diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2a596551a45..af18c5ffe6f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- -FROM mcr.microsoft.com/dotnet/nightly/sdk:5.0.100-rc.1 +FROM mcr.microsoft.com/powershell/test-deps:ubuntu-18.04 # Avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 36ae9537336..c7b3de62eef 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ // See https://aka.ms/vscode-remote/devcontainer.json for format details. { - "name": ".NET Core 5.0, including pwsh (Debian 10)", + "name": ".NET Core 6.0, including pwsh (Ubuntu 18.04)", "dockerFile": "Dockerfile", // Uncomment the next line to run commands after the container is created. diff --git a/.editorconfig b/.editorconfig index 74496fb9a7c..517c9656ba6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,6 +21,7 @@ indent_size = 4 # Shell scripts [*.sh] +end_of_line = lf indent_size = 4 # Xml project files @@ -43,6 +44,9 @@ indent_size = 2 [*.{props,targets,config,nuspec}] indent_size = 2 +[*.tsv] +indent_style = tab + # Dotnet code style settings: [*.cs] # Sort using and Import directives with System.* appearing first diff --git a/.gitattributes b/.gitattributes index 10790ce3949..c9033dc798a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,5 +2,6 @@ CHANGELOG.md merge=union * text=auto *.png binary *.rtf binary +*.sh text eol=lf testablescript.ps1 text eol=lf TestFileCatalog.txt text eol=lf diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8548101590f..04346dd9abb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -82,10 +82,12 @@ which can be run in interactive mode to correct typos or add words to the ignore To run the spellchecker, follow these steps: -* install [Node.js](https://nodejs.org/en/) (v6.4.0 or up) +* install [Node.js](https://nodejs.org/en/) (v10 or up) * install [markdown-spellcheck](https://github.com/lukeapage/node-markdown-spellcheck) by `npm install -g markdown-spellcheck` (v0.11.0 or up) -* run `mdspell "**/*.md" --ignore-numbers --ignore-acronyms --en-us` +* run `mdspell "**/*.md" "!**/dotnet-tools/**/*.md" --ignore-numbers --ignore-acronyms --en-us`. + - The folder `dotnet-tools` is excluded because files in that folder are copied from the `dotnet/performance` repository + and will need to be synchronized from time to time. * if the `.spelling` file is updated, commit and push it #### Checking links in documentation @@ -96,9 +98,9 @@ which can be run to see if any links are dead. To run the link-checker, follow these steps: -* install [Node.js](https://nodejs.org/en/) (v6.4.0 or up) +* install [Node.js](https://nodejs.org/en/) (v10 or up) * install markdown-link-check by - `npm install -g markdown-link-check@3.7.2` (v3.7.2 **only**) + `npm install -g markdown-link-check@3.8.5` * run `find . \*.md -exec markdown-link-check {} \;` ## Contributing to Code diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.md b/.github/ISSUE_TEMPLATE/Bug_Report.md deleted file mode 100644 index 2c51890e890..00000000000 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: Bug report 🐛 -about: Report errors or unexpected behavior 🤔 -title: "My bug report" -labels: Issue-Question -assignees: '' - ---- - - -## Steps to reproduce - -```powershell - -``` - -## Expected behavior - -```none - -``` - -## Actual behavior - -```none - -``` - -## Environment data - - - -```none - -``` diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yaml b/.github/ISSUE_TEMPLATE/Bug_Report.yaml new file mode 100644 index 00000000000..a2f7629ef4e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yaml @@ -0,0 +1,75 @@ +name: Bug report 🐛 +description: Report errors or unexpected behavior 🤔 +labels: Needs-Triage +body: +- type: markdown + attributes: + value: > + For Windows PowerShell 5.1 issues, suggestions, or feature requests please use the + [Feedback Hub app](https://support.microsoft.com/windows/send-feedback-to-microsoft-with-the-feedback-hub-app-f59187f8-8739-22d6-ba93-f66612949332) + + This repository is **ONLY** for PowerShell Core 6 and PowerShell 7+ issues. +- type: checkboxes + attributes: + label: Prerequisites + options: + - label: Write a descriptive title. + required: true + - label: Make sure you are able to repro it on the [latest released version](https://github.com/PowerShell/PowerShell/releases) + required: true + - label: Search the existing issues. + required: true + - label: Refer to the [FAQ](https://github.com/PowerShell/PowerShell/blob/master/docs/FAQ.md). + required: true + - label: Refer to [Differences between Windows PowerShell 5.1 and PowerShell](https://docs.microsoft.com/powershell/scripting/whats-new/differences-from-windows-powershell). + required: true +- type: textarea + attributes: + label: Steps to reproduce + description: > + List of steps, sample code, failing test or link to a project that reproduces the behavior. + Make sure you place a stack trace inside a code (```) block to avoid linking unrelated issues. + placeholder: > + I am experiencing a problem with X. + I think Y should be happening but Z is actually happening. + validations: + required: true +- type: textarea + attributes: + label: Expected behavior + render: console + placeholder: | + PS> 2 + 2 + 4 + validations: + required: true +- type: textarea + attributes: + label: Actual behavior + render: console + placeholder: | + PS> 2 + 2 + 5 + validations: + required: true +- type: textarea + attributes: + label: Error details + description: Paste verbatim output from `Get-Error` if PowerShell return an error. + render: console + placeholder: PS> Get-Error +- type: textarea + attributes: + label: Environment data + description: Paste verbatim output from `$PSVersionTable` below. + render: powershell + placeholder: PS> $PSVersionTable + validations: + required: true +- type: textarea + attributes: + label: Visuals + description: > + Please upload images or animations that can be used to reproduce issues in the area below. + Try the [Steps Recorder](https://support.microsoft.com/en-us/windows/record-steps-to-reproduce-a-problem-46582a9b-620f-2e36-00c9-04e25d784e47) + on Windows or [Screenshot](https://support.apple.com/en-us/HT208721) on macOS. diff --git a/.github/ISSUE_TEMPLATE/Distribution_Request.md b/.github/ISSUE_TEMPLATE/Distribution_Request.md deleted file mode 100644 index ff089662700..00000000000 --- a/.github/ISSUE_TEMPLATE/Distribution_Request.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -name: Distribution Support Request -about: Requests support for a new distribution -title: "Distribution Support Request" -labels: Distribution-Request -assignees: '' - ---- - -## Details of the Distribution - -- Name of the Distribution: -- Version of the Distribution: -- Package Types - - [ ] Deb - - [ ] RPM - - [ ] Tar.gz - - Snap - Please file issue in https://github.com/powershell/powershell-snap. This issues type is unrelated to snap packages with a distribution neutral. -- Processor Architecture (One per request): -- [ ] **Required** - An issues has been filed to create a Docker image in https://github.com/powershell/powershell-docker -- The following is a requirement for supporting a distribution **without exception.** - - [ ] The version and architecture of the Distribution is [supported by .NET Core](https://github.com/dotnet/core/blob/master/release-notes/3.0/3.0-supported-os.md#linux). -- The following are requirements for supporting a distribution. - Please write a justification for any exception where these criteria are not met and - the PowerShell committee will review the request. - - [ ] The version of the Distribution is supported for at least one year. - - [ ] The version of the Distribution is not an [interim release](https://ubuntu.com/about/release-cycle) or equivalent. - -## Progress - For PowerShell Team **ONLY** - -- [ ] Docker image created -- [ ] Docker image published -- [ ] Distribution tested -- [ ] Update `packages.microsoft.com` deployment -- [ ] [Lifecycle](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/staging/reference/docs-conceptual/PowerShell-Support-Lifecycle.md) updated -- [ ] Documentation Updated diff --git a/.github/ISSUE_TEMPLATE/Distribution_Request.yaml b/.github/ISSUE_TEMPLATE/Distribution_Request.yaml new file mode 100644 index 00000000000..de15814cb3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Distribution_Request.yaml @@ -0,0 +1,64 @@ +name: Distribution Support Request +description: Requests support for a new distribution +title: Distribution Support Request +labels: [Distribution-Request, Needs-Triage] +body: +- type: input + attributes: + label: Name of the Distribution + validations: + required: true +- type: input + attributes: + label: Version of the Distribution + validations: + required: true +- type: checkboxes + attributes: + label: Package Types + options: + - label: Deb + - label: RPM + - label: Tar.gz + - label: Snap - Stop! Please file your issue in [PowerShell-Snap](https://github.com/powershell/powershell-snap) instead. +- type: input + attributes: + label: Processor Architecture + description: One per request! + validations: + required: true +- type: checkboxes + attributes: + label: .NET Core Support + description: The following is a requirement for supporting a distribution **without exception.** + options: + - label: The version and architecture of the Distribution is [supported by .NET Core](https://github.com/dotnet/core/blob/master/release-notes/5.0/5.0-supported-os.md#linux). + required: true +- type: checkboxes + attributes: + label: Distribution Requirements + description: The following are requirements for supporting a distribution. + options: + - label: The version of the Distribution is supported for at least one year. + - label: The version of the Distribution is not an [interim release](https://ubuntu.com/about/release-cycle) or equivalent. +- type: input + attributes: + label: Exemption Justification + description: | + Please write a justification for any exception where the above criteria + are not met. The PowerShell committee will review the request. +- type: checkboxes + attributes: + label: Progress + options: + - label: An issue has been filed to create a Docker image in [PowerShell-Docker](https://github.com/powershell/powershell-docker) +- type: checkboxes + attributes: + label: For PowerShell Team **ONLY** + options: + - label: Docker image created + - label: Docker image published + - label: Distribution tested + - label: Update `packages.microsoft.com` deployment + - label: "[Lifecycle](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/staging/reference/docs-conceptual/PowerShell-Support-Lifecycle.md) updated" + - label: Documentation Updated diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.md b/.github/ISSUE_TEMPLATE/Feature_Request.md deleted file mode 100644 index cf91c6e3dc3..00000000000 --- a/.github/ISSUE_TEMPLATE/Feature_Request.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Feature Request/Idea 🚀 -about: Suggest a new feature or improvement (this does not mean you have to implement it) -title: "Feature Request" -labels: Issue-Enhancement -assignees: '' - ---- - -## Summary of the new feature/enhancement - - - -## Proposed technical implementation details (optional) - - diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.yaml b/.github/ISSUE_TEMPLATE/Feature_Request.yaml new file mode 100644 index 00000000000..c8e4cec3c4d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_Request.yaml @@ -0,0 +1,20 @@ +name: Feature Request / Idea 🚀 +description: Suggest a new feature or improvement (this does not mean you have to implement it) +labels: [Issue-Enhancement, Needs-Triage] +body: +- type: textarea + attributes: + label: Summary of the new feature / enhancement + description: > + A clear and concise description of what the problem is that the + new feature would solve. Try formulating it in user story style + (if applicable). + placeholder: "'As a user I want X so that Y...' with X being the being the action and Y being the value of the action." + validations: + required: true +- type: textarea + attributes: + label: Proposed technical implementation details (optional) + placeholder: > + A clear and concise description of what you want to happen. + Consider providing an example PowerShell experience with expected result. diff --git a/.github/ISSUE_TEMPLATE/Microsoft_Update_Issue.yaml b/.github/ISSUE_TEMPLATE/Microsoft_Update_Issue.yaml new file mode 100644 index 00000000000..4a14c329e2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Microsoft_Update_Issue.yaml @@ -0,0 +1,87 @@ +name: Microsoft Update issue report 🐛 +description: Report issue installing a PowerShell 7 Update or fresh install through Microsoft Update 🤔 +labels: Needs-Triage +assignees: + - TravisEz13 +body: +- type: markdown + attributes: + value: > + For Windows PowerShell 5.1 issues, suggestions, or feature requests please use the + [Feedback Hub app](https://support.microsoft.com/windows/send-feedback-to-microsoft-with-the-feedback-hub-app-f59187f8-8739-22d6-ba93-f66612949332) + + This repository is **ONLY** for PowerShell Core 6 and PowerShell 7+ issues. +- type: checkboxes + attributes: + label: Prerequisites + options: + - label: Write a descriptive title. + required: true + - label: Make sure you are able to repro it on the [latest released version](https://github.com/PowerShell/PowerShell/releases) + required: true + - label: Search the existing issues. + required: true + - label: Refer to the [FAQ](https://github.com/PowerShell/PowerShell/blob/master/docs/FAQ.md). + required: true + - label: Refer to [Differences between Windows PowerShell 5.1 and PowerShell](https://docs.microsoft.com/powershell/scripting/whats-new/differences-from-windows-powershell). + required: true +- type: textarea + attributes: + label: Steps to reproduce + description: > + List of steps, sample code, failing test or link to a project that reproduces the behavior. + Make sure you place a stack trace inside a code (```) block to avoid linking unrelated issues. + placeholder: > + I am experiencing a problem with X. + I think Y should be happening but Z is actually happening. + validations: + required: true +- type: textarea + attributes: + label: Expected behavior + render: console + placeholder: | + PS> 2 + 2 + 4 + validations: + required: true +- type: textarea + attributes: + label: Actual behavior + render: console + placeholder: | + PS> 2 + 2 + 5 + validations: + required: true +- type: textarea + attributes: + label: Environment data + description: Paste verbatim output from `$PSVersionTable` below. + render: powershell + placeholder: PS> $PSVersionTable + validations: + required: true +- type: textarea + attributes: + label: OS Data + description: Paste verbatim output from `(Get-CimInstance Win32_OperatingSystem) | Select-Object -Property Version, Caption` below. + render: powershell + placeholder: PS> (Get-CimInstance Win32_OperatingSystem) | Select-Object -Property Version, Caption + validations: + required: true +- type: textarea + attributes: + label: Windows update log + description: Please run `Get-WindowsUpdateLog` and upload the resulting file to this issue. + render: markdown + placeholder: PS> Get-WindowsUpdateLog + validations: + required: true +- type: textarea + attributes: + label: Visuals + description: > + Please upload images or animations that can be used to reproduce issues in the area below. + Try the [Steps Recorder](https://support.microsoft.com/en-us/windows/record-steps-to-reproduce-a-problem-46582a9b-620f-2e36-00c9-04e25d784e47) + on Windows or [Screenshot](https://support.apple.com/en-us/HT208721) on macOS. diff --git a/.github/ISSUE_TEMPLATE/Release_Process.md b/.github/ISSUE_TEMPLATE/Release_Process.md deleted file mode 100644 index 1932bff5c6d..00000000000 --- a/.github/ISSUE_TEMPLATE/Release_Process.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -name: Release Process -about: Maintainers Only - Release Process -title: "Release Process for v6.x.x" -labels: Issue-Meta -assignees: '' - ---- - - - -## Checklist - -- [ ] Verify that `PowerShell-Native` has been updated/released as needed. -- [ ] Check for `PowerShellGet` and `PackageManagement` release plans. -- [ ] Start process to sync Azure DevOps artifacts feed such as modules and NuGet packages. -- [ ] Create a private branch named `release/v6.x.x` in Azure DevOps repository. - All release related changes should happen in this branch. -- [ ] Prepare packages - - [ ] Kick off coordinated build. -- [ ] Kick off Release pipeline. - - *These tasks are orchestrated by the release pipeline, but here as status to the community.* - - [ ] Prepare packages - - [ ] Sign the RPM package. - - [ ] Install and verify the packages. - - [ ] Trigger the docker staging builds (signing must be done). - - [ ] Create the release tag and push the tag to `PowerShell/PowerShell` repository. - - [ ] Run tests on all supported Linux distributions and publish results. - - [ ] Update documentation, and scripts. - - [ ] Update [CHANGELOG.md](../../CHANGELOG.md) with the finalized change log draft. - - [ ] Stage a PR to master to update other documents and - scripts to use the new package names, links, and `metadata.json`. - - [ ] For preview releases, - merge the release branch to GitHub `master` with a merge commit. - - [ ] For non-preview releases, - make sure all changes are either already in master or have a PR open. - - [ ] Delete the release branch. - - [ ] Trigger the Docker image release. - - [ ] Retain builds. - - [ ] Update https://github.com/dotnet/dotnet-docker/tree/master/3.0/sdk with new version and SHA hashes for global tool. diff --git a/.github/ISSUE_TEMPLATE/Release_Process.yaml b/.github/ISSUE_TEMPLATE/Release_Process.yaml new file mode 100644 index 00000000000..7e8d6282db1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Release_Process.yaml @@ -0,0 +1,41 @@ +name: Release Process +description: Maintainers Only - Release Process +title: "Release Process for v7.x.x" +labels: [Issue-Meta, Needs-Triage] +body: +- type: markdown + attributes: + value: > + This template is for maintainers to create an issues to track the release process. + Please **only** use this template if you are a maintainer. +- type: textarea + attributes: + label: Checklist + value: | + - [ ] Verify that [`PowerShell-Native`](https://github.com/PowerShell/PowerShell-Native) has been updated / released as needed. + - [ ] Check for `PowerShellGet` and `PackageManagement` release plans. + - [ ] Start process to sync Azure DevOps artifacts feed such as modules and NuGet packages. + - [ ] Create a private branch named `release/v6.x.x` in Azure DevOps repository. + All release related changes should happen in this branch. + - [ ] Prepare packages + - [ ] Kick off coordinated build. + - [ ] Kick off Release pipeline. + - *These tasks are orchestrated by the release pipeline, but here as status to the community.* + - [ ] Prepare packages + - [ ] Sign the RPM package. + - [ ] Install and verify the packages. + - [ ] Trigger the docker staging builds (signing must be done). + - [ ] Create the release tag and push the tag to `PowerShell/PowerShell` repository. + - [ ] Run tests on all supported Linux distributions and publish results. + - [ ] Update documentation, and scripts. + - [ ] Update [CHANGELOG.md](../../CHANGELOG.md) with the finalized change log draft. + - [ ] Stage a PR to master to update other documents and + scripts to use the new package names, links, and `metadata.json`. + - [ ] For preview releases, + merge the release branch to GitHub `master` with a merge commit. + - [ ] For non-preview releases, + make sure all changes are either already in master or have a PR open. + - [ ] Delete the release branch. + - [ ] Trigger the Docker image release. + - [ ] Retain builds. + - [ ] Update https://github.com/dotnet/dotnet-docker/tree/master/3.0/sdk with new version and SHA hashes for global tool. NOTE: this link is broken! diff --git a/.github/ISSUE_TEMPLATE/Security_Issue_Report.md b/.github/ISSUE_TEMPLATE/Security_Issue_Report.md deleted file mode 100644 index f2304882dc3..00000000000 --- a/.github/ISSUE_TEMPLATE/Security_Issue_Report.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Security Issue -about: Security Issue -title: "!!! READ TEMPLATE COMPLETELY FIRST!!!" -labels: Area-Security -assignees: 'TravisEz13' - ---- - -## Security Issue - -Excerpt from [Issue Management - Security Vulnerabilities](https://github.com/PowerShell/PowerShell/blob/master/.github/SECURITY.md) - -> If you believe that there is a security vulnerability in PowerShell, -it **must** be reported to [secure@microsoft.com](https://technet.microsoft.com/security/ff852094.aspx) -to allow for [Coordinated Vulnerability Disclosure](https://technet.microsoft.com/security/dn467923). -**Only** file an issue, if secure@microsoft.com has confirmed filing an issue is appropriate. - -When you have permission from [secure@microsoft.com](https://technet.microsoft.com/security/ff852094.aspx) to file an issue here, -please use the Bug Report template and state in the description that you are reporting the issue in coordination with [secure@microsoft.com](https://technet.microsoft.com/security/ff852094.aspx). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index efbe076a8b9..b64343410f7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -33,8 +33,13 @@ - **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 enumerated concerns in the summary. 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). - - Impact on Completions (both in the console and in editors) - one of PowerShell's most powerful features. - - Impact on [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) (which provides linting & formatting in the editor extensions). - - Impact on [EditorSyntax](https://github.com/PowerShell/EditorSyntax) (which provides syntax highlighting with in VSCode, GitHub, and many other editors). + - [ ] 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: diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index a34d36186ed..3eaa070852a 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -8,6 +8,6 @@ If you know how to fix the issue, feel free to send a pull request our way. (The [Official Support Policy]: https://docs.microsoft.com/powershell/scripting/powershell-support-lifecycle [FAQ]: https://github.com/PowerShell/PowerShell/tree/master/docs/FAQ.md [Contribution Guides]: https://github.com/PowerShell/PowerShell/tree/master/.github/CONTRIBUTING.md -[known issues]: https://docs.microsoft.com/powershell/scripting/whats-new/known-issues-ps6 +[known issues]: https://docs.microsoft.com/powershell/scripting/whats-new/differences-from-windows-powershell [GitHub issues]: https://github.com/PowerShell/PowerShell/issues [new issue]: https://github.com/PowerShell/PowerShell/issues/new/choose diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bf13e4c9510..38a493b7f36 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,12 +1,10 @@ version: 2 -# update_schedule: live is only supported on javascript, ruby:bundler, python, php:composer, dotnet:nuget, rust:cargo, elixir:hex - updates: - - package-ecosystem: "dotnet:nuget" + - package-ecosystem: "nuget" directory: "/" schedule: - interval: "live" + interval: "daily" labels: - "CL-BuildPackaging" ignore: @@ -14,42 +12,42 @@ updates: - dependency-name: "Microsoft.Win32.Registry.AccessControl" - dependency-name: "Microsoft.Windows.Compatibility" - - package-ecosystem: "dotnet:nuget" + - package-ecosystem: "nuget" directory: "/tools/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility" schedule: - interval: "live" + interval: "daily" labels: - "CL-BuildPackaging" - ignored_updates: + ignore: - dependency-name: "System.*" - dependency-name: "Microsoft.Win32.Registry.AccessControl" - dependency-name: "Microsoft.Windows.Compatibility" - - package-ecosystem: "dotnet:nuget" + - package-ecosystem: "nuget" directory: "/tools/packaging/projects/reference/System.Management.Automation" schedule: - interval: "live" + interval: "daily" labels: - "CL-BuildPackaging" - ignored_updates: + ignore: - dependency-name: "System.*" - dependency-name: "Microsoft.Win32.Registry.AccessControl" - dependency-name: "Microsoft.Windows.Compatibility" - - package-ecosystem: "dotnet:nuget" + - package-ecosystem: "nuget" directory: "/test/tools/Modules" schedule: - interval: "live" + interval: "daily" labels: - "CL-BuildPackaging" - ignored_updates: + ignore: - dependency-name: "System.*" - dependency-name: "Microsoft.Win32.Registry.AccessControl" - dependency-name: "Microsoft.Windows.Compatibility" - - package_manager: "dotnet:nuget" + - package-ecosystem: "nuget" directory: "/src/Modules" schedule: - interval: "live" + interval: "daily" labels: - "CL-BuildPackaging" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000000..903ee79cf4d --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,62 @@ +name: "CodeQL" + +on: + push: + branches: [master] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + +defaults: + run: + shell: pwsh + +env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-18.04 + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['csharp'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: '0' + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + - run: | + Get-ChildItem -Path env: + name: Capture Environment + + - run: | + Import-Module .\tools\ci.psm1 + Invoke-CIInstall -SkipUser + name: Bootstrap + + - run: | + Import-Module .\tools\ci.psm1 + Invoke-CIBuild + name: Build + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 3447bf1803d..a1c883c98f0 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -3,6 +3,7 @@ name: PowerShell Daily on: + workflow_dispatch: schedule: # At 13:00 UTC every day. - cron: '0 13 * * *' @@ -30,20 +31,26 @@ jobs: - name: Execute Update .NET script run: | $currentVersion = (Get-Content .\global.json | ConvertFrom-Json).sdk.version - Write-Verbose "name=OLD_VERSION::$currentVersion" -Verbose - Write-Host "::set-env name=OLD_VERSION::$currentVersion" + Write-Verbose "OLD_VERSION=$currentVersion" -Verbose + "OLD_VERSION=$currentVersion" | Out-File $env:GITHUB_ENV -Append - ./tools/UpdateDotnetRuntime.ps1 -UpdateMSIPackaging + ./tools/UpdateDotnetRuntime.ps1 -UpdateMSIPackaging -UseInternalFeed $newVersion = (Get-Content .\global.json | ConvertFrom-Json).sdk.version - Write-Verbose "name=NEW_VERSION::$newVersion" -Verbose - Write-Host "::set-env name=NEW_VERSION::$newVersion" + Write-Verbose "NEW_VERSION=$newVersion" -Verbose + "NEW_VERSION=$newVersion" | Out-File $env:GITHUB_ENV -Append if ($currentVersion -ne $newVersion) { - Write-Verbose "name=CREATE_PR::true" -Verbose - Write-Host "::set-env name=CREATE_PR::true" + Write-Verbose "CREATE_PR=true" -Verbose + "CREATE_PR=true" | Out-File $env:GITHUB_ENV -Append } + - name: Microsoft Teams Notifier + uses: skitionek/notify-microsoft-teams@master + if: failure() + with: + webhook_url: ${{ secrets.PS_BUILD_TEAMS_CHANNEL }} + overwrite: "{title: `Failure in updating .NET build. Look at ${workflow_link}`}" - name: Create Pull Request - uses: peter-evans/create-pull-request@v2 + uses: peter-evans/create-pull-request@v3 id: cpr if: env.CREATE_PR == 'true' with: diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml new file mode 100644 index 00000000000..f54254f1435 --- /dev/null +++ b/.github/workflows/rebase.yml @@ -0,0 +1,21 @@ +# This cannot rebase workflow changes into a PR +# It also only works if the GITHUB_TOKEN has permission to push to the branch +# see: https://github.com/cirrus-actions/rebase/issues/12#issuecomment-632594995 +on: + issue_comment: + types: [created] +name: Automatic Rebase +jobs: + rebase: + name: Rebase + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') + runs-on: ubuntu-latest + steps: + - name: Checkout the latest code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Automatic Rebase + uses: cirrus-actions/rebase@1.4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index fb19bcffa77..cbf0016dd16 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,6 @@ StyleCop.Cache # Ignore SelfSignedCertificate autogenerated files test/tools/Modules/SelfSignedCertificate/ + +# BenchmarkDotNet artifacts +test/perf/BenchmarkDotNet.Artifacts/ diff --git a/.globalconfig b/.globalconfig new file mode 100644 index 00000000000..80a1131796f --- /dev/null +++ b/.globalconfig @@ -0,0 +1,2253 @@ +is_global = true + +# CA1000: Do not declare static members on generic types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1000 +dotnet_diagnostic.CA1000.severity = warning +dotnet_code_quality.CA1000.api_surface = all + +# CA1001: Types that own disposable fields should be disposable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1001 +dotnet_diagnostic.CA1001.severity = silent + +# CA1002: Do not expose generic lists +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1002 +dotnet_diagnostic.CA1002.severity = none + +# CA1003: Use generic event handler instances +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1003 +dotnet_diagnostic.CA1003.severity = warning +dotnet_code_quality.CA1003.api_surface = private, internal + +# CA1005: Avoid excessive parameters on generic types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1005 +dotnet_diagnostic.CA1005.severity = none + +# CA1008: Enums should have zero value +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1008 +dotnet_diagnostic.CA1008.severity = none +dotnet_code_quality.CA1008.api_surface = public + +# CA1010: Generic interface should also be implemented +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1010 +dotnet_diagnostic.CA1010.severity = silent +dotnet_code_quality.CA1010.api_surface = public + +# CA1012: Abstract types should not have public constructors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1012 +dotnet_diagnostic.CA1012.severity = warning +dotnet_code_quality.CA1012.api_surface = all + +# CA1014: Mark assemblies with CLSCompliant +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1014 +dotnet_diagnostic.CA1014.severity = none + +# CA1016: Mark assemblies with assembly version +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1016 +dotnet_diagnostic.CA1016.severity = warning + +# CA1017: Mark assemblies with ComVisible +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1017 +dotnet_diagnostic.CA1017.severity = none + +# CA1018: Mark attributes with AttributeUsageAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1018 +dotnet_diagnostic.CA1018.severity = warning + +# CA1019: Define accessors for attribute arguments +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1019 +dotnet_diagnostic.CA1019.severity = none + +# CA1021: Avoid out parameters +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1021 +dotnet_diagnostic.CA1021.severity = none + +# CA1024: Use properties where appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1024 +dotnet_diagnostic.CA1024.severity = none +dotnet_code_quality.CA1024.api_surface = public + +# CA1027: Mark enums with FlagsAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1027 +dotnet_diagnostic.CA1027.severity = none +dotnet_code_quality.CA1027.api_surface = public + +# CA1028: Enum Storage should be Int32 +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1028 +dotnet_diagnostic.CA1028.severity = none +dotnet_code_quality.CA1028.api_surface = public + +# CA1030: Use events where appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1030 +dotnet_diagnostic.CA1030.severity = none +dotnet_code_quality.CA1030.api_surface = public + +# CA1031: Do not catch general exception types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031 +dotnet_diagnostic.CA1031.severity = none + +# CA1032: Implement standard exception constructors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1032 +dotnet_diagnostic.CA1032.severity = none + +# CA1033: Interface methods should be callable by child types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1033 +dotnet_diagnostic.CA1033.severity = none + +# CA1034: Nested types should not be visible +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1034 +dotnet_diagnostic.CA1034.severity = none + +# CA1036: Override methods on comparable types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1036 +dotnet_diagnostic.CA1036.severity = silent +dotnet_code_quality.CA1036.api_surface = public + +# CA1040: Avoid empty interfaces +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1040 +dotnet_diagnostic.CA1040.severity = none +dotnet_code_quality.CA1040.api_surface = public + +# CA1041: Provide ObsoleteAttribute message +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1041 +dotnet_diagnostic.CA1041.severity = warning +dotnet_code_quality.CA1041.api_surface = public + +# CA1043: Use Integral Or String Argument For Indexers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1043 +dotnet_diagnostic.CA1043.severity = warning +dotnet_code_quality.CA1043.api_surface = all + +# CA1044: Properties should not be write only +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1044 +dotnet_diagnostic.CA1044.severity = none +dotnet_code_quality.CA1044.api_surface = public + +# CA1045: Do not pass types by reference +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1045 +dotnet_diagnostic.CA1045.severity = none + +# CA1046: Do not overload equality operator on reference types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1046 +dotnet_diagnostic.CA1046.severity = none + +# CA1047: Do not declare protected member in sealed type +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1047 +dotnet_diagnostic.CA1047.severity = warning + +# CA1050: Declare types in namespaces +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1050 +dotnet_diagnostic.CA1050.severity = warning + +# CA1051: Do not declare visible instance fields +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1051 +dotnet_diagnostic.CA1051.severity = silent +dotnet_code_quality.CA1051.api_surface = public + +# CA1052: Static holder types should be Static or NotInheritable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1052 +dotnet_diagnostic.CA1052.severity = warning +dotnet_code_quality.CA1052.api_surface = all + +# CA1054: URI-like parameters should not be strings +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1054 +dotnet_diagnostic.CA1054.severity = none +dotnet_code_quality.CA1054.api_surface = public + +# CA1055: URI-like return values should not be strings +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1055 +dotnet_diagnostic.CA1055.severity = none +dotnet_code_quality.CA1055.api_surface = public + +# CA1056: URI-like properties should not be strings +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056 +dotnet_diagnostic.CA1056.severity = none +dotnet_code_quality.CA1056.api_surface = public + +# CA1058: Types should not extend certain base types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1058 +dotnet_diagnostic.CA1058.severity = none +dotnet_code_quality.CA1058.api_surface = public + +# CA1060: Move pinvokes to native methods class +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1060 +dotnet_diagnostic.CA1060.severity = none + +# CA1061: Do not hide base class methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1061 +dotnet_diagnostic.CA1061.severity = warning + +# CA1062: Validate arguments of public methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1062 +dotnet_diagnostic.CA1062.severity = none + +# CA1063: Implement IDisposable Correctly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1063 +dotnet_diagnostic.CA1063.severity = none +dotnet_code_quality.CA1063.api_surface = public + +# CA1064: Exceptions should be public +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1064 +dotnet_diagnostic.CA1064.severity = none + +# CA1065: Do not raise exceptions in unexpected locations +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1065 +dotnet_diagnostic.CA1065.severity = warning + +# CA1066: Implement IEquatable when overriding Object.Equals +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1066 +dotnet_diagnostic.CA1066.severity = none + +# CA1067: Override Object.Equals(object) when implementing IEquatable +# # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1067 +dotnet_diagnostic.CA1067.severity = warning + +# CA1068: CancellationToken parameters must come last +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1068 +dotnet_diagnostic.CA1068.severity = warning + +# CA1069: Enums values should not be duplicated +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1069 +dotnet_diagnostic.CA1069.severity = suggestion + +# CA1070: Do not declare event fields as virtual +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1070 +dotnet_diagnostic.CA1070.severity = warning + +# CA1200: Avoid using cref tags with a prefix +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1200 +dotnet_diagnostic.CA1200.severity = silent + +# CA1303: Do not pass literals as localized parameters +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1303 +dotnet_diagnostic.CA1303.severity = none + +# CA1304: Specify CultureInfo +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1304 +dotnet_diagnostic.CA1304.severity = silent + +# CA1305: Specify IFormatProvider +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305 +dotnet_diagnostic.CA1305.severity = silent + +# CA1307: Specify StringComparison for clarity +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1307 +dotnet_diagnostic.CA1307.severity = none + +# CA1308: Normalize strings to uppercase +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1308 +dotnet_diagnostic.CA1308.severity = none + +# CA1309: Use ordinal string comparison +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1309 +dotnet_diagnostic.CA1309.severity = silent + +# CA1310: Specify StringComparison for correctness +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310 +dotnet_diagnostic.CA1310.severity = silent + +# CA1401: P/Invokes should not be visible +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1401 +dotnet_diagnostic.CA1401.severity = warning + +# CA1416: Validate platform compatibility +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416 +dotnet_diagnostic.CA1416.severity = warning + +# CA1417: Do not use 'OutAttribute' on string parameters for P/Invokes +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1417 +dotnet_diagnostic.CA1417.severity = warning + +# CA1418: Use valid platform string +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1418 +dotnet_diagnostic.CA1418.severity = warning + +# CA1501: Avoid excessive inheritance +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1501 +dotnet_diagnostic.CA1501.severity = none + +# CA1502: Avoid excessive complexity +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1502 +dotnet_diagnostic.CA1502.severity = none + +# CA1505: Avoid unmaintainable code +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1505 +dotnet_diagnostic.CA1505.severity = none + +# CA1506: Avoid excessive class coupling +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1506 +dotnet_diagnostic.CA1506.severity = none + +# CA1507: Use nameof to express symbol names +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1507 +dotnet_diagnostic.CA1507.severity = suggestion + +# CA1508: Avoid dead conditional code +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1508 +dotnet_diagnostic.CA1508.severity = none + +# CA1509: Invalid entry in code metrics rule specification file +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1509 +dotnet_diagnostic.CA1509.severity = none + +# CA1700: Do not name enum values 'Reserved' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1700 +dotnet_diagnostic.CA1700.severity = none + +# CA1707: Identifiers should not contain underscores +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707 +dotnet_diagnostic.CA1707.severity = silent + +# CA1708: Identifiers should differ by more than case +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1708 +dotnet_diagnostic.CA1708.severity = silent +dotnet_code_quality.CA1708.api_surface = public + +# CA1710: Identifiers should have correct suffix +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1710 +dotnet_diagnostic.CA1710.severity = silent +dotnet_code_quality.CA1710.api_surface = public + +# CA1711: Identifiers should not have incorrect suffix +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1711 +dotnet_diagnostic.CA1711.severity = silent +dotnet_code_quality.CA1711.api_surface = public + +# CA1712: Do not prefix enum values with type name +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1712 +dotnet_diagnostic.CA1712.severity = silent + +# CA1713: Events should not have 'Before' or 'After' prefix +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1713 +dotnet_diagnostic.CA1713.severity = none + +# CA1715: Identifiers should have correct prefix +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1715 +dotnet_diagnostic.CA1715.severity = silent +dotnet_code_quality.CA1715.api_surface = public + +# CA1716: Identifiers should not match keywords +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1716 +dotnet_diagnostic.CA1716.severity = silent +dotnet_code_quality.CA1716.api_surface = public + +# CA1720: Identifier contains type name +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1720 +dotnet_diagnostic.CA1720.severity = silent +dotnet_code_quality.CA1720.api_surface = public + +# CA1721: Property names should not match get methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1721 +dotnet_diagnostic.CA1721.severity = none +dotnet_code_quality.CA1721.api_surface = public + +# CA1724: Type names should not match namespaces +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1724 +dotnet_diagnostic.CA1724.severity = none + +# CA1725: Parameter names should match base declaration +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1725 +dotnet_diagnostic.CA1725.severity = silent +dotnet_code_quality.CA1725.api_surface = public + +# CA1801: Review unused parameters +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1801 +dotnet_diagnostic.CA1801.severity = none +dotnet_code_quality.CA1801.api_surface = all + +# CA1802: Use literals where appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1802 +dotnet_diagnostic.CA1802.severity = none +dotnet_code_quality.CA1802.api_surface = public + +# CA1805: Do not initialize unnecessarily +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1805 +dotnet_diagnostic.CA1805.severity = suggestion + +# CA1806: Do not ignore method results +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1806 +dotnet_diagnostic.CA1806.severity = suggestion + +# CA1810: Initialize reference type static fields inline +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1810 +dotnet_diagnostic.CA1810.severity = none + +# CA1812: Avoid uninstantiated internal classes +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1812 +dotnet_diagnostic.CA1812.severity = warning + +# CA1813: Avoid unsealed attributes +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1813 +dotnet_diagnostic.CA1813.severity = none + +# CA1814: Prefer jagged arrays over multidimensional +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1814 +dotnet_diagnostic.CA1814.severity = none + +# CA1815: Override equals and operator equals on value types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1815 +dotnet_diagnostic.CA1815.severity = none +dotnet_code_quality.CA1815.api_surface = public + +# CA1816: Dispose methods should call SuppressFinalize +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1816 +dotnet_diagnostic.CA1816.severity = warning + +# CA1819: Properties should not return arrays +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1819 +dotnet_diagnostic.CA1819.severity = none +dotnet_code_quality.CA1819.api_surface = public + +# CA1820: Test for empty strings using string length +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1820 +dotnet_diagnostic.CA1820.severity = none + +# CA1821: Remove empty Finalizers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1821 +dotnet_diagnostic.CA1821.severity = warning + +# CA1822: Mark members as static +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1822 +dotnet_diagnostic.CA1822.severity = warning +dotnet_code_quality.CA1822.api_surface = private + +# CA1823: Avoid unused private fields +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1823 +dotnet_diagnostic.CA1823.severity = none + +# CA1824: Mark assemblies with NeutralResourcesLanguageAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1824 +dotnet_diagnostic.CA1824.severity = warning + +# CA1825: Avoid zero-length array allocations +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1825 +dotnet_diagnostic.CA1825.severity = warning + +# CA1826: Do not use Enumerable methods on indexable collections +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1826 +dotnet_diagnostic.CA1826.severity = warning + +# CA1827: Do not use Count() or LongCount() when Any() can be used +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1827 +dotnet_diagnostic.CA1827.severity = warning + +# CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1828 +dotnet_diagnostic.CA1828.severity = warning + +# CA1829: Use Length/Count property instead of Count() when available +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1829 +dotnet_diagnostic.CA1829.severity = warning + +# CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1830 +dotnet_diagnostic.CA1830.severity = warning + +# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1831 +dotnet_diagnostic.CA1831.severity = warning + +# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1832 +dotnet_diagnostic.CA1832.severity = warning + +# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1833 +dotnet_diagnostic.CA1833.severity = warning + +# CA1834: Consider using 'StringBuilder.Append(char)' when applicable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1834 +dotnet_diagnostic.CA1834.severity = warning + +# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1835 +dotnet_diagnostic.CA1835.severity = suggestion + +# CA1836: Prefer IsEmpty over Count +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1836 +dotnet_diagnostic.CA1836.severity = warning + +# CA1837: Use 'Environment.ProcessId' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1837 +dotnet_diagnostic.CA1837.severity = warning + +# CA1838: Avoid 'StringBuilder' parameters for P/Invokes +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1838 +dotnet_diagnostic.CA1838.severity = silent + +# CA1839: Use 'Environment.ProcessPath' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1839 +dotnet_diagnostic.CA1839.severity = warning + +# CA1840: Use 'Environment.CurrentManagedThreadId' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1840 +dotnet_diagnostic.CA1840.severity = warning + +# CA1841: Prefer Dictionary.Contains methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1841 +dotnet_diagnostic.CA1841.severity = warning + +# CA1842: Do not use 'WhenAll' with a single task +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1842 +dotnet_diagnostic.CA1842.severity = warning + +# CA1843: Do not use 'WaitAll' with a single task +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1843 +dotnet_diagnostic.CA1843.severity = warning + +# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1844 +dotnet_diagnostic.CA1844.severity = warning + +# CA1845: Use span-based 'string.Concat' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1845 +dotnet_diagnostic.CA1845.severity = warning + +# CA1846: Prefer 'AsSpan' over 'Substring' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1846 +dotnet_diagnostic.CA1846.severity = warning + +# CA1847: Use char literal for a single character lookup +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847 +dotnet_diagnostic.CA1847.severity = warning + +# CA2000: Dispose objects before losing scope +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000 +dotnet_diagnostic.CA2000.severity = none + +# CA2002: Do not lock on objects with weak identity +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2002 +dotnet_diagnostic.CA2002.severity = none + +# CA2007: Consider calling ConfigureAwait on the awaited task +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007 +dotnet_diagnostic.CA2007.severity = none + +# CA2008: Do not create tasks without passing a TaskScheduler +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2008 +dotnet_diagnostic.CA2008.severity = none + +# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2009 +dotnet_diagnostic.CA2009.severity = warning + +# CA2011: Avoid infinite recursion +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2011 +dotnet_diagnostic.CA2011.severity = warning + +# CA2012: Use ValueTasks correctly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2012 +dotnet_diagnostic.CA2012.severity = warning + +# CA2013: Do not use ReferenceEquals with value types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2013 +dotnet_diagnostic.CA2013.severity = warning + +# CA2014: Do not use stackalloc in loops +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2014 +dotnet_diagnostic.CA2014.severity = warning + +# CA2015: Do not define finalizers for types derived from MemoryManager +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2015 +dotnet_diagnostic.CA2015.severity = warning + +# CA2016: Forward the 'CancellationToken' parameter to methods that take one +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2016 +dotnet_diagnostic.CA2016.severity = suggestion + +# CA2100: Review SQL queries for security vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100 +dotnet_diagnostic.CA2100.severity = none + +# CA2101: Specify marshaling for P/Invoke string arguments +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2101 +dotnet_diagnostic.CA2101.severity = suggestion + +# CA2109: Review visible event handlers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2109 +dotnet_diagnostic.CA2109.severity = none + +# CA2119: Seal methods that satisfy private interfaces +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2119 +dotnet_diagnostic.CA2119.severity = none + +# CA2153: Do Not Catch Corrupted State Exceptions +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2153 +dotnet_diagnostic.CA2153.severity = none + +# CA2200: Rethrow to preserve stack details +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2200 +dotnet_diagnostic.CA2200.severity = warning + +# CA2201: Do not raise reserved exception types +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2201 +dotnet_diagnostic.CA2201.severity = silent + +# CA2207: Initialize value type static fields inline +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2207 +dotnet_diagnostic.CA2207.severity = warning + +# CA2208: Instantiate argument exceptions correctly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2208 +dotnet_diagnostic.CA2208.severity = suggestion +dotnet_code_quality.CA2208.api_surface = all + +# CA2211: Non-constant fields should not be visible +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2211 +dotnet_diagnostic.CA2211.severity = warning + +# CA2213: Disposable fields should be disposed +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2213 +dotnet_diagnostic.CA2213.severity = none + +# CA2214: Do not call overridable methods in constructors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2214 +dotnet_diagnostic.CA2214.severity = none + +# CA2215: Dispose methods should call base class dispose +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2215 +dotnet_diagnostic.CA2215.severity = silent + +# CA2216: Disposable types should declare finalizer +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2216 +dotnet_diagnostic.CA2216.severity = warning + +# CA2217: Do not mark enums with FlagsAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2217 +dotnet_diagnostic.CA2217.severity = none +dotnet_code_quality.CA2217.api_surface = public + +# CA2218: Override GetHashCode on overriding Equals +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2218 +dotnet_diagnostic.CA2218.severity = suggestion + +# CA2219: Do not raise exceptions in finally clauses +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2219 +dotnet_diagnostic.CA2219.severity = suggestion + +# CA2224: Override Equals on overloading operator equals +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2224 +dotnet_diagnostic.CA2224.severity = suggestion + +# CA2225: Operator overloads have named alternates +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2225 +dotnet_diagnostic.CA2225.severity = none +dotnet_code_quality.CA2225.api_surface = public + +# CA2226: Operators should have symmetrical overloads +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2226 +dotnet_diagnostic.CA2226.severity = none +dotnet_code_quality.CA2226.api_surface = public + +# CA2227: Collection properties should be read only +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2227 +dotnet_diagnostic.CA2227.severity = none + +# CA2229: Implement serialization constructors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2229 +dotnet_diagnostic.CA2229.severity = silent + +# CA2231: Overload operator equals on overriding value type Equals +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2231 +dotnet_diagnostic.CA2231.severity = suggestion +dotnet_code_quality.CA2231.api_surface = public + +# CA2234: Pass system uri objects instead of strings +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2234 +dotnet_diagnostic.CA2234.severity = none +dotnet_code_quality.CA2234.api_surface = public + +# CA2235: Mark all non-serializable fields +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2235 +dotnet_diagnostic.CA2235.severity = none + +# CA2237: Mark ISerializable types with serializable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2237 +dotnet_diagnostic.CA2237.severity = none + +# CA2241: Provide correct arguments to formatting methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2241 +dotnet_diagnostic.CA2241.severity = suggestion + +# CA2242: Test for NaN correctly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2242 +dotnet_diagnostic.CA2242.severity = suggestion + +# CA2243: Attribute string literals should parse correctly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2243 +dotnet_diagnostic.CA2243.severity = warning + +# CA2244: Do not duplicate indexed element initializations +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2244 +dotnet_diagnostic.CA2244.severity = suggestion + +# CA2245: Do not assign a property to itself +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2245 +dotnet_diagnostic.CA2245.severity = suggestion + +# CA2246: Assigning symbol and its member in the same statement +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2246 +dotnet_diagnostic.CA2246.severity = suggestion + +# CA2247: Argument passed to TaskCompletionSource constructor should be TaskCreationOptions enum instead of TaskContinuationOptions enum +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2247 +dotnet_diagnostic.CA2247.severity = warning + +# CA2248: Provide correct 'enum' argument to 'Enum.HasFlag' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2248 +dotnet_diagnostic.CA2248.severity = suggestion + +# CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2249 +dotnet_diagnostic.CA2249.severity = warning + +# CA2250: Use 'ThrowIfCancellationRequested' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2250 +dotnet_diagnostic.CA2250.severity = warning + +# CA2251: Use 'string.Equals' +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2251 +dotnet_diagnostic.CA2251.severity = warning + +# CA2252: This API requires opting into preview features +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2252 +dotnet_diagnostic.CA2251.severity = none + +# CA2300: Do not use insecure deserializer BinaryFormatter +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2300 +dotnet_diagnostic.CA2300.severity = none + +# CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2301 +dotnet_diagnostic.CA2301.severity = none + +# CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2302 +dotnet_diagnostic.CA2302.severity = none + +# CA2305: Do not use insecure deserializer LosFormatter +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2305 +dotnet_diagnostic.CA2305.severity = none + +# CA2310: Do not use insecure deserializer NetDataContractSerializer +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2310 +dotnet_diagnostic.CA2310.severity = none + +# CA2311: Do not deserialize without first setting NetDataContractSerializer.Binder +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2311 +dotnet_diagnostic.CA2311.severity = none + +# CA2312: Ensure NetDataContractSerializer.Binder is set before deserializing +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2312 +dotnet_diagnostic.CA2312.severity = none + +# CA2315: Do not use insecure deserializer ObjectStateFormatter +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2315 +dotnet_diagnostic.CA2315.severity = none + +# CA2321: Do not deserialize with JavaScriptSerializer using a SimpleTypeResolver +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2321 +dotnet_diagnostic.CA2321.severity = none + +# CA2322: Ensure JavaScriptSerializer is not initialized with SimpleTypeResolver before deserializing +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2322 +dotnet_diagnostic.CA2322.severity = none + +# CA2326: Do not use TypeNameHandling values other than None +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2326 +dotnet_diagnostic.CA2326.severity = none + +# CA2327: Do not use insecure JsonSerializerSettings +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2327 +dotnet_diagnostic.CA2327.severity = none + +# CA2328: Ensure that JsonSerializerSettings are secure +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2328 +dotnet_diagnostic.CA2328.severity = none + +# CA2329: Do not deserialize with JsonSerializer using an insecure configuration +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2329 +dotnet_diagnostic.CA2329.severity = none + +# CA2330: Ensure that JsonSerializer has a secure configuration when deserializing +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2330 +dotnet_diagnostic.CA2330.severity = none + +# CA2350: Do not use DataTable.ReadXml() with untrusted data +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2350 +dotnet_diagnostic.CA2350.severity = none + +# CA2351: Do not use DataSet.ReadXml() with untrusted data +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2351 +dotnet_diagnostic.CA2351.severity = none + +# CA2352: Unsafe DataSet or DataTable in serializable type can be vulnerable to remote code execution attacks +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2352 +dotnet_diagnostic.CA2352.severity = none + +# CA2353: Unsafe DataSet or DataTable in serializable type +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2353 +dotnet_diagnostic.CA2353.severity = none + +# CA2354: Unsafe DataSet or DataTable in deserialized object graph can be vulnerable to remote code execution attacks +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2354 +dotnet_diagnostic.CA2354.severity = none + +# CA2355: Unsafe DataSet or DataTable type found in deserializable object graph +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2355 +dotnet_diagnostic.CA2355.severity = none + +# CA2356: Unsafe DataSet or DataTable type in web deserializable object graph +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2356 +dotnet_diagnostic.CA2356.severity = none + +# CA2361: Ensure autogenerated class containing DataSet.ReadXml() is not used with untrusted data +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2361 +dotnet_diagnostic.CA2361.severity = none + +# CA2362: Unsafe DataSet or DataTable in autogenerated serializable type can be vulnerable to remote code execution attacks +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2362 +dotnet_diagnostic.CA2362.severity = none + +# CA3001: Review code for SQL injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3001 +dotnet_diagnostic.CA3001.severity = none + +# CA3002: Review code for XSS vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3002 +dotnet_diagnostic.CA3002.severity = none + +# CA3003: Review code for file path injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3003 +dotnet_diagnostic.CA3003.severity = none + +# CA3004: Review code for information disclosure vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3004 +dotnet_diagnostic.CA3004.severity = none + +# CA3005: Review code for LDAP injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3005 +dotnet_diagnostic.CA3005.severity = none + +# CA3006: Review code for process command injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3006 +dotnet_diagnostic.CA3006.severity = none + +# CA3007: Review code for open redirect vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3007 +dotnet_diagnostic.CA3007.severity = none + +# CA3008: Review code for XPath injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3008 +dotnet_diagnostic.CA3008.severity = none + +# CA3009: Review code for XML injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3009 +dotnet_diagnostic.CA3009.severity = none + +# CA3010: Review code for XAML injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3010 +dotnet_diagnostic.CA3010.severity = none + +# CA3011: Review code for DLL injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3011 +dotnet_diagnostic.CA3011.severity = none + +# CA3012: Review code for regex injection vulnerabilities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3012 +dotnet_diagnostic.CA3012.severity = none + +# CA3061: Do Not Add Schema By URL +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3061 +dotnet_diagnostic.CA3061.severity = silent + +# CA3075: Insecure DTD processing in XML +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3075 +dotnet_diagnostic.CA3075.severity = silent + +# CA3076: Insecure XSLT script processing. +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3076 +dotnet_diagnostic.CA3076.severity = silent + +# CA3077: Insecure Processing in API Design, XmlDocument and XmlTextReader +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3077 +dotnet_diagnostic.CA3077.severity = silent + +# CA3147: Mark Verb Handlers With Validate Antiforgery Token +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3147 +dotnet_diagnostic.CA3147.severity = silent + +# CA5350: Do Not Use Weak Cryptographic Algorithms +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5350 +dotnet_diagnostic.CA5350.severity = silent + +# CA5351: Do Not Use Broken Cryptographic Algorithms +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5351 +dotnet_diagnostic.CA5351.severity = silent + +# CA5358: Review cipher mode usage with cryptography experts +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5358 +dotnet_diagnostic.CA5358.severity = none + +# CA5359: Do Not Disable Certificate Validation +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5359 +dotnet_diagnostic.CA5359.severity = silent + +# CA5360: Do Not Call Dangerous Methods In Deserialization +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5360 +dotnet_diagnostic.CA5360.severity = silent + +# CA5361: Do Not Disable SChannel Use of Strong Crypto +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5361 +dotnet_diagnostic.CA5361.severity = none + +# CA5362: Potential reference cycle in deserialized object graph +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5362 +dotnet_diagnostic.CA5362.severity = none + +# CA5363: Do Not Disable Request Validation +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5363 +dotnet_diagnostic.CA5363.severity = silent + +# CA5364: Do Not Use Deprecated Security Protocols +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5364 +dotnet_diagnostic.CA5364.severity = silent + +# CA5365: Do Not Disable HTTP Header Checking +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5365 +dotnet_diagnostic.CA5365.severity = silent + +# CA5366: Use XmlReader For DataSet Read Xml +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5366 +dotnet_diagnostic.CA5366.severity = silent + +# CA5367: Do Not Serialize Types With Pointer Fields +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5367 +dotnet_diagnostic.CA5367.severity = none + +# CA5368: Set ViewStateUserKey For Classes Derived From Page +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5368 +dotnet_diagnostic.CA5368.severity = silent + +# CA5369: Use XmlReader For Deserialize +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5369 +dotnet_diagnostic.CA5369.severity = silent + +# CA5370: Use XmlReader For Validating Reader +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5370 +dotnet_diagnostic.CA5370.severity = silent + +# CA5371: Use XmlReader For Schema Read +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5371 +dotnet_diagnostic.CA5371.severity = silent + +# CA5372: Use XmlReader For XPathDocument +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5372 +dotnet_diagnostic.CA5372.severity = silent + +# CA5373: Do not use obsolete key derivation function +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5373 +dotnet_diagnostic.CA5373.severity = silent + +# CA5374: Do Not Use XslTransform +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5374 +dotnet_diagnostic.CA5374.severity = silent + +# CA5375: Do Not Use Account Shared Access Signature +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5375 +dotnet_diagnostic.CA5375.severity = none + +# CA5376: Use SharedAccessProtocol HttpsOnly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5376 +dotnet_diagnostic.CA5376.severity = none + +# CA5377: Use Container Level Access Policy +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5377 +dotnet_diagnostic.CA5377.severity = none + +# CA5378: Do not disable ServicePointManagerSecurityProtocols +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5378 +dotnet_diagnostic.CA5378.severity = none + +# CA5379: Do Not Use Weak Key Derivation Function Algorithm +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5379 +dotnet_diagnostic.CA5379.severity = silent + +# CA5380: Do Not Add Certificates To Root Store +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5380 +dotnet_diagnostic.CA5380.severity = none + +# CA5381: Ensure Certificates Are Not Added To Root Store +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5381 +dotnet_diagnostic.CA5381.severity = none + +# CA5382: Use Secure Cookies In ASP.Net Core +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5382 +dotnet_diagnostic.CA5382.severity = none + +# CA5383: Ensure Use Secure Cookies In ASP.Net Core +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5383 +dotnet_diagnostic.CA5383.severity = none + +# CA5384: Do Not Use Digital Signature Algorithm (DSA) +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5384 +dotnet_diagnostic.CA5384.severity = silent + +# CA5385: Use Rivest–Shamir–Adleman (RSA) Algorithm With Sufficient Key Size +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5385 +dotnet_diagnostic.CA5385.severity = silent + +# CA5386: Avoid hardcoding SecurityProtocolType value +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5386 +dotnet_diagnostic.CA5386.severity = none + +# CA5387: Do Not Use Weak Key Derivation Function With Insufficient Iteration Count +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5387 +dotnet_diagnostic.CA5387.severity = none + +# CA5388: Ensure Sufficient Iteration Count When Using Weak Key Derivation Function +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5388 +dotnet_diagnostic.CA5388.severity = none + +# CA5389: Do Not Add Archive Item's Path To The Target File System Path +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5389 +dotnet_diagnostic.CA5389.severity = none + +# CA5390: Do not hard-code encryption key +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5390 +dotnet_diagnostic.CA5390.severity = none + +# CA5391: Use antiforgery tokens in ASP.NET Core MVC controllers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5391 +dotnet_diagnostic.CA5391.severity = none + +# CA5392: Use DefaultDllImportSearchPaths attribute for P/Invokes +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5392 +dotnet_diagnostic.CA5392.severity = none + +# CA5393: Do not use unsafe DllImportSearchPath value +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5393 +dotnet_diagnostic.CA5393.severity = none + +# CA5394: Do not use insecure randomness +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5394 +dotnet_diagnostic.CA5394.severity = none + +# CA5395: Miss HttpVerb attribute for action methods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5395 +dotnet_diagnostic.CA5395.severity = none + +# CA5396: Set HttpOnly to true for HttpCookie +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5396 +dotnet_diagnostic.CA5396.severity = none + +# CA5397: Do not use deprecated SslProtocols values +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5397 +dotnet_diagnostic.CA5397.severity = silent + +# CA5398: Avoid hardcoded SslProtocols values +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5398 +dotnet_diagnostic.CA5398.severity = none + +# CA5399: HttpClients should enable certificate revocation list checks +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5399 +dotnet_diagnostic.CA5399.severity = none + +# CA5400: Ensure HttpClient certificate revocation list check is not disabled +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5400 +dotnet_diagnostic.CA5400.severity = none + +# CA5401: Do not use CreateEncryptor with non-default IV +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5401 +dotnet_diagnostic.CA5401.severity = none + +# CA5402: Use CreateEncryptor with the default IV +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5402 +dotnet_diagnostic.CA5402.severity = none + +# CA5403: Do not hard-code certificate +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5403 +dotnet_diagnostic.CA5403.severity = none + +# IL3000: Avoid using accessing Assembly file path when publishing as a single-file +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3000 +dotnet_diagnostic.IL3000.severity = warning + +# IL3001: Avoid using accessing Assembly file path when publishing as a single-file +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3001 +dotnet_diagnostic.IL3001.severity = warning + +# IL3002: Using member with RequiresAssemblyFilesAttribute can break functionality when embedded in a single-file app +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3002 +dotnet_diagnostic.IL3002.severity = warning + +# DOC100: PlaceTextInParagraphs +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC100.md +dotnet_diagnostic.DOC100.severity = none + +# DOC101: UseChildBlocksConsistently +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC101.md +dotnet_diagnostic.DOC101.severity = none + +# DOC102: UseChildBlocksConsistentlyAcrossElementsOfTheSameKind +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC102.md +dotnet_diagnostic.DOC102.severity = none + +# DOC103: UseUnicodeCharacters +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC103.md +dotnet_diagnostic.DOC103.severity = none + +# DOC104: UseSeeLangword +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC104.md +dotnet_diagnostic.DOC104.severity = suggestion + +# DOC105: UseParamref +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC105.md +dotnet_diagnostic.DOC105.severity = none + +# DOC106: UseTypeparamref +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC106.md +dotnet_diagnostic.DOC106.severity = none + +# DOC107: UseSeeCref +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC107.md +dotnet_diagnostic.DOC107.severity = none + +# DOC108: AvoidEmptyParagraphs +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC108.md +dotnet_diagnostic.DOC108.severity = none + +# DOC200: UseXmlDocumentationSyntax +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC200.md +dotnet_diagnostic.DOC200.severity = none + +# DOC201: ItemShouldHaveDescription +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC201.md +dotnet_diagnostic.DOC201.severity = none + +# DOC202: UseSectionElementsCorrectly +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC202.md +dotnet_diagnostic.DOC202.severity = none + +# DOC203: UseBlockElementsCorrectly +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC203.md +dotnet_diagnostic.DOC203.severity = none + +# DOC204: UseInlineElementsCorrectly +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC204.md +dotnet_diagnostic.DOC204.severity = none + +# DOC207: UseSeeLangwordCorrectly +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC207.md +dotnet_diagnostic.DOC207.severity = none + +# DOC209: UseSeeHrefCorrectly +# https://github.com/DotNetAnalyzers/DocumentationAnalyzers/blob/master/docs/DOC209.md +dotnet_diagnostic.DOC209.severity = none + +# IDE0001: SimplifyNames +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0001 +dotnet_diagnostic.IDE0001.severity = silent + +# IDE0002: SimplifyMemberAccess +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0002 +dotnet_diagnostic.IDE0002.severity = silent + +# IDE0003: RemoveQualification +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0003 +dotnet_diagnostic.IDE0003.severity = silent + +# IDE0004: RemoveUnnecessaryCast +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0004 +dotnet_diagnostic.IDE0004.severity = silent + +# IDE0005: RemoveUnnecessaryImports +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005 +dotnet_diagnostic.IDE0005.severity = silent + +# IDE0006: IntellisenseBuildFailed +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0006 +dotnet_diagnostic.IDE0006.severity = silent + +# IDE0007: UseImplicitType +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0007 +dotnet_diagnostic.IDE0007.severity = silent + +# IDE0008: UseExplicitType +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008 +dotnet_diagnostic.IDE0008.severity = silent + +# IDE0009: AddQualification +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0009 +dotnet_diagnostic.IDE0009.severity = silent + +# IDE0010: PopulateSwitchStatement +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0010 +dotnet_diagnostic.IDE0010.severity = silent + +# IDE0011: AddBraces +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0011 +dotnet_diagnostic.IDE0011.severity = silent + +# IDE0016: UseThrowExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0016 +dotnet_diagnostic.IDE0016.severity = silent + +# IDE0017: UseObjectInitializer +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0017 +dotnet_diagnostic.IDE0017.severity = silent + +# IDE0018: InlineDeclaration +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0018 +dotnet_diagnostic.IDE0018.severity = silent + +# IDE0019: InlineAsTypeCheck +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0019 +dotnet_diagnostic.IDE0019.severity = silent + +# IDE0020: InlineIsTypeCheck +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0020 +dotnet_diagnostic.IDE0020.severity = silent + +# IDE0021: UseExpressionBodyForConstructors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0021 +dotnet_diagnostic.IDE0021.severity = silent + +# IDE0022: UseExpressionBodyForMethods +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0022 +dotnet_diagnostic.IDE0022.severity = silent + +# IDE0023: UseExpressionBodyForConversionOperators +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0023 +dotnet_diagnostic.IDE0023.severity = silent + +# IDE0024: UseExpressionBodyForOperators +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0024 +dotnet_diagnostic.IDE0024.severity = silent + +# IDE0025: UseExpressionBodyForProperties +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0025 +dotnet_diagnostic.IDE0025.severity = silent + +# IDE0026: UseExpressionBodyForIndexers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0026 +dotnet_diagnostic.IDE0026.severity = silent + +# IDE0027: UseExpressionBodyForAccessors +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0027 +dotnet_diagnostic.IDE0027.severity = silent + +# IDE0028: UseCollectionInitializer +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0028 +dotnet_diagnostic.IDE0028.severity = silent + +# IDE0029: UseCoalesceExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0029 +dotnet_diagnostic.IDE0029.severity = warning + +# IDE0030: UseCoalesceExpressionForNullable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0030 +dotnet_diagnostic.IDE0030.severity = warning + +# IDE0031: UseNullPropagation +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0031 +dotnet_diagnostic.IDE0031.severity = warning + +# IDE0032: UseAutoProperty +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0032 +dotnet_diagnostic.IDE0032.severity = silent + +# IDE0033: UseExplicitTupleName +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0033 +dotnet_diagnostic.IDE0033.severity = silent + +# IDE0034: UseDefaultLiteral +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0034 +dotnet_diagnostic.IDE0034.severity = silent + +# IDE0035: RemoveUnreachableCode +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0035 +dotnet_diagnostic.IDE0035.severity = silent + +# IDE0036: OrderModifiers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0036 +dotnet_diagnostic.IDE0036.severity = warning + +# IDE0037: UseInferredMemberName +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0037 +dotnet_diagnostic.IDE0037.severity = silent + +# IDE0038: InlineIsTypeWithoutNameCheck +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0038 +dotnet_diagnostic.IDE0038.severity = silent + +# IDE0039: UseLocalFunction +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0039 +dotnet_diagnostic.IDE0039.severity = silent + +# IDE0040: AddAccessibilityModifiers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0040 +dotnet_diagnostic.IDE0040.severity = warning + +# IDE0041: UseIsNullCheck +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0041 +dotnet_diagnostic.IDE0041.severity = warning + +# IDE0042: UseDeconstruction +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0042 +dotnet_diagnostic.IDE0042.severity = silent + +# IDE0043: ValidateFormatString +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0043 +dotnet_diagnostic.IDE0043.severity = silent + +# IDE0044: MakeFieldReadonly +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0044 +dotnet_diagnostic.IDE0044.severity = warning + +# IDE0045: UseConditionalExpressionForAssignment +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0045 +dotnet_diagnostic.IDE0045.severity = silent + +# IDE0046: UseConditionalExpressionForReturn +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0046 +dotnet_diagnostic.IDE0046.severity = silent + +# IDE0047: RemoveUnnecessaryParentheses +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0047 +dotnet_diagnostic.IDE0047.severity = silent + +# IDE0048: AddRequiredParentheses +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0048 +dotnet_diagnostic.IDE0048.severity = suggestion + +# IDE0049: PreferBuiltInOrFrameworkType +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0049 +dotnet_diagnostic.IDE0049.severity = warning + +# IDE0050: ConvertAnonymousTypeToTuple +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0050 +dotnet_diagnostic.IDE0050.severity = silent + +# IDE0051: RemoveUnusedMembers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0051 +dotnet_diagnostic.IDE0051.severity = silent + +# IDE0052: RemoveUnreadMembers +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0052 +dotnet_diagnostic.IDE0052.severity = silent + +# IDE0053: UseExpressionBodyForLambdaExpressions +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0053 +dotnet_diagnostic.IDE0053.severity = silent + +# IDE0054: UseCompoundAssignment +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0054 +dotnet_diagnostic.IDE0054.severity = warning + +# IDE0055: Formatting +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055 +dotnet_diagnostic.IDE0055.severity = silent + +# IDE0056: UseIndexOperator +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0056 +dotnet_diagnostic.IDE0056.severity = silent + +# IDE0057: UseRangeOperator +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0057 +dotnet_diagnostic.IDE0057.severity = silent + +# IDE0058: ExpressionValueIsUnused +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0058 +dotnet_diagnostic.IDE0058.severity = silent + +# IDE0059: ValueAssignedIsUnused +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059 +dotnet_diagnostic.IDE0059.severity = silent + +# IDE0060: UnusedParameter +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060 +dotnet_diagnostic.IDE0060.severity = silent + +# IDE0061: UseExpressionBodyForLocalFunctions +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0061 +dotnet_diagnostic.IDE0061.severity = silent + +# IDE0062: MakeLocalFunctionStatic +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0062 +dotnet_diagnostic.IDE0062.severity = warning + +# IDE0063: UseSimpleUsingStatement +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0063 +dotnet_diagnostic.IDE0063.severity = silent + +# IDE0064: MakeStructFieldsWritable +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0064 +dotnet_diagnostic.IDE0064.severity = warning + +# IDE0065: MoveMisplacedUsingDirectives +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0065 +dotnet_diagnostic.IDE0065.severity = silent + +# IDE0066: ConvertSwitchStatementToExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0066 +dotnet_diagnostic.IDE0066.severity = silent + +# IDE0070: UseSystemHashCode +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0070 +dotnet_diagnostic.IDE0070.severity = warning + +# IDE0071: SimplifyInterpolation +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0071 +dotnet_diagnostic.IDE0071.severity = silent + +# IDE0072: PopulateSwitchExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0072 +dotnet_diagnostic.IDE0072.severity = silent + +# IDE0073: FileHeaderMismatch +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0073 +dotnet_diagnostic.IDE0073.severity = suggestion + +# IDE0074: UseCoalesceCompoundAssignment +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0074 +dotnet_diagnostic.IDE0074.severity = warning + +# IDE0075: SimplifyConditionalExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0075 +dotnet_diagnostic.IDE0075.severity = warning + +# IDE0076: InvalidSuppressMessageAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0076 +dotnet_diagnostic.IDE0076.severity = warning + +# IDE0077: LegacyFormatSuppressMessageAttribute +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0077 +dotnet_diagnostic.IDE0077.severity = warning + +# IDE0078: UsePatternCombinators +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0078 +dotnet_diagnostic.IDE0078.severity = silent + +# IDE0079: RemoveUnnecessarySuppression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0079 +dotnet_diagnostic.IDE0079.severity = silent + +# IDE0080: RemoveConfusingSuppressionForIsExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0080 +dotnet_diagnostic.IDE0080.severity = silent + +# IDE0081: RemoveUnnecessaryByVal +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0081 +dotnet_diagnostic.IDE0081.severity = silent + +# IDE0082: ConvertTypeOfToNameOf +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0082 +dotnet_diagnostic.IDE0082.severity = warning + +# IDE0083: UseNotPattern +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0083 +dotnet_diagnostic.IDE0083.severity = silent + +# IDE0084: UseIsNotExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0084 +dotnet_diagnostic.IDE0084.severity = silent + +# IDE0090: UseNew +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0090 +dotnet_diagnostic.IDE0090.severity = suggestion + +# IDE0100: RemoveRedundantEquality +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0100 +dotnet_diagnostic.IDE0100.severity = warning + +# IDE0110: RemoveUnnecessaryDiscard +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0110 +dotnet_diagnostic.IDE0110.severity = suggestion + +# IDE0120: SimplifyLINQExpression +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0120 +dotnet_diagnostic.IDE0120.severity = warning + +# IDE0130: NamespaceDoesNotMatchFolderStructure +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0130 +dotnet_diagnostic.IDE0130.severity = silent + +# IDE1001: AnalyzerChanged +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1001 +dotnet_diagnostic.IDE1001.severity = silent + +# IDE1002: AnalyzerDependencyConflict +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1002 +dotnet_diagnostic.IDE1002.severity = silent + +# IDE1003: MissingAnalyzerReference +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1003 +dotnet_diagnostic.IDE1003.severity = silent + +# IDE1004: ErrorReadingRuleset +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1004 +dotnet_diagnostic.IDE1004.severity = silent + +# IDE1005: InvokeDelegateWithConditionalAccess +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1005 +dotnet_diagnostic.IDE1005.severity = warning + +# IDE1006: NamingRule +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006 +dotnet_diagnostic.IDE1006.severity = silent + +# IDE1007: UnboundIdentifier +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1007 +dotnet_diagnostic.IDE1007.severity = silent + +# IDE1008: UnboundConstructor +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1008 +dotnet_diagnostic.IDE1008.severity = silent + +# IDE2000: MultipleBlankLines +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000 +dotnet_diagnostic.IDE2000.severity = warning + +# IDE2001: EmbeddedStatementsMustBeOnTheirOwnLine +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2001 +dotnet_diagnostic.IDE2001.severity = warning + +# IDE2002: ConsecutiveBracesMustNotHaveBlankLinesBetweenThem +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2002 +dotnet_diagnostic.IDE2002.severity = warning + +# IDE2003: ConsecutiveStatementPlacement +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2003 +dotnet_diagnostic.IDE2003.severity = warning + +# IDE2004: BlankLineNotAllowedAfterConstructorInitializerColon +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2004 +dotnet_diagnostic.IDE2004.severity = warning + +# SA0001: XML comment analysis disabled +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA0001.md +dotnet_diagnostic.SA0001.severity = none + +# SA0002: Invalid settings file +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA0002.md +dotnet_diagnostic.SA0002.severity = none + +# SA1000: Keywords should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1000.md +dotnet_diagnostic.SA1000.severity = warning + +# SA1001: Commas should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1001.md +dotnet_diagnostic.SA1001.severity = warning + +# SA1002: Semicolons should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1002.md +dotnet_diagnostic.SA1002.severity = warning + +# SA1003: Symbols should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1003.md +dotnet_diagnostic.SA1003.severity = warning + +# SA1004: Documentation lines should begin with single space +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1004.md +dotnet_diagnostic.SA1004.severity = none + +# SA1005: Single line comments should begin with single space +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1005.md +dotnet_diagnostic.SA1005.severity = none + +# SA1006: Preprocessor keywords should not be preceded by space +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1006.md +dotnet_diagnostic.SA1006.severity = warning + +# SA1007: Operator keyword should be followed by space +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1007.md +dotnet_diagnostic.SA1007.severity = warning + +# SA1008: Opening parenthesis should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1008.md +dotnet_diagnostic.SA1008.severity = warning + +# SA1009: Closing parenthesis should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1009.md +dotnet_diagnostic.SA1009.severity = none + +# SA1010: Opening square brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1010.md +dotnet_diagnostic.SA1010.severity = none + +# SA1011: Closing square brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1011.md +dotnet_diagnostic.SA1011.severity = none + +# SA1012: Opening braces should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1012.md +dotnet_diagnostic.SA1012.severity = none + +# SA1013: Closing braces should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1013.md +dotnet_diagnostic.SA1013.severity = none + +# SA1014: Opening generic brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1014.md +dotnet_diagnostic.SA1014.severity = none + +# SA1015: Closing generic brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1015.md +dotnet_diagnostic.SA1015.severity = none + +# SA1016: Opening attribute brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1016.md +dotnet_diagnostic.SA1016.severity = none + +# SA1017: Closing attribute brackets should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1017.md +dotnet_diagnostic.SA1017.severity = none + +# SA1018: Nullable type symbols should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1018.md +dotnet_diagnostic.SA1018.severity = none + +# SA1019: Member access symbols should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1019.md +dotnet_diagnostic.SA1019.severity = none + +# SA1020: Increment decrement symbols should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1020.md +dotnet_diagnostic.SA1020.severity = none + +# SA1021: Negative signs should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1021.md +dotnet_diagnostic.SA1021.severity = none + +# SA1022: Positive signs should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1022.md +dotnet_diagnostic.SA1022.severity = none + +# SA1023: Dereference and access of symbols should be spaced correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1023.md +dotnet_diagnostic.SA1023.severity = none + +# SA1024: Colons Should Be Spaced Correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1024.md +dotnet_diagnostic.SA1024.severity = none + +# SA1025: Code should not contain multiple whitespace in a row +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1025.md +dotnet_diagnostic.SA1025.severity = none + +# SA1026: Code should not contain space after new or stackalloc keyword in implicitly typed array allocation +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1026.md +dotnet_diagnostic.SA1026.severity = none + +# SA1027: Use tabs correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1027.md +dotnet_diagnostic.SA1027.severity = none + +# SA1028: Code should not contain trailing whitespace +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1028.md +dotnet_diagnostic.SA1028.severity = none + +# SA1100: Do not prefix calls with base unless local implementation exists +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1100.md +dotnet_diagnostic.SA1100.severity = none + +# SA1101: Prefix local calls with this +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1101.md +dotnet_diagnostic.SA1101.severity = none + +# SA1102: Query clause should follow previous clause +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1102.md +dotnet_diagnostic.SA1102.severity = none + +# SA1103: Query clauses should be on separate lines or all on one line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1103.md +dotnet_diagnostic.SA1103.severity = none + +# SA1104: Query clause should begin on new line when previous clause spans multiple lines +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1104.md +dotnet_diagnostic.SA1104.severity = none + +# SA1105: Query clauses spanning multiple lines should begin on own line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1105.md +dotnet_diagnostic.SA1105.severity = none + +# SA1106: Code should not contain empty statements +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1106.md +dotnet_diagnostic.SA1106.severity = warning + +# SA1107: Code should not contain multiple statements on one line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1107.md +dotnet_diagnostic.SA1107.severity = none + +# SA1108: Block statements should not contain embedded comments +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1108.md +dotnet_diagnostic.SA1108.severity = none + +# SA1110: Opening parenthesis or bracket should be on declaration line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1110.md +dotnet_diagnostic.SA1110.severity = none + +# SA1111: Closing parenthesis should be on line of last parameter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1111.md +dotnet_diagnostic.SA1111.severity = none + +# SA1112: Closing parenthesis should be on line of opening parenthesis +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1112.md +dotnet_diagnostic.SA1112.severity = none + +# SA1113: Comma should be on the same line as previous parameter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1113.md +dotnet_diagnostic.SA1113.severity = none + +# SA1114: Parameter list should follow declaration +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1114.md +dotnet_diagnostic.SA1114.severity = none + +# SA1115: Parameter should follow comma +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1115.md +dotnet_diagnostic.SA1115.severity = none + +# SA1116: Split parameters should start on line after declaration +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md +dotnet_diagnostic.SA1116.severity = none + +# SA1117: Parameters should be on same line or separate lines +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1117.md +dotnet_diagnostic.SA1117.severity = none + +# SA1118: Parameter should not span multiple lines +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1118.md +dotnet_diagnostic.SA1118.severity = none + +# SA1119: Statement should not use unnecessary parenthesis +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1119.md +dotnet_diagnostic.SA1119.severity = none + +# SA1120: Comments should contain text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1120.md +dotnet_diagnostic.SA1120.severity = none + +# SA1121: Use built-in type alias +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1121.md +dotnet_diagnostic.SA1121.severity = none + +# SA1122: Use string.Empty for empty strings +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1122.md +dotnet_diagnostic.SA1122.severity = warning + +# SA1123: Do not place regions within elements +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1123.md +dotnet_diagnostic.SA1123.severity = none + +# SA1124: Do not use regions +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1124.md +dotnet_diagnostic.SA1124.severity = none + +# SA1125: Use shorthand for nullable types +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1125.md +dotnet_diagnostic.SA1125.severity = none + +# SA1127: Generic type constraints should be on their own line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1127.md +dotnet_diagnostic.SA1127.severity = none + +# SA1128: Put constructor initializers on their own line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1128.md +dotnet_diagnostic.SA1128.severity = none + +# SA1129: Do not use default value type constructor +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1129.md +dotnet_diagnostic.SA1129.severity = none + +# SA1130: Use lambda syntax +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1130.md +dotnet_diagnostic.SA1130.severity = none + +# SA1131: Use readable conditions +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1131.md +dotnet_diagnostic.SA1131.severity = warning + +# SA1132: Do not combine fields +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1132.md +dotnet_diagnostic.SA1132.severity = none + +# SA1133: Do not combine attributes +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1133.md +dotnet_diagnostic.SA1133.severity = none + +# SA1134: Attributes should not share line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1134.md +dotnet_diagnostic.SA1134.severity = none + +# SA1135: Using directives should be qualified +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1135.md +dotnet_diagnostic.SA1135.severity = none + +# SA1136: Enum values should be on separate lines +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1136.md +dotnet_diagnostic.SA1136.severity = none + +# SA1137: Elements should have the same indentation +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md +dotnet_diagnostic.SA1137.severity = none + +# SA1139: Use literal suffix notation instead of casting +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1139.md +dotnet_diagnostic.SA1139.severity = none + +# SA1141: Use tuple syntax +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1141.md +dotnet_diagnostic.SA1141.severity = none + +# SA1142: Refer to tuple fields by name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1142.md +dotnet_diagnostic.SA1142.severity = none + +# SA1200: Using directives should be placed correctly +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1200.md +dotnet_diagnostic.SA1200.severity = none + +# SA1201: Elements should appear in the correct order +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1201.md +dotnet_diagnostic.SA1201.severity = none + +# SA1202: Elements should be ordered by access +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md +dotnet_diagnostic.SA1202.severity = none + +# SA1203: Constants should appear before fields +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1203.md +dotnet_diagnostic.SA1203.severity = none + +# SA1204: Static elements should appear before instance elements +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1204.md +dotnet_diagnostic.SA1204.severity = none + +# SA1205: Partial elements should declare access +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1205.md +dotnet_diagnostic.SA1205.severity = warning + +# SA1206: Declaration keywords should follow order +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1206.md +dotnet_diagnostic.SA1206.severity = none + +# SA1207: Protected should come before internal +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1207.md +dotnet_diagnostic.SA1207.severity = none + +# SA1208: System using directives should be placed before other using directives +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1208.md +dotnet_diagnostic.SA1208.severity = none + +# SA1209: Using alias directives should be placed after other using directives +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1209.md +dotnet_diagnostic.SA1209.severity = none + +# SA1210: Using directives should be ordered alphabetically by namespace +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1210.md +dotnet_diagnostic.SA1210.severity = none + +# SA1211: Using alias directives should be ordered alphabetically by alias name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1211.md +dotnet_diagnostic.SA1211.severity = none + +# SA1212: Property accessors should follow order +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1212.md +dotnet_diagnostic.SA1212.severity = warning + +# SA1213: Event accessors should follow order +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1213.md +dotnet_diagnostic.SA1213.severity = warning + +# SA1214: Readonly fields should appear before non-readonly fields +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1214.md +dotnet_diagnostic.SA1214.severity = none + +# SA1216: Using static directives should be placed at the correct location +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1216.md +dotnet_diagnostic.SA1216.severity = warning + +# SA1217: Using static directives should be ordered alphabetically +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1217.md +dotnet_diagnostic.SA1217.severity = warning + +# SA1300: Element should begin with upper-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md +dotnet_diagnostic.SA1300.severity = none + +# SA1302: Interface names should begin with I +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1302.md +dotnet_diagnostic.SA1302.severity = none + +# SA1303: Const field names should begin with upper-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md +dotnet_diagnostic.SA1303.severity = none + +# SA1304: Non-private readonly fields should begin with upper-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1304.md +dotnet_diagnostic.SA1304.severity = none + +# SA1305: Field names should not use Hungarian notation +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1305.md +dotnet_diagnostic.SA1305.severity = none + +# SA1306: Field names should begin with lower-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md +dotnet_diagnostic.SA1306.severity = none + +# SA1307: Accessible fields should begin with upper-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1307.md +dotnet_diagnostic.SA1307.severity = none + +# SA1308: Variable names should not be prefixed +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1308.md +dotnet_diagnostic.SA1308.severity = none + +# SA1309: Field names should not begin with underscore +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1309.md +dotnet_diagnostic.SA1309.severity = none + +# SA1310: Field names should not contain underscore +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1310.md +dotnet_diagnostic.SA1310.severity = none + +# SA1311: Static readonly fields should begin with upper-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md +dotnet_diagnostic.SA1311.severity = none + +# SA1312: Variable names should begin with lower-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md +dotnet_diagnostic.SA1312.severity = none + +# SA1313: Parameter names should begin with lower-case letter +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1313.md +dotnet_diagnostic.SA1313.severity = none + +# SA1314: Type parameter names should begin with T +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1314.md +dotnet_diagnostic.SA1314.severity = warning + +# SA1316: Tuple element names should use correct casing +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1316.md +dotnet_diagnostic.SA1316.severity = none + +# SA1400: Access modifier should be declared +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1400.md +dotnet_diagnostic.SA1400.severity = none + +# SA1401: Fields should be private +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md +dotnet_diagnostic.SA1401.severity = none + +# SA1402: File may only contain a single type +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1402.md +dotnet_diagnostic.SA1402.severity = none + +# SA1403: File may only contain a single namespace +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1403.md +dotnet_diagnostic.SA1403.severity = none + +# SA1404: Code analysis suppression should have justification +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1404.md +dotnet_diagnostic.SA1404.severity = none + +# SA1405: Debug.Assert should provide message text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1405.md +dotnet_diagnostic.SA1405.severity = none + +# SA1406: Debug.Fail should provide message text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1406.md +dotnet_diagnostic.SA1406.severity = none + +# SA1407: Arithmetic expressions should declare precedence +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1407.md +dotnet_diagnostic.SA1407.severity = none + +# SA1408: Conditional expressions should declare precedence +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1408.md +dotnet_diagnostic.SA1408.severity = none + +# SA1410: Remove delegate parenthesis when possible +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1410.md +dotnet_diagnostic.SA1410.severity = none + +# SA1411: Attribute constructor should not use unnecessary parenthesis +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1411.md +dotnet_diagnostic.SA1411.severity = none + +# SA1412: Store files as UTF-8 with byte order mark +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1412.md +dotnet_diagnostic.SA1412.severity = none + +# SA1413: Use trailing comma in multi-line initializers +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1413.md +dotnet_diagnostic.SA1413.severity = none + +# SA1414: Tuple types in signatures should have element names +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1414.md +dotnet_diagnostic.SA1414.severity = none + +# SA1500: Braces for multi-line statements should not share line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1500.md +dotnet_diagnostic.SA1500.severity = none + +# SA1501: Statement should not be on a single line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1501.md +dotnet_diagnostic.SA1501.severity = none + +# SA1502: Element should not be on a single line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1502.md +dotnet_diagnostic.SA1502.severity = none + +# SA1503: Braces should not be omitted +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1503.md +dotnet_diagnostic.SA1503.severity = none + +# SA1504: All accessors should be single-line or multi-line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1504.md +dotnet_diagnostic.SA1504.severity = warning + +# SA1505: Opening braces should not be followed by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1505.md +dotnet_diagnostic.SA1505.severity = none + +# SA1506: Element documentation headers should not be followed by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1506.md +dotnet_diagnostic.SA1506.severity = none + +# SA1507: Code should not contain multiple blank lines in a row +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md +dotnet_diagnostic.SA1507.severity = warning + +# SA1508: Closing braces should not be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1508.md +dotnet_diagnostic.SA1508.severity = none + +# SA1509: Opening braces should not be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1509.md +dotnet_diagnostic.SA1509.severity = none + +# SA1510: Chained statement blocks should not be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1510.md +dotnet_diagnostic.SA1510.severity = none + +# SA1511: While-do footer should not be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1511.md +dotnet_diagnostic.SA1511.severity = none + +# SA1512: Single-line comments should not be followed by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1512.md +dotnet_diagnostic.SA1512.severity = none + +# SA1513: Closing brace should be followed by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1513.md +dotnet_diagnostic.SA1513.severity = none + +# SA1514: Element documentation header should be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md +dotnet_diagnostic.SA1514.severity = none + +# SA1515: Single-line comment should be preceded by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1515.md +dotnet_diagnostic.SA1515.severity = none + +# SA1516: Elements should be separated by blank line +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1516.md +dotnet_diagnostic.SA1516.severity = warning + +# SA1517: Code should not contain blank lines at start of file +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1517.md +dotnet_diagnostic.SA1517.severity = warning + +# SA1518: Use line endings correctly at end of file +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1518.md +dotnet_diagnostic.SA1518.severity = warning + +# SA1519: Braces should not be omitted from multi-line child statement +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1519.md +dotnet_diagnostic.SA1519.severity = none + +# SA1520: Use braces consistently +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1520.md +dotnet_diagnostic.SA1520.severity = none + +# SA1600: Elements should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1600.md +dotnet_diagnostic.SA1600.severity = none + +# SA1601: Partial elements should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1601.md +dotnet_diagnostic.SA1601.severity = none + +# SA1602: Enumeration items should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1602.md +dotnet_diagnostic.SA1602.severity = none + +# SA1604: Element documentation should have summary +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1604.md +dotnet_diagnostic.SA1604.severity = none + +# SA1605: Partial element documentation should have summary +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1605.md +dotnet_diagnostic.SA1605.severity = none + +# SA1606: Element documentation should have summary text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1606.md +dotnet_diagnostic.SA1606.severity = none + +# SA1607: Partial element documentation should have summary text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1607.md +dotnet_diagnostic.SA1607.severity = none + +# SA1608: Element documentation should not have default summary +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1608.md +dotnet_diagnostic.SA1608.severity = none + +# SA1609: Property documentation should have value +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1609.md +dotnet_diagnostic.SA1609.severity = none + +# SA1610: Property documentation should have value text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1610.md +dotnet_diagnostic.SA1610.severity = none + +# SA1611: Element parameters should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1611.md +dotnet_diagnostic.SA1611.severity = none + +# SA1612: Element parameter documentation should match element parameters +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1612.md +dotnet_diagnostic.SA1612.severity = none + +# SA1613: Element parameter documentation should declare parameter name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1613.md +dotnet_diagnostic.SA1613.severity = none + +# SA1614: Element parameter documentation should have text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1614.md +dotnet_diagnostic.SA1614.severity = none + +# SA1615: Element return value should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1615.md +dotnet_diagnostic.SA1615.severity = none + +# SA1616: Element return value documentation should have text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1616.md +dotnet_diagnostic.SA1616.severity = none + +# SA1617: Void return value should not be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1617.md +dotnet_diagnostic.SA1617.severity = none + +# SA1618: Generic type parameters should be documented +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1618.md +dotnet_diagnostic.SA1618.severity = none + +# SA1619: Generic type parameters should be documented partial class +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1619.md +dotnet_diagnostic.SA1619.severity = none + +# SA1620: Generic type parameter documentation should match type parameters +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1620.md +dotnet_diagnostic.SA1620.severity = none + +# SA1621: Generic type parameter documentation should declare parameter name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1621.md +dotnet_diagnostic.SA1621.severity = none + +# SA1622: Generic type parameter documentation should have text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1622.md +dotnet_diagnostic.SA1622.severity = none + +# SA1623: Property summary documentation should match accessors +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1623.md +dotnet_diagnostic.SA1623.severity = none + +# SA1624: Property summary documentation should omit accessor with restricted access +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1624.md +dotnet_diagnostic.SA1624.severity = none + +# SA1625: Element documentation should not be copied and pasted +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1625.md +dotnet_diagnostic.SA1625.severity = none + +# SA1626: Single-line comments should not use documentation style slashes +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1626.md +dotnet_diagnostic.SA1626.severity = none + +# SA1627: Documentation text should not be empty +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1627.md +dotnet_diagnostic.SA1627.severity = none + +# SA1629: Documentation text should end with a period +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1629.md +dotnet_diagnostic.SA1629.severity = none + +# SA1633: File should have header +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1633.md +dotnet_diagnostic.SA1633.severity = none + +# SA1634: File header should show copyright +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1634.md +dotnet_diagnostic.SA1634.severity = none + +# SA1635: File header should have copyright text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1635.md +dotnet_diagnostic.SA1635.severity = none + +# SA1636: File header copyright text should match +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1636.md +dotnet_diagnostic.SA1636.severity = none + +# SA1637: File header should contain file name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1637.md +dotnet_diagnostic.SA1637.severity = none + +# SA1638: File header file name documentation should match file name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1638.md +dotnet_diagnostic.SA1638.severity = none + +# SA1639: File header should have summary +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1639.md +dotnet_diagnostic.SA1639.severity = none + +# SA1640: File header should have valid company text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1640.md +dotnet_diagnostic.SA1640.severity = none + +# SA1641: File header company name text should match +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1641.md +dotnet_diagnostic.SA1641.severity = none + +# SA1642: Constructor summary documentation should begin with standard text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1642.md +dotnet_diagnostic.SA1642.severity = none + +# SA1643: Destructor summary documentation should begin with standard text +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1643.md +dotnet_diagnostic.SA1643.severity = warning + +# SA1648: inheritdoc should be used with inheriting class +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1648.md +dotnet_diagnostic.SA1648.severity = none + +# SA1649: File name should match first type name +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1649.md +dotnet_diagnostic.SA1649.severity = none + +# SA1651: Do not use placeholder elements +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1651.md +dotnet_diagnostic.SA1651.severity = none + +# SX1101: Do not prefix local calls with 'this.' +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SX1101.md +dotnet_diagnostic.SX1101.severity = none + +# SX1309: Field names should begin with underscore +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SX1309.md +dotnet_diagnostic.SX1309.severity = none + +# SX1309S: Static field names should begin with underscore +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SX1309S.md +dotnet_diagnostic.SX1309S.severity = none diff --git a/.spelling b/.spelling index aa51076c83e..65fef8f019e 100644 --- a/.spelling +++ b/.spelling @@ -132,6 +132,7 @@ CodeFormatter codeowner codepage commanddiscovery +CommandInvocationIntrinsics commandsearch CommandSearcher comobject @@ -176,6 +177,7 @@ ctrl CurrentCulture CustomShellCommands.cs DamirAinullin +DarylGraves darquewarrior darwinjs DateTime @@ -284,6 +286,7 @@ folderName foreach formatfileloading formatviewbinding +FormatWideCommand Francisco-Gamino frontload fullclr @@ -355,6 +358,7 @@ helpproviderwithfullcache helpsystem hemant hemantmahawar +Higinbotham himura2la hololens homebrew @@ -383,6 +387,7 @@ includeusername informationrecord initializers install-packageprovider +IntelliSense interactivetesting interop interoperation @@ -443,6 +448,8 @@ launch.json ldspits lee303 Leonhardt +Libera.Chat +libicu libpsl libpsl-native libunwind8 @@ -481,6 +488,7 @@ miaromero microsoft Microsoft.ApplicationInsights Microsoft.CodeAnalysis.CSharp +Microsoft.CodeAnalysis.NetAnalyzers microsoft.com microsoft.management.infrastructure.cimcmdlets microsoft.management.infrastructure.native @@ -646,6 +654,7 @@ preview.5.20268.9 preview.5.20272.6 preview.6 preview.6.20318.15 +preview.6.21355.2 preview.7 preview.7.20356.2 preview.7.20358.6 @@ -654,6 +663,7 @@ preview.7.20366.2 preview.7.20366.15 preview.4.20258.7 preview.4.20229.10 +preview.8 preview1-24530-04 preview7 productversion @@ -695,6 +705,8 @@ RandomNoun7 raspbian rc rc.1 +rc.1.21455.2 +rc.1.21458.32 rc.2 rc.3 rc2-24027 @@ -912,6 +924,7 @@ unregister-pssessionconfiguration unregistering untracked unvalidated +UpdateDotnetRuntime.ps1 update-formatdata update-modulemanifest update-scriptfileinfo @@ -953,6 +966,7 @@ v6.2.3 v6.2.4 v7.0.0 v7.0.3 +v7.0.4 v7.1.0 validatenotnullorempty versioned @@ -1009,6 +1023,109 @@ Youssef1313 zackjknight ComInterop runtime#33060 +vexx32 +perf +britishben +felixfbecker +vpondala +dependabot +jellyfrog +1redone +tommymaynard +vmsilvamolina +fbehrens +lockdown +lukexjeremy +deserializing +kiazhi +v6.1.2 +Menagarishvili +anmenaga +fxdependent +sba923 +replicaJunction +lupino3 +hvitved +unvalidated +Geweldig +mjanko5 +v7.0.0 +renehernandez +ece-jacob-scott +st0le +MohiTheFish +CodeFormatter +StyleCop +SytzeAndr +yashrajbharti +Leonhardt +tylerleonhardt +nuget.config +libmi +rpms +authenticode +env +MarianoAlipi +Microsoft.PowerShell.Native +davidBar-On +parameterized +misconfigured +hez2010 +ZhiZe-ZG +SecureStringHelper.FromPlainTextString +ProcessBaseCommand.AllProcesses +Parser.cs +MultipleServiceCommandBase.AllServices +JustinGrote +Newtonsoft.Json +minSize +WGs +wg-definitions +thejasonhelmick +winps +componentization +CimCmdlets +Microsoft.PowerShell.Host +PSDiagnostics +nightlies +wg +Visio +triaged +lifecycle +v2.0.5 +mutex +gukoff +dinhngtu +globbed +octos4murai +PSCommand +System.Management.Automation.ICommandRuntime +AppDomain.CreateDomain +AppDomain.Unload +ProcessModule.FileName +Environment.ProcessPath +PSUtils.GetMainModule +schuelermine +SupportsShouldProcess +Start-PSBootstrap +DotnetMetadataRuntime.json +deps.json +Jaykul +eltociear +consolehost.proto +IDisposable +ConvertToJsonCommand +CommandPathSearch +UseCoalesceExpression +UseSystemHashCode +UseCoalesceExpressionForNullable +substring +RemoveAll +MakeFieldReadonly +Microsoft.Management.UI.Internal +StringComparison +osx-arm64 +crossgen2 - CHANGELOG.md aavdberg asrosent @@ -1125,7 +1242,7 @@ wpa wpaProfile - demos/WindowsPowerShellModules/README.md 2.x. - - CHANGELOG/preview.md + - CHANGELOG/7.1.md ThomasNieto spongemike2 davidseibel @@ -1140,4 +1257,149 @@ CommandLineParameterParser jackerr3 preview.8.20407.11 pre-check +davidreis97 +soccypowa +nologo +InstallLocation +PkgES +Microsoft.PowerShell.Native +rtm.20526.5 +ini +package.json jcotton42 +RPMs +PSDesiredStateConfiguration + - CHANGELOG/preview.md +Gimly +jborean93 +mkswd +PatLeong +paul-cheung +georgettica +ProcessId +CurrentManagedThreadId +System.Environment +LongCount +nullable +Guid +accessor +CancellationToken +struct +IsEmpty +StringBuilder.Append +String.Concat +String.Substring +NoLanguage +kyanha +accessors +matthewjdegarmo +Reset-PWSHSystemPath +StyleCop.Analyzers +UseIsNullCheck +ConvertTypeOfToNameOf +usings +PriorityAttribute +System.Management.Automation.Interpreter.IBoxableInstruction +System.Management.Automation.Provider.IDynamicPropertyProvider +System.Management.Automation.Language.IScriptExtent +System.Management.Automation.Language.ICustomAstVisitor2 +System.Management.Automation.LanguagePrimitives.IConversionData +System.Automation.Remoting.Client.IWSManNativeApiFacade +System.Management.Automation.Language.ISupportsAssignment +System.Management.Automation.ICommandRuntime2 +System.Management.Automation.IOutputProcessingState +System.Management.Automation.IJobDebugger +System.Management.Automation.Interpreter.IInstructionProvider +System.Management.Automation.IHasSessionStateEntryVisibility +System.Management.Automation.Tracing.IEtwEventCorrelator +AclCommands +System.Management.Automation.Language.IAstPostVisitHandler +System.Management.Automation.IModuleAssemblyInitializer +nuget.org +GetFiles +TestModuleManifestCommand +System.Management.Automation.Provider.IContentWriter +TranscriptionOption.FlushContentToDisk +structs +System.Management.Automation.IArgumentCompleter +GetDirectories +System.Management.Automation.Host.IHostSupportsInteractiveSession +System.Management.Automation.Provider.IPropertyCmdletProvider +SimplifyConditionalExpression +MarkdownLint +AsSpan +AsMemory +xml +finalizer +finalizers +const +UseAutoProperty +SuppressFinalize +string.Empty +LoadBinaryModule +GetListOfFilesFromData +RPMs +NullableAttribute +PSDesiredStateConfiguration +brianary +Fs00 +MartinGC94 +jakekerr +strikethrough +string.Contains +imba-tjd +url +ArrayList +SDKs +XunitXml.TestLogger +Backport +v7.1.1 +about_PSDesiredStateConfiguration +hbuckle +preview.2.21155.3 +3.final +codesign +powershell.config.json +romero126 +boolean +rtm.20526.5 +dbaileyut +un-localized +awakecoding +bcwood +ThrowTerminatingError +DoesNotReturn +GetValueOrDefault +PSLanguageMode +adamsitnik +msixbundle +PowerShell-Native#70 +AppxManifest.xml +preview.9 +preview.10 +ArmaanMcleod +entrypoint +lselden +SethFalco +CodeQL +slowy07 +rc.2.21505.57 +ThirdPartyNotices.txt +cgmanifest.json +buildinfo +tar.gz +psoptions.json +manifest.spdx.json +vPack + - CHANGELOG/7.0.md +codesign +release-BuildJson +yml +centos-7 +PSDesiredStateConfiguration + - test/perf/benchmarks/README.md +benchmarked +BenchmarkDotNet + - docs/community/working-group-definitions.md +TobiasPSP +jdhitsolutions diff --git a/.vsts-ci/linux-daily.yml b/.vsts-ci/linux-daily.yml index 6ab1832dfd9..e6a5375b0c9 100644 --- a/.vsts-ci/linux-daily.yml +++ b/.vsts-ci/linux-daily.yml @@ -47,7 +47,7 @@ stages: jobs: - template: templates/ci-build.yml parameters: - pool: ubuntu-16.04 + pool: ubuntu-20.04 jobName: linux_build displayName: linux Build @@ -56,7 +56,7 @@ stages: jobs: - job: linux_test pool: - vmImage: ubuntu-16.04 + vmImage: ubuntu-20.04 displayName: Linux Test steps: @@ -149,7 +149,7 @@ stages: - job: CodeCovTestPackage displayName: CodeCoverage and Test Packages pool: - vmImage: ubuntu-16.04 + vmImage: ubuntu-20.04 steps: - pwsh: | Import-Module .\tools\ci.psm1 diff --git a/.vsts-ci/linux.yml b/.vsts-ci/linux.yml index 3b934fccb4a..e4ddeaf27f8 100644 --- a/.vsts-ci/linux.yml +++ b/.vsts-ci/linux.yml @@ -11,9 +11,10 @@ trigger: include: - '*' exclude: - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml + - .vsts-ci/misc-analysis.yml + - .github/ISSUE_TEMPLATE/* + - .dependabot/config.yml + - test/perf/* pr: branches: include: @@ -24,11 +25,17 @@ pr: include: - '*' exclude: + - .dependabot/config.yml + - .github/ISSUE_TEMPLATE/* + - .vsts-ci/misc-analysis.yml + - .vsts-ci/windows.yml + - .vsts-ci/windows/* + - cgmanifest.json + - LICENSE.txt + - test/common/markdown/* + - test/perf/* - tools/releaseBuild/* - tools/releaseBuild/azureDevOps/templates/* - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml variables: DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -47,7 +54,7 @@ stages: jobs: - template: templates/ci-build.yml parameters: - pool: ubuntu-16.04 + pool: ubuntu-20.04 jobName: linux_build displayName: linux Build @@ -57,34 +64,42 @@ stages: - template: templates/nix-test.yml parameters: name: Linux - pool: ubuntu-16.04 + pool: ubuntu-20.04 purpose: UnelevatedPesterTests tagSet: CI - template: templates/nix-test.yml parameters: name: Linux - pool: ubuntu-16.04 + pool: ubuntu-20.04 purpose: ElevatedPesterTests tagSet: CI - template: templates/nix-test.yml parameters: name: Linux - pool: ubuntu-16.04 + pool: ubuntu-20.04 purpose: UnelevatedPesterTests tagSet: Others - template: templates/nix-test.yml parameters: name: Linux - pool: ubuntu-16.04 + pool: ubuntu-20.04 purpose: ElevatedPesterTests tagSet: Others - template: templates/verify-xunit.yml parameters: - pool: ubuntu-16.04 + pool: ubuntu-20.04 + +- stage: PackageLinux + displayName: Package Linux + dependsOn: ["BuildLinux"] + jobs: + - template: linux/templates/packaging.yml + parameters: + pool: ubuntu-20.04 - stage: CodeCovTestPackage displayName: CodeCoverage and Test Packages @@ -93,7 +108,7 @@ stages: - job: CodeCovTestPackage displayName: CodeCoverage and Test Packages pool: - vmImage: ubuntu-16.04 + vmImage: ubuntu-20.04 steps: - pwsh: | Import-Module .\tools\ci.psm1 diff --git a/.vsts-ci/linux/templates/packaging.yml b/.vsts-ci/linux/templates/packaging.yml new file mode 100644 index 00000000000..74a234aff78 --- /dev/null +++ b/.vsts-ci/linux/templates/packaging.yml @@ -0,0 +1,92 @@ +parameters: + pool: 'ubuntu-20.04' + parentJobs: [] + name: 'Linux' + +jobs: +- job: ${{ parameters.name }}_packaging + dependsOn: + ${{ parameters.parentJobs }} + pool: + vmImage: ${{ parameters.pool }} + + displayName: ${{ parameters.name }} packaging + + steps: + - pwsh: | + Get-ChildItem -Path env: + displayName: Capture Environment + condition: succeededOrFailed() + + - task: DownloadBuildArtifacts@0 + displayName: 'Download build artifacts' + inputs: + downloadType: specific + itemPattern: | + build/**/* + downloadPath: '$(System.ArtifactsDirectory)' + + - pwsh: | + Get-ChildItem "$(System.ArtifactsDirectory)\*" -Recurse + displayName: 'Capture Artifacts Directory' + continueOnError: true + + - pwsh: | + Import-Module .\build.psm1 + Start-PSBootstrap -Package + displayName: Bootstrap + + - pwsh: | + Import-Module ./build.psm1 + displayName: 'Capture Artifacts Directory' + continueOnError: true + + - task: ExtractFiles@1 + displayName: 'Extract Build ZIP' + inputs: + archiveFilePatterns: '$(System.ArtifactsDirectory)/build/build.zip' + destinationFolder: '$(System.ArtifactsDirectory)/bins' + + - bash: | + find "$(System.ArtifactsDirectory)/bins" -type d -exec chmod +rwx {} \; + find "$(System.ArtifactsDirectory)/bins" -type f -exec chmod +rw {} \; + displayName: 'Fix permissions' + continueOnError: true + + - pwsh: | + Get-ChildItem "$(System.ArtifactsDirectory)\bins\*" -Recurse -ErrorAction SilentlyContinue + displayName: 'Capture Extracted Build ZIP' + continueOnError: true + + - pwsh: | + Import-Module .\tools\ci.psm1 + Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' + $options = (Get-PSOptions) + $rootPath = '$(System.ArtifactsDirectory)\bins' + $originalRootPath = Split-Path -path $options.Output + $path = Join-Path -path $rootPath -ChildPath (split-path -leaf -path $originalRootPath) + $pwshPath = Join-Path -path $path -ChildPath 'pwsh' + chmod a+x $pwshPath + $options.Output = $pwshPath + Set-PSOptions $options + Invoke-CIFinish + displayName: Packaging Tests + condition: succeeded() + + - pwsh: | + Get-ChildItem "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}\*.deb" -Recurse | ForEach-Object { + $packagePath = $_.FullName + Write-Host "Uploading $packagePath" + Write-Host "##vso[artifact.upload containerfolder=deb;artifactname=deb]$packagePath" + } + Get-ChildItem "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}\*.rpm" -Recurse | ForEach-Object { + $packagePath = $_.FullName + Write-Host "Uploading $packagePath" + Write-Host "##vso[artifact.upload containerfolder=rpm;artifactname=rpm]$packagePath" + } + Get-ChildItem "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}\*.tar.gz" -Recurse | ForEach-Object { + $packagePath = $_.FullName + Write-Host "Uploading $packagePath" + Write-Host "##vso[artifact.upload containerfolder=rpm;artifactname=rpm]$packagePath" + } + displayName: Upload packages diff --git a/.vsts-ci/mac.yml b/.vsts-ci/mac.yml index 445c0e3f463..84d3d1ef02a 100644 --- a/.vsts-ci/mac.yml +++ b/.vsts-ci/mac.yml @@ -11,10 +11,11 @@ trigger: include: - '*' exclude: - - /tools/releaseBuild/**/* - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml + - tools/releaseBuild/**/* + - .vsts-ci/misc-analysis.yml + - .github/ISSUE_TEMPLATE/* + - .dependabot/config.yml + - test/perf/* pr: branches: include: @@ -25,9 +26,16 @@ pr: include: - '*' exclude: - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml + - .dependabot/config.yml + - .github/ISSUE_TEMPLATE/* + - .vsts-ci/misc-analysis.yml + - .vsts-ci/windows.yml + - .vsts-ci/windows/* + - cgmanifest.json + - LICENSE.txt + - test/common/markdown/* + - test/perf/* + - tools/packaging/* - tools/releaseBuild/* - tools/releaseBuild/azureDevOps/templates/* diff --git a/.vsts-ci/misc-analysis.yml b/.vsts-ci/misc-analysis.yml index 327e5528107..5de5e28265a 100644 --- a/.vsts-ci/misc-analysis.yml +++ b/.vsts-ci/misc-analysis.yml @@ -16,18 +16,54 @@ pr: - feature* resources: -- repo: self - clean: true + repositories: + - repository: ComplianceRepo + type: github + endpoint: PowerShell + name: PowerShell/compliance + ref: master + +variables: + - name: repoFolder + value: PowerShell + jobs: -- template: templates/credscan.yml +- job: CI_Compliance + displayName: CI Compliance -- job: Linux_CI + pool: + vmImage: windows-latest + + variables: + - name: repoPath + value: $(Agent.BuildDirectory)\$(repoFolder) + + steps: + - checkout: self + clean: true + path: $(repoFolder) + + - checkout: ComplianceRepo + + - template: ci-compliance.yml@ComplianceRepo +- job: Linux_CI displayName: Markdown and Common Tests pool: - name: Hosted Ubuntu 1604 + vmImage: ubuntu-20.04 + + variables: + - name: repoPath + value: $(Agent.BuildDirectory)/$(repoFolder) + steps: + - checkout: self + clean: true + path: $(repoFolder) + + - checkout: ComplianceRepo + - powershell: | Get-ChildItem -Path env: displayName: Capture Environment @@ -48,28 +84,26 @@ jobs: displayName: Install mdspell condition: succeededOrFailed() - - powershell: Write-Host "##vso[build.updatebuildnumber]$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))" - displayName: Set Build Name for Non-PR - condition: ne(variables['Build.Reason'], 'PullRequest') - - bash: | - mdspell '**/*.md' '!**/Pester/**/*.md' --ignore-numbers --ignore-acronyms --report --en-us; + mdspell '**/*.md' '!**/Pester/**/*.md' '!**/dotnet-tools/**/*.md' --ignore-numbers --ignore-acronyms --report --en-us; displayName: Test Spelling in Markdown condition: succeededOrFailed() + workingDirectory: '$(repoPath)' - - powershell: | - Import-module ./build.psm1 - $path = Join-Path -Path $pwd -ChildPath './commonTestResults.xml' - $results = invoke-pester -Script ./test/common -OutputFile $path -OutputFormat NUnitXml -PassThru - Write-Host "##vso[results.publish type=NUnit;mergeResults=true;runTitle=Common Tests;publishRunAttachments=true;resultFiles=$path;]" - if($results.TotalCount -eq 0 -or $results.FailedCount -gt 0) - { - throw "Markdown tests failed" - } - displayName: Run Common Tests - condition: succeededOrFailed() - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - inputs: - sourceScanPath: '$(Build.SourcesDirectory)' - snapshotForceEnabled: true + - ${{ if not(contains(variables['SYSTEM.COLLECTIONURI'],'mscodehub')) }}: + - pwsh: | + Import-module ./build.psm1 + $path = Join-Path -Path $pwd -ChildPath './commonTestResults.xml' + $results = invoke-pester -Script ./test/common -OutputFile $path -OutputFormat NUnitXml -PassThru + Write-Host "##vso[results.publish type=NUnit;mergeResults=true;runTitle=Common Tests;publishRunAttachments=true;resultFiles=$path;]" + if($results.TotalCount -eq 0 -or $results.FailedCount -gt 0) + { + throw "Markdown tests failed" + } + displayName: Run Common Tests + condition: succeededOrFailed() + workingDirectory: '$(repoPath)' + + - template: dailyBuildCompliance.yml@ComplianceRepo + parameters: + sourceScanPath: '$(repoPath)' diff --git a/.vsts-ci/templates/ci-build.yml b/.vsts-ci/templates/ci-build.yml index 026448908f6..cbbd5349417 100644 --- a/.vsts-ci/templates/ci-build.yml +++ b/.vsts-ci/templates/ci-build.yml @@ -11,31 +11,31 @@ jobs: displayName: ${{ parameters.displayName }} steps: - - powershell: | + - pwsh: | Get-ChildItem -Path env: displayName: Capture Environment condition: succeededOrFailed() - - powershell: Write-Host "##vso[build.updatebuildnumber]$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))" + - pwsh: Write-Host "##vso[build.updatebuildnumber]$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))" displayName: Set Build Name for Non-PR condition: ne(variables['Build.Reason'], 'PullRequest') - - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml + - ${{ if ne(variables['AzDevOpsFeed'], '') }}: + - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml - - powershell: | - [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + - pwsh: | Import-Module .\tools\ci.psm1 Invoke-CIInstall -SkipUser displayName: Bootstrap - condition: succeededOrFailed() + condition: succeeded() - - powershell: | + - pwsh: | Import-Module .\tools\ci.psm1 Invoke-CIBuild displayName: Build condition: succeeded() - - powershell: | + - pwsh: | Import-Module .\tools\ci.psm1 Restore-PSOptions Invoke-CIxUnit -SkipFailing diff --git a/.vsts-ci/templates/nix-test.yml b/.vsts-ci/templates/nix-test.yml index 0938a93bcf9..f2f04d9dd5c 100644 --- a/.vsts-ci/templates/nix-test.yml +++ b/.vsts-ci/templates/nix-test.yml @@ -37,7 +37,6 @@ jobs: Import-Module .\tools\ci.psm1 Invoke-CIInstall -SkipUser displayName: Bootstrap - condition: succeededOrFailed() - task: ExtractFiles@1 displayName: 'Extract Build ZIP' diff --git a/.vsts-ci/templates/windows-packaging.yml b/.vsts-ci/templates/windows-packaging.yml deleted file mode 100644 index 455efbb9fec..00000000000 --- a/.vsts-ci/templates/windows-packaging.yml +++ /dev/null @@ -1,34 +0,0 @@ -parameters: - pool: 'Hosted VS2017' - jobName: 'win_packaging' - parentJobs: [] - -jobs: -- job: ${{ parameters.jobName }} - dependsOn: - ${{ parameters.parentJobs }} - pool: - name: ${{ parameters.pool }} - - displayName: Windows Packaging - - steps: - - powershell: | - Get-ChildItem -Path env: - displayName: Capture environment - condition: succeededOrFailed() - - - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml - - - powershell: | - [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 - Import-Module .\tools\ci.psm1 - Invoke-CIInstall - displayName: Bootstrap - condition: succeededOrFailed() - - - pwsh: | - Import-Module .\tools\ci.psm1 - New-CodeCoverageAndTestPackage - Invoke-CIFinish -NuGetKey $(NUGET_KEY) - displayName: Build and Test Package diff --git a/.vsts-ci/templates/windows-test.yml b/.vsts-ci/templates/windows-test.yml index a153b563e3f..b316f8f360e 100644 --- a/.vsts-ci/templates/windows-test.yml +++ b/.vsts-ci/templates/windows-test.yml @@ -34,12 +34,25 @@ jobs: # must be run frow Windows PowerShell - powershell: | + # Remove "Program Files\dotnet" from the env variable PATH, so old SDKs won't affect us. + Write-Host "Old Path:" + Write-Host $env:Path + + $dotnetPath = Join-Path $env:SystemDrive 'Program Files\dotnet' + $paths = $env:Path -split ";" | Where-Object { -not $_.StartsWith($dotnetPath) } + $env:Path = $paths -join ";" + + Write-Host "New Path:" + Write-Host $env:Path + + # Bootstrap Import-Module .\tools\ci.psm1 Invoke-CIInstall displayName: Bootstrap - condition: succeededOrFailed() - pwsh: | + Import-Module .\build.psm1 -force + Start-PSBootstrap Import-Module .\tools\ci.psm1 Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' $options = (Get-PSOptions) diff --git a/.vsts-ci/windows-daily.yml b/.vsts-ci/windows-daily.yml index a13714782d0..9171112b362 100644 --- a/.vsts-ci/windows-daily.yml +++ b/.vsts-ci/windows-daily.yml @@ -99,6 +99,17 @@ stages: # must be run frow Windows PowerShell - powershell: | + # Remove "Program Files\dotnet" from the env variable PATH, so old SDKs won't affect us. + Write-Host "Old Path:" + Write-Host $env:Path + + $dotnetPath = Join-Path $env:SystemDrive 'Program Files\dotnet' + $paths = $env:Path -split ";" | Where-Object { -not $_.StartsWith($dotnetPath) } + $env:Path = $paths -join ";" + + Write-Host "New Path:" + Write-Host $env:Path + Import-Module .\tools\ci.psm1 Invoke-CIInstall displayName: Bootstrap @@ -121,6 +132,8 @@ stages: condition: succeeded() - pwsh: | + Import-Module .\build.psm1 + Start-PSBootstrap Import-Module .\tools\ci.psm1 Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' Invoke-CITest -Purpose UnelevatedPesterTests -TagSet CI @@ -128,6 +141,8 @@ stages: condition: succeeded() - pwsh: | + Import-Module .\build.psm1 + Start-PSBootstrap Import-Module .\tools\ci.psm1 Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' Invoke-CITest -Purpose ElevatedPesterTests -TagSet CI @@ -135,6 +150,8 @@ stages: condition: succeededOrFailed() - pwsh: | + Import-Module .\build.psm1 + Start-PSBootstrap Import-Module .\tools\ci.psm1 Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' Invoke-CITest -Purpose UnelevatedPesterTests -TagSet Others @@ -142,6 +159,8 @@ stages: condition: succeededOrFailed() - pwsh: | + Import-Module .\build.psm1 + Start-PSBootstrap Import-Module .\tools\ci.psm1 Restore-PSOptions -PSOptionsPath '$(System.ArtifactsDirectory)\build\psoptions.json' Invoke-CITest -Purpose ElevatedPesterTests -TagSet Others @@ -165,9 +184,3 @@ stages: } displayName: 'Upload CLR Trace' condition: always() - -- stage: PackagingWin - displayName: Packaging for Windows - jobs: - # Unlike daily builds, we do not upload nuget package to MyGet so we do not wait on tests to finish. - - template: templates/windows-packaging.yml diff --git a/.vsts-ci/windows.yml b/.vsts-ci/windows.yml index 11bccbbbfa6..70775761fba 100644 --- a/.vsts-ci/windows.yml +++ b/.vsts-ci/windows.yml @@ -11,9 +11,10 @@ trigger: include: - '*' exclude: - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml + - .vsts-ci/misc-analysis.yml + - .github/ISSUE_TEMPLATE/* + - .dependabot/config.yml + - test/perf/* pr: branches: include: @@ -24,9 +25,14 @@ pr: include: - '*' exclude: - - /.vsts-ci/misc-analysis.yml - - /.github/ISSUE_TEMPLATE/* - - /.dependabot/config.yml + - .dependabot/config.yml + - .github/ISSUE_TEMPLATE/* + - .vsts-ci/misc-analysis.yml + - cgmanifest.json + - LICENSE.txt + - test/common/markdown/* + - test/perf/* + - tools/packaging/* - tools/releaseBuild/* - tools/releaseBuild/azureDevOps/templates/* @@ -72,11 +78,3 @@ stages: tagSet: Others - template: templates/verify-xunit.yml - -- stage: PackagingWin - displayName: Packaging for Windows - dependsOn: [] # by specifying an empty array, this stage doesn't depend on the stage before it - jobs: - # Unlike daily builds, we do not upload nuget package to MyGet so we do not wait on tests to finish. - - template: templates/windows-packaging.yml - diff --git a/.vsts-ci/windows/templates/windows-packaging.yml b/.vsts-ci/windows/templates/windows-packaging.yml new file mode 100644 index 00000000000..353d722bb92 --- /dev/null +++ b/.vsts-ci/windows/templates/windows-packaging.yml @@ -0,0 +1,78 @@ +parameters: + - name: pool + default: 'Hosted VS2017' + - name: jobName + default: 'win_packaging' + - name: runtimePrefix + default: 'win7' + - name: architecture + default: 'x64' + - name: channel + default: 'preview' + +jobs: +- job: ${{ parameters.jobName }}_${{ parameters.channel }}_${{ parameters.architecture }} + + variables: + - name: repoFolder + value: PowerShell + - name: repoPath + value: $(Agent.BuildDirectory)\$(repoFolder) + - name: complianceRepoFolder + value: compliance + - name: complianceRepoPath + value: $(Agent.BuildDirectory)\$(complianceRepoFolder) + + pool: + name: ${{ parameters.pool }} + + displayName: Windows Packaging - ${{ parameters.architecture }} - ${{ parameters.channel }} + + steps: + - checkout: self + clean: true + path: $(repoFolder) + + - checkout: ComplianceRepo + clean: true + path: $(complianceRepoFolder) + + - powershell: | + Get-ChildItem -Path env: + displayName: Capture environment + condition: succeededOrFailed() + + - pwsh: | + $PSVersionTable + displayName: Capture PowerShell Version Table + condition: succeededOrFailed() + + + - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml + + - pwsh: | + Import-Module .\tools\ci.psm1 + Invoke-CIInstall -SkipUser + displayName: Bootstrap + condition: succeeded() + workingDirectory: $(repoPath) + + - pwsh: | + Import-Module .\tools\ci.psm1 + New-CodeCoverageAndTestPackage + Invoke-CIFinish -Runtime ${{ parameters.runtimePrefix }}-${{ parameters.architecture }} -channel ${{ parameters.channel }} -Stage Build + displayName: Build + workingDirectory: $(repoPath) + + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/mainBuild' + Build_Repository_Uri: $(build.repository.uri) + displayName: SBOM + + - pwsh: | + Import-Module .\tools\ci.psm1 + New-CodeCoverageAndTestPackage + Invoke-CIFinish -Runtime ${{ parameters.runtimePrefix }}-${{ parameters.architecture }} -channel ${{ parameters.channel }} -Stage Package + displayName: Package and Test + workingDirectory: $(repoPath) diff --git a/.vsts-ci/windows/windows-packaging.yml b/.vsts-ci/windows/windows-packaging.yml new file mode 100644 index 00000000000..b8aa2c22950 --- /dev/null +++ b/.vsts-ci/windows/windows-packaging.yml @@ -0,0 +1,105 @@ +name: PR-$(System.PullRequest.PullRequestNumber)-$(Date:yyyyMMdd)$(Rev:.rr) +trigger: + # Batch merge builds together while a merge build is running + batch: true + branches: + include: + - master + - release* + - feature* + paths: + exclude: + - tests/* + - docs/* + - demos/* + - CHANGELOG/* + - .devcontainer/* + - .github/* + - .poshchan/* + - .vscode/* + - code-server/* + - docker/* + +pr: + branches: + include: + - master + - release* + - feature* + paths: + # file extension filters are not supported when this was written. + # This really should be /src/**/*.csproj + include: + - .vsts-ci/windows/* + - assets/wix/* + - build.psm1 + - global.json + - nuget.config + - PowerShell.Common.props + - src/Microsoft.Management.Infrastructure.CimCmdlets/Microsoft.Management.Infrastructure.CimCmdlets.csproj + - src/Microsoft.Management.UI.Internal/Microsoft.PowerShell.GraphicalHost.csproj + - src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj + - src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj + - src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj + - src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj + - src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj + - src/Microsoft.PowerShell.GlobalTool.Shim/Microsoft.PowerShell.GlobalTool.Shim.csproj + - src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj + - src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj + - src/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.csproj + - src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj + - src/Microsoft.WSMan.Runtime/Microsoft.WSMan.Runtime.csproj + - src/Modules/PSGalleryModules.csproj + - src/powershell-win-core/powershell-win-core.csproj + - tools/ci.psm1 + - tools/packaging/* + +variables: + - name: GIT_CONFIG_PARAMETERS + value: "'core.autocrlf=false'" + - name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 + - name: POWERSHELL_TELEMETRY_OPTOUT + value: 1 + # Avoid expensive initialization of dotnet cli, see: https://donovanbrown.com/post/Stop-wasting-time-during-NET-Core-builds + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - name: __SuppressAnsiEscapeSequences + value: 1 + - group: fakeNugetKey + - name: SBOMGenerator_Formats + value: spdx:2.2 + +resources: + repositories: + - repository: ComplianceRepo + type: github + endpoint: PowerShell + name: PowerShell/compliance + ref: master + +stages: +- stage: PackagingWin + displayName: Packaging for Windows + dependsOn: [] # by specifying an empty array, this stage doesn't depend on the stage before it + jobs: + # Unlike daily builds, we do not upload nuget package to MyGet so we do not wait on tests to finish. + - template: templates/windows-packaging.yml + - template: templates/windows-packaging.yml + parameters: + channel: stable + architecture: x86 + - template: templates/windows-packaging.yml + parameters: + channel: preview + architecture: x86 + - template: templates/windows-packaging.yml + parameters: + channel: preview + architecture: arm + runtimePrefix: win + - template: templates/windows-packaging.yml + parameters: + channel: preview + architecture: arm64 + runtimePrefix: win diff --git a/ADOPTERS.md b/ADOPTERS.md index 301386034a7..110f56d16e6 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -18,7 +18,7 @@ This is a list of adopters of using PowerShell in production or in their product * [Azure Functions - PowerShell](https://github.com/Azure/azure-functions-powershell-worker) is a serverless compute service to execute PowerShell scripts in the cloud without worrying about managing resources. In addition, Azure Functions provides client tools such as [`Az.Functions`](https://www.powershellgallery.com/packages/Az.Functions), a cross-platform PowerShell module to manage function apps and service plans in the cloud. For more information about Functions, please visit [functions overview](https://docs.microsoft.com/azure/azure-functions/functions-overview). -* [PowerShell Universal Dashboard](https://ironmansoftware.com/powershell-universal-dashboard) is a cross-platform web framework for PowerShell. +* [PowerShell Universal](https://ironmansoftware.com/powershell-universal) is a cross-platform web framework for PowerShell. It provides the ability to create robust, interactive websites, REST APIs, and Electron-based desktop apps with PowerShell script. More information about PowerShell Universal Dashboard is available at the [PowerShell Universal Dashboard Docs](https://docs.universaldashboard.io). * [System Frontier](https://systemfrontier.com/solutions/powershell/) provides dynamically generated web GUIs and REST APIs for PowerShell and other scripting languages. diff --git a/Analyzers.props b/Analyzers.props new file mode 100644 index 00000000000..dacf53c4625 --- /dev/null +++ b/Analyzers.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/CHANGELOG/6.0.md b/CHANGELOG/6.0.md index b5993b5be30..948197f0619 100644 --- a/CHANGELOG/6.0.md +++ b/CHANGELOG/6.0.md @@ -104,7 +104,7 @@ work is required for Microsoft to continue to sign and release packages from the project as official Microsoft packages. - Remove `PerformWSManPluginReportCompletion`, which was not used, from `pwrshplugin.dll` (#5498) (Thanks @bergmeister!) -- Remove exclusion for hang and add context exception for remaining instances (#5595) +- Remove exclusion for unresponsive condition and add context exception for remaining instances (#5595) - Replace `strlen` with `strnlen` in native code (#5510) ## [6.0.0-rc] - 2017-11-16 @@ -781,7 +781,7 @@ Many modules and cmdlets that didn't work in the past may now work on .NET Core, If you want to opt-out of this telemetry, simply delete `$PSHome\DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY`. Even before the first run of Powershell, deleting this file will bypass all telemetry. -In the future, we plan on also enabling a configuration value for whatever is approved as part of [RFC0015](https://github.com/PowerShell/PowerShell-RFC/blob/master/X-Rejected/RFC0015-PowerShell-StartupConfig.md). +In the future, we plan on also enabling a configuration value for whatever is approved as part of [RFC0015](https://github.com/PowerShell/PowerShell-RFC/blob/master/Archive/Rejected/RFC0015-PowerShell-StartupConfig.md). We also plan on exposing this telemetry data (as well as whatever insights we leverage from the telemetry) in [our community dashboard](https://devblogs.microsoft.com/powershell/powershell-open-source-community-dashboard/). If you have any questions or comments about our telemetry, please file an issue. diff --git a/CHANGELOG/6.1.md b/CHANGELOG/6.1.md index f8e12f47001..59cf2842d78 100644 --- a/CHANGELOG/6.1.md +++ b/CHANGELOG/6.1.md @@ -428,7 +428,7 @@ - Fix crash when terminal is reset (#6777) - Fix a module-loading regression that caused an infinite loop (#6843) - Further improve `PSMethod` to `Delegate` conversion (#6851) -- Blacklist `System.Windows.Forms` from loading to prevent a crash (#6822) +- Block list `System.Windows.Forms` from loading to prevent a crash (#6822) - Fix `Format-Table` where rows were being trimmed unnecessarily if there's only one row of headers (#6772) - Fix `SetDate` function in `libpsl-native` to avoid corrupting memory during `P/Invoke` (#6881) - Fix tab completions for hash table (#6839) (Thanks @iSazonov!) diff --git a/CHANGELOG/6.2.md b/CHANGELOG/6.2.md index 06ad8f41482..bf54f978eba 100644 --- a/CHANGELOG/6.2.md +++ b/CHANGELOG/6.2.md @@ -844,7 +844,7 @@ ### Documentation and Help Content -- Replace ambiguous `hang` term (#7902, #7931) (Thanks @iSazonov!) +- Replace ambiguous term (#7902, #7931) (Thanks @iSazonov!) - Updating incorrect example of `PowerShell.Create()` (#7926) (Thanks @1RedOne!) - Update `governance.md` (#7927) (Thanks @tommymaynard!) - Add `cURL` to the Bash users list in `README.md` (#7948) (Thanks @vmsilvamolina!) diff --git a/CHANGELOG/7.0.md b/CHANGELOG/7.0.md index e80c0b179fc..9b7c0a9f45b 100644 --- a/CHANGELOG/7.0.md +++ b/CHANGELOG/7.0.md @@ -1,5 +1,136 @@ # 7.0 Changelog +## [7.0.7] - 2021-08-12 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to 3.1.412 + + +
    +
  • Remove cat file from PSDesiredStateConfiguration module (Internal 16722)
  • +
  • Update .NET SDK to 3.1.412 (Internal 16717)
  • +
+ +
+ +[7.0.7]: https://github.com/PowerShell/PowerShell/compare/v7.0.6...v7.0.7 + +## [7.0.6] - 2021-03-11 + +### General Cmdlet Updates and Fixes + +- Fix web cmdlets to properly construct URI from body when using `-NoProxy` (#14673) +- Fix `PromptForCredential()` to add `targetName` as domain (#14504) +- Clean up the IPC named pipe on PowerShell exit (#12187) + +### Tests + +- Update markdown test packages with security fixes (#13730, #14145, #14454) + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 3.1.407 + + +
    +
  • Bump .NET to version 3.1.407 (Internal 14783)
  • +
  • Fix the miscellaneous analysis CI build (#14971, #14974, #14975)
  • +
  • Declare which variable group is used for checking the blob in the release build (#14970)
  • +
  • Use template that disables component governance for CI (#14938)
  • +
  • Suppress the warning for having multiple nuget feeds (#14893)
  • +
  • Disable codesign validation where the file type is not supported (#14885)
  • +
  • Make universal Deb package based on deb package spec (#14681)
  • +
  • Add manual release automation steps and improve changelog script (#14445)
  • +
  • Fix a typo in the Get-ChangeLog function (#14129)
  • +
  • Add validation and dependencies for Ubuntu 20.04 distribution to packaging script (#13993)
  • +
  • Add comment in release-BuildJson.yml for date formatting
  • +
  • Install wget on centos-7 docker image
  • +
  • Fix install-dotnet download (#14856)
  • +
  • Fix release build to upload global tool packages to artifacts (#14620)
  • +
  • Fixes to release pipeline for GA release (#14034)
  • +
  • Add checkout step to release build templates (#13840)
  • +
  • Add flag to make Linux script publish to production repo (#13714)
  • +
  • Use new release script for Linux packages (#13705)
  • +
  • Change stage dependency for docker release stage in release pipeline (#13512)
  • +
  • Create the folder before copying the global tools (#13476)
  • +
  • A few fixes to the release pipeline (#13473)
  • +
  • Change the variable group name (Internal 12339)
  • +
  • Create release pipeline as a yaml pipeline (#13394)
  • +
+ +
+ +[7.0.6]: https://github.com/PowerShell/PowerShell/compare/v7.0.5...v7.0.6 + +## [7.0.5] - 2021-02-11 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 3.1.406 + + +
    +
  • Fix third party signing for files in sub-folders (#14751)
  • +
  • Bump .NET SDK to 3.1.12 (Internal 14462)
  • +
+ +
+ +[7.0.5]: https://github.com/PowerShell/PowerShell/compare/v7.0.4...v7.0.5 + +## [7.0.4] - 2021-01-19 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 3.1.405 + + +
    +
  • Remove MyGet feeds from test nuget.config (Internal 14147)
  • +
  • Update WXS file for 7.0.4 (Internal 14122)
  • +
  • Update .NET dependencies for 7.0.4 (Internal 14104)
  • +
  • Fix 7.0.4 `Get-Module` test failure (Internal 13946)
  • +
  • Fix directory creation failure (Internal 13904)
  • +
  • Disable WMF link invocation test (#13479)
  • +
  • Use PowerShell Core for build and test of package in CI build (#13223)
  • +
  • Disable libmi dependent tests for macOS. (#14446)
  • +
  • Use one feed in each nuget.config in official builds (#14363)
  • +
  • Fix path signed RPMs are uploaded from in release build (#14424)
  • +
  • Fix syntax error in Windows packaging script (#14377)
  • +
  • Make AppLocker Enforce mode take precedence over UMCI Audit mode (#14353)
  • +
  • Fix issue with unsigned build (#14367)
  • +
  • Move macOS and NuGet to ESRP signing (#14324)
  • +
  • Move Windows package signing to use ESRP (#14060)
  • +
  • Move Linux to ESRP signing (#14210)
  • +
  • Migrate 3rd party signing to ESRP (#14010)
  • +
  • Don't do a shallow checkout (#13992)
  • +
  • Move to ESRP signing for Windows files (#13988)
  • +
  • Fix breaks in packages daily build due to macOS signing changes (#13421)
  • +
  • Sign individual files in package (#13392)
  • +
  • Use Authenticode certificate for MSIX signing (#13330)
  • +
  • Sign the MSIX files for the store (#12582)
  • +
  • Use temporary personal path at runspace startup when $env:HOME not defined (#13239)
  • +
  • Fix MSIX packaging to determine if a preview release by inspecting the semantic version string (#11991)
  • +
  • Add default help content to the assets folder (#13257)
  • +
+ +
+ +[7.0.4]: https://github.com/PowerShell/PowerShell/compare/v7.0.3...v7.0.4 + ## [7.0.3] - 2020-07-16 ### Tests @@ -196,7 +327,7 @@ Move to .NET Core 3.1.202 SDK and update packages. - Skip null data in output data received handler to fix a `NullReferenceException` (#11448) (Thanks @iSazonov!) - Add `ssh` parameter sets for the parameter `-JobName` in `Invoke-Command` (#11444) - Adding `PowerShell Editor Services` and `PSScriptAnalyzer` to tracked modules (#11514) -- Fix key exchange hang with `SecureString` for the `OutOfProc` transports (#11380, #11406) +- Fix condition when key exchange stops responding with `SecureString` for the `OutOfProc` transports (#11380, #11406) - Add setting to disable the implicit `WinPS` module loading (#11332) ### General Cmdlet Updates and Fixes diff --git a/CHANGELOG/7.1.md b/CHANGELOG/7.1.md new file mode 100644 index 00000000000..91d00b70a49 --- /dev/null +++ b/CHANGELOG/7.1.md @@ -0,0 +1,1042 @@ +# 7.1 Changelog + +## [7.1.4] - 2021-08-12 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 5.0.400 + + +
    +
  • Remove the cat file from PSDesiredStateConfiguration module (Internal 16723)
  • +
  • Update .NET SDK version and other packages (Internal 16715)
  • +
+ +
+ +[7.1.4]: https://github.com/PowerShell/PowerShell/compare/v7.1.3...v7.1.4 + +## [7.1.3] - 2021-03-11 + +### Engine Updates and Fixes + +- Remove the 32K character limit on the environment block for `Start-Process` (#14111) +- Fix webcmdlets to properly construct URI from body when using `-NoProxy` (#14673) + +### General Cmdlet Updates and Fixes + +- Fix `PromptForCredential()` to add `targetName` as domain (#14504) + +### Build and Packaging Improvements + +
+ + + +Bump .NET SDK to 5.0.4 + + + +
    +
  • Bump .NET SDK to 5.0.4 (Internal 14775)
  • +
  • Disable running markdown link verification in release build CI (#14971, #14974, #14975)
  • +
  • Use template that disables component governance for CI (#14938)
  • +
  • Declare which variable group is used for checking the blob in the release build (#14970)
  • +
  • Add suppress for nuget multi-feed warning (#14893)
  • +
  • Disable code signing validation where the file type is not supported (#14885)
  • +
  • Install wget on CentOS 7 docker image (#14857)
  • +
  • Fix install-dotnet download (#14856)
  • +
  • Make universal Deb package based on deb package spec (#14681)
  • +
  • Fix release build to upload global tool packages to artifacts (#14620)
  • +
  • Update ini component version in test package.json (#14454)
  • +
  • Add manual release automation steps and improve changelog script (#14445)
  • +
  • Update markdown test packages with security fixes (#14145)
  • +
  • Fix a typo in the Get-ChangeLog function (#14129)
  • +
  • Disable global tool copy to unblock release
  • +
+ +
+ +[7.1.3]: https://github.com/PowerShell/PowerShell/compare/v7.1.2...v7.1.3 + +## [7.1.2] - 2021-02-11 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 5.0.103 + + +
    +
  • Fix third party signing for files in sub-folders (#14751)
  • +
  • Bump .NET SDK to version 5.0.103 (Internal 14459)
  • +
  • Publish the global tool package for stable release
  • +
+ +
+ +[7.1.2]: https://github.com/PowerShell/PowerShell/compare/v7.1.1...v7.1.2 + +## [7.1.1] - 2021-01-14 + +### General Cmdlet Updates and Fixes + +- Avoid an exception if file system does not support reparse points (#13634) (Thanks @iSazonov!) +- Make AppLocker Enforce mode take precedence over UMCI Audit mode (#14353) + +### Code Cleanup + +- Fix syntax error in Windows packaging script (#14377) + +### Build and Packaging Improvements + +
+ +
    +
  • Use one feed in each nuget.config in official builds (#14363)
  • +
  • Fix path signed RPMs are uploaded from in release build (#14424)
  • +
  • Fix issue with unsigned build (#14367)
  • +
  • Move macOS and NuGet packages to ESRP signing (#14324)
  • +
  • Move Windows packages signing to use ESRP (#14060)
  • +
  • Move Linux packages to ESRP signing (#14210)
  • +
  • Migrate 3rd party signing to ESRP (#14010)
  • +
  • Don't do a shallow checkout (#13992)
  • +
  • Move to ESRP signing for Windows files (#13988)
  • +
  • Add checkout step to release build templates (#13840)
  • +
+ +
+ +[7.1.1]: https://github.com/PowerShell/PowerShell/compare/v7.1.0...v7.1.1 + +## [7.1.0] - 2020-11-11 + +### Engine Updates and Fixes + +- Fix a logic bug in `MapSecurityZone` (#13921) (Thanks @iSazonov!) + +### General Cmdlet Updates and Fixes + +- Update `pwsh -?` output to match docs (#13748) + +### Tests + +- `markdownlint` security updates (#13730) + +### Build and Packaging Improvements + +
+ +
    +
  • Fixes to release pipeline for GA release (Internal 13410)
  • +
  • Add validation and dependencies for Ubuntu 20.04 distribution to packaging script (#13993)
  • +
  • Change PkgES Lab to unblock build (Internal 13376)
  • +
  • Add .NET install workaround for RTM (#13991)
  • +
  • Bump Microsoft.PowerShell.Native version from 7.1.0-rc.2 to 7.1.0 (#13976)
  • +
  • Bump PSReadLine version to 2.1.0 (#13975)
  • +
  • Bump .NET to version 5.0.100-rtm.20526.5 (#13920)
  • +
  • Update script to use .NET RTM feeds (#13927)
  • +
+ +
+ +[7.1.0]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-rc.2...v7.1.0 + +## [7.1.0-rc.2] - 2020-10-20 + +### Engine Updates and Fixes + +- Rename `Get-Subsystem` to `Get-PSSubsystem` and fix two related minor issues (#13765) +- Add missing `PSToken` token table entries to fix the `PSParser` API (#13779) +- Add additional PowerShell modules to the tracked modules list (#12183) +- Fix blocking wait when starting file associated with a Windows application (#13750) +- Revert `PSNativePSPathResolution` to being an experimental feature (#13734) + +### General Cmdlet Updates and Fixes + +- Emit warning if `ConvertTo-Json` exceeds `-Depth` value (#13692) + +### Build and Packaging Improvements + +- Change Linux package script call to publish to the production repository in release builds (#13714) +- Update `PSReadLine` version to `2.1.0-rc1` (#13777) +- Move PowerShell build to dotnet `5.0-RC.2` (#13780) +- Bump `Microsoft.PowerShell.Native` to `7.1.0-rc.2` (#13794) + +[7.1.0-rc.2]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-rc.1...v7.1.0-rc.2 + +## [7.1.0-rc.1] - 2020-09-29 + +### Engine Updates and Fixes + +- Make fixes to `ComInterop` code as suggested by .NET team (#13533) + +### General Cmdlet Updates and Fixes + +- Fix case where exception message contains just ``"`n"`` on Windows (#13684) +- Recognize `CONOUT$` and `CONIN$` as reserved device names (#13508) (Thanks @davidreis97!) +- Fix `ConciseView` for interactive advanced function when writing error (#13623) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @soccypowa

+ +
+ +
    +
  • Simplify logical negation (#13555) (Thanks @xtqqczze!)
  • +
  • Fixed the indentation of the help content for -nologo (#13557) (Thanks @soccypowa!)
  • +
+ +
+ +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@heaths

+ +
+ +
    +
  • Bump NJsonSchema from 10.1.24 to 10.1.26 (#13586)
  • +
  • Bump PowerShellGet from 2.2.4 to 2.2.5 (#13683)
  • +
  • Bump Microsoft.ApplicationInsights from 2.14.0 to 2.15.0 (#13639)
  • +
  • Update PowerShell to build against dotnet 5.0-RC.1 (#13643)
  • +
  • Write the InstallLocation to fixed registry key (#13576) (Thanks @heaths!)
  • +
+ +
+ +### Documentation and Help Content + +- Update `README` and `metadata.json` for `7.1.0-preview.7` release (#13565) + +[7.1.0-rc.1]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.7...v7.1.0-rc.1 + +## [7.1.0-preview.7] - 2020-09-08 + +### Breaking Changes + +- Fix `$?` to not be `$false` when native command writes to `stderr` (#13395) + +### Engine Updates and Fixes + +- Initial work of the subsystem plugin model (for minimal powershell) (#13186) +- Optimize `GetSystemLockdownPolicy` for non-lockdown scenarios (#13438) + +### General Cmdlet Updates and Fixes + +- Revert "Add the parameter `-Paged` to `Get-Help` to support paging (#13374)" (#13519) +- Add support for `TLS` 1.3 in Web cmdlets (#13409) (Thanks @iSazonov!) +- Add null check for `args` in `CommandLineParser` (#13451) (Thanks @iSazonov!) +- Process reparse points for Microsoft Store applications (#13481) (Thanks @iSazonov!) +- Move `PSNullConditionalOperators` feature out of experimental (#13529) +- Move `PSNativePSPathResolution` feature out of Experimental (#13522) +- Use field if property does not exist for `ObRoot` when using PowerShell Direct to container (#13375) (Thanks @hemisphera!) +- Suppress `UTF-7` obsolete warnings (#13484) +- Avoid multiple enumerations of an `IEnumerable` instance in `Compiler.cs` (#13491) +- Change `Add-Type -OutputType` to not support `ConsoleApplication` and `WindowsApplication` (#13440) +- Create warnings when `UTF-7` is specified as an encoding (#13430) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @tamasvajk

+ +
+ +
    +
  • Add single blank line after copyright header (#13486) (Thanks @xtqqczze!)
  • +
  • Use read-only auto-implemented properties (#13507) (Thanks @xtqqczze!)
  • +
  • Use boolean instead of bitwise operators on bool values (#13506) (Thanks @xtqqczze!)
  • +
  • Fix erroneous assert (#13495) (Thanks @tamasvajk!)
  • +
  • Cleanup: remove duplicate words in comments (#13539) (Thanks @xtqqczze!)
  • +
  • Reformat StringUtil (#13509) (Thanks @xtqqczze!)
  • +
  • Use uint instead of long for PDH constants (#13502) (Thanks @xtqqczze!)
  • +
  • Cleanup: Remove redundant empty lines (#13404) (Thanks @xtqqczze!)
  • +
  • Add StringUtil.Format overload to avoid unnecessary allocations (#13408) (Thanks @xtqqczze!)
  • +
  • Fix test hooks for CommandLineParameterParser (#13459)
  • +
  • Remove redundant delegate creation (#13441) (Thanks @xtqqczze!)
  • +
+ +
+ +### Tools + +- vscode: Add `editorconfig` to recommended extensions (#13537) (Thanks @xtqqczze!) +- Remove the out-dated `ZapDisable` related code from `build.psm1` (#13350) (Thanks @jackerr3!) + +### Tests + +- Disable `WMF` download link validation test (#13479) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@yecril71pl

+ +
+ +
    +
  • Add Microsoft.NET.Test.Sdk dependency (Internal 12589)
  • +
  • Update .NET NuGet package version to 5.0.0-preview.8.20407.11 (Internal 12555)
  • +
  • Update to .NET 5 preview 8 (#13530)
  • +
  • Change stage dependency for docker release stage in release pipeline (#13512)
  • +
  • Bump Microsoft.NET.Test.Sdk from 16.7.0 to 16.7.1 (#13492)
  • +
  • Create the folder before copying the global tools (#13476)
  • +
  • A few fixes to the release pipeline (#13473)
  • +
  • Bump Markdig.Signed from 0.20.0 to 0.21.1 (#13463)
  • +
  • Add a pre-check for git to build.psm1 (#13227) (Thanks @yecril71pl!)
  • +
+ +
+ +### Documentation and Help Content + +- Update `README` links and `metadata.json` for `7.1.0-preview.6` (#13437) + +[7.1.0-preview.7]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.6...v7.1.0-preview.7 + +## [7.1.0-preview.6] - 2020-08-17 + +### Breaking Changes + +- Rename `-FromUnixTime` to `-UnixTimeSeconds` on `Get-Date` to allow Unix time input (#13084) (Thanks @aetos382!) +- Make `$ErrorActionPreference` not affect `stderr` output of native commands (#13361) +- Allow explicitly specified named parameter to supersede the same one from hashtable splatting (#13162) + +### Engine Updates and Fixes + +- Refactor command line parser to do early parsing (#11482) (Thanks @iSazonov!) +- Add support for some .NET intrinsic type converters (#12580) (Thanks @iSazonov!) +- Refresh and enable the `ComInterop` code in PowerShell (#13304) + +### Experimental Features + +- Add `-Runspace` parameter to all `*-PSBreakpoint` cmdlets (#10492) (Thanks @KirkMunro!) + +### General Cmdlet Updates and Fixes + +- Fix error message from new symbolic link missing target (#13085) (Thanks @yecril71pl!) +- Make the parameter `args` non-nullable in the public `ConsoleHost` APIs (#13429) +- Add missing dispose for `CancellationTokenSource` (#13420) (Thanks @Youssef1313!) +- Add the parameter `-Paged` to `Get-Help` to support paging (#13374) +- Fix `Get-Help` not properly displaying if parameter supports wildcards (#13353) (Thanks @ThomasNieto!) +- Update `pwsh` help for `-InputFormat` parameter (#13355) (Thanks @sethvs!) +- Declare MIT license for files copied from Roslyn (#13305) (Thanks @xtqqczze!) +- Improve `BigInteger` casting behaviors (#12629) (Thanks @vexx32!) +- Fix `Get-Acl -LiteralPath "HKLM:Software\Classes\*"` behavior (#13107) (Thanks @Shriram0908!) +- Add `DefaultVisit` method to the visitor interface and class (#13258) +- Fix conflicting shorthand switch `-s` (STA) for `pwsh` (#13262) (Thanks @iSazonov!) +- Change `Read-Host -MaskInput` to use existing `SecureString` path, but return as plain text (#13256) +- Remove `ComEnumerator` as COM objects using `IEnumerator` is now supported in .NET 5.0 (#13259) +- Use temporary personal path at Runspace startup when the 'HOME' environment variable is not defined (#13239) +- Fix `Invoke-Command` to detect recursive call of the same history entry (#13197) +- Change `pwsh` executable `-inputformat` switch prefix `-in` to `-inp` to fix conflict with `-interactive` (#13205) (Thanks @iSazonov!) +- Handle WSL filesystem path when analyze security zone of a file (#13120) +- Make other switches mandatory in `Split-Path` (#13150) (Thanks @kvprasoon!) +- New Fluent Design icon for PowerShell 7 (#13100) (Thanks @sarthakmalik!) +- Fix `Move-Item` to support cross-mount moves on Unix (#13044) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @yecril71pl, @ThomasNieto, @dgoldman-msft

+ +
+ +
    +
  • Use null check with pattern-matching instead of object.ReferenceEquals (#13065) (Thanks @xtqqczze!)
  • +
  • Fix comparison of value type object to null (#13285) (Thanks @xtqqczze!)
  • +
  • Use is operator instead of as operator (#13287) (Thanks @xtqqczze!)
  • +
  • Change SwitchParameter fields to properties (#13291) (Thanks @xtqqczze!)
  • +
  • Change "operable" to "executable" (#13281) (Thanks @yecril71pl!)
  • +
  • Remove AssemblyInfo property from list views (#13331) (Thanks @ThomasNieto!)
  • +
  • Use is not syntax where appropriate and remove unnecessary parentheses (#13323) (Thanks @xtqqczze!)
  • +
  • Remove unreachable code in CustomShellCommands.cs (#13316) (Thanks @xtqqczze!)
  • +
  • Add copyright header to .editorconfig and update files (#13306) (Thanks @xtqqczze!)
  • +
  • Fix typo in Out-File.cs and Out-Printer.cs (#13298) (Thanks @dgoldman-msft!)
  • +
  • Fix SA1026CodeMustNotContainSpaceAfterNewKeywordInImplicitlyTypedArrayAllocation (#13249) (Thanks @xtqqczze!)
  • +
  • Remove usage of do statement to create an infinite loop (#13137) (Thanks @xtqqczze!)
  • +
  • Use int instead of uint in places where it's more appropriate (#13141) (Thanks @xtqqczze!)
  • +
  • Use int instead of long to avoid Interlocked.Read (#13069) (Thanks @xtqqczze!)
  • +
+ +
+ +### Tools + +- Fix `dotnet` install errors (#13387) +- Increase the timeout of Windows daily build to 90 minutes (#13354) +- Update the `dependabot` configuration to version 2 (#13230) (Thanks @RDIL!) +- Fix `Test-XUnitTestResults` function (#13270) (Thanks @iSazonov!) +- Update `.devcontainer` to use nightly docker SDK images (#13128) + +### Tests + +- Mark `Test-Connection -TraceRoute` tests as pending (#13310) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @iSazonov, @77, @WorrenB

+ +
+ +
    +
  • Update README.md and metadata.json for next release (#13059)
  • +
  • Create release pipeline as a yaml pipeline (#13394)
  • +
  • Update infrastructure to consume private builds from .NET (#13427)
  • +
  • Fix breaks in packages daily build due to macOS signing changes (#13421)
  • +
  • Sign individual files for macOS PKG (#13392)
  • +
  • Disable code sign validation on jobs that do not sign (#13389)
  • +
  • Bump PSReadLine from 2.0.2 to 2.0.4 (#13240)
  • +
  • Update build documentation for Visual Studio 2019 dependency (#13336) (Thanks @xtqqczze!)
  • +
  • Bump Microsoft.CodeAnalysis.CSharp from 3.6.0 to 3.7.0 (#13360)
  • +
  • Bump Microsoft.NET.Test.Sdk from 16.6.1 to 16.7.0 (#13364)
  • +
  • Bump xunit.runner.visualstudio from 2.4.2 to 2.4.3 (#13343)
  • +
  • Use Authenticode certificate for MSIX signing (#13330)
  • +
  • Add default help content to the assets folder (#13257)
  • +
  • Update .NET SDK version from 5.0.100-preview.7.20366.2 to 5.0.100-preview.7.20366.15 (#13200)
  • +
  • Set C# language version to preview/9.0 (#13090) (Thanks @iSazonov!)
  • +
  • Use pwsh for build and test of package in CI build (#13223)
  • +
  • Remove rcedit dependency, move daily ico dependency to props file (#13123)
  • +
  • Bump NJsonSchema from 10.1.23 to 10.1.24 (#13214)
  • +
  • Update .NET SDK version from 5.0.100-preview.7.20364.3 to 5.0.100-preview.7.20366.2 (#13192)
  • +
  • Add support for installing arm64 MSIX package. (#13043) (Thanks @77!)
  • +
  • Fix Azure file copy issues in release build (#13182)
  • +
  • Update .NET SDK version from 5.0.100-preview.7.20358.6 to 5.0.100-preview.7.20364.3 (#13155)
  • +
  • Fix Azure file copy break in Azure DevOps (#13173)
  • +
  • Bump Xunit.SkippableFact from 1.4.8 to 1.4.13 (#13143)
  • +
  • Add new chibi svg version of the avatar (#13160) (Thanks @WorrenB!)
  • +
  • Refactor MSI code to make it easier to add a WiX exe installer (#13139)
  • +
  • Disable ReadyToRun for debug build (#13144) (Thanks @iSazonov!)
  • +
  • Add new chibi version of the avatar (#13140)
  • +
  • Update .NET SDK version from 5.0.100-preview.7.20356.2 to 5.0.100-preview.7.20358.6 (#13134) (Thanks @github-actions[bot]!)
  • +
  • Update .NET SDK version from 5.0.100-preview.6.20318.15 to 5.0.100-preview.7.20356.2 (#13125) (Thanks @github-actions[bot]!)
  • +
+ +
+ +### Documentation and Help Content + +- Fix/clarify instructions for running Start-PSPester tests (#13373) +- Improve inline documentation for `VerbInfo` (#13265) (Thanks @yecril71pl!) +- Improve the wording of inline comments in the help system (#13274) (Thanks @yecril71pl!) +- Correct grammar in `README.md` and other docs (#13269) (Thanks @tasnimzotder!) +- Add "GitHub Actions Python builds" to `ADOPTERS.md` (#13228) (Thanks @brcrista!) +- Update change logs for `6.2.x` and `7.0.x` (#13194) +- Update `README.md` and `metadata.json` for the v7.0.3 release (#13187) + +[7.1.0-preview.6]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.5...v7.1.0-preview.6 + +## [7.1.0-preview.5] - 2020-07-06 + +### Engine Updates and Fixes + +- Ensure assemblies listed in the module manifest `FileList` field are not loaded (#12968) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze

+ +
+ +
    +
  • Code performance fixes (#12956) (Thanks @xtqqczze!)
  • +
+ +
+ +### Tools + +- Add missing `.editorconfig` settings present in `dotnet/runtime` (#12871) (Thanks @xtqqczze!) + +### Tests + +- Add new test for `Format-Custom` to avoid data loss (#11393) (Thanks @iSazonov!) + +### Build and Packaging Improvements + +
+ + +

Fixed upgrade code in MSI package.

+ +
+
    +
  • Change log for v7.1.0-preview.5 (Internal 11880)
  • +
  • Fix Path for the Preview MSI (#13070)
  • +
  • Correct stable and preview upgrade codes for MSI (#13036)
  • +
  • Changelog for `v7.1.0-preview.4` (Internal 11841)
  • +
  • Fix NuGet package compliance issues (#13045)
  • +
  • Bump xunit.runner.visualstudio from 2.4.1 to 2.4.2 (#12874)
  • +
  • Bump NJsonSchema from `10.1.21` to `10.1.23` (#13032) (#13022)
  • +
+ +
+ +### Documentation and Help Content + +- Fix links for MSI packages to point to `7.1.0-preview.3` (#13056) +- Add update `packages.microsoft.com` step to distribution request template. (#13008) +- Update `windows-core.md` (#13053) (Thanks @xtqqczze!) +- Add `@rjmholt` to maintainers list (#13033) +- Update docs for `v7.1.0-preview.4` release (#13028) + +## [7.1.0-preview.4] - 2020-06-25 + +### Breaking Changes + +- Make the switch parameter `-Qualifier` not positional for `Split-Path` (#12960) (Thanks @yecril71pl!) +- Resolve the working directory as literal path for `Start-Process` when it's not specified (#11946) (Thanks @NoMoreFood!) +- Make `-OutFile` parameter in web cmdlets to work like `-LiteralPath` (#11701) (Thanks @iSazonov!) + +### Engine Updates and Fixes + +- Ensure null-coalescing LHS is evaluated only once (#12667) +- Fix path handling bug in `PSTask` (#12554) (Thanks @IISResetMe!) +- Remove extra line before formatting group (#12163) (Thanks @iSazonov!) +- Make module formatting not generate error with strict mode (#11943) +- Adding more ETW logs to WSMan plugin (#12798) (Thanks @krishnayalavarthi!) +- Restrict loading of `amsi.dll` to `system32` folder (#12730) + +### General Cmdlet Updates and Fixes + +- Fix `NullReferenceException` in `CommandSearcher.GetNextCmdlet` (#12659) (Thanks @powercode!) +- Prevent `NullReferenceException` in Unix computer cmdlets with test hooks active (#12651) (Thanks @vexx32!) +- Fix issue in `Select-Object` where `Hashtable` members (e.g. `Keys`) cannot be used with `-Property` or `-ExpandProperty` (#11097) (Thanks @vexx32!) +- Fix conflicting shorthand switch `-w` for pwsh (#12945) +- Rename the `CimCmdlet` resource file (#12955) (Thanks @iSazonov!) +- Remove use of `Test-Path` in `ConciseView` (#12778) +- Flag `default` switch statement condition clause as keyword (#10487) (Thanks @msftrncs!) +- Add parameter `SchemaFile` to `Test-Json` cmdlet (#11934) (Thanks @beatcracker!) +- Bring back Certificate provider parameters (#10622) (Thanks @iSazonov!) +- Fix `New-Item` to create symbolic link to relative path target (#12797) (Thanks @iSazonov!) +- Add `CommandLine` property to Process (#12288) (Thanks @iSazonov!) +- Adds `-MaskInput` parameter to `Read-Host` (#10908) (Thanks @davinci26!) +- Change `CimCmdlets` to use `AliasAttribute` (#12617) (Thanks @thlac!) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @sethvs, @romero126, @kvprasoon, @powercode

+ +
+ +
    +
  • Use nameof operator (#12716) (Thanks @xtqqczze!)
  • +
  • Fix comments in Mshexpression.cs (#12711) (Thanks @sethvs!)
  • +
  • Formatting: remove duplicate semicolons (#12666) (Thanks @xtqqczze!)
  • +
  • Replace SortedList with Generic.SortedList<TKey,TValue> (#12954) (Thanks @xtqqczze!)
  • +
  • Use HashSet instead of Hashtable with null values (#12958) (Thanks @xtqqczze!)
  • +
  • Rename CopyItem.Tests.ps1 to Copy-Item.Tests.ps1 to match other tests (#10701) (Thanks @romero126!)
  • +
  • Fix RCS1114: Remove redundant delegate creation (#12917) (Thanks @xtqqczze!)
  • +
  • Code redundancy fixes (#12916) (Thanks @xtqqczze!)
  • +
  • Update the PowerShell modules to use the new Help URI (#12686)
  • +
  • Reorder modifiers according to preferred order (#12864) (Thanks @xtqqczze!)
  • +
  • Expand numberOfPowershellRefAssemblies list capacity (#12840) (Thanks @xtqqczze!)
  • +
  • Add readonly modifier to internal static members (#11777) (Thanks @xtqqczze!)
  • +
  • cleanup: Use coalesce expression (#12829) (Thanks @xtqqczze!)
  • +
  • Add missing assessibility modifiers (#12820) (Thanks @xtqqczze!)
  • +
  • Use t_ naming convention for ThreadStatic members (#12826) (Thanks @xtqqczze!)
  • +
  • Formatting: Add empty line between declarations (#12824) (Thanks @xtqqczze!)
  • +
  • Clarify defaultRefAssemblies list capacity in AddType.cs (#12520) (Thanks @xtqqczze!)
  • +
  • Fixing "Double "period" (..) in message for System.InvalidOperationException" (#12758) (Thanks @kvprasoon!)
  • +
  • Rethrow to preserve stack details for better maintainability (#12723) (Thanks @xtqqczze!)
  • +
  • Delete license.rtf (#12738) (Thanks @xtqqczze!)
  • +
  • Nullable annotations for CommandSearcher (#12733) (Thanks @powercode!)
  • +
  • Redundancy: Remove 'partial' modifier from type with a single part (#12725) (Thanks @xtqqczze!)
  • +
  • Remove phrase 'All rights reserved' from Microsoft copyright statements (#12722) (Thanks @xtqqczze!)
  • +
  • IDictionary -> IDictionary<string, FunctionInfo> for FunctionTable (#12658) (Thanks @powercode!)
  • +
+ +
+ +### Tools + +- Use correct isError parameter with Write-Log (#12989) +- Disable `NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter` rule in `StyleCop` (#12855) (Thanks @xtqqczze!) +- Add @TylerLeonhardt to PowerShell team list to correct changelog generation (#12927) +- Enable the upload of `ETW` traces to `CLR CAP` in Windows daily build (#12890) +- Prevent GitHub workflow for daily dotnet build updates from running in forks (#12763) (Thanks @bergmeister!) +- Add GitHub action for PR creation and `Wix` file generation logic (#12748) + +### Tests + +- Remove duplicate tests from `Measure-Object.Tests.ps1` (#12683) (Thanks @sethvs!) +- Fix tests to not write errors to console (#13010) +- Make sure tabcompletion tests run (#12981) +- Remove dependency on DNS for `Test-Connection` tests on macOS (#12943) +- Restore `markdownlint` tests (#12549) (Thanks @xtqqczze!) +- Wrap tests in pester blocks (#12700) (Thanks @xtqqczze!) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@iSazonov, @kvprasoon, @Saancreed, @heaths, @xtqqczze

+ +
+ +
    +
  • Update Distribution_Request.md
  • +
  • Bump NJsonSchema from 10.1.15 to 10.1.16 (#12685)
  • +
  • Disable uploading Symbols package (#12687)
  • +
  • Update .NET SDK version from 5.0.100-preview.5.20279.10 to 5.0.100-preview.6.20318.15 (#13018)
  • +
  • Remove component ref when re-generating the wix file (#13019)
  • +
  • Make sure icons are added to MSI staging folder (#12983)
  • +
  • Update DotnetRutimeMetadata.json to point to preview 6 (#12972)
  • +
  • Bump PSReadLine from 2.0.1 to 2.0.2 (#12909)
  • +
  • Bump NJsonSchema from 10.1.18 to 10.1.21 (#12944)
  • +
  • Check if Azure Blob exists before overwriting (#12921)
  • +
  • Enable skipped tests (#12894) (Thanks @iSazonov!)
  • +
  • Fix break in package build by pinning ffi version to 1.12 (#12889)
  • +
  • Upgrade APIScan version (#12876)
  • +
  • Make contributors unique in Release notes (#12878) (Thanks @kvprasoon!)
  • +
  • Update Linux daily CI to run in a single agent & collect traces (#12866)
  • +
  • Update .NET SDK version from 5.0.100-preview.5.20278.13 to 5.0.100-preview.5.20279.10 (#12844) (Thanks @github-actions[bot]!)
  • +
  • Sign the MSIX files for the store (#12582)
  • +
  • Update the CI builds (#12830)
  • +
  • Update .NET SDK version from 5.0.100-preview.5.20272.6 to 5.0.100-preview.5.20278.13 (#12772) (Thanks @github-actions[bot]!)
  • +
  • Allow use of build module on unknown Linux distros (#11146) (Thanks @Saancreed!)
  • +
  • Fix MSI upgrade and shortcut issues (#12792) (Thanks @heaths!)
  • +
  • Bump NJsonSchema from 10.1.17 to 10.1.18 (#12812)
  • +
  • Update .NET SDK version from 5.0.100-preview.5.20269.29 to 5.0.100-preview.5.20272.6 (#12759) (Thanks @github-actions[bot]!)
  • +
  • Bump NJsonSchema from 10.1.16 to 10.1.17 (#12761)
  • +
  • Update to dotnet SDK 5.0.0-preview.5.20268.9 (#12740)
  • +
  • Remove assets\license.rtf (#12721) (Thanks @xtqqczze!)
  • +
  • Bump Microsoft.CodeAnalysis.CSharp from 3.5.0 to 3.6.0 (#12731)
  • +
+ +
+ +### Documentation and Help Content + +- Update `README` and `metadata` files for next release (#12717) +- Update `README.md` removing experimental status of `Arm` builds, but `Win-Arm64` is still preview for Stable release. (#12707) +- Add link to Github compare in changelog (#12713) (Thanks @xtqqczze!) +- Added missing changelog for v7.1.0-preview.2 (#12665) +- Update required Visual Studio version in build docs (#12628) (Thanks @xtqqczze!) +- minor update to Distribution_Request.md (#12705) (Thanks @kilasuit!) +- Update docs.microsoft.com links (#12653) (Thanks @xtqqczze!) +- Update change log for `6.2.5` release (#12670) +- Update `README.md` and `metadata.json` for next release (#12668) +- Merge 7.0.1 change log (#12669) +- Remove markdown unused definitions (#12656) (Thanks @xtqqczze!) +- Add HoloLens to list of PowerShell adopters (#12940) (Thanks @reynoldsbd!) +- Update `README.md` and `metadata.json` for next releases (#12939) +- Fix broken link in `README.md` (#12887) (Thanks @xtqqczze!) +- Minor typo corrections in Distribution Request Issue Templates (#12744) (Thanks @corbob!) +- Correct 'review-for-comments' in `Governance.md` (#11035) (Thanks @MarvTheRobot!) +- Fix markdown ordered lists (#12657) (Thanks @xtqqczze!) +- Fix broken `docs.microsoft.com` link (#12776) (Thanks @xtqqczze!) +- Replace link to Slack with link to PowerShell Virtual User Group (#12786) (Thanks @xtqqczze!) +- Update `LICENSE.txt` so that it's recognized as MIT (#12729) + +## [7.1.0-preview.3] - 2020-05-14 + +### Breaking Changes + +- Fix string parameter binding for `BigInteger` numeric literals (#11634) (Thanks @vexx32!) + +### Engine Updates and Fixes + +- Set correct `PSProvider` full name at module load time (#11813) (Thanks @iSazonov!) + +### Experimental Features + +- Support passing `PSPath` to native commands (#12386) + +### General Cmdlet Updates and Fixes + +- Fix incorrect index in format string in ParameterBinderBase (#12630) (Thanks @powercode!) +- Copy the `CommandInfo` property in `Command.Clone()` (#12301) (Thanks @TylerLeonhardt!) +- Apply `-IncludeEqual` in `Compa-Object` when `-ExcludeDifferent` is specified (#12317) (Thanks @davidseibel!) +- Change `Get-FileHash` to close file handles before writing output (#12474) (Thanks @HumanEquivalentUnit!) +- Fix inconsistent exception message in `-replace` operator (#12388) (Thanks @jackdcasey!) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @RDIL, @powercode, @xtqqczze, @xtqqczze

+ +
+ +
    +
  • Replace Unicode non-breaking space character with space (#12576) (Thanks @xtqqczze!)
  • +
  • Remove unused New-DockerTestBuild.ps1 (#12610) (Thanks @RDIL!)
  • +
  • Annotate Assert methods for better code analysis (#12618) (Thanks @powercode!)
  • +
  • Use correct casing for cmdlet names and parameters in *.ps1 files throughout the codebase (#12584) (Thanks @xtqqczze!)
  • +
  • Document why PackageVersion is used in PowerShell.Common.props (#12523) (Thanks @xtqqczze!)
  • +
+ +
+ +### Tools + +- Update `@PoshChan` config to include `SSH` (#12526) (Thanks @vexx32!) +- Update log message in `Start-PSBootstrap` (#12573) (Thanks @xtqqczze!) +- Add the `.NET SDK` installation path to the current process path in `tools/UpdateDotnetRuntime.ps1` (#12525) + +### Tests + +- Make CIM tab completion test case insensitive (#12636) +- Mark ping tests as Pending due to stability issues in macOS (#12504) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@jcotton42, @iSazonov, @iSazonov, @iSazonov

+ +
+ +
    +
  • Update build to use the new .NET SDK 5.0.100-preview.4.20258.7 (#12637)
  • +
  • Bump NJsonSchema from 10.1.14 to 10.1.15 (#12608)
  • +
  • Bump NJsonSchema from 10.1.13 to 10.1.14 (#12598)
  • +
  • Bump NJsonSchema from 10.1.12 to 10.1.13 (#12583)
  • +
  • Update the build to sign any unsigned files as 3rd party Dlls (#12581)
  • +
  • Update .NET SDK to 5.0.100-preview.4.20229.10 (#12538)
  • +
  • Add ability to Install-Dotnet to specify directory (#12469)
  • +
  • Allow / in relative paths for using module (#7424) (#12492) (Thanks @jcotton42!)
  • +
  • Update dotnet metadata for next channel for automated updates (#12502)
  • +
  • Bump .NET to 5.0.0-preview.4 (#12507)
  • +
  • Bump Microsoft.ApplicationInsights from 2.13.1 to 2.14.0 (#12479)
  • +
  • Bump PackageManagement from 1.4.6 to 1.4.7 in /src/Modules (#12506)
  • +
  • Bump Xunit.SkippableFact from 1.3.12 to 1.4.8 (#12480)
  • +
  • Fix quotes to allow variable expansion (#12512)
  • +
  • Use new TargetFramework as net5.0 in packaging scripts (#12503) (Thanks @iSazonov!)
  • +
  • Use new value for TargetFramework as net5.0 instead of netcoreapp5.0 (#12486) (Thanks @iSazonov!)
  • +
  • Disable PublishReadyToRun for framework dependent packages (#12450)
  • +
  • Add dependabot rules to ignore updates from .NET (#12466)
  • +
  • Update README.md and metadata.json for upcoming release (#12441)
  • +
  • Turn on ReadyToRun (#12361) (Thanks @iSazonov!)
  • +
  • Add summary to compressed sections of change log (#12429)
  • +
+ +
+ +### Documentation and Help Content + +- Add link to life cycle doc to distribution request template (#12638) +- Update TFM reference in build docs (#12514) (Thanks @xtqqczze!) +- Fix broken link for blogs in documents (#12471) + +## [7.1.0-preview.2] - 2020-04-23 + +### Breaking Changes + +- On Windows, `Start-Process` creates a process environment with + all the environment variables from current session, + using `-UseNewEnvironment` creates a new default process environment (#10830) (Thanks @iSazonov!) +- Do not wrap return result to `PSObject` when converting ScriptBlock to delegate (#10619) + +### Engine Updates and Fixes + +- Allow case insensitive paths for determining `PSModulePath` (#12192) +- Add PowerShell version 7.0 to compatible version list (#12184) +- Discover assemblies loaded by `Assembly.Load(byte[])` and `Assembly.LoadFile` (#12203) + +### General Cmdlet Updates and Fixes + +- Fix `WinCompat` module loading to treat PowerShell 7 modules with higher priority (#12269) +- Implement `ForEach-Object -Parallel` runspace reuse (#12122) +- Fix `Get-Service` to not modify collection while enumerating it (#11851) (Thanks @NextTurn!) +- Clean up the IPC named pipe on PowerShell exit (#12187) +- Fix `` detection regex in web cmdlets (#12099) (Thanks @vexx32!) +- Allow shorter signed hex literals with appropriate type suffixes (#11844) (Thanks @vexx32!) +- Update `UseNewEnvironment` parameter behavior of `Start-Process` cmdlet on Windows (#10830) (Thanks @iSazonov!) +- Add `-Shuffle` switch to `Get-Random` command (#11093) (Thanks @eugenesmlv!) +- Make `GetWindowsPowerShellModulePath` compatible with multiple PS installations (#12280) +- Fix `Start-Job` to work on systems that don't have Windows PowerShell registered as default shell (#12296) +- Specifying an alias and `-Syntax` to `Get-Command` returns the aliased commands syntax (#10784) (Thanks @ChrisLGardner!) +- Make CSV cmdlets work when using `-AsNeeded` and there is an incomplete row (#12281) (Thanks @iSazonov!) +- In local invocations, do not require `-PowerShellVersion 5.1` for `Get-FormatData` in order to see all format data. (#11270) (Thanks @mklement0!) +- Added Support For Big Endian `UTF-32` (#11947) (Thanks @NoMoreFood!) +- Fix possible race that leaks PowerShell object dispose in `ForEach-Object -Parallel` (#12227) +- Add `-FromUnixTime` to `Get-Date` to allow Unix time input (#12179) (Thanks @jackdcasey!) +- Change default progress foreground and background colors to provide improved contrast (#11455) (Thanks @rkeithhill!) +- Fix `foreach -parallel` when current drive is not available (#12197) +- Do not wrap return result to `PSObject` when converting `ScriptBlock` to `delegate` (#10619) +- Don't write DNS resolution errors on `Test-Connection -Quiet` (#12204) (Thanks @vexx32!) +- Use dedicated threads to read the redirected output and error streams from the child process for out-of-proc jobs (#11713) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@ShaydeNofziger, @RDIL

+ +
+ +
    +
  • Fix erroneous comment in tokenizer.cs (#12206) (Thanks @ShaydeNofziger!)
  • +
  • Fix terms checker issues (#12189)
  • +
  • Update copyright notice to latest guidance (#12190)
  • +
  • CodeFactor cleanup (#12251) (Thanks @RDIL!)
  • +
+ +
+ +### Tools + +- Update .NET dependency update script to include test `csproj` files (#12372) +- Scripts to update to .NET prerelease version (#12284) + +### Tests + +- Pin major Pester version to 4 to prevent breaking changes caused by upcoming release of v5 (#12262) (Thanks @bergmeister!) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@rkitover, @bergmeister

+ +
+ +
    +
  • Add the nuget.config from root to the temporary build folder (#12394)
  • +
  • Bump System.IO.Packaging (#12365)
  • +
  • Bump Markdig.Signed from 0.18.3 to 0.20.0 (#12379)
  • +
  • Bump to .NET 5 Preview 3 pre-release (#12353)
  • +
  • Bump PowerShellGet from 2.2.3 to 2.2.4 (#12342)
  • +
  • Linux: Initial support for Gentoo installations. (#11429) (Thanks @rkitover!)
  • +
  • Upgrade to .NET 5 Preview 2 (#12250) (Thanks @bergmeister!)
  • +
  • Fix the Sync PSGalleryModules to Artifacts build (#12277)
  • +
  • Bump PSReadLine from 2.0.0 to 2.0.1 (#12243)
  • +
  • Bump NJsonSchema from 10.1.11 to 10.1.12 (#12230)
  • +
  • Update change log generation script to support collapsible sections (#12214)
  • +
+ +
+ +### Documentation and Help Content + +- Add documentation for `WebResponseObject` and `BasicHtmlWebResponseObject` properties (#11876) (Thanks @kevinoid!) +- Add Windows 10 IoT Core reference in `Adopters.md` (#12266) (Thanks @parameshbabu!) +- Update `README.md` and `metadata.json` for `7.1.0-preview.1` (#12211) + +## [7.1.0-preview.1] - 2020-03-26 + +### Breaking Changes + +- Use invariant culture string conversion for `-replace` operator (#10954) (Thanks @iSazonov!) + +### Engine Updates and Fixes + +- Revert the PRs that made `DBNull.Value` and `NullString.Value` treated as `$null` (#11648) + +### Experimental Features + +- Use invariant culture string conversion for `-replace` operator (#10954) (Thanks @iSazonov!) + +### General Cmdlet Updates and Fixes + +- Fix an operator preference order issue in binder code (#12075) (Thanks @DamirAinullin!) +- Fix `NullReferenceException` when binding common parameters of type `ActionPreference` (#12124) +- Fix default formatting for deserialized `MatchInfo` (#11728) (Thanks @iSazonov!) +- Use asynchronous streams in `Invoke-RestMethod` (#11095) (Thanks @iSazonov!) +- Address UTF-8 Detection In `Get-Content -Tail` (#11899) (Thanks @NoMoreFood!) +- Handle the `IOException` in `Get-FileHash` (#11944) (Thanks @iSazonov!) +- Change `PowerShell Core` to `PowerShell` in a resource string (#11928) (Thanks @alexandair!) +- Bring back `MainWindowTitle` in `PSHostProcessInfo` (#11885) (Thanks @iSazonov!) +- Miscellaneous minor updates to Windows Compatibility (#11980) +- Fix `ConciseView` to split `PositionMessage` using `[Environment]::NewLine` (#12010) +- Remove network hop restriction for interactive sessions (#11920) +- Fix `NullReferenceException` in `SuspendStoppingPipeline()` and `RestoreStoppingPipeline()` (#11870) (Thanks @iSazonov!) +- Generate GUID for `FormatViewDefinition` `InstanceId` if not provided (#11896) +- Fix `ConciseView` where error message is wider than window width and doesn't have whitespace (#11880) +- Allow cross-platform `CAPI-compatible` remote key exchange (#11185) (Thanks @silijon!) +- Fix error message (#11862) (Thanks @NextTurn!) +- Fix `ConciseView` to handle case where there isn't a console to obtain the width (#11784) +- Update `CmsCommands` to use Store vs certificate provider (#11643) (Thanks @mikeTWC1984!) +- Enable `pwsh` to work on Windows systems where `mpr.dll` and STA is not available (#11748) +- Refactor and implement `Restart-Computer` for `Un*x` and macOS (#11319) +- Add an implementation of `Stop-Computer` for Linux and macOS (#11151) +- Fix `help` function to check if `less` is available before using (#11737) +- Update `PSPath` in `certificate_format_ps1.xml` (#11603) (Thanks @xtqqczze!) +- Change regular expression to match relation-types without quotes in Link header (#11711) (Thanks @Marusyk!) +- Fix error message during symbolic link deletion (#11331) +- Add custom `Selected.*` type to `PSCustomObject` in `Select-Object` only once (#11548) (Thanks @iSazonov!) +- Add `-AsUTC` to the `Get-Date` cmdlet (#11611) +- Fix grouping behavior with Boolean values in `Format-Hex` (#11587) (Thanks @vexx32!) +- Make `Test-Connection` always use the default synchronization context for sending ping requests (#11517) +- Correct startup error messages (#11473) (Thanks @iSazonov!) +- Ignore headers with null values in web cmdlets (#11424) (Thanks @iSazonov!) +- Re-add check for `Invoke-Command` job dispose. (#11388) +- Revert "Update formatter to not write newlines if content is empty (#11193)" (#11342) (Thanks @iSazonov!) +- Allow `CompleteInput` to return results from `ArgumentCompleter` when `AST` or Script has matching function definition (#10574) (Thanks @M1kep!) +- Update formatter to not write new lines if content is empty (#11193) + +### Code Cleanup + +
+ +
    +
  • Use span-based overloads (#11884) (Thanks @iSazonov!)
  • +
  • Use new string.Split() overloads (#11867) (Thanks @iSazonov!)
  • +
  • Remove unreachable DSC code (#12076) (Thanks @DamirAinullin!)
  • +
  • Remove old dead code from FullCLR (#11886) (Thanks @iSazonov!)
  • +
  • Use Dictionary.TryAdd() where possible (#11767) (Thanks @iSazonov!)
  • +
  • Use Environment.NewLine instead of hard-coded linefeed in ParseError.ToString (#11746)
  • +
  • Fix FileSystem provider error message (#11741) (Thanks @iSazonov!)
  • +
  • Reformat code according to EditorConfig rules (#11681) (Thanks @xtqqczze!)
  • +
  • Replace use of throw GetExceptionForHR with ThrowExceptionForHR (#11640) (Thanks @xtqqczze!)
  • +
  • Refactor delegate types to lambda expressions (#11690) (Thanks @xtqqczze!)
  • +
  • Remove Unicode BOM from text files (#11546) (Thanks @xtqqczze!)
  • +
  • Fix Typo in Get-ComputerInfo cmdlet description (#11321) (Thanks @doctordns!)
  • +
  • Fix typo in description for Get-ExperimentalFeature PSWindowsPowerShellCompatibility (#11282) (Thanks @alvarodelvalle!)
  • +
  • Cleanups in command discovery (#10815) (Thanks @iSazonov!)
  • +
  • Review CurrentCulture (#11044) (Thanks @iSazonov!)
  • +
+ +
+ +### Tools + +- Change recommended VS Code extension name from `ms-vscode.csharp` to `ms-dotnettools.csharp` (#12083) (Thanks @devlead!) +- Specify `csharp_preferred_modifier_order` in `EditorConfig` (#11775) (Thanks @xtqqczze!) +- Update `.editorconfig` (#11675) (Thanks @xtqqczze!) +- Enable `EditorConfig` support in `OmniSharp` (#11627) (Thanks @xtqqczze!) +- Specify charset in `.editorconfig` as `utf-8` (no BOM) (#11654) (Thanks @xtqqczze!) +- Configure the issue label bot (#11527) +- Avoid variable names that conflict with automatic variables (#11392) (Thanks @xtqqczze!) + +### Tests + +- Add empty `preview.md` file to fix broken link (#12041) +- Add helper functions for SSH remoting tests (#11955) +- Add new tests for `Get-ChildItem` for `FileSystemProvider` (#11602) (Thanks @iSazonov!) +- Ensure that types referenced by `PowerShellStandard` are present (#10634) +- Check state and report reason if it's not "opened" (#11574) +- Fixes for running tests on Raspbian (#11661) +- Unify pester test syntax for the arguments of `-BeOfType` (#11558) (Thanks @xtqqczze!) +- Correct casing for automatic variables (#11568) (Thanks @iSazonov!) +- Avoid variable names that conflict with automatic variables part 2 (#11559) (Thanks @xtqqczze!) +- Update pester syntax to v4 (#11544) (Thanks @xtqqczze!) +- Allow error 504 (Gateway Timeout) in `markdown-link` tests (#11439) (Thanks @xtqqczze!) +- Re-balance CI tests (#11420) (Thanks @iSazonov!) +- Include URL in the markdown-links test error message (#11438) (Thanks @xtqqczze!) +- Use CIM cmdlets instead of WMI cmdlets in tests (#11423) (Thanks @xtqqczze!) + +### Build and Packaging Improvements + +
+ +
    +
  • Put symbols in separate package (#12169)
  • +
  • Disable x86 PDB generation (#12167)
  • +
  • Bump NJsonSchema from 10.1.5 to 10.1.11 (#12050) (#12088) (#12166)
  • +
  • Create crossgen symbols for Windows x64 and x86 (#12157)
  • +
  • Move to .NET 5 preview.1 (#12140)
  • +
  • Bump Microsoft.CodeAnalysis.CSharp from 3.4.0 to 3.5.0 (#12136)
  • +
  • Move to standard internal pool for building (#12119)
  • +
  • Fix package syncing to private Module Feed (#11841)
  • +
  • Add Ubuntu SSH remoting tests CI (#12033)
  • +
  • Bump Markdig.Signed from 0.18.1 to 0.18.3 (#12078)
  • +
  • Fix MSIX packaging to determine if a Preview release by inspecting the semantic version string (#11991)
  • +
  • Ignore last exit code in the build step as dotnet may return error when SDK is not installed (#11972)
  • +
  • Fix daily package build (#11882)
  • +
  • Fix package sorting for syncing to private Module Feed (#11838)
  • +
  • Set StrictMode version 3.0 (#11563) (Thanks @xtqqczze!)
  • +
  • Bump .devcontainer version to dotnet 3.1.101 (#11707) (Thanks @Jawz84!)
  • +
  • Move to version 3 of AzFileCopy (#11697)
  • +
  • Update README.md and metadata.json for next release (#11664)
  • +
  • Code Cleanup for environment data gathering in build.psm1 (#11572) (Thanks @xtqqczze!)
  • +
  • Update Debian Install Script To Support Debian 10 (#11540) (Thanks @RandomNoun7!)
  • +
  • Update ADOPTERS.md (#11261) (Thanks @edyoung!)
  • +
  • Change back to use powershell.exe in 'SetVersionVariables.yml' to unblock daily build (#11207)
  • +
  • Change to use pwsh to have consistent JSON conversion for DateTime (#11126)
  • +
+ +
+ +### Documentation and Help Content + +- Replace `VSCode` link in `CONTRIBUTING.md` (#11475) (Thanks @stevend811!) +- Remove the version number of PowerShell from LICENSE (#12019) +- Add the 7.0 change log link to `CHANGELOG/README.md` (#12062) (Thanks @LabhanshAgrawal!) +- Improvements to the contribution guide (#12086) (Thanks @ShaydeNofziger!) +- Update the doc about debugging dotnet core in VSCode (#11969) +- Update `README.md` and `metadata.json` for the next release (#11918) (#11992) +- Update `Adopters.md` to include info on Azure Pipelines and GitHub Actions (#11888) (Thanks @alepauly!) +- Add information about how Amazon AWS uses PowerShell. (#11365) (Thanks @bpayette!) +- Add link to .NET CLI version in build documentation (#11725) (Thanks @joeltankam!) +- Added info about `DeploymentScripts` in `ADOPTERS.md` (#11703) +- Update `CHANGELOG.md` for `6.2.4` release (#11699) +- Update `README.md` and `metadata.json` for next release (#11597) +- Update the breaking change definition (#11516) +- Adding System Frontier to the PowerShell Core adopters list `ADOPTERS.md` (#11480) (Thanks @OneScripter!) +- Update `ChangeLog`, `README.md` and `metadata.json` for `7.0.0-rc.1` release (#11363) +- Add `AzFunctions` to `ADOPTERS.md` (#11311) (Thanks @Francisco-Gamino!) +- Add `Universal Dashboard` to `ADOPTERS.md` (#11283) (Thanks @adamdriscoll!) +- Add `config.yml` for `ISSUE_TEMPLATE` so that Doc, Security, Support, and Windows PowerShell issues go to URLs (#11153) +- Add `Adopters.md` file (#11256) +- Update `Readme.md` for `preview.6` release (#11108) +- Update `SUPPORT.md` (#11101) (Thanks @mklement0!) +- Update `README.md` (#11100) (Thanks @mklement0!) + +[7.1.0-preview.5]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.4...v7.1.0-preview.5 +[7.1.0-preview.4]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.3...v7.1.0-preview.4 +[7.1.0-preview.3]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.2...v7.1.0-preview.3 +[7.1.0-preview.2]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.1...v7.1.0-preview.2 +[7.1.0-preview.1]: https://github.com/PowerShell/PowerShell/compare/v7.0.0-preview.6...v7.1.0-preview.1 + diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md index 4c271de1a2c..83efcb0fed5 100644 --- a/CHANGELOG/README.md +++ b/CHANGELOG/README.md @@ -1,6 +1,7 @@ # Changelogs * [Current preview changelog](preview.md) +* [7.1 changelog](7.1.md) * [7.0 changelog](7.0.md) * [6.2 changelog](6.2.md) * [6.1 changelog](6.1.md) diff --git a/CHANGELOG/preview.md b/CHANGELOG/preview.md index 525cea149cf..9086cdd5665 100644 --- a/CHANGELOG/preview.md +++ b/CHANGELOG/preview.md @@ -1,29 +1,71 @@ # Current preview release -## [7.1.0-preview.7] - 2020-09-08 +## [7.2.0-rc.1] - 2021-10-21 -### Breaking Changes +### General Cmdlet Updates and Fixes + +- Disallow COM calls for AppLocker system lockdown (#16268) +- Configure `Microsoft.ApplicationInsights` to not send cloud role name (#16246) +- Disallow `Add-Type` in NoLanguage mode on a locked down machine (#16245) +- Make property names for color VT100 sequences consistent with documentation (#16212) +- Make moving a directory into itself with `Move-Item` an error (#16198) +- Change `FileSystemInfo.Target` from a `CodeProperty` to an `AliasProperty` that points to `FileSystemInfo.LinkTarget` (#16165) + +### Tests + +- Removed deprecated docker-based tests for PowerShell release packages (#16224) -- Fix `$?` to not be `$false` when native command writes to `stderr` (#13395) +### Build and Packaging Improvements + +
+ + +

Bump .NET SDK to 6.0.100-rc.2

+
+ +
    +
  • Update .NET 6 to version 6.0.100-rc.2.21505.57 (#16249)
  • +
  • Fix RPM packaging (Internal 17704)
  • +
  • Update ThirdPartyNotices.txt (#16283)
  • +
  • Update pipeline yaml file to use ubuntu-latest image (#16279)
  • +
  • Add script to generate cgmanifest.json (#16278)
  • +
  • Update version of Microsoft.PowerShell.Native and Microsoft.PowerShell.MarkdownRender packages (#16277)
  • +
  • Add cgmanifest.json for generating correct third party notice file (#16266)
  • +
  • Only upload stable buildinfo for stable releases (#16251)
  • +
  • Don't upload .dep or .tar.gz for RPM because there are none (#16230)
  • +
  • Ensure RPM license is recognized (#16189)
  • +
  • Add condition to only generate release files in local dev build only (#16259)
  • +
  • Ensure psoptions.json and manifest.spdx.json files always exist in packages (#16258)
  • +
  • Fix CI script and split out ARM runs (#16252)
  • +
  • Update vPack task version to 12 (#16250)
  • +
  • Sign third party executables (#16229)
  • +
  • Add Software Bill of Materials to the main packages (#16202)
  • +
  • Upgrade set-value package for markdown test (#16196)
  • +
  • Fix Microsoft update spelling issue (#16178)
  • +
  • Move vPack build to 1ES Pool (#16169)
  • +
+ +
+ +[7.2.0-rc.1]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.10...v7.2.0-rc.1 + +## [7.2.0-preview.10] - 2021-09-28 ### Engine Updates and Fixes -- Initial work of the subsystem plugin model (for minimal powershell) (#13186) -- Optimize `GetSystemLockdownPolicy` for non-lockdown scenarios (#13438) +- Remove duplicate remote server mediator code (#16027) ### General Cmdlet Updates and Fixes -- Revert "Add the parameter `-Paged` to `Get-Help` to support paging (#13374)" (#13519) -- Add support for `TLS` 1.3 in Web cmdlets (#13409) (Thanks @iSazonov!) -- Add null check for `args` in `CommandLineParser` (#13451) (Thanks @iSazonov!) -- Process reparse points for Microsoft Store applications (#13481) (Thanks @iSazonov!) -- Move `PSNullConditionalOperators` feature out of experimental (#13529) -- Move `PSNativePSPathResolution` feature out of Experimental (#13522) -- Use field if property does not exist for `ObRoot` when using PowerShell Direct to container (#13375) (Thanks @hemisphera!) -- Suppress `UTF-7` obsolete warnings (#13484) -- Avoid multiple enumerations of an `IEnumerable` instance in `Compiler.cs` (#13491) -- Change `Add-Type -OutputType` to not support `ConsoleApplication` and `WindowsApplication` (#13440) -- Create warnings when `UTF-7` is specified as an encoding (#13430) +- Use `PlainText` when writing to a host that doesn't support VT (#16092) +- Remove support for `AppExecLinks` to retrieve target (#16044) +- Move `GetOuputString()` and `GetFormatStyleString()` to `PSHostUserInterface` as public API (#16075) +- Add `isOutputRedirected` parameter to `GetFormatStyleString()` method (#14397) +- Fix `ConvertTo-SecureString` with key regression due to .NET breaking change (#16068) +- Fix regression in `Move-Item` to only fallback to `CopyAndDelete` in specific cases (#16029) +- Set `$?` correctly for command expression with redirection (#16046) +- Use `CurrentCulture` when handling conversions to `DateTime` in `Add-History` (#16005) (Thanks @vexx32!) +- Fix `NullReferenceException` in `Format-Wide` (#15990) (Thanks @DarylGraves!) ### Code Cleanup @@ -32,106 +74,89 @@

We thank the following contributors!

-

@xtqqczze, @tamasvajk

+

@xtqqczze!

    -
  • Add single blank line after copyright header (#13486) (Thanks @xtqqczze!)
  • -
  • Use read-only auto-implemented properties (#13507) (Thanks @xtqqczze!)
  • -
  • Use boolean instead of bitwise operators on bool values (#13506) (Thanks @xtqqczze!)
  • -
  • Fix erroneous assert (#13495) (Thanks @tamasvajk!)
  • -
  • Cleanup: remove duplicate words in comments (#13539) (Thanks @xtqqczze!)
  • -
  • Reformat StringUtil (#13509) (Thanks @xtqqczze!)
  • -
  • Use uint instead of long for PDH constants (#13502) (Thanks @xtqqczze!)
  • -
  • Cleanup: Remove redundant empty lines (#13404) (Thanks @xtqqczze!)
  • -
  • Add StringUtil.Format overload to avoid unnecessary allocations (#13408) (Thanks @xtqqczze!)
  • -
  • Fix test hooks for CommandLineParameterParser (#13459)
  • -
  • Remove redundant delegate creation (#13441) (Thanks @xtqqczze!)
  • +
  • Improve CommandInvocationIntrinsics API documentation and style (#14369)
  • +
  • Use bool?.GetValueOrDefault() in FormatWideCommand (#15988) (Thanks @xtqqczze!)
### Tools -- vscode: Add `editorconfig` to recommended extensions (#13537) (Thanks @xtqqczze!) -- Remove the out-dated `ZapDisable` related code from `build.psm1` (#13350) (Thanks @jackerr3!) +- Fix typo in build.psm1 (#16038) (Thanks @eltociear!) +- Add `.stylecop` to `filetypexml` and format it (#16025) +- Enable sending Teams notification when workflow fails (#15982) ### Tests -- Disable `WMF` download link validation test (#13479) +- Enable two previously disabled `Get-Process` tests (#15845) (Thanks @iSazonov!) ### Build and Packaging Improvements
- -

We thank the following contributors!

-

@yecril71pl

- +Details
    -
  • Add Microsoft.NET.Test.Sdk dependency (Internal 12589)
  • -
  • Update .NET NuGet package version to 5.0.0-preview.8.20407.11 (Internal 12555)
  • -
  • Update to .NET 5 preview 8 (#13530)
  • -
  • Change stage dependency for docker release stage in release pipeline (#13512)
  • -
  • Bump Microsoft.NET.Test.Sdk from 16.7.0 to 16.7.1 (#13492)
  • -
  • Create the folder before copying the global tools (#13476)
  • -
  • A few fixes to the release pipeline (#13473)
  • -
  • Bump Markdig.Signed from 0.20.0 to 0.21.1 (#13463)
  • -
  • Add a pre-check for git to build.psm1 (#13227) (Thanks @yecril71pl!)
  • +
  • Add SHA256 hashes to release (#16147)
  • +
  • Update Microsoft.CodeAnalysis.CSharp version (#16138)
  • +
  • Change path for Component Governance for build to the path we actually use to build (#16137)
  • +
  • Bump Microsoft.CodeAnalysis.NetAnalyzers (#16070) (#16045) (#16036) (#16021) (#15985)
  • +
  • Update .NET to 6.0.100-rc.1.21458.32 (#16066)
  • +
  • Update minimum required OS version for macOS (#16088)
  • +
  • Ensure locale is set correctly on Ubuntu 20.04 in CI (#16067) (#16073)
  • +
  • Update .NET SDK version from 6.0.100-preview.6.21355.2 to 6.0.100-rc.1.21455.2 (#16041) (#16028) (#15648)
  • +
  • Fix the GitHub Action for updating .NET daily builds (#16042)
  • +
  • Move from PkgES hosted agents to 1ES hosted agents (#16023)
  • +
  • Update Ubuntu images to use Ubuntu 20.04 (#15906)
  • +
  • Fix the macOS build by updating the pool image name (#16010)
  • +
  • Use Alpine 3.12 for building PowerShell for Alpine Linux (#16008)
  • +
  • Ignore error from Find-Package (#15999)
  • +
  • Find packages separately for each source in UpdateDotnetRuntime.ps1 script (#15998)
  • +
  • Update metadata to start using .NET 6 RC1 builds (#15981)
-### Documentation and Help Content - -- Update `README` links and `metadata.json` for `7.1.0-preview.6` (#13437) - -[7.1.0-preview.7]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.6...v7.1.0-preview.7 +[7.2.0-preview.10]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.9...v7.2.0-preview.10 -## [7.1.0-preview.6] - 2020-08-17 +## [7.2.0-preview.9] - 2021-08-23 ### Breaking Changes -- Rename `-FromUnixTime` to `-UnixTimeSeconds` on `Get-Date` to allow Unix time input (#13084) (Thanks @aetos382!) -- Make `$ErrorActionPreference` not affect `stderr` output of native commands (#13361) -- Allow explicitly specified named parameter to supersede the same one from hashtable splatting (#13162) +- Change the default value of `$PSStyle.OutputRendering` to `OutputRendering.Host` and remove `OutputRendering.Automatic` (#15882) +- Fix `CA1052` for public API to make classes static when they only have static methods (#15775) (Thanks @xtqqczze!) +- Update `pwsh.exe -File` to only accept `.ps1` script files on Windows (#15859) ### Engine Updates and Fixes -- Refactor command line parser to do early parsing (#11482) (Thanks @iSazonov!) -- Add support for some .NET intrinsic type converters (#12580) (Thanks @iSazonov!) -- Refresh and enable the `ComInterop` code in PowerShell (#13304) - -### Experimental Features - -- Add `-Runspace` parameter to all `*-PSBreakpoint` cmdlets (#10492) (Thanks @KirkMunro!) +- Update .NET adapter to handle interface static members properly (#15908) +- Catch and handle unauthorized access exception when removing AppLocker test files (#15881) ### General Cmdlet Updates and Fixes -- Fix error message from new symbolic link missing target (#13085) (Thanks @yecril71pl!) -- Make the parameter `args` non-nullable in the public `ConsoleHost` APIs (#13429) -- Add missing dispose for `CancellationTokenSource` (#13420) (Thanks @Youssef1313!) -- Add the parameter `-Paged` to `Get-Help` to support paging (#13374) -- Fix `Get-Help` not properly displaying if parameter supports wildcards (#13353) (Thanks @ThomasNieto!) -- Update `pwsh` help for `-InputFormat` parameter (#13355) (Thanks @sethvs!) -- Declare MIT license for files copied from Roslyn (#13305) (Thanks @xtqqczze!) -- Improve `BigInteger` casting behaviors (#12629) (Thanks @vexx32!) -- Fix `Get-Acl -LiteralPath "HKLM:Software\Classes\*"` behavior (#13107) (Thanks @Shriram0908!) -- Add `DefaultVisit` method to the visitor interface and class (#13258) -- Fix conflicting shorthand switch `-s` (STA) for `pwsh` (#13262) (Thanks @iSazonov!) -- Change `Read-Host -MaskInput` to use existing `SecureString` path, but return as plain text (#13256) -- Remove `ComEnumerator` as COM objects using `IEnumerator` is now supported in .NET 5.0 (#13259) -- Use temporary personal path at Runspace startup when the 'HOME' environment variable is not defined (#13239) -- Fix `Invoke-Command` to detect recursive call of the same history entry (#13197) -- Change `pwsh` executable `-inputformat` switch prefix `-in` to `-inp` to fix conflict with `-interactive` (#13205) (Thanks @iSazonov!) -- Handle WSL filesystem path when analyze security zone of a file (#13120) -- Make other switches mandatory in `Split-Path` (#13150) (Thanks @kvprasoon!) -- New Fluent Design icon for PowerShell 7 (#13100) (Thanks @sarthakmalik!) -- Fix `Move-Item` to support cross-mount moves on Unix (#13044) +- Add `-PassThru` parameter to `Set-Clipboard` (#13713) (Thanks @ThomasNieto!) +- Add `-Encoding` parameter for `Tee-Object` (#12135) (Thanks @Peter-Schneider!) +- Update `ConvertTo-Csv` and `Export-Csv` to handle `IDictionary` objects (#11029) (Thanks @vexx32!) +- Update the parameters `-Exception` and `-ErrorRecord` for `Write-Error` to be position 0 (#13813) (Thanks @ThomasNieto!) +- Don't use `ArgumentList` when creating COM object with `New-Object` as it's not applicable to the COM parameter set (#15915) +- Fix `$PSStyle` list output to correctly show `TableHeader` (#15928) +- Remove the `PSImplicitRemotingBatching` experimental feature (#15863) +- Fix issue with `Get-Process -Module` failing to stop when it's piped to `Select-Object` (#15682) (Thanks @ArmaanMcleod!) +- Make the experimental features `PSUnixFileStat`, `PSCultureInvariantReplaceOperator`, `PSNotApplyErrorActionToStderr`, `PSAnsiRendering`, `PSAnsiProgressFeatureName` stable (#15864) +- Enhance `Remove-Item` to work with OneDrive (#15571) (Thanks @iSazonov!) +- Make global tool entrypoint class static (#15880) +- Update `ServerRemoteHost` version to be same as `PSVersion` (#15809) +- Make the initialization of `HttpKnownHeaderNames` thread safe (#15519) (Thanks @iSazonov!) +- `ConvertTo-Csv`: Quote fields with quotes and newlines when using `-UseQuotes AsNeeded` (#15765) (Thanks @lselden!) +- Forwarding progress stream changes from `Foreach-Object -Parallel` runspaces (#14271) (Thanks @powercode!) +- Add validation to `$PSStyle` to reject printable text when setting a property that only expects ANSI escape sequence (#15825) ### Code Cleanup @@ -140,40 +165,31 @@

We thank the following contributors!

-

@xtqqczze, @yecril71pl, @ThomasNieto, @dgoldman-msft

+

@xtqqczze

    -
  • Use null check with pattern-matching instead of object.ReferenceEquals (#13065) (Thanks @xtqqczze!)
  • -
  • Fix comparison of value type object to null (#13285) (Thanks @xtqqczze!)
  • -
  • Use is operator instead of as operator (#13287) (Thanks @xtqqczze!)
  • -
  • Change SwitchParameter fields to properties (#13291) (Thanks @xtqqczze!)
  • -
  • Change "operable" to "executable" (#13281) (Thanks @yecril71pl!)
  • -
  • Remove AssemblyInfo property from list views (#13331) (Thanks @ThomasNieto!)
  • -
  • Use is not syntax where appropriate and remove unnecessary parentheses (#13323) (Thanks @xtqqczze!)
  • -
  • Remove unreachable code in CustomShellCommands.cs (#13316) (Thanks @xtqqczze!)
  • -
  • Add copyright header to .editorconfig and update files (#13306) (Thanks @xtqqczze!)
  • -
  • Fix typo in Out-File.cs and Out-Printer.cs (#13298) (Thanks @dgoldman-msft!)
  • -
  • Fix SA1026CodeMustNotContainSpaceAfterNewKeywordInImplicitlyTypedArrayAllocation (#13249) (Thanks @xtqqczze!)
  • -
  • Remove usage of do statement to create an infinite loop (#13137) (Thanks @xtqqczze!)
  • -
  • Use int instead of uint in places where it's more appropriate (#13141) (Thanks @xtqqczze!)
  • -
  • Use int instead of long to avoid Interlocked.Read (#13069) (Thanks @xtqqczze!)
  • +
  • Avoid unneeded array allocation in module code (#14329) (Thanks @xtqqczze!)
  • +
  • Enable and fix analysis rules CA1052, CA1067, and IDE0049 (#15840) (Thanks @xtqqczze!)
  • +
  • Avoid unnecessary allocation in formatting code (#15832) (Thanks @xtqqczze!)
  • +
  • Specify the analyzed API surface for all code quality rules (#15778) (Thanks @xtqqczze!)
### Tools -- Fix `dotnet` install errors (#13387) -- Increase the timeout of Windows daily build to 90 minutes (#13354) -- Update the `dependabot` configuration to version 2 (#13230) (Thanks @RDIL!) -- Fix `Test-XUnitTestResults` function (#13270) (Thanks @iSazonov!) -- Update `.devcontainer` to use nightly docker SDK images (#13128) +- Enable `/rebase` to automatically rebase a PR (#15808) +- Update `.editorconfig` to not replace tabs with spaces in `.tsv` files (#15815) (Thanks @SethFalco!) +- Update PowerShell team members in the change log generation script (#15817) ### Tests -- Mark `Test-Connection -TraceRoute` tests as pending (#13310) +- Add more tests to validate the current command error handling behaviors (#15919) +- Make `Measure-Object` property test independent of the file system (#15879) +- Add more information when a `syslog` parsing error occurs (#15857) +- Harden logic when looking for `syslog` entries to be sure that we select based on the process id (#15841) ### Build and Packaging Improvements @@ -182,62 +198,46 @@

We thank the following contributors!

-

@xtqqczze, @iSazonov, @77, @WorrenB

+

@xtqqczze

    -
  • Update README.md and metadata.json for next release (#13059)
  • -
  • Create release pipeline as a yaml pipeline (#13394)
  • -
  • Update infrastructure to consume private builds from .NET (#13427)
  • -
  • Fix breaks in packages daily build due to macOS signing changes (#13421)
  • -
  • Sign individual files for macOS PKG (#13392)
  • -
  • Disable code sign validation on jobs that do not sign (#13389)
  • -
  • Bump PSReadLine from 2.0.2 to 2.0.4 (#13240)
  • -
  • Update build documentation for Visual Studio 2019 dependency (#13336) (Thanks @xtqqczze!)
  • -
  • Bump Microsoft.CodeAnalysis.CSharp from 3.6.0 to 3.7.0 (#13360)
  • -
  • Bump Microsoft.NET.Test.Sdk from 16.6.1 to 16.7.0 (#13364)
  • -
  • Bump xunit.runner.visualstudio from 2.4.2 to 2.4.3 (#13343)
  • -
  • Use Authenticode certificate for MSIX signing (#13330)
  • -
  • Add default help content to the assets folder (#13257)
  • -
  • Update .NET SDK version from 5.0.100-preview.7.20366.2 to 5.0.100-preview.7.20366.15 (#13200)
  • -
  • Set C# language version to preview/9.0 (#13090) (Thanks @iSazonov!)
  • -
  • Use pwsh for build and test of package in CI build (#13223)
  • -
  • Remove rcedit dependency, move daily ico dependency to props file (#13123)
  • -
  • Bump NJsonSchema from 10.1.23 to 10.1.24 (#13214)
  • -
  • Update .NET SDK version from 5.0.100-preview.7.20364.3 to 5.0.100-preview.7.20366.2 (#13192)
  • -
  • Add support for installing arm64 MSIX package. (#13043) (Thanks @77!)
  • -
  • Fix Azure file copy issues in release build (#13182)
  • -
  • Update .NET SDK version from 5.0.100-preview.7.20358.6 to 5.0.100-preview.7.20364.3 (#13155)
  • -
  • Fix Azure file copy break in Azure DevOps (#13173)
  • -
  • Bump Xunit.SkippableFact from 1.4.8 to 1.4.13 (#13143)
  • -
  • Add new chibi svg version of the avatar (#13160) (Thanks @WorrenB!)
  • -
  • Refactor MSI code to make it easier to add a WiX exe installer (#13139)
  • -
  • Disable ReadyToRun for debug build (#13144) (Thanks @iSazonov!)
  • -
  • Add new chibi version of the avatar (#13140)
  • -
  • Update .NET SDK version from 5.0.100-preview.7.20356.2 to 5.0.100-preview.7.20358.6 (#13134) (Thanks @github-actions[bot]!)
  • -
  • Update .NET SDK version from 5.0.100-preview.6.20318.15 to 5.0.100-preview.7.20356.2 (#13125) (Thanks @github-actions[bot]!)
  • +
  • Disable implicit namespace imports for test projects (#15895)
  • +
  • Update language version to 10 and fix related issues (#15886)
  • +
  • Update CodeQL workflow to use Ubuntu 18.04 (#15868)
  • +
  • Bump the version of various packages (#15944, #15934, #15935, #15891, #15812, #15822) (Thanks @xtqqczze!)
### Documentation and Help Content -- Fix/clarify instructions for running Start-PSPester tests (#13373) -- Improve inline documentation for `VerbInfo` (#13265) (Thanks @yecril71pl!) -- Improve the wording of inline comments in the help system (#13274) (Thanks @yecril71pl!) -- Correct grammar in `README.md` and other docs (#13269) (Thanks @tasnimzotder!) -- Add "GitHub Actions Python builds" to `ADOPTERS.md` (#13228) (Thanks @brcrista!) -- Update change logs for `6.2.x` and `7.0.x` (#13194) -- Update `README.md` and `metadata.json` for the v7.0.3 release (#13187) +- Update `README` and `metadata files` for release `v7.2.0-preview.8` (#15819) +- Update change logs for 7.0.7 and 7.1.4 (#15921) +- Fix spelling in XML docs (#15939) (Thanks @slowy07!) +- Update PowerShell Committee members (#15837) -[7.1.0-preview.6]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.5...v7.1.0-preview.6 +[7.2.0-preview.9]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.8...v7.2.0-preview.9 -## [7.1.0-preview.5] - 2020-07-06 +## [7.2.0-preview.8] - 2021-07-22 ### Engine Updates and Fixes -- Ensure assemblies listed in the module manifest `FileList` field are not loaded (#12968) +- Add a Windows mode to `$PSNativeCommandArgumentPassing` that allows some commands to use legacy argument passing (#15408) +- Use `nameof` to get parameter names when creating `ArgumentNullException` (#15604) (Thanks @gukoff!) +- Test if a command is 'Out-Default' more thoroughly for transcribing scenarios (#15653) +- Add `Microsoft.PowerShell.Crescendo` to telemetry allow list (#15372) + +### General Cmdlet Updates and Fixes + +- Use `$PSStyle.Formatting.FormatAccent` for `Format-List` and `$PSStyle.Formatting.TableHeader` for `Format-Table` output (#14406) +- Highlight using error color the exception `Message` and underline in `PositionMessage` for `Get-Error` (#15786) +- Implement a completion for View parameter of format cmdlets (#14513) (Thanks @iSazonov!) +- Add support to colorize `FileInfo` file names (#14403) +- Don't serialize to JSON ETS properties for `DateTime` and `string` types (#15665) +- Fix `HyperVSocketEndPoint.ServiceId` setter (#15704) (Thanks @xtqqczze!) +- Add `DetailedView` to `$ErrorView` (#15609) ### Code Cleanup @@ -246,84 +246,106 @@

We thank the following contributors!

-

@xtqqczze

+

@iSazonov, @xtqqczze

    -
  • Code performance fixes (#12956) (Thanks @xtqqczze!)
  • +
  • Remove consolehost.proto file (#15741) (Thanks @iSazonov!)
  • +
  • Implement IDisposable for ConvertToJsonCommand (#15787) (Thanks @xtqqczze!)
  • +
  • Fix IDisposable implementation for CommandPathSearch (#15793) (Thanks @xtqqczze!)
  • +
  • Delete IDE dispose analyzer rules (#15798) (Thanks @xtqqczze!)
  • +
  • Seal private classes (#15725) (Thanks @xtqqczze!)
  • +
  • Enable IDE0029: UseCoalesceExpression (#15770) (Thanks @xtqqczze!)
  • +
  • Enable IDE0070: UseSystemHashCode (#15715) (Thanks @xtqqczze!)
  • +
  • Enable IDE0030: UseCoalesceExpressionForNullable (#14289) (Thanks @xtqqczze!)
  • +
  • Fix CA1846 and CA1845 for using AsSpan instead of Substring (#15738)
  • +
  • Use List<T>.RemoveAll to avoid creating temporary list (#15686) (Thanks @xtqqczze!)
  • +
  • Enable IDE0044: MakeFieldReadonly (#13880) (Thanks @xtqqczze!)
  • +
  • Disable IDE0130 (#15728) (Thanks @xtqqczze!)
  • +
  • Make classes sealed (#15675) (Thanks @xtqqczze!)
  • +
  • Enable CA1043: Use integral or string argument for indexers (#14467) (Thanks @xtqqczze!)
  • +
  • Enable CA1812 (#15674) (Thanks @xtqqczze!)
  • +
  • Replace Single with First when we know the element count is 1 (#15676) (Thanks @xtqqczze!)
  • +
  • Skip analyzers for Microsoft.Management.UI.Internal (#15677) (Thanks @xtqqczze!)
  • +
  • Fix CA2243: Attribute string literals should parse correctly (#15622) (Thanks @xtqqczze!)
  • +
  • Enable CA1401 (#15621) (Thanks @xtqqczze!)
  • +
  • Fix CA1309: Use ordinal StringComparison in Certificate Provider (#14352) (Thanks @xtqqczze!)
  • +
  • Fix CA1839: Use Environment.ProcessPath (#15650) (Thanks @xtqqczze!)
  • +
  • Add new analyzer rules (#15620) (Thanks @xtqqczze!)
### Tools -- Add missing `.editorconfig` settings present in `dotnet/runtime` (#12871) (Thanks @xtqqczze!) +- Add `SkipRoslynAnalyzers` parameter to `Start-PSBuild` (#15640) (Thanks @xtqqczze!) +- Create issue template for issues updating PowerShell through Windows update. (#15700) +- Add `DocumentationAnalyzers` to build (#14336) (Thanks @xtqqczze!) +- Convert GitHub issue templates to modern forms (#15645) ### Tests -- Add new test for `Format-Custom` to avoid data loss (#11393) (Thanks @iSazonov!) +- Add more tests for `ConvertFrom-Json` (#15706) (Thanks @strawgate!) +- Update `glob-parent` and `hosted-git-info` test dependencies (#15643) ### Build and Packaging Improvements
- - -

Fixed upgrade code in MSI package.

+ +Update .NET to version v6.0.0-preview.6 +
    -
  • Change log for v7.1.0-preview.5 (Internal 11880)
  • -
  • Fix Path for the Preview MSI (#13070)
  • -
  • Correct stable and preview upgrade codes for MSI (#13036)
  • -
  • Changelog for `v7.1.0-preview.4` (Internal 11841)
  • -
  • Fix NuGet package compliance issues (#13045)
  • -
  • Bump xunit.runner.visualstudio from 2.4.1 to 2.4.2 (#12874)
  • -
  • Bump NJsonSchema from `10.1.21` to `10.1.23` (#13032) (#13022)
  • +
  • Add new package name for osx-arm64 (#15813)
  • +
  • Prefer version when available for dotnet-install (#15810)
  • +
  • Make warning about MU being required dynamic (#15776)
  • +
  • Add Start-PSBootstrap before running tests (#15804)
  • +
  • Update to .NET 6 Preview 6 and use crossgen2 (#15763)
  • +
  • Enable ARM64 packaging for macOS (#15768)
  • +
  • Make Microsoft Update opt-out/in check boxes work (#15784)
  • +
  • Add Microsoft Update opt out to MSI install (#15727)
  • +
  • Bump NJsonSchema from 10.4.4 to 10.4.5 (#15769)
  • +
  • Fix computation of SHA512 checksum (#15736)
  • +
  • Update the script to use quality parameter for dotnet-install (#15731)
  • +
  • Generate SHA512 checksum file for all packages (#15678)
  • +
  • Enable signing daily release build with lifetime certificate (#15642)
  • +
  • Update metadata and README for 7.2.0-preview.7 (#15593)
### Documentation and Help Content -- Fix links for MSI packages to point to `7.1.0-preview.3` (#13056) -- Add update `packages.microsoft.com` step to distribution request template. (#13008) -- Update `windows-core.md` (#13053) (Thanks @xtqqczze!) -- Add `@rjmholt` to maintainers list (#13033) -- Update docs for `v7.1.0-preview.4` release (#13028) +- Fix broken RFC links (#15807) +- Add to bug report template getting details from `Get-Error` (#15737) +- Update issue templates to link to new docs (#15711) +- Add @jborean93 to Remoting Working Group (#15683) -## [7.1.0-preview.4] - 2020-06-25 +[7.2.0-preview.8]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.7...v7.2.0-preview.8 + +## [7.2.0-preview.7] - 2021-06-17 ### Breaking Changes -- Make the switch parameter `-Qualifier` not positional for `Split-Path` (#12960) (Thanks @yecril71pl!) -- Resolve the working directory as literal path for `Start-Process` when it's not specified (#11946) (Thanks @NoMoreFood!) -- Make `-OutFile` parameter in web cmdlets to work like `-LiteralPath` (#11701) (Thanks @iSazonov!) +- Remove PSDesiredStateConfiguration v2.0.5 module and published it to the PowerShell Gallery (#15536) ### Engine Updates and Fixes -- Ensure null-coalescing LHS is evaluated only once (#12667) -- Fix path handling bug in `PSTask` (#12554) (Thanks @IISResetMe!) -- Remove extra line before formatting group (#12163) (Thanks @iSazonov!) -- Make module formatting not generate error with strict mode (#11943) -- Adding more ETW logs to WSMan plugin (#12798) (Thanks @krishnayalavarthi!) -- Restrict loading of `amsi.dll` to `system32` folder (#12730) +- Fix splatting being treated as positional parameter in completions (#14623) (Thanks @MartinGC94!) +- Prevent PowerShell from crashing when a telemetry mutex can't be created (#15574) (Thanks @gukoff!) +- Ignore all exceptions when disposing an instance of a subsystem implementation (#15511) +- Wait for SSH exit when closing remote connection (#14635) (Thanks @dinhngtu!) + +### Performance + +- Retrieve `ProductVersion` using informational version attribute in `AmsiUtils.Init()` (#15527) (Thanks @Fs00!) ### General Cmdlet Updates and Fixes -- Fix `NullReferenceException` in `CommandSearcher.GetNextCmdlet` (#12659) (Thanks @powercode!) -- Prevent `NullReferenceException` in Unix computer cmdlets with test hooks active (#12651) (Thanks @vexx32!) -- Fix issue in `Select-Object` where `Hashtable` members (e.g. `Keys`) cannot be used with `-Property` or `-ExpandProperty` (#11097) (Thanks @vexx32!) -- Fix conflicting shorthand switch `-w` for pwsh (#12945) -- Rename the `CimCmdlet` resource file (#12955) (Thanks @iSazonov!) -- Remove use of `Test-Path` in `ConciseView` (#12778) -- Flag `default` switch statement condition clause as keyword (#10487) (Thanks @msftrncs!) -- Add parameter `SchemaFile` to `Test-Json` cmdlet (#11934) (Thanks @beatcracker!) -- Bring back Certificate provider parameters (#10622) (Thanks @iSazonov!) -- Fix `New-Item` to create symbolic link to relative path target (#12797) (Thanks @iSazonov!) -- Add `CommandLine` property to Process (#12288) (Thanks @iSazonov!) -- Adds `-MaskInput` parameter to `Read-Host` (#10908) (Thanks @davinci26!) -- Change `CimCmdlets` to use `AliasAttribute` (#12617) (Thanks @thlac!) +- Fix retrieving dynamic parameters from provider even if globbed path returns no results (#15525) +- Revert "Enhance Remove-Item to work with OneDrive (#15260)" due to long path issue (#15546) ### Code Cleanup @@ -332,56 +354,23 @@

We thank the following contributors!

-

@xtqqczze, @sethvs, @romero126, @kvprasoon, @powercode

+

@octos4murai, @iSazonov, @Fs00

    -
  • Use nameof operator (#12716) (Thanks @xtqqczze!)
  • -
  • Fix comments in Mshexpression.cs (#12711) (Thanks @sethvs!)
  • -
  • Formatting: remove duplicate semicolons (#12666) (Thanks @xtqqczze!)
  • -
  • Replace SortedList with Generic.SortedList<TKey,TValue> (#12954) (Thanks @xtqqczze!)
  • -
  • Use HashSet instead of Hashtable with null values (#12958) (Thanks @xtqqczze!)
  • -
  • Rename CopyItem.Tests.ps1 to Copy-Item.Tests.ps1 to match other tests (#10701) (Thanks @romero126!)
  • -
  • Fix RCS1114: Remove redundant delegate creation (#12917) (Thanks @xtqqczze!)
  • -
  • Code redundancy fixes (#12916) (Thanks @xtqqczze!)
  • -
  • Update the PowerShell modules to use the new Help URI (#12686)
  • -
  • Reorder modifiers according to preferred order (#12864) (Thanks @xtqqczze!)
  • -
  • Expand numberOfPowershellRefAssemblies list capacity (#12840) (Thanks @xtqqczze!)
  • -
  • Add readonly modifier to internal static members (#11777) (Thanks @xtqqczze!)
  • -
  • cleanup: Use coalesce expression (#12829) (Thanks @xtqqczze!)
  • -
  • Add missing assessibility modifiers (#12820) (Thanks @xtqqczze!)
  • -
  • Use t_ naming convention for ThreadStatic members (#12826) (Thanks @xtqqczze!)
  • -
  • Formatting: Add empty line between declarations (#12824) (Thanks @xtqqczze!)
  • -
  • Clarify defaultRefAssemblies list capacity in AddType.cs (#12520) (Thanks @xtqqczze!)
  • -
  • Fixing "Double "period" (..) in message for System.InvalidOperationException" (#12758) (Thanks @kvprasoon!)
  • -
  • Rethrow to preserve stack details for better maintainability (#12723) (Thanks @xtqqczze!)
  • -
  • Delete license.rtf (#12738) (Thanks @xtqqczze!)
  • -
  • Nullable annotations for CommandSearcher (#12733) (Thanks @powercode!)
  • -
  • Redundancy: Remove 'partial' modifier from type with a single part (#12725) (Thanks @xtqqczze!)
  • -
  • Remove phrase 'All rights reserved' from Microsoft copyright statements (#12722) (Thanks @xtqqczze!)
  • -
  • IDictionary -> IDictionary<string, FunctionInfo> for FunctionTable (#12658) (Thanks @powercode!)
  • +
  • Correct parameter name passed to exception in PSCommand constructor (#15580) (Thanks @octos4murai!)
  • +
  • Enable nullable: System.Management.Automation.ICommandRuntime (#15566) (Thanks @iSazonov!)
  • +
  • Clean up code regarding AppDomain.CreateDomain and AppDomain.Unload (#15554)
  • +
  • Replace ProcessModule.FileName with Environment.ProcessPath and remove PSUtils.GetMainModule (#15012) (Thanks @Fs00!)
-### Tools - -- Use correct isError parameter with Write-Log (#12989) -- Disable `NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter` rule in `StyleCop` (#12855) (Thanks @xtqqczze!) -- Add @TylerLeonhardt to PowerShell team list to correct changelog generation (#12927) -- Enable the upload of `ETW` traces to `CLR CAP` in Windows daily build (#12890) -- Prevent GitHub workflow for daily dotnet build updates from running in forks (#12763) (Thanks @bergmeister!) -- Add GitHub action for PR creation and `Wix` file generation logic (#12748) - ### Tests -- Remove duplicate tests from `Measure-Object.Tests.ps1` (#12683) (Thanks @sethvs!) -- Fix tests to not write errors to console (#13010) -- Make sure tabcompletion tests run (#12981) -- Remove dependency on DNS for `Test-Connection` tests on macOS (#12943) -- Restore `markdownlint` tests (#12549) (Thanks @xtqqczze!) -- Wrap tests in pester blocks (#12700) (Thanks @xtqqczze!) +- Fix `Start-Benchmarking` to put `TargetPSVersion` and `TargetFramework` in separate parameter sets (#15508) +- Add `win-x86` test package to the build (#15517) ### Build and Packaging Improvements @@ -390,86 +379,64 @@

We thank the following contributors!

-

@iSazonov, @kvprasoon, @Saancreed, @heaths, @xtqqczze

+

@schuelermine

    -
  • Update Distribution_Request.md
  • -
  • Bump NJsonSchema from 10.1.15 to 10.1.16 (#12685)
  • -
  • Disable uploading Symbols package (#12687)
  • -
  • Update .NET SDK version from 5.0.100-preview.5.20279.10 to 5.0.100-preview.6.20318.15 (#13018)
  • -
  • Remove component ref when re-generating the wix file (#13019)
  • -
  • Make sure icons are added to MSI staging folder (#12983)
  • -
  • Update DotnetRutimeMetadata.json to point to preview 6 (#12972)
  • -
  • Bump PSReadLine from 2.0.1 to 2.0.2 (#12909)
  • -
  • Bump NJsonSchema from 10.1.18 to 10.1.21 (#12944)
  • -
  • Check if Azure Blob exists before overwriting (#12921)
  • -
  • Enable skipped tests (#12894) (Thanks @iSazonov!)
  • -
  • Fix break in package build by pinning ffi version to 1.12 (#12889)
  • -
  • Upgrade APIScan version (#12876)
  • -
  • Make contributors unique in Release notes (#12878) (Thanks @kvprasoon!)
  • -
  • Update Linux daily CI to run in a single agent & collect traces (#12866)
  • -
  • Update .NET SDK version from 5.0.100-preview.5.20278.13 to 5.0.100-preview.5.20279.10 (#12844) (Thanks @github-actions[bot]!)
  • -
  • Sign the MSIX files for the store (#12582)
  • -
  • Update the CI builds (#12830)
  • -
  • Update .NET SDK version from 5.0.100-preview.5.20272.6 to 5.0.100-preview.5.20278.13 (#12772) (Thanks @github-actions[bot]!)
  • -
  • Allow use of build module on unknown Linux distros (#11146) (Thanks @Saancreed!)
  • -
  • Fix MSI upgrade and shortcut issues (#12792) (Thanks @heaths!)
  • -
  • Bump NJsonSchema from 10.1.17 to 10.1.18 (#12812)
  • -
  • Update .NET SDK version from 5.0.100-preview.5.20269.29 to 5.0.100-preview.5.20272.6 (#12759) (Thanks @github-actions[bot]!)
  • -
  • Bump NJsonSchema from 10.1.16 to 10.1.17 (#12761)
  • -
  • Update to dotnet SDK 5.0.0-preview.5.20268.9 (#12740)
  • -
  • Remove assets\license.rtf (#12721) (Thanks @xtqqczze!)
  • -
  • Bump Microsoft.CodeAnalysis.CSharp from 3.5.0 to 3.6.0 (#12731)
  • +
  • Update README.md and metadata.json for version 7.2.0-preview.6 (#15464)
  • +
  • Make sure GA revision increases from RC and Preview releases (#15558)
  • +
  • Remove SupportsShouldProcess from Start-PSBootstrap in build.psm1 (#15491) (Thanks @schuelermine!)
  • +
  • Update DotnetMetadataRuntime.json next channel to take daily build from .NET preview 5 (#15518)
  • +
  • Fix deps.json update in the release pipeline (#15486)
### Documentation and Help Content -- Update `README` and `metadata` files for next release (#12717) -- Update `README.md` removing experimental status of `Arm` builds, but `Win-Arm64` is still preview for Stable release. (#12707) -- Add link to Github compare in changelog (#12713) (Thanks @xtqqczze!) -- Added missing changelog for v7.1.0-preview.2 (#12665) -- Update required Visual Studio version in build docs (#12628) (Thanks @xtqqczze!) -- minor update to Distribution_Request.md (#12705) (Thanks @kilasuit!) -- Update docs.microsoft.com links (#12653) (Thanks @xtqqczze!) -- Update change log for `6.2.5` release (#12670) -- Update `README.md` and `metadata.json` for next release (#12668) -- Merge 7.0.1 change log (#12669) -- Remove markdown unused definitions (#12656) (Thanks @xtqqczze!) -- Add HoloLens to list of PowerShell adopters (#12940) (Thanks @reynoldsbd!) -- Update `README.md` and `metadata.json` for next releases (#12939) -- Fix broken link in `README.md` (#12887) (Thanks @xtqqczze!) -- Minor typo corrections in Distribution Request Issue Templates (#12744) (Thanks @corbob!) -- Correct 'review-for-comments' in `Governance.md` (#11035) (Thanks @MarvTheRobot!) -- Fix markdown ordered lists (#12657) (Thanks @xtqqczze!) -- Fix broken `docs.microsoft.com` link (#12776) (Thanks @xtqqczze!) -- Replace link to Slack with link to PowerShell Virtual User Group (#12786) (Thanks @xtqqczze!) -- Update `LICENSE.txt` so that it's recognized as MIT (#12729) - -## [7.1.0-preview.3] - 2020-05-14 +- Add new members to Engine and Cmdlet Working Groups document (#15560) +- Update the `mdspell` command to exclude the folder that should be ignored (#15576) +- Replace 'User Voice' with 'Feedback Hub' in `README.md` (#15557) +- Update Virtual User Group chat links (#15505) (Thanks @Jaykul!) +- Fix typo in `FileSystemProvider.cs` (#15445) (Thanks @eltociear!) +- Add `PipelineStoppedException` notes to PowerShell API (#15324) +- Updated governance on Working Groups (WGs) (#14603) +- Correct and improve XML documentation comments on `PSCommand` (#15568) (Thanks @octos4murai!) -### Breaking Changes +[7.2.0-preview.7]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.6...v7.2.0-preview.7 -- Fix string parameter binding for `BigInteger` numeric literals (#11634) (Thanks @vexx32!) +## [7.2.0-preview.6] - 2021-05-27 -### Engine Updates and Fixes +### Experimental Features -- Set correct `PSProvider` full name at module load time (#11813) (Thanks @iSazonov!) +- [Breaking Change] Update prediction interface to provide additional feedback to a predictor plugin (#15421) -### Experimental Features +### Performance -- Support passing `PSPath` to native commands (#12386) +- Avoid collecting logs in buffer if a pipeline execution event is not going to be logged (#15350) +- Avoid allocation in `LanguagePrimitives.UpdateTypeConvertFromTypeTable` (#15168) (Thanks @xtqqczze!) +- Replace `Directory.GetDirectories` with `Directory.EnumerateDirectories` to avoid array allocations (#15167) (Thanks @xtqqczze!) +- Use `List.ConvertAll` instead of `LINQ` (#15140) (Thanks @xtqqczze!) ### General Cmdlet Updates and Fixes -- Fix incorrect index in format string in ParameterBinderBase (#12630) (Thanks @powercode!) -- Copy the `CommandInfo` property in `Command.Clone()` (#12301) (Thanks @TylerLeonhardt!) -- Apply `-IncludeEqual` in `Compa-Object` when `-ExcludeDifferent` is specified (#12317) (Thanks @davidseibel!) -- Change `Get-FileHash` to close file handles before writing output (#12474) (Thanks @HumanEquivalentUnit!) -- Fix inconsistent exception message in `-replace` operator (#12388) (Thanks @jackdcasey!) +- Use `AllocConsole` before initializing CLR to ensure codepage is correct for WinRM remoting (PowerShell/PowerShell-Native#70) (Thanks @jborean93!) +- Add completions for `#requires` statements (#14596) (Thanks @MartinGC94!) +- Add completions for comment-based help keywords (#15337) (Thanks @MartinGC94!) +- Move cross platform DSC code to a PowerShell engine subsystem (#15127) +- Fix `Minimal` progress view to handle activity that is longer than console width (#15264) +- Handle exception if ConsoleHost tries to set cursor out of bounds because screen buffer changed (#15380) +- Fix `NullReferenceException` in DSC `ClearCache()` (#15373) +- Update `ControlSequenceLength` to handle colon as a virtual terminal parameter separator (#14942) +- Update the summary comment for `StopTranscriptCmdlet.cs` (#15349) (Thanks @dbaileyut!) +- Remove the unusable alias `d` for the `-Directory` parameter from `Get-ChildItem` (#15171) (Thanks @kvprasoon!) +- Fix tab completion for un-localized `about` topics (#15265) (Thanks @MartinGC94!) +- Remove the unneeded SSH stdio handle workaround (#15308) +- Add `LoadAssemblyFromNativeMemory` API to load assemblies from memory in a native PowerShell host (#14652) (Thanks @awakecoding!) +- Re-implement `Remove-Item` OneDrive support (#15260) (Thanks @iSazonov!) +- Kill native processes in pipeline when pipeline is disposed on Unix (#15287) +- Default to MTA on Windows platforms where STA is not supported (#15106) ### Code Cleanup @@ -478,112 +445,81 @@

We thank the following contributors!

-

@xtqqczze, @RDIL, @powercode, @xtqqczze, @xtqqczze

+

@xtqqczze, @powercode, @bcwood

    -
  • Replace Unicode non-breaking space character with space (#12576) (Thanks @xtqqczze!)
  • -
  • Remove unused New-DockerTestBuild.ps1 (#12610) (Thanks @RDIL!)
  • -
  • Annotate Assert methods for better code analysis (#12618) (Thanks @powercode!)
  • -
  • Use correct casing for cmdlet names and parameters in *.ps1 files throughout the codebase (#12584) (Thanks @xtqqczze!)
  • -
  • Document why PackageVersion is used in PowerShell.Common.props (#12523) (Thanks @xtqqczze!)
  • +
  • Enable nullable in some classes (#14185, #14177, #14159, #14191, #14162, #14150, #14156, #14161, #14155, #14163, #14181, #14157, #14151) (Thanks @powercode!)
  • +
  • Annotate ThrowTerminatingError with DoesNotReturn attribute (#15352) (Thanks @powercode!)
  • +
  • Use GetValueOrDefault() for nullable PSLanguageMode (#13849) (Thanks @bcwood!)
  • +
  • Enable SA1008: Opening parenthesis should be spaced correctly (#14242) (Thanks @xtqqczze!)
### Tools -- Update `@PoshChan` config to include `SSH` (#12526) (Thanks @vexx32!) -- Update log message in `Start-PSBootstrap` (#12573) (Thanks @xtqqczze!) -- Add the `.NET SDK` installation path to the current process path in `tools/UpdateDotnetRuntime.ps1` (#12525) +- Add `winget` release script (#15050) ### Tests -- Make CIM tab completion test case insensitive (#12636) -- Mark ping tests as Pending due to stability issues in macOS (#12504) +- Enable cross-runtime benchmarking to compare different .NET runtimes (#15387) (Thanks @adamsitnik!) +- Add the performance benchmark project for PowerShell performance testing (#15242) ### Build and Packaging Improvements
- -

We thank the following contributors!

-

@jcotton42, @iSazonov, @iSazonov, @iSazonov

- +Update .NET to version v6.0.0-preview.4
    -
  • Update build to use the new .NET SDK 5.0.100-preview.4.20258.7 (#12637)
  • -
  • Bump NJsonSchema from 10.1.14 to 10.1.15 (#12608)
  • -
  • Bump NJsonSchema from 10.1.13 to 10.1.14 (#12598)
  • -
  • Bump NJsonSchema from 10.1.12 to 10.1.13 (#12583)
  • -
  • Update the build to sign any unsigned files as 3rd party Dlls (#12581)
  • -
  • Update .NET SDK to 5.0.100-preview.4.20229.10 (#12538)
  • -
  • Add ability to Install-Dotnet to specify directory (#12469)
  • -
  • Allow / in relative paths for using module (#7424) (#12492) (Thanks @jcotton42!)
  • -
  • Update dotnet metadata for next channel for automated updates (#12502)
  • -
  • Bump .NET to 5.0.0-preview.4 (#12507)
  • -
  • Bump Microsoft.ApplicationInsights from 2.13.1 to 2.14.0 (#12479)
  • -
  • Bump PackageManagement from 1.4.6 to 1.4.7 in /src/Modules (#12506)
  • -
  • Bump Xunit.SkippableFact from 1.3.12 to 1.4.8 (#12480)
  • -
  • Fix quotes to allow variable expansion (#12512)
  • -
  • Use new TargetFramework as net5.0 in packaging scripts (#12503) (Thanks @iSazonov!)
  • -
  • Use new value for TargetFramework as net5.0 instead of netcoreapp5.0 (#12486) (Thanks @iSazonov!)
  • -
  • Disable PublishReadyToRun for framework dependent packages (#12450)
  • -
  • Add dependabot rules to ignore updates from .NET (#12466)
  • -
  • Update README.md and metadata.json for upcoming release (#12441)
  • -
  • Turn on ReadyToRun (#12361) (Thanks @iSazonov!)
  • -
  • Add summary to compressed sections of change log (#12429)
  • +
  • Suppress prompting when uploading the msixbundle package to blob (#15227)
  • +
  • Update to .NET preview 4 SDK (#15452)
  • +
  • Update AppxManifest.xml with newer OS version to allow PowerShell installed from Windows Store to make system-level changes (#15375)
  • +
  • Ensure the build works when PSDesiredStateConfiguration module is pulled in from PSGallery (#15355)
  • +
  • Make sure daily release tag does not change when retrying failures (#15286)
  • +
  • Improve messages and behavior when there's a problem in finding zip files (#15284)
### Documentation and Help Content -- Add link to life cycle doc to distribution request template (#12638) -- Update TFM reference in build docs (#12514) (Thanks @xtqqczze!) -- Fix broken link for blogs in documents (#12471) +- Add documentation comments section to coding guidelines (#14316) (Thanks @xtqqczze!) + +[7.2.0-preview.6]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.5...v7.2.0-preview.6 -## [7.1.0-preview.2] - 2020-04-23 +## [7.2.0-preview.5] - 2021-04-14 ### Breaking Changes -- On Windows, `Start-Process` creates a process environment with - all the environment variables from current session, - using `-UseNewEnvironment` creates a new default process environment (#10830) (Thanks @iSazonov!) -- Do not wrap return result to `PSObject` when converting ScriptBlock to delegate (#10619) +- Make PowerShell Linux deb and RPM packages universal (#15109) +- Enforce AppLocker Deny configuration before Execution Policy Bypass configuration (#15035) +- Disallow mixed dash and slash in command line parameter prefix (#15142) (Thanks @davidBar-On!) + +### Experimental Features + +- `PSNativeCommandArgumentPassing`: Use `ArgumentList` for native executable invocation (breaking change) (#14692) ### Engine Updates and Fixes -- Allow case insensitive paths for determining `PSModulePath` (#12192) -- Add PowerShell version 7.0 to compatible version list (#12184) -- Discover assemblies loaded by `Assembly.Load(byte[])` and `Assembly.LoadFile` (#12203) +- Add `IArgumentCompleterFactory` for parameterized `ArgumentCompleters` (#12605) (Thanks @powercode!) ### General Cmdlet Updates and Fixes -- Fix `WinCompat` module loading to treat PowerShell 7 modules with higher priority (#12269) -- Implement `ForEach-Object -Parallel` runspace reuse (#12122) -- Fix `Get-Service` to not modify collection while enumerating it (#11851) (Thanks @NextTurn!) -- Clean up the IPC named pipe on PowerShell exit (#12187) -- Fix `` detection regex in web cmdlets (#12099) (Thanks @vexx32!) -- Allow shorter signed hex literals with appropriate type suffixes (#11844) (Thanks @vexx32!) -- Update `UseNewEnvironment` parameter behavior of `Start-Process` cmdlet on Windows (#10830) (Thanks @iSazonov!) -- Add `-Shuffle` switch to `Get-Random` command (#11093) (Thanks @eugenesmlv!) -- Make `GetWindowsPowerShellModulePath` compatible with multiple PS installations (#12280) -- Fix `Start-Job` to work on systems that don't have Windows PowerShell registered as default shell (#12296) -- Specifying an alias and `-Syntax` to `Get-Command` returns the aliased commands syntax (#10784) (Thanks @ChrisLGardner!) -- Make CSV cmdlets work when using `-AsNeeded` and there is an incomplete row (#12281) (Thanks @iSazonov!) -- In local invocations, do not require `-PowerShellVersion 5.1` for `Get-FormatData` in order to see all format data. (#11270) (Thanks @mklement0!) -- Added Support For Big Endian `UTF-32` (#11947) (Thanks @NoMoreFood!) -- Fix possible race that leaks PowerShell object dispose in `ForEach-Object -Parallel` (#12227) -- Add `-FromUnixTime` to `Get-Date` to allow Unix time input (#12179) (Thanks @jackdcasey!) -- Change default progress foreground and background colors to provide improved contrast (#11455) (Thanks @rkeithhill!) -- Fix `foreach -parallel` when current drive is not available (#12197) -- Do not wrap return result to `PSObject` when converting `ScriptBlock` to `delegate` (#10619) -- Don't write DNS resolution errors on `Test-Connection -Quiet` (#12204) (Thanks @vexx32!) -- Use dedicated threads to read the redirected output and error streams from the child process for out-of-proc jobs (#11713) +- Fix SSH remoting connection never finishing with misconfigured endpoint (#15175) +- Respect `TERM` and `NO_COLOR` environment variables for `$PSStyle` rendering (#14969) +- Use `ProgressView.Classic` when Virtual Terminal is not supported (#15048) +- Fix `Get-Counter` issue with `-Computer` parameter (#15166) (Thanks @krishnayalavarthi!) +- Fix redundant iteration while splitting lines (#14851) (Thanks @hez2010!) +- Enhance `Remove-Item -Recurse` to work with OneDrive (#14902) (Thanks @iSazonov!) +- Change minimum depth to 0 for `ConvertTo-Json` (#14830) (Thanks @kvprasoon!) +- Allow `Set-Clipboard` to accept empty string (#14579) +- Turn on and off `DECCKM` to modify keyboard mode for Unix native commands to work correctly (#14943) +- Fall back to `CopyAndDelete()` when `MoveTo()` fails due to an `IOException` (#15077) ### Code Cleanup @@ -592,27 +528,31 @@

We thank the following contributors!

-

@ShaydeNofziger, @RDIL

+

@xtqqczze, @iSazonov, @ZhiZe-ZG

    -
  • Fix erroneous comment in tokenizer.cs (#12206) (Thanks @ShaydeNofziger!)
  • -
  • Fix terms checker issues (#12189)
  • -
  • Update copyright notice to latest guidance (#12190)
  • -
  • CodeFactor cleanup (#12251) (Thanks @RDIL!)
  • +
  • Update .NET to 6.0.0-preview.3 (#15221)
  • +
  • Add space before comma to hosting test to fix error reported by SA1001 (#15224)
  • +
  • Add SecureStringHelper.FromPlainTextString helper method for efficient secure string creation (#14124) (Thanks @xtqqczze!)
  • +
  • Use static lambda keyword (#15154) (Thanks @iSazonov!)
  • +
  • Remove unnecessary Array -> List -> Array conversion in ProcessBaseCommand.AllProcesses (#15052) (Thanks @xtqqczze!)
  • +
  • Standardize grammar comments in Parser.cs (#15114) (Thanks @ZhiZe-ZG!)
  • +
  • Enable SA1001: Commas should be spaced correctly (#14171) (Thanks @xtqqczze!)
  • +
  • Refactor MultipleServiceCommandBase.AllServices (#15053) (Thanks @xtqqczze!)
### Tools -- Update .NET dependency update script to include test `csproj` files (#12372) -- Scripts to update to .NET prerelease version (#12284) +- Use Unix line endings for shell scripts (#15180) (Thanks @xtqqczze!) ### Tests -- Pin major Pester version to 4 to prevent breaking changes caused by upcoming release of v5 (#12262) (Thanks @bergmeister!) +- Add the missing tag in Host Utilities tests (#14983) +- Update `copy-props` version in `package.json` (#15124) ### Build and Packaging Improvements @@ -621,195 +561,523 @@

We thank the following contributors!

-

@rkitover, @bergmeister

+

@JustinGrote

+ +
+ +
    +
  • Fix yarn-lock for copy-props (#15225)
  • +
  • Make package validation regex accept universal Linux packages (#15226)
  • +
  • Bump NJsonSchema from 10.4.0 to 10.4.1 (#15190)
  • +
  • Make MSI and EXE signing always copy to fix daily build (#15191)
  • +
  • Sign internals of EXE package so that it works correctly when signed (#15132)
  • +
  • Bump Microsoft.NET.Test.Sdk from 16.9.1 to 16.9.4 (#15141)
  • +
  • Update daily release tag format to work with new Microsoft Update work (#15164)
  • +
  • Feature: Add Ubuntu 20.04 Support to install-powershell.sh (#15095) (Thanks @JustinGrote!)
  • +
  • Treat rebuild branches like release branches (#15099)
  • +
  • Update WiX to 3.11.2 (#15097)
  • +
  • Bump NJsonSchema from 10.3.11 to 10.4.0 (#15092)
  • +
  • Allow patching of preview releases (#15074)
  • +
  • Bump Newtonsoft.Json from 12.0.3 to 13.0.1 (#15084, #15085)
  • +
  • Update the minSize build package filter to be explicit (#15055)
  • +
  • Bump NJsonSchema from 10.3.10 to 10.3.11 (#14965)
  • +
+ + + +### Documentation and Help Content + +- Merge `7.2.0-preview.4` changes to master (#15056) +- Update `README` and `metadata.json` (#15046) +- Fix broken links for `dotnet` CLI (#14937) + +[7.2.0-preview.5]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.4...v7.2.0-preview.5 + +## [7.2.0-preview.4] - 2021-03-16 + +### Breaking Changes +- Fix `Get-Date -UFormat` `%G` and `%g` behavior (#14555) (Thanks @brianary!) + +### Engine Updates and Fixes + +- Update engine script signature validation to match `Get-AuthenticodeSignature` logic (#14849) +- Avoid array allocations from `GetDirectories` and `GetFiles` (#14327) (Thanks @xtqqczze!) + +### General Cmdlet Updates and Fixes + +- Add `UseOSCIndicator` setting to enable progress indicator in terminal (#14927) +- Re-enable VT mode on Windows after running command in `ConsoleHost` (#14413) +- Fix `Move-Item` for `FileSystemProvider` to use copy-delete instead of move for DFS paths (#14913) +- Fix `PromptForCredential()` to add `targetName` as domain (#14504) +- Update `Concise` `ErrorView` to not show line information for errors from script module functions (#14912) +- Remove the 32,767 character limit on the environment block for `Start-Process` (#14111) (Thanks @hbuckle!) +- Don't write possible secrets to verbose stream for web cmdlets (#14788) + +### Tools + +- Update `dependabot` configuration to V2 format (#14882) +- Add tooling issue slots in PR template (#14697) + +### Tests + +- Move misplaced test file to tests directory (#14908) (Thanks @MarianoAlipi!) +- Refactor MSI CI (#14753) + +### Build and Packaging Improvements + +
+ + +Update .NET to version 6.0.100-preview.2.21155.3
    -
  • Add the nuget.config from root to the temporary build folder (#12394)
  • -
  • Bump System.IO.Packaging (#12365)
  • -
  • Bump Markdig.Signed from 0.18.3 to 0.20.0 (#12379)
  • -
  • Bump to .NET 5 Preview 3 pre-release (#12353)
  • -
  • Bump PowerShellGet from 2.2.3 to 2.2.4 (#12342)
  • -
  • Linux: Initial support for Gentoo installations. (#11429) (Thanks @rkitover!)
  • -
  • Upgrade to .NET 5 Preview 2 (#12250) (Thanks @bergmeister!)
  • -
  • Fix the Sync PSGalleryModules to Artifacts build (#12277)
  • -
  • Bump PSReadLine from 2.0.0 to 2.0.1 (#12243)
  • -
  • Bump NJsonSchema from 10.1.11 to 10.1.12 (#12230)
  • -
  • Update change log generation script to support collapsible sections (#12214)
  • +
  • Update .NET to version 6.0.100-preview.2.21155.3 (#15007)
  • +
  • Bump Microsoft.PowerShell.Native to 7.2.0-preview.1 (#15030)
  • +
  • Create MSIX Bundle package in release pipeline (#14982)
  • +
  • Build self-contained minimal size package for Guest Config team (#14976)
  • +
  • Bump XunitXml.TestLogger from 3.0.62 to 3.0.66 (#14993) (Thanks @dependabot[bot]!)
  • +
  • Enable building PowerShell for Apple M1 runtime (#14923)
  • +
  • Fix the variable name in the condition for miscellaneous analysis CI (#14975)
  • +
  • Fix the variable usage in CI yaml (#14974)
  • +
  • Disable running markdown link verification in release build CI (#14971)
  • +
  • Bump Microsoft.CodeAnalysis.CSharp from 3.9.0-3.final to 3.9.0 (#14934) (Thanks @dependabot[bot]!)
  • +
  • Declare which variable group is used for checking the blob in the release build (#14970)
  • +
  • Update metadata and script to enable consuming .NET daily builds (#14940)
  • +
  • Bump NJsonSchema from 10.3.9 to 10.3.10 (#14933) (Thanks @dependabot[bot]!)
  • +
  • Use template that disables component governance for CI (#14938)
  • +
  • Add suppress for nuget multi-feed warning (#14893)
  • +
  • Bump NJsonSchema from 10.3.8 to 10.3.9 (#14926) (Thanks @dependabot[bot]!)
  • +
  • Add exe wrapper to release (#14881)
  • +
  • Bump Microsoft.ApplicationInsights from 2.16.0 to 2.17.0 (#14847)
  • +
  • Bump Microsoft.NET.Test.Sdk from 16.8.3 to 16.9.1 (#14895) (Thanks @dependabot[bot]!)
  • +
  • Bump NJsonSchema from 10.3.7 to 10.3.8 (#14896) (Thanks @dependabot[bot]!)
  • +
  • Disable codesign validation where the file type is not supported (#14885)
  • +
  • Fixing broken Experimental Feature list in powershell.config.json (#14858)
  • +
  • Bump NJsonSchema from 10.3.6 to 10.3.7 (#14855)
  • +
  • Add exe wrapper for Microsoft Update scenarios (#14737)
  • +
  • Install wget on CentOS 7 docker image (#14857)
  • +
  • Fix install-dotnet download (#14856)
  • +
  • Fix Bootstrap step in Windows daily test runs (#14820)
  • +
  • Bump NJsonSchema from 10.3.5 to 10.3.6 (#14818)
  • +
  • Bump NJsonSchema from 10.3.4 to 10.3.5 (#14807)
### Documentation and Help Content -- Add documentation for `WebResponseObject` and `BasicHtmlWebResponseObject` properties (#11876) (Thanks @kevinoid!) -- Add Windows 10 IoT Core reference in `Adopters.md` (#12266) (Thanks @parameshbabu!) -- Update `README.md` and `metadata.json` for `7.1.0-preview.1` (#12211) +- Update `README.md` and `metadata.json` for upcoming releases (#14755) +- Merge 7.1.3 and 7.0.6 Change log to master (#15009) +- Update `README` and `metadata.json` for releases (#14997) +- Update ChangeLog for `v7.1.2` release (#14783) +- Update ChangeLog for `v7.0.5` release (#14782) (Internal 14479) -## [7.1.0-preview.1] - 2020-03-26 +[7.2.0-preview.4]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.3...v7.2.0-preview.4 + +## [7.2.0-preview.3] - 2021-02-11 ### Breaking Changes -- Use invariant culture string conversion for `-replace` operator (#10954) (Thanks @iSazonov!) +- Fix `Get-Date -UFormat %u` behavior to comply with ISO 8601 (#14549) (Thanks @brianary!) ### Engine Updates and Fixes -- Revert the PRs that made `DBNull.Value` and `NullString.Value` treated as `$null` (#11648) +- Together with `PSDesiredStateConfiguration` `v3` module allows `Get-DscResource`, `Invoke-DscResource` and DSC configuration compilation on all platforms, supported by PowerShell (using class-based DSC resources). + +### Performance + +- Avoid array allocations from `Directory.GetDirectories` and `Directory.GetFiles`. (#14326) (Thanks @xtqqczze!) +- Avoid `string.ToLowerInvariant()` from `GetEnvironmentVariableAsBool()` to avoid loading libicu at startup (#14323) (Thanks @iSazonov!) +- Get PowerShell version in `PSVersionInfo` using assembly attribute instead of `FileVersionInfo` (#14332) (Thanks @Fs00!) + +### General Cmdlet Updates and Fixes + +- Suppress `Write-Progress` in `ConsoleHost` if output is redirected and fix tests (#14716) +- Experimental feature `PSAnsiProgress`: Add minimal progress bar using ANSI rendering (#14414) +- Fix web cmdlets to properly construct URI from body when using `-NoProxy` (#14673) +- Update the `ICommandPredictor` to provide more feedback and also make feedback easier to be correlated (#14649) +- Reset color after writing `Verbose`, `Debug`, and `Warning` messages (#14698) +- Fix using variable for nested `ForEach-Object -Parallel` calls (#14548) +- When formatting, if collection is modified, don't fail the entire pipeline (#14438) +- Improve completion of parameters for attributes (#14525) (Thanks @MartinGC94!) +- Write proper error messages for `Get-Command ' '` (#13564) (Thanks @jakekerr!) +- Fix typo in the resource string `ProxyURINotSupplied` (#14526) (Thanks @romero126!) +- Add support to `$PSStyle` for strikethrough and hyperlinks (#14461) +- Fix `$PSStyle` blink codes (#14447) (Thanks @iSazonov!) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @powercode

+ +
+ +
    +
  • Fix coding style issues: RCS1215, IDE0090, SA1504, SA1119, RCS1139, IDE0032 (#14356, #14341, #14241, #14204, #14442, #14443) (Thanks @xtqqczze!)
  • +
  • Enable coding style checks: CA2249, CA1052, IDE0076, IDE0077, SA1205, SA1003, SA1314, SA1216, SA1217, SA1213 (#14395, #14483, #14494, #14495, #14441, #14476, #14470, #14471, #14472) (Thanks @xtqqczze!)
  • +
  • Enable nullable in PowerShell codebase (#14160, #14172, #14088, #14154, #14166, #14184, #14178) (Thanks @powercode!)
  • +
  • Use string.Split(char) instead of string.Split(string) (#14465) (Thanks @xtqqczze!)
  • +
  • Use string.Contains(char) overload (#14368) (Thanks @xtqqczze!)
  • +
  • Refactor complex if statements (#14398) (Thanks @xtqqczze!)
  • +
+ +
+ +### Tools + +- Update script to use .NET 6 build resources (#14705) +- Fix the daily GitHub action (#14711) (Thanks @imba-tjd!) +- GitHub Actions: fix deprecated `::set-env` (#14629) (Thanks @imba-tjd!) +- Update markdown test tools (#14325) (Thanks @RDIL!) +- Upgrade `StyleCopAnalyzers` to `v1.2.0-beta.312` (#14354) (Thanks @xtqqczze!) + +### Tests + +- Remove packaging from daily Windows build (#14749) +- Update link to the Manning book (#14750) +- A separate Windows packaging CI (#14670) +- Update `ini` component version in test `package.json` (#14454) +- Disable `libmi` dependent tests for macOS. (#14446) + +### Build and Packaging Improvements + +
+ +
    +
  • Fix the NuGet feed name and URL for .NET 6
  • +
  • Fix third party signing for files in sub-folders (#14751)
  • +
  • Make build script variable an ArrayList to enable Add() method (#14748)
  • +
  • Remove old .NET SDKs to make dotnet restore work with the latest SDK in CI pipeline (#14746)
  • +
  • Remove outdated Linux dependencies (#14688)
  • +
  • Bump .NET SDK version to 6.0.0-preview.1 (#14719)
  • +
  • Bump NJsonSchema to 10.3.4 (#14714)
  • +
  • Update daily GitHub action to allow manual trigger (#14718)
  • +
  • Bump XunitXml.TestLogger to 3.0.62 (#14702)
  • +
  • Make universal deb package based on the deb package specification (#14681)
  • +
  • Add manual release automation steps and improve changelog script (#14445)
  • +
  • Fix release build to upload global tool packages to artifacts (#14620)
  • +
  • Port changes from the PowerShell v7.0.4 release (#14637)
  • +
  • Port changes from the PowerShell v7.1.1 release (#14621)
  • +
  • Updated README and metadata.json (#14401, #14606, #14612)
  • +
  • Do not push nupkg artifacts to MyGet (#14613)
  • +
  • Use one feed in each nuget.config in official builds (#14363)
  • +
  • Fix path signed RPMs are uploaded from in release build (#14424)
  • +
+ +
+ +### Documentation and Help Content + +- Update distribution support request template to point to .NET 5.0 support document (#14578) +- Remove security GitHub issue template (#14453) +- Add intent for using the Discussions feature in repo (#14399) +- Fix Universal Dashboard to refer to PowerShell Universal (#14437) +- Update document link because of HTTP 301 redirect (#14431) (Thanks @xtqqczze!) + +[7.2.0-preview.3]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.2...v7.2.0-preview.3 + +## [7.2.0-preview.2] - 2020-12-15 + +### Breaking Changes + +- Improve detection of mutable value types (#12495) (Thanks @vexx32!) +- Ensure `-PipelineVariable` is set for all output from script cmdlets (#12766) (Thanks @vexx32!) ### Experimental Features -- Use invariant culture string conversion for `-replace` operator (#10954) (Thanks @iSazonov!) +- `PSAnsiRendering`: Enable ANSI formatting via `$PSStyle` and support suppressing ANSI output (#13758) + +### Performance + +- Optimize `IEnumerable` variant of replace operator (#14221) (Thanks @iSazonov!) +- Refactor multiply operation for better performance in two `Microsoft.PowerShell.Commands.Utility` methods (#14148) (Thanks @xtqqczze!) +- Use `Environment.TickCount64` instead of `Datetime.Now` as the random seed for AppLocker test file content (#14283) (Thanks @iSazonov!) +- Avoid unnecessary array allocations when searching in GAC (#14291) (Thanks @xtqqczze!) +- Use `OrdinalIgnoreCase` in `CommandLineParser` (#14303) (Thanks @iSazonov!) +- Use `StringComparison.Ordinal` instead of `StringComparison.CurrentCulture` (#14298) (Thanks @iSazonov!) +- Avoid creating instances of the generated delegate helper class in `-replace` implementation (#14128) ### General Cmdlet Updates and Fixes -- Fix an operator preference order issue in binder code (#12075) (Thanks @DamirAinullin!) -- Fix `NullReferenceException` when binding common parameters of type `ActionPreference` (#12124) -- Fix default formatting for deserialized `MatchInfo` (#11728) (Thanks @iSazonov!) -- Use asynchronous streams in `Invoke-RestMethod` (#11095) (Thanks @iSazonov!) -- Address UTF-8 Detection In `Get-Content -Tail` (#11899) (Thanks @NoMoreFood!) -- Handle the `IOException` in `Get-FileHash` (#11944) (Thanks @iSazonov!) -- Change `PowerShell Core` to `PowerShell` in a resource string (#11928) (Thanks @alexandair!) -- Bring back `MainWindowTitle` in `PSHostProcessInfo` (#11885) (Thanks @iSazonov!) -- Miscellaneous minor updates to Windows Compatibility (#11980) -- Fix `ConciseView` to split `PositionMessage` using `[Environment]::NewLine` (#12010) -- Remove network hop restriction for interactive sessions (#11920) -- Fix `NullReferenceException` in `SuspendStoppingPipeline()` and `RestoreStoppingPipeline()` (#11870) (Thanks @iSazonov!) -- Generate GUID for `FormatViewDefinition` `InstanceId` if not provided (#11896) -- Fix `ConciseView` where error message is wider than window width and doesn't have whitespace (#11880) -- Allow cross-platform `CAPI-compatible` remote key exchange (#11185) (Thanks @silijon!) -- Fix error message (#11862) (Thanks @NextTurn!) -- Fix `ConciseView` to handle case where there isn't a console to obtain the width (#11784) -- Update `CmsCommands` to use Store vs certificate provider (#11643) (Thanks @mikeTWC1984!) -- Enable `pwsh` to work on Windows systems where `mpr.dll` and STA is not available (#11748) -- Refactor and implement `Restart-Computer` for `Un*x` and macOS (#11319) -- Add an implementation of `Stop-Computer` for Linux and macOS (#11151) -- Fix `help` function to check if `less` is available before using (#11737) -- Update `PSPath` in `certificate_format_ps1.xml` (#11603) (Thanks @xtqqczze!) -- Change regular expression to match relation-types without quotes in Link header (#11711) (Thanks @Marusyk!) -- Fix error message during symbolic link deletion (#11331) -- Add custom `Selected.*` type to `PSCustomObject` in `Select-Object` only once (#11548) (Thanks @iSazonov!) -- Add `-AsUTC` to the `Get-Date` cmdlet (#11611) -- Fix grouping behavior with Boolean values in `Format-Hex` (#11587) (Thanks @vexx32!) -- Make `Test-Connection` always use the default synchronization context for sending ping requests (#11517) -- Correct startup error messages (#11473) (Thanks @iSazonov!) -- Ignore headers with null values in web cmdlets (#11424) (Thanks @iSazonov!) -- Re-add check for `Invoke-Command` job dispose. (#11388) -- Revert "Update formatter to not write newlines if content is empty (#11193)" (#11342) (Thanks @iSazonov!) -- Allow `CompleteInput` to return results from `ArgumentCompleter` when `AST` or Script has matching function definition (#10574) (Thanks @M1kep!) -- Update formatter to not write new lines if content is empty (#11193) +- Write better error message if config file is broken (#13496) (Thanks @iSazonov!) +- Make AppLocker Enforce mode take precedence over UMCI Audit mode (#14353) +- Add `-SkipLimitCheck` switch to `Import-PowerShellDataFile` (#13672) +- Restrict `New-Object` in NoLanguage mode under lock down (#14140) (Thanks @krishnayalavarthi!) +- The `-Stream` parameter now works with directories (#13941) (Thanks @kyanha!) +- Avoid an exception if file system does not support reparse points (#13634) (Thanks @iSazonov!) +- Enable `CA1012`: Abstract types should not have public constructors (#13940) (Thanks @xtqqczze!) +- Enable `SA1212`: Property accessors should follow order (#14051) (Thanks @xtqqczze!) ### Code Cleanup
+ + +

We thank the following contributors!

+

@xtqqczze, @matthewjdegarmo, @powercode, @Gimly

+ +
+
    -
  • Use span-based overloads (#11884) (Thanks @iSazonov!)
  • -
  • Use new string.Split() overloads (#11867) (Thanks @iSazonov!)
  • -
  • Remove unreachable DSC code (#12076) (Thanks @DamirAinullin!)
  • -
  • Remove old dead code from FullCLR (#11886) (Thanks @iSazonov!)
  • -
  • Use Dictionary.TryAdd() where possible (#11767) (Thanks @iSazonov!)
  • -
  • Use Environment.NewLine instead of hard-coded linefeed in ParseError.ToString (#11746)
  • -
  • Fix FileSystem provider error message (#11741) (Thanks @iSazonov!)
  • -
  • Reformat code according to EditorConfig rules (#11681) (Thanks @xtqqczze!)
  • -
  • Replace use of throw GetExceptionForHR with ThrowExceptionForHR (#11640) (Thanks @xtqqczze!)
  • -
  • Refactor delegate types to lambda expressions (#11690) (Thanks @xtqqczze!)
  • -
  • Remove Unicode BOM from text files (#11546) (Thanks @xtqqczze!)
  • -
  • Fix Typo in Get-ComputerInfo cmdlet description (#11321) (Thanks @doctordns!)
  • -
  • Fix typo in description for Get-ExperimentalFeature PSWindowsPowerShellCompatibility (#11282) (Thanks @alvarodelvalle!)
  • -
  • Cleanups in command discovery (#10815) (Thanks @iSazonov!)
  • -
  • Review CurrentCulture (#11044) (Thanks @iSazonov!)
  • +
  • Enable SA1007: Operator keyword should be followed by space (#14130) (Thanks @xtqqczze!)
  • +
  • Expand where alias to Where-Object in Reset-PWSHSystemPath.ps1 (#14113) (Thanks @matthewjdegarmo!)
  • +
  • Fix whitespace issues (#14092) (Thanks @xtqqczze!)
  • +
  • Add StyleCop.Analyzers package (#13963) (Thanks @xtqqczze!)
  • +
  • Enable IDE0041: UseIsNullCheck (#14041) (Thanks @xtqqczze!)
  • +
  • Enable IDE0082: ConvertTypeOfToNameOf (#14042) (Thanks @xtqqczze!)
  • +
  • Remove unnecessary usings part 4 (#14023) (Thanks @xtqqczze!)
  • +
  • Fix PriorityAttribute name (#14094) (Thanks @xtqqczze!)
  • +
  • Enable nullable: System.Management.Automation.Interpreter.IBoxableInstruction (#14165) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Provider.IDynamicPropertyProvider (#14167) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Language.IScriptExtent (#14179) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Language.ICustomAstVisitor2 (#14192) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.LanguagePrimitives.IConversionData (#14187) (Thanks @powercode!)
  • +
  • Enable nullable: System.Automation.Remoting.Client.IWSManNativeApiFacade (#14186) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Language.ISupportsAssignment (#14180) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.ICommandRuntime2 (#14183) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.IOutputProcessingState (#14175) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.IJobDebugger (#14174) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Interpreter.IInstructionProvider (#14173) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.IHasSessionStateEntryVisibility (#14169) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Tracing.IEtwEventCorrelator (#14168) (Thanks @powercode!)
  • +
  • Fix syntax error in Windows packaging script (#14377)
  • +
  • Remove redundant local assignment in AclCommands (#14358) (Thanks @xtqqczze!)
  • +
  • Enable nullable: System.Management.Automation.Language.IAstPostVisitHandler (#14164) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.IModuleAssemblyInitializer (#14158) (Thanks @powercode!)
  • +
  • Use Microsoft.PowerShell.MarkdownRender package from nuget.org (#14090)
  • +
  • Replace GetFiles in TestModuleManifestCommand (#14317) (Thanks @xtqqczze!)
  • +
  • Enable nullable: System.Management.Automation.Provider.IContentWriter (#14152) (Thanks @powercode!)
  • +
  • Simplify getting Encoding in TranscriptionOption.FlushContentToDisk (#13910) (Thanks @Gimly!)
  • +
  • Mark applicable structs as readonly and use in-modifier (#13919) (Thanks @xtqqczze!)
  • +
  • Enable nullable: System.Management.Automation.IArgumentCompleter (#14182) (Thanks @powercode!)
  • +
  • Enable CA1822: Mark private members as static (#13897) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 6 (#14338) (Thanks @xtqqczze!)
  • +
  • Avoid array allocations from GetDirectories/GetFiles. (#14328) (Thanks @xtqqczze!)
  • +
  • Avoid array allocations from GetDirectories/GetFiles. (#14330) (Thanks @xtqqczze!)
  • +
  • Fix RCS1188: Remove redundant auto-property initialization part 2 (#14262) (Thanks @xtqqczze!)
  • +
  • Enable nullable: System.Management.Automation.Host.IHostSupportsInteractiveSession (#14170) (Thanks @powercode!)
  • +
  • Enable nullable: System.Management.Automation.Provider.IPropertyCmdletProvider (#14176) (Thanks @powercode!)
  • +
  • Fix IDE0090: Simplify new expression part 5 (#14301) (Thanks @xtqqczze!)
  • +
  • Enable IDE0075: SimplifyConditionalExpression (#14078) (Thanks @xtqqczze!)
  • +
  • Remove unnecessary usings part 9 (#14288) (Thanks @xtqqczze!)
  • +
  • Fix StyleCop and MarkdownLint CI failures (#14297) (Thanks @xtqqczze!)
  • +
  • Enable SA1000: Keywords should be spaced correctly (#13973) (Thanks @xtqqczze!)
  • +
  • Fix RCS1188: Remove redundant auto-property initialization part 1 (#14261) (Thanks @xtqqczze!)
  • +
  • Mark private members as static part 10 (#14235) (Thanks @xtqqczze!)
  • +
  • Mark private members as static part 9 (#14234) (Thanks @xtqqczze!)
  • +
  • Fix SA1642 for Microsoft.Management.Infrastructure.CimCmdlets (#14239) (Thanks @xtqqczze!)
  • +
  • Use AsSpan/AsMemory slice constructor (#14265) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.6 (#14260) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.5 (#14259) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.3 (#14257) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.2 (#14256) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 2 (#14200) (Thanks @xtqqczze!)
  • +
  • Enable SA1643: Destructor summary documentation should begin with standard text (#14236) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.4 (#14258) (Thanks @xtqqczze!)
  • +
  • Use xml documentation child blocks correctly (#14249) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 4.1 (#14255) (Thanks @xtqqczze!)
  • +
  • Use consistent spacing in xml documentation tags (#14231) (Thanks @xtqqczze!)
  • +
  • Enable IDE0074: Use coalesce compound assignment (#13396) (Thanks @xtqqczze!)
  • +
  • Remove unnecessary finalizers (#14248) (Thanks @xtqqczze!)
  • +
  • Mark local variable as const (#13217) (Thanks @xtqqczze!)
  • +
  • Fix IDE0032: UseAutoProperty part 2 (#14244) (Thanks @xtqqczze!)
  • +
  • Fix IDE0032: UseAutoProperty part 1 (#14243) (Thanks @xtqqczze!)
  • +
  • Mark private members as static part 8 (#14233) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 6 (#14229) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 5 (#14228) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 4 (#14227) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 3 (#14226) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 2 (#14225) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 1 (#14224) (Thanks @xtqqczze!)
  • +
  • Use see keyword in documentation (#14220) (Thanks @xtqqczze!)
  • +
  • Enable CA2211: Non-constant fields should not be visible (#14073) (Thanks @xtqqczze!)
  • +
  • Enable CA1816: Dispose methods should call SuppressFinalize (#14074) (Thanks @xtqqczze!)
  • +
  • Remove incorrectly implemented finalizer (#14246) (Thanks @xtqqczze!)
  • +
  • Fix CA1822: Mark members as static part 7 (#14230) (Thanks @xtqqczze!)
  • +
  • Fix SA1122: Use string.Empty for empty strings (#14218) (Thanks @xtqqczze!)
  • +
  • Fix various xml documentation issues (#14223) (Thanks @xtqqczze!)
  • +
  • Remove unnecessary usings part 8 (#14072) (Thanks @xtqqczze!)
  • +
  • Enable SA1006: Preprocessor keywords should not be preceded by space (#14052) (Thanks @xtqqczze!)
  • +
  • Fix SA1642 for Microsoft.PowerShell.Commands.Utility (#14142) (Thanks @xtqqczze!)
  • +
  • Enable CA2216: Disposable types should declare finalizer (#14089) (Thanks @xtqqczze!)
  • +
  • Wrap and name LoadBinaryModule arguments (#14193) (Thanks @xtqqczze!)
  • +
  • Wrap and name GetListOfFilesFromData arguments (#14194) (Thanks @xtqqczze!)
  • +
  • Enable SA1002: Semicolons should be spaced correctly (#14197) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 3 (#14201) (Thanks @xtqqczze!)
  • +
  • Enable SA1106: Code should not contain empty statements (#13964) (Thanks @xtqqczze!)
  • +
  • Code performance fixes follow-up (#14207) (Thanks @xtqqczze!)
  • +
  • Remove uninformative comments (#14199) (Thanks @xtqqczze!)
  • +
  • Fix IDE0090: Simplify new expression part 1 (#14027) (Thanks @xtqqczze!)
  • +
  • Enable SA1517: Code should not contain blank lines at start of file (#14131) (Thanks @xtqqczze!)
  • +
  • Enable SA1131: Use readable conditions (#14132) (Thanks @xtqqczze!)
  • +
  • Enable SA1507: Code should not contain multiple blank lines in a row (#14136) (Thanks @xtqqczze!)
  • +
  • Enable SA1516 Elements should be separated by blank line (#14137) (Thanks @xtqqczze!)
  • +
  • Enable IDE0031: Null check can be simplified (#13548) (Thanks @xtqqczze!)
  • +
  • Enable CA1065: Do not raise exceptions in unexpected locations (#14117) (Thanks @xtqqczze!)
  • +
  • Enable CA1000: Do not declare static members on generic types (#14097) (Thanks @xtqqczze!)
### Tools -- Change recommended VS Code extension name from `ms-vscode.csharp` to `ms-dotnettools.csharp` (#12083) (Thanks @devlead!) -- Specify `csharp_preferred_modifier_order` in `EditorConfig` (#11775) (Thanks @xtqqczze!) -- Update `.editorconfig` (#11675) (Thanks @xtqqczze!) -- Enable `EditorConfig` support in `OmniSharp` (#11627) (Thanks @xtqqczze!) -- Specify charset in `.editorconfig` as `utf-8` (no BOM) (#11654) (Thanks @xtqqczze!) -- Configure the issue label bot (#11527) -- Avoid variable names that conflict with automatic variables (#11392) (Thanks @xtqqczze!) +- Fixing formatting in `Reset-PWSHSystemPath.ps1` (#13689) (Thanks @dgoldman-msft!) ### Tests -- Add empty `preview.md` file to fix broken link (#12041) -- Add helper functions for SSH remoting tests (#11955) -- Add new tests for `Get-ChildItem` for `FileSystemProvider` (#11602) (Thanks @iSazonov!) -- Ensure that types referenced by `PowerShellStandard` are present (#10634) -- Check state and report reason if it's not "opened" (#11574) -- Fixes for running tests on Raspbian (#11661) -- Unify pester test syntax for the arguments of `-BeOfType` (#11558) (Thanks @xtqqczze!) -- Correct casing for automatic variables (#11568) (Thanks @iSazonov!) -- Avoid variable names that conflict with automatic variables part 2 (#11559) (Thanks @xtqqczze!) -- Update pester syntax to v4 (#11544) (Thanks @xtqqczze!) -- Allow error 504 (Gateway Timeout) in `markdown-link` tests (#11439) (Thanks @xtqqczze!) -- Re-balance CI tests (#11420) (Thanks @iSazonov!) -- Include URL in the markdown-links test error message (#11438) (Thanks @xtqqczze!) -- Use CIM cmdlets instead of WMI cmdlets in tests (#11423) (Thanks @xtqqczze!) +- Reinstate `Test-Connection` tests (#13324) +- Update markdown test packages with security fixes (#14145) ### Build and Packaging Improvements
    -
  • Put symbols in separate package (#12169)
  • -
  • Disable x86 PDB generation (#12167)
  • -
  • Bump NJsonSchema from 10.1.5 to 10.1.11 (#12050) (#12088) (#12166)
  • -
  • Create crossgen symbols for Windows x64 and x86 (#12157)
  • -
  • Move to .NET 5 preview.1 (#12140)
  • -
  • Bump Microsoft.CodeAnalysis.CSharp from 3.4.0 to 3.5.0 (#12136)
  • -
  • Move to standard internal pool for building (#12119)
  • -
  • Fix package syncing to private Module Feed (#11841)
  • -
  • Add Ubuntu SSH remoting tests CI (#12033)
  • -
  • Bump Markdig.Signed from 0.18.1 to 0.18.3 (#12078)
  • -
  • Fix MSIX packaging to determine if a Preview release by inspecting the semantic version string (#11991)
  • -
  • Ignore last exit code in the build step as dotnet may return error when SDK is not installed (#11972)
  • -
  • Fix daily package build (#11882)
  • -
  • Fix package sorting for syncing to private Module Feed (#11838)
  • -
  • Set StrictMode version 3.0 (#11563) (Thanks @xtqqczze!)
  • -
  • Bump .devcontainer version to dotnet 3.1.101 (#11707) (Thanks @Jawz84!)
  • -
  • Move to version 3 of AzFileCopy (#11697)
  • -
  • Update README.md and metadata.json for next release (#11664)
  • -
  • Code Cleanup for environment data gathering in build.psm1 (#11572) (Thanks @xtqqczze!)
  • -
  • Update Debian Install Script To Support Debian 10 (#11540) (Thanks @RandomNoun7!)
  • -
  • Update ADOPTERS.md (#11261) (Thanks @edyoung!)
  • -
  • Change back to use powershell.exe in 'SetVersionVariables.yml' to unblock daily build (#11207)
  • -
  • Change to use pwsh to have consistent JSON conversion for DateTime (#11126)
  • +
  • Fix a typo in the Get-ChangeLog function (#14129)
  • +
  • Update README and metadata.json for 7.2.0-preview.1 release (#14104)
  • +
  • Bump NJsonSchema from 10.2.2 to 10.3.1 (#14040)
  • +
  • Move windows package signing to use ESRP (#14060)
  • +
  • Use one feed in each nuget.config in official builds (#14363)
  • +
  • Fix path signed RPMs are uploaded from in release build (#14424)
  • +
  • Add Microsoft.PowerShell.MarkdownRender to the package reference list (#14386)
  • +
  • Fix issue with unsigned build (#14367)
  • +
  • Move macOS and nuget to ESRP signing (#14324)
  • +
  • Fix nuget packaging to scrub NullableAttribute (#14344)
  • +
  • Bump Microsoft.NET.Test.Sdk from 16.8.0 to 16.8.3 (#14310)
  • +
  • Bump Markdig.Signed from 0.22.0 to 0.22.1 (#14305)
  • +
  • Bump Microsoft.ApplicationInsights from 2.15.0 to 2.16.0 (#14031)
  • +
  • Move Linux to ESRP signing (#14210)
  • +
+ +
+ +### Documentation and Help Content + +- Fix example `nuget.config` (#14349) +- Fix a broken link in Code Guidelines doc (#14314) (Thanks @iSazonov!) + +[7.2.0-preview.2]: https://github.com/PowerShell/PowerShell/compare/v7.2.0-preview.1...v7.2.0-preview.2 + +## [7.2.0-preview.1] - 2020-11-17 + +### Engine Updates and Fixes + +- Change the default fallback encoding for `GetEncoding` in `Start-Transcript` to be `UTF8` without a BOM (#13732) (Thanks @Gimly!) + +### General Cmdlet Updates and Fixes + +- Update `pwsh -?` output to match docs (#13748) +- Fix `NullReferenceException` in `Test-Json` (#12942) (Thanks @iSazonov!) +- Make `Dispose` in `TranscriptionOption` idempotent (#13839) (Thanks @krishnayalavarthi!) +- Add additional Microsoft PowerShell modules to the tracked modules list (#12183) +- Relax further `SSL` verification checks for `WSMan` on non-Windows hosts with verification available (#13786) (Thanks @jborean93!) +- Add the `OutputTypeAttribute` to `Get-ExperimentalFeature` (#13738) (Thanks @ThomasNieto!) +- Fix blocking wait when starting file associated with a Windows application (#13750) +- Emit warning if `ConvertTo-Json` exceeds `-Depth` value (#13692) + +### Code Cleanup + +
+ + + +

We thank the following contributors!

+

@xtqqczze, @mkswd, @ThomasNieto, @PatLeong, @paul-cheung, @georgettica

+ +
+ +
    +
  • Fix RCS1049: Simplify boolean comparison (#13994) (Thanks @xtqqczze!)
  • +
  • Enable IDE0062: Make local function static (#14044) (Thanks @xtqqczze!)
  • +
  • Enable CA2207: Initialize value type static fields inline (#14068) (Thanks @xtqqczze!)
  • +
  • Enable CA1837: Use ProcessId and CurrentManagedThreadId from System.Environment (#14063) (Thanks @xtqqczze and @PatLeong!)
  • +
  • Remove unnecessary using directives (#14014, #14017, #14021, #14050, #14065, #14066, #13863, #13860, #13861, #13814) (Thanks @xtqqczze and @ThomasNieto!)
  • +
  • Remove unnecessary usage of LINQ Count method (#13545) (Thanks @xtqqczze!)
  • +
  • Fix SA1518: The code must not contain extra blank lines at the end of the file (#13574) (Thanks @xtqqczze!)
  • +
  • Enable CA1829: Use the Length or Count property instead of Count() (#13925) (Thanks @xtqqczze!)
  • +
  • Enable CA1827: Do not use Count() or LongCount() when Any() can be used (#13923) (Thanks @xtqqczze!)
  • +
  • Enable or fix nullable usage in a few files (#13793, #13805, #13808, #14018, #13804) (Thanks @mkswd and @georgettica!)
  • +
  • Enable IDE0040: Add accessibility modifiers (#13962, #13874) (Thanks @xtqqczze!)
  • +
  • Make applicable private Guid fields readonly (#14000) (Thanks @xtqqczze!)
  • +
  • Fix CA1003: Use generic event handler instances (#13937) (Thanks @xtqqczze!)
  • +
  • Simplify delegate creation (#13578) (Thanks @xtqqczze!)
  • +
  • Fix RCS1033: Remove redundant boolean literal (#13454) (Thanks @xtqqczze!)
  • +
  • Fix RCS1221: Use pattern matching instead of combination of as operator and null check (#13333) (Thanks @xtqqczze!)
  • +
  • Use is not syntax (#13338) (Thanks @xtqqczze!)
  • +
  • Replace magic number with constant in PDH (#13536) (Thanks @xtqqczze!)
  • +
  • Fix accessor order (#13538) (Thanks @xtqqczze!)
  • +
  • Enable IDE0054: Use compound assignment (#13546) (Thanks @xtqqczze!)
  • +
  • Fix RCS1098: Constant values should be on right side of comparisons (#13833) (Thanks @xtqqczze!)
  • +
  • Enable CA1068: CancellationToken parameters must come last (#13867) (Thanks @xtqqczze!)
  • +
  • Enable CA10XX rules with suggestion severity (#13870, #13928, #13924) (Thanks @xtqqczze!)
  • +
  • Enable IDE0064: Make Struct fields writable (#13945) (Thanks @xtqqczze!)
  • +
  • Run dotnet-format to improve formatting of source code (#13503) (Thanks @xtqqczze!)
  • +
  • Enable CA1825: Avoid zero-length array allocations (#13961) (Thanks @xtqqczze!)
  • +
  • Add IDE analyzer rule IDs to comments (#13960) (Thanks @xtqqczze!)
  • +
  • Enable CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder (#13926) (Thanks @xtqqczze!)
  • +
  • Enforce code style in build (#13957) (Thanks @xtqqczze!)
  • +
  • Enable CA1836: Prefer IsEmpty over Count when available (#13877) (Thanks @xtqqczze!)
  • +
  • Enable CA1834: Consider using StringBuilder.Append(char) when applicable (#13878) (Thanks @xtqqczze!)
  • +
  • Fix IDE0044: Make field readonly (#13884, #13885, #13888, #13892, #13889, #13886, #13890, #13891, #13887, #13893, #13969, #13967, #13968, #13970, #13971, #13966, #14012) (Thanks @xtqqczze!)
  • +
  • Enable IDE0048: Add required parentheses (#13896) (Thanks @xtqqczze!)
  • +
  • Enable IDE1005: Invoke delegate with conditional access (#13911) (Thanks @xtqqczze!)
  • +
  • Enable IDE0036: Enable the check on the order of modifiers (#13958, #13881) (Thanks @xtqqczze!)
  • +
  • Use span-based String.Concat instead of String.Substring (#13500) (Thanks @xtqqczze!)
  • +
  • Enable CA1050: Declare types in namespace (#13872) (Thanks @xtqqczze!)
  • +
  • Fix minor keyword typo in C# code comment (#13811) (Thanks @paul-cheung!)
  • +
+ +
+ +### Tools + +- Enable `CodeQL` Security scanning (#13894) +- Add global `AnalyzerConfig` with default configuration (#13835) (Thanks @xtqqczze!) + +### Build and Packaging Improvements + +
+ + + +

We thank the following contributors!

+

@mkswd, @xtqqczze

+ +
+ +
    +
  • Bump Microsoft.NET.Test.Sdk to 16.8.0 (#14020)
  • +
  • Bump Microsoft.CodeAnalysis.CSharp to 3.8.0 (#14075)
  • +
  • Remove workarounds for .NET 5 RTM builds (#14038)
  • +
  • Migrate 3rd party signing to ESRP (#14010)
  • +
  • Fixes to release pipeline for GA release (#14034)
  • +
  • Don't do a shallow checkout (#13992)
  • +
  • Add validation and dependencies for Ubuntu 20.04 distribution to packaging script (#13993)
  • +
  • Add .NET install workaround for RTM (#13991)
  • +
  • Move to ESRP signing for Windows files (#13988)
  • +
  • Update PSReadLine version to 2.1.0 (#13975)
  • +
  • Bump .NET to version 5.0.100-rtm.20526.5 (#13920)
  • +
  • Update script to use .NET RTM feeds (#13927)
  • +
  • Add checkout step to release build templates (#13840)
  • +
  • Turn on /features:strict for all projects (#13383) (Thanks @xtqqczze!)
  • +
  • Bump NJsonSchema to 10.2.2 (#13722, #13751)
  • +
  • Add flag to make Linux script publish to production repo (#13714)
  • +
  • Bump Markdig.Signed to 0.22.0 (#13741)
  • +
  • Use new release script for Linux packages (#13705)
### Documentation and Help Content -- Replace `VSCode` link in `CONTRIBUTING.md` (#11475) (Thanks @stevend811!) -- Remove the version number of PowerShell from LICENSE (#12019) -- Add the 7.0 change log link to `CHANGELOG/README.md` (#12062) (Thanks @LabhanshAgrawal!) -- Improvements to the contribution guide (#12086) (Thanks @ShaydeNofziger!) -- Update the doc about debugging dotnet core in VSCode (#11969) -- Update `README.md` and `metadata.json` for the next release (#11918) (#11992) -- Update `Adopters.md` to include info on Azure Pipelines and GitHub Actions (#11888) (Thanks @alepauly!) -- Add information about how Amazon AWS uses PowerShell. (#11365) (Thanks @bpayette!) -- Add link to .NET CLI version in build documentation (#11725) (Thanks @joeltankam!) -- Added info about `DeploymentScripts` in `ADOPTERS.md` (#11703) -- Update `CHANGELOG.md` for `6.2.4` release (#11699) -- Update `README.md` and `metadata.json` for next release (#11597) -- Update the breaking change definition (#11516) -- Adding System Frontier to the PowerShell Core adopters list `ADOPTERS.md` (#11480) (Thanks @OneScripter!) -- Update `ChangeLog`, `README.md` and `metadata.json` for `7.0.0-rc.1` release (#11363) -- Add `AzFunctions` to `ADOPTERS.md` (#11311) (Thanks @Francisco-Gamino!) -- Add `Universal Dashboard` to `ADOPTERS.md` (#11283) (Thanks @adamdriscoll!) -- Add `config.yml` for `ISSUE_TEMPLATE` so that Doc, Security, Support, and Windows PowerShell issues go to URLs (#11153) -- Add `Adopters.md` file (#11256) -- Update `Readme.md` for `preview.6` release (#11108) -- Update `SUPPORT.md` (#11101) (Thanks @mklement0!) -- Update `README.md` (#11100) (Thanks @mklement0!) - -[7.1.0-preview.5]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.4...v7.1.0-preview.5 -[7.1.0-preview.4]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.3...v7.1.0-preview.4 -[7.1.0-preview.3]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.2...v7.1.0-preview.3 -[7.1.0-preview.2]: https://github.com/PowerShell/PowerShell/compare/v7.1.0-preview.1...v7.1.0-preview.2 -[7.1.0-preview.1]: https://github.com/PowerShell/PowerShell/compare/v7.0.0-preview.6...v7.1.0-preview.1 +- Fix links to LTS versions for Windows (#14070) +- Fix `crontab` formatting in example doc (#13712) (Thanks @dgoldman-msft!) +[7.2.0-preview.1]: https://github.com/PowerShell/PowerShell/compare/v7.1.0...v7.2.0-preview.1 diff --git a/DotnetRuntimeMetadata.json b/DotnetRuntimeMetadata.json index d6c02300df9..1b95abccd68 100644 --- a/DotnetRuntimeMetadata.json +++ b/DotnetRuntimeMetadata.json @@ -1,8 +1,15 @@ { "sdk": { - "channel": "release/5.0.1xx-rc1", - "packageVersionPattern": "5.0.0-rc.1", - "sdkImageVersion": "5.0.100-rc.1", - "nextChannel": "net5/rc1" + "channel": "6.0.1xx", + "quality": "signed", + "qualityFallback": "daily", + "packageVersionPattern": "6.0.0", + "sdkImageVersion": "6.0.100", + "nextChannel": "6.0.1xx", + "azureFeed": "https://dotnetstage.blob.core.windows.net/6-0-100-rtm-21527-11-public", + "sdkImageOverride": "6.0.100-rtm.21527.11" + }, + "internalfeed" : { + "url": "https://pkgs.dev.azure.com/dnceng/public/_packaging/6.0.100-rtm.21527.11-shipping/nuget/v2" } } diff --git a/PowerShell.Common.props b/PowerShell.Common.props index d8fb6aa59bb..4054cd5b19a 100644 --- a/PowerShell.Common.props +++ b/PowerShell.Common.props @@ -1,4 +1,5 @@ + + + + ^((\d+).(\d+).(\d+))(-(\w+)(.(\d+))?)?$ + $([System.Text.RegularExpressions.Regex]::Match($(ReleaseTag), $(RegexReleaseTag)).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(ReleaseTag), $(RegexReleaseTag)).Groups[8].Value) + $([System.Text.RegularExpressions.Regex]::Match($(ReleaseTag), $(RegexReleaseTag)).Groups[6].Value) + + 100 + + 500 + $([MSBuild]::Add($(ReleaseTagSemVersionPart), $(RCIncrementValue))) + $(ReleaseTag) + + $(ReleaseTagVersionPart).$(ReleaseTagSemVersionPart) + + $(ReleaseTagVersionPart).$(GAIncrementValue) ^v(.+)-(\d+)-g(.+) + $([System.Text.RegularExpressions.Regex]::Match($(PowerShellVersion), $(RegexGitVersion)).Groups[1].Value) $([System.Text.RegularExpressions.Regex]::Match($(PowerShellVersion), $(RegexGitVersion)).Groups[1].Value) $([System.Text.RegularExpressions.Regex]::Match($(PowerShellVersion), $(RegexGitVersion)).Groups[2].Value) $([System.Text.RegularExpressions.Regex]::Match($(PowerShellVersion), $(RegexGitVersion)).Groups[3].Value) @@ -51,7 +87,7 @@ Here we define explicitly 'Version' to set 'FileVersion' and 'AssemblyVersion' by 'GetAssemblyVersion' target in 'Microsoft.NET.GenerateAssemblyInfo.targets'. Here we define explicitly 'InformationalVersion' because by default it is defined as 'Version' by 'GetAssemblyVersion' target in 'Microsoft.NET.GenerateAssemblyInfo.targets'. --> - $(PSCoreBuildVersion) + $(PSCoreFileVersion) $(PSCoreFormattedVersion) $(PSCoreFormattedVersion) @@ -71,8 +107,11 @@ portable + + + strict + + + + true + diff --git a/PowerShell.sln b/PowerShell.sln index b164361d7d2..224d27ab3fc 100644 --- a/PowerShell.sln +++ b/PowerShell.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 +# Visual Studio Version 16 # https://github.com/dotnet/project-system/blob/master/docs/opening-with-new-project-system.md#project-type-guids VisualStudioVersion = 15.0.26730.12 MinimumVisualStudioVersion = 10.0.40219.1 @@ -29,8 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.WSMan.Runtime", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "powershell-unix", "src\powershell-unix\powershell-unix.csproj", "{73EA0BE6-C0C5-4B56-A5AA-DADA4C01D690}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerShell.MarkdownRender", "src\Microsoft.PowerShell.MarkdownRender\Microsoft.PowerShell.MarkdownRender.csproj", "{43D4F8DA-A7DE-494B-81B0-BDE3CFD7B1F1}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xUnit.tests", "test\xUnit\xUnit.tests.csproj", "{08704934-9764-48CE-86DB-BCF0A1CF7899}" EndProject # Configuration mapping comment diff --git a/README.md b/README.md index 907942d8858..d30953d7d5b 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ It includes a command-line shell, an associated scripting language and a framewo Although this repository started as a fork of the Windows PowerShell code base, changes made in this repository do not make their way back to Windows PowerShell 5.1 automatically. This also means that [issues tracked here][issues] are only for PowerShell Core 6 and higher. -Windows PowerShell specific issues should be opened on [UserVoice][]. +Windows PowerShell specific issues should be reported with the [Feedback Hub app][feedback-hub], by choosing "Apps > PowerShell" in category. [issues]: https://github.com/PowerShell/PowerShell/issues -[UserVoice]: https://windowsserver.uservoice.com/forums/301869-powershell +[feedback-hub]: https://support.microsoft.com/windows/send-feedback-to-microsoft-with-the-feedback-hub-app-f59187f8-8739-22d6-ba93-f66612949332 ## New to PowerShell? @@ -28,18 +28,21 @@ You can download and install a PowerShell package for any of the following platf | Supported Platform | Download (LTS) | Downloads (stable) | Downloads (preview) | How to Install | | -------------------------------------------| ------------------------| ------------------------| ----------------------| ------------------------------| -| [Windows (x64)][corefx-win] | [.msi][rl-windows-64] | [.msi][rl-windows-64] | [.msi][pv-windows-64] | [Instructions][in-windows] | -| [Windows (x86)][corefx-win] | [.msi][rl-windows-86] | [.msi][rl-windows-86] | [.msi][pv-windows-86] | [Instructions][in-windows] | -| [Ubuntu 18.04][corefx-linux] | [.deb][lts-ubuntu18] | [.deb][rl-ubuntu18] | [.deb][pv-ubuntu18] | [Instructions][in-ubuntu18] | -| [Ubuntu 16.04][corefx-linux] | [.deb][lts-ubuntu16] | [.deb][rl-ubuntu16] | [.deb][pv-ubuntu16] | [Instructions][in-ubuntu16] | -| [Debian 9][corefx-linux] | [.deb][lts-debian9] | [.deb][rl-debian9] | [.deb][pv-debian9] | [Instructions][in-deb9] | -| [Debian 10][corefx-linux] | [.deb][lts-debian10] | [.deb][rl-debian10] | [.deb][pv-debian10] | | -| [CentOS 7][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-centos] | [Instructions][in-centos] | -| [CentOS 8][corefx-linux] | [.rpm][lts-centos8] | [.rpm][rl-centos8] | [.rpm][pv-centos8] | | -| [Red Hat Enterprise Linux 7][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-centos] | [Instructions][in-rhel7] | -| [openSUSE 42.3][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-centos] | [Instructions][in-opensuse] | -| [Fedora 30][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-centos] | [Instructions][in-fedora] | -| [macOS 10.13+][corefx-macos] | [.pkg][lts-macos] | [.pkg][rl-macos] | [.pkg][pv-macos] | [Instructions][in-macos] | +| [Windows (x64)][corefx-win] | [.msi][lts-windows-64] | [.msi][rl-windows-64] | [.msi][pv-windows-64] | [Instructions][in-windows] | +| [Windows (x86)][corefx-win] | [.msi][lts-windows-86] | [.msi][rl-windows-86] | [.msi][pv-windows-86] | [Instructions][in-windows] | +| [Ubuntu 20.04][corefx-linux] | | [.deb][rl-ubuntu20] | [.deb][pv-deb] | [Instructions][in-ubuntu20] | +| [Ubuntu 18.04][corefx-linux] | [.deb][lts-ubuntu18] | [.deb][rl-ubuntu18] | [.deb][pv-deb] | [Instructions][in-ubuntu18] | +| [Ubuntu 16.04][corefx-linux] | [.deb][lts-ubuntu16] | [.deb][rl-ubuntu16] | [.deb][pv-deb] | [Instructions][in-ubuntu16] | +| [Debian 9][corefx-linux] | [.deb][lts-debian9] | [.deb][rl-debian9] | [.deb][pv-deb] | [Instructions][in-deb9] | +| [Debian 10][corefx-linux] | [.deb][lts-debian10] | [.deb][rl-debian10] | [.deb][pv-deb] | [Instructions][in-deb9] | +| [Debian 11][corefx-linux] | | [.deb][rl-debian11] | [.deb][pv-deb] | | +| [CentOS 7][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-rpm] | [Instructions][in-centos] | +| [CentOS 8][corefx-linux] | [.rpm][lts-centos8] | [.rpm][rl-centos8] | [.rpm][pv-rpm] | | +| [Red Hat Enterprise Linux 7][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-rpm] | [Instructions][in-rhel7] | +| [openSUSE 42.3][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-rpm] | [Instructions][in-opensuse] | +| [Fedora 30][corefx-linux] | [.rpm][lts-centos] | [.rpm][rl-centos] | [.rpm][pv-rpm] | [Instructions][in-fedora] | +| [macOS 10.13+ (x64)][corefx-macos] | [.pkg][lts-macos] | [.pkg][rl-macos] | [.pkg][pv-macos] | [Instructions][in-macos] | +| [macOS 10.13+ (arm64)][corefx-macos] | | | [.pkg][pv-macos-arm64]| [Instructions][in-macos] | | Docker | | | | [Instructions][in-docker] | You can download and install a PowerShell package for any of the following platforms, **which are supported by the community.** @@ -47,7 +50,7 @@ You can download and install a PowerShell package for any of the following platf | Platform | Downloads (stable) | Downloads (preview) | How to Install | | -------------------------| ------------------------| ----------------------------- | ------------------------------| | Arch Linux | | | [Instructions][in-archlinux] | -| Kali Linux | [.deb][rl-ubuntu16] | [.deb][pv-ubuntu16] | [Instructions][in-kali] | +| Kali Linux | [.deb][rl-ubuntu16] | [.deb][pv-deb] | [Instructions][in-kali] | | Many Linux distributions | [Snapcraft][rl-snap] | [Snapcraft][pv-snap] | | You can also download the PowerShell binary archives for Windows, macOS and Linux. @@ -56,60 +59,63 @@ You can also download the PowerShell binary archives for Windows, macOS and Linu | ---------------| --------------------------------------------------- | ------------------------------------------------| -----------------------------------------------| | Windows | [32-bit][rl-winx86-zip]/[64-bit][rl-winx64-zip] | [32-bit][pv-winx86-zip]/[64-bit][pv-winx64-zip] | [Instructions][in-windows-zip] | | macOS | [64-bit][rl-macos-tar] | [64-bit][pv-macos-tar] | [Instructions][in-tar-macos] | +| macOS | | [64-bit][pv-macos-tar-arm64] | [Instructions][in-tar-macos] | | Linux | [64-bit][rl-linux-tar] | [64-bit][pv-linux-tar] | [Instructions][in-tar-linux] | -| Windows (Arm) | [32-bit][rl-winarm]/[64-bit][rl-winarm64] (preview) | [32-bit][pv-winarm]/[64-bit][pv-winarm64] | [Instructions][in-arm] | +| Windows (Arm) | [64-bit][rl-winarm64] (preview) | [64-bit][pv-winarm64] | [Instructions][in-arm] | | Raspbian (Arm) | [32-bit][rl-arm32]/[64-bit][rl-arm64] | [32-bit][pv-arm32]/[64-bit][pv-arm64] | [Instructions][in-raspbian] | -[lts-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts_7.0.3-1.ubuntu.18.04_amd64.deb -[lts-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts_7.0.3-1.ubuntu.16.04_amd64.deb -[lts-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts_7.0.3-1.debian.9_amd64.deb -[lts-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts_7.0.3-1.debian.10_amd64.deb -[lts-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts-7.0.3-1.rhel.7.x86_64.rpm -[lts-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts-7.0.3-1.centos.8.x86_64.rpm -[lts-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-lts-7.0.3-osx-x64.pkg - -[rl-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x64.msi -[rl-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x86.msi -[rl-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell_7.0.3-1.ubuntu.18.04_amd64.deb -[rl-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell_7.0.3-1.ubuntu.16.04_amd64.deb -[rl-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell_7.0.3-1.debian.9_amd64.deb -[rl-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell_7.0.3-1.debian.10_amd64.deb -[rl-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-1.rhel.7.x86_64.rpm -[rl-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-1.centos.8.x86_64.rpm -[rl-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-osx-x64.pkg -[rl-winarm]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-arm32.zip -[rl-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-arm64.zip -[rl-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x86.zip -[rl-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x64.zip -[rl-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-osx-x64.tar.gz -[rl-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-linux-x64.tar.gz -[rl-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-linux-arm32.tar.gz -[rl-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-linux-arm64.tar.gz +[lts-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/PowerShell-7.0.7-win-x86.msi +[lts-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/PowerShell-7.0.7-win-x64.msi +[lts-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts_7.0.7-1.ubuntu.18.04_amd64.deb +[lts-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts_7.0.7-1.ubuntu.16.04_amd64.deb +[lts-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts_7.0.7-1.debian.9_amd64.deb +[lts-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts_7.0.7-1.debian.10_amd64.deb +[lts-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts-7.0.7-1.rhel.7.x86_64.rpm +[lts-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts-7.0.7-1.centos.8.x86_64.rpm +[lts-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.7/powershell-lts-7.0.7-osx-x64.pkg + +[rl-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/PowerShell-7.1.4-win-x64.msi +[rl-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/PowerShell-7.1.4-win-x86.msi +[rl-ubuntu20]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.ubuntu.20.04_amd64.deb +[rl-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.ubuntu.18.04_amd64.deb +[rl-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.ubuntu.16.04_amd64.deb +[rl-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.debian.9_amd64.deb +[rl-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.debian.10_amd64.deb +[rl-debian11]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell_7.1.4-1.debian.11_amd64.deb +[rl-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-1.rhel.7.x86_64.rpm +[rl-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-1.centos.8.x86_64.rpm +[rl-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-osx-x64.pkg +[rl-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/PowerShell-7.1.4-win-arm64.zip +[rl-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/PowerShell-7.1.4-win-x86.zip +[rl-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/PowerShell-7.1.4-win-x64.zip +[rl-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-osx-x64.tar.gz +[rl-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-linux-x64.tar.gz +[rl-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-linux-arm32.tar.gz +[rl-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.4/powershell-7.1.4-linux-arm64.tar.gz [rl-snap]: https://snapcraft.io/powershell -[pv-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-x64.msi -[pv-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-x86.msi -[pv-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview_7.1.0-preview.7-1.ubuntu.18.04_amd64.deb -[pv-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview_7.1.0-preview.7-1.ubuntu.16.04_amd64.deb -[pv-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview_7.1.0-preview.7-1.debian.9_amd64.deb -[pv-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview_7.1.0-preview.7-1.debian.10_amd64.deb -[pv-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview-7.1.0_preview.7-1.rhel.7.x86_64.rpm -[pv-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-preview-7.1.0_preview.7-1.centos.8.x86_64.rpm -[pv-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-7.1.0-preview.7-osx-x64.pkg -[pv-winarm]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-arm32.zip -[pv-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-arm64.zip -[pv-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-x86.zip -[pv-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/PowerShell-7.1.0-preview.7-win-x64.zip -[pv-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-7.1.0-preview.7-osx-x64.tar.gz -[pv-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-7.1.0-preview.7-linux-x64.tar.gz -[pv-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-7.1.0-preview.7-linux-arm32.tar.gz -[pv-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0-preview.7/powershell-7.1.0-preview.7-linux-arm64.tar.gz +[pv-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/PowerShell-7.2.0-preview.8-win-x64.msi +[pv-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/PowerShell-7.2.0-preview.8-win-x86.msi +[pv-deb]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-preview_7.2.0-preview.8-1.deb_amd64.deb +[pv-rpm]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-preview-7.2.0_preview.8-1.rh.x86_64.rpm +[pv-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-osx-x64.pkg +[pv-macos-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-osx-arm64.pkg +[pv-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/PowerShell-7.2.0-preview.8-win-arm64.zip +[pv-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/PowerShell-7.2.0-preview.8-win-x86.zip +[pv-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/PowerShell-7.2.0-preview.8-win-x64.zip +[pv-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-osx-x64.tar.gz +[pv-macos-tar-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-osx-arm64.tar.gz +[pv-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-linux-x64.tar.gz +[pv-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-linux-arm32.tar.gz +[pv-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.8/powershell-7.2.0-preview.8-linux-arm64.tar.gz [pv-snap]: https://snapcraft.io/powershell-preview [in-windows]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-windows [in-ubuntu16]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#ubuntu-1604 [in-ubuntu18]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#ubuntu-1804 +[in-ubuntu20]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#ubuntu-2004 [in-deb9]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#debian-9 +[in-deb10]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#debian-10 [in-centos]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#centos-7 [in-rhel7]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#red-hat-enterprise-linux-rhel-7 [in-opensuse]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux#opensuse @@ -135,18 +141,28 @@ To install a specific version, visit [releases](https://github.com/PowerShell/Po For more information on how and why we built this dashboard, check out this [blog post](https://devblogs.microsoft.com/powershell/powershell-open-source-community-dashboard/). -## Chat +## Discussions -Want to chat with other members of the PowerShell community? +[GitHub Discussions](https://docs.github.com/en/free-pro-team@latest/discussions/quickstart) is a feature to enable fluid and open discussions within the community +for topics that are not related to code, unlike issues. + +This is an experiment we are trying in our repositories to see if it helps move discussions out of issues so that issues remain actionable by the team or members of the community. +There should be no expectation that PowerShell team members are regular participants in the discussions. +Individual PowerShell team members may choose to participate in discussions, but the expectation is that community members help drive discussions so that team members +can focus on issues. -We have a Gitter Room which you can join below. +Create or join a [discussion](https://github.com/PowerShell/PowerShell/discussions). -[![Join the chat](https://img.shields.io/static/v1.svg?label=chat&message=on%20gitter&color=informational&logo=gitter)](https://gitter.im/PowerShell/PowerShell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +## Chat + +Want to chat with other members of the PowerShell community? -There is also the community-driven PowerShell Virtual User Group, which you can join on: +There are dozens of topic specific channels on our community-driven PowerShell Virtual User Group, which you can join on: +* [Gitter](https://gitter.im/PowerShell/PowerShell) +* [Discord](https://discord.gg/PowerShell) +* [IRC](https://web.libera.chat/#powershell) on Libera.Chat * [Slack](https://aka.ms/psslack) -* [Discord](https://aka.ms/psdiscord) ## Add-ons and libraries diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 06747f655ca..73301c45a84 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -15,13 +15,11 @@ USA Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License. +--------------------------------------------------------- + +Microsoft.Extensions.ObjectPool 5.0.10 - Apache-2.0 -------------------------------------------------------------------- -Microsoft.CodeAnalysis.Common 3.3.1 - Apache-2.0 -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. Apache License @@ -121,126 +119,13 @@ See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -Microsoft.CodeAnalysis.CSharp 3.3.1 - Apache-2.0 -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) Microsoft Corporation. -9Copyright (c) Microsoft Corporation. -ACopyright (c) Microsoft Corporation. -BCopyright (c) Microsoft Corporation. -CCopyright (c) Microsoft Corporation. -DCopyright (c) Microsoft Corporation. -OCopyright (c) Microsoft Corporation. -Copyright (c) Microsoft Corporation. Alle Rechte - -Apache License - -Version 2.0, January 2004 - -http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - - - "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - - - - "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - - - - "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - - - "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - - - - "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - - - - "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - - - - "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - - - - "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - - - - "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - - - - "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - - (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. - - You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - -To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -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. +--------------------------------------------------------- -------------------------------------------------------------------- +Markdig.Signed 0.22.0 - BSD-2-Clause -------------------------------------------------------------------- -Markdig.Signed 0.17.1 - BSD-2-Clause (c) 2008 VeriSign, Inc. Copyright (c) . All rights reserved. @@ -253,11 +138,13 @@ Redistribution and use in source and binary forms, with or without modification, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights 2.18.0 - MIT -------------------------------------------------------------------- -Microsoft.ApplicationInsights 2.11.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. @@ -271,32 +158,50 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Bcl.AsyncInterfaces 5.0.0 - MIT -------------------------------------------------------------------- -Microsoft.NETCore.Platforms 3.0.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -323,11 +228,84 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.CodeAnalysis.Common 4.0.0-6.final - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation and Contributors + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.CodeAnalysis.CSharp 4.0.0-6.final - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation. +9Copyright (c) Microsoft Corporation. +ACopyright (c) Microsoft Corporation. +BCopyright (c) Microsoft Corporation. +CCopyright (c) Microsoft Corporation. +DCopyright (c) Microsoft Corporation. +OCopyright (c) Microsoft Corporation. +Copyright (c) .NET Foundation and Contributors +Copyright (c) Microsoft Corporation. Alle Rechte + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.PowerShell.MarkdownRender 7.2.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +(c) Microsoft Corporation. PowerShell's Markdown Rendering project PowerShell Markdown Renderer + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.PowerShell.Native 7.2.0 - MIT -------------------------------------------------------------------- -Microsoft.PowerShell.Native 7.0.0-preview.2 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) by P.J. Plauger @@ -342,11 +320,13 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Win32.Registry 4.7.0 - MIT -------------------------------------------------------------------- -Microsoft.Win32.Registry 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) .NET Foundation. @@ -394,32 +374,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Win32.Registry.AccessControl 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -Microsoft.Win32.Registry.AccessControl 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -446,32 +445,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Win32.SystemEvents 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -Microsoft.Win32.SystemEvents 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -498,32 +516,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Windows.Compatibility 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -Microsoft.Windows.Compatibility 3.0.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -550,11 +587,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Namotion.Reflection 2.0.3 - MIT -------------------------------------------------------------------- -Namotion.Reflection 1.0.7 - MIT (c) 2008 VeriSign, Inc. MIT License @@ -567,11 +606,13 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json 13.0.1 - MIT -------------------------------------------------------------------- -Newtonsoft.Json 12.0.2 - MIT (c) 2008 VeriSign, Inc. Copyright James Newton-King 2008 Copyright (c) 2007 James Newton-King @@ -599,15 +640,16 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +NJsonSchema 10.5.2 - MIT -------------------------------------------------------------------- -NJsonSchema 10.0.27 - MIT +Copyright Rico Suter (c) 2008 VeriSign, Inc. -Copyright Rico Suter, 2018 -Copyright (c) Rico Suter, 2018 -Copyright Rico Suter, 2018 4JSON Schema +Copyright (c) Rico Suter MIT License @@ -619,32 +661,51 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +runtime.linux-arm.runtime.native.System.IO.Ports 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -runtime.linux-arm.runtime.native.System.IO.Ports 4.6.0-rc2.19462.14 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -671,34 +732,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- - -runtime.linux-arm64.runtime.native.System.IO.Ports 4.6.0-rc2.19462.14 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS - -The MIT License (MIT) +--------------------------------------------------------- + +runtime.linux-arm64.runtime.native.System.IO.Ports 6.0.0-rc.2.21480.5 - MIT + + + +The MIT License (MIT) Copyright (c) .NET Foundation and Contributors @@ -723,32 +765,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +runtime.linux-x64.runtime.native.System.IO.Ports 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -runtime.linux-x64.runtime.native.System.IO.Ports 4.6.0-rc2.19462.14 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -775,11 +798,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +runtime.native.System.Data.SqlClient.sni 4.7.0 - MIT -------------------------------------------------------------------- -runtime.native.System.Data.SqlClient.sni 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) .NET Foundation. @@ -827,32 +852,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +runtime.native.System.IO.Ports 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -runtime.native.System.IO.Ports 4.6.0 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -879,32 +885,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +runtime.osx-x64.runtime.native.System.IO.Ports 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -runtime.osx-x64.runtime.native.System.IO.Ports 4.6.0-rc2.19462.14 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -931,32 +918,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.CodeDom 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.CodeDom 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -983,26 +989,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Collections.Immutable 5.0.0 - MIT -------------------------------------------------------------------- -System.Collections.Immutable 1.5.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1029,32 +1059,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ComponentModel.Composition 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.ComponentModel.Composition 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1081,32 +1130,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ComponentModel.Composition.Registration 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.ComponentModel.Composition.Registration 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1133,32 +1201,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Configuration.ConfigurationManager 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Configuration.ConfigurationManager 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1185,11 +1272,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Data.Odbc 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Data.DataSetExtensions 4.5.0 - MIT +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1216,32 +1343,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Data.OleDb 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Data.Odbc 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1268,11 +1414,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +System.Data.SqlClient 4.8.3 - MIT -System.Data.OleDb 4.6.0 - MIT + +2008 SQL Server 2012 (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) .NET Foundation. @@ -1320,33 +1469,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Diagnostics.DiagnosticSource 5.0.0 - MIT -------------------------------------------------------------------- -System.Data.SqlClient 4.7.0 - MIT -2008 SQL Server 2012 (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1373,32 +1539,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Diagnostics.EventLog 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Diagnostics.EventLog 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1425,32 +1610,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Diagnostics.PerformanceCounter 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Diagnostics.PerformanceCounter 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1477,32 +1681,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.DirectoryServices 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.DirectoryServices 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1529,32 +1752,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.DirectoryServices.AccountManagement 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.DirectoryServices.AccountManagement 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1581,32 +1823,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.DirectoryServices.Protocols 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.DirectoryServices.Protocols 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1633,32 +1894,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Drawing.Common 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Drawing.Common 4.6.0 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -1685,32 +1927,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Formats.Asn1 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.IO.FileSystem.AccessControl 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1737,32 +1998,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.IO.Packaging 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.IO.Packaging 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1789,26 +2069,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.IO.Ports 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.IO.Pipes.AccessControl 4.5.1 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1835,32 +2140,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Management 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.IO.Ports 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1887,25 +2211,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Memory 4.5.4 - MIT -------------------------------------------------------------------- -System.Management 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. -Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) @@ -1939,25 +2259,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Net.Http.WinHttpHandler 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Memory 4.5.3 - MIT (c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -1984,25 +2330,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Numerics.Vectors 4.5.0 - MIT -------------------------------------------------------------------- -System.Net.Http.WinHttpHandler 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. -Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) @@ -2036,11 +2378,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Private.ServiceModel 4.9.0-rc2.21473.1 - MIT -------------------------------------------------------------------- -System.Private.ServiceModel 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) .NET Foundation and Contributors @@ -2071,32 +2415,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Reflection.Context 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Reflection.Context 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2123,11 +2486,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +System.Reflection.DispatchProxy 4.7.1 - MIT -System.Reflection.DispatchProxy 4.5.0 - MIT + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -2154,32 +2540,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Reflection.Metadata 5.0.0 - MIT -------------------------------------------------------------------- -System.Reflection.Emit 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2206,32 +2610,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Runtime.Caching 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Reflection.Emit.ILGeneration 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2258,32 +2681,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Runtime.CompilerServices.Unsafe 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Reflection.Emit.Lightweight 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2310,11 +2752,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -System.Reflection.Metadata 1.6.0 - MIT +System.Security.AccessControl 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2341,32 +2823,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Cryptography.Pkcs 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.Runtime.Caching 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2393,15 +2894,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Cryptography.ProtectedData 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.ServiceModel.Duplex 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors -Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2428,15 +2965,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Cryptography.Xml 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.ServiceModel.Http 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors -Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2463,15 +3036,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Permissions 6.0.0-rc.2.21480.5 - MIT -------------------------------------------------------------------- -System.ServiceModel.NetTcp 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors -Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2498,15 +3107,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Principal.Windows 5.0.0 - MIT -------------------------------------------------------------------- -System.ServiceModel.Primitives 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors -Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) @@ -2533,11 +3177,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceModel.Duplex 4.9.0-rc2.21473.1 - MIT -------------------------------------------------------------------- -System.ServiceModel.Security 4.6.0 - MIT (c) 2008 VeriSign, Inc. (c) Microsoft Corporation. Copyright (c) .NET Foundation and Contributors @@ -2568,32 +3214,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceModel.Http 4.9.0-rc2.21473.1 - MIT -------------------------------------------------------------------- -System.Threading.AccessControl 4.6.0 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) .NET Foundation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -2620,26 +3247,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceModel.NetTcp 4.9.0-rc2.21473.1 - MIT -------------------------------------------------------------------- -System.Threading.Tasks.Extensions 4.5.3 - MIT -(c) 2008 VeriSign, Inc. -(c) Microsoft Corporation. -Copyright (c) 2011, Google Inc. -(c) 1997-2005 Sean Eron Anderson. -Copyright (c) 1991-2017 Unicode, Inc. -Portions (c) International Organization -Copyright (c) 2015 The Chromium Authors. -Copyright (c) 2004-2006 Intel Corporation -Copyright (c) .NET Foundation Contributors -Copyright (c) .NET Foundation and Contributors -Copyright (c) 2011 Novell, Inc (http://www.novell.com) -Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) @@ -2666,25 +3280,521 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -System.Windows.Extensions 4.6.0 - MIT -(c) 2008 VeriSign, Inc. +System.ServiceModel.Primitives 4.9.0-rc2.21473.1 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceModel.Security 4.9.0-rc2.21473.1 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceModel.Syndication 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ServiceProcess.ServiceController 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Speech 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Text.Encoding.CodePages 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Text.Encodings.Web 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Threading.AccessControl 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Threading.Tasks.Extensions 4.5.4 - MIT + + +(c) 2008 VeriSign, Inc. (c) Microsoft Corporation. -Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. -Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2013-2017, Alfred Klomp -Copyright (c) 2015-2017, Wojciech Mula -Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation -Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) @@ -2718,88 +3828,165 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -Additional - +System.Web.Services.Description 4.9.0-rc2.21473.1 - MIT ---------------------------------------------- -File: PSReadLine ---------------------------------------------- -https://github.com/lzybkr/PSReadLine +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) -Copyright (c) 2013, Jason Shirk +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors All rights reserved. -BSD License +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------- -File: Hashtables from ConvertFrom-json ----------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Windows.Extensions 6.0.0-rc.2.21480.5 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright 2018 Daniel Lemire +Copyright 2012 the V8 project +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation +Copyright (c) 2007 James Newton-King +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Copyright (c) 2018 Alexander Chermyanin +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2019 Microsoft Corporation, Daan Leijen +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To -https://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h +The MIT License (MIT) -Copyright (c) 2015 Dave Wyatt. All rights reserved. +Copyright (c) .NET Foundation and Contributors All rights reserved. -MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + + +------------------------------------------------------------------- + +------------------------------------------------------------------- + +Additional - ------------------------------------------------- -PackageManagement +Microsoft.PowerShell.Archive ------------------------------------------------- -Copyright (c) Microsoft Corporation -All rights reserved. +Copyright (c) 2016 Microsoft Corporation. -MIT License +The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the Software), to deal +of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +------------------------------------------------- +Microsoft.Management.Infrastructure.Runtime.Unix +Microsoft.Management.Infrastructure +------------------------------------------------- + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------- • NuGet.Common @@ -2831,4 +4018,116 @@ 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. -------------------------------------------------------------------- +------------------------------------------------- +PackageManagement +------------------------------------------------- + +Copyright (c) Microsoft Corporation +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the Software), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------- +PowerShellGet +------------------------------------------------- + +Copyright (c) Microsoft Corporation + +All rights reserved. + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------------------------------- +File: PSReadLine +--------------------------------------------- + +https://github.com/PowerShell/PSReadLine + +Copyright (c) 2013, Jason Shirk + +All rights reserved. + +BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------- +ThreadJob +------------------------------------------------- + +Copyright (c) 2018 Paul Higinbotham + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/assets/AppxManifest.xml b/assets/AppxManifest.xml index 83df8c31b41..bba68ca976b 100644 --- a/assets/AppxManifest.xml +++ b/assets/AppxManifest.xml @@ -20,7 +20,7 @@ - + diff --git a/assets/additionalAttributions.txt b/assets/additionalAttributions.txt index d244bad6877..c43aba0ef65 100644 --- a/assets/additionalAttributions.txt +++ b/assets/additionalAttributions.txt @@ -2,11 +2,139 @@ ## Copy this into the additional attributions fields ## Copy everything below here, but do not include this line +------------------------------------------------- +Microsoft.PowerShell.Archive +------------------------------------------------- + +Copyright (c) 2016 Microsoft Corporation. + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +------------------------------------------------- +Microsoft.Management.Infrastructure.Runtime.Unix +Microsoft.Management.Infrastructure +------------------------------------------------- + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------- +• NuGet.Common +• NuGet.Configuration +• NuGet.DependencyResolver.Core +• NuGet.Frameworks +• NuGet.LibraryModel +• NuGet.Packaging +• NuGet.Packaging.Core +• NuGet.Packaging.Core.Types +• NuGet.ProjectModel +• NuGet.Protocol.Core.Types +• NuGet.Protocol.Core.v3 +• NuGet.Repositories +• NuGet.RuntimeModel +• NuGet.Versioning +---------------------------------------------------------- + +Copyright (c) .NET Foundation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +these files except in compliance with the License. You may obtain a copy of the +License at + +https://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. + +------------------------------------------------- +PackageManagement +------------------------------------------------- + +Copyright (c) Microsoft Corporation +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the Software), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------- +PowerShellGet +------------------------------------------------- + +Copyright (c) Microsoft Corporation + +All rights reserved. + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + --------------------------------------------- File: PSReadLine --------------------------------------------- -https://github.com/lzybkr/PSReadLine +https://github.com/PowerShell/PSReadLine Copyright (c) 2013, Jason Shirk @@ -34,35 +162,16 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------- -File: Hashtables from ConvertFrom-json ----------------------------------------------- - -https://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h - -Copyright (c) 2015 Dave Wyatt. All rights reserved. - -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------- -PackageManagement +ThreadJob ------------------------------------------------- -Copyright (c) Microsoft Corporation -All rights reserved. +Copyright (c) 2018 Paul Higinbotham MIT License Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the Software), to deal +of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is @@ -71,40 +180,10 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------- -• NuGet.Common -• NuGet.Configuration -• NuGet.DependencyResolver.Core -• NuGet.Frameworks -• NuGet.LibraryModel -• NuGet.Packaging -• NuGet.Packaging.Core -• NuGet.Packaging.Core.Types -• NuGet.ProjectModel -• NuGet.Protocol.Core.Types -• NuGet.Protocol.Core.v3 -• NuGet.Repositories -• NuGet.RuntimeModel -• NuGet.Versioning ----------------------------------------------------------- - -Copyright (c) .NET Foundation. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -these files except in compliance with the License. You may obtain a copy of the -License at - -https://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. diff --git a/assets/wix/ExeLicense.rtf b/assets/wix/ExeLicense.rtf new file mode 100644 index 00000000000..09b0b1402a5 --- /dev/null +++ b/assets/wix/ExeLicense.rtf @@ -0,0 +1,206 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1032\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f1033\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f1035\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f1036\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f1037\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\f1038\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f1039\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f1040\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\f1372\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f1373\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f1375\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f1376\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;} +{\f1379\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f1380\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f1402\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f1403\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f1405\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f1406\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f1407\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f1408\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);} +{\f1409\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f1410\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;} +{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);} +{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} +{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;\chyperlink\ctint255\cshade255\red5\green99\blue193;\red96\green94\blue92;\red225\green223\blue221;} +{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\af0\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\* +\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf19 \sbasedon10 \sunhideused \styrsid11998831 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \cf20\chshdng0\chcfpat0\chcbpat21 \sbasedon10 \ssemihidden \sunhideused \styrsid11998831 +Unresolved Mention;}{\s17\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext17 \ssemihidden \sunhideused \styrsid11998831 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid203718\rsid534261\rsid10121125\rsid11155465 +\rsid11998831\rsid15422468\rsid15613908}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Travis Plunk}{\operator Travis Plunk} +{\creatim\yr2021\mo2\dy19\hr9\min23}{\revtim\yr2021\mo2\dy19\hr12\min33}{\version4}{\edmins5}{\nofpages1}{\nofwords75}{\nofchars430}{\nofcharsws504}{\vern6021}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen +\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1 +\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct +\asianbrkrule\rsidroot11998831\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0 +{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang +{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}} +\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15422468 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid15422468\charrsid15422468 This application is licensed under the\~}{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11155465 HYPERLINK "https://aka.ms/PowerShellLicense"}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid11155465\charrsid15422468 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5a000000680074007400700073003a002f002f0061006b0061002e006d0073002f0050006f007700650072005300680065006c006c004c006900630065006e00730065000000795881f43b1d7f48af2c825dc4852763 +0000000085ab000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf19\insrsid15422468\charrsid15422468 MIT License}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid15422468\charrsid15422468 +. +\par You may review the\~}{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11155465 HYPERLINK "https://aka.ms/PowerShellThirdPartyNotices"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11155465\charrsid15422468 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6e000000680074007400700073003a002f002f0061006b0061002e006d0073002f0050006f007700650072005300680065006c006c0054006800690072006400500061007200740079004e006f007400690063006500 +73000000795881f43b1d7f48af2c825dc48527630000000085ab000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf19\insrsid15422468\charrsid15422468 ThirdPartyNotices}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid15422468\charrsid15422468 . +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid15422468\charrsid15422468 This application collects telemetry under the\~}{\field\fldedit{\*\fldinst {\rtlch\fcs1 +\af0 \ltrch\fcs0 \insrsid534261 HYPERLINK "https://aka.ms/PrivacyPolicy"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid534261 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b52000000680074007400700073003a002f002f0061006b0061002e006d0073002f00500072006900760061006300790050006f006c006900630079000000795881f43b1d7f48af2c825dc48527630000000085ab0000} +}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf19\insrsid15422468\charrsid15422468 Microsoft Privacy Statement}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid15422468\charrsid15422468 +. To opt out, see\~}{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11155465 HYPERLINK "https://aka.ms/PowerShellTelemetryOptOut" \\o "Original URL:https://github.com/PowerShell/PowerS +hell/blob/master/README.md#telemetryClick to follow link."}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11155465\charrsid15422468 {\*\datafield +10d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f0061006b0061002e006d0073002f0050006f007700650072005300680065006c006c00540065006c0065006d0065007400720079004f00700074004f00750074000000 +795881f43b1d7f48af2c825dc48527630000000085ab000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf19\insrsid15422468\charrsid15422468 here}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid15422468\charrsid15422468 .}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11998831 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f +7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd +ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d +7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b +d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52 +fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71 +b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b +fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567 +9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd +79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf +5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2 +d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1 +738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68 +2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac +5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a +b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9 +493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2 +be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f +f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64 +7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e +b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4 +6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd +f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d +7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39 +4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf +1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a +faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2 +67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9 +416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27 +1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b +8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4 +8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65 +2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36 +3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e +3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985 +0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000 +0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000 +000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000 +7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000 +000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000 +000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax376\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; +\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; +\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; +\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; +\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; +\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; +\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; +\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; +\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; +\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; +\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; +\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; +\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; +\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; +\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; +\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; +\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Link;}}{\*\datastore }} \ No newline at end of file diff --git a/assets/Product.wxs b/assets/wix/Product.wxs similarity index 84% rename from assets/Product.wxs rename to assets/wix/Product.wxs index a0ab0692706..3691f5268ca 100644 --- a/assets/Product.wxs +++ b/assets/wix/Product.wxs @@ -53,9 +53,9 @@ - - - + + + @@ -84,6 +84,16 @@ Execute="deferred" Return="ignore" Impersonate="no" /> + + Installed AND NOT UPGRADINGPRODUCTCODE @@ -93,6 +103,9 @@ + + + @@ -135,6 +148,7 @@ + @@ -176,6 +190,13 @@ + + USE_MU=1 + + + + + @@ -317,6 +338,41 @@ + + + + + + + + + + + + + + + + + "1"]]> + "1" AND USE_MU="1"]]> + + + See the Microsoft Update FAQ]]> + + + Read the Microsoft Update Priacy Statement]]> + + + + + + + 1 + + + + @@ -325,6 +381,7 @@ - WixUI_WelcomeDlg - WixUI_InstallDirDlg - ExplorerContextMenuDialog + - MuDialog - WixUI_VerifyReadyDlg - WixUI_DiskCostDlg Maintenance dialog sequence: @@ -364,7 +421,9 @@ Installed AND PATCH 1 - 1 + 1 + 1 + 1 1 1 @@ -375,7 +434,7 @@ 1 1 - NOT Installed + NOT Installed Installed AND NOT PATCH Installed AND PATCH diff --git a/assets/WixUIBannerBmp.png b/assets/wix/WixUIBannerBmp.png similarity index 100% rename from assets/WixUIBannerBmp.png rename to assets/wix/WixUIBannerBmp.png diff --git a/assets/WixUIDialogBmp.png b/assets/wix/WixUIDialogBmp.png similarity index 100% rename from assets/WixUIDialogBmp.png rename to assets/wix/WixUIDialogBmp.png diff --git a/assets/WixUIInfoIco.png b/assets/wix/WixUIInfoIco.png similarity index 100% rename from assets/WixUIInfoIco.png rename to assets/wix/WixUIInfoIco.png diff --git a/assets/wix/bundle.wxs b/assets/wix/bundle.wxs new file mode 100644 index 00000000000..dc577cb36b0 --- /dev/null +++ b/assets/wix/bundle.wxs @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/files.wxs b/assets/wix/files.wxs similarity index 95% rename from assets/files.wxs rename to assets/wix/files.wxs index bf47743e985..13e38dbdd68 100644 --- a/assets/files.wxs +++ b/assets/wix/files.wxs @@ -104,9 +104,6 @@ - - - @@ -1163,9 +1160,6 @@ - - - @@ -1602,18 +1596,9 @@ - - - - - - - - - @@ -1623,11 +1608,35 @@ - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + @@ -1647,49 +1656,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1834,12 +1810,6 @@ - - - - - - @@ -1996,9 +1966,6 @@ - - - @@ -2020,6 +1987,12 @@ + + + + + + @@ -2061,9 +2034,6 @@ - - - @@ -2082,6 +2052,12 @@ + + + + + + @@ -2090,9 +2066,6 @@ - - - @@ -2144,6 +2117,12 @@ + + + + + + @@ -2152,9 +2131,6 @@ - - - @@ -2206,6 +2182,12 @@ + + + + + + @@ -2247,9 +2229,6 @@ - - - @@ -2268,6 +2247,12 @@ + + + + + + @@ -2294,9 +2279,6 @@ - - - @@ -2330,6 +2312,12 @@ + + + + + + @@ -2374,9 +2362,6 @@ - - - @@ -2392,6 +2377,12 @@ + + + + + + @@ -2403,9 +2394,6 @@ - - - @@ -2454,6 +2442,12 @@ + + + + + + @@ -2492,9 +2486,6 @@ - - - @@ -2516,6 +2507,12 @@ + + + + + + @@ -2560,9 +2557,6 @@ - - - @@ -2578,6 +2572,12 @@ + + + + + + @@ -2625,9 +2625,6 @@ - - - @@ -2640,6 +2637,12 @@ + + + + + + @@ -2660,9 +2663,6 @@ - - - @@ -2702,6 +2702,12 @@ + + + + + + @@ -2749,9 +2755,6 @@ - - - @@ -2764,6 +2767,12 @@ + + + + + + @@ -3105,14 +3114,45 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + @@ -3152,7 +3192,6 @@ - @@ -3505,7 +3544,6 @@ - @@ -3651,26 +3689,12 @@ - - - - - - - - - - - - - - @@ -3708,8 +3732,6 @@ - - @@ -3752,7 +3774,6 @@ - @@ -3773,7 +3794,6 @@ - @@ -3782,7 +3802,6 @@ - @@ -3802,7 +3821,6 @@ - @@ -3833,7 +3851,6 @@ - @@ -3848,7 +3865,6 @@ - @@ -3874,7 +3890,6 @@ - @@ -3883,7 +3898,6 @@ - @@ -3912,7 +3926,6 @@ - @@ -3934,7 +3947,6 @@ - @@ -3955,7 +3967,6 @@ - @@ -3966,7 +3977,6 @@ - @@ -3995,7 +4005,6 @@ - @@ -4113,11 +4122,54 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/patch-template.wxs b/assets/wix/patch-template.wxs similarity index 100% rename from assets/patch-template.wxs rename to assets/wix/patch-template.wxs diff --git a/build.psm1 b/build.psm1 index 0b99a020ec2..a68d7351014 100644 --- a/build.psm1 +++ b/build.psm1 @@ -13,7 +13,11 @@ Set-StrictMode -Version 3.0 $script:TestModulePathSeparator = [System.IO.Path]::PathSeparator $script:Options = $null -$dotnetCLIChannel = $(Get-Content $PSScriptRoot/DotnetRuntimeMetadata.json | ConvertFrom-Json).Sdk.Channel +$dotnetMetadata = Get-Content $PSScriptRoot/DotnetRuntimeMetadata.json | ConvertFrom-Json +$dotnetCLIChannel = $dotnetMetadata.Sdk.Channel +$dotnetCLIQuality = $dotnetMetadata.Sdk.Quality +$dotnetAzureFeed = $dotnetMetadata.Sdk.azureFeed +$dotnetSDKVersionOveride = $dotnetMetadata.Sdk.sdkImageOverride $dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version # Track if tags have been sync'ed @@ -31,14 +35,21 @@ function Sync-PSTags $AddRemoteIfMissing ) - $PowerShellRemoteUrl = "https://github.com/PowerShell/PowerShell.git" + $powerShellRemoteUrls = @( + 'https://github.com/PowerShell/PowerShell' + 'git@github.com:PowerShell/PowerShell' + ) + $defaultRemoteUrl = "$($powerShellRemoteUrls[0]).git" + $upstreamRemoteDefaultName = 'upstream' $remotes = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote} $upstreamRemote = $null foreach($remote in $remotes) { $url = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote get-url $remote} - if($url -eq $PowerShellRemoteUrl) + if ($url.EndsWith('.git')) { $url = $url.Substring(0, $url.Length - 4) } + + if($url -in $powerShellRemoteUrls) { $upstreamRemote = $remote break @@ -47,12 +58,12 @@ function Sync-PSTags if(!$upstreamRemote -and $AddRemoteIfMissing.IsPresent -and $remotes -notcontains $upstreamRemoteDefaultName) { - $null = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote add $upstreamRemoteDefaultName $PowerShellRemoteUrl} + $null = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote add $upstreamRemoteDefaultName $defaultRemoteUrl} $upstreamRemote = $upstreamRemoteDefaultName } elseif(!$upstreamRemote) { - Write-Error "Please add a remote to PowerShell\PowerShell. Example: git remote add $upstreamRemoteDefaultName $PowerShellRemoteUrl" -ErrorAction Stop + Write-Error "Please add a remote to PowerShell\PowerShell. Example: git remote add $upstreamRemoteDefaultName $defaultRemoteUrl" -ErrorAction Stop } $null = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" fetch --tags --quiet $upstreamRemote} @@ -122,7 +133,7 @@ function Get-EnvironmentInformation if ($environment.IsWindows) { $environment += @{'IsAdmin' = (New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)} - $environment += @{'nugetPackagesRoot' = "${env:USERPROFILE}\.nuget\packages"} + $environment += @{'nugetPackagesRoot' = "${env:USERPROFILE}\.nuget\packages", "${env:NUGET_PACKAGES}"} } else { @@ -133,6 +144,10 @@ function Get-EnvironmentInformation $environment += @{'UsingHomebrew' = [bool](Get-Command brew -ErrorAction ignore)} $environment += @{'UsingMacports' = [bool](Get-Command port -ErrorAction ignore)} + $environment += @{ + 'OSArchitecture' = if ((uname -v) -match 'ARM64') { 'arm64' } else { 'x64' } + } + if (-not($environment.UsingHomebrew -or $environment.UsingMacports)) { throw "Neither Homebrew nor MacPorts is installed on this system, visit https://brew.sh/ or https://www.macports.org/ to continue" } @@ -156,6 +171,7 @@ function Get-EnvironmentInformation $environment += @{'IsUbuntu' = $LinuxInfo.ID -match 'ubuntu' -or $LinuxID -match 'Ubuntu'} $environment += @{'IsUbuntu16' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '16.04'} $environment += @{'IsUbuntu18' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '18.04'} + $environment += @{'IsUbuntu20' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '20.04'} $environment += @{'IsCentOS' = $LinuxInfo.ID -match 'centos' -and $LinuxInfo.VERSION_ID -match '7'} $environment += @{'IsFedora' = $LinuxInfo.ID -match 'fedora' -and $LinuxInfo.VERSION_ID -ge 24} $environment += @{'IsOpenSUSE' = $LinuxInfo.ID -match 'opensuse'} @@ -270,6 +286,7 @@ function Start-PSBuild { [Parameter(ParameterSetName="Default")] [switch]$NoPSModuleRestore, [switch]$CI, + [switch]$ForMinimalSize, # Skips the step where the pwsh that's been built is used to create a configuration # Useful when changing parsing/compilation, since bugs there can mean we can't get past this step @@ -288,6 +305,7 @@ function Start-PSBuild { "linux-arm", "linux-arm64", "linux-x64", + "osx-arm64", "osx-x64", "win-arm", "win-arm64", @@ -298,15 +316,19 @@ function Start-PSBuild { [ValidateSet('Debug', 'Release', 'CodeCoverage', '')] # We might need "Checked" as well [string]$Configuration, - [switch]$CrossGen, - - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [ValidateNotNullOrEmpty()] [string]$ReleaseTag, [switch]$Detailed, - [switch]$InteractiveAuth + [switch]$InteractiveAuth, + [switch]$SkipRoslynAnalyzers, + [string]$PSOptionsPath ) + if ($ReleaseTag -and $ReleaseTag -notmatch "^v\d+\.\d+\.\d+(-(preview|rc)(\.\d{1,2})?)?$") { + Write-Warning "Only preview or rc are supported for releasing pre-release version of PowerShell" + } + if ($PSCmdlet.ParameterSetName -eq "Default" -and !$NoPSModuleRestore) { $PSModuleRestore = $true @@ -319,6 +341,13 @@ function Start-PSBuild { if ("win-arm","win-arm64" -contains $Runtime -and -not $environment.IsWindows) { throw "Cross compiling for win-arm or win-arm64 is only supported on Windows environment" } + + if ($ForMinimalSize) { + if ($Runtime -and "linux-x64", "win7-x64", "osx-x64" -notcontains $Runtime) { + throw "Build for the minimal size is enabled only for following runtimes: 'linux-x64', 'win7-x64', 'osx-x64'" + } + } + function Stop-DevPowerShell { Get-Process pwsh* | Where-Object { @@ -336,7 +365,8 @@ function Start-PSBuild { try { # Excluded sqlite3 folder is due to this Roslyn issue: https://github.com/dotnet/roslyn/issues/23060 # Excluded src/Modules/nuget.config as this is required for release build. - git clean -fdX --exclude .vs/PowerShell/v16/Server/sqlite3 --exclude src/Modules/nuget.config + # Excluded nuget.config as this is required for release build. + git clean -fdX --exclude .vs/PowerShell/v16/Server/sqlite3 --exclude src/Modules/nuget.config --exclude nuget.config } finally { Pop-Location } @@ -358,7 +388,8 @@ function Start-PSBuild { } # Verify if the dotnet in-use is the required version - $dotnetCLIInstalledVersion = Start-NativeExecution -sb { dotnet --version } -IgnoreExitcode + $dotnetCLIInstalledVersion = Get-LatestInstalledSDK + If ($dotnetCLIInstalledVersion -ne $dotnetCLIRequiredVersion) { Write-Warning @" The currently installed .NET Command Line Tools is not the required version. @@ -380,13 +411,13 @@ Fix steps: # set output options $OptionsArguments = @{ - CrossGen=$CrossGen Output=$Output Runtime=$Runtime Configuration=$Configuration Verbose=$true SMAOnly=[bool]$SMAOnly PSModuleRestore=$PSModuleRestore + ForMinimalSize=$ForMinimalSize } $script:Options = New-PSOptions @OptionsArguments @@ -395,11 +426,26 @@ Fix steps: } # setup arguments - $Arguments = @("publish","--no-restore","/property:GenerateFullPaths=true") + # adding ErrorOnDuplicatePublishOutputFiles=false due to .NET SDk issue: https://github.com/dotnet/sdk/issues/15748 + # removing --no-restore due to .NET SDK issue: https://github.com/dotnet/sdk/issues/18999 + # $Arguments = @("publish","--no-restore","/property:GenerateFullPaths=true", "/property:ErrorOnDuplicatePublishOutputFiles=false") + $Arguments = @("publish","/property:GenerateFullPaths=true", "/property:ErrorOnDuplicatePublishOutputFiles=false") if ($Output -or $SMAOnly) { $Arguments += "--output", (Split-Path $Options.Output) } + # Add --self-contained due to "warning NETSDK1179: One of '--self-contained' or '--no-self-contained' options are required when '--runtime' is used." + if ($Options.Runtime -like 'fxdependent*') { + $Arguments += "--no-self-contained" + # The UseAppHost = false property avoids creating ".exe" for the fxdependent packages. + # The ".exe" is not a cross-platform executable, but specific to the platform that it was built on. + # We do not need to ship that. + $Arguments += "/property:UseAppHost=false" + } + else { + $Arguments += "--self-contained" + } + if ($Options.Runtime -like 'win*' -or ($Options.Runtime -like 'fxdependent*' -and $environment.IsWindows)) { $Arguments += "/property:IsWindows=true" } @@ -410,7 +456,7 @@ Fix steps: # Framework Dependent builds do not support ReadyToRun as it needs a specific runtime to optimize for. # The property is set in Powershell.Common.props file. # We override the property through the build command line. - if($Options.Runtime -like 'fxdependent*') { + if($Options.Runtime -like 'fxdependent*' -or $ForMinimalSize) { $Arguments += "/property:PublishReadyToRun=false" } @@ -432,6 +478,10 @@ Fix steps: $Arguments += "/property:ReleaseTag=$ReleaseTagToUse" } + if ($SkipRoslynAnalyzers) { + $Arguments += "/property:RunAnalyzersDuringBuild=false" + } + # handle Restore Restore-PSPackage -Options $Options -Force:$Restore -InteractiveAuth:$InteractiveAuth @@ -463,21 +513,18 @@ Fix steps: Push-Location $Options.Top if ($Options.Runtime -notlike 'fxdependent*') { - if ($Options.Runtime -like 'win-arm*') { - $Arguments += "/property:SDKToUse=Microsoft.NET.Sdk" - } else { - $Arguments += "/property:SDKToUse=Microsoft.NET.Sdk.WindowsDesktop" + $sdkToUse = 'Microsoft.NET.Sdk' + if ($Options.Runtime -like 'win7-*' -and !$ForMinimalSize) { + ## WPF/WinForm and the PowerShell GraphicalHost assemblies are included + ## when 'Microsoft.NET.Sdk.WindowsDesktop' is used. + $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop' } + $Arguments += "/property:SDKToUse=$sdkToUse" + Write-Log -message "Run dotnet $Arguments from $PWD" Start-NativeExecution { dotnet $Arguments } Write-Log -message "PowerShell output: $($Options.Output)" - - if ($CrossGen) { - ## fxdependent package cannot be CrossGen'ed - Start-CrossGen -PublishPath $publishPath -Runtime $script:Options.Runtime - Write-Log -message "pwsh.exe with ngen binaries is available at: $($Options.Output)" - } } else { $globalToolSrcFolder = Resolve-Path (Join-Path $Options.Top "../Microsoft.PowerShell.GlobalTool.Shim") | Select-Object -ExpandProperty Path @@ -585,18 +632,23 @@ Fix steps: -not ($Runtime -like 'fxdependent*')) { $json = & $publishPath\pwsh -noprofile -command { - $expFeatures = [System.Collections.Generic.List[string]]::new() - Get-ExperimentalFeature | ForEach-Object { $expFeatures.Add($_.Name) } + # Special case for DSC code in PS; + # this experimental feature requires new DSC module that is not inbox, + # so we don't want default DSC use case be broken + [System.Collections.ArrayList] $expFeatures = Get-ExperimentalFeature | Where-Object Name -NE PS7DscSupport | ForEach-Object -MemberName Name + + $expFeatures | Out-String | Write-Verbose -Verbose # Make sure ExperimentalFeatures from modules in PSHome are added # https://github.com/PowerShell/PowerShell/issues/10550 - @("PSDesiredStateConfiguration.InvokeDscResource") | ForEach-Object { + $ExperimentalFeaturesFromGalleryModulesInPSHome = @() + $ExperimentalFeaturesFromGalleryModulesInPSHome | ForEach-Object { if (!$expFeatures.Contains($_)) { - $expFeatures.Add($_) + $null = $expFeatures.Add($_) } } - ConvertTo-Json $expFeatures.ToArray() + ConvertTo-Json $expFeatures } $config += @{ ExperimentalFeatures = ([string[]] ($json | ConvertFrom-Json)) } @@ -611,6 +663,15 @@ Fix steps: if ($CI) { Restore-PSPester -Destination (Join-Path $publishPath "Modules") } + + if ($PSOptionsPath) { + $resolvedPSOptionsPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($PSOptionsPath) + $parent = Split-Path -Path $resolvedPSOptionsPath + if (!(Test-Path $parent)) { + $null = New-Item -ItemType Directory -Path $parent + } + Save-PSOptions -PSOptionsPath $PSOptionsPath -Options $Options + } } function Restore-PSPackage @@ -627,7 +688,9 @@ function Restore-PSPackage [switch] $Force, - [switch] $InteractiveAuth + [switch] $InteractiveAuth, + + [switch] $PSModule ) if (-not $ProjectDirs) @@ -641,17 +704,20 @@ function Restore-PSPackage if ($Force -or (-not (Test-Path "$($Options.Top)/obj/project.assets.json"))) { - $sdkToUse = if (($Options.Runtime -eq 'fxdependent-win-desktop' -or $Options.Runtime -like 'win*')) { # this is fxd or some windows runtime - if ($Options.Runtime -like 'win-arm*') { - 'Microsoft.NET.Sdk' - } else { - 'Microsoft.NET.Sdk.WindowsDesktop' + if ($Options.Runtime -eq 'fxdependent-win-desktop') { + $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop' + } + else { + $sdkToUse = 'Microsoft.NET.Sdk' + if ($Options.Runtime -like 'win7-*' -and !$Options.ForMinimalSize) { + $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop' } - } else { - 'Microsoft.NET.Sdk' } - if ($Options.Runtime -notlike 'fxdependent*') { + if ($PSModule.IsPresent) { + $RestoreArguments = @("--verbosity") + } + elseif ($Options.Runtime -notlike 'fxdependent*') { $RestoreArguments = @("--runtime", $Options.Runtime, "/property:SDKToUse=$sdkToUse", "--verbosity") } else { $RestoreArguments = @("/property:SDKToUse=$sdkToUse", "--verbosity") @@ -741,8 +807,8 @@ function New-PSOptions { [ValidateSet("Debug", "Release", "CodeCoverage", '')] [string]$Configuration, - [ValidateSet("net5.0")] - [string]$Framework = "net5.0", + [ValidateSet("net6.0")] + [string]$Framework = "net6.0", # These are duplicated from Start-PSBuild # We do not use ValidateScript since we want tab completion @@ -753,6 +819,7 @@ function New-PSOptions { "linux-arm", "linux-arm64", "linux-x64", + "osx-arm64", "osx-x64", "win-arm", "win-arm64", @@ -760,8 +827,6 @@ function New-PSOptions { "win7-x86")] [string]$Runtime, - [switch]$CrossGen, - # Accept a path to the output directory # If not null or empty, name of the executable will be appended to # this path, otherwise, to the default path, and then the full path @@ -770,7 +835,9 @@ function New-PSOptions { [switch]$SMAOnly, - [switch]$PSModuleRestore + [switch]$PSModuleRestore, + + [switch]$ForMinimalSize ) # Add .NET CLI tools to PATH @@ -787,7 +854,12 @@ function New-PSOptions { if ($environment.IsLinux) { $Runtime = "linux-x64" } elseif ($environment.IsMacOS) { - $Runtime = "osx-x64" + if ($PSVersionTable.OS.Contains('ARM64')) { + $Runtime = "osx-arm64" + } + else { + $Runtime = "osx-x64" + } } else { $RID = dotnet --info | ForEach-Object { if ($_ -match "RID") { @@ -795,7 +867,7 @@ function New-PSOptions { } } - # We plan to release packages targetting win7-x64 and win7-x86 RIDs, + # We plan to release packages targeting win7-x64 and win7-x86 RIDs, # which supports all supported windows platforms. # So we, will change the RID to win7- $Runtime = $RID -replace "win\d+", "win7" @@ -860,11 +932,11 @@ function New-PSOptions { -RootInfo ([PSCustomObject]$RootInfo) ` -Top $Top ` -Runtime $Runtime ` - -Crossgen $Crossgen.IsPresent ` -Configuration $Configuration ` -PSModuleRestore $PSModuleRestore.IsPresent ` -Framework $Framework ` - -Output $Output + -Output $Output ` + -ForMinimalSize $ForMinimalSize } # Get the Options of the last build @@ -1152,7 +1224,13 @@ function Start-PSPester { if ($Unelevate) { - $outputBufferFilePath = [System.IO.Path]::GetTempFileName() + if ($environment.IsWindows) { + $outputBufferFilePath = [System.IO.Path]::GetTempFileName() + } + else { + # Azure DevOps agents do not have Temp folder setup on Ubuntu 20.04, hence using HOME directory + $outputBufferFilePath = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } } $command += "Invoke-Pester " @@ -1234,7 +1312,14 @@ function Start-PSPester { $PSFlags = @("-noprofile") if (-not [string]::IsNullOrEmpty($ExperimentalFeatureName)) { - $configFile = [System.IO.Path]::GetTempFileName() + + if ($environment.IsWindows) { + $configFile = [System.IO.Path]::GetTempFileName() + } + else { + $configFile = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } + $configFile = [System.IO.Path]::ChangeExtension($configFile, ".json") ## Create the config.json file to enable the given experimental feature. @@ -1313,7 +1398,13 @@ function Start-PSPester { { if ($PassThru.IsPresent) { - $passThruFile = [System.IO.Path]::GetTempFileName() + if ($environment.IsWindows) { + $passThruFile = [System.IO.Path]::GetTempFileName() + } + else { + $passThruFile = Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName()) + } + try { $command += "| Export-Clixml -Path '$passThruFile' -Force" @@ -1651,12 +1742,20 @@ function Install-Dotnet { param( [string]$Channel = $dotnetCLIChannel, [string]$Version = $dotnetCLIRequiredVersion, + [string]$Quality = $dotnetCLIQuality, [switch]$NoSudo, [string]$InstallDir, [string]$AzureFeed, [string]$FeedCredential ) + Write-Verbose -Verbose "In install-dotnet" + + # This is needed workaround for RTM pre-release build as the SDK version is always 6.0.100 after installation for every pre-release + if ($dotnetCLIRequiredVersion -like '6.0.100-rtm.*') { + $dotnetCLIRequiredVersion = '6.0.100' + } + # This allows sudo install to be optional; needed when running in containers / as root # Note that when it is null, Invoke-Expression (but not &) must be used to interpolate properly $sudo = if (!$NoSudo) { "sudo" } @@ -1666,7 +1765,7 @@ function Install-Dotnet { # Install for Linux and OS X if ($environment.IsLinux -or $environment.IsMacOS) { - $curl = Get-Command -Name curl -CommandType Application -TotalCount 1 -ErrorAction Stop + $wget = Get-Command -Name wget -CommandType Application -TotalCount 1 -ErrorAction Stop # Uninstall all previous dotnet packages $uninstallScript = if ($environment.IsLinux -and $environment.IsUbuntu) { @@ -1677,28 +1776,47 @@ function Install-Dotnet { if ($uninstallScript) { Start-NativeExecution { - & $curl -sO $uninstallObtainUrl/uninstall/$uninstallScript + & $wget $uninstallObtainUrl/uninstall/$uninstallScript Invoke-Expression "$sudo bash ./$uninstallScript" } } else { Write-Warning "This script only removes prior versions of dotnet for Ubuntu and OS X" } + Write-Verbose -Verbose "Invoking install script" + # Install new dotnet 1.1.0 preview packages $installScript = "dotnet-install.sh" - Start-NativeExecution { - & $curl -sO $installObtainUrl/$installScript - $bashArgs = @("./$installScript", '-c', $Channel, '-v', $Version) + Write-Verbose -Message "downloading install script from $installObtainUrl/$installScript ..." -Verbose + & $wget $installObtainUrl/$installScript + + if ((Get-ChildItem "./$installScript").Length -eq 0) { + throw "./$installScript was 0 length" + } + + if ($Version) { + $bashArgs = @("./$installScript", '-v', $Version, '-q', $Quality) + } + elseif ($Channel) { + $bashArgs = @("./$installScript", '-c', $Channel, '-q', $Quality) + } if ($InstallDir) { $bashArgs += @('-i', $InstallDir) } if ($AzureFeed) { - $bashArgs += @('-AzureFeed', $AzureFeed, '-FeedCredential', $FeedCredential) + $bashArgs += @('-AzureFeed', $AzureFeed) } + if ($FeedCredential) { + $bashArgs += @('-FeedCredential', $FeedCredential) + } + + $bashArgs | Out-String | Write-Verbose -Verbose + + Start-NativeExecution { bash @bashArgs } } elseif ($environment.IsWindows) { @@ -1707,8 +1825,13 @@ function Install-Dotnet { Invoke-WebRequest -Uri $installObtainUrl/$installScript -OutFile $installScript if (-not $environment.IsCoreCLR) { $installArgs = @{ - Channel = $Channel - Version = $Version + Quality = $Quality + } + + if ($Version) { + $installArgs += @{ Version = $Version } + } elseif ($Channel) { + $installArgs += @{ Channel = $Channel } } if ($InstallDir) { @@ -1716,29 +1839,44 @@ function Install-Dotnet { } if ($AzureFeed) { - $installArgs += @{ - AzureFeed = $AzureFeed - $FeedCredential = $FeedCredential - } + $installArgs += @{AzureFeed = $AzureFeed} + } + + if ($FeedCredential) { + $installArgs += @{FeedCredential = $FeedCredential} } + $installArgs | Out-String | Write-Verbose -Verbose + & ./$installScript @installArgs } else { # dotnet-install.ps1 uses APIs that are not supported in .NET Core, so we run it with Windows PowerShell $fullPSPath = Join-Path -Path $env:windir -ChildPath "System32\WindowsPowerShell\v1.0\powershell.exe" $fullDotnetInstallPath = Join-Path -Path $PWD.Path -ChildPath $installScript - Start-NativeExecution { - $psArgs = @('-NoLogo', '-NoProfile', '-File', $fullDotnetInstallPath, '-Channel', $Channel, '-Version', $Version) - if ($InstallDir) { - $psArgs += @('-InstallDir', $InstallDir) - } + if ($Version) { + $psArgs = @('-NoLogo', '-NoProfile', '-File', $fullDotnetInstallPath, '-Version', $Version, '-Quality', $Quality) + } + elseif ($Channel) { + $psArgs = @('-NoLogo', '-NoProfile', '-File', $fullDotnetInstallPath, '-Channel', $Channel, '-Quality', $Quality) + } - if ($AzureFeed) { - $psArgs += @('-AzureFeed', $AzureFeed, '-FeedCredential', $FeedCredential) - } + if ($InstallDir) { + $psArgs += @('-InstallDir', $InstallDir) + } + + if ($AzureFeed) { + $psArgs += @('-AzureFeed', $AzureFeed) + } + + if ($FeedCredential) { + $psArgs += @('-FeedCredential', $FeedCredential) + } + + $psArgs | Out-String | Write-Verbose -Verbose + Start-NativeExecution { & $fullPSPath @psArgs } } @@ -1756,9 +1894,7 @@ function Get-RedHatPackageManager { } function Start-PSBootstrap { - [CmdletBinding( - SupportsShouldProcess=$true, - ConfirmImpact="High")] + [CmdletBinding()] param( [string]$Channel = $dotnetCLIChannel, # we currently pin dotnet-cli version, and will @@ -1774,6 +1910,10 @@ function Start-PSBootstrap { Push-Location $PSScriptRoot/tools + if ($dotnetSDKVersionOveride) { + $Version = $dotnetSDKVersionOveride + } + try { if ($environment.IsLinux -or $environment.IsMacOS) { # This allows sudo install to be optional; needed when running in containers / as root @@ -1903,14 +2043,18 @@ function Start-PSBootstrap { } } + Write-Verbose -Verbose "Calling Find-Dotnet from Start-PSBootstrap" + # Try to locate dotnet-SDK before installing it Find-Dotnet + Write-Verbose -Verbose "Back from calling Find-Dotnet from Start-PSBootstrap" + # Install dotnet-SDK $dotNetExists = precheck 'dotnet' $null $dotNetVersion = [string]::Empty if($dotNetExists) { - $dotNetVersion = Start-NativeExecution -sb { dotnet --version } -IgnoreExitcode + $dotNetVersion = Get-LatestInstalledSDK } if(!$dotNetExists -or $dotNetVersion -ne $dotnetCLIRequiredVersion -or $Force.IsPresent) { @@ -1925,6 +2069,12 @@ function Start-PSBootstrap { } $DotnetArguments = @{ Channel=$Channel; Version=$Version; NoSudo=$NoSudo } + + if ($dotnetAzureFeed) { + $null = $DotnetArguments.Add("AzureFeed", $dotnetAzureFeed) + $null = $DotnetArguments.Add("FeedCredential", $null) + } + Install-Dotnet @DotnetArguments } else { @@ -1946,6 +2096,12 @@ function Start-PSBootstrap { } } +function Get-LatestInstalledSDK { + Start-NativeExecution -sb { + dotnet --list-sdks | Select-String -Pattern '\d*.\d*.\d*(-\w*\.\d*)?' | ForEach-Object { [System.Management.Automation.SemanticVersion]::new($_.matches.value) } | Sort-Object -Descending | Select-Object -First 1 + } -IgnoreExitcode 2> $null +} + function Start-DevPowerShell { [CmdletBinding(DefaultParameterSetName='ConfigurationParamSet')] param( @@ -2078,17 +2234,29 @@ function Start-ResGen } function Find-Dotnet() { + Write-Verbose -Verbose "In Find-DotNet" + $originalPath = $env:PATH $dotnetPath = if ($environment.IsWindows) { "$env:LocalAppData\Microsoft\dotnet" } else { "$env:HOME/.dotnet" } + $chosenDotNetVersion = if($dotnetSDKVersionOveride) { + $dotnetSDKVersionOveride + } + else { + $dotnetCLIRequiredVersion + } + # If there dotnet is already in the PATH, check to see if that version of dotnet can find the required SDK # This is "typically" the globally installed dotnet if (precheck dotnet) { # Must run from within repo to ensure global.json can specify the required SDK version Push-Location $PSScriptRoot - $dotnetCLIInstalledVersion = Start-NativeExecution -sb { dotnet --version } -IgnoreExitcode 2> $null + $dotnetCLIInstalledVersion = Get-LatestInstalledSDK Pop-Location - if ($dotnetCLIInstalledVersion -ne $dotnetCLIRequiredVersion) { + + Write-Verbose -Verbose "dotnetCLIInstalledVersion = $dotnetCLIInstalledVersion`nchosenDotNetVersion = $chosenDotNetVersion" + + if ($dotnetCLIInstalledVersion -ne $chosenDotNetVersion) { Write-Warning "The 'dotnet' in the current path can't find SDK version ${dotnetCLIRequiredVersion}, prepending $dotnetPath to PATH." # Globally installed dotnet doesn't have the required SDK version, prepend the user local dotnet location $env:PATH = $dotnetPath + [IO.Path]::PathSeparator + $env:PATH @@ -2233,239 +2401,6 @@ function script:Start-NativeExecution } } -function Start-CrossGen { - [CmdletBinding()] - param( - [Parameter(Mandatory= $true)] - [ValidateNotNullOrEmpty()] - [String] - $PublishPath, - - [Parameter(Mandatory=$true)] - [ValidateSet("alpine-x64", - "linux-arm", - "linux-arm64", - "linux-x64", - "osx-x64", - "win-arm", - "win-arm64", - "win7-x64", - "win7-x86")] - [string] - $Runtime - ) - - function New-CrossGenAssembly { - param ( - [Parameter(Mandatory= $true)] - [ValidateNotNullOrEmpty()] - [String] - $AssemblyPath, - [Parameter(Mandatory= $true)] - [ValidateNotNullOrEmpty()] - [String] - $CrossgenPath - ) - - $outputAssembly = $AssemblyPath.Replace(".dll", ".ni.dll") - $platformAssembliesPath = Split-Path $AssemblyPath -Parent - $crossgenFolder = Split-Path $CrossgenPath - $niAssemblyName = Split-Path $outputAssembly -Leaf - - try { - Push-Location $crossgenFolder - - # Generate the ngen assembly - Write-Verbose "Generating assembly $niAssemblyName" - Start-NativeExecution { - & $CrossgenPath /ReadyToRun /MissingDependenciesOK /in $AssemblyPath /out $outputAssembly /Platform_Assemblies_Paths $platformAssembliesPath - } | Write-Verbose - } finally { - Pop-Location - } - } - - function New-CrossGenSymbol { - param ( - [Parameter(Mandatory= $true)] - [ValidateNotNullOrEmpty()] - [String] - $AssemblyPath, - [Parameter(Mandatory= $true)] - [ValidateNotNullOrEmpty()] - [String] - $CrossgenPath - ) - - - $platformAssembliesPath = Split-Path $AssemblyPath -Parent - $crossgenFolder = Split-Path $CrossgenPath - - try { - Push-Location $crossgenFolder - - $symbolsPath = [System.IO.Path]::ChangeExtension($assemblyPath, ".pdb") - - $createSymbolOptionName = $null - if($Environment.IsWindows) - { - $createSymbolOptionName = '-CreatePDB' - - } - elseif ($Environment.IsLinux) - { - $createSymbolOptionName = '-CreatePerfMap' - } - - if($createSymbolOptionName) - { - Start-NativeExecution { - & $CrossgenPath -readytorun -platform_assemblies_paths $platformAssembliesPath $createSymbolOptionName $platformAssembliesPath $AssemblyPath - } | Write-Verbose - } - - # Rename the corresponding ni.dll assembly to be the same as the IL assembly - $niSymbolsPath = [System.IO.Path]::ChangeExtension($symbolsPath, "ni.pdb") - Rename-Item $niSymbolsPath $symbolsPath -Force -ErrorAction Stop - } finally { - Pop-Location - } - } - - if (-not (Test-Path $PublishPath)) { - throw "Path '$PublishPath' does not exist." - } - - # Get the path to crossgen - $crossGenExe = if ($environment.IsWindows) { "crossgen.exe" } else { "crossgen" } - $generateSymbols = $false - - # The crossgen tool is only published for these particular runtimes - $crossGenRuntime = if ($environment.IsWindows) { - if ($Runtime -match "-x86") { - "win-x86" - } elseif ($Runtime -match "-x64") { - "win-x64" - $generateSymbols = $true - } elseif (!($env:PROCESSOR_ARCHITECTURE -match "arm")) { - throw "crossgen for 'win-arm' and 'win-arm64' must be run on that platform" - } - } elseif ($Runtime -eq "linux-arm") { - throw "crossgen is not available for 'linux-arm'" - } elseif ($Runtime -eq "linux-x64") { - $Runtime - # We should set $generateSymbols = $true, but the code needs to be adjusted for different extension on Linux - } else { - $Runtime - } - - if (-not $crossGenRuntime) { - throw "crossgen is not available for this platform" - } - - $dotnetRuntimeVersion = $script:Options.Framework -replace 'net' - - # Get the CrossGen.exe for the correct runtime with the latest version - $crossGenPath = Get-ChildItem $script:Environment.nugetPackagesRoot $crossGenExe -Recurse | ` - Where-Object { $_.FullName -match $crossGenRuntime } | ` - Where-Object { $_.FullName -match $dotnetRuntimeVersion } | ` - Sort-Object -Property FullName -Descending | ` - Select-Object -First 1 | ` - ForEach-Object { $_.FullName } - if (-not $crossGenPath) { - throw "Unable to find latest version of crossgen.exe. 'Please run Start-PSBuild -Clean' first, and then try again." - } - Write-Verbose "Matched CrossGen.exe: $crossGenPath" -Verbose - - # Crossgen.exe requires the following assemblies: - # mscorlib.dll - # System.Private.CoreLib.dll - # clrjit.dll on Windows or libclrjit.so/dylib on Linux/OS X - $crossGenRequiredAssemblies = @("mscorlib.dll", "System.Private.CoreLib.dll") - - $crossGenRequiredAssemblies += if ($environment.IsWindows) { - "clrjit.dll" - } elseif ($environment.IsLinux) { - "libclrjit.so" - } elseif ($environment.IsMacOS) { - "libclrjit.dylib" - } - - # Make sure that all dependencies required by crossgen are at the directory. - $crossGenFolder = Split-Path $crossGenPath - foreach ($assemblyName in $crossGenRequiredAssemblies) { - if (-not (Test-Path "$crossGenFolder\$assemblyName")) { - Copy-Item -Path "$PublishPath\$assemblyName" -Destination $crossGenFolder -Force -ErrorAction Stop - } - } - - # Common assemblies used by Add-Type or assemblies with high JIT and no pdbs to crossgen - $commonAssembliesForAddType = @( - "Microsoft.CodeAnalysis.CSharp.dll" - "Microsoft.CodeAnalysis.dll" - "System.Linq.Expressions.dll" - "Microsoft.CSharp.dll" - "System.Runtime.Extensions.dll" - "System.Linq.dll" - "System.Collections.Concurrent.dll" - "System.Collections.dll" - "Newtonsoft.Json.dll" - "System.IO.FileSystem.dll" - "System.Diagnostics.Process.dll" - "System.Threading.Tasks.Parallel.dll" - "System.Security.AccessControl.dll" - "System.Text.Encoding.CodePages.dll" - "System.Private.Uri.dll" - "System.Threading.dll" - "System.Security.Principal.Windows.dll" - "System.Console.dll" - "Microsoft.Win32.Registry.dll" - "System.IO.Pipes.dll" - "System.Diagnostics.FileVersionInfo.dll" - "System.Collections.Specialized.dll" - "Microsoft.ApplicationInsights.dll" - ) - - $fullAssemblyList = $commonAssembliesForAddType - - foreach ($assemblyName in $fullAssemblyList) { - $assemblyPath = Join-Path $PublishPath $assemblyName - New-CrossGenAssembly -CrossgenPath $crossGenPath -AssemblyPath $assemblyPath - } - - # - # With the latest dotnet.exe, the default load context is only able to load TPAs, and TPA - # only contains IL assembly names. In order to make the default load context able to load - # the NI PS assemblies, we need to replace the IL PS assemblies with the corresponding NI - # PS assemblies, but with the same IL assembly names. - # - Write-Verbose "PowerShell Ngen assemblies have been generated. Deploying ..." -Verbose - foreach ($assemblyName in $fullAssemblyList) { - - # Remove the IL assembly and its symbols. - $assemblyPath = Join-Path $PublishPath $assemblyName - $symbolsPath = [System.IO.Path]::ChangeExtension($assemblyPath, ".pdb") - - Remove-Item $assemblyPath -Force -ErrorAction Stop - - # Rename the corresponding ni.dll assembly to be the same as the IL assembly - $niAssemblyPath = [System.IO.Path]::ChangeExtension($assemblyPath, "ni.dll") - Rename-Item $niAssemblyPath $assemblyPath -Force -ErrorAction Stop - - # No symbols are available for Microsoft.CodeAnalysis.CSharp.dll, Microsoft.CodeAnalysis.dll, - # Microsoft.CodeAnalysis.VisualBasic.dll, and Microsoft.CSharp.dll. - if ($commonAssembliesForAddType -notcontains $assemblyName) { - Remove-Item $symbolsPath -Force -ErrorAction Stop - - if($generateSymbols) - { - Write-Verbose "Generating Symbols for $assemblyPath" - New-CrossGenSymbol -CrossgenPath $crossGenPath -AssemblyPath $assemblyPath - } - } - } -} - # Cleans the PowerShell repo - everything but the root folder function Clear-PSRepo { @@ -2499,7 +2434,7 @@ function Copy-PSGalleryModules Find-DotNet - Restore-PSPackage -ProjectDirs (Split-Path $CsProjPath) -Force:$Force.IsPresent + Restore-PSPackage -ProjectDirs (Split-Path $CsProjPath) -Force:$Force.IsPresent -PSModule $cache = dotnet nuget locals global-packages -l if ($cache -match "global-packages: (.*)") { @@ -2988,11 +2923,11 @@ function Restore-PSOptions { -RootInfo $options.RootInfo ` -Top $options.Top ` -Runtime $options.Runtime ` - -Crossgen $options.Crossgen ` -Configuration $options.Configuration ` -PSModuleRestore $options.PSModuleRestore ` -Framework $options.Framework ` - -Output $options.Output + -Output $options.Output ` + -ForMinimalSize $options.ForMinimalSize Set-PSOptions -Options $newOptions } @@ -3011,10 +2946,6 @@ function New-PSOptionsObject [String] $Runtime, - [Parameter(Mandatory)] - [Bool] - $CrossGen, - [Parameter(Mandatory)] [String] $Configuration, @@ -3029,7 +2960,11 @@ function New-PSOptionsObject [Parameter(Mandatory)] [String] - $Output + $Output, + + [Parameter(Mandatory)] + [Bool] + $ForMinimalSize ) return @{ @@ -3039,8 +2974,8 @@ function New-PSOptionsObject Framework = $Framework Runtime = $Runtime Output = $Output - CrossGen = $CrossGen PSModuleRestore = $PSModuleRestore + ForMinimalSize = $ForMinimalSize } } @@ -3281,8 +3216,10 @@ function New-NugetConfigFile - + + + <[FEEDNAME]> @@ -3296,3 +3233,23 @@ function New-NugetConfigFile Set-Content -Path (Join-Path $Destination 'nuget.config') -Value $content -Force } + +function Set-CorrectLocale +{ + if (-not $IsLinux) + { + return + } + + $environment = Get-EnvironmentInformation + if ($environment.IsUbuntu -and $environment.IsUbuntu20) + { + $env:LC_ALL = 'en_US.UTF-8' + $env:LANG = 'en_US.UTF-8' + sudo locale-gen $env:LANG + sudo update-locale + } + + # Output the locale to log it + locale +} diff --git a/cgmanifest.json b/cgmanifest.json new file mode 100644 index 00000000000..38ca28d18f1 --- /dev/null +++ b/cgmanifest.json @@ -0,0 +1,804 @@ +{ + "Registrations": [ + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.CodeAnalysis.Common", + "Version": "4.0.0-6.final" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.CodeAnalysis.CSharp", + "Version": "4.0.0-6.final" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.CSharp", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.Management.Infrastructure.Runtime.Unix", + "Version": "2.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.Management.Infrastructure.Runtime.Win", + "Version": "2.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.Management.Infrastructure", + "Version": "2.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.NETCore.Platforms", + "Version": "1.1.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.NETCore.Targets", + "Version": "1.1.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.NETCore.Windows.ApiSets", + "Version": "1.0.1" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "Microsoft.Win32.Registry", + "Version": "4.7.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Collections", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Globalization", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.IO", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Reflection.Extensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Reflection.Primitives", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Reflection", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Resources.ResourceManager", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Runtime.Handles", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Runtime.InteropServices", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Runtime", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Text.Encoding", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.any.System.Threading.Tasks", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.native.System", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.osx-arm64.runtime.native.System.IO.Ports", + "Version": "6.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.unix.System.Diagnostics.Debug", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.unix.System.Private.Uri", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.unix.System.Runtime.Extensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win.System.Diagnostics.Debug", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win.System.Runtime.Extensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win7.System.Private.Uri", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win7-x64.Microsoft.NETCore.Windows.ApiSets", + "Version": "1.0.1" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win7-x86.Microsoft.NETCore.Windows.ApiSets", + "Version": "1.0.1" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni", + "Version": "4.4.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win-x64.runtime.native.System.Data.SqlClient.sni", + "Version": "4.4.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "runtime.win-x86.runtime.native.System.Data.SqlClient.sni", + "Version": "4.4.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Collections.Immutable", + "Version": "5.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Collections", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Diagnostics.Debug", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Diagnostics.DiagnosticSource", + "Version": "5.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Dynamic.Runtime", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Globalization", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.IO", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Linq.Expressions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Linq", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Memory", + "Version": "4.5.4" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Numerics.Vectors", + "Version": "4.5.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.ObjectModel", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Private.Uri", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.DispatchProxy", + "Version": "4.7.1" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Emit.ILGeneration", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Emit.Lightweight", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Emit", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Extensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Metadata", + "Version": "5.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.Primitives", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection.TypeExtensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Reflection", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Resources.ResourceManager", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Runtime.Extensions", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Runtime.Handles", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Runtime.InteropServices", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Runtime", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Security.Principal.Windows", + "Version": "5.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Text.Encoding.CodePages", + "Version": "6.0.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Text.Encoding", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Threading.Tasks.Extensions", + "Version": "4.5.4" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Threading.Tasks", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Threading", + "Version": "4.3.0" + } + }, + "DevelopmentDependency": false + }, + { + "Component": { + "Type": "nuget", + "Nuget": { + "Name": "System.Web.Services.Description", + "Version": "4.9.0" + } + }, + "DevelopmentDependency": false + } + ] +} diff --git a/demos/crontab/CronTab/CronTab.psm1 b/demos/crontab/CronTab/CronTab.psm1 index d354419c9bf..4cb88e586b9 100644 --- a/demos/crontab/CronTab/CronTab.psm1 +++ b/demos/crontab/CronTab/CronTab.psm1 @@ -77,16 +77,22 @@ function Remove-CronJob { <# .SYNOPSIS Removes the exactly matching cron job from the cron table + .DESCRIPTION Removes the exactly matching cron job from the cron table + .EXAMPLE Get-CronJob | Where-Object {%_.Command -like 'foo *'} | Remove-CronJob + .RETURNVALUE None + .PARAMETER UserName Optional parameter to specify a specific user's cron table + .PARAMETER Job Cron job object returned from Get-CronJob + .PARAMETER Force Don't prompt when removing the cron job #> @@ -143,20 +149,28 @@ function New-CronJob { 0-23/2 or */2. .EXAMPLE New-CronJob -Minute 10-30 -Hour 10-20/2 -DayOfMonth */2 -Command "/bin/bash -c 'echo hello' > ~/hello" + .RETURNVALUE If successful, an object representing the cron job is returned + .PARAMETER UserName Optional parameter to specify a specific user's cron table + .PARAMETER Minute Valid values are 0 to 59. If not specified, defaults to *. + .PARAMETER Hour Valid values are 0-23. If not specified, defaults to *. + .PARAMETER DayOfMonth Valid values are 1-31. If not specified, defaults to *. + .PARAMETER Month Valid values are 1-12. If not specified, defaults to *. + .PARAMETER DayOfWeek Valid values are 0-7. 0 and 7 are both Sunday. If not specified, defaults to *. + .PARAMETER Command Command to execute at the scheduled time and day. #> @@ -190,12 +204,16 @@ function Get-CronJob { <# .SYNOPSIS Returns the current cron jobs from the cron table + .DESCRIPTION Returns the current cron jobs from the cron table + .EXAMPLE Get-CronJob -UserName Steve + .RETURNVALUE CronJob objects + .PARAMETER UserName Optional parameter to specify a specific user's cron table #> diff --git a/docker/tests/README.md b/docker/tests/README.md deleted file mode 100644 index 716a7d6f62e..00000000000 --- a/docker/tests/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Docker tests - -## Windows and Linux containers - -The tests must be run separately on the Windows and Linux docker daemons. You can use the Linux docker daemon on Windows, but that will only test Linux containers not Windows Containers. - -## To building and basic behavior of the containers - -```PowerShell -Invoke-Pester -``` - -Note: be sure to do this using both the Windows and Linux docker daemon. - -## To test the productions containers - -```PowerShell -Invoke-Pester -Tag Behavior -``` - -## To test only building the containers - -```PowerShell -Invoke-Pester -Tag Build -``` diff --git a/docker/tests/Templates/centos7/Dockerfile b/docker/tests/Templates/centos7/Dockerfile deleted file mode 100644 index dddf2439445..00000000000 --- a/docker/tests/Templates/centos7/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM centos:7 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN yum install -y \ - curl \ - glibc-locale-source \ - git - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME \ - && yum install -y $PACKAGENAME -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/debian.9/Dockerfile b/docker/tests/Templates/debian.9/Dockerfile deleted file mode 100644 index f2de0f8d61f..00000000000 --- a/docker/tests/Templates/debian.9/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM debian:stretch - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - curl \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dpkg -i $PACKAGENAME || : -RUN apt-get install -y -f --no-install-recommends -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fedora28/Dockerfile b/docker/tests/Templates/fedora28/Dockerfile deleted file mode 100644 index 9c9f958f54d..00000000000 --- a/docker/tests/Templates/fedora28/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM fedora:28 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN dnf install -y \ - curl \ - glibc-locale-source \ - git \ - compat-openssl10 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dnf install -y $PACKAGENAME -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-centos7/Dockerfile b/docker/tests/Templates/fxdependent-centos7/Dockerfile deleted file mode 100644 index 10cde0cd125..00000000000 --- a/docker/tests/Templates/fxdependent-centos7/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM centos:7 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN yum install -y \ - glibc-locale-source \ - git - -# Install dotnet-runtime -RUN rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm -RUN yum install -y \ - dotnet-runtime-2.1 - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-debian.9/Dockerfile b/docker/tests/Templates/fxdependent-debian.9/Dockerfile deleted file mode 100644 index 2d7beff913b..00000000000 --- a/docker/tests/Templates/fxdependent-debian.9/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM microsoft/dotnet:2.1.7-runtime-stretch-slim - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-dotnetsdk-latest/Dockerfile b/docker/tests/Templates/fxdependent-dotnetsdk-latest/Dockerfile deleted file mode 100644 index cf56e4ec074..00000000000 --- a/docker/tests/Templates/fxdependent-dotnetsdk-latest/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM microsoft/dotnet:3.0.100-preview-sdk - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell \ - && tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-fedora28/Dockerfile b/docker/tests/Templates/fxdependent-fedora28/Dockerfile deleted file mode 100644 index 6acb7452446..00000000000 --- a/docker/tests/Templates/fxdependent-fedora28/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM fedora:28 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN dnf install -y \ - glibc-locale-source \ - git \ - compat-openssl10 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Install dotnet-runtime -RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc -ADD https://packages.microsoft.com/config/fedora/27/prod.repo . -RUN mv prod.repo /etc/yum.repos.d/microsoft-prod.repo -RUN dnf install -y \ - dotnet-runtime-2.1 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell \ - && tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile b/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile deleted file mode 100644 index 74b4bc98256..00000000000 --- a/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM opensuse:42.3 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - glibc-locale \ - glibc-i18ndata \ - tar \ - libunwind \ - libicu \ - openssl \ - git - -# Install dotnet-runtime -ADD https://packages.microsoft.com/keys/microsoft.asc . -RUN rpmkeys --import microsoft.asc -ADD https://packages.microsoft.com/config/opensuse/42.2/prod.repo . -RUN mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - dotnet-runtime-2.1 - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-ubuntu16.04/Dockerfile b/docker/tests/Templates/fxdependent-ubuntu16.04/Dockerfile deleted file mode 100644 index aa976ddb19e..00000000000 --- a/docker/tests/Templates/fxdependent-ubuntu16.04/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM ubuntu:xenial - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Install dotnet-runtime -ADD https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb . -RUN dpkg -i packages-microsoft-prod.deb -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - dotnet-runtime-2.1 \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell \ - && tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile b/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile deleted file mode 100644 index adc9219a07d..00000000000 --- a/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM microsoft/dotnet:2.1.7-runtime-bionic - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell \ - && tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/opensuse42.3/Dockerfile b/docker/tests/Templates/opensuse42.3/Dockerfile deleted file mode 100644 index d401e611382..00000000000 --- a/docker/tests/Templates/opensuse42.3/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM opensuse:42.3 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -ARG POWERSHELL_LINKFILE=/usr/bin/pwsh - -# Install dependencies -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - glibc-locale \ - glibc-i18ndata \ - tar \ - curl \ - libunwind \ - libicu \ - openssl \ - git - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME - -# Create the target folder where powershell will be placed -RUN mkdir -p /opt/microsoft/powershell -# Expand powershell to the target folder -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Create the symbolic link that points to powershell -RUN ln -s /opt/microsoft/powershell/pwsh $POWERSHELL_LINKFILE - -RUN $TESTDOWNLOADCOMMAND -RUN pwsh -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/ubuntu16.04/Dockerfile b/docker/tests/Templates/ubuntu16.04/Dockerfile deleted file mode 100644 index 7439eda5a7d..00000000000 --- a/docker/tests/Templates/ubuntu16.04/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM ubuntu:xenial - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - curl \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dpkg -i $PACKAGENAME || : -RUN apt-get install -y -f --no-install-recommends -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/ubuntu18.04/Dockerfile b/docker/tests/Templates/ubuntu18.04/Dockerfile deleted file mode 100644 index 6c7a960130d..00000000000 --- a/docker/tests/Templates/ubuntu18.04/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM ubuntu:bionic - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - curl \ - apt-transport-https \ - locales \ - git \ - && apt-get clean - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dpkg -i $PACKAGENAME || : -RUN apt-get install -y -f --no-install-recommends -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/containerTestCommon.psm1 b/docker/tests/containerTestCommon.psm1 deleted file mode 100644 index c6b540abd77..00000000000 --- a/docker/tests/containerTestCommon.psm1 +++ /dev/null @@ -1,370 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -$script:forcePull = $true -# Get docker Engine OS -function Get-DockerEngineOs -{ - docker info --format '{{ .OperatingSystem }}' -} - -# Call Docker with appropriate result checksfunction Invoke-Docker -function Invoke-Docker -{ - param( - [Parameter(Mandatory=$true)] - [string[]] - $Command, - [ValidateSet("error","warning",'ignore')] - $FailureAction = 'error', - - [Parameter(Mandatory=$true)] - [string[]] - $Params, - - [switch] - $PassThru, - [switch] - $SuppressHostOutput - ) - - $ErrorActionPreference = 'Continue' - - # Log how we are running docker for troubleshooting issues - Write-Verbose "Running docker $command $params" -Verbose - if($SuppressHostOutput.IsPresent) - { - $result = docker $command $params 2>&1 - } - else - { - &'docker' $command $params 2>&1 | Tee-Object -Variable result -ErrorAction SilentlyContinue | Out-String -Stream -ErrorAction SilentlyContinue | Write-Host -ErrorAction SilentlyContinue - } - - $dockerExitCode = $LASTEXITCODE - if($PassThru.IsPresent) - { - Write-Verbose "passing through docker result$($result.length)..." -Verbose - return $result - } - elseif($dockerExitCode -ne 0 -and $FailureAction -eq 'error') - { - Write-Error "docker $command failed with: $result" -ErrorAction Stop - return $false - } - elseif($dockerExitCode -ne 0 -and $FailureAction -eq 'warning') - { - Write-Warning "docker $command failed with: $result" - return $false - } - elseif($dockerExitCode -ne 0) - { - return $false - } - - return $true -} - -# Return a list of Linux Container Test Cases -function Get-LinuxContainer -{ - foreach($os in 'centos7','ubuntu16.04') - { - Write-Output @{ - Name = $os - Path = "$PSScriptRoot/../release/$os" - } - } -} - -# Return a list of Windows Container Test Cases -function Get-WindowsContainer -{ - foreach($os in 'windowsservercore','nanoserver') - { - Write-Output @{ - Name = $os - Path = "$PSScriptRoot/../release/$os" - } - } -} - -$script:repoName = 'microsoft/powershell' -function Get-RepoName -{ - return $script:repoName -} - -function Set-RepoName -{ - param([string]$RepoName) - - $script:repoName = $RepoName - $script:forcePull = $false -} - -function Test-SkipWindows -{ - [bool] $canRunWindows = (Get-DockerEngineOs) -like 'Windows*' - return ($IsLinux -or $IsMacOS -or !$canRunWindows) -} - -function Test-SkipLinux -{ - $os = Get-DockerEngineOs - - switch -wildcard ($os) - { - '*Linux*' { - return $false - } - '*Mac' { - return $false - } - # Docker for Windows means we are running the linux kernel - 'Docker for Windows' { - return $false - } - 'Windows*' { - return $true - } - default { - throw "Unknown docker os '$os'" - } - } -} - -function Get-TestContext -{ - param( - [ValidateSet('Linux','Windows','macOS')] - [string]$Type - ) - - $resultFileName = 'results.xml' - $logFileName = 'results.log' - $containerTestDrive = '/test' - - # Return a windows context if the Context in Windows *AND* - # the current system is windows, otherwise Join-path will fail. - if($Type -eq 'Windows' -and $IsWindows) - { - $ContainerTestDrive = 'C:\test' - } - $resolvedTestDrive = (Resolve-Path "Testdrive:\").providerPath - - return @{ - ResolvedTestDrive = $resolvedTestDrive - ResolvedXmlPath = Join-Path $resolvedTestDrive -ChildPath $resultFileName - ResolvedLogPath = Join-Path $resolvedTestDrive -ChildPath $logFileName - ContainerTestDrive = $ContainerTestDrive - ContainerXmlPath = Join-Path $containerTestDrive -ChildPath $resultFileName - ContainerLogPath = Join-Path $containerTestDrive -ChildPath $logFileName - Type = $Type - ForcePull = $script:forcePull - } -} - -function Get-ContainerPowerShellVersion -{ - param( - [HashTable] $TestContext, - [string] $RepoName, - [string] $Name - ) - - $imageTag = "${script:repoName}:${Name}" - - if($TestContext.ForcePull) - { - $null=Invoke-Docker -Command 'image', 'pull' -Params $imageTag -SuppressHostOutput - } - - $runParams = @() - $localVolumeName = $testContext.resolvedTestDrive - $runParams += '--rm' - if($TestContext.Type -ne 'Windows' -and $IsWindows) - { - # use a container volume on windows because host volumes are not automatic - $volumeName = "test-volume-" + (Get-Random -Minimum 100 -Maximum 999) - - # using alpine because it's tiny - $null=Invoke-Docker -Command create -Params '-v', '/test', '--name', $volumeName, 'alpine' -SuppressHostOutput - $runParams += '--volumes-from' - $runParams += $volumeName - } - else { - $runParams += '-v' - $runParams += "${localVolumeName}:$($testContext.containerTestDrive)" - } - - $runParams += $imageTag - $runParams += 'pwsh' - $runParams += '-c' - $runParams += ('$PSVersionTable.PSVersion.ToString() | out-string | out-file -encoding ascii -FilePath '+$testContext.containerLogPath) - - $null = Invoke-Docker -Command run -Params $runParams -SuppressHostOutput - if($TestContext.Type -ne 'Windows' -and $IsWindows) - { - $null = Invoke-Docker -Command cp -Params "${volumeName}:$($testContext.containerLogPath)", $TestContext.ResolvedLogPath - $null = Invoke-Docker -Command container, rm -Params $volumeName, '--force' -SuppressHostOutput - } - return (Get-Content -Encoding Ascii $testContext.resolvedLogPath)[0] -} - -# Function defines a config mapping for testing Preview packages. -# The list of supported OS for each release can be found here: -# https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/docs-conceptual/PowerShell-Core-Support.md#supported-platforms -function Get-DefaultPreviewConfigForPackageValidation -{ - # format: = - @{ 'centos7'='rhel.7'; - 'debian.9'='debian.9'; - 'fedora28'='rhel.7'; - 'opensuse42.3'='linux-x64.tar.gz'; - 'ubuntu16.04'='ubuntu.16.04'; - 'ubuntu18.04'='ubuntu.18.04'; - 'fxdependent-centos7'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-debian.9'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-fedora28'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-opensuse42.3'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-ubuntu16.04'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-ubuntu18.04'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-dotnetsdk-latest'='linux-x64-fxd-dotnetsdk.tar.gz' - } -} - -# Function defines a config mapping for testing Stable packages. -# The list of supported OS for each release can be found here: -# https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/docs-conceptual/PowerShell-Core-Support.md#supported-platforms -function Get-DefaultStableConfigForPackageValidation -{ - # format: = - @{ 'centos7'='rhel.7'; - 'debian.9'='debian.9'; - 'opensuse42.3'='linux-x64.tar.gz'; - 'ubuntu16.04'='ubuntu.16.04'; - 'fxdependent-centos7'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-debian.9'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-opensuse42.3'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-ubuntu16.04'='linux-x64-fxdependent.tar.gz' - } -} - -# Returns a list of files in a specified Azure container. -function Get-PackageNamesOnAzureBlob -{ - param( - [string] - $ContainerUrl, - - # $SAS (shared access signature) param should include beginning '?' and trailing '&' - [string] - $SAS - ) - - - $response = Invoke-RestMethod -Method Get -Uri $($ContainerUrl + $SAS + 'restype=container&comp=list') - - $xmlResponce = [xml]$response.Substring($response.IndexOf(' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + + + + Start/End + User has idea! + + + + + + + + + + + + + + + + + + + User has idea! + + Dynamic connector + + + + Process + User files issue with rationale and use cases + + + + + + + + + + + + + + + + + + + User files issue with rationale and use cases + + Dynamic connector.9 + + + + Process.8 + Maintainers label issue with Area Label + + + + + + + + + + + + + + + + + + + Maintainers label issue with Area Label + + Dynamic connector.13 + No + + + + + No + + Process.12 + Users discuss idea “exhaustively” (TBD by WGs) + + + + + + + + + + + + + + + + + + + Users discuss idea exhaustively” (TBD by WGs) + + Dynamic connector.15 + + + + Decision + Do the WGs think the idea has potential / is worth pursuing? + + + + + + + + + + + + + + + + + + + Do the WGs think the idea has potential / is worth pursuing? + + Dynamic connector.23 + No + + + + + No + + Subprocess + Committee appeals process (TBD) + + + + + + + + + + + + + + + + + + + + + + + Committee appeals process (TBD) + + Dynamic connector.27 + Appeal unsuccessful + + + + + Appeal unsuccessful + + Start/End.26 + Issue is closed, idea not pursued within PS repo + + + + + + + + + + + + + + + + + + + + Issue is closed, idea not pursued within PS repo + + Dynamic connector.30 + Successful appeal + + + + + Successful appeal + + Process.32 + Implement and release the implementation outside of PS + + + + + + + + + + + + + + + + + + + Implement and release the implementation outside of PS + + Process.43 + WGs label “RFC required”; Both paths are (eventually) require... + + + + + + + + + + + + + + + + + + + + WGs label “RFC required”; Both paths are (eventually) required; author(s) can choose to do in any order + + Dynamic connector.46 + + + + Process.45 + Contributor writes and publishes RFC as draft PR in PowerShel... + + + + + + + + + + + + + + + + + + + + Contributor writes and publishes RFC as draft PR in PowerShell-RFC(add reference in original issue) + + Dynamic connector.48 + + + + Process.47 + Contributor publishes PR with WIP and/or prototype code as dr... + + + + + + + + + + + + + + + + + + + + Contributor publishes PR with WIP and/or prototype code as draft PR in PowerShell repo(add reference in original issue, Maintainers add `Proposal` label) + + Dynamic connector.50 + + + + Process.49 + WGs, contributors, and any others have discussion about RFC f... + + + + + + + + + + + + + + + + + + + WGs, contributors, and any others have discussion about RFC for >= 2 months + + Dynamic connector.52 + + + + Process.51 + Author marks RFC PR as non-draft + + + + + + + + + + + + + + + + + + + Author marks RFC PR as non-draft + + Dynamic connector.56 + + + + Decision.55 + Does the code PR meet WG and Maintainer standards? + + + + + + + + + + + + + + + + + + + + Does the code PR meet WG and Maintainer standards? + + Decision.65 + Is the RFC accepted and matching the implemen-tation? + + + + + + + + + + + + + + + + + + + + Is the RFC accepted and matching the implemen-tation? + + Dynamic connector.67 + No + + + + + No + + Dynamic connector.69 + + + + Start/End.68 + Merge as non-experimental code + + + + + + + + + + + + + + + + + + + Merge as non-experimental code + + Dynamic connector.71 + + + + Process.70 + Committee review + + + + + + + + + + + + + + + + + + + Committee review + + Decision.75 + Does the RFC contain all necessary info to merge as experimen... + + + + + + + + + + + + + + + + + + + + Does the RFC contain all necessary info to merge as experimental? + + Decision.77 + Committee votes to approve RFC + + + + + + + + + + + + + + + + + + + Committee votes to approve RFC + + Dynamic connector.79 + Reject + + + + + Reject + + Process.80 + RFC author adds additional info + + + + + + + + + + + + + + + + + + + RFC author adds additional info + + Dynamic connector.87 + Approve + + + + + Approve + + Decision.86 + Is the code ready to go? + + + + + + + + + + + + + + + + + + + Is the code ready to go? + + Dynamic connector.88 + Yes + + + + + Yes + + Dynamic connector.90 + No + + + + + No + + Decision.36 + Do you still think it needs to be in the PS package? + + + + + + + + + + + + + + + + + + + + Do you still think it needs to be in the PS package? + + Dynamic connector.1012 + Yes + + + + + Yes + + Decision.1006 + Can the idea be implemented outside of the PS code repo? + + + + + + + + + + + + + + + + + + + + Can the idea be implemented outside of the PS code repo? + + Dynamic connector.1007 + + + + Dynamic connector.1008 + Yes + + + + + Yes + + Dynamic connector.1001 + + + + Dynamic connector.1014 + + + + Decision.1015 + Do the WGs think an RFC is required? + + + + + + + + + + + + + + + + + + + Do the WGs think an RFC is required? + + Dynamic connector.1016 + Yes + + + + + Yes + + Dynamic connector.1017 + Yes + + + + + Yes + + Dynamic connector.1019 + No + + + + + No + + Process.1018 + WGs label “RFC not required”; Contributor opens a PR to be re... + + + + + + + + + + + + + + + + + + + + WGs label “RFC not required”; Contributor opens a PR to be reviewed by WGs and merged by maintainers + + Dynamic connector.1020 + Yes + + + + + Yes + + Process.1021 + Committee labels RFC PR with “Experimental - Approved” + + + + + + + + + + + + + + + + + + + Committee labels RFC PR with Experimental - Approved + + Dynamic connector.1023 + No + + + + + No + + Dynamic connector.1024 + + + + Dynamic connector.1026 + Yes + + + + + Yes + + Decision.1025 + Has the RFC been marked with “Experimental - Approved”? + + + + + + + + + + + + + + + + + + + + Has the RFC been marked with Experimental - Approved”? + + Dynamic connector.1028 + Yes + + + + + Yes + + Process.1027 + Merge code PR as Experimental Feature + + + + + + + + + + + + + + + + + + + Merge code PR as Experimental Feature + + Dynamic connector.1029 + No + + + + + No + + Dynamic connector.1031 + No + + + + + No + + Process.1030 + Contributor updates code PR based on feedback + + + + + + + + + + + + + + + + + + + Contributor updates code PR based on feedback + + Dynamic connector.1033 + + + + Decision.1032 + Has the code PR been merged as experimental? + + + + + + + + + + + + + + + + + + + + Has the code PR been merged as experimental? + + Dynamic connector.1034 + No + + + + + No + + Dynamic connector.1036 + Yes + + + + + Yes + + Decision.1035 + Does the Committee believe the experimental feature has had e... + + + + + + + + + + + + + + + + + + + + Does the Committee believe the experimental feature has had enough time to bake? + + Dynamic connector.1037 + Yes + + + + + Yes + + Dynamic connector.1038 + + + + Dynamic connector.1040 + + + + Decision.1039 + Does the Committee think the intent of the RFC is reasonable ... + + + + + + + + + + + + + + + + + + + + Does the Committee think the intent of the RFC is reasonable to pursue + + Dynamic connector.1041 + Yes + + + + + Yes + + Dynamic connector.1043 + No + + + + + No + + Start/End.1042 + Process stops + + + + + + + + + + + + + + + + + + + Process stops + + diff --git a/docs/community/process_diagram.vsdx b/docs/community/process_diagram.vsdx new file mode 100644 index 00000000000..014c28fa43d Binary files /dev/null and b/docs/community/process_diagram.vsdx differ diff --git a/docs/community/working-group-definitions.md b/docs/community/working-group-definitions.md new file mode 100644 index 00000000000..b7e9cf323a7 --- /dev/null +++ b/docs/community/working-group-definitions.md @@ -0,0 +1,185 @@ +# Working Group Definitions + +This document maintains a list of the current PowerShell [Working Groups (WG)](working-group.md), +as well as their definitions, membership, and a non-exhaustive set of examples of topics that fall +within the purview of that WG. + +For an up-to-date list of the issue/PR labels associated with these WGs, +see [Issue Management](../maintainers/issue-management.md) + +## Desired State Configuration (DSC) + +The Desired State Configuration (DSC) WG manages all facets of DSC in PowerShell 7, +including language features (like the `Configuration` keyword) +and the `PSDesiredStateConfiguration` module. + +Today, DSC is integrated into the PowerShell language, and we need to manage it as such. + +### Members + +* @TravisEz13 +* @theJasonHelmick +* @joeyaiello +* @anmenaga + +## Developer Experience + +The PowerShell developer experience includes the **development of modules** (in C#, PowerShell script, etc.), +as well as the experience of **hosting PowerShell and its APIs** in other applications and language runtimes. +Special consideration should be given to topics like **backwards compatibility** with Windows PowerShell +(e.g. with **PowerShell Standard**) and **integration with related developer tools** +(e.g. .NET CLI or the PowerShell extension for VS Code). + +### Members + +* @JamesWTruher (PS Standard, module authoring) +* @adityapatwardhan (SDK) +* @rjmholt (hosting, WinPS compatibility) + +## Engine + +The PowerShell engine is one of the largest and most complex aspects of the codebase. +The Engine WG should be focused on the +**implementation and maintenance of core PowerShell engine code**. +This includes (but is not limited to): + +* The language parser +* The command and parameter binders +* The module and provider systems + * `*-Item` cmdlets + * Providers +* Performance +* Componentization +* AssemblyLoadContext + +It's worth noting that the Engine WG is not responsible for the definition of the PowerShell language. +This should be handled by the Language WG instead. +However, it's expected that many issues will require input from both WGs. + +### Members + +* @BrucePay +* @daxian-dbw +* @JamesWTruher +* @rjmholt +* @rkeithhill +* @vexx32 + +## Interactive UX + +While much of PowerShell can be used through both interactive and non-interactive means, +some of the PowerShell user experience is exclusively interactive. +These topics include (but are not limited to): + +* Console +* Help System +* Tab completion / IntelliSense +* Markdown rendering +* PSReadLine +* Debugging + +### Members + +* @daxian-dbw (PSReadline / IntelliSense) +* @adityapatwardhan (Markdown / help system) +* @JamesWTruher (cmdlet design) + +## Language + +The Language WG is distinct from the Engine WG in that they deal with the abstract definition +of the PowerShell language itself. +While all WGs will be working closely with the PowerShell Committee (and may share members), +it's likely that the Language WG will work especially close with them, +particularly given the long-lasting effects of language decisions. + +### Members + +* @JamesWTruher +* @rjmholt +* @daxian-dbw +* @BrucePay + +## Remoting + +The Remoting WG should focus on topics like the **PowerShell Remoting Protocol (PSRP)**, +the **protocols implemented under PSRP** (e.g. WinRM and SSH), +and **other protocols used for remoting** (e.g. "pure SSH" as opposed to SSH over PSRP). +Given the commonality of serialization boundaries, the Remoting WG should also focus on +**the PowerShell job system**. + +### Members + +* @anmenaga +* @jborean93 +* @PaulHigin +* @TravisEz13 + +## Cmdlets and Modules + +The Cmdlet WG should focus on core/inbox modules whose source code lives within the +`PowerShell/PowerShell` repository, +including the proposal of new cmdlets and parameters, improvements and bug fixes to existing +cmdlets/parameters, and breaking changes. + +However, some modules that ship as part of the PowerShell package are managed in other source repositories. +These modules are owned by the maintainers of those individual repositories. +These modules include: + +* [`Microsoft.PowerShell.Archive`](https://github.com/PowerShell/Microsoft.PowerShell.Archive) +* [`PackageManagement` (formerly `OneGet`)](https://github.com/OneGet/oneget) +* [`PowerShellGet`](https://github.com/PowerShell/PowerShellGet) +* [`PSDesiredStateConfiguration`](https://github.com/PowerShell/xPSDesiredStateConfiguration) + (Note: this community repository maintains a slightly different version of this module on the Gallery, + but should be used for future development of `PSDesiredStateConfiguration`.) +* [`PSReadLine`](https://github.com/PowerShell/PSReadLine) +* [`ThreadJob`](https://github.com/PowerShell/Modules/tree/master/Modules/Microsoft.PowerShell.ThreadJob) + +### Members + +* PowerShell Committee as interim members +* @jdhitsolutions +* @TobiasPSP + +## Security + +The Security WG should be brought into any issues or pull requests which may have security implications +in order to provide their expertise, concerns, and guidance. + +### Members + +* @TravisEz13 +* @PaulHigin + +## Explicitly not Working Groups + +Some areas of ownership in PowerShell specifically do not have Working Groups. +For the sake of completeness, these are listed below: + +### Build + +Build includes everything that is needed to build, compile, and package PowerShell. +This bucket is also not oriented a customer-facing deliverable and is already something handled by Maintainers, +so we don't need to address it as part of the WGs. + +* Build + * `build.psm1` + * `install-powershell.ps1` + * Build infrastructure and automation +* Packaging + * Scripts + * Infrastructure + +### Quality + +Similar to the topic of building PowerShell, quality +(including **test code**, **test infrastructure**, and **code coverage**) +should be managed by the PowerShell Maintainers. + +* Test code + * Pester unit tests + * xUnit unit tests +* Test infrastructure + * Nightlies + * CI +* Code coverage +* Pester diff --git a/docs/community/working-group.md b/docs/community/working-group.md new file mode 100644 index 00000000000..54bbcadf014 --- /dev/null +++ b/docs/community/working-group.md @@ -0,0 +1,190 @@ +# Working Groups + +Working Groups (WGs) are collections of contributors with knowledge of specific components or +technologies in the PowerShell domain. +They are responsible for issue triage/acceptance, code reviews, and providing their expertise to +others in issues, PRs, and RFC discussions. + +The list, description, and membership of the existing Working Groups is available +[here](working-group-definitions.md). + +## Terms + +* **Contributor** is used interchangeably within this doc as anyone participating in issues or + contributing code, RFCs, documentations, tests, bug reports, etc., + regardless of their status with the PowerShell project. +* **Repository Maintainers** are trusted stewards of the PowerShell repository responsible for + maintaining consistency and quality of PowerShell code. + One of their primary responsibilities is merging pull requests after all requirements have been fulfilled. + (Learn more about the Repository Maintainers [here](https://github.com/PowerShell/PowerShell/tree/master/docs/maintainers).) +* The **PowerShell Committee** is responsible for the design and governance of the PowerShell project, + primarily by voting to accept or reject review-for-comment (RFC) documents. + (Learn more about the PowerShell Committee [here](https://github.com/PowerShell/PowerShell/blob/master/docs/community/governance.md#powershell-committee).) +* A **Working Group** is a collection of people responsible for providing expertise on a specific + area of PowerShell in order to help establish consensus within the community and Committee. + The responsibilities of Working Groups are outlined below. + (Note: while some experts within Working Groups may have more specific expertise in a sub-topic + of the team, + the intent is that each team is holistically and collectively responsible for making decisions + within the larger topic space.) + +## Goals + +In designing the WG process, the Committee had a few goals: + +1. Increase the velocity of innovation without compromising the stability of PowerShell +1. Reduce the time spent by contributors on writing/reviewing PRs and RFCs that are not feasible +1. Increase the formal authority of subject matter experts (SMEs) inside and outside of Microsoft +1. Decrease the volume of required technical discussions held by the Committee + +## Process + +This process is represented within the [`process_diagram.vsdx` Visio diagram](process_diagram.vsdx): + +![process_diagram](process_diagram.svg) + +1. A contributor has an idea for PowerShell +1. The contributor files an issue informally describing the idea, + including some rationale as to why it should happen and a few use cases to show how it could work, + as well as to determine viability and value to the community. + This should include examples of expected input and output so that others understand how the feature would function in the real world. +1. The issue gets triaged into an [Area label](https://github.com/PowerShell/PowerShell/blob/master/docs/maintainers/issue-management.md#feature-areas) + by Maintainers. + This area label maps to one or more Working Groups. +1. If the Working Group determines that an idea can be prototyped or built outside of the PowerShell repo + (e.g. as a module), + contributors should start that idea outside of the PowerShell project. + Given that the issue is no longer directly relevant to the PowerShell project, it should be closed + (with a link to the new project, if available). + If the implementation turns out to be successful and particularly popular, + and a contributor believes that it would be overwhelmingly valuable to include in the primary PowerShell package, + they can restart the process in a new issue proposing that the functionality be + incorporated directly into the primary PowerShell package. +1. After the issue is filed, interested contributors should discuss the + feasibility and approach of the idea in the issue. + The Working Group that owns that Area is expected to contribute to this discussion. + Working groups may have their own criteria to consider in their areas. +1. After an appropriately exhaustive discussion/conversation + (i.e. the Working Group has determined that no new arguments are being made), + the Working Group makes a call on whether they believe the idea should continue through this process. + Note: this should be done via a best effort of consensus among the Working Group. + We don't currently have hard requirements for how this should be done, + but some ideas include: + + * a single member of the Working Group makes a proposal as a comment and other members should + "react" on GitHub with up/down thumbs + * Working Groups communicate privately through their own established channel to reach consensus + + It's worth noting that Working Group members who repeatedly speak on behalf of the Working Group without + consensus, they may be censured or removed from the team. + +### Working Groups reject the proposal + +If the Working Group says the idea should not pursued, the process stops. +Some reasons for rejection include (but are not limited to): + +* the idea can be implemented and validated for usefulness and popularity outside of the primary PowerShell repo/package +* the idea is difficult/impossible to implement +* the implementation would introduce undesirable (and possibly breaking) changes to PowerShell +* other reasons specific to individual Working Groups + +In the instance that the contributor feels they have compelling arguments showing that the +Working Group is incorrect in their rejection, +they can appeal to the PowerShell Committee by mentioning `@PowerShell/PowerShell-Committee`, +upon which a maintainer will add the `Review-Committee` label to the issue and reopen it. +Then, the PS Committee will discuss further with the Working Group and others to make a final call on +whether or not the issue should be pursued further. + +Be sure to enumerate your reasons for appeal, as unfounded appeals may be rejected for consideration +by the Committee until reasons are given. + +### Working groups believe the proposal has merit and/or potential + +If the idea passes the preliminary acceptance criteria for the Working Group, +the process proceeds on one of a few different paths: + +#### "RFC Not Required" + +In some cases, a proposed idea is determined by the Working Group to be small, uncontroversial, or simple, +such that an RFC is not required (to be determined by the Working Group). +In these circumstances, the Working Group should mark the issue as "RFC not required", +upon which it can move directly to the code PR phase to be reviewed by Working Groups and Maintainers. + +The Committee still holds the authority to require an RFC if they see an "RFC Not Required" issue +that they feel needs more exposition before merging. + +In cases of minor breaking changes, Maintainers or Working Groups can add the `Review - Committee` label to get +additional opinions from the Committee. + +#### RFC/Prototype Process + +If an idea has any significant design or ecosystem implications, +*cannot* be prototyped or built outside of the PowerShell repo, +and the community and Working Groups agree that the idea is worth pursuing, +a contributor (who may or may not be the original issue filer) must do two things: + +* Write an RFC as a [Draft PR](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) + into `PowerShell/PowerShell-RFC` +* Prototype the implementation as a [Draft PR](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) + into `PowerShell/PowerShell` + +In both cases, the intention is to provide Working Groups and other contributors who care about the +idea an opportunity to provide feedback on the design and implementation. + +Either of these two steps can be done first, but both are required in order to have code accepted +into the PowerShell repository, including experimental features. + +Note: When "Draft" is capitalized in this document, I'm referring to the +[Draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) +feature on GitHub. +We intend to use this feature liberally to mark the lifecycle of an idea through to implementation. + +#### RFCs + +The existing RFC process uses folders as a way to move an RFC through a multi-stage process +(Draft -> Experimental -> Accepted/Final). +However, it was difficult to reconcile this process with the benefits of PR reviews. + +With the introduction of Draft PRs on GitHub, we are reorienting the acceptance process around the PR itself. +Going forward, an RFC will have three stages: + +1. A Draft PR, denoting that the RFC is still in the review period, openly soliciting comments, + and that it may continue to be significantly iterated upon with revisions, edits, and responses to + community feedback or concerns. +1. After a minimum of two months of discussion, the RFC/PR author marks the PR as + [ready for review](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request), + upon which the RFC will enter the Committee's review queue to discuss the RFC contents and comments, + and make a decision on whether it is reasonable to pursue. + If after this review, the Committee determines that the intent of the RFC is not reasonable + (e.g. there may be irreconcilable issues with the design, + or the intent may not fit with the principles of PowerShell), + they will reject the PR and the process terminates. +1. In most cases, the Committee will choose to wait for the code PR to be merged as experimental, + and leverage user feedback or telemetry to determine if the RFC PR should be merged. +1. Finally, the Committee will choose to either merge or close the RFC PR, + marking the RFC as either accepted or rejected, respectively. + +#### Experiments + +Often times, implementing an idea can demonstrate opportunities or challenges that were not well +understood when the idea was formulated. +Similarly, a "simple" code change can have far reaching effects that are not well understood +until you're able to experiment with an idea within working code. + +To that end, it's required that *some* implementation exist before the Committee will consider an +RFC for acceptance. +That way, contributors can compile the PR branch to play with a working iteration of the idea +as a way to understand whether the feature is working as expected and valuable. + +In most cases, as long as an RFC has already been written and published as a draft, +Working Groups or the Committee will approve the feature for incorporation as an experimental feature, +so that it can be trialed with greater usage as part of a preview release. +In addition to increasing the scope of those who can provide real-world feedback on the feature, +this enables us to use telemetry to understand if users are turning off the feature in large numbers. + +Note: today, this will be done on a case-by-case basis, but over time, the Committee will establish +firmer guidelines around when PRs should be merged as experimental. + +Experiments should be complete to the extent that they serve as reasonable indicators of the user experience. +In the case that breaking changes are required of the feature, the break should be made in the prototype +so that users can experiment with whether or not the break has a significant negative effect. diff --git a/docs/dev-process/coding-guidelines.md b/docs/dev-process/coding-guidelines.md index 3472296251b..9bf46aee02d 100644 --- a/docs/dev-process/coding-guidelines.md +++ b/docs/dev-process/coding-guidelines.md @@ -86,9 +86,15 @@ We also run the [.NET code formatter tool](https://github.com/dotnet/codeformatt * Make sure the added/updated comments are meaningful, accurate and easy to understand. -* Public members must use [doc comments](https://docs.microsoft.com/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments). +### Documentation comments + +* Create documentation using [XML documentation comments](https://docs.microsoft.com/dotnet/csharp/codedoc) so that Visual Studio and other IDEs can use IntelliSense to show quick information about types or members. + +* Publicly visible types and their members must be documented. Internal and private members may use doc comments but it is not required. +* Documentation text should be written using complete sentences ending with full stops. + ## Performance Considerations PowerShell has a lot of performance sensitive code as well as a lot of inefficient code. @@ -111,9 +117,6 @@ Some general guidelines: * Avoid using string interpolations and overloads with implicit parameters such as `Culture` and `StringComparison`. Instead, use overloads with more explicit parameters such as `String.Format(IFormatProvider, String, Object[])` and `Equals(String, String, StringComparison)`. -* Avoid creating empty arrays. - Instead, reuse the static ones via `Utils.EmptyArray`. - * Avoid unnecessary memory allocation in a loop. Move the memory allocation outside the loop if possible. diff --git a/docs/host-powershell/sample/NuGet.config b/docs/host-powershell/sample/NuGet.config index 58f8d2c9b6d..b3ce3cb82a5 100644 --- a/docs/host-powershell/sample/NuGet.config +++ b/docs/host-powershell/sample/NuGet.config @@ -1,8 +1,10 @@ + - - + + + diff --git a/docs/learning-powershell/README.md b/docs/learning-powershell/README.md index 6ce2c8832ff..0dbbc5b8576 100644 --- a/docs/learning-powershell/README.md +++ b/docs/learning-powershell/README.md @@ -115,7 +115,7 @@ Note that all bash commands should continue working on PowerShell session. [powershell-intro]: https://www.pluralsight.com/courses/powershell-intro [lynda-training]: https://www.lynda.com/PowerShell-training-tutorials/5779-0.html [learn-win-powershell]: https://www.amazon.com/Learn-Windows-PowerShell-Month-Lunches/dp/1617294160 -[learn-powershell]: https://www.manning.com/books/learn-powershell-in-a-month-of-lunches-linux-and-macos-edition +[learn-powershell]: https://www.manning.com/books/learn-powershell-in-a-month-of-lunches [getstarted-with-powershell]: https://channel9.msdn.com/Series/GetStartedPowerShell3 [why-learn-powershell]: https://blogs.technet.microsoft.com/heyscriptingguy/2014/10/18/weekend-scripter-why-learn-powershell/ diff --git a/docs/learning-powershell/powershell-beginners-guide.md b/docs/learning-powershell/powershell-beginners-guide.md index ce49a4b9bfe..2017b191066 100644 --- a/docs/learning-powershell/powershell-beginners-guide.md +++ b/docs/learning-powershell/powershell-beginners-guide.md @@ -325,7 +325,7 @@ For more details, see [Create and Run PowerShell Script Guide][create-run-script [in-action]: https://www.amazon.com/Windows-PowerShell-Action-Bruce-Payette/dp/1633430294 [cookbook]: http://shop.oreilly.com/product/9780596801519.do [ebook-list]: https://martin77s.wordpress.com/2014/05/26/free-powershell-ebooks/ -[tutorial]: https://www.computerperformance.co.uk/powershell/index.htm +[tutorial]: https://www.computerperformance.co.uk/powershell/index-13/ [to-learn]:https://blogs.technet.microsoft.com/heyscriptingguy/2015/01/04/weekend-scripter-the-best-ways-to-learn-powershell/ [ps-module]:https://docs.microsoft.com/powershell/scripting/developer/module/understanding-a-windows-powershell-module [create-ps-module]:https://www.business.com/articles/powershell-modules/ diff --git a/docs/maintainers/README.md b/docs/maintainers/README.md index 2cafeb94888..0c28e2cc9de 100644 --- a/docs/maintainers/README.md +++ b/docs/maintainers/README.md @@ -3,7 +3,7 @@ Repository Maintainers are trusted stewards of the PowerShell repository responsible for maintaining consistency and quality of PowerShell code. One of their primary responsibilities is merging pull requests after all requirements have been fulfilled. -They have [write access](https://help.github.com/articles/repository-permission-levels-for-an-organization/) to the PowerShell repositories which gives them the power to: +They have [write access](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/repository-permission-levels-for-an-organization) to the PowerShell repositories which gives them the power to: 1. `git push` to the official PowerShell repository 1. Merge [pull requests](https://www.thinkful.com/learn/github-pull-request-tutorial/) diff --git a/docs/maintainers/issue-management.md b/docs/maintainers/issue-management.md index 4021d44c82a..0cc8eb00e37 100644 --- a/docs/maintainers/issue-management.md +++ b/docs/maintainers/issue-management.md @@ -7,6 +7,8 @@ first follow the [vulnerability issue reporting policy](../../.github/SECURITY.m ## Long-living issue labels +Issue labels for PowerShell/PowerShell can be found [here](https://github.com/powershell/powershell/labels). + ### Issue and PR Labels Issues are opened for many different reasons. @@ -37,32 +39,35 @@ When an issue is resolved, the following labels are used to describe the resolut ### Feature areas -These labels describe what feature area of PowerShell that an issue affects: +These labels describe what feature area of PowerShell that an issue affects. +Those labels denoted by `WG-*` are owned by a Working Group (WG) defined +[here](../community/working-group-definitions.md): -* `Area-Build`: build issues +* `Area-Maintainers-Build`: build issues * `Area-Cmdlets-Core`: cmdlets in the Microsoft.PowerShell.Core module * `Area-Cmdlets-Utility`: cmdlets in the Microsoft.PowerShell.Utility module * `Area-Cmdlets-Management`: cmdlets in the Microsoft.PowerShell.Management module -* `Area-Console`: the console experience -* `Area-Debugging`: debugging PowerShell script -* `Area-Demo`: a demo or sample * `Area-Documentation`: PowerShell *repo* documentation issues, general PowerShell doc issues go [here](https://github.com/PowerShell/PowerShell-Docs/issues) * `Area-DSC`: DSC related issues -* `Area-Engine`: core PowerShell engine, interpreter, runtime -* `Area-HelpSystem`: anything related to the help infrastructure and formatting of help -* `Area-Intellisense`: tab completion -* `Area-Language`: parser, language semantics -* `Area-OMI`: OMI -* `Area-PackageManagement`: PackageManagement related issues -* `Area-Performance`: a performance issue -* `Area-Portability`: anything affecting script portability * `Area-PowerShellGet`: PowerShellGet related issues -* `Area-Providers`: PowerShell providers such as FileSystem, Certificates, Registry, etc... -* `Area-PSReadline`: PSReadline related issues -* `Area-Remoting`: PSRP issues with any transport layer -* `Area-Security`: security related areas such as [JEA](https://github.com/powershell/JEA) * `Area-SideBySide`: side by side support -* `Area-Test`: issues in a test or in test infrastructure +* `WG-DevEx-Portability`: anything related to authoring cross-platform or cross-architecture + modules, cmdlets, and scripts +* `WG-DevEx-SDK`: anything related to hosting PowerShell as a runtime, PowerShell's APIs, + PowerShell Standard, or the development of modules and cmdlets +* `WG-Engine`: core PowerShell engine, interpreter, and runtime +* `WG-Engine-Performance`: core PowerShell engine, interpreter, and runtime performance +* `WG-Engine-Providers`: built-in PowerShell providers such as FileSystem, Certificates, + Registry, etc. (or anything returned by `Get-PSProvider`) +* `WG-Interactive-Console`: the console experience +* `WG-Interactive-Debugging`: debugging PowerShell script +* `WG-Interactive-HelpSystem`: anything related to the help infrastructure and formatting of help +* `WG-Interactive-IntelliSense`: tab completion +* `WG-Interactive-PSReadline`: PSReadline related issues +* `WG-Language`: parser, language semantics +* `WG-Quality-Test`: issues in a test or in test infrastructure +* `WG-Remoting`: PSRP issues with any transport layer +* `WG-Security`: security related areas such as [JEA](https://github.com/powershell/JEA) ### Operating Systems diff --git a/docs/testing-guidelines/testing-guidelines.md b/docs/testing-guidelines/testing-guidelines.md index ce987beb6d0..e00c8352ee7 100755 --- a/docs/testing-guidelines/testing-guidelines.md +++ b/docs/testing-guidelines/testing-guidelines.md @@ -88,7 +88,7 @@ When you would want to do this: ### xUnit -For those tests which are not easily run via Pester, we have decided to use [xUnit](https://xunit.github.io/) as the test framework. +For those tests which are not easily run via Pester, we have decided to use [xUnit](https://xunit.net/) as the test framework. Currently, we have a minuscule number of tests which are run by using xUnit. ## Running tests outside of CI diff --git a/global.json b/global.json index 1780ad8789f..047020849f2 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "5.0.100-rc.1.20452.10" + "version": "6.0.100" } } diff --git a/nuget.config b/nuget.config index cbb2494cecf..cf9fec6fb1e 100644 --- a/nuget.config +++ b/nuget.config @@ -2,10 +2,13 @@ - + - - - + + + + + + diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs index afadd0a3fe4..49f39c8c019 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Globalization; using System.Management.Automation; using System.Threading; @@ -27,9 +26,9 @@ internal abstract class CimAsyncOperation : IDisposable #region Constructor /// - /// The constructor. + /// Initializes a new instance of the class. /// - public CimAsyncOperation() + protected CimAsyncOperation() { this.moreActionEvent = new ManualResetEventSlim(false); this.actionQueue = new ConcurrentQueue(); @@ -238,7 +237,7 @@ protected bool IsActive() /// protected CimSessionProxy CreateCimSessionProxy(CimSessionProxy originalProxy) { - CimSessionProxy proxy = new CimSessionProxy(originalProxy); + CimSessionProxy proxy = new(originalProxy); this.SubscribeEventAndAddProxytoCache(proxy); return proxy; } @@ -260,7 +259,7 @@ protected CimSessionProxy CreateCimSessionProxy(CimSessionProxy originalProxy, b /// protected CimSessionProxy CreateCimSessionProxy(CimSession session) { - CimSessionProxy proxy = new CimSessionProxy(session); + CimSessionProxy proxy = new(session); this.SubscribeEventAndAddProxytoCache(proxy); return proxy; } @@ -283,7 +282,7 @@ protected CimSessionProxy CreateCimSessionProxy(CimSession session, bool passThr /// protected CimSessionProxy CreateCimSessionProxy(string computerName) { - CimSessionProxy proxy = new CimSessionProxy(computerName); + CimSessionProxy proxy = new(computerName); this.SubscribeEventAndAddProxytoCache(proxy); return proxy; } @@ -297,7 +296,7 @@ protected CimSessionProxy CreateCimSessionProxy(string computerName) /// protected CimSessionProxy CreateCimSessionProxy(string computerName, CimInstance cimInstance) { - CimSessionProxy proxy = new CimSessionProxy(computerName, cimInstance); + CimSessionProxy proxy = new(computerName, cimInstance); this.SubscribeEventAndAddProxytoCache(proxy); return proxy; } @@ -388,8 +387,7 @@ protected object GetReferenceOrReferenceArrayObject(object value, ref CimType re if (cimReference != null) { object baseObject = GetBaseObject(cimReference.Value); - CimInstance cimInstance = baseObject as CimInstance; - if (cimInstance == null) + if (!(baseObject is CimInstance cimInstance)) { return null; } @@ -412,8 +410,7 @@ protected object GetReferenceOrReferenceArrayObject(object value, ref CimType re CimInstance[] cimInstanceArray = new CimInstance[cimReferenceArray.Length]; for (int i = 0; i < cimReferenceArray.Length; i++) { - PSReference tempCimReference = cimReferenceArray[i] as PSReference; - if (tempCimReference == null) + if (!(cimReferenceArray[i] is PSReference tempCimReference)) { return null; } @@ -549,7 +546,7 @@ private void Cleanup() /// /// Lock object. /// - private readonly object a_lock = new object(); + private readonly object a_lock = new(); /// /// Number of active operations. @@ -559,19 +556,19 @@ private void Cleanup() /// /// Event to notify ps thread that more action is available. /// - private ManualResetEventSlim moreActionEvent; + private readonly ManualResetEventSlim moreActionEvent; /// /// The following is the definition of action queue. /// The queue holding all actions to be executed in the context of either /// ProcessRecord or EndProcessing. /// - private ConcurrentQueue actionQueue; + private readonly ConcurrentQueue actionQueue; /// /// Lock object. /// - private readonly object cimSessionProxyCacheLock = new object(); + private readonly object cimSessionProxyCacheLock = new(); /// /// Cache all objects related to diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs index 345b27bb48b..e3e487a9533 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs @@ -3,9 +3,9 @@ #region Using directives +using System; using System.Threading; using Microsoft.Management.Infrastructure.Options; -using System; #endregion @@ -17,9 +17,9 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal abstract class CimBaseAction { /// - /// Constructor method. + /// Initializes a new instance of the class. /// - public CimBaseAction() + protected CimBaseAction() { } @@ -44,20 +44,7 @@ public virtual void Execute(CmdletOperationBase cmdlet) /// , object. /// /// - protected XOperationContextBase Context - { - get - { - return this.context; - } - - set - { - this.context = value; - } - } - - private XOperationContextBase context; + protected XOperationContextBase Context { get; set; } } /// @@ -69,7 +56,7 @@ protected XOperationContextBase Context internal class CimSyncAction : CimBaseAction, IDisposable { /// - /// The constructor. + /// Initializes a new instance of the class. /// public CimSyncAction() { @@ -126,7 +113,7 @@ protected virtual void Block() /// /// Action completed event. /// - private ManualResetEventSlim completeEvent; + private readonly ManualResetEventSlim completeEvent; /// /// Response result. diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs index 2488490c514..4e9bf4f296e 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs @@ -25,41 +25,25 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal class ParameterDefinitionEntry { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// internal ParameterDefinitionEntry(string parameterSetName, bool mandatory) { - this.mandatory = mandatory; - this.parameterSetName = parameterSetName; + this.IsMandatory = mandatory; + this.ParameterSetName = parameterSetName; } /// /// Property ParameterSetName. /// - internal string ParameterSetName - { - get - { - return this.parameterSetName; - } - } - - private readonly string parameterSetName = null; + internal string ParameterSetName { get; } /// /// Whether the parameter is mandatory to the set. /// - internal bool IsMandatory - { - get - { - return this.mandatory; - } - } - - private readonly bool mandatory = false; + internal bool IsMandatory { get; } } /// @@ -70,36 +54,36 @@ internal bool IsMandatory internal class ParameterSetEntry { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// - internal ParameterSetEntry(UInt32 mandatoryParameterCount) + internal ParameterSetEntry(uint mandatoryParameterCount) { - this.mandatoryParameterCount = mandatoryParameterCount; - this.isDefaultParameterSet = false; + this.MandatoryParameterCount = mandatoryParameterCount; + this.IsDefaultParameterSet = false; reset(); } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// internal ParameterSetEntry(ParameterSetEntry toClone) { - this.mandatoryParameterCount = toClone.MandatoryParameterCount; - this.isDefaultParameterSet = toClone.IsDefaultParameterSet; + this.MandatoryParameterCount = toClone.MandatoryParameterCount; + this.IsDefaultParameterSet = toClone.IsDefaultParameterSet; reset(); } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// - internal ParameterSetEntry(UInt32 mandatoryParameterCount, bool isDefault) + internal ParameterSetEntry(uint mandatoryParameterCount, bool isDefault) { - this.mandatoryParameterCount = mandatoryParameterCount; - this.isDefaultParameterSet = isDefault; + this.MandatoryParameterCount = mandatoryParameterCount; + this.IsDefaultParameterSet = isDefault; reset(); } @@ -108,107 +92,39 @@ internal ParameterSetEntry(UInt32 mandatoryParameterCount, bool isDefault) /// internal void reset() { - this.setMandatoryParameterCount = this.setMandatoryParameterCountAtBeginProcess; - this.isValueSet = this.isValueSetAtBeginProcess; + this.SetMandatoryParameterCount = this.SetMandatoryParameterCountAtBeginProcess; + this.IsValueSet = this.IsValueSetAtBeginProcess; } /// /// Property DefaultParameterSet /// - internal bool IsDefaultParameterSet - { - get - { - return this.isDefaultParameterSet; - } - } - - private readonly bool isDefaultParameterSet = false; + internal bool IsDefaultParameterSet { get; } /// /// Property MandatoryParameterCount /// - internal UInt32 MandatoryParameterCount - { - get - { - return this.mandatoryParameterCount; - } - } - - private readonly UInt32 mandatoryParameterCount = 0; + internal uint MandatoryParameterCount { get; } = 0; /// /// Property IsValueSet /// - internal bool IsValueSet - { - get - { - return this.isValueSet; - } - - set - { - this.isValueSet = value; - } - } - - private bool isValueSet = false; + internal bool IsValueSet { get; set; } /// /// Property IsValueSetAtBeginProcess /// - internal bool IsValueSetAtBeginProcess - { - get - { - return this.isValueSetAtBeginProcess; - } - - set - { - this.isValueSetAtBeginProcess = value; - } - } - - private bool isValueSetAtBeginProcess = false; + internal bool IsValueSetAtBeginProcess { get; set; } /// /// Property SetMandatoryParameterCount /// - internal UInt32 SetMandatoryParameterCount - { - get - { - return this.setMandatoryParameterCount; - } - - set - { - this.setMandatoryParameterCount = value; - } - } - - private UInt32 setMandatoryParameterCount = 0; + internal uint SetMandatoryParameterCount { get; set; } = 0; /// /// Property SetMandatoryParameterCountAtBeginProcess /// - internal UInt32 SetMandatoryParameterCountAtBeginProcess - { - get - { - return this.setMandatoryParameterCountAtBeginProcess; - } - - set - { - this.setMandatoryParameterCountAtBeginProcess = value; - } - } - - private UInt32 setMandatoryParameterCountAtBeginProcess = 0; + internal uint SetMandatoryParameterCountAtBeginProcess { get; set; } = 0; } /// @@ -217,7 +133,7 @@ internal UInt32 SetMandatoryParameterCountAtBeginProcess internal class ParameterBinder { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -256,12 +172,12 @@ internal ParameterBinder( /// throw exception /// /// - private List parametersetNamesList = new List(); + private List parametersetNamesList = new(); /// /// Parameter names list. /// - private List parameterNamesList = new List(); + private readonly List parameterNamesList = new(); /// /// @@ -270,12 +186,12 @@ internal ParameterBinder( /// throw exception /// /// - private List parametersetNamesListAtBeginProcess = new List(); + private List parametersetNamesListAtBeginProcess = new(); /// /// Parameter names list before begin process. /// - private List parameterNamesListAtBeginProcess = new List(); + private readonly List parameterNamesListAtBeginProcess = new(); /// /// @@ -331,7 +247,7 @@ internal void SetParameter(string parameterName, bool isBeginProcess) if (this.parametersetNamesList.Count == 0) { - List nameset = new List(); + List nameset = new(); foreach (ParameterDefinitionEntry parameterDefinitionEntry in this.parameterDefinitionEntries[parameterName]) { DebugHelper.WriteLogEx("parameterset name = '{0}'; mandatory = '{1}'", 1, parameterDefinitionEntry.ParameterSetName, parameterDefinitionEntry.IsMandatory); @@ -370,7 +286,7 @@ internal void SetParameter(string parameterName, bool isBeginProcess) } else { - List nameset = new List(); + List nameset = new(); foreach (ParameterDefinitionEntry entry in this.parameterDefinitionEntries[parameterName]) { if (this.parametersetNamesList.Contains(entry.ParameterSetName)) @@ -418,7 +334,7 @@ internal string GetParameterSet() string boundParameterSetName = null; string defaultParameterSetName = null; - List noMandatoryParameterSet = new List(); + List noMandatoryParameterSet = new(); // Looking for parameter set which have mandatory parameters foreach (string parameterSetName in this.parameterSetEntries.Keys) @@ -531,7 +447,7 @@ internal void CheckParameterSet() { try { - this.parameterSetName = this.parameterBinder.GetParameterSet(); + this.ParameterSetName = this.parameterBinder.GetParameterSet(); } finally { @@ -539,7 +455,7 @@ internal void CheckParameterSet() } } - DebugHelper.WriteLog("current parameterset is: " + this.parameterSetName, 4); + DebugHelper.WriteLog("current parameterset is: " + this.ParameterSetName, 4); } /// @@ -567,7 +483,7 @@ internal void SetParameter(object value, string parameterName) #region constructors /// - /// Constructor. + /// Initializes a new instance of the class. /// internal CimBaseCommand() { @@ -576,7 +492,7 @@ internal CimBaseCommand() } /// - /// Constructor. + /// Initializes a new instance of the class. /// internal CimBaseCommand(Dictionary> parameters, Dictionary sets) @@ -675,7 +591,7 @@ protected virtual void DisposeInternal() /// /// Parameter binder used to resolve parameter set name. /// - private ParameterBinder parameterBinder; + private readonly ParameterBinder parameterBinder; /// /// @@ -687,14 +603,7 @@ protected virtual void DisposeInternal() /// /// Lock object. /// - private readonly object myLock = new object(); - - /// - /// - /// parameter set name - /// - /// - private string parameterSetName; + private readonly object myLock = new(); /// /// This flag is introduced to resolve the parameter set name @@ -727,6 +636,11 @@ internal bool AtBeginProcess /// internal CimAsyncOperation AsyncOperation { + get + { + return this.operation; + } + set { lock (this.myLock) @@ -735,11 +649,6 @@ internal CimAsyncOperation AsyncOperation this.operation = value; } } - - get - { - return this.operation; - } } /// @@ -747,13 +656,7 @@ internal CimAsyncOperation AsyncOperation /// Get current ParameterSetName of the cmdlet /// /// - internal string ParameterSetName - { - get - { - return this.parameterSetName; - } - } + internal string ParameterSetName { get; private set; } /// /// Gets/Sets cmdlet operation wrapper object. @@ -769,9 +672,10 @@ internal virtual CmdletOperationBase CmdletOperation /// Throw terminating error /// /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] internal void ThrowTerminatingError(Exception exception, string operation) { - ErrorRecord errorRecord = new ErrorRecord(exception, operation, ErrorCategory.InvalidOperation, this); + ErrorRecord errorRecord = new(exception, operation, ErrorCategory.InvalidOperation, this); this.CmdletOperation.ThrowTerminatingError(errorRecord); } @@ -909,7 +813,7 @@ internal void ThrowInvalidAuthenticationTypeError( ImpersonatedAuthenticationMechanism.Negotiate, ImpersonatedAuthenticationMechanism.Kerberos, ImpersonatedAuthenticationMechanism.NtlmDomain); - PSArgumentOutOfRangeException exception = new PSArgumentOutOfRangeException( + PSArgumentOutOfRangeException exception = new( parameterName, authentication, message); ThrowTerminatingError(exception, operationName); } @@ -928,7 +832,7 @@ internal void ThrowConflictParameterWasSet( string message = string.Format(CultureInfo.CurrentUICulture, CimCmdletStrings.ConflictParameterWasSet, parameterName, conflictParameterName); - PSArgumentException exception = new PSArgumentException(message, parameterName); + PSArgumentException exception = new(message, parameterName); ThrowTerminatingError(exception, operationName); } @@ -944,12 +848,12 @@ internal void ThrowInvalidProperty( string operationName, IDictionary actualValue) { - StringBuilder propList = new StringBuilder(); + StringBuilder propList = new(); foreach (string property in propertiesList) { if (propList.Length > 0) { - propList.Append(","); + propList.Append(','); } propList.Append(property); @@ -957,7 +861,7 @@ internal void ThrowInvalidProperty( string message = string.Format(CultureInfo.CurrentUICulture, CimCmdletStrings.CouldNotFindPropertyFromGivenClass, className, propList); - PSArgumentOutOfRangeException exception = new PSArgumentOutOfRangeException( + PSArgumentOutOfRangeException exception = new( parameterName, actualValue, message); ThrowTerminatingError(exception, operationName); } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs index b0b95d14c50..0ab4988c57d 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs @@ -3,8 +3,6 @@ #region Using directives -using System.Collections; -using System; using System.Collections.Generic; #endregion @@ -19,9 +17,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal sealed class CimGetAssociatedInstance : CimAsyncOperation { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimGetAssociatedInstance() : base() @@ -45,7 +41,7 @@ public void GetCimAssociatedInstance(GetCimAssociatedInstanceCommand cmdlet) nameSpace = ConstValue.GetNamespace(cmdlet.CimInstance.CimSystemProperties.Namespace); } - List proxys = new List(); + List proxys = new(); switch (cmdlet.ParameterSetName) { case CimBaseCommand.ComputerSetName: @@ -89,7 +85,7 @@ public void GetCimAssociatedInstance(GetCimAssociatedInstanceCommand cmdlet) /// /// /// - private void SetSessionProxyProperties( + private static void SetSessionProxyProperties( ref CimSessionProxy proxy, GetCimAssociatedInstanceCommand cmdlet) { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs index a3826487e24..728ce6b8c8e 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs @@ -3,11 +3,8 @@ #region Using directives -using System.Collections; -using System; using System.Collections.Generic; using System.Management.Automation; -using System.Globalization; #endregion @@ -20,9 +17,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal class CimGetCimClassContext : XOperationContextBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// /// @@ -33,10 +28,10 @@ internal CimGetCimClassContext( string thePropertyName, string theQualifierName) { - this.className = theClassName; - this.methodName = theMethodName; - this.propertyName = thePropertyName; - this.qualifierName = theQualifierName; + this.ClassName = theClassName; + this.MethodName = theMethodName; + this.PropertyName = thePropertyName; + this.QualifierName = theQualifierName; } /// @@ -47,14 +42,7 @@ internal CimGetCimClassContext( /// Wildcard expansion should be allowed. /// /// - public string ClassName - { - get { return className; } - - set { className = value; } - } - - private string className; + public string ClassName { get; set; } /// /// @@ -63,12 +51,7 @@ public string ClassName /// Then Filter the by given methodname /// /// - internal string MethodName - { - get { return methodName; } - } - - private string methodName; + internal string MethodName { get; } /// /// @@ -77,12 +60,7 @@ internal string MethodName /// Filter the by given property name. /// /// - internal string PropertyName - { - get { return propertyName; } - } - - private string propertyName; + internal string PropertyName { get; } /// /// @@ -91,12 +69,7 @@ internal string PropertyName /// Filter the by given methodname /// /// - internal string QualifierName - { - get { return qualifierName; } - } - - private string qualifierName; + internal string QualifierName { get; } } /// @@ -107,9 +80,7 @@ internal string QualifierName internal sealed class CimGetCimClass : CimAsyncOperation { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimGetCimClass() : base() @@ -124,10 +95,10 @@ public CimGetCimClass() /// object. public void GetCimClass(GetCimClassCommand cmdlet) { - List proxys = new List(); + List proxys = new(); string nameSpace = ConstValue.GetNamespace(cmdlet.Namespace); - string className = (cmdlet.ClassName == null) ? @"*" : cmdlet.ClassName; - CimGetCimClassContext context = new CimGetCimClassContext( + string className = cmdlet.ClassName ?? @"*"; + CimGetCimClassContext context = new( cmdlet.ClassName, cmdlet.MethodName, cmdlet.PropertyName, @@ -189,7 +160,7 @@ public void GetCimClass(GetCimClassCommand cmdlet) /// /// /// - private void SetSessionProxyProperties( + private static void SetSessionProxyProperties( ref CimSessionProxy proxy, GetCimClassCommand cmdlet) { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs index c462d5b9918..25400514401 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs @@ -3,8 +3,6 @@ #region Using directives -using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Management.Automation; @@ -53,6 +51,7 @@ public object Process(object resultObject) internal class CimGetInstance : CimAsyncOperation { /// + /// Initializes a new instance of the class. /// /// Constructor /// @@ -83,8 +82,8 @@ protected void GetCimInstanceInternal(CimBaseCommand cmdlet) IEnumerable computerNames = ConstValue.GetComputerNames( GetComputerName(cmdlet)); string nameSpace; - List proxys = new List(); - bool isGetCimInstanceCommand = (cmdlet is GetCimInstanceCommand); + List proxys = new(); + bool isGetCimInstanceCommand = cmdlet is GetCimInstanceCommand; CimInstance targetCimInstance = null; switch (cmdlet.ParameterSetName) { @@ -95,7 +94,7 @@ protected void GetCimInstanceInternal(CimBaseCommand cmdlet) CimSessionProxy proxy = CreateSessionProxy(computerName, targetCimInstance, cmdlet); if (isGetCimInstanceCommand) { - this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); } proxys.Add(proxy); @@ -110,7 +109,7 @@ protected void GetCimInstanceInternal(CimBaseCommand cmdlet) CimSessionProxy proxy = CreateSessionProxy(computerName, cmdlet); if (isGetCimInstanceCommand) { - this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); } proxys.Add(proxy); @@ -126,7 +125,7 @@ protected void GetCimInstanceInternal(CimBaseCommand cmdlet) CimSessionProxy proxy = CreateSessionProxy(session, cmdlet); if (isGetCimInstanceCommand) { - this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); } proxys.Add(proxy); @@ -303,10 +302,10 @@ protected static string CreateQuery(CimBaseCommand cmdlet) GetCimInstanceCommand cmd = cmdlet as GetCimInstanceCommand; if (cmd != null) { - StringBuilder propertyList = new StringBuilder(); + StringBuilder propertyList = new(); if (cmd.SelectProperties == null) { - propertyList.Append("*"); + propertyList.Append('*'); } else { @@ -314,7 +313,7 @@ protected static string CreateQuery(CimBaseCommand cmdlet) { if (propertyList.Length > 0) { - propertyList.Append(","); + propertyList.Append(','); } propertyList.Append(property); @@ -375,7 +374,7 @@ protected static CimInstance GetCimInstanceParameter(CimBaseCommand cmdlet) /// /// /// - private void SetSessionProxyProperties( + private static void SetSessionProxyProperties( ref CimSessionProxy proxy, CimBaseCommand cmdlet) { @@ -399,7 +398,7 @@ private void SetSessionProxyProperties( proxy.ResourceUri = removeCimInstance.ResourceUri; } - CimRemoveCimInstanceContext context = new CimRemoveCimInstanceContext( + CimRemoveCimInstanceContext context = new( ConstValue.GetNamespace(removeCimInstance.Namespace), proxy); proxy.ContextObject = context; @@ -413,7 +412,7 @@ private void SetSessionProxyProperties( proxy.ResourceUri = setCimInstance.ResourceUri; } - CimSetCimInstanceContext context = new CimSetCimInstanceContext( + CimSetCimInstanceContext context = new( ConstValue.GetNamespace(setCimInstance.Namespace), setCimInstance.Property, proxy, @@ -516,7 +515,7 @@ protected CimSessionProxy CreateSessionProxy( /// /// /// - private void SetPreProcess(CimSessionProxy proxy, GetCimInstanceCommand cmdlet) + private static void SetPreProcess(CimSessionProxy proxy, GetCimInstanceCommand cmdlet) { if (cmdlet.KeyOnly || (cmdlet.SelectProperties != null)) { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs index fd44d922009..cb5cfc27056 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs @@ -45,26 +45,16 @@ public class CimIndicationEventExceptionEventArgs : CimIndicationEventArgs /// Returns an exception /// /// - public Exception Exception - { - get - { - return exception; - } - } - - private Exception exception; + public Exception Exception { get; } /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// public CimIndicationEventExceptionEventArgs(Exception theException) { context = null; - this.exception = theException; + this.Exception = theException; } } @@ -81,7 +71,7 @@ public CimInstance NewEvent { get { - return (result == null) ? null : result.Instance; + return result?.Instance; } } @@ -92,7 +82,7 @@ public string MachineId { get { - return (result == null) ? null : result.MachineId; + return result?.MachineId; } } @@ -103,14 +93,12 @@ public string Bookmark { get { - return (result == null) ? null : result.Bookmark; + return result?.Bookmark; } } /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// public CimIndicationEventInstanceEventArgs(CimSubscriptionResult result) @@ -124,7 +112,7 @@ public CimIndicationEventInstanceEventArgs(CimSubscriptionResult result) /// subscription result /// /// - private CimSubscriptionResult result; + private readonly CimSubscriptionResult result; } /// @@ -154,9 +142,7 @@ internal enum Status public event EventHandler CimIndicationArrived; /// - /// - /// Constructor with given computerName, namespace, queryExpression and timeout - /// + /// Initializes a new instance of the class. /// /// /// @@ -167,7 +153,7 @@ public CimIndicationWatcher( string theNamespace, string queryDialect, string queryExpression, - UInt32 operationTimeout) + uint operationTimeout) { ValidationHelper.ValidateNoNullorWhiteSpaceArgument(queryExpression, queryExpressionParameterName); computerName = ConstValue.GetComputerName(computerName); @@ -176,9 +162,7 @@ public CimIndicationWatcher( } /// - /// - /// Constructor with given cimsession, namespace, queryExpression and timeout - /// + /// Initializes a new instance of the class. /// /// /// @@ -189,7 +173,7 @@ public CimIndicationWatcher( string theNamespace, string queryDialect, string queryExpression, - UInt32 operationTimeout) + uint operationTimeout) { ValidationHelper.ValidateNoNullorWhiteSpaceArgument(queryExpression, queryExpressionParameterName); ValidationHelper.ValidateNoNullArgument(cimSession, cimSessionParameterName); @@ -208,7 +192,7 @@ private void Initialize( string theNameSpace, string theQueryDialect, string theQueryExpression, - UInt32 theOperationTimeout) + uint theOperationTimeout) { enableRaisingEvents = false; status = Status.Default; @@ -394,7 +378,7 @@ internal void SetCmdlet(Cmdlet cmdlet) private string nameSpace; private string queryDialect; private string queryExpression; - private UInt32 operationTimeout; + private uint operationTimeout; #endregion #endregion } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs index ba82ff9e432..50f4d12dd74 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.Management.Automation; #endregion @@ -28,9 +27,7 @@ internal sealed class CimInvokeCimMethod : CimAsyncOperation internal class CimInvokeCimMethodContext : XOperationContextBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// /// @@ -41,42 +38,24 @@ internal CimInvokeCimMethodContext(string theNamespace, CimSessionProxy theProxy) { this.proxy = theProxy; - this.methodName = theMethodName; - this.collection = theCollection; + this.MethodName = theMethodName; + this.ParametersCollection = theCollection; this.nameSpace = theNamespace; } /// /// namespace /// - internal string MethodName - { - get - { - return this.methodName; - } - } - - private string methodName; + internal string MethodName { get; } /// /// parameters collection /// - internal CimMethodParametersCollection ParametersCollection - { - get - { - return this.collection; - } - } - - private CimMethodParametersCollection collection; + internal CimMethodParametersCollection ParametersCollection { get; } } /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimInvokeCimMethod() : base() @@ -93,7 +72,7 @@ public void InvokeCimMethod(InvokeCimMethodCommand cmdlet) { IEnumerable computerNames = ConstValue.GetComputerNames(cmdlet.ComputerName); string nameSpace; - List proxys = new List(); + List proxys = new(); string action = string.Format(CultureInfo.CurrentUICulture, actionTemplate, cmdlet.MethodName); switch (cmdlet.ParameterSetName) @@ -195,7 +174,7 @@ public void InvokeCimMethod(InvokeCimMethodCommand cmdlet) foreach (CimSessionProxy proxy in proxys) { // create context object - CimInvokeCimMethodContext context = new CimInvokeCimMethodContext( + CimInvokeCimMethodContext context = new( nameSpace, cmdlet.MethodName, paramsCollection, @@ -275,7 +254,7 @@ public void InvokeCimMethodOnCimInstance(CimInstance cimInstance, XOperationCont /// /// /// - private void SetSessionProxyProperties( + private static void SetSessionProxyProperties( ref CimSessionProxy proxy, InvokeCimMethodCommand cmdlet) { @@ -374,7 +353,7 @@ private CimMethodParametersCollection CreateParametersCollection( { string parameterName = enumerator.Key.ToString(); - CimFlags parameterFlags = CimFlags.In; + const CimFlags parameterFlags = CimFlags.In; object parameterValue = GetBaseObject(enumerator.Value); DebugHelper.WriteLog(@"Create parameter name= {0}, value= {1}, flags= {2}.", 4, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs index 14c57c87888..176cb1828e2 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs @@ -20,9 +20,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal class CimNewCimInstanceContext : XOperationContextBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// /// @@ -44,6 +42,7 @@ internal CimNewCimInstanceContext( internal sealed class CimNewCimInstance : CimAsyncOperation { /// + /// Initializes a new instance of the class. /// /// Constructor /// @@ -133,7 +132,7 @@ public void NewCimInstance(NewCimInstanceCommand cmdlet) } // create ciminstance on server - List proxys = new List(); + List proxys = new(); switch (cmdlet.ParameterSetName) { @@ -188,7 +187,7 @@ internal void GetCimInstance(CimInstance cimInstance, XOperationContextBase cont } CimSessionProxy proxy = CreateCimSessionProxy(newCimInstanceContext.Proxy); - string nameSpace = (cimInstance.CimSystemProperties.Namespace == null) ? newCimInstanceContext.Namespace : cimInstance.CimSystemProperties.Namespace; + string nameSpace = cimInstance.CimSystemProperties.Namespace ?? newCimInstanceContext.Namespace; proxy.GetInstanceAsync(nameSpace, cimInstance); } @@ -203,7 +202,7 @@ internal void GetCimInstance(CimInstance cimInstance, XOperationContextBase cont /// /// /// - private void SetSessionProxyProperties( + private static void SetSessionProxyProperties( ref CimSessionProxy proxy, NewCimInstanceCommand cmdlet) { @@ -267,13 +266,13 @@ private CimInstance CreateCimInstance( IDictionary properties, NewCimInstanceCommand cmdlet) { - CimInstance cimInstance = new CimInstance(className, cimNamespace); + CimInstance cimInstance = new(className, cimNamespace); if (properties == null) { return cimInstance; } - List keys = new List(); + List keys = new(); if (key != null) { foreach (string keyName in key) @@ -331,13 +330,13 @@ private CimInstance CreateCimInstance( IDictionary properties, NewCimInstanceCommand cmdlet) { - CimInstance cimInstance = new CimInstance(cimClass); + CimInstance cimInstance = new(cimClass); if (properties == null) { return cimInstance; } - List notfoundProperties = new List(); + List notfoundProperties = new(); foreach (string property in properties.Keys) { if (cimInstance.CimInstanceProperties[property] == null) diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs index 4d4ff5d6ec5..48b887f00b4 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs @@ -22,12 +22,12 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal sealed class CimPromptUser : CimSyncAction { /// - /// Constructor. + /// Initializes a new instance of the class. /// public CimPromptUser(string message, CimPromptType prompt) { - this.message = message; + this.Message = message; this.prompt = prompt; } @@ -54,7 +54,7 @@ public override void Execute(CmdletOperationBase cmdlet) // NOTES: prepare the whatif message and caption try { - result = cmdlet.ShouldContinue(message, "caption", ref yestoall, ref notoall); + result = cmdlet.ShouldContinue(Message, "caption", ref yestoall, ref notoall); if (yestoall) { this.responseType = CimResponseType.YesToAll; @@ -87,7 +87,7 @@ public override void Execute(CmdletOperationBase cmdlet) case CimPromptType.Normal: try { - result = cmdlet.ShouldProcess(message); + result = cmdlet.ShouldProcess(Message); if (result) { this.responseType = CimResponseType.Yes; @@ -121,20 +121,12 @@ public override void Execute(CmdletOperationBase cmdlet) /// /// Prompt message. /// - public string Message - { - get - { - return message; - } - } - - private string message; + public string Message { get; } /// /// Prompt type -Normal or Critical. /// - private CimPromptType prompt; + private readonly CimPromptType prompt; #endregion } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs index 559c58b8a11..24b9332bde5 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs @@ -47,25 +47,17 @@ internal class CimSubscriptionResultEventArgs : CimSubscriptionEventArgs /// subscription result /// /// - public CimSubscriptionResult Result - { - get - { - return result; - } - } - - private CimSubscriptionResult result; + public CimSubscriptionResult Result { get; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// public CimSubscriptionResultEventArgs( CimSubscriptionResult theResult) { this.context = null; - this.result = theResult; + this.Result = theResult; } } @@ -81,25 +73,17 @@ internal class CimSubscriptionExceptionEventArgs : CimSubscriptionEventArgs /// subscription result /// /// - public Exception Exception - { - get - { - return exception; - } - } - - private Exception exception; + public Exception Exception { get; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// public CimSubscriptionExceptionEventArgs( Exception theException) { this.context = null; - this.exception = theException; + this.Exception = theException; } } @@ -118,9 +102,7 @@ internal sealed class CimRegisterCimIndication : CimAsyncOperation public event EventHandler OnNewSubscriptionResult; /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimRegisterCimIndication() : base() @@ -141,7 +123,7 @@ public void RegisterCimIndication( string nameSpace, string queryDialect, string queryExpression, - UInt32 operationTimeout) + uint operationTimeout) { DebugHelper.WriteLogEx("queryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); this.TargetComputerName = computerName; @@ -164,12 +146,12 @@ public void RegisterCimIndication( string nameSpace, string queryDialect, string queryExpression, - UInt32 operationTimeout) + uint operationTimeout) { DebugHelper.WriteLogEx("queryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); if (cimSession == null) { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentUICulture, CimCmdletStrings.NullArgument, @"cimSession")); + throw new ArgumentNullException(string.Format(CultureInfo.CurrentUICulture, CimCmdletStrings.NullArgument, nameof(cimSession))); } this.TargetComputerName = cimSession.ComputerName; @@ -219,7 +201,7 @@ private void CimIndicationHandler(object cimSession, CmdletActionEventArgs actio CimWriteError cimWriteError = actionArgs.Action as CimWriteError; if (cimWriteError != null) { - this.exception = cimWriteError.Exception; + this.Exception = cimWriteError.Exception; if (!this.ackedEvent.IsSet) { // an exception happened @@ -233,10 +215,10 @@ private void CimIndicationHandler(object cimSession, CmdletActionEventArgs actio { DebugHelper.WriteLog("Raise an exception event", 2); - temp(this, new CimSubscriptionExceptionEventArgs(this.exception)); + temp(this, new CimSubscriptionExceptionEventArgs(this.Exception)); } - DebugHelper.WriteLog("Got an exception: {0}", 2, exception); + DebugHelper.WriteLog("Got an exception: {0}", 2, Exception); } CimWriteResultObject cimWriteResultObject = actionArgs.Action as CimWriteResultObject; @@ -276,7 +258,7 @@ private void WaitForAckMessage() { DebugHelper.WriteLogEx(); this.ackedEvent.Wait(); - if (this.exception != null) + if (this.Exception != null) { DebugHelper.WriteLogEx("error happened", 0); if (this.Cmdlet != null) @@ -285,14 +267,14 @@ private void WaitForAckMessage() // throw terminating error ErrorRecord errorRecord = ErrorToErrorRecord.ErrorRecordFromAnyException( - new InvocationContext(this.TargetComputerName, null), this.exception, null); + new InvocationContext(this.TargetComputerName, null), this.Exception, null); this.Cmdlet.ThrowTerminatingError(errorRecord); } else { DebugHelper.WriteLogEx("Throw exception", 1); // throw exception out - throw this.exception; + throw this.Exception; } } @@ -309,8 +291,8 @@ private void WaitForAckMessage() /// internal Cmdlet Cmdlet { - set; get; + set; } /// @@ -318,8 +300,8 @@ internal Cmdlet Cmdlet /// internal string TargetComputerName { - set; get; + set; } #endregion @@ -335,7 +317,7 @@ internal string TargetComputerName /// private CimSessionProxy CreateSessionProxy( string computerName, - UInt32 timeout) + uint timeout) { CimSessionProxy proxy = CreateCimSessionProxy(computerName); proxy.OperationTimeout = timeout; @@ -350,7 +332,7 @@ private CimSessionProxy CreateSessionProxy( /// private CimSessionProxy CreateSessionProxy( CimSession session, - UInt32 timeout) + uint timeout) { CimSessionProxy proxy = CreateCimSessionProxy(session); proxy.OperationTimeout = timeout; @@ -363,15 +345,7 @@ private CimSessionProxy CreateSessionProxy( /// /// Exception occurred while start the subscription. /// - internal Exception Exception - { - get - { - return exception; - } - } - - private Exception exception; + internal Exception Exception { get; private set; } #endregion diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs index 3dbae04b726..a6182166170 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs @@ -3,8 +3,6 @@ #region Using directives -using System.Collections; -using System; using System.Collections.Generic; using System.Diagnostics; @@ -19,9 +17,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal class CimRemoveCimInstanceContext : XOperationContextBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// /// @@ -41,9 +37,7 @@ internal CimRemoveCimInstanceContext(string theNamespace, internal sealed class CimRemoveCimInstance : CimGetInstance { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimRemoveCimInstance() : base() @@ -62,7 +56,7 @@ public void RemoveCimInstance(RemoveCimInstanceCommand cmdlet) IEnumerable computerNames = ConstValue.GetComputerNames( GetComputerName(cmdlet)); - List proxys = new List(); + List proxys = new(); switch (cmdlet.ParameterSetName) { case CimBaseCommand.CimInstanceComputerSet: diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs index 55cf540c0e8..c27c7493ddb 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs @@ -4,8 +4,8 @@ #region Using directives using System; -using System.Management.Automation; using System.Globalization; +using System.Management.Automation; #endregion @@ -32,26 +32,18 @@ public enum AsyncResultType internal class CimResultContext { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// internal CimResultContext(object ErrorSource) { - this.errorSource = ErrorSource; + this.ErrorSource = ErrorSource; } /// /// ErrorSource property. /// - internal object ErrorSource - { - get - { - return this.errorSource; - } - } - - private object errorSource; + internal object ErrorSource { get; } } #endregion @@ -64,12 +56,12 @@ internal object ErrorSource internal abstract class AsyncResultEventArgsBase : EventArgs { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// /// - public AsyncResultEventArgsBase( + protected AsyncResultEventArgsBase( CimSession session, IObservable observable, AsyncResultType resultType) @@ -80,13 +72,13 @@ public AsyncResultEventArgsBase( } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// /// /// - public AsyncResultEventArgsBase( + protected AsyncResultEventArgsBase( CimSession session, IObservable observable, AsyncResultType resultType, @@ -117,16 +109,14 @@ public AsyncResultEventArgsBase( internal class AsyncResultCompleteEventArgs : AsyncResultEventArgsBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// object. /// public AsyncResultCompleteEventArgs( CimSession session, - IObservable observable) : - base(session, observable, AsyncResultType.Completion) + IObservable observable) + : base(session, observable, AsyncResultType.Completion) { } } @@ -139,7 +129,7 @@ public AsyncResultCompleteEventArgs( internal class AsyncResultObjectEventArgs : AsyncResultEventArgsBase { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -147,8 +137,8 @@ internal class AsyncResultObjectEventArgs : AsyncResultEventArgsBase public AsyncResultObjectEventArgs( CimSession session, IObservable observable, - object resultObject) : - base(session, observable, AsyncResultType.Result) + object resultObject) + : base(session, observable, AsyncResultType.Result) { this.resultObject = resultObject; } @@ -164,7 +154,7 @@ public AsyncResultObjectEventArgs( internal class AsyncResultErrorEventArgs : AsyncResultEventArgsBase { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -172,14 +162,14 @@ internal class AsyncResultErrorEventArgs : AsyncResultEventArgsBase public AsyncResultErrorEventArgs( CimSession session, IObservable observable, - Exception error) : - base(session, observable, AsyncResultType.Exception) + Exception error) + : base(session, observable, AsyncResultType.Exception) { this.error = error; } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -189,8 +179,8 @@ public AsyncResultErrorEventArgs( CimSession session, IObservable observable, Exception error, - CimResultContext cimResultContext) : - base(session, observable, AsyncResultType.Exception, cimResultContext) + CimResultContext cimResultContext) + : base(session, observable, AsyncResultType.Exception, cimResultContext) { this.error = error; } @@ -216,34 +206,24 @@ public AsyncResultErrorEventArgs( /// object type internal class CimResultObserver : IObserver { - /// - /// Define delegate that handles new cmdlet action come from - /// the operations related to the current CimSession object. - /// - /// CimSession object, which raised the event. - /// Event args. - public delegate void ResultEventHandler( - object observer, - AsyncResultEventArgsBase resultArgs); - /// /// Define an Event based on the NewActionHandler. /// - public event ResultEventHandler OnNewResult; + public event EventHandler OnNewResult; /// - /// Constructor. + /// Initializes a new instance of the class. /// /// object that issued the operation. /// Operation that can be observed. public CimResultObserver(CimSession session, IObservable observable) { - this.session = session; + this.CurrentSession = session; this.observable = observable; } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// object that issued the operation. /// Operation that can be observed. @@ -251,7 +231,7 @@ public CimResultObserver(CimSession session, IObservable observable, CimResultContext cimResultContext) { - this.session = session; + this.CurrentSession = session; this.observable = observable; this.context = cimResultContext; } @@ -269,8 +249,8 @@ public virtual void OnCompleted() // OnNext, OnError try { - AsyncResultCompleteEventArgs completeArgs = new AsyncResultCompleteEventArgs( - this.session, this.observable); + AsyncResultCompleteEventArgs completeArgs = new( + this.CurrentSession, this.observable); this.OnNewResult(this, completeArgs); } catch (Exception ex) @@ -290,8 +270,8 @@ public virtual void OnError(Exception error) { try { - AsyncResultErrorEventArgs errorArgs = new AsyncResultErrorEventArgs( - this.session, this.observable, error, this.context); + AsyncResultErrorEventArgs errorArgs = new( + this.CurrentSession, this.observable, error, this.context); this.OnNewResult(this, errorArgs); } catch (Exception ex) @@ -310,8 +290,8 @@ protected void OnNextCore(object value) DebugHelper.WriteLogEx("value = {0}.", 1, value); try { - AsyncResultObjectEventArgs resultArgs = new AsyncResultObjectEventArgs( - this.session, this.observable, value); + AsyncResultObjectEventArgs resultArgs = new( + this.CurrentSession, this.observable, value); this.OnNewResult(this, resultArgs); } catch (Exception ex) @@ -344,25 +324,17 @@ public virtual void OnNext(T value) /// /// Session object of the operation. /// - protected CimSession CurrentSession - { - get - { - return session; - } - } - - private CimSession session; + protected CimSession CurrentSession { get; } /// /// Async operation that can be observed. /// - private IObservable observable; + private readonly IObservable observable; /// /// object used during delivering result. /// - private CimResultContext context; + private readonly CimResultContext context; #endregion } @@ -372,7 +344,7 @@ protected CimSession CurrentSession internal class CimSubscriptionResultObserver : CimResultObserver { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -382,7 +354,7 @@ public CimSubscriptionResultObserver(CimSession session, IObservable obs } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -411,7 +383,7 @@ public override void OnNext(CimSubscriptionResult value) internal class CimMethodResultObserver : CimResultObserver { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -421,7 +393,7 @@ public CimMethodResultObserver(CimSession session, IObservable observabl } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// @@ -504,7 +476,7 @@ internal string ClassName internal class IgnoreResultObserver : CimResultObserver { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs index 0dd85ea213c..c22db2087e4 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs @@ -6,9 +6,9 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Management.Automation; using System.Management.Automation.Runspaces; -using System.Globalization; using Microsoft.Management.Infrastructure.Options; #endregion @@ -24,67 +24,27 @@ internal class CimSessionWrapper /// /// Id of the cimsession. /// - public uint SessionId - { - get - { - return this.sessionId; - } - } - - private uint sessionId; + public uint SessionId { get; } /// /// InstanceId of the cimsession. /// - public Guid InstanceId - { - get - { - return this.instanceId; - } - } - - private Guid instanceId; + public Guid InstanceId { get; } /// /// Name of the cimsession. /// - public string Name - { - get - { - return this.name; - } - } - - private string name; + public string Name { get; } /// /// Computer name of the cimsession. /// - public string ComputerName - { - get - { - return this.computerName; - } - } - - private string computerName; + public string ComputerName { get; } /// /// Wrapped cimsession object. /// - public CimSession CimSession - { - get - { - return this.cimSession; - } - } - - private CimSession cimSession; + public CimSession CimSession { get; } /// /// Computer name of the cimsession. @@ -110,7 +70,7 @@ internal ProtocolType GetProtocolType() return protocol; } - private ProtocolType protocol; + private readonly ProtocolType protocol; /// /// PSObject that wrapped the cimSession. @@ -127,11 +87,11 @@ internal CimSessionWrapper( CimSession theCimSession, ProtocolType theProtocol) { - this.sessionId = theSessionId; - this.instanceId = theInstanceId; - this.name = theName; - this.computerName = theComputerName; - this.cimSession = theCimSession; + this.SessionId = theSessionId; + this.InstanceId = theInstanceId; + this.Name = theName; + this.ComputerName = theComputerName; + this.CimSession = theCimSession; this.psObject = null; this.protocol = theProtocol; } @@ -140,18 +100,18 @@ internal PSObject GetPSObject() { if (psObject == null) { - psObject = new PSObject(this.cimSession); - psObject.Properties.Add(new PSNoteProperty(CimSessionState.idPropName, this.sessionId)); - psObject.Properties.Add(new PSNoteProperty(CimSessionState.namePropName, this.name)); - psObject.Properties.Add(new PSNoteProperty(CimSessionState.instanceidPropName, this.instanceId)); + psObject = new PSObject(this.CimSession); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.idPropName, this.SessionId)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.namePropName, this.Name)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.instanceidPropName, this.InstanceId)); psObject.Properties.Add(new PSNoteProperty(CimSessionState.computernamePropName, this.ComputerName)); psObject.Properties.Add(new PSNoteProperty(CimSessionState.protocolPropName, this.Protocol)); } else { psObject.Properties[CimSessionState.idPropName].Value = this.SessionId; - psObject.Properties[CimSessionState.namePropName].Value = this.name; - psObject.Properties[CimSessionState.instanceidPropName].Value = this.instanceId; + psObject.Properties[CimSessionState.namePropName].Value = this.Name; + psObject.Properties[CimSessionState.instanceidPropName].Value = this.InstanceId; psObject.Properties[CimSessionState.computernamePropName].Value = this.ComputerName; psObject.Properties[CimSessionState.protocolPropName].Value = this.Protocol; } @@ -231,42 +191,40 @@ internal class CimSessionState : IDisposable /// Dictionary used to holds all CimSessions in current runspace by session name. /// /// - private Dictionary> curCimSessionsByName; + private readonly Dictionary> curCimSessionsByName; /// /// /// Dictionary used to holds all CimSessions in current runspace by computer name. /// /// - private Dictionary> curCimSessionsByComputerName; + private readonly Dictionary> curCimSessionsByComputerName; /// /// /// Dictionary used to holds all CimSessions in current runspace by instance ID. /// /// - private Dictionary curCimSessionsByInstanceId; + private readonly Dictionary curCimSessionsByInstanceId; /// /// /// Dictionary used to holds all CimSessions in current runspace by session id. /// /// - private Dictionary curCimSessionsById; + private readonly Dictionary curCimSessionsById; /// /// /// Dictionary used to link CimSession object with PSObject. /// /// - private Dictionary curCimSessionWrapper; + private readonly Dictionary curCimSessionWrapper; #endregion /// - /// - /// The constructor. - /// + /// Initializes a new instance of the class. /// internal CimSessionState() { @@ -399,7 +357,7 @@ internal PSObject AddObjectToCache( string computerName, ProtocolType protocol) { - CimSessionWrapper wrapper = new CimSessionWrapper( + CimSessionWrapper wrapper = new( sessionId, instanceId, name, computerName, session, protocol); HashSet objects; @@ -546,7 +504,7 @@ private void RemoveSessionInternal(CimSession session, CimSessionWrapper wrapper /// /// /// - private void AddErrorRecord( + private static void AddErrorRecord( ref List errRecords, string propertyName, object propertyValue) @@ -568,9 +526,9 @@ internal IEnumerable QuerySession( IEnumerable ids, out IEnumerable errorRecords) { - HashSet sessions = new HashSet(); - HashSet sessionIds = new HashSet(); - List errRecords = new List(); + HashSet sessions = new(); + HashSet sessionIds = new(); + List errRecords = new(); errorRecords = errRecords; // NOTES: use template function to implement this will save duplicate code foreach (uint id in ids) @@ -601,9 +559,9 @@ internal IEnumerable QuerySession( IEnumerable instanceIds, out IEnumerable errorRecords) { - HashSet sessions = new HashSet(); - HashSet sessionIds = new HashSet(); - List errRecords = new List(); + HashSet sessions = new(); + HashSet sessionIds = new(); + List errRecords = new(); errorRecords = errRecords; foreach (Guid instanceid in instanceIds) { @@ -633,20 +591,20 @@ internal IEnumerable QuerySession( internal IEnumerable QuerySession(IEnumerable nameArray, out IEnumerable errorRecords) { - HashSet sessions = new HashSet(); - HashSet sessionIds = new HashSet(); - List errRecords = new List(); + HashSet sessions = new(); + HashSet sessionIds = new(); + List errRecords = new(); errorRecords = errRecords; foreach (string name in nameArray) { bool foundSession = false; - WildcardPattern pattern = new WildcardPattern(name, WildcardOptions.IgnoreCase); + WildcardPattern pattern = new(name, WildcardOptions.IgnoreCase); foreach (KeyValuePair> kvp in this.curCimSessionsByName) { if (pattern.IsMatch(kvp.Key)) { HashSet wrappers = kvp.Value; - foundSession = (wrappers.Count > 0); + foundSession = wrappers.Count > 0; foreach (CimSessionWrapper wrapper in wrappers) { if (!sessionIds.Contains(wrapper.SessionId)) @@ -676,9 +634,9 @@ internal IEnumerable QuerySessionByComputerName( IEnumerable computernameArray, out IEnumerable errorRecords) { - HashSet sessions = new HashSet(); - HashSet sessionIds = new HashSet(); - List errRecords = new List(); + HashSet sessions = new(); + HashSet sessionIds = new(); + List errRecords = new(); errorRecords = errRecords; foreach (string computername in computernameArray) { @@ -686,7 +644,7 @@ internal IEnumerable QuerySessionByComputerName( if (this.curCimSessionsByComputerName.ContainsKey(computername)) { HashSet wrappers = this.curCimSessionsByComputerName[computername]; - foundSession = (wrappers.Count > 0); + foundSession = wrappers.Count > 0; foreach (CimSessionWrapper wrapper in wrappers) { if (!sessionIds.Contains(wrapper.SessionId)) @@ -714,9 +672,9 @@ internal IEnumerable QuerySessionByComputerName( internal IEnumerable QuerySession(IEnumerable cimsessions, out IEnumerable errorRecords) { - HashSet sessions = new HashSet(); - HashSet sessionIds = new HashSet(); - List errRecords = new List(); + HashSet sessions = new(); + HashSet sessionIds = new(); + List errRecords = new(); errorRecords = errRecords; foreach (CimSession cimsession in cimsessions) { @@ -785,13 +743,13 @@ internal class CimSessionBase #region constructor /// - /// The constructor. + /// Initializes a new instance of the class. /// public CimSessionBase() { this.sessionState = cimSessions.GetOrAdd( CurrentRunspaceId, - delegate (Guid instanceId) + (Guid instanceId) => { if (Runspace.DefaultRunspace != null) { @@ -814,7 +772,7 @@ public CimSessionBase() /// /// internal static readonly ConcurrentDictionary cimSessions - = new ConcurrentDictionary(); + = new(); /// /// @@ -908,9 +866,7 @@ internal class CimNewSession : CimSessionBase, IDisposable internal class CimTestCimSessionContext : XOperationContextBase { /// - /// - /// The constructor. - /// + /// Initializes a new instance of the class. /// /// /// @@ -919,33 +875,23 @@ internal CimTestCimSessionContext( CimSessionWrapper wrapper) { this.proxy = theProxy; - this.cimSessionWrapper = wrapper; + this.CimSessionWrapper = wrapper; this.nameSpace = null; } /// /// Namespace /// - internal CimSessionWrapper CimSessionWrapper - { - get - { - return this.cimSessionWrapper; - } - } - - private CimSessionWrapper cimSessionWrapper; + internal CimSessionWrapper CimSessionWrapper { get; } } /// - /// - /// The constructor. - /// + /// Initializes a new instance of the class. /// internal CimNewSession() : base() { this.cimTestSession = new CimTestSession(); - this._disposed = false; + this.Disposed = false; } /// @@ -974,8 +920,8 @@ internal void NewCimSession(NewCimSessionCommand cmdlet, proxy = new CimSessionProxyTestConnection(computerName, sessionOptions); string computerNameValue = (computerName == ConstValue.NullComputerName) ? ConstValue.LocalhostComputerName : computerName; - CimSessionWrapper wrapper = new CimSessionWrapper(0, Guid.Empty, cmdlet.Name, computerNameValue, proxy.CimSession, proxy.Protocol); - CimTestCimSessionContext context = new CimTestCimSessionContext(proxy, wrapper); + CimSessionWrapper wrapper = new(0, Guid.Empty, cmdlet.Name, computerNameValue, proxy.CimSession, proxy.Protocol); + CimTestCimSessionContext context = new(proxy, wrapper); proxy.ContextObject = context; // Skip test the connection if user intend to if (cmdlet.SkipTestConnection.IsPresent) @@ -1005,7 +951,7 @@ internal void AddSessionToCache(CimSession cimSession, XOperationContextBase con CimTestCimSessionContext testCimSessionContext = context as CimTestCimSessionContext; uint sessionId = this.sessionState.GenerateSessionId(); string originalSessionName = testCimSessionContext.CimSessionWrapper.Name; - string sessionName = (originalSessionName != null) ? originalSessionName : string.Format(CultureInfo.CurrentUICulture, @"{0}{1}", CimSessionState.CimSessionClassName, sessionId); + string sessionName = originalSessionName ?? string.Format(CultureInfo.CurrentUICulture, @"{0}{1}", CimSessionState.CimSessionClassName, sessionId); // detach CimSession from the proxy object CimSession createdCimSession = testCimSessionContext.Proxy.Detach(); @@ -1052,7 +998,7 @@ public void ProcessRemainActions(CmdletOperationBase cmdletOperation) /// object. /// /// - private CimTestSession cimTestSession; + private readonly CimTestSession cimTestSession; #endregion // private members #region IDisposable @@ -1062,15 +1008,7 @@ public void ProcessRemainActions(CmdletOperationBase cmdletOperation) /// Indicates whether this object was disposed or not. /// /// - protected bool Disposed - { - get - { - return _disposed; - } - } - - private bool _disposed; + protected bool Disposed { get; private set; } /// /// @@ -1104,13 +1042,13 @@ public void Dispose() /// Whether it is directly called. protected virtual void Dispose(bool disposing) { - if (!this._disposed) + if (!this.Disposed) { if (disposing) { // free managed resources this.cimTestSession.Dispose(); - this._disposed = true; + this.Disposed = true; } // free native resources if there are any } @@ -1130,7 +1068,7 @@ protected virtual void Dispose(bool disposing) internal class CimGetSession : CimSessionBase { /// - /// The constructor. + /// Initializes a new instance of the class. /// public CimGetSession() : base() { @@ -1212,7 +1150,7 @@ internal class CimRemoveSession : CimSessionBase internal static readonly string RemoveCimSessionActionName = "Remove CimSession"; /// - /// Constructor. + /// Initializes a new instance of the class. /// public CimRemoveSession() : base() { @@ -1282,7 +1220,7 @@ public void RemoveCimSession(RemoveCimSessionCommand cmdlet) internal class CimTestSession : CimAsyncOperation { /// - /// Constructor. + /// Initializes a new instance of the class. /// internal CimTestSession() : base() diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs index 56e90ad6f8b..9321c86ec77 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs @@ -65,7 +65,7 @@ internal CimSessionProxy Proxy internal class InvocationContext { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// internal InvocationContext(CimSessionProxy proxy) @@ -78,7 +78,7 @@ internal InvocationContext(CimSessionProxy proxy) } /// - /// Constructor. + /// Initializes a new instance of the class. /// /// internal InvocationContext(string computerName, CimInstance targetCimInstance) @@ -91,20 +91,20 @@ internal InvocationContext(string computerName, CimInstance targetCimInstance) /// /// ComputerName of the session /// + /// /// /// return value could be null /// - /// internal virtual string ComputerName { get; } /// /// /// CimInstance on which the current operation against. /// + /// /// /// return value could be null /// - /// internal virtual CimInstance TargetCimInstance { get; } } #endregion @@ -135,7 +135,7 @@ internal interface IObjectPreProcess internal sealed class CmdletActionEventArgs : EventArgs { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// CimBaseAction object bound to the event. public CmdletActionEventArgs(CimBaseAction action) @@ -152,7 +152,7 @@ public CmdletActionEventArgs(CimBaseAction action) internal sealed class OperationEventArgs : EventArgs { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// Object used to cancel the operation. /// Async observable operation. @@ -192,7 +192,7 @@ internal class CimSessionProxy : IDisposable /// /// Temporary CimSession cache lock. /// - private static readonly object temporarySessionCacheLock = new object(); + private static readonly object temporarySessionCacheLock = new(); /// /// temporary CimSession cache @@ -210,7 +210,7 @@ internal class CimSessionProxy : IDisposable /// then call Dispose on it. /// /// - private static Dictionary temporarySessionCache = new Dictionary(); + private static readonly Dictionary temporarySessionCache = new(); /// /// @@ -296,88 +296,80 @@ internal static void RemoveCimSessionFromTemporaryCache(CimSession session) #region Event definitions - /// - /// Define delegate that handles new cmdlet action come from - /// the operations related to the current CimSession object. - /// - /// CimSession object, which raised the event. - /// Event args. - public delegate void NewCmdletActionHandler( - object cimSession, - CmdletActionEventArgs actionArgs); - /// /// Define an Event based on the NewActionHandler. /// - public event NewCmdletActionHandler OnNewCmdletAction; - - /// - /// Define delegate that handles operation creation and complete - /// issued by the current CimSession object. - /// - /// CimSession object, which raised the event. - /// Event args. - public delegate void OperationEventHandler( - object cimSession, - OperationEventArgs actionArgs); + public event EventHandler OnNewCmdletAction; /// /// Event triggered when a new operation is started. /// - public event OperationEventHandler OnOperationCreated; + public event EventHandler OnOperationCreated; /// /// Event triggered when a new operation is completed, /// either success or failed. /// - public event OperationEventHandler OnOperationDeleted; + public event EventHandler OnOperationDeleted; #endregion #region constructors /// - /// Then create wrapper object by given CimSessionProxy object. + /// Initializes a new instance of the class. /// + /// + /// Then create wrapper object by given CimSessionProxy object. + /// /// public CimSessionProxy(CimSessionProxy proxy) { DebugHelper.WriteLogEx("protocol = {0}", 1, proxy.Protocol); CreateSetSession(null, proxy.CimSession, null, proxy.OperationOptions, proxy.IsTemporaryCimSession); - this.protocol = proxy.Protocol; + this.Protocol = proxy.Protocol; this.OperationTimeout = proxy.OperationTimeout; this.isDefaultSession = proxy.isDefaultSession; } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name. /// Then create wrapper object. - /// + /// /// public CimSessionProxy(string computerName) { CreateSetSession(computerName, null, null, null, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and session options. /// Then create wrapper object. - /// + /// /// /// public CimSessionProxy(string computerName, CimSessionOptions sessionOptions) { CreateSetSession(computerName, null, sessionOptions, null, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and cimInstance. Then create wrapper object. - /// + /// /// /// public CimSessionProxy(string computerName, CimInstance cimInstance) @@ -411,39 +403,48 @@ public CimSessionProxy(string computerName, CimInstance cimInstance) string cimsessionComputerName = cimInstance.GetCimSessionComputerName(); CreateSetSession(cimsessionComputerName, null, null, null, false); - this.isDefaultSession = (cimsessionComputerName == ConstValue.NullComputerName); + this.isDefaultSession = cimsessionComputerName == ConstValue.NullComputerName; DebugHelper.WriteLogEx("Create a temp session with computerName = {0}.", 0, cimsessionComputerName); } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name, /// session options. - /// + /// /// /// /// Used when create async operation. public CimSessionProxy(string computerName, CimSessionOptions sessionOptions, CimOperationOptions operOptions) { CreateSetSession(computerName, null, sessionOptions, operOptions, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name. /// Then create wrapper object. - /// + /// /// /// Used when create async operation. public CimSessionProxy(string computerName, CimOperationOptions operOptions) { CreateSetSession(computerName, null, null, operOptions, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// - /// Create wrapper object by given session object. + /// Initializes a new instance of the class. /// + /// + /// Create wrapper object by given session object. + /// /// public CimSessionProxy(CimSession session) { @@ -451,8 +452,11 @@ public CimSessionProxy(CimSession session) } /// - /// Create wrapper object by given session object. + /// Initializes a new instance of the class. /// + /// + /// Create wrapper object by given session object. + /// /// /// Used when create async operation. public CimSessionProxy(CimSession session, CimOperationOptions operOptions) @@ -483,19 +487,19 @@ private void CreateSetSession( } InitOption(operOptions); - this.protocol = ProtocolType.Wsman; - this.isTemporaryCimSession = temporaryCimSession; + this.Protocol = ProtocolType.Wsman; + this.IsTemporaryCimSession = temporaryCimSession; if (cimSession != null) { - this.session = cimSession; + this.CimSession = cimSession; CimSessionState state = CimSessionBase.GetCimSessionState(); if (state != null) { CimSessionWrapper wrapper = state.QuerySession(cimSession); if (wrapper != null) { - this.protocol = wrapper.GetProtocolType(); + this.Protocol = wrapper.GetProtocolType(); } } } @@ -506,29 +510,29 @@ private void CreateSetSession( if (sessionOptions is DComSessionOptions) { string defaultComputerName = ConstValue.IsDefaultComputerName(computerName) ? ConstValue.NullComputerName : computerName; - this.session = CimSession.Create(defaultComputerName, sessionOptions); - this.protocol = ProtocolType.Dcom; + this.CimSession = CimSession.Create(defaultComputerName, sessionOptions); + this.Protocol = ProtocolType.Dcom; } else { - this.session = CimSession.Create(computerName, sessionOptions); + this.CimSession = CimSession.Create(computerName, sessionOptions); } } else { - this.session = CreateCimSessionByComputerName(computerName); + this.CimSession = CreateCimSessionByComputerName(computerName); } - this.isTemporaryCimSession = true; + this.IsTemporaryCimSession = true; } - if (this.isTemporaryCimSession) + if (this.IsTemporaryCimSession) { - AddCimSessionToTemporaryCache(this.session); + AddCimSessionToTemporaryCache(this.CimSession); } this.invocationContextObject = new InvocationContext(this); - DebugHelper.WriteLog("Protocol {0}, Is temporary session ? {1}", 1, this.protocol, this.isTemporaryCimSession); + DebugHelper.WriteLog("Protocol {0}, Is temporary session ? {1}", 1, this.Protocol, this.IsTemporaryCimSession); } #endregion @@ -538,18 +542,18 @@ private void CreateSetSession( /// /// Set timeout value (seconds) of the operation. /// - public UInt32 OperationTimeout + public uint OperationTimeout { - set + get { - DebugHelper.WriteLogEx("OperationTimeout {0},", 0, value); - - this.options.Timeout = TimeSpan.FromSeconds((double)value); + return (uint)this.OperationOptions.Timeout.TotalSeconds; } - get + set { - return (UInt32)this.options.Timeout.TotalSeconds; + DebugHelper.WriteLogEx("OperationTimeout {0},", 0, value); + + this.OperationOptions.Timeout = TimeSpan.FromSeconds((double)value); } } @@ -558,16 +562,16 @@ public UInt32 OperationTimeout /// public Uri ResourceUri { - set + get { - DebugHelper.WriteLogEx("ResourceUri {0},", 0, value); - - this.options.ResourceUri = value; + return this.OperationOptions.ResourceUri; } - get + set { - return this.options.ResourceUri; + DebugHelper.WriteLogEx("ResourceUri {0},", 0, value); + + this.OperationOptions.ResourceUri = value; } } @@ -579,13 +583,13 @@ public bool EnableMethodResultStreaming { get { - return this.options.EnableMethodResultStreaming; + return this.OperationOptions.EnableMethodResultStreaming; } set { DebugHelper.WriteLogEx("EnableMethodResultStreaming {0}", 0, value); - this.options.EnableMethodResultStreaming = value; + this.OperationOptions.EnableMethodResultStreaming = value; } } @@ -600,7 +604,7 @@ public bool EnablePromptUser DebugHelper.WriteLogEx("EnablePromptUser {0}", 0, value); if (value) { - this.options.PromptUser = this.PromptUser; + this.OperationOptions.PromptUser = this.PromptUser; } } } @@ -614,15 +618,15 @@ private void EnablePSSemantics() // this.options.PromptUserForceFlag... // this.options.WriteErrorMode - this.options.WriteErrorMode = CimCallbackMode.Inquire; + this.OperationOptions.WriteErrorMode = CimCallbackMode.Inquire; // !!!NOTES: Does not subscribe to PromptUser for CimCmdlets now // since cmdlet does not provider an approach // to let user select how to handle prompt message // this can be enabled later if needed. - this.options.WriteError = this.WriteError; - this.options.WriteMessage = this.WriteMessage; - this.options.WriteProgress = this.WriteProgress; + this.OperationOptions.WriteError = this.WriteError; + this.OperationOptions.WriteMessage = this.WriteMessage; + this.OperationOptions.WriteProgress = this.WriteProgress; } /// @@ -630,7 +634,7 @@ private void EnablePSSemantics() /// public SwitchParameter KeyOnly { - set { this.options.KeysOnly = value.IsPresent; } + set { this.OperationOptions.KeysOnly = value.IsPresent; } } /// @@ -642,11 +646,11 @@ public SwitchParameter Shallow { if (value.IsPresent) { - this.options.Flags = CimOperationFlags.PolymorphismShallow; + this.OperationOptions.Flags = CimOperationFlags.PolymorphismShallow; } else { - this.options.Flags = CimOperationFlags.None; + this.OperationOptions.Flags = CimOperationFlags.None; } } } @@ -660,11 +664,11 @@ private void InitOption(CimOperationOptions operOptions) if (operOptions != null) { - this.options = new CimOperationOptions(operOptions); + this.OperationOptions = new CimOperationOptions(operOptions); } - else if (this.options == null) + else if (this.OperationOptions == null) { - this.options = new CimOperationOptions(); + this.OperationOptions = new CimOperationOptions(); } this.EnableMethodResultStreaming = true; @@ -685,10 +689,10 @@ public CimSession Detach() DebugHelper.WriteLogEx(); // Remove the CimSession from cache but don't dispose it - RemoveCimSessionFromTemporaryCache(this.session, false); - CimSession sessionToReturn = this.session; - this.session = null; - this.isTemporaryCimSession = false; + RemoveCimSessionFromTemporaryCache(this.CimSession, false); + CimSession sessionToReturn = this.CimSession; + this.CimSession = null; + this.IsTemporaryCimSession = false; return sessionToReturn; } @@ -727,7 +731,7 @@ private void RemoveOperation(IObservable operation) this.operation = null; } - if (this.session != null && this.ContextObject == null) + if (this.CimSession != null && this.ContextObject == null) { DebugHelper.WriteLog("Dispose this proxy object @ RemoveOperation"); this.Dispose(); @@ -745,16 +749,16 @@ protected void FireNewActionEvent(CimBaseAction action) { DebugHelper.WriteLogEx(); - CmdletActionEventArgs actionArgs = new CmdletActionEventArgs(action); + CmdletActionEventArgs actionArgs = new(action); if (!PreNewActionEvent(actionArgs)) { return; } - NewCmdletActionHandler temp = this.OnNewCmdletAction; + EventHandler temp = this.OnNewCmdletAction; if (temp != null) { - temp(this.session, actionArgs); + temp(this.CimSession, actionArgs); } else { @@ -777,13 +781,9 @@ private void FireOperationCreatedEvent( { DebugHelper.WriteLogEx(); - OperationEventArgs args = new OperationEventArgs( + OperationEventArgs args = new( cancelOperation, operation, false); - OperationEventHandler temp = this.OnOperationCreated; - if (temp != null) - { - temp(this.session, args); - } + this.OnOperationCreated?.Invoke(this.CimSession, args); this.PostOperationCreateEvent(args); } @@ -800,14 +800,10 @@ private void FireOperationDeletedEvent( { DebugHelper.WriteLogEx(); this.WriteOperationCompleteMessage(this.operationName); - OperationEventArgs args = new OperationEventArgs( + OperationEventArgs args = new( null, operation, success); PreOperationDeleteEvent(args); - OperationEventHandler temp = this.OnOperationDeleted; - if (temp != null) - { - temp(this.session, args); - } + this.OnOperationDeleted?.Invoke(this.CimSession, args); this.PostOperationDeleteEvent(args); this.RemoveOperation(operation); @@ -825,12 +821,12 @@ private void FireOperationDeletedEvent( /// /// /// - internal void WriteMessage(UInt32 channel, string message) + internal void WriteMessage(uint channel, string message) { DebugHelper.WriteLogEx("Channel = {0} message = {1}", 0, channel, message); try { - CimWriteMessage action = new CimWriteMessage(channel, message); + CimWriteMessage action = new(channel, message); this.FireNewActionEvent(action); } catch (Exception ex) @@ -849,14 +845,14 @@ internal void WriteMessage(UInt32 channel, string message) internal void WriteOperationStartMessage(string operation, Hashtable parameterList) { DebugHelper.WriteLogEx(); - StringBuilder parameters = new StringBuilder(); + StringBuilder parameters = new(); if (parameterList != null) { foreach (string key in parameterList.Keys) { if (parameters.Length > 0) { - parameters.Append(","); + parameters.Append(','); } parameters.Append(string.Format(CultureInfo.CurrentUICulture, @"'{0}' = {1}", key, parameterList[key])); @@ -867,7 +863,7 @@ internal void WriteOperationStartMessage(string operation, Hashtable parameterLi CimCmdletStrings.CimOperationStart, operation, (parameters.Length == 0) ? "null" : parameters.ToString()); - WriteMessage((UInt32)CimWriteMessageChannel.Verbose, operationStartMessage); + WriteMessage((uint)CimWriteMessageChannel.Verbose, operationStartMessage); } /// @@ -882,7 +878,7 @@ internal void WriteOperationCompleteMessage(string operation) string operationCompleteMessage = string.Format(CultureInfo.CurrentUICulture, CimCmdletStrings.CimOperationCompleted, operation); - WriteMessage((UInt32)CimWriteMessageChannel.Verbose, operationCompleteMessage); + WriteMessage((uint)CimWriteMessageChannel.Verbose, operationCompleteMessage); } /// @@ -898,15 +894,15 @@ internal void WriteOperationCompleteMessage(string operation) public void WriteProgress(string activity, string currentOperation, string statusDescription, - UInt32 percentageCompleted, - UInt32 secondsRemaining) + uint percentageCompleted, + uint secondsRemaining) { DebugHelper.WriteLogEx("activity:{0}; currentOperation:{1}; percentageCompleted:{2}; secondsRemaining:{3}", 0, activity, currentOperation, percentageCompleted, secondsRemaining); try { - CimWriteProgress action = new CimWriteProgress( + CimWriteProgress action = new( activity, (int)this.operationID, currentOperation, @@ -933,7 +929,7 @@ public CimResponseType WriteError(CimInstance instance) DebugHelper.WriteLogEx("Error:{0}", 0, instance); try { - CimWriteError action = new CimWriteError(instance, this.invocationContextObject); + CimWriteError action = new(instance, this.invocationContextObject); this.FireNewActionEvent(action); return action.GetResponse(); } @@ -955,7 +951,7 @@ public CimResponseType PromptUser(string message, CimPromptType prompt) DebugHelper.WriteLogEx("message:{0} prompt:{1}", 0, message, prompt); try { - CimPromptUser action = new CimPromptUser(message, prompt); + CimPromptUser action = new(message, prompt); this.FireNewActionEvent(action); return action.GetResponse(); } @@ -971,7 +967,7 @@ public CimResponseType PromptUser(string message, CimPromptType prompt) /// /// - /// Handle async event triggered by + /// Handle async event triggered by /// /// /// Object triggered the event. @@ -997,7 +993,7 @@ internal void ResultEventHandler( AsyncResultErrorEventArgs args = resultArgs as AsyncResultErrorEventArgs; DebugHelper.WriteLog("ResultEventHandler::Exception {0}", 4, args.error); - using (CimWriteError action = new CimWriteError(args.error, this.invocationContextObject, args.context)) + using (CimWriteError action = new(args.error, this.invocationContextObject, args.context)) { this.FireNewActionEvent(action); } @@ -1023,7 +1019,7 @@ internal void ResultEventHandler( #if DEBUG resultObject = PostProcessCimInstance(resultObject); #endif - CimWriteResultObject action = new CimWriteResultObject(resultObject, this.ContextObject); + CimWriteResultObject action = new(resultObject, this.ContextObject); this.FireNewActionEvent(action); } @@ -1052,19 +1048,19 @@ private static void AddShowComputerNameMarker(object o) return; } - PSNoteProperty psShowComputerNameProperty = new PSNoteProperty(ConstValue.ShowComputerNameNoteProperty, true); + PSNoteProperty psShowComputerNameProperty = new(ConstValue.ShowComputerNameNoteProperty, true); pso.Members.Add(psShowComputerNameProperty); } #if DEBUG - private static bool isCliXmlTestabilityHookActive = GetIsCliXmlTestabilityHookActive(); + private static readonly bool isCliXmlTestabilityHookActive = GetIsCliXmlTestabilityHookActive(); private static bool GetIsCliXmlTestabilityHookActive() { return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CDXML_CLIXML_TEST")); } - private object PostProcessCimInstance(object resultObject) + private static object PostProcessCimInstance(object resultObject) { DebugHelper.WriteLogEx(); if (isCliXmlTestabilityHookActive && (resultObject is CimInstance)) @@ -1093,15 +1089,15 @@ private object PostProcessCimInstance(object resultObject) public void CreateInstanceAsync(string namespaceName, CimInstance instance) { Debug.Assert(instance != null, "Caller should verify that instance != NULL."); - DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.OperationOptions.EnableMethodResultStreaming); this.CheckAvailability(); - this.targetCimInstance = instance; + this.TargetCimInstance = instance; this.operationName = CimCmdletStrings.CimOperationNameCreateInstance; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"instance", instance); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncResult asyncResult = this.session.CreateInstanceAsync(namespaceName, instance, this.options); + CimAsyncResult asyncResult = this.CimSession.CreateInstanceAsync(namespaceName, instance, this.OperationOptions); ConsumeCimInstanceAsync(asyncResult, new CimResultContext(instance)); } @@ -1115,13 +1111,13 @@ public void DeleteInstanceAsync(string namespaceName, CimInstance instance) Debug.Assert(instance != null, "Caller should verify that instance != NULL."); DebugHelper.WriteLogEx("namespace = {0}; classname = {1};", 0, namespaceName, instance.CimSystemProperties.ClassName); this.CheckAvailability(); - this.targetCimInstance = instance; + this.TargetCimInstance = instance; this.operationName = CimCmdletStrings.CimOperationNameDeleteInstance; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"instance", instance); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncStatus asyncResult = this.session.DeleteInstanceAsync(namespaceName, instance, this.options); + CimAsyncStatus asyncResult = this.CimSession.DeleteInstanceAsync(namespaceName, instance, this.OperationOptions); ConsumeObjectAsync(asyncResult, new CimResultContext(instance)); } @@ -1133,15 +1129,15 @@ public void DeleteInstanceAsync(string namespaceName, CimInstance instance) public void GetInstanceAsync(string namespaceName, CimInstance instance) { Debug.Assert(instance != null, "Caller should verify that instance != NULL."); - DebugHelper.WriteLogEx("namespace = {0}; classname = {1}; keyonly = {2}", 0, namespaceName, instance.CimSystemProperties.ClassName, this.options.KeysOnly); + DebugHelper.WriteLogEx("namespace = {0}; classname = {1}; keyonly = {2}", 0, namespaceName, instance.CimSystemProperties.ClassName, this.OperationOptions.KeysOnly); this.CheckAvailability(); - this.targetCimInstance = instance; + this.TargetCimInstance = instance; this.operationName = CimCmdletStrings.CimOperationNameGetInstance; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"instance", instance); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncResult asyncResult = this.session.GetInstanceAsync(namespaceName, instance, this.options); + CimAsyncResult asyncResult = this.CimSession.GetInstanceAsync(namespaceName, instance, this.OperationOptions); ConsumeCimInstanceAsync(asyncResult, new CimResultContext(instance)); } @@ -1155,13 +1151,13 @@ public void ModifyInstanceAsync(string namespaceName, CimInstance instance) Debug.Assert(instance != null, "Caller should verify that instance != NULL."); DebugHelper.WriteLogEx("namespace = {0}; classname = {1}", 0, namespaceName, instance.CimSystemProperties.ClassName); this.CheckAvailability(); - this.targetCimInstance = instance; + this.TargetCimInstance = instance; this.operationName = CimCmdletStrings.CimOperationNameModifyInstance; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"instance", instance); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncResult asyncResult = this.session.ModifyInstanceAsync(namespaceName, instance, this.options); + CimAsyncResult asyncResult = this.CimSession.ModifyInstanceAsync(namespaceName, instance, this.OperationOptions); ConsumeObjectAsync(asyncResult, new CimResultContext(instance)); } @@ -1186,7 +1182,7 @@ public void EnumerateAssociatedInstancesAsync( Debug.Assert(sourceInstance != null, "Caller should verify that sourceInstance != NULL."); DebugHelper.WriteLogEx("Instance class {0}, association class {1}", 0, sourceInstance.CimSystemProperties.ClassName, associationClassName); this.CheckAvailability(); - this.targetCimInstance = sourceInstance; + this.TargetCimInstance = sourceInstance; this.operationName = CimCmdletStrings.CimOperationNameEnumerateAssociatedInstances; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); @@ -1196,7 +1192,7 @@ public void EnumerateAssociatedInstancesAsync( this.operationParameters.Add(@"sourceRole", sourceRole); this.operationParameters.Add(@"resultRole", resultRole); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.EnumerateAssociatedInstancesAsync(namespaceName, sourceInstance, associationClassName, resultClassName, sourceRole, resultRole, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.EnumerateAssociatedInstancesAsync(namespaceName, sourceInstance, associationClassName, resultClassName, sourceRole, resultRole, this.OperationOptions); ConsumeCimInstanceAsync(asyncResult, new CimResultContext(sourceInstance)); } @@ -1207,15 +1203,15 @@ public void EnumerateAssociatedInstancesAsync( /// public void EnumerateInstancesAsync(string namespaceName, string className) { - DebugHelper.WriteLogEx("KeyOnly {0}", 0, this.options.KeysOnly); + DebugHelper.WriteLogEx("KeyOnly {0}", 0, this.OperationOptions.KeysOnly); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameEnumerateInstances; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"className", className); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.EnumerateInstancesAsync(namespaceName, className, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.EnumerateInstancesAsync(namespaceName, className, this.OperationOptions); string errorSource = string.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); ConsumeCimInstanceAsync(asyncResult, new CimResultContext(errorSource)); } @@ -1252,16 +1248,16 @@ public void QueryInstancesAsync( string queryDialect, string queryExpression) { - DebugHelper.WriteLogEx("KeyOnly = {0}", 0, this.options.KeysOnly); + DebugHelper.WriteLogEx("KeyOnly = {0}", 0, this.OperationOptions.KeysOnly); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameQueryInstances; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"queryDialect", queryDialect); this.operationParameters.Add(@"queryExpression", queryExpression); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.QueryInstancesAsync(namespaceName, queryDialect, queryExpression, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.QueryInstancesAsync(namespaceName, queryDialect, queryExpression, this.OperationOptions); ConsumeCimInstanceAsync(asyncResult, null); } @@ -1274,12 +1270,12 @@ public void EnumerateClassesAsync(string namespaceName) { DebugHelper.WriteLogEx("namespace {0}", 0, namespaceName); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameEnumerateClasses; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.EnumerateClassesAsync(namespaceName, null, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.EnumerateClassesAsync(namespaceName, null, this.OperationOptions); ConsumeCimClassAsync(asyncResult, null); } @@ -1291,13 +1287,13 @@ public void EnumerateClassesAsync(string namespaceName) public void EnumerateClassesAsync(string namespaceName, string className) { this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameEnumerateClasses; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"className", className); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.EnumerateClassesAsync(namespaceName, className, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.EnumerateClassesAsync(namespaceName, className, this.OperationOptions); string errorSource = string.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); ConsumeCimClassAsync(asyncResult, new CimResultContext(errorSource)); } @@ -1311,13 +1307,13 @@ public void GetClassAsync(string namespaceName, string className) { DebugHelper.WriteLogEx("namespace = {0}, className = {1}", 0, namespaceName, className); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameGetClass; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"className", className); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncResult asyncResult = this.session.GetClassAsync(namespaceName, className, this.options); + CimAsyncResult asyncResult = this.CimSession.GetClassAsync(namespaceName, className, this.OperationOptions); string errorSource = string.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); ConsumeCimClassAsync(asyncResult, new CimResultContext(errorSource)); } @@ -1336,16 +1332,16 @@ public void InvokeMethodAsync( CimMethodParametersCollection methodParameters) { Debug.Assert(instance != null, "Caller should verify that instance != NULL."); - DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.OperationOptions.EnableMethodResultStreaming); this.CheckAvailability(); - this.targetCimInstance = instance; + this.TargetCimInstance = instance; this.operationName = CimCmdletStrings.CimOperationNameInvokeMethod; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"instance", instance); this.operationParameters.Add(@"methodName", methodName); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.InvokeMethodAsync(namespaceName, instance, methodName, methodParameters, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.InvokeMethodAsync(namespaceName, instance, methodName, methodParameters, this.OperationOptions); ConsumeCimInvokeMethodResultAsync(asyncResult, instance.CimSystemProperties.ClassName, methodName, new CimResultContext(instance)); } @@ -1362,16 +1358,16 @@ public void InvokeMethodAsync( string methodName, CimMethodParametersCollection methodParameters) { - DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.OperationOptions.EnableMethodResultStreaming); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameInvokeMethod; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); this.operationParameters.Add(@"className", className); this.operationParameters.Add(@"methodName", methodName); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - CimAsyncMultipleResults asyncResult = this.session.InvokeMethodAsync(namespaceName, className, methodName, methodParameters, this.options); + CimAsyncMultipleResults asyncResult = this.CimSession.InvokeMethodAsync(namespaceName, className, methodName, methodParameters, this.OperationOptions); string errorSource = string.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); ConsumeCimInvokeMethodResultAsync(asyncResult, className, methodName, new CimResultContext(errorSource)); } @@ -1391,7 +1387,7 @@ public void SubscribeAsync( { DebugHelper.WriteLogEx("QueryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); this.CheckAvailability(); - this.targetCimInstance = null; + this.TargetCimInstance = null; this.operationName = CimCmdletStrings.CimOperationNameSubscribeIndication; this.operationParameters.Clear(); this.operationParameters.Add(@"namespaceName", namespaceName); @@ -1399,8 +1395,8 @@ public void SubscribeAsync( this.operationParameters.Add(@"queryExpression", queryExpression); this.WriteOperationStartMessage(this.operationName, this.operationParameters); - this.options.Flags |= CimOperationFlags.ReportOperationStarted; - CimAsyncMultipleResults asyncResult = this.session.SubscribeAsync(namespaceName, queryDialect, queryExpression, this.options); + this.OperationOptions.Flags |= CimOperationFlags.ReportOperationStarted; + CimAsyncMultipleResults asyncResult = this.CimSession.SubscribeAsync(namespaceName, queryDialect, queryExpression, this.OperationOptions); ConsumeCimSubscriptionResultAsync(asyncResult, null); } @@ -1413,8 +1409,8 @@ public void TestConnectionAsync() { DebugHelper.WriteLogEx("Start test connection", 0); this.CheckAvailability(); - this.targetCimInstance = null; - CimAsyncResult asyncResult = this.session.TestConnectionAsync(); + this.TargetCimInstance = null; + CimAsyncResult asyncResult = this.CimSession.TestConnectionAsync(); // ignore the test connection result objects ConsumeCimInstanceAsync(asyncResult, true, null); } @@ -1479,42 +1475,15 @@ protected virtual void PostOperationDeleteEvent(OperationEventArgs args) /// The session will be closed while disposing this proxy object /// if it is created by constuctor. /// - internal CimSession CimSession - { - get - { - return this.session; - } - } - - private CimSession session; + internal CimSession CimSession { get; private set; } /// /// The current CimInstance object, against which issued /// current operation, it could be null. /// - internal CimInstance TargetCimInstance - { - get - { - return this.targetCimInstance; - } - } - - private CimInstance targetCimInstance = null; - - /// - /// Flag controls whether session object should be closed or not. - /// - private bool isTemporaryCimSession; + internal CimInstance TargetCimInstance { get; private set; } - internal bool IsTemporaryCimSession - { - get - { - return isTemporaryCimSession; - } - } + internal bool IsTemporaryCimSession { get; private set; } /// /// The CimOperationOptions object, which specifies the options @@ -1524,15 +1493,7 @@ internal bool IsTemporaryCimSession /// The setting MUST be set before start new operation on the /// this proxy object. /// - internal CimOperationOptions OperationOptions - { - get - { - return this.options; - } - } - - private CimOperationOptions options; + internal CimOperationOptions OperationOptions { get; private set; } /// /// All operations completed. @@ -1546,7 +1507,7 @@ private bool Completed /// Lock object used to lock /// operation & cancelOperation members. /// - private readonly object stateLock = new object(); + private readonly object stateLock = new(); /// /// The operation issued by cimSession. @@ -1561,7 +1522,7 @@ private bool Completed /// /// The current operation parameters. /// - private Hashtable operationParameters = new Hashtable(); + private readonly Hashtable operationParameters = new(); /// /// Handler used to cancel operation. @@ -1595,50 +1556,29 @@ private void DisposeCancelOperation() /// private IDisposable CancelOperation { + get + { + return this._cancelOperation; + } + set { DebugHelper.WriteLogEx(); this._cancelOperation = value; Interlocked.Exchange(ref this._cancelOperationDisposed, 0); } - - get - { - return this._cancelOperation; - } } /// /// Current protocol name /// DCOM or WSMAN. /// - internal ProtocolType Protocol - { - get - { - return protocol; - } - } - - private ProtocolType protocol; + internal ProtocolType Protocol { get; private set; } /// /// Cross operation context object. /// - internal XOperationContextBase ContextObject - { - set - { - this.contextObject = value; - } - - get - { - return this.contextObject; - } - } - - private XOperationContextBase contextObject; + internal XOperationContextBase ContextObject { get; set; } /// /// Invocation context object. @@ -1649,27 +1589,14 @@ internal XOperationContextBase ContextObject /// A preprocess object to pre-processing the result object, /// for example, adding PSTypeName, etc. /// - internal IObjectPreProcess ObjectPreProcess - { - set - { - this.objectPreprocess = value; - } - - get - { - return this.objectPreprocess; - } - } - - private IObjectPreProcess objectPreprocess; + internal IObjectPreProcess ObjectPreProcess { get; set; } /// - /// is true if this was + /// is if this was /// created to handle the "default" session, in cases where cmdlets are invoked without /// ComputerName and/or CimSession parameters. /// - private bool isDefaultSession; + private readonly bool isDefaultSession; #endregion @@ -1712,10 +1639,10 @@ protected virtual void Dispose(bool disposing) // Dispose managed resources. this.DisposeCancelOperation(); - if (this.options != null) + if (this.OperationOptions != null) { - this.options.Dispose(); - this.options = null; + this.OperationOptions.Dispose(); + this.OperationOptions = null; } DisposeTemporaryCimSession(); @@ -1738,12 +1665,12 @@ public bool IsDisposed /// private void DisposeTemporaryCimSession() { - if (this.isTemporaryCimSession && this.session != null) + if (this.IsTemporaryCimSession && this.CimSession != null) { // remove the cimsession from temporary cache - RemoveCimSessionFromTemporaryCache(this.session); - this.isTemporaryCimSession = false; - this.session = null; + RemoveCimSessionFromTemporaryCache(this.CimSession); + this.IsTemporaryCimSession = false; + this.CimSession = null; } } #endregion @@ -1779,11 +1706,11 @@ protected void ConsumeCimInstanceAsync( CimResultObserver observer; if (ignoreResultObjects) { - observer = new IgnoreResultObserver(this.session, asyncResult); + observer = new IgnoreResultObserver(this.CimSession, asyncResult); } else { - observer = new CimResultObserver(this.session, asyncResult, cimResultContext); + observer = new CimResultObserver(this.CimSession, asyncResult, cimResultContext); } observer.OnNewResult += this.ResultEventHandler; @@ -1803,8 +1730,8 @@ protected void ConsumeCimInstanceAsync( protected void ConsumeObjectAsync(IObservable asyncResult, CimResultContext cimResultContext) { - CimResultObserver observer = new CimResultObserver( - this.session, asyncResult, cimResultContext); + CimResultObserver observer = new( + this.CimSession, asyncResult, cimResultContext); observer.OnNewResult += this.ResultEventHandler; this.operationID = Interlocked.Increment(ref gOperationCounter); @@ -1824,8 +1751,8 @@ protected void ConsumeObjectAsync(IObservable asyncResult, protected void ConsumeCimClassAsync(IObservable asyncResult, CimResultContext cimResultContext) { - CimResultObserver observer = new CimResultObserver( - this.session, asyncResult, cimResultContext); + CimResultObserver observer = new( + this.CimSession, asyncResult, cimResultContext); observer.OnNewResult += this.ResultEventHandler; this.operationID = Interlocked.Increment(ref gOperationCounter); @@ -1845,8 +1772,8 @@ protected void ConsumeCimSubscriptionResultAsync( IObservable asyncResult, CimResultContext cimResultContext) { - CimSubscriptionResultObserver observer = new CimSubscriptionResultObserver( - this.session, asyncResult, cimResultContext); + CimSubscriptionResultObserver observer = new( + this.CimSession, asyncResult, cimResultContext); observer.OnNewResult += this.ResultEventHandler; this.operationID = Interlocked.Increment(ref gOperationCounter); this.AddOperation(asyncResult); @@ -1869,7 +1796,7 @@ protected void ConsumeCimInvokeMethodResultAsync( string methodName, CimResultContext cimResultContext) { - CimMethodResultObserver observer = new CimMethodResultObserver(this.session, asyncResult, cimResultContext) + CimMethodResultObserver observer = new(this.CimSession, asyncResult, cimResultContext) { ClassName = className, MethodName = methodName @@ -1900,7 +1827,7 @@ private void CheckAvailability() } } - DebugHelper.WriteLog("KeyOnly {0},", 1, this.options.KeysOnly); + DebugHelper.WriteLog("KeyOnly {0},", 1, this.OperationOptions.KeysOnly); } /// @@ -1910,9 +1837,9 @@ private void CheckAvailability() /// private void AssertSession() { - if (this.IsDisposed || (this.session == null)) + if (this.IsDisposed || (this.CimSession == null)) { - DebugHelper.WriteLogEx("Invalid CimSessionProxy object, disposed? {0}; session object {1}", 1, this.IsDisposed, this.session); + DebugHelper.WriteLogEx("Invalid CimSessionProxy object, disposed? {0}; session object {1}", 1, this.IsDisposed, this.CimSession); throw new ObjectDisposedException(this.ToString()); } } @@ -1931,7 +1858,7 @@ private CimSession CreateCimSessionByComputerName(string computerName) if (option is DComSessionOptions) { DebugHelper.WriteLog("Create dcom cimSession"); - this.protocol = ProtocolType.Dcom; + this.Protocol = ProtocolType.Dcom; return CimSession.Create(ConstValue.NullComputerName, option); } else @@ -1952,7 +1879,7 @@ private CimSession CreateCimSessionByComputerName(string computerName) /// /// internal static CimSessionOptions CreateCimSessionOption(string computerName, - UInt32 timeout, CimCredential credential) + uint timeout, CimCredential credential) { DebugHelper.WriteLogEx(); @@ -1997,10 +1924,13 @@ internal class CimSessionProxyTestConnection : CimSessionProxy #region constructors /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and session options. /// Then create wrapper object. - /// + /// /// /// public CimSessionProxyTestConnection(string computerName, CimSessionOptions sessionOptions) @@ -2023,7 +1953,7 @@ protected override void PreOperationDeleteEvent(OperationEventArgs args) if (args.success) { // test connection success, write session object to pipeline - CimWriteResultObject result = new CimWriteResultObject(this.CimSession, this.ContextObject); + CimWriteResultObject result = new(this.CimSession, this.ContextObject); this.FireNewActionEvent(result); } } @@ -2046,9 +1976,12 @@ internal class CimSessionProxyGetCimClass : CimSessionProxy #region constructors /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name. /// Then create wrapper object. - /// + /// /// public CimSessionProxyGetCimClass(string computerName) : base(computerName) @@ -2056,10 +1989,13 @@ public CimSessionProxyGetCimClass(string computerName) } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and session options. /// Then create wrapper object. - /// + /// /// /// public CimSessionProxyGetCimClass(CimSession session) @@ -2085,8 +2021,7 @@ protected override bool PreNewActionEvent(CmdletActionEventArgs args) } CimWriteResultObject writeResultObject = args.Action as CimWriteResultObject; - CimClass cimClass = writeResultObject.Result as CimClass; - if (cimClass == null) + if (!(writeResultObject.Result is CimClass cimClass)) { return true; } @@ -2198,27 +2133,33 @@ internal class CimSessionProxyNewCimInstance : CimSessionProxy #region constructors /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name. /// Then create wrapper object. - /// + /// /// public CimSessionProxyNewCimInstance(string computerName, CimNewCimInstance operation) : base(computerName) { - this.newCimInstance = operation; + this.NewCimInstanceOperation = operation; } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and session options. /// Then create wrapper object. - /// + /// /// /// public CimSessionProxyNewCimInstance(CimSession session, CimNewCimInstance operation) : base(session) { - this.newCimInstance = operation; + this.NewCimInstanceOperation = operation; } #endregion @@ -2239,8 +2180,7 @@ protected override bool PreNewActionEvent(CmdletActionEventArgs args) } CimWriteResultObject writeResultObject = args.Action as CimWriteResultObject; - CimInstance cimInstance = writeResultObject.Result as CimInstance; - if (cimInstance == null) + if (!(writeResultObject.Result is CimInstance cimInstance)) { return true; } @@ -2253,15 +2193,7 @@ protected override bool PreNewActionEvent(CmdletActionEventArgs args) #region private members - private CimNewCimInstance newCimInstance = null; - - internal CimNewCimInstance NewCimInstanceOperation - { - get - { - return this.newCimInstance; - } - } + internal CimNewCimInstance NewCimInstanceOperation { get; } #endregion } @@ -2279,9 +2211,12 @@ internal class CimSessionProxySetCimInstance : CimSessionProxy { #region constructors /// + /// Initializes a new instance of the class. + /// + /// /// Create by given object. /// Then create wrapper object. - /// + /// /// object to clone. /// PassThru, true means output the modified instance; otherwise does not output. public CimSessionProxySetCimInstance(CimSessionProxy originalProxy, bool passThru) @@ -2291,9 +2226,12 @@ public CimSessionProxySetCimInstance(CimSessionProxy originalProxy, bool passThr } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name. /// Then create wrapper object. - /// + /// /// /// /// @@ -2306,10 +2244,13 @@ public CimSessionProxySetCimInstance(string computerName, } /// + /// Initializes a new instance of the class. + /// + /// /// Create by given computer name /// and session options. /// Then create wrapper object. - /// + /// /// /// public CimSessionProxySetCimInstance(CimSession session, bool passThru) @@ -2343,7 +2284,7 @@ protected override bool PreNewActionEvent(CmdletActionEventArgs args) /// /// Ture indicates need to output the modified result. /// - private bool passThru = false; + private readonly bool passThru = false; #endregion } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs index fbe0830318d..91cf332bde9 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs @@ -3,11 +3,10 @@ #region Using directives -using System.Collections; using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; -using System.Management.Automation; #endregion @@ -20,9 +19,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal class CimSetCimInstanceContext : XOperationContextBase { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// /// /// @@ -34,50 +31,26 @@ internal CimSetCimInstanceContext(string theNamespace, bool passThru) { this.proxy = theProxy; - this.property = theProperty; + this.Property = theProperty; this.nameSpace = theNamespace; - this.parameterSetName = theParameterSetName; - this.passThru = passThru; + this.ParameterSetName = theParameterSetName; + this.PassThru = passThru; } /// /// property value /// - internal IDictionary Property - { - get - { - return this.property; - } - } - - private IDictionary property; + internal IDictionary Property { get; } /// /// parameter set name /// - internal string ParameterSetName - { - get - { - return this.parameterSetName; - } - } - - private string parameterSetName; + internal string ParameterSetName { get; } /// /// PassThru value /// - internal bool PassThru - { - get - { - return this.passThru; - } - } - - private bool passThru; + internal bool PassThru { get; } } /// @@ -88,9 +61,7 @@ internal bool PassThru internal sealed class CimSetCimInstance : CimGetInstance { /// - /// - /// Constructor - /// + /// Initializes a new instance of the class. /// public CimSetCimInstance() : base() @@ -107,7 +78,7 @@ public void SetCimInstance(SetCimInstanceCommand cmdlet) { IEnumerable computerNames = ConstValue.GetComputerNames( GetComputerName(cmdlet)); - List proxys = new List(); + List proxys = new(); switch (cmdlet.ParameterSetName) { case CimBaseCommand.CimInstanceComputerSet: diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs index fbd780450ab..d3ae3419fa4 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs @@ -166,7 +166,7 @@ internal static ErrorRecord InitializeErrorRecordCore( } } - ErrorRecord coreErrorRecord = new ErrorRecord( + ErrorRecord coreErrorRecord = new( exception: exception, errorId: errorId, errorCategory: errorCategory, @@ -177,7 +177,7 @@ internal static ErrorRecord InitializeErrorRecordCore( return coreErrorRecord; } - System.Management.Automation.Remoting.OriginInfo originInfo = new System.Management.Automation.Remoting.OriginInfo( + System.Management.Automation.Remoting.OriginInfo originInfo = new( context.ComputerName, Guid.Empty); @@ -317,24 +317,26 @@ internal static ErrorCategory ConvertCimErrorToErrorCategory(CimInstance cimErro internal sealed class CimWriteError : CimSyncAction { /// - /// Constructor with an error. + /// Initializes a new instance of the class + /// with the specified . /// /// public CimWriteError(CimInstance error, InvocationContext context) { - this.error = error; - this.invocationContext = context; + this.Error = error; + this.CimInvocationContext = context; } /// - /// Construct with an exception object. + /// Initializes a new instance of the class + /// with the specified . /// /// public CimWriteError(Exception exception, InvocationContext context, CimResultContext cimResultContext) { - this.exception = exception; - this.invocationContext = context; - this.cimResultContext = cimResultContext; + this.Exception = exception; + this.CimInvocationContext = context; + this.ResultContext = cimResultContext; } /// @@ -348,10 +350,10 @@ public override void Execute(CmdletOperationBase cmdlet) Debug.Assert(cmdlet != null, "Caller should verify that cmdlet != null"); try { - Exception errorException = (error != null) ? new CimException(error) : this.Exception; + Exception errorException = (Error != null) ? new CimException(Error) : this.Exception; // PS engine takes care of handling error action - cmdlet.WriteError(ErrorToErrorRecord.ErrorRecordFromAnyException(this.invocationContext, errorException, this.cimResultContext)); + cmdlet.WriteError(ErrorToErrorRecord.ErrorRecordFromAnyException(this.CimInvocationContext, errorException, this.ResultContext)); // if user wants to continue, we will get here this.responseType = CimResponseType.Yes; @@ -375,59 +377,19 @@ public override void Execute(CmdletOperationBase cmdlet) /// Error instance /// /// - private CimInstance error; - internal CimInstance Error - { - get - { - return error; - } - } + internal CimInstance Error { get; } /// /// /// Exception object /// /// - internal Exception Exception - { - get - { - return exception; - } - } - - private Exception exception; + internal Exception Exception { get; } - /// - /// - /// object that contains - /// the information while issuing the current operation - /// - /// - private InvocationContext invocationContext; + internal InvocationContext CimInvocationContext { get; } - internal InvocationContext CimInvocationContext - { - get - { - return invocationContext; - } - } - - /// - /// - /// - private CimResultContext cimResultContext; - - internal CimResultContext ResultContext - { - get - { - return cimResultContext; - } - } + internal CimResultContext ResultContext { get; } #endregion } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs index b351813c4d4..f4b244b97f9 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs @@ -22,36 +22,24 @@ internal sealed class CimWriteMessage : CimBaseAction /// /// Channel id. /// - private UInt32 channel; - - /// - /// Message to write to the channel. - /// - private string message; #endregion #region Properties - internal UInt32 Channel - { - get { return channel; } - } + internal uint Channel { get; } - internal string Message - { - get { return message; } - } + internal string Message { get; } #endregion /// - /// Constructor method. + /// Initializes a new instance of the class. /// - public CimWriteMessage(UInt32 channel, + public CimWriteMessage(uint channel, string message) { - this.channel = channel; - this.message = message; + this.Channel = channel; + this.Message = message; } /// @@ -64,16 +52,16 @@ public override void Execute(CmdletOperationBase cmdlet) { ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); - switch ((CimWriteMessageChannel)channel) + switch ((CimWriteMessageChannel)Channel) { case CimWriteMessageChannel.Verbose: - cmdlet.WriteVerbose(message); + cmdlet.WriteVerbose(Message); break; case CimWriteMessageChannel.Warning: - cmdlet.WriteWarning(message); + cmdlet.WriteWarning(Message); break; case CimWriteMessageChannel.Debug: - cmdlet.WriteDebug(message); + cmdlet.WriteDebug(Message); break; default: break; diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs index bd02c5dde42..b99407ccc81 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs @@ -18,7 +18,7 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal sealed class CimWriteProgress : CimBaseAction { /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// Activity identifier of the given activity @@ -40,23 +40,23 @@ public CimWriteProgress( int theActivityID, string theCurrentOperation, string theStatusDescription, - UInt32 thePercentageCompleted, - UInt32 theSecondsRemaining) + uint thePercentageCompleted, + uint theSecondsRemaining) { - this.activity = theActivity; - this.activityID = theActivityID; - this.currentOperation = theCurrentOperation; + this.Activity = theActivity; + this.ActivityID = theActivityID; + this.CurrentOperation = theCurrentOperation; if (string.IsNullOrEmpty(theStatusDescription)) { - this.statusDescription = CimCmdletStrings.DefaultStatusDescription; + this.StatusDescription = CimCmdletStrings.DefaultStatusDescription; } else { - this.statusDescription = theStatusDescription; + this.StatusDescription = theStatusDescription; } - this.percentageCompleted = thePercentageCompleted; - this.secondsRemaining = theSecondsRemaining; + this.PercentageCompleted = thePercentageCompleted; + this.SecondsRemaining = theSecondsRemaining; } /// @@ -70,84 +70,54 @@ public override void Execute(CmdletOperationBase cmdlet) DebugHelper.WriteLog( "...Activity {0}: id={1}, remain seconds ={2}, percentage completed = {3}", 4, - this.activity, - this.activityID, - this.secondsRemaining, - this.percentageCompleted); + this.Activity, + this.ActivityID, + this.SecondsRemaining, + this.PercentageCompleted); ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); - ProgressRecord record = new ProgressRecord( - this.activityID, - this.activity, - this.statusDescription); - record.Activity = this.activity; + ProgressRecord record = new( + this.ActivityID, + this.Activity, + this.StatusDescription); + record.Activity = this.Activity; record.ParentActivityId = 0; - record.SecondsRemaining = (int)this.secondsRemaining; - record.PercentComplete = (int)this.percentageCompleted; + record.SecondsRemaining = (int)this.SecondsRemaining; + record.PercentComplete = (int)this.PercentageCompleted; cmdlet.WriteProgress(record); } #region members /// - /// Activity of the given activity. + /// Gets the activity of the given activity. /// - private string activity; + internal string Activity { get; } /// - /// Activity identifier of the given activity. + /// Gets the activity identifier of the given activity. /// - private int activityID; + internal int ActivityID { get; } /// - /// Current operation text of the given activity. + /// Gets the current operation text of the given activity. /// - private string currentOperation; + internal string CurrentOperation { get; } /// - /// Status description of the given activity. + /// Gets the status description of the given activity. /// - private string statusDescription; + internal string StatusDescription { get; } /// - /// Percentage completed of the given activity. + /// Gets the percentage completed of the given activity. /// - private UInt32 percentageCompleted; + internal uint PercentageCompleted { get; } /// - /// How many seconds remained for the given activity. + /// Gets the number of seconds remaining for the given activity. /// - private UInt32 secondsRemaining; - - internal string Activity - { - get { return activity; } - } - - internal int ActivityID - { - get { return activityID; } - } - - internal string CurrentOperation - { - get { return currentOperation; } - } - - internal string StatusDescription - { - get { return statusDescription; } - } - - internal UInt32 PercentageCompleted - { - get { return percentageCompleted; } - } - - internal UInt32 SecondsRemaining - { - get { return secondsRemaining; } - } + internal uint SecondsRemaining { get; } #endregion } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs index 91f3d574a12..a4dcdfaa5c4 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs @@ -15,11 +15,11 @@ namespace Microsoft.Management.Infrastructure.CimCmdlets internal sealed class CimWriteResultObject : CimBaseAction { /// - /// Constructor. + /// Initializes a new instance of the class. /// public CimWriteResultObject(object result, XOperationContextBase theContext) { - this.result = result; + this.Result = result; this.Context = theContext; } @@ -32,22 +32,14 @@ public CimWriteResultObject(object result, XOperationContextBase theContext) public override void Execute(CmdletOperationBase cmdlet) { ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); - cmdlet.WriteObject(result, this.Context); + cmdlet.WriteObject(Result, this.Context); } #region members /// /// Result object. /// - internal object Result - { - get - { - return result; - } - } - - private object result; + internal object Result { get; } #endregion } } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs index bee7905cc52..03db6967aef 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. #region Using directives -using System.Management.Automation; using System; -using System.Globalization; +using System.Management.Automation; #endregion @@ -66,6 +65,7 @@ public virtual bool ShouldProcess(string verboseDescription, string verboseWarni return cmdlet.ShouldProcess(verboseDescription, verboseWarning, caption, out shouldProcessReason); } + [System.Diagnostics.CodeAnalysis.DoesNotReturn] public virtual void ThrowTerminatingError(ErrorRecord errorRecord) { cmdlet.ThrowTerminatingError(errorRecord); @@ -116,15 +116,16 @@ public virtual void WriteWarning(string text) /// Throw terminating error /// /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] internal void ThrowTerminatingError(Exception exception, string operation) { - ErrorRecord errorRecord = new ErrorRecord(exception, operation, ErrorCategory.InvalidOperation, this); + ErrorRecord errorRecord = new(exception, operation, ErrorCategory.InvalidOperation, this); cmdlet.ThrowTerminatingError(errorRecord); } #endregion /// - /// Constructor method. + /// Initializes a new instance of the class. /// public CmdletOperationBase(Cmdlet cmdlet) { @@ -144,7 +145,7 @@ public CmdletOperationBase(Cmdlet cmdlet) internal class CmdletOperationRemoveCimInstance : CmdletOperationBase { /// - /// Constructor method. + /// Initializes a new instance of the class. /// /// public CmdletOperationRemoveCimInstance(Cmdlet cmdlet, @@ -188,7 +189,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection #region private methods - private CimRemoveCimInstance removeCimInstance; + private readonly CimRemoveCimInstance removeCimInstance; private const string cimRemoveCimInstanceParameterName = @"cimRemoveCimInstance"; @@ -208,7 +209,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection internal class CmdletOperationSetCimInstance : CmdletOperationBase { /// - /// Constructor method. + /// Initializes a new instance of the class. /// /// public CmdletOperationSetCimInstance(Cmdlet cmdlet, @@ -268,7 +269,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection #region private methods - private CimSetCimInstance setCimInstance; + private readonly CimSetCimInstance setCimInstance; private const string theCimSetCimInstanceParameterName = @"theCimSetCimInstance"; @@ -286,7 +287,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection internal class CmdletOperationInvokeCimMethod : CmdletOperationBase { /// - /// Constructor method. + /// Initializes a new instance of the class. /// /// public CmdletOperationInvokeCimMethod(Cmdlet cmdlet, @@ -331,7 +332,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection #region private methods - private CimInvokeCimMethod cimInvokeCimMethod; + private readonly CimInvokeCimMethod cimInvokeCimMethod; private const string theCimInvokeCimMethodParameterName = @"theCimInvokeCimMethod"; @@ -351,7 +352,7 @@ public override void WriteObject(object sendToPipeline, bool enumerateCollection internal class CmdletOperationTestCimSession : CmdletOperationBase { /// - /// Constructor method. + /// Initializes a new instance of the class. /// /// public CmdletOperationTestCimSession(Cmdlet cmdlet, @@ -392,7 +393,7 @@ public override void WriteObject(object sendToPipeline, XOperationContextBase co #region private methods - private CimNewSession cimNewSession; + private readonly CimNewSession cimNewSession; private const string theCimNewSessionParameterName = @"theCimNewSession"; diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs index 36987d35bd9..90acd1c6c0e 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs @@ -4,9 +4,9 @@ #region Using directives using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Management.Automation; -using System.Collections.Generic; #endregion @@ -33,7 +33,7 @@ public class GetCimAssociatedInstanceCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public GetCimAssociatedInstanceCommand() : base(parameters, parameterSets) @@ -53,14 +53,7 @@ public GetCimAssociatedInstanceCommand() [Parameter( Position = 1, ValueFromPipelineByPropertyName = true)] - public string Association - { - get { return association; } - - set { association = value; } - } - - private string association; + public string Association { get; set; } /// /// The following is the definition of the input parameter "ResultClassName". @@ -68,14 +61,7 @@ public string Association /// the given instance. /// [Parameter] - public string ResultClassName - { - get { return resultClassName; } - - set { resultClassName = value; } - } - - private string resultClassName; + public string ResultClassName { get; set; } /// /// @@ -90,11 +76,14 @@ public string ResultClassName [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return cimInstance; } + get + { + return CimInstance; + } set { - cimInstance = value; + CimInstance = value; base.SetParameter(value, nameCimInstance); } } @@ -102,12 +91,7 @@ public CimInstance InputObject /// /// Property for internal usage purpose. /// - internal CimInstance CimInstance - { - get { return cimInstance; } - } - - private CimInstance cimInstance; + internal CimInstance CimInstance { get; private set; } /// /// The following is the definition of the input parameter "Namespace". @@ -115,14 +99,7 @@ internal CimInstance CimInstance /// is registered. /// [Parameter(ValueFromPipelineByPropertyName = true)] - public string Namespace - { - get { return nameSpace; } - - set { nameSpace = value; } - } - - private string nameSpace; + public string Namespace { get; set; } /// /// The following is the definition of the input parameter "OperationTimeoutSec". @@ -133,14 +110,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter(ValueFromPipelineByPropertyName = true)] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// @@ -151,7 +121,10 @@ public UInt32 OperationTimeoutSec [Parameter] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -179,7 +152,10 @@ public Uri ResourceUri [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -201,7 +177,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public Microsoft.Management.Infrastructure.CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -220,14 +199,7 @@ public Microsoft.Management.Infrastructure.CimSession[] CimSession /// /// [Parameter] - public SwitchParameter KeyOnly - { - get { return keyOnly; } - - set { keyOnly = value; } - } - - private SwitchParameter keyOnly; + public SwitchParameter KeyOnly { get; set; } #endregion @@ -315,7 +287,7 @@ private CimGetAssociatedInstance CreateOperationAgent() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameComputerName, new HashSet { @@ -344,7 +316,7 @@ private CimGetAssociatedInstance CreateOperationAgent() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.SessionSetName, new ParameterSetEntry(2, false) }, { CimBaseCommand.ComputerSetName, new ParameterSetEntry(1, true) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs index a439e263f0d..adc669ab645 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs @@ -31,7 +31,7 @@ public class GetCimClassCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public GetCimClassCommand() : base(parameters, parameterSets) @@ -54,14 +54,7 @@ public GetCimClassCommand() [Parameter( Position = 0, ValueFromPipelineByPropertyName = true)] - public string ClassName - { - get { return className; } - - set { className = value; } - } - - private string className; + public string ClassName { get; set; } /// /// @@ -77,14 +70,7 @@ public string ClassName [Parameter( Position = 1, ValueFromPipelineByPropertyName = true)] - public string Namespace - { - get { return nameSpace; } - - set { nameSpace = value; } - } - - private string nameSpace; + public string Namespace { get; set; } /// /// The following is the definition of the input parameter "OperationTimeoutSec". @@ -93,14 +79,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter(ValueFromPipelineByPropertyName = true)] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// The following is the definition of the input parameter "Session". @@ -113,7 +92,10 @@ public UInt32 OperationTimeoutSec [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -139,7 +121,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -158,14 +143,7 @@ public string[] ComputerName /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public string MethodName - { - get { return methodName; } - - set { methodName = value; } - } - - private string methodName; + public string MethodName { get; set; } /// /// @@ -175,14 +153,7 @@ public string MethodName /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public string PropertyName - { - get { return propertyName; } - - set { propertyName = value; } - } - - private string propertyName; + public string PropertyName { get; set; } /// /// @@ -192,14 +163,7 @@ public string PropertyName /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public string QualifierName - { - get { return qualifierName; } - - set { qualifierName = value; } - } - - private string qualifierName; + public string QualifierName { get; set; } #endregion @@ -250,7 +214,7 @@ protected override void EndProcessing() /// private CimGetCimClass GetOperationAgent() { - return (this.AsyncOperation as CimGetCimClass); + return this.AsyncOperation as CimGetCimClass; } /// @@ -262,7 +226,7 @@ private CimGetCimClass GetOperationAgent() /// private CimGetCimClass CreateOperationAgent() { - CimGetCimClass cimGetCimClass = new CimGetCimClass(); + CimGetCimClass cimGetCimClass = new(); this.AsyncOperation = cimGetCimClass; return cimGetCimClass; } @@ -288,7 +252,7 @@ private CimGetCimClass CreateOperationAgent() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameCimSession, new HashSet { @@ -306,7 +270,7 @@ private CimGetCimClass CreateOperationAgent() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.SessionSetName, new ParameterSetEntry(1) }, { CimBaseCommand.ComputerSetName, new ParameterSetEntry(0, true) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs index 9e38546793b..d61a9363922 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs @@ -5,9 +5,8 @@ using System; using System.Collections.Generic; -using System.Management.Automation; -using System.Collections; using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; #endregion @@ -26,6 +25,7 @@ public class GetCimInstanceCommand : CimBaseCommand #region constructor /// + /// Initializes a new instance of the class. /// Constructor. /// public GetCimInstanceCommand() @@ -63,7 +63,10 @@ public GetCimInstanceCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -90,7 +93,10 @@ public CimSession[] CimSession ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ClassName { - get { return className; } + get + { + return className; + } set { @@ -125,7 +131,10 @@ public string ClassName ParameterSetName = CimBaseCommand.QuerySessionSet)] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -161,7 +170,10 @@ public Uri ResourceUri [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -185,7 +197,10 @@ public string[] ComputerName [Parameter(ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] public SwitchParameter KeyOnly { - get { return keyOnly; } + get + { + return keyOnly; + } set { @@ -220,7 +235,10 @@ public SwitchParameter KeyOnly ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -242,14 +260,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// The following is the definition of the input parameter "InputObject". @@ -277,11 +288,14 @@ public UInt32 OperationTimeoutSec [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return cimInstance; } + get + { + return CimInstance; + } set { - cimInstance = value; + CimInstance = value; base.SetParameter(value, nameCimInstance); } } @@ -289,12 +303,7 @@ public CimInstance InputObject /// /// Property for internal usage purpose. /// - internal CimInstance CimInstance - { - get { return cimInstance; } - } - - private CimInstance cimInstance; + internal CimInstance CimInstance { get; private set; } /// /// The following is the definition of the input parameter "Query". @@ -309,7 +318,10 @@ internal CimInstance CimInstance ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -338,7 +350,10 @@ public string Query public string QueryDialect { - get { return queryDialect; } + get + { + return queryDialect; + } set { @@ -366,7 +381,10 @@ public string QueryDialect [Parameter(ParameterSetName = CimBaseCommand.QuerySessionSet)] public SwitchParameter Shallow { - get { return shallow; } + get + { + return shallow; + } set { @@ -393,7 +411,10 @@ public SwitchParameter Shallow ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] public string Filter { - get { return filter; } + get + { + return filter; + } set { @@ -422,23 +443,21 @@ public string Filter [Alias("SelectProperties")] public string[] Property { - get { return property; } + get + { + return SelectProperties; + } set { - property = value; + SelectProperties = value; base.SetParameter(value, nameSelectProperties); } } /// /// Property for internal usage. /// - internal string[] SelectProperties - { - get { return property; } - } - - private string[] property; + internal string[] SelectProperties { get; private set; } #endregion @@ -491,7 +510,7 @@ protected override void EndProcessing() /// private CimGetInstance GetOperationAgent() { - return (this.AsyncOperation as CimGetInstance); + return this.AsyncOperation as CimGetInstance; } /// @@ -504,7 +523,7 @@ private CimGetInstance GetOperationAgent() /// private CimGetInstance CreateOperationAgent() { - CimGetInstance cimGetInstance = new CimGetInstance(); + CimGetInstance cimGetInstance = new(); this.AsyncOperation = cimGetInstance; return cimGetInstance; } @@ -520,7 +539,7 @@ private void CheckArgument() case CimBaseCommand.ClassNameSessionSet: // validate the classname & property this.className = ValidationHelper.ValidateArgumentIsValidName(nameClassName, this.className); - this.property = ValidationHelper.ValidateArgumentIsValidName(nameSelectProperties, this.property); + this.SelectProperties = ValidationHelper.ValidateArgumentIsValidName(nameSelectProperties, this.SelectProperties); break; default: break; @@ -549,7 +568,7 @@ private void CheckArgument() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameCimSession, new HashSet { @@ -652,7 +671,7 @@ private void CheckArgument() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(1) }, { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(2) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs index 34d10b1d204..3289b6c86c0 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs @@ -22,7 +22,7 @@ public sealed class GetCimSessionCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public GetCimSessionCommand() : base(parameters, parameterSets) @@ -58,7 +58,10 @@ public GetCimSessionCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -78,9 +81,12 @@ public string[] ComputerName ValueFromPipelineByPropertyName = true, ParameterSetName = SessionIdSet)] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public UInt32[] Id + public uint[] Id { - get { return id; } + get + { + return id; + } set { @@ -89,7 +95,7 @@ public UInt32[] Id } } - private UInt32[] id; + private uint[] id; /// /// The following is the definition of the input parameter "InstanceID". @@ -101,7 +107,10 @@ public UInt32[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public Guid[] InstanceId { - get { return instanceid; } + get + { + return instanceid; + } set { @@ -123,7 +132,10 @@ public Guid[] InstanceId [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return name; } + get + { + return name; + } set { @@ -173,7 +185,7 @@ protected override void ProcessRecord() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameComputerName, new HashSet { @@ -200,7 +212,7 @@ protected override void ProcessRecord() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.ComputerNameSet, new ParameterSetEntry(0, true) }, { CimBaseCommand.SessionIdSet, new ParameterSetEntry(1) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs index e777987a87b..26e1d8eaf5f 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs @@ -27,7 +27,7 @@ public class InvokeCimMethodCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public InvokeCimMethodCommand() : base(parameters, parameterSets) @@ -54,7 +54,10 @@ public InvokeCimMethodCommand() [Alias("Class")] public string ClassName { - get { return className; } + get + { + return className; + } set { @@ -83,7 +86,10 @@ public string ClassName ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -108,7 +114,10 @@ public Uri ResourceUri ParameterSetName = CimClassSessionSet)] public CimClass CimClass { - get { return cimClass; } + get + { + return cimClass; + } set { @@ -131,7 +140,10 @@ public CimClass CimClass ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -155,7 +167,10 @@ public string Query ParameterSetName = CimBaseCommand.QuerySessionSet)] public string QueryDialect { - get { return queryDialect; } + get + { + return queryDialect; + } set { @@ -182,11 +197,14 @@ public string QueryDialect [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return cimInstance; } + get + { + return CimInstance; + } set { - cimInstance = value; + CimInstance = value; base.SetParameter(value, nameCimInstance); } } @@ -194,12 +212,7 @@ public CimInstance InputObject /// /// Property for internal usage purpose. /// - internal CimInstance CimInstance - { - get { return cimInstance; } - } - - private CimInstance cimInstance; + internal CimInstance CimInstance { get; private set; } /// /// The following is the definition of the input parameter "ComputerName". @@ -229,7 +242,10 @@ internal CimInstance CimInstance [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -269,7 +285,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -287,14 +306,7 @@ public CimSession[] CimSession /// [Parameter(Position = 1, ValueFromPipelineByPropertyName = true)] [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] - public IDictionary Arguments - { - get { return arguments; } - - set { arguments = value; } - } - - private IDictionary arguments; + public IDictionary Arguments { get; set; } /// /// The following is the definition of the input parameter "MethodName". @@ -306,7 +318,10 @@ public IDictionary Arguments [Alias("Name")] public string MethodName { - get { return methodName; } + get + { + return methodName; + } set { @@ -337,7 +352,10 @@ public string MethodName ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -355,14 +373,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } #endregion @@ -427,7 +438,7 @@ private CimInvokeCimMethod GetOperationAgent() /// private CimInvokeCimMethod CreateOperationAgent() { - CimInvokeCimMethod cimInvokeMethod = new CimInvokeCimMethod(); + CimInvokeCimMethod cimInvokeMethod = new(); this.AsyncOperation = cimInvokeMethod; return cimInvokeMethod; } @@ -469,7 +480,7 @@ private void CheckArgument() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameClassName, new HashSet { @@ -556,7 +567,7 @@ private void CheckArgument() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(2, true) }, { CimBaseCommand.ResourceUriSessionSet, new ParameterSetEntry(3) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs index 31b860777ea..53d7c28b924 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs @@ -29,7 +29,7 @@ public class NewCimInstanceCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public NewCimInstanceCommand() : base(parameters, parameterSets) @@ -57,7 +57,10 @@ public NewCimInstanceCommand() ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ClassName { - get { return className; } + get + { + return className; + } set { @@ -82,7 +85,10 @@ public string ClassName ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -117,7 +123,10 @@ public Uri ResourceUri [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Key { - get { return key; } + get + { + return key; + } set { @@ -144,7 +153,10 @@ public string[] Key ParameterSetName = CimClassComputerSet)] public CimClass CimClass { - get { return cimClass; } + get + { + return cimClass; + } set { @@ -169,14 +181,7 @@ public CimClass CimClass ValueFromPipelineByPropertyName = true)] [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] [Alias("Arguments")] - public IDictionary Property - { - get { return property; } - - set { property = value; } - } - - private IDictionary property; + public IDictionary Property { get; set; } /// /// The following is the definition of the input parameter "Namespace". @@ -197,7 +202,10 @@ public IDictionary Property ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -215,14 +223,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// @@ -245,7 +246,10 @@ public UInt32 OperationTimeoutSec [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -277,7 +281,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -305,7 +312,10 @@ public string[] ComputerName ParameterSetName = CimBaseCommand.CimClassSessionSet)] public SwitchParameter ClientOnly { - get { return clientOnly; } + get + { + return clientOnly; + } set { @@ -385,7 +395,7 @@ protected override void EndProcessing() /// private CimNewCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimNewCimInstance); + return this.AsyncOperation as CimNewCimInstance; } /// @@ -397,7 +407,7 @@ private CimNewCimInstance GetOperationAgent() /// private CimNewCimInstance CreateOperationAgent() { - CimNewCimInstance cimNewCimInstance = new CimNewCimInstance(); + CimNewCimInstance cimNewCimInstance = new(); this.AsyncOperation = cimNewCimInstance; return cimNewCimInstance; } @@ -437,7 +447,7 @@ private void CheckArgument() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameClassName, new HashSet { @@ -500,7 +510,7 @@ private void CheckArgument() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.ClassNameSessionSet, new ParameterSetEntry(2) }, { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(1, true) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs index eeb4cba4c4d..9957372d592 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs @@ -3,8 +3,8 @@ #region Using directives using System; -using System.Management.Automation; using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; using Microsoft.Management.Infrastructure.Options; #endregion @@ -33,7 +33,10 @@ public sealed class NewCimSessionCommand : CimBaseCommand ParameterSetName = CredentialParameterSet)] public PasswordAuthenticationMechanism Authentication { - get { return authentication; } + get + { + return authentication; + } set { @@ -52,14 +55,7 @@ public PasswordAuthenticationMechanism Authentication /// [Parameter(Position = 1, ParameterSetName = CredentialParameterSet)] [Credential()] - public PSCredential Credential - { - get { return credential; } - - set { credential = value; } - } - - private PSCredential credential; + public PSCredential Credential { get; set; } /// /// The following is the definition of the input parameter "CertificateThumbprint". @@ -67,14 +63,7 @@ public PSCredential Credential /// [Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = CertificateParameterSet)] - public string CertificateThumbprint - { - get { return certificatethumbprint; } - - set { certificatethumbprint = value; } - } - - private string certificatethumbprint; + public string CertificateThumbprint { get; set; } /// /// The following is the definition of the input parameter "ComputerName". @@ -87,14 +76,7 @@ public string CertificateThumbprint ValueFromPipelineByPropertyName = true)] [ValidateNotNullOrEmpty] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public string[] ComputerName - { - get { return computername; } - - set { computername = value; } - } - - private string[] computername; + public string[] ComputerName { get; set; } /// /// @@ -108,14 +90,7 @@ public string[] ComputerName /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public string Name - { - get { return name; } - - set { name = value; } - } - - private string name; + public string Name { get; set; } /// /// @@ -125,13 +100,16 @@ public string Name /// /// /// The unit is Second. - /// + /// /// [Alias(AliasOT)] [Parameter(ValueFromPipelineByPropertyName = true)] - public UInt32 OperationTimeoutSec + public uint OperationTimeoutSec { - get { return operationTimeout; } + get + { + return operationTimeout; + } set { @@ -140,7 +118,7 @@ public UInt32 OperationTimeoutSec } } - private UInt32 operationTimeout; + private uint operationTimeout; internal bool operationTimeoutSet = false; /// @@ -150,17 +128,7 @@ public UInt32 OperationTimeoutSec /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public SwitchParameter SkipTestConnection - { - get { return skipTestConnection; } - - set - { - skipTestConnection = value; - } - } - - private SwitchParameter skipTestConnection; + public SwitchParameter SkipTestConnection { get; set; } /// /// The following is the definition of the input parameter "Port". @@ -168,9 +136,12 @@ public SwitchParameter SkipTestConnection /// This is specificly for wsman protocol. /// [Parameter(ValueFromPipelineByPropertyName = true)] - public UInt32 Port + public uint Port { - get { return port; } + get + { + return port; + } set { @@ -179,7 +150,7 @@ public UInt32 Port } } - private UInt32 port; + private uint port; private bool portSet = false; /// @@ -191,19 +162,14 @@ public UInt32 Port /// If the argument is not given, a default SessionOption will be created for /// the session in .NET API layer. /// + /// /// If a object is passed, then /// connection is made using DCOM. If a /// object is passed, then connection is made using WsMan. + /// /// [Parameter(ValueFromPipelineByPropertyName = true)] - public Microsoft.Management.Infrastructure.Options.CimSessionOptions SessionOption - { - get { return sessionOption; } - - set { sessionOption = value; } - } - - private Microsoft.Management.Infrastructure.Options.CimSessionOptions sessionOption; + public Microsoft.Management.Infrastructure.Options.CimSessionOptions SessionOption { get; set; } #endregion @@ -256,11 +222,11 @@ internal void BuildSessionOptions(out CimSessionOptions outputOptions, out CimCr // clone the sessionOption object if (this.SessionOption is WSManSessionOptions) { - options = new WSManSessionOptions(this.sessionOption as WSManSessionOptions); + options = new WSManSessionOptions(this.SessionOption as WSManSessionOptions); } else { - options = new DComSessionOptions(this.sessionOption as DComSessionOptions); + options = new DComSessionOptions(this.SessionOption as DComSessionOptions); } } @@ -268,7 +234,7 @@ internal void BuildSessionOptions(out CimSessionOptions outputOptions, out CimCr outputCredential = null; if (options != null) { - DComSessionOptions dcomOptions = (options as DComSessionOptions); + DComSessionOptions dcomOptions = options as DComSessionOptions; if (dcomOptions != null) { bool conflict = false; @@ -304,7 +270,7 @@ internal void BuildSessionOptions(out CimSessionOptions outputOptions, out CimCr if (this.CertificateThumbprint != null) { - CimCredential credentials = new CimCredential(CertificateAuthenticationMechanism.Default, this.CertificateThumbprint); + CimCredential credentials = new(CertificateAuthenticationMechanism.Default, this.CertificateThumbprint); wsmanOptions.AddDestinationCredentials(credentials); } @@ -319,7 +285,7 @@ internal void BuildSessionOptions(out CimSessionOptions outputOptions, out CimCr } } - if (this.authenticationSet || (this.credential != null)) + if (this.authenticationSet || (this.Credential != null)) { PasswordAuthenticationMechanism authentication = this.authenticationSet ? this.Authentication : PasswordAuthenticationMechanism.Default; if (this.authenticationSet) diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs index aba99d9401c..c82a882fb25 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs @@ -24,7 +24,7 @@ public enum ProtocolType [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] Wsman - }; + } /// /// The Cmdlet allows the IT Pro to create a CimSessionOptions object that she/he @@ -45,7 +45,7 @@ public sealed class NewCimSessionOptionCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public NewCimSessionOptionCommand() : base(parameters, parameterSets) @@ -64,7 +64,10 @@ public NewCimSessionOptionCommand() [Parameter(ParameterSetName = WSManParameterSet)] public SwitchParameter NoEncryption { - get { return noEncryption; } + get + { + return noEncryption; + } set { @@ -85,7 +88,10 @@ public SwitchParameter NoEncryption ParameterSetName = WSManParameterSet)] public SwitchParameter SkipCACheck { - get { return skipCACheck; } + get + { + return skipCACheck; + } set { @@ -106,7 +112,10 @@ public SwitchParameter SkipCACheck ParameterSetName = WSManParameterSet)] public SwitchParameter SkipCNCheck { - get { return skipCNCheck; } + get + { + return skipCNCheck; + } set { @@ -127,7 +136,10 @@ public SwitchParameter SkipCNCheck ParameterSetName = WSManParameterSet)] public SwitchParameter SkipRevocationCheck { - get { return skipRevocationCheck; } + get + { + return skipRevocationCheck; + } set { @@ -148,7 +160,10 @@ public SwitchParameter SkipRevocationCheck ParameterSetName = WSManParameterSet)] public SwitchParameter EncodePortInServicePrincipalName { - get { return encodeportinserviceprincipalname; } + get + { + return encodeportinserviceprincipalname; + } set { @@ -171,7 +186,10 @@ public SwitchParameter EncodePortInServicePrincipalName ParameterSetName = WSManParameterSet)] public PacketEncoding Encoding { - get { return encoding; } + get + { + return encoding; + } set { @@ -193,7 +211,10 @@ public PacketEncoding Encoding ParameterSetName = WSManParameterSet)] public Uri HttpPrefix { - get { return httpprefix; } + get + { + return httpprefix; + } set { @@ -210,9 +231,12 @@ public Uri HttpPrefix /// [Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = WSManParameterSet)] - public UInt32 MaxEnvelopeSizeKB + public uint MaxEnvelopeSizeKB { - get { return maxenvelopesizekb; } + get + { + return maxenvelopesizekb; + } set { @@ -222,7 +246,7 @@ public UInt32 MaxEnvelopeSizeKB } } - private UInt32 maxenvelopesizekb; + private uint maxenvelopesizekb; private bool maxenvelopesizekbSet = false; /// @@ -233,7 +257,10 @@ public UInt32 MaxEnvelopeSizeKB ParameterSetName = WSManParameterSet)] public PasswordAuthenticationMechanism ProxyAuthentication { - get { return proxyAuthentication; } + get + { + return proxyAuthentication; + } set { @@ -253,7 +280,10 @@ public PasswordAuthenticationMechanism ProxyAuthentication ParameterSetName = WSManParameterSet)] public string ProxyCertificateThumbprint { - get { return proxycertificatethumbprint; } + get + { + return proxycertificatethumbprint; + } set { @@ -272,7 +302,10 @@ public string ProxyCertificateThumbprint [Credential()] public PSCredential ProxyCredential { - get { return proxycredential; } + get + { + return proxycredential; + } set { @@ -292,7 +325,10 @@ public PSCredential ProxyCredential ParameterSetName = WSManParameterSet)] public ProxyType ProxyType { - get { return proxytype; } + get + { + return proxytype; + } set { @@ -313,7 +349,10 @@ public ProxyType ProxyType ParameterSetName = WSManParameterSet)] public SwitchParameter UseSsl { - get { return usessl; } + get + { + return usessl; + } set { @@ -334,7 +373,10 @@ public SwitchParameter UseSsl [Parameter(ParameterSetName = DcomParameterSet)] public ImpersonationType Impersonation { - get { return impersonation; } + get + { + return impersonation; + } set { @@ -355,7 +397,10 @@ public ImpersonationType Impersonation [Parameter(ParameterSetName = DcomParameterSet)] public SwitchParameter PacketIntegrity { - get { return packetintegrity; } + get + { + return packetintegrity; + } set { @@ -376,7 +421,10 @@ public SwitchParameter PacketIntegrity [Parameter(ParameterSetName = DcomParameterSet)] public SwitchParameter PacketPrivacy { - get { return packetprivacy; } + get + { + return packetprivacy; + } set { @@ -400,7 +448,10 @@ public SwitchParameter PacketPrivacy ParameterSetName = ProtocolNameParameterSet)] public ProtocolType Protocol { - get { return protocol; } + get + { + return protocol; + } set { @@ -416,28 +467,14 @@ public ProtocolType Protocol /// Specifies the UI Culture to use. i.e. en-us, ar-sa. /// [Parameter(ValueFromPipelineByPropertyName = true)] - public CultureInfo UICulture - { - get { return uiculture; } - - set { uiculture = value; } - } - - private CultureInfo uiculture; + public CultureInfo UICulture { get; set; } /// /// The following is the definition of the input parameter "Culture". /// Specifies the culture to use. i.e. en-us, ar-sa. /// [Parameter(ValueFromPipelineByPropertyName = true)] - public CultureInfo Culture - { - get { return culture; } - - set { culture = value; } - } - - private CultureInfo culture; + public CultureInfo Culture { get; set; } #endregion @@ -522,7 +559,7 @@ protected override void EndProcessing() /// internal DComSessionOptions CreateDComSessionOptions() { - DComSessionOptions dcomoptions = new DComSessionOptions(); + DComSessionOptions dcomoptions = new(); if (this.impersonationSet) { dcomoptions.Impersonation = this.Impersonation; @@ -562,7 +599,7 @@ internal DComSessionOptions CreateDComSessionOptions() /// internal WSManSessionOptions CreateWSMANSessionOptions() { - WSManSessionOptions wsmanoptions = new WSManSessionOptions(); + WSManSessionOptions wsmanoptions = new(); if (this.noEncryptionSet) { wsmanoptions.NoEncryption = true; @@ -638,7 +675,7 @@ internal WSManSessionOptions CreateWSMANSessionOptions() if (!string.IsNullOrWhiteSpace(this.ProxyCertificateThumbprint)) { - CimCredential credentials = new CimCredential(CertificateAuthenticationMechanism.Default, this.ProxyCertificateThumbprint); + CimCredential credentials = new(CertificateAuthenticationMechanism.Default, this.ProxyCertificateThumbprint); wsmanoptions.AddProxyCredentials(credentials); } @@ -712,7 +749,7 @@ internal WSManSessionOptions CreateWSMANSessionOptions() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameNoEncryption, new HashSet { @@ -813,7 +850,7 @@ internal WSManSessionOptions CreateWSMANSessionOptions() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.ProtocolNameParameterSet, new ParameterSetEntry(1, true) }, { CimBaseCommand.DcomParameterSet, new ParameterSetEntry(0) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs index de7bd63feae..d22644ececd 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs @@ -35,14 +35,7 @@ public class RegisterCimIndicationCommand : ObjectEventRegistrationBase /// /// [Parameter] - public string Namespace - { - get { return nameSpace; } - - set { nameSpace = value; } - } - - private string nameSpace; + public string Namespace { get; set; } /// /// The following is the definition of the input parameter "ClassName". @@ -57,7 +50,10 @@ public string Namespace ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ClassName { - get { return className; } + get + { + return className; + } set { @@ -82,7 +78,10 @@ public string ClassName ParameterSetName = CimBaseCommand.QueryExpressionComputerSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -104,7 +103,10 @@ public string Query [Parameter(ParameterSetName = CimBaseCommand.QueryExpressionSessionSet)] public string QueryDialect { - get { return queryDialect; } + get + { + return queryDialect; + } set { @@ -122,14 +124,7 @@ public string QueryDialect /// [Alias(CimBaseCommand.AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// The following is the definition of the input parameter "Session". @@ -143,7 +138,10 @@ public UInt32 OperationTimeoutSec ParameterSetName = CimBaseCommand.ClassNameSessionSet)] public CimSession CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -164,7 +162,10 @@ public CimSession CimSession [Parameter(ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -292,7 +293,7 @@ private void CheckArgument() /// /// Parameter binder used to resolve parameter set name. /// - private ParameterBinder parameterBinder = new ParameterBinder( + private readonly ParameterBinder parameterBinder = new( parameters, parameterSets); /// @@ -320,7 +321,7 @@ private void SetParameter(object value, string parameterName) /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameClassName, new HashSet { @@ -357,7 +358,7 @@ private void SetParameter(object value, string parameterName) /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.QueryExpressionSessionSet, new ParameterSetEntry(2) }, { CimBaseCommand.QueryExpressionComputerSet, new ParameterSetEntry(1) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs index 60b152055b9..273311485ce 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs @@ -27,7 +27,7 @@ public class RemoveCimInstanceCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public RemoveCimInstanceCommand() : base(parameters, parameterSets) @@ -53,7 +53,10 @@ public RemoveCimInstanceCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -76,7 +79,10 @@ public CimSession[] CimSession ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -99,7 +105,10 @@ public Uri ResourceUri [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -124,7 +133,10 @@ public string[] ComputerName ParameterSetName = CimBaseCommand.QueryComputerSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -142,14 +154,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// The following is the definition of the input parameter "InputObject". @@ -168,11 +173,14 @@ public UInt32 OperationTimeoutSec [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return cimInstance; } + get + { + return CimInstance; + } set { - cimInstance = value; + CimInstance = value; base.SetParameter(value, nameCimInstance); } } @@ -180,12 +188,7 @@ public CimInstance InputObject /// /// Property for internal usage purpose. /// - internal CimInstance CimInstance - { - get { return cimInstance; } - } - - private CimInstance cimInstance; + internal CimInstance CimInstance { get; private set; } /// /// The following is the definition of the input parameter "Query". @@ -202,7 +205,10 @@ internal CimInstance CimInstance ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -224,7 +230,10 @@ public string Query ParameterSetName = CimBaseCommand.QueryComputerSet)] public string QueryDialect { - get { return querydialect; } + get + { + return querydialect; + } set { @@ -285,7 +294,7 @@ protected override void EndProcessing() /// private CimRemoveCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimRemoveCimInstance); + return this.AsyncOperation as CimRemoveCimInstance; } /// @@ -297,7 +306,7 @@ private CimRemoveCimInstance GetOperationAgent() /// private CimRemoveCimInstance CreateOperationAgent() { - CimRemoveCimInstance cimRemoveInstance = new CimRemoveCimInstance(); + CimRemoveCimInstance cimRemoveInstance = new(); this.AsyncOperation = cimRemoveInstance; return cimRemoveInstance; } @@ -319,7 +328,7 @@ private CimRemoveCimInstance CreateOperationAgent() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameCimSession, new HashSet { @@ -368,7 +377,7 @@ private CimRemoveCimInstance CreateOperationAgent() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(1, true) }, { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(2) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs index 2fb4126a5b0..2f1a5ad026e 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs @@ -29,7 +29,7 @@ public sealed class RemoveCimSessionCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public RemoveCimSessionCommand() : base(parameters, parameterSets) @@ -54,7 +54,10 @@ public RemoveCimSessionCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimsession; } + get + { + return cimsession; + } set { @@ -81,7 +84,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -102,9 +108,12 @@ public string[] ComputerName ValueFromPipelineByPropertyName = true, ParameterSetName = SessionIdSet)] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public UInt32[] Id + public uint[] Id { - get { return id; } + get + { + return id; + } set { @@ -113,7 +122,7 @@ public UInt32[] Id } } - private UInt32[] id; + private uint[] id; /// /// The following is the definition of the input parameter "InstanceId". @@ -127,7 +136,10 @@ public UInt32[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public Guid[] InstanceId { - get { return instanceid; } + get + { + return instanceid; + } set { @@ -150,7 +162,10 @@ public Guid[] InstanceId [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return name; } + get + { + return name; + } set { @@ -199,7 +214,7 @@ protected override void ProcessRecord() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameCimSession, new HashSet { @@ -231,7 +246,7 @@ protected override void ProcessRecord() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.CimSessionSet, new ParameterSetEntry(1, true) }, { CimBaseCommand.ComputerNameSet, new ParameterSetEntry(1) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs index 7237352b61a..de6857db5eb 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs @@ -29,7 +29,7 @@ public class SetCimInstanceCommand : CimBaseCommand #region constructor /// - /// Constructor. + /// Initializes a new instance of the class. /// public SetCimInstanceCommand() : base(parameters, parameterSets) @@ -54,7 +54,10 @@ public SetCimInstanceCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -77,7 +80,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -100,7 +106,10 @@ public string[] ComputerName ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -121,7 +130,10 @@ public Uri ResourceUri ParameterSetName = CimBaseCommand.QueryComputerSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -139,14 +151,7 @@ public string Namespace /// [Alias(AliasOT)] [Parameter] - public UInt32 OperationTimeoutSec - { - get { return operationTimeout; } - - set { operationTimeout = value; } - } - - private UInt32 operationTimeout; + public uint OperationTimeoutSec { get; set; } /// /// The following is the definition of the input parameter "InputObject". @@ -165,11 +170,14 @@ public UInt32 OperationTimeoutSec [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return cimInstance; } + get + { + return CimInstance; + } set { - cimInstance = value; + CimInstance = value; base.SetParameter(value, nameCimInstance); } } @@ -177,12 +185,7 @@ public CimInstance InputObject /// /// Property for internal usage purpose. /// - internal CimInstance CimInstance - { - get { return cimInstance; } - } - - private CimInstance cimInstance; + internal CimInstance CimInstance { get; private set; } /// /// The following is the definition of the input parameter "Query". @@ -199,7 +202,10 @@ internal CimInstance CimInstance ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -221,7 +227,10 @@ public string Query ParameterSetName = CimBaseCommand.QueryComputerSet)] public string QueryDialect { - get { return querydialect; } + get + { + return querydialect; + } set { @@ -256,7 +265,10 @@ public string QueryDialect [Alias("Arguments")] public IDictionary Property { - get { return property; } + get + { + return property; + } set { @@ -268,8 +280,10 @@ public IDictionary Property private IDictionary property; /// + /// /// The following is the definition of the input parameter "PassThru", /// indicate whether Set-CimInstance should output modified result instance or not. + /// /// /// True indicates output the result instance, otherwise output nothing as by default /// behavior. @@ -277,20 +291,7 @@ public IDictionary Property /// [Parameter] [ValidateNotNull] - public SwitchParameter PassThru - { - set - { - this.passThru = value; - } - - get - { - return this.passThru; - } - } - - private SwitchParameter passThru; + public SwitchParameter PassThru { get; set; } #endregion @@ -342,7 +343,7 @@ protected override void EndProcessing() /// private CimSetCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimSetCimInstance); + return this.AsyncOperation as CimSetCimInstance; } /// @@ -354,7 +355,7 @@ private CimSetCimInstance GetOperationAgent() /// private CimSetCimInstance CreateOperationAgent() { - CimSetCimInstance cimSetCimInstance = new CimSetCimInstance(); + CimSetCimInstance cimSetCimInstance = new(); this.AsyncOperation = cimSetCimInstance; return cimSetCimInstance; } @@ -377,7 +378,7 @@ private CimSetCimInstance CreateOperationAgent() /// /// Static parameter definition entries. /// - private static Dictionary> parameters = new Dictionary> + private static readonly Dictionary> parameters = new() { { nameCimSession, new HashSet { @@ -434,7 +435,7 @@ private CimSetCimInstance CreateOperationAgent() /// /// Static parameter set entries. /// - private static Dictionary parameterSets = new Dictionary + private static readonly Dictionary parameterSets = new() { { CimBaseCommand.QuerySessionSet, new ParameterSetEntry(3) }, { CimBaseCommand.QueryComputerSet, new ParameterSetEntry(2) }, diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs index 10fbc48a444..955d7f8613f 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs @@ -9,9 +9,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; -using System.Management.Automation; using System.Text.RegularExpressions; -using System.Threading; namespace Microsoft.Management.Infrastructure.CimCmdlets { @@ -90,7 +88,7 @@ internal static bool IsDefaultComputerName(string computerName) /// internal static IEnumerable GetComputerNames(IEnumerable computerNames) { - return (computerNames == null) ? NullComputerNames : computerNames; + return computerNames ?? NullComputerNames; } /// @@ -112,7 +110,7 @@ internal static string GetComputerName(string computerName) /// internal static string GetNamespace(string nameSpace) { - return (nameSpace == null) ? DefaultNameSpace : nameSpace; + return nameSpace ?? DefaultNameSpace; } /// @@ -124,7 +122,7 @@ internal static string GetNamespace(string nameSpace) /// internal static string GetQueryDialectWithDefault(string queryDialect) { - return (queryDialect == null) ? DefaultQueryDialect : queryDialect; + return queryDialect ?? DefaultQueryDialect; } } @@ -140,31 +138,14 @@ internal static class DebugHelper /// /// Flag used to control generating log message into file. /// - private static bool generateLog = true; - - internal static bool GenerateLog - { - get { return generateLog; } - - set { generateLog = value; } - } + internal static bool GenerateLog { get; set; } = true; /// /// Whether the log been initialized. /// private static bool logInitialized = false; - /// - /// Flag used to control generating message into powershell. - /// - private static bool generateVerboseMessage = true; - - internal static bool GenerateVerboseMessage - { - get { return generateVerboseMessage; } - - set { generateVerboseMessage = value; } - } + internal static bool GenerateVerboseMessage { get; set; } = true; /// /// Flag used to control generating message into powershell. @@ -191,7 +172,7 @@ internal static bool GenerateVerboseMessage /// /// Lock the log file. /// - internal static readonly object logLock = new object(); + internal static readonly object logLock = new(); #endregion @@ -216,7 +197,7 @@ internal static bool GenerateVerboseMessage #region runtime methods internal static string GetSourceCodeInformation(bool withFileName, int depth) { - StackTrace trace = new StackTrace(); + StackTrace trace = new(); StackFrame frame = trace.GetFrame(depth); // if (withFileName) // { @@ -339,7 +320,7 @@ private static void WriteLogInternal(string message, int indent, int depth) } } - if (generateLog) + if (GenerateLog) { if (indent < 0) { @@ -357,7 +338,7 @@ private static void WriteLogInternal(string message, int indent, int depth) sourceInformation = string.Format( CultureInfo.InvariantCulture, "Thread {0}#{1}:{2}:{3} {4}", - Thread.CurrentThread.ManagedThreadId, + Environment.CurrentManagedThreadId, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, @@ -366,8 +347,8 @@ private static void WriteLogInternal(string message, int indent, int depth) lock (logLock) { - using (FileStream fs = new FileStream(logFile, FileMode.OpenOrCreate)) - using (StreamWriter writer = new StreamWriter(fs)) + using (FileStream fs = new(logFile, FileMode.OpenOrCreate)) + using (StreamWriter writer = new(fs)) { writer.WriteLineAsync(spaces[indent] + sourceInformation + @" " + message); } @@ -425,7 +406,7 @@ public static string ValidateArgumentIsValidName(string parameterName, string va string trimed = value.Trim(); // The first character should be contained in set: [A-Za-z_] // Inner characters should be contained in set: [A-Za-z0-9_] - Regex regex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]*\z"); + Regex regex = new(@"^[a-zA-Z_][a-zA-Z0-9_]*\z"); if (regex.IsMatch(trimed)) { DebugHelper.WriteLogEx("A valid name: {0}={1}", 0, parameterName, value); diff --git a/src/Microsoft.Management.UI.Internal/HelpWindow/HelpParagraphBuilder.cs b/src/Microsoft.Management.UI.Internal/HelpWindow/HelpParagraphBuilder.cs index 1d4bcacd893..a0f2cf950bd 100644 --- a/src/Microsoft.Management.UI.Internal/HelpWindow/HelpParagraphBuilder.cs +++ b/src/Microsoft.Management.UI.Internal/HelpWindow/HelpParagraphBuilder.cs @@ -690,7 +690,7 @@ private static void FormatMethodData(PSObject member, string name, out string me { parameterType = GetPropertyString(parameterTypeData, "name"); - // If there is no type for the paramter, we expect it is System.Object + // If there is no type for the parameter, we expect it is System.Object if (string.IsNullOrEmpty(parameterType)) { parameterType = "object"; diff --git a/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphBuilder.cs b/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphBuilder.cs index 822e4c05026..3d3613c1860 100644 --- a/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphBuilder.cs +++ b/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphBuilder.cs @@ -128,7 +128,7 @@ internal void BuildParagraph() } /// - /// Highlights all ocurrences of . + /// Highlights all occurrences of . /// This is called after all calls to AddText have been made. /// /// Search string. @@ -249,7 +249,7 @@ private static void AddInline(Paragraph currentParagraph, bool currentBold, bool /// /// Current index within . /// Current span within . - /// Caracter position. This comes from a position within this.textBuilder. + /// Character position. This comes from a position within this.textBuilder. /// The collection of spans. This is either this.boldSpans or this.highlightedSpans. private static void MoveSpanToPosition(ref int currentSpanIndex, ref TextSpan? currentSpan, int caracterPosition, List allSpans) { diff --git a/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphSearcher.cs b/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphSearcher.cs index e71a27bac8b..6c42047b1b7 100644 --- a/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphSearcher.cs +++ b/src/Microsoft.Management.UI.Internal/HelpWindow/ParagraphSearcher.cs @@ -56,7 +56,7 @@ internal Run MoveAndHighlightNextNextMatch(bool forward, TextPointer caretPositi } // If the caret is in the end of a highlight we move to the adjacent run - // It has to be in the end because if there is a match at the begining of the file + // It has to be in the end because if there is a match at the beginning of the file // and the caret has not been touched (so it is in the beginning of the file too) // we want to highlight this first match. // Considering the caller allways set the caret to the end of the highlight diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/Common/KeyboardHelp.cs b/src/Microsoft.Management.UI.Internal/ManagementList/Common/KeyboardHelp.cs index 90684f3f6cc..0d174fb25ed 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/Common/KeyboardHelp.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/Common/KeyboardHelp.cs @@ -109,7 +109,7 @@ public static FocusNavigationDirection GetNavigationDirection(DependencyObject e /// True if a control is is pressed. public static bool IsControlPressed() { - if (ModifierKeys.Control == (Keyboard.Modifiers & ModifierKeys.Control)) + if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { return true; } diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/Common/Utilities.cs b/src/Microsoft.Management.UI.Internal/ManagementList/Common/Utilities.cs index f0308a8c2b7..c6bcfcb1737 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/Common/Utilities.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/Common/Utilities.cs @@ -90,7 +90,7 @@ public static bool AreAllItemsOfType(IEnumerable items) foreach (object item in items) { - if (!(item is T)) + if (item is not T) { return false; } diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterEvaluator.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterEvaluator.cs index 2b33153a983..3e811368476 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterEvaluator.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterEvaluator.cs @@ -9,7 +9,7 @@ namespace Microsoft.Management.UI.Internal { /// - /// The FilterEvaluator class is responsible for allowing the registeration of + /// The FilterEvaluator class is responsible for allowing the registration of /// the FilterExpressionProviders and producing a FilterExpression composed of /// the FilterExpression returned from the providers. /// diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterRules/FilterRule.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterRules/FilterRule.cs index 1c2fc523e86..89b31449ba6 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterRules/FilterRule.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/FilterRules/FilterRule.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Management.UI.Internal { @@ -66,12 +67,14 @@ protected FilterRule() /// protected void NotifyEvaluationResultInvalidated() { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. var eh = this.EvaluationResultInvalidated; if (eh != null) { eh(this, new EventArgs()); } + #pragma warning restore IDE1005 } #endregion diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/IEvaluate.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/IEvaluate.cs index f83f6b377aa..161f14d4537 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/IEvaluate.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/IEvaluate.cs @@ -13,7 +13,7 @@ public interface IEvaluate { /// /// Gets a values indicating whether the supplied item has meet the - /// criteria rule specificed by the rule. + /// criteria rule specified by the rule. /// /// /// The item to evaluate. diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingSelectorValue.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingSelectorValue.cs index ed5389668e6..e86f2020ecc 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingSelectorValue.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingSelectorValue.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Windows.Data; @@ -214,12 +215,14 @@ protected override DataErrorInfoValidationResult Validate(string columnName) /// protected void NotifySelectedValueChanged(T oldValue, T newValue) { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. EventHandler> eh = this.SelectedValueChanged; if (eh != null) { eh(this, new PropertyChangedEventArgs(oldValue, newValue)); } + #pragma warning restore IDE1005 } #endregion NotifySelectedValueChanged diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingValueBase.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingValueBase.cs index f3959685349..ea2b255063f 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingValueBase.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterCore/ValidatingValueBase.cs @@ -6,6 +6,7 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace Microsoft.Management.UI.Internal @@ -260,12 +261,14 @@ protected void InvalidateValidationResult() /// protected void NotifyPropertyChanged(string propertyName) { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. PropertyChangedEventHandler eh = this.PropertyChanged; if (eh != null) { eh(this, new PropertyChangedEventArgs(propertyName)); } + #pragma warning restore IDE1005 } #endregion NotifyPropertyChanged diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/AddFilterRulePickerItem.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/AddFilterRulePickerItem.cs index 24c6eec1889..962d4a9665a 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/AddFilterRulePickerItem.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/AddFilterRulePickerItem.cs @@ -70,12 +70,14 @@ public AddFilterRulePickerItem(FilterRulePanelItem filterRule) /// protected void NotifyPropertyChanged(string propertyName) { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. PropertyChangedEventHandler eh = this.PropertyChanged; if (eh != null) { eh(this, new PropertyChangedEventArgs(propertyName)); } + #pragma warning restore IDE1005 } #endregion NotifyPropertyChanged diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanel.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanel.cs index bcc9a01a92c..35060a1b8ff 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanel.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanel.cs @@ -213,11 +213,13 @@ public void ClearContentTemplates() /// protected virtual void NotifyFilterExpressionChanged() { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. EventHandler eh = this.FilterExpressionChanged; if (eh != null) { eh(this, new EventArgs()); } + #pragma warning restore IDE1005 } private void Controller_FilterExpressionChanged(object sender, EventArgs e) diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelController.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelController.cs index dcec5022d98..c4956063aa3 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelController.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelController.cs @@ -266,11 +266,13 @@ private void UpdateFilterRulePanelItemTypes() /// protected virtual void NotifyFilterExpressionChanged() { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. EventHandler eh = this.FilterExpressionChanged; if (eh != null) { eh(this, new EventArgs()); } + #pragma warning restore IDE1005 } #endregion Notify Filter Expression Changed diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelItem.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelItem.cs index a1a873cdbc7..7f9a5afcc4c 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelItem.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/FilterRulePanelItem.cs @@ -25,7 +25,7 @@ public FilterRule Rule } /// - /// Gets a string that indentifies which group this + /// Gets a string that identifies which group this /// item belongs to. /// public string GroupId @@ -107,11 +107,15 @@ protected void NotifyPropertyChanged(string propertyName) { Debug.Assert(!string.IsNullOrEmpty(propertyName), "not null"); + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. + PropertyChangedEventHandler eh = this.PropertyChanged; if (eh != null) { eh(this, new PropertyChangedEventArgs(propertyName)); } + + #pragma warning restore IDE1005s } #endregion Public Methods diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/SearchBox.cs b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/SearchBox.cs index 25830150939..b6471b6f653 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/SearchBox.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/FilterProviders/SearchBox.cs @@ -60,11 +60,13 @@ public bool HasFilterExpression /// protected virtual void NotifyFilterExpressionChanged() { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. EventHandler eh = this.FilterExpressionChanged; if (eh != null) { eh(this, new EventArgs()); } + #pragma warning restore IDE1005s } #endregion diff --git a/src/Microsoft.Management.UI.Internal/ManagementList/ManagementList/Innerlist.cs b/src/Microsoft.Management.UI.Internal/ManagementList/ManagementList/Innerlist.cs index 03c7acdf008..868e17d85c4 100644 --- a/src/Microsoft.Management.UI.Internal/ManagementList/ManagementList/Innerlist.cs +++ b/src/Microsoft.Management.UI.Internal/ManagementList/ManagementList/Innerlist.cs @@ -296,7 +296,7 @@ protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldV this.itemsSourceIsEmpty = this.ItemsSource != null && this.ItemsSource.GetEnumerator().MoveNext() == false; - // A view can be created if there is data to auto-generate columns, or columns are added programatically \\ + // A view can be created if there is data to auto-generate columns, or columns are added programmatically \\ bool canCreateView = (this.ItemsSource != null) && (this.itemsSourceIsEmpty == false || this.AutoGenerateColumns == false); @@ -355,7 +355,7 @@ protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); - if ((Key.Left == e.Key || Key.Right == e.Key) && + if ((e.Key == Key.Left || e.Key == Key.Right) && Keyboard.Modifiers == ModifierKeys.None) { // If pressing Left or Right on a column header, move the focus \\ @@ -388,8 +388,8 @@ private static void InnerList_OnViewChanged(DependencyObject obj, DependencyProp throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, InvariantResources.ViewSetWithType, - typeof(GridView).Name, - typeof(InnerListGridView).Name)); + nameof(GridView), + nameof(InnerListGridView))); } ((InnerList)obj).innerGrid = innerGrid; @@ -405,7 +405,7 @@ private static NotSupportedException GetItemsException() string.Format( CultureInfo.InvariantCulture, InvariantResources.NotSupportAddingToItems, - typeof(InnerList).Name, + nameof(InnerList), ItemsControl.ItemsSourceProperty.Name)); } #endregion static private methods diff --git a/src/Microsoft.Management.UI.Internal/Microsoft.PowerShell.GraphicalHost.csproj b/src/Microsoft.Management.UI.Internal/Microsoft.PowerShell.GraphicalHost.csproj index 72eb8d6572f..607148b02fe 100644 --- a/src/Microsoft.Management.UI.Internal/Microsoft.PowerShell.GraphicalHost.csproj +++ b/src/Microsoft.Management.UI.Internal/Microsoft.PowerShell.GraphicalHost.csproj @@ -8,6 +8,7 @@ True Windows 7.0 + false diff --git a/src/Microsoft.Management.UI.Internal/ShowCommand/Controls/ParameterSetControl.xaml.cs b/src/Microsoft.Management.UI.Internal/ShowCommand/Controls/ParameterSetControl.xaml.cs index c258a2819ac..08f9df29337 100644 --- a/src/Microsoft.Management.UI.Internal/ShowCommand/Controls/ParameterSetControl.xaml.cs +++ b/src/Microsoft.Management.UI.Internal/ShowCommand/Controls/ParameterSetControl.xaml.cs @@ -357,7 +357,7 @@ private RowDefinition CreateNewRow() /// Will adding UIControl. private void AddControlToMainGrid(UIElement uiControl) { - if (this.firstFocusableElement == null && !(uiControl is Label)) + if (this.firstFocusableElement == null && uiControl is not Label) { this.firstFocusableElement = uiControl; } diff --git a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/CommandViewModel.cs b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/CommandViewModel.cs index e5eb1be800d..33908ea732f 100644 --- a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/CommandViewModel.cs +++ b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/CommandViewModel.cs @@ -438,12 +438,12 @@ public string GetScript() builder.Append(commandName); } - builder.Append(" "); + builder.Append(' '); if (this.SelectedParameterSet != null) { builder.Append(this.SelectedParameterSet.GetScript()); - builder.Append(" "); + builder.Append(' '); } if (this.CommonParameters != null) @@ -465,7 +465,7 @@ public void OpenHelpWindow() } /// - /// Determins whether current command name and a specifed ParameterSetName have same name. + /// Determines whether current command name and a specified ParameterSetName have same name. /// /// The name of ShareParameterSet. /// Return true is ShareParameterSet. Else return false. @@ -553,6 +553,8 @@ internal static CommandViewModel GetCommandViewModel(ModuleViewModel module, Sho return returnValue; } + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. + /// /// Called to trigger the event fired when help is needed for the command. /// @@ -628,6 +630,8 @@ private void OnNotifyPropertyChanged(string propertyName) } } + #pragma warning restore IDE1005 + /// /// Called when the PropertyChanged event is triggered on the SelectedParameterSet. /// diff --git a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ModuleViewModel.cs b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ModuleViewModel.cs index 38925e458a9..95e45123d22 100644 --- a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ModuleViewModel.cs +++ b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ModuleViewModel.cs @@ -373,7 +373,7 @@ internal void RefreshFilteredCommands(string filter) } /// - /// Callled in response to a GUI event that requires the command to be run. + /// Called in response to a GUI event that requires the command to be run. /// internal void OnRunSelectedCommand() { diff --git a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterSetViewModel.cs b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterSetViewModel.cs index 756f58c62c8..1521aab7742 100644 --- a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterSetViewModel.cs +++ b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterSetViewModel.cs @@ -39,7 +39,7 @@ public class ParameterSetViewModel : INotifyPropertyChanged /// Initializes a new instance of the ParameterSetViewModel class. /// /// The name of the parameterSet. - /// The array parametes of the parameterSet. + /// The array parameters of the parameterSet. [SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Justification = "this type is internal, made public only for WPF Binding")] public ParameterSetViewModel( string name, @@ -369,11 +369,13 @@ private void EvaluateAllMandatoryParametersHaveValues() /// The changed property. private void OnNotifyPropertyChanged(string propertyName) { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } + #pragma warning restore IDE1005 } /// diff --git a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterViewModel.cs b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterViewModel.cs index 2c6931eb08e..ccd2fd635c8 100644 --- a/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterViewModel.cs +++ b/src/Microsoft.Management.UI.Internal/ShowCommand/ViewModel/ParameterViewModel.cs @@ -268,11 +268,13 @@ internal static string EvaluateTooltip(string typeName, int position, bool manda /// The changed property. private void OnNotifyPropertyChanged(string propertyName) { + #pragma warning disable IDE1005 // IDE1005: Delegate invocation can be simplified. PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } + #pragma warning restore IDE1005 } } } diff --git a/src/Microsoft.Management.UI.Internal/commandHelpers/OutGridView.cs b/src/Microsoft.Management.UI.Internal/commandHelpers/OutGridView.cs index 85ecd95a36f..f38a8a70945 100644 --- a/src/Microsoft.Management.UI.Internal/commandHelpers/OutGridView.cs +++ b/src/Microsoft.Management.UI.Internal/commandHelpers/OutGridView.cs @@ -213,7 +213,7 @@ private void ZoomEventHandlerPlus(object sender, ExecutedRoutedEventArgs e) if (this.zoomLevel < ZOOM_MAX) { - this.zoomLevel = this.zoomLevel + ZOOM_INCREMENT; + this.zoomLevel += ZOOM_INCREMENT; Grid g = this.gridViewWindow.Content as Grid; if (g != null) @@ -232,7 +232,7 @@ private void ZoomEventHandlerMinus(object sender, ExecutedRoutedEventArgs e) { if (this.zoomLevel >= ZOOM_MIN) { - this.zoomLevel = this.zoomLevel - ZOOM_INCREMENT; + this.zoomLevel -= ZOOM_INCREMENT; Grid g = this.gridViewWindow.Content as Grid; if (g != null) { diff --git a/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs b/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs index 5d401fc94c6..873f15e2c41 100644 --- a/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs +++ b/src/Microsoft.Management.UI.Internal/commandHelpers/ShowCommandHelper.cs @@ -289,7 +289,7 @@ private ShowCommandHelper() } /// - /// Finalizes an instance of the ShowCommandHelper class. + /// Finalizes an instance of the class. /// ~ShowCommandHelper() { @@ -750,7 +750,7 @@ private static object GetPropertyValue(Type type, object obj, string propertyNam try { - return property.GetValue(obj, new object[] { }); + return property.GetValue(obj, Array.Empty()); } catch (ArgumentException) { @@ -794,7 +794,7 @@ private static bool SetPropertyValue(Type type, object obj, string propertyName, try { - property.SetValue(obj, value, new object[] { }); + property.SetValue(obj, value, Array.Empty()); } catch (ArgumentException) { @@ -1000,7 +1000,7 @@ private void ImportModuleDone(Dictionary imported { this.window.Dispatcher.Invoke( new SendOrPostCallback( - delegate (object ignored) + delegate(object ignored) { this.allModulesViewModel = ShowCommandHelper.GetNewAllModulesViewModel( this.allModulesViewModel, @@ -1050,7 +1050,7 @@ private void DisplayHelp(Collection getHelpResults) { this.window.Dispatcher.Invoke( new SendOrPostCallback( - delegate (object ignored) + delegate(object ignored) { HelpWindow help = new HelpWindow(getHelpResults[0]); help.Owner = this.window; diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CommonUtils.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CommonUtils.cs index bd99ef7aff2..dfe046ec8ca 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CommonUtils.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CommonUtils.cs @@ -2,9 +2,7 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Diagnostics; -using System.Globalization; using System.Reflection; using System.Resources; using System.Runtime.InteropServices; @@ -42,12 +40,12 @@ uint dwFlags [DllImport(LocalizationDllName, EntryPoint = "GetUserDefaultLangID", CallingConvention = CallingConvention.Winapi, SetLastError = true)] private static extern ushort GetUserDefaultLangID(); - public static uint FormatMessageFromModule(uint lastError, string moduleName, out String msg) + public static uint FormatMessageFromModule(uint lastError, string moduleName, out string msg) { Debug.Assert(!string.IsNullOrEmpty(moduleName)); uint formatError = 0; - msg = String.Empty; + msg = string.Empty; IntPtr moduleHandle = LoadLibraryEx(moduleName, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); if (moduleHandle == IntPtr.Zero) @@ -57,7 +55,6 @@ public static uint FormatMessageFromModule(uint lastError, string moduleName, ou try { - uint dwFormatFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE; uint LANGID = (uint)GetUserDefaultLangID(); uint langError = (uint)Marshal.GetLastWin32Error(); if (langError != 0) @@ -65,14 +62,15 @@ public static uint FormatMessageFromModule(uint lastError, string moduleName, ou LANGID = 0; // neutral } - StringBuilder outStringBuilder = new StringBuilder(1024); - uint nChars = FormatMessage(dwFormatFlags, - moduleHandle, - lastError, - LANGID, - outStringBuilder, - (uint)outStringBuilder.Capacity, - IntPtr.Zero); + StringBuilder outStringBuilder = new(1024); + uint nChars = FormatMessage( + dwFlags: FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, + lpSource: moduleHandle, + dwMessageId: lastError, + dwLanguageId: LANGID, + lpBuffer: outStringBuilder, + nSize: (uint)outStringBuilder.Capacity, + Arguments: IntPtr.Zero); if (nChars == 0) { @@ -100,4 +98,3 @@ public static ResourceManager GetResourceManager() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CoreCLR/Stubs.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CoreCLR/Stubs.cs index 00981ad8847..845179009f7 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CoreCLR/Stubs.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CoreCLR/Stubs.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. #if CORECLR -using System.ComponentModel; namespace System.Diagnostics { @@ -29,8 +28,8 @@ public enum PerformanceCounterCategoryType } /// - /// Specifies the formula used to calculate the - /// method for a instance. + /// Specifies the formula used to calculate the + /// method for a instance. /// /// 2 public enum PerformanceCounterType @@ -246,7 +245,7 @@ public enum PerformanceCounterType /// A difference counter that shows the change in the measured attribute /// between the two most recent sample intervals. It is the same as the /// CounterDelta32 counter type except that is uses larger fields to - /// accomodate larger values. + /// accommodate larger values. CounterDelta64 = 4195584 } } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs index 3a7af308f29..9089216a485 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs @@ -2,16 +2,10 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; -using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Reflection; using System.Resources; -using Microsoft.Powershell.Commands.GetCounter.PdhNative; - namespace Microsoft.PowerShell.Commands.GetCounter { public class PerformanceCounterSample @@ -33,127 +27,43 @@ internal PerformanceCounterSample(string path, UInt64 timeStamp100nSec, UInt32 status) { - _path = path; - _instanceName = instanceName; - _cookedValue = cookedValue; - _rawValue = rawValue; - _secondValue = secondValue; - _multiCount = multiCount; - _counterType = counterType; - _defaultScale = defaultScale; - _timeBase = timeBase; - _timeStamp = timeStamp; - _timeStamp100nSec = timeStamp100nSec; - _status = status; + Path = path; + InstanceName = instanceName; + CookedValue = cookedValue; + RawValue = rawValue; + SecondValue = secondValue; + MultipleCount = multiCount; + CounterType = counterType; + DefaultScale = defaultScale; + TimeBase = timeBase; + Timestamp = timeStamp; + Timestamp100NSec = timeStamp100nSec; + Status = status; } - public string Path - { - get { return _path; } + public string Path { get; set; } = string.Empty; - set { _path = value; } - } + public string InstanceName { get; set; } = string.Empty; - private string _path = string.Empty; + public double CookedValue { get; set; } - public string InstanceName - { - get { return _instanceName; } + public UInt64 RawValue { get; set; } - set { _instanceName = value; } - } + public UInt64 SecondValue { get; set; } - private string _instanceName = string.Empty; + public uint MultipleCount { get; set; } - public double CookedValue - { - get { return _cookedValue; } + public PerformanceCounterType CounterType { get; set; } - set { _cookedValue = value; } - } + public DateTime Timestamp { get; set; } = DateTime.MinValue; - private double _cookedValue = 0; + public UInt64 Timestamp100NSec { get; set; } - public UInt64 RawValue - { - get { return _rawValue; } - - set { _rawValue = value; } - } - - private UInt64 _rawValue = 0; - - public UInt64 SecondValue - { - get { return _secondValue; } - - set { _secondValue = value; } - } + public UInt32 Status { get; set; } - private UInt64 _secondValue = 0; - - public uint MultipleCount - { - get { return _multiCount; } - - set { _multiCount = value; } - } - - private uint _multiCount = 0; - - public PerformanceCounterType CounterType - { - get { return _counterType; } - - set { _counterType = value; } - } - - private PerformanceCounterType _counterType = 0; - - public DateTime Timestamp - { - get { return _timeStamp; } - - set { _timeStamp = value; } - } + public UInt32 DefaultScale { get; set; } - private DateTime _timeStamp = DateTime.MinValue; - - public UInt64 Timestamp100NSec - { - get { return _timeStamp100nSec; } - - set { _timeStamp100nSec = value; } - } - - private UInt64 _timeStamp100nSec = 0; - - public UInt32 Status - { - get { return _status; } - - set { _status = value; } - } - - private UInt32 _status = 0; - - public UInt32 DefaultScale - { - get { return _defaultScale; } - - set { _defaultScale = value; } - } - - private UInt32 _defaultScale = 0; - - public UInt64 TimeBase - { - get { return _timeBase; } - - set { _timeBase = value; } - } - - private UInt64 _timeBase = 0; + public UInt64 TimeBase { get; set; } } public class PerformanceCounterSampleSet @@ -167,32 +77,18 @@ internal PerformanceCounterSampleSet(DateTime timeStamp, PerformanceCounterSample[] counterSamples, bool firstSet) : this() { - _timeStamp = timeStamp; - _counterSamples = counterSamples; - } - - public DateTime Timestamp - { - get { return _timeStamp; } - - set { _timeStamp = value; } + Timestamp = timeStamp; + CounterSamples = counterSamples; } - private DateTime _timeStamp = DateTime.MinValue; + public DateTime Timestamp { get; set; } = DateTime.MinValue; [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample.CounterSamples", Justification = "A string[] is required here because that is the type Powershell supports")] - public PerformanceCounterSample[] CounterSamples - { - get { return _counterSamples; } - - set { _counterSamples = value; } - } - - private PerformanceCounterSample[] _counterSamples = null; + public PerformanceCounterSample[] CounterSamples { get; set; } - private ResourceManager _resourceMgr = null; + private readonly ResourceManager _resourceMgr = null; } } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs index c1474ec4209..dfc175b604c 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs @@ -2,10 +2,8 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics; namespace Microsoft.PowerShell.Commands.GetCounter @@ -18,94 +16,54 @@ internal CounterSet(string setName, string setHelp, ref Dictionary counterInstanceMapping) { - _counterSetName = setName; + CounterSetName = setName; if (machineName == null || machineName.Length == 0) { machineName = "."; } else { - _machineName = machineName; - if (!_machineName.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase)) + MachineName = machineName; + if (!MachineName.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase)) { - _machineName = @"\\" + _machineName; + MachineName = @"\\" + MachineName; } } - _counterSetType = categoryType; - _description = setHelp; - _counterInstanceMapping = counterInstanceMapping; + CounterSetType = categoryType; + Description = setHelp; + CounterInstanceMapping = counterInstanceMapping; } - public string CounterSetName - { - get - { - return _counterSetName; - } - } - - private string _counterSetName = string.Empty; - - public string MachineName - { - get - { - return _machineName; - } - } - - private string _machineName = "."; - - public PerformanceCounterCategoryType CounterSetType - { - get - { - return _counterSetType; - } - } + public string CounterSetName { get; } = string.Empty; - private PerformanceCounterCategoryType _counterSetType; + public string MachineName { get; } = "."; - public string Description - { - get - { - return _description; - } - } - - private string _description = string.Empty; + public PerformanceCounterCategoryType CounterSetType { get; } - internal Dictionary CounterInstanceMapping - { - get - { - return _counterInstanceMapping; - } - } + public string Description { get; } = string.Empty; - private Dictionary _counterInstanceMapping; + internal Dictionary CounterInstanceMapping { get; } public StringCollection Paths { get { - StringCollection retColl = new StringCollection(); + StringCollection retColl = new(); foreach (string counterName in this.CounterInstanceMapping.Keys) { string path; if (CounterInstanceMapping[counterName].Length != 0) { - path = (_machineName == ".") ? - ("\\" + _counterSetName + "(*)\\" + counterName) : - (_machineName + "\\" + _counterSetName + "(*)\\" + counterName); + path = (MachineName == ".") ? + ("\\" + CounterSetName + "(*)\\" + counterName) : + (MachineName + "\\" + CounterSetName + "(*)\\" + counterName); } else { - path = (_machineName == ".") ? - ("\\" + _counterSetName + "\\" + counterName) : - (_machineName + "\\" + _counterSetName + "\\" + counterName); + path = (MachineName == ".") ? + ("\\" + CounterSetName + "\\" + counterName) : + (MachineName + "\\" + CounterSetName + "\\" + counterName); } retColl.Add(path); @@ -119,14 +77,14 @@ public StringCollection PathsWithInstances { get { - StringCollection retColl = new StringCollection(); + StringCollection retColl = new(); foreach (string counterName in CounterInstanceMapping.Keys) { foreach (string instanceName in CounterInstanceMapping[counterName]) { - string path = (_machineName == ".") ? - ("\\" + _counterSetName + "(" + instanceName + ")\\" + counterName) : - (_machineName + "\\" + _counterSetName + "(" + instanceName + ")\\" + counterName); + string path = (MachineName == ".") ? + ("\\" + CounterSetName + "(" + instanceName + ")\\" + counterName) : + (MachineName + "\\" + CounterSetName + "(" + instanceName + ")\\" + counterName); retColl.Add(path); } } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs index 459d553e27a..f04c8ceff0f 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs @@ -2,35 +2,23 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.IO; using System.Management.Automation; -using System.Management.Automation.Runspaces; -using System.Net; -using System.Reflection; using System.Resources; -using System.Security; -using System.Security.Principal; -using System.Text; using System.Threading; -using System.Xml; - +using Microsoft.Powershell.Commands.GetCounter.PdhNative; using Microsoft.PowerShell.Commands.Diagnostics.Common; using Microsoft.PowerShell.Commands.GetCounter; -using Microsoft.Powershell.Commands.GetCounter.PdhNative; namespace Microsoft.PowerShell.Commands { - /// + /// /// Class that implements the Get-Counter cmdlet. - /// + /// [Cmdlet(VerbsCommon.Get, "Counter", DefaultParameterSetName = "GetCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2109647")] public sealed class GetCounterCommand : PSCmdlet { @@ -49,15 +37,7 @@ public sealed class GetCounterCommand : PSCmdlet Scope = "member", Target = "Microsoft.PowerShell.Commands.GetCounterCommand.ListSet", Justification = "A string[] is required here because that is the type Powershell supports")] - - public string[] ListSet - { - get { return _listSet; } - - set { _listSet = value; } - } - - private string[] _listSet = { "*" }; + public string[] ListSet { get; set; } = { "*" }; // // Counter parameter @@ -75,7 +55,10 @@ public string[] ListSet Justification = "A string[] is required here because that is the type Powershell supports")] public string[] Counter { - get { return _counter; } + get + { + return _counter; + } set { @@ -93,7 +76,7 @@ public string[] Counter private bool _defaultCounters = true; - private List _accumulatedCounters = new List(); + private readonly List _accumulatedCounters = new(); // // SampleInterval parameter. @@ -105,14 +88,7 @@ public string[] Counter ValueFromPipelineByPropertyName = false, HelpMessageBaseName = "GetEventResources")] [ValidateRange((int)1, int.MaxValue)] - public int SampleInterval - { - get { return _sampleInterval; } - - set { _sampleInterval = value; } - } - - private int _sampleInterval = 1; + public int SampleInterval { get; set; } = 1; // // MaxSamples parameter @@ -127,7 +103,10 @@ public int SampleInterval [ValidateRange((Int64)1, Int64.MaxValue)] public Int64 MaxSamples { - get { return _maxSamples; } + get + { + return _maxSamples; + } set { @@ -167,20 +146,13 @@ public SwitchParameter Continuous Scope = "member", Target = "Microsoft.PowerShell.Commands.GetCounterCommand.ComputerName", Justification = "A string[] is required here because that is the type Powershell supports")] - public string[] ComputerName - { - get { return _computerName; } - - set { _computerName = value; } - } - - private string[] _computerName = Array.Empty(); + public string[] ComputerName { get; set; } = Array.Empty(); private ResourceManager _resourceMgr = null; private PdhHelper _pdhHelper = null; - private EventWaitHandle _cancelEventArrived = new EventWaitHandle(false, EventResetMode.ManualReset); + private readonly EventWaitHandle _cancelEventArrived = new(false, EventResetMode.ManualReset); // Culture identifier(s) private const string FrenchCultureId = "fr-FR"; @@ -192,17 +164,17 @@ public string[] ComputerName // // With this dictionary, we can add special mapping if we find other special cases in the future. private readonly Dictionary>> _cultureAndSpecialCharacterMap = - new Dictionary>>() + new() { { FrenchCultureId, new List>() { // 'APOSTROPHE' to 'RIGHT SINGLE QUOTATION MARK' - new Tuple((char) 0x0027, (char) 0x2019), + new Tuple((char)0x0027, (char)0x2019), // 'MODIFIER LETTER APOSTROPHE' to 'RIGHT SINGLE QUOTATION MARK' - new Tuple((char) 0x02BC, (char) 0x2019), + new Tuple((char)0x02BC, (char)0x2019), // 'HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT' to 'RIGHT SINGLE QUOTATION MARK' - new Tuple((char) 0x275C, (char) 0x2019), + new Tuple((char)0x275C, (char)0x2019), } } }; @@ -222,7 +194,7 @@ protected override void BeginProcessing() _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager(); uint res = _pdhHelper.ConnectToDataSource(); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { ReportPdhError(res, true); return; @@ -230,7 +202,7 @@ protected override void BeginProcessing() if (Continuous.IsPresent && _maxSamplesSpecified) { - Exception exc = new Exception(string.Format(CultureInfo.CurrentCulture, _resourceMgr.GetString("CounterContinuousOrMaxSamples"))); + Exception exc = new(string.Format(CultureInfo.CurrentCulture, _resourceMgr.GetString("CounterContinuousOrMaxSamples"))); ThrowTerminatingError(new ErrorRecord(exc, "CounterContinuousOrMaxSamples", ErrorCategory.InvalidArgument, null)); } } @@ -300,12 +272,12 @@ private void AccumulatePipelineCounters() // private void ProcessListSet() { - if (_computerName.Length == 0) + if (ComputerName.Length == 0) { ProcessListSetPerMachine(null); } else - foreach (string machine in _computerName) + foreach (string machine in ComputerName) { ProcessListSetPerMachine(machine); } @@ -317,24 +289,24 @@ private void ProcessListSet() // private void ProcessListSetPerMachine(string machine) { - StringCollection counterSets = new StringCollection(); + StringCollection counterSets = new(); uint res = _pdhHelper.EnumObjects(machine, ref counterSets); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // add an error message string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoCounterSetsOnComputer"), machine, res); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "NoCounterSetsOnComputer", ErrorCategory.InvalidResult, machine)); return; } CultureInfo culture = GetCurrentCulture(); List> characterReplacementList = null; - StringCollection validPaths = new StringCollection(); + StringCollection validPaths = new(); _cultureAndSpecialCharacterMap.TryGetValue(culture.Name, out characterReplacementList); - foreach (string pattern in _listSet) + foreach (string pattern in ListSet) { bool bMatched = false; string normalizedPattern = pattern; @@ -347,7 +319,7 @@ private void ProcessListSetPerMachine(string machine) } } - WildcardPattern wildLogPattern = new WildcardPattern(normalizedPattern, WildcardOptions.IgnoreCase); + WildcardPattern wildLogPattern = new(normalizedPattern, WildcardOptions.IgnoreCase); foreach (string counterSet in counterSets) { @@ -356,18 +328,18 @@ private void ProcessListSetPerMachine(string machine) continue; } - StringCollection counterSetCounters = new StringCollection(); - StringCollection counterSetInstances = new StringCollection(); + StringCollection counterSetCounters = new(); + StringCollection counterSetInstances = new(); res = _pdhHelper.EnumObjectItems(machine, counterSet, ref counterSetCounters, ref counterSetInstances); if (res == PdhResults.PDH_ACCESS_DENIED) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterSetEnumAccessDenied"), counterSet); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "CounterSetEnumAccessDenied", ErrorCategory.InvalidResult, null)); continue; } - else if (res != 0) + else if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { ReportPdhError(res, false); continue; @@ -389,7 +361,7 @@ private void ProcessListSetPerMachine(string machine) instanceArray[0] = "*"; } - Dictionary counterInstanceMapping = new Dictionary(); + Dictionary counterInstanceMapping = new(); foreach (string counter in counterSetCounters) { counterInstanceMapping.TryAdd(counter, instanceArray); @@ -407,7 +379,7 @@ private void ProcessListSetPerMachine(string machine) string setHelp = _pdhHelper.GetCounterSetHelp(machine, counterSet); - CounterSet setObj = new CounterSet(counterSet, machine, categoryType, setHelp, ref counterInstanceMapping); + CounterSet setObj = new(counterSet, machine, categoryType, setHelp, ref counterInstanceMapping); WriteObject(setObj); bMatched = true; } @@ -415,7 +387,7 @@ private void ProcessListSetPerMachine(string machine) if (!bMatched) { string msg = _resourceMgr.GetString("NoMatchingCounterSetsFound"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, machine ?? "localhost", normalizedPattern)); WriteError(new ErrorRecord(exc, "NoMatchingCounterSetsFound", ErrorCategory.ObjectNotFound, null)); } @@ -437,24 +409,24 @@ private void ProcessGetCounter() CultureInfo culture = GetCurrentCulture(); List> characterReplacementList = null; List paths = CombineMachinesAndCounterPaths(); - uint res = 0; if (!_defaultCounters) { _cultureAndSpecialCharacterMap.TryGetValue(culture.Name, out characterReplacementList); } - StringCollection allExpandedPaths = new StringCollection(); + StringCollection allExpandedPaths = new(); + uint res; foreach (string path in paths) { string localizedPath = path; if (_defaultCounters) { res = _pdhHelper.TranslateLocalCounterPath(path, out localizedPath); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { string msg = string.Format(CultureInfo.CurrentCulture, _resourceMgr.GetString("CounterPathTranslationFailed"), res); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "CounterPathTranslationFailed", ErrorCategory.InvalidResult, null)); localizedPath = path; @@ -470,7 +442,7 @@ private void ProcessGetCounter() StringCollection expandedPaths; res = _pdhHelper.ExpandWildCardPath(localizedPath, out expandedPaths); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { WriteDebug("Could not expand path " + localizedPath); ReportPdhError(res, false); @@ -482,7 +454,7 @@ private void ProcessGetCounter() if (!_pdhHelper.IsPathValid(expandedPath)) { string msg = string.Format(CultureInfo.CurrentCulture, _resourceMgr.GetString("CounterPathIsInvalid"), localizedPath); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "CounterPathIsInvalid", ErrorCategory.InvalidResult, null)); continue; @@ -498,13 +470,13 @@ private void ProcessGetCounter() } res = _pdhHelper.OpenQuery(); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { ReportPdhError(res, false); } res = _pdhHelper.AddCounters(ref allExpandedPaths, true); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { ReportPdhError(res, true); @@ -526,7 +498,7 @@ private void ProcessGetCounter() // read the first set just to get the initial values res = _pdhHelper.ReadNextSet(out nextSet, bSkip); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { // Display valid data if (!bSkip) @@ -562,7 +534,7 @@ private void ProcessGetCounter() break; } - bool cancelled = _cancelEventArrived.WaitOne((int)_sampleInterval * 1000, true); + bool cancelled = _cancelEventArrived.WaitOne((int)SampleInterval * 1000, true); if (cancelled) { break; @@ -579,7 +551,7 @@ private void ReportPdhError(uint res, bool bTerminate) msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterApiError"), res); } - Exception exc = new Exception(msg); + Exception exc = new(msg); if (bTerminate) { ThrowTerminatingError(new ErrorRecord(exc, "CounterApiError", ErrorCategory.InvalidResult, null)); @@ -597,9 +569,9 @@ private void ReportPdhError(uint res, bool bTerminate) // private List CombineMachinesAndCounterPaths() { - List retColl = new List(); + List retColl = new(); - if (_computerName.Length == 0) + if (ComputerName.Length == 0) { retColl.AddRange(_accumulatedCounters); return retColl; @@ -613,15 +585,16 @@ private List CombineMachinesAndCounterPaths() } else { - foreach (string machine in _computerName) + foreach (string machine in ComputerName) { + string slashBeforePath = path.Length > 0 && path[0] == '\\' ? string.Empty : "\\"; if (machine.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) { - retColl.Add(machine + "\\" + path); + retColl.Add(machine + slashBeforePath + path); } else { - retColl.Add("\\\\" + machine + "\\" + path); + retColl.Add("\\\\" + machine + slashBeforePath + path); } } } @@ -642,7 +615,7 @@ private void WriteSampleSetObject(PerformanceCounterSampleSet set) if (sample.Status != 0) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterSampleDataInvalid")); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "CounterApiError", ErrorCategory.InvalidResult, null)); break; } @@ -657,4 +630,3 @@ private static CultureInfo GetCurrentCulture() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs index 33e127565e6..10044e29466 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs @@ -11,7 +11,6 @@ using System.Globalization; using System.Management.Automation; using System.Net; -using System.Reflection; using System.Resources; using System.Security.Principal; using System.Text; @@ -21,9 +20,9 @@ namespace Microsoft.PowerShell.Commands { - /// + /// /// Class that implements the Get-WinEvent cmdlet. - /// + /// [Cmdlet(VerbsCommon.Get, "WinEvent", DefaultParameterSetName = "GetLogSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096581")] public sealed class GetWinEventCommand : PSCmdlet { @@ -43,15 +42,7 @@ public sealed class GetWinEventCommand : PSCmdlet Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.ListLog", Justification = "A string[] is required here because that is the type Powershell supports")] - - public string[] ListLog - { - get { return _listLog; } - - set { _listLog = value; } - } - - private string[] _listLog = { "*" }; + public string[] ListLog { get; set; } = { "*" }; /// /// GetLog parameter. @@ -67,14 +58,7 @@ public string[] ListLog Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.LogName", Justification = "A string[] is required here because that is the type Powershell supports")] - public string[] LogName - { - get { return _logName; } - - set { _logName = value; } - } - - private string[] _logName = { "*" }; + public string[] LogName { get; set; } = { "*" }; /// /// ListProvider parameter. @@ -88,20 +72,11 @@ public string[] LogName HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "ListProviderParamHelp")] [AllowEmptyCollection] - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.ListProvider", Justification = "A string[] is required here because that is the type Powershell supports")] - - public string[] ListProvider - { - get { return _listProvider; } - - set { _listProvider = value; } - } - - private string[] _listProvider = { "*" }; + public string[] ListProvider { get; set; } = { "*" }; /// /// ProviderName parameter. @@ -113,20 +88,11 @@ public string[] ListProvider ValueFromPipelineByPropertyName = true, HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "GetProviderParamHelp")] - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.ProviderName", Justification = "A string[] is required here because that is the type Powershell supports")] - - public string[] ProviderName - { - get { return _providerName; } - - set { _providerName = value; } - } - - private string[] _providerName; + public string[] ProviderName { get; set; } /// /// Path parameter. @@ -138,20 +104,12 @@ public string[] ProviderName ValueFromPipelineByPropertyName = true, HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "PathParamHelp")] - [Alias("PSPath")] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.Path", Justification = "A string[] is required here because that is the type Powershell supports")] - public string[] Path - { - get { return _path; } - - set { _path = value; } - } - - private string[] _path; + public string[] Path { get; set; } /// /// MaxEvents parameter. @@ -186,15 +144,8 @@ public string[] Path ValueFromPipelineByPropertyName = false, HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "MaxEventsParamHelp")] - [ValidateRange((Int64)1, Int64.MaxValue)] - public Int64 MaxEvents - { - get { return _maxEvents; } - - set { _maxEvents = value; } - } - - private Int64 _maxEvents = -1; + [ValidateRange((long)1, long.MaxValue)] + public long MaxEvents { get; set; } = -1; /// /// ComputerName parameter. @@ -223,17 +174,9 @@ public Int64 MaxEvents ParameterSetName = "XmlQuerySet", HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "ComputerNameParamHelp")] - [ValidateNotNull] [Alias("Cn")] - public string ComputerName - { - get { return _computerName; } - - set { _computerName = value; } - } - - private string _computerName = string.Empty; + public string ComputerName { get; set; } = string.Empty; /// /// Credential parameter. @@ -246,14 +189,7 @@ public string ComputerName [Parameter(ParameterSetName = "XmlQuerySet")] [Parameter(ParameterSetName = "FileSet")] [Credential] - public PSCredential Credential - { - get { return _credential; } - - set { _credential = value; } - } - - private PSCredential _credential = PSCredential.Empty; + public PSCredential Credential { get; set; } = PSCredential.Empty; /// /// FilterXPath parameter. @@ -274,14 +210,7 @@ public PSCredential Credential ValueFromPipelineByPropertyName = false, HelpMessageBaseName = "GetEventResources")] [ValidateNotNull] - public string FilterXPath - { - get { return _filter; } - - set { _filter = value; } - } - - private string _filter = "*"; + public string FilterXPath { get; set; } = "*"; /// /// FilterXml parameter. @@ -293,20 +222,11 @@ public string FilterXPath ValueFromPipelineByPropertyName = false, ParameterSetName = "XmlQuerySet", HelpMessageBaseName = "GetEventResources")] - [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.FilterXml", Justification = "An XmlDocument is required here because that is the type Powershell supports")] - - public XmlDocument FilterXml - { - get { return _xmlQuery; } - - set { _xmlQuery = value; } - } - - private XmlDocument _xmlQuery = null; + public XmlDocument FilterXml { get; set; } /// /// FilterHashtable parameter. @@ -318,20 +238,11 @@ public XmlDocument FilterXml ValueFromPipelineByPropertyName = false, ParameterSetName = "HashQuerySet", HelpMessageBaseName = "GetEventResources")] - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.PowerShell.Commands.GetEvent.FilterHashtable", Justification = "A string[] is required here because that is the type Powershell supports")] - - public Hashtable[] FilterHashtable - { - get { return _selector; } - - set { _selector = value; } - } - - private Hashtable[] _selector; + public Hashtable[] FilterHashtable { get; set; } /// /// Force switch. @@ -339,16 +250,8 @@ public Hashtable[] FilterHashtable [Parameter(ParameterSetName = "ListLogSet")] [Parameter(ParameterSetName = "GetProviderSet")] [Parameter(ParameterSetName = "GetLogSet")] - [Parameter(ParameterSetName = "HashQuerySet")] - public SwitchParameter Force - { - get { return _force; } - - set { _force = value; } - } - - private SwitchParameter _force; + public SwitchParameter Force { get; set; } /// /// Oldest switch. @@ -356,7 +259,6 @@ public SwitchParameter Force [Parameter(ParameterSetName = "FileSet")] [Parameter(ParameterSetName = "GetProviderSet")] [Parameter(ParameterSetName = "GetLogSet")] - [Parameter(ParameterSetName = "HashQuerySet")] [Parameter(ParameterSetName = "XmlQuerySet")] public SwitchParameter Oldest @@ -379,8 +281,8 @@ public SwitchParameter Oldest private const string SelectCloser = ""; private const string suppressOpener = "*"; private const string suppressCloser = ""; - private const string propOpen = "["; - private const string propClose = "]"; + private const char propOpen = '['; + private const char propClose = ']'; private const string filePrefix = "file://"; private const string NamedDataTemplate = "((EventData[Data[@Name='{0}']='{1}']) or (UserData/*/{0}='{1}'))"; private const string DataTemplate = "(EventData/Data='{0}')"; @@ -396,14 +298,14 @@ public SwitchParameter Oldest // Other private members and constants // private ResourceManager _resourceMgr = null; - private Dictionary _providersByLogMap = new Dictionary(); + private readonly Dictionary _providersByLogMap = new(); private StringCollection _logNamesMatchingWildcard = null; - private StringCollection _resolvedPaths = new StringCollection(); + private readonly StringCollection _resolvedPaths = new(); - private List _accumulatedLogNames = new List(); - private List _accumulatedProviderNames = new List(); - private List _accumulatedFileNames = new List(); + private readonly List _accumulatedLogNames = new(); + private readonly List _accumulatedProviderNames = new(); + private readonly List _accumulatedFileNames = new(); private const uint MAX_EVENT_BATCH = 100; @@ -502,7 +404,7 @@ protected override void ProcessRecord() // private void AccumulatePipelineLogNames() { - _accumulatedLogNames.AddRange(_logName); + _accumulatedLogNames.AddRange(LogName); } // @@ -511,7 +413,7 @@ private void AccumulatePipelineLogNames() // private void AccumulatePipelineProviderNames() { - _accumulatedProviderNames.AddRange(_logName); + _accumulatedProviderNames.AddRange(LogName); } // @@ -520,7 +422,7 @@ private void AccumulatePipelineProviderNames() // private void AccumulatePipelineFileNames() { - _accumulatedFileNames.AddRange(_logName); + _accumulatedFileNames.AddRange(LogName); } // @@ -545,7 +447,7 @@ private void ProcessGetLog() } else { - logQuery = new EventLogQuery(_logNamesMatchingWildcard[0], PathType.LogName, _filter); + logQuery = new EventLogQuery(_logNamesMatchingWildcard[0], PathType.LogName, FilterXPath); } logQuery.Session = eventLogSession; @@ -562,7 +464,7 @@ private void ProcessGetProvider() { using (EventLogSession eventLogSession = CreateSession()) { - FindProvidersByLogForWildcardPatterns(eventLogSession, _providerName); + FindProvidersByLogForWildcardPatterns(eventLogSession, ProviderName); if (_providersByLogMap.Count == 0) { @@ -605,10 +507,10 @@ private void ProcessListLog() { using (EventLogSession eventLogSession = CreateSession()) { - foreach (string logPattern in _listLog) + foreach (string logPattern in ListLog) { bool bMatchFound = false; - WildcardPattern wildLogPattern = new WildcardPattern(logPattern, WildcardOptions.IgnoreCase); + WildcardPattern wildLogPattern = new(logPattern, WildcardOptions.IgnoreCase); foreach (string logName in eventLogSession.GetLogNames()) { @@ -619,7 +521,7 @@ private void ProcessListLog() { try { - EventLogConfiguration logObj = new EventLogConfiguration(logName, eventLogSession); + EventLogConfiguration logObj = new(logName, eventLogSession); // // Skip direct channels matching the wildcard unless -Force is present. @@ -634,7 +536,7 @@ private void ProcessListLog() EventLogInformation logInfoObj = eventLogSession.GetLogInformation(logName, PathType.LogName); - PSObject outputObj = new PSObject(logObj); + PSObject outputObj = new(logObj); outputObj.Properties.Add(new PSNoteProperty("FileSize", logInfoObj.FileSize)); outputObj.Properties.Add(new PSNoteProperty("IsLogFull", logInfoObj.IsLogFull)); @@ -651,7 +553,7 @@ private void ProcessListLog() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("LogInfoUnavailable"), logName, exc.Message); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "LogInfoUnavailable", ErrorCategory.NotSpecified, null)); continue; } @@ -661,7 +563,7 @@ private void ProcessListLog() if (!bMatchFound) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, _computerName, logPattern)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, ComputerName, logPattern)); WriteError(new ErrorRecord(exc, "NoMatchingLogsFound", ErrorCategory.ObjectNotFound, null)); } } @@ -675,10 +577,10 @@ private void ProcessListProvider() { using (EventLogSession eventLogSession = CreateSession()) { - foreach (string provPattern in _listProvider) + foreach (string provPattern in ListProvider) { bool bMatchFound = false; - WildcardPattern wildProvPattern = new WildcardPattern(provPattern, WildcardOptions.IgnoreCase); + WildcardPattern wildProvPattern = new(provPattern, WildcardOptions.IgnoreCase); foreach (string provName in eventLogSession.GetProviderNames()) { @@ -689,7 +591,7 @@ private void ProcessListProvider() { try { - ProviderMetadata provObj = new ProviderMetadata(provName, eventLogSession, CultureInfo.CurrentCulture); + ProviderMetadata provObj = new(provName, eventLogSession, CultureInfo.CurrentCulture); WriteObject(provObj); bMatchFound = true; } @@ -698,7 +600,7 @@ private void ProcessListProvider() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderMetadataUnavailable"), provName, exc.Message); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "ProviderMetadataUnavailable", ErrorCategory.NotSpecified, null)); continue; } @@ -708,8 +610,8 @@ private void ProcessListProvider() if (!bMatchFound) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoMatchingProvidersFound"), - _computerName, provPattern); - Exception exc = new Exception(msg); + ComputerName, provPattern); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "NoMatchingProvidersFound", ErrorCategory.ObjectNotFound, null)); } } @@ -728,7 +630,7 @@ private void ProcessFilterXml() // // Do minimal parsing of xmlQuery to determine if any direct channels or ETL files are in it. // - XmlElement root = _xmlQuery.DocumentElement; + XmlElement root = FilterXml.DocumentElement; XmlNodeList queryNodes = root.SelectNodes("//Query//Select"); foreach (XmlNode queryNode in queryNodes) { @@ -750,7 +652,7 @@ private void ProcessFilterXml() } } - EventLogQuery logQuery = new EventLogQuery(null, PathType.LogName, _xmlQuery.InnerXml); + EventLogQuery logQuery = new(null, PathType.LogName, FilterXml.InnerXml); logQuery.Session = eventLogSession; logQuery.ReverseDirection = !_oldest; @@ -769,9 +671,9 @@ private void ProcessFile() // At this point, _path array contains paths that might have wildcards, // environment variables or PS drives. Let's resolve those. // - for (int i = 0; i < _path.Length; i++) + for (int i = 0; i < Path.Length; i++) { - StringCollection resolvedPaths = ValidateAndResolveFilePath(_path[i]); + StringCollection resolvedPaths = ValidateAndResolveFilePath(Path[i]); foreach (string resolvedPath in resolvedPaths) { _resolvedPaths.Add(resolvedPath); @@ -792,7 +694,7 @@ private void ProcessFile() } else { - logQuery = new EventLogQuery(_resolvedPaths[0], PathType.FilePath, _filter); + logQuery = new EventLogQuery(_resolvedPaths[0], PathType.FilePath, FilterXPath); } logQuery.Session = eventLogSession; @@ -817,7 +719,7 @@ private void ProcessHashQuery() return; } - EventLogQuery logQuery = new EventLogQuery(null, PathType.FilePath, query); + EventLogQuery logQuery = new(null, PathType.FilePath, query); logQuery.Session = eventLogSession; logQuery.TolerateQueryErrors = true; logQuery.ReverseDirection = !_oldest; @@ -834,30 +736,30 @@ private EventLogSession CreateSession() { EventLogSession eventLogSession = null; - if (_computerName == string.Empty) + if (ComputerName == string.Empty) { // Set _computerName to "localhost" for future error messages, // but do not use it for the connection to avoid RPC overhead. - _computerName = "localhost"; + ComputerName = "localhost"; - if (_credential == PSCredential.Empty) + if (Credential == PSCredential.Empty) { return new EventLogSession(); } } - else if (_credential == PSCredential.Empty) + else if (Credential == PSCredential.Empty) { - return new EventLogSession(_computerName); + return new EventLogSession(ComputerName); } // If we are here, either both computer name and credential were passed initially, // or credential only - we will use it with "localhost" - NetworkCredential netCred = (NetworkCredential)_credential; - eventLogSession = new EventLogSession(_computerName, + NetworkCredential netCred = (NetworkCredential)Credential; + eventLogSession = new EventLogSession(ComputerName, netCred.Domain, netCred.UserName, - _credential.Password, + Credential.Password, SessionAuthentication.Default ); // @@ -873,9 +775,9 @@ private EventLogSession CreateSession() // private void ReadEvents(EventLogQuery logQuery) { - using (EventLogReader readerObj = new EventLogReader(logQuery)) + using (EventLogReader readerObj = new(logQuery)) { - Int64 numEvents = 0; + long numEvents = 0; EventRecord evtObj = null; while (true) @@ -895,12 +797,12 @@ private void ReadEvents(EventLogQuery logQuery) break; } - if (_maxEvents != -1 && numEvents >= _maxEvents) + if (MaxEvents != -1 && numEvents >= MaxEvents) { break; } - PSObject outputObj = new PSObject(evtObj); + PSObject outputObj = new(evtObj); string evtMessage = _resourceMgr.GetString("NoEventMessage"); try @@ -924,7 +826,7 @@ private void ReadEvents(EventLogQuery logQuery) if (numEvents == 0) { string msg = _resourceMgr.GetString("NoMatchingEventsFound"); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "NoMatchingEventsFound", ErrorCategory.ObjectNotFound, null)); } } @@ -935,7 +837,7 @@ private void ReadEvents(EventLogQuery logQuery) // private string BuildStructuredQuery(EventLogSession eventLogSession) { - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); switch (ParameterSetName) { @@ -967,7 +869,7 @@ private string BuildStructuredQuery(EventLogSession eventLogSession) if (_logNamesMatchingWildcard.Count > WindowsEventLogAPILimit) { string msg = _resourceMgr.GetString("LogCountLimitExceeded"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, _logNamesMatchingWildcard.Count, WindowsEventLogAPILimit)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, _logNamesMatchingWildcard.Count, WindowsEventLogAPILimit)); ThrowTerminatingError(new ErrorRecord(exc, "LogCountLimitExceeded", ErrorCategory.LimitsExceeded, null)); } @@ -975,7 +877,7 @@ private string BuildStructuredQuery(EventLogSession eventLogSession) uint queryId = 0; foreach (string log in _logNamesMatchingWildcard) { - result.AppendFormat(CultureInfo.InvariantCulture, queryTemplate, new object[] { queryId++, log, _filter }); + result.AppendFormat(CultureInfo.InvariantCulture, queryTemplate, new object[] { queryId++, log, FilterXPath }); } result.Append(queryListClose); @@ -990,7 +892,7 @@ private string BuildStructuredQuery(EventLogSession eventLogSession) foreach (string filePath in _resolvedPaths) { string properFilePath = filePrefix + filePath; - result.AppendFormat(CultureInfo.InvariantCulture, queryTemplate, new object[] { queryId++, properFilePath, _filter }); + result.AppendFormat(CultureInfo.InvariantCulture, queryTemplate, new object[] { queryId++, properFilePath, FilterXPath }); } result.Append(queryListClose); @@ -1017,7 +919,7 @@ private string BuildStructuredQuery(EventLogSession eventLogSession) // private string BuildXPathFromHashTable(Hashtable hash) { - StringBuilder xpathString = new StringBuilder(string.Empty); + StringBuilder xpathString = new(string.Empty); bool bDateTimeHandled = false; foreach (string key in hash.Keys) @@ -1106,13 +1008,13 @@ private string BuildXPathFromHashTable(Hashtable hash) // private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession) { - StringBuilder result = new StringBuilder(string.Empty); + StringBuilder result = new(string.Empty); result.Append(queryListOpen); uint queryId = 0; - foreach (Hashtable hash in _selector) + foreach (Hashtable hash in FilterHashtable) { string xpathString = string.Empty; string xpathStringSuppress = string.Empty; @@ -1123,12 +1025,12 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession // Local queriedLogsQueryMap will hold names of logs or files to be queried // mapped to the actual query strings being built up. // - Dictionary queriedLogsQueryMap = new Dictionary(); + Dictionary queriedLogsQueryMap = new(); // // queriedLogsQueryMapSuppress is the same as queriedLogsQueryMap but for // - Dictionary queriedLogsQueryMapSuppress = new Dictionary(); + Dictionary queriedLogsQueryMapSuppress = new(); // // Process log, _path, or provider parameters first @@ -1139,7 +1041,7 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession // if (hash.ContainsKey(hashkey_logname_lc)) { - List logPatterns = new List(); + List logPatterns = new(); if (hash[hashkey_logname_lc] is Array) { foreach (object elt in (Array)hash[hashkey_logname_lc]) @@ -1194,7 +1096,7 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession if (hash.ContainsKey(hashkey_providername_lc)) { - List provPatterns = new List(); + List provPatterns = new(); if (hash[hashkey_providername_lc] is Array) { foreach (object elt in (Array)hash[hashkey_providername_lc]) @@ -1227,7 +1129,7 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession } else { - List keysList = new List(queriedLogsQueryMap.Keys); + List keysList = new(queriedLogsQueryMap.Keys); bool bRemovedIrrelevantLogs = false; foreach (string queriedLog in keysList) { @@ -1257,7 +1159,7 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession if (bRemovedIrrelevantLogs && (queriedLogsQueryMap.Count == 0)) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("LogsAndProvidersDontOverlap")); - Exception exc = new Exception(msg); + Exception exc = new(msg); WriteError(new ErrorRecord(exc, "LogsAndProvidersDontOverlap", ErrorCategory.InvalidArgument, null)); continue; } @@ -1347,27 +1249,27 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession // HandleEventIdHashValue helper for hashtable structured query builder. // Constructs and returns EventId XPath portion as a string. // - private string HandleEventIdHashValue(object value) + private static string HandleEventIdHashValue(object value) { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new(); Array idsArray = value as Array; if (idsArray != null) { - ret.Append("("); + ret.Append('('); for (int i = 0; i < idsArray.Length; i++) { - ret.Append(SystemEventIDTemplate).Append(idsArray.GetValue(i).ToString()).Append(")"); + ret.Append(SystemEventIDTemplate).Append(idsArray.GetValue(i).ToString()).Append(')'); if (i < (idsArray.Length - 1)) { ret.Append(" or "); } } - ret.Append(")"); + ret.Append(')'); } else { - ret.Append(SystemEventIDTemplate).Append(value).Append(")"); + ret.Append(SystemEventIDTemplate).Append(value).Append(')'); } return ret.ToString(); @@ -1377,27 +1279,27 @@ private string HandleEventIdHashValue(object value) // HandleLevelHashValue helper for hashtable structured query builder. // Constructs and returns Level XPath portion as a string. // - private string HandleLevelHashValue(object value) + private static string HandleLevelHashValue(object value) { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new(); Array levelsArray = value as Array; if (levelsArray != null) { - ret.Append("("); + ret.Append('('); for (int i = 0; i < levelsArray.Length; i++) { - ret.Append(SystemLevelTemplate).Append(levelsArray.GetValue(i).ToString()).Append(")"); + ret.Append(SystemLevelTemplate).Append(levelsArray.GetValue(i).ToString()).Append(')'); if (i < (levelsArray.Length - 1)) { ret.Append(" or "); } } - ret.Append(")"); + ret.Append(')'); } else { - ret.Append(SystemLevelTemplate).Append(value).Append(")"); + ret.Append(SystemLevelTemplate).Append(value).Append(')'); } return ret.ToString(); @@ -1409,8 +1311,8 @@ private string HandleLevelHashValue(object value) // private string HandleKeywordHashValue(object value) { - Int64 keywordsMask = 0; - Int64 keywordLong = 0; + long keywordsMask = 0; + long keywordLong = 0; Array keywordArray = value as Array; if (keywordArray != null) @@ -1458,13 +1360,13 @@ private string HandleContextHashValue(object value) { try { - NTAccount acct = new NTAccount(value.ToString()); + NTAccount acct = new(value.ToString()); sidCandidate = (SecurityIdentifier)acct.Translate(typeof(SecurityIdentifier)); } catch (ArgumentException exc) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("InvalidContext"), value.ToString()); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "InvalidContext", ErrorCategory.InvalidArgument, null)); return string.Empty; } @@ -1480,8 +1382,8 @@ private string HandleContextHashValue(object value) // private string HandleStartTimeHashValue(object value, Hashtable hash) { - StringBuilder ret = new StringBuilder(); - DateTime startTime = new DateTime(); + StringBuilder ret = new(); + DateTime startTime = new(); if (!StringToDateTime(value.ToString(), ref startTime)) { return string.Empty; @@ -1492,7 +1394,7 @@ private string HandleStartTimeHashValue(object value, Hashtable hash) if (hash.ContainsKey(hashkey_endtime_lc)) { - DateTime endTime = new DateTime(); + DateTime endTime = new(); if (!StringToDateTime(hash[hashkey_endtime_lc].ToString(), ref endTime)) { return string.Empty; @@ -1523,8 +1425,8 @@ private string HandleStartTimeHashValue(object value, Hashtable hash) // private string HandleEndTimeHashValue(object value, Hashtable hash) { - StringBuilder ret = new StringBuilder(); - DateTime endTime = new DateTime(); + StringBuilder ret = new(); + DateTime endTime = new(); if (!StringToDateTime(value.ToString(), ref endTime)) { return string.Empty; @@ -1536,7 +1438,7 @@ private string HandleEndTimeHashValue(object value, Hashtable hash) if (hash.ContainsKey(hashkey_starttime_lc)) { - DateTime startTime = new DateTime(); + DateTime startTime = new(); if (!StringToDateTime(hash[hashkey_starttime_lc].ToString(), ref startTime)) { return string.Empty; @@ -1565,13 +1467,13 @@ private string HandleEndTimeHashValue(object value, Hashtable hash) // HandleDataHashValue helper for hashtable structured query builder. // Constructs and returns EventData/Data XPath portion as a string. // - private string HandleDataHashValue(object value) + private static string HandleDataHashValue(object value) { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new(); Array dataArray = value as Array; if (dataArray != null) { - ret.Append("("); + ret.Append('('); for (int i = 0; i < dataArray.Length; i++) { ret.AppendFormat(CultureInfo.InvariantCulture, DataTemplate, dataArray.GetValue(i).ToString()); @@ -1581,7 +1483,7 @@ private string HandleDataHashValue(object value) } } - ret.Append(")"); + ret.Append(')'); } else { @@ -1596,13 +1498,13 @@ private string HandleDataHashValue(object value) // Constructs and returns named event data field XPath portion as a string. // Fix Issue #2327 // - private string HandleNamedDataHashValue(string key, object value) + private static string HandleNamedDataHashValue(string key, object value) { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new(); Array dataArray = value as Array; if (dataArray != null) { - ret.Append("("); + ret.Append('('); for (int i = 0; i < dataArray.Length; i++) { ret.AppendFormat(CultureInfo.InvariantCulture, @@ -1614,7 +1516,7 @@ private string HandleNamedDataHashValue(string key, object value) } } - ret.Append(")"); + ret.Append(')'); } else { @@ -1639,7 +1541,7 @@ private void CheckHashTableForQueryPathPresence(Hashtable hash) if (!isLogHash && !isProviderHash && !isPathHash) { string msg = _resourceMgr.GetString("LogProviderOrPathNeeded"); - Exception exc = new Exception(msg); + Exception exc = new(msg); ThrowTerminatingError(new ErrorRecord(exc, "LogProviderOrPathNeeded", ErrorCategory.InvalidArgument, null)); } } @@ -1655,7 +1557,7 @@ private void TerminateForNonEvtxFileWithoutOldest(string fileName) System.IO.Path.GetExtension(fileName).Equals(".evt", StringComparison.OrdinalIgnoreCase)) { string msg = _resourceMgr.GetString("SpecifyOldestForEtlEvt"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, fileName)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, fileName)); ThrowTerminatingError(new ErrorRecord(exc, "SpecifyOldestForEtlEvt", ErrorCategory.InvalidArgument, fileName)); } } @@ -1675,7 +1577,7 @@ private bool ValidateLogName(string logName, EventLogSession eventLogSession) catch (EventLogNotFoundException) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, _computerName, logName)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, ComputerName, logName)); WriteError(new ErrorRecord(exc, "NoMatchingLogsFound", ErrorCategory.ObjectNotFound, logName)); return false; } @@ -1684,7 +1586,7 @@ private bool ValidateLogName(string logName, EventLogSession eventLogSession) string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("LogInfoUnavailable"), logName, exc.Message); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "LogInfoUnavailable", ErrorCategory.NotSpecified, null)); return false; } @@ -1694,7 +1596,7 @@ private bool ValidateLogName(string logName, EventLogSession eventLogSession) if (logObj.LogType == EventLogType.Debug || logObj.LogType == EventLogType.Analytical) { string msg = _resourceMgr.GetString("SpecifyOldestForLog"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, logName)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, logName)); ThrowTerminatingError(new ErrorRecord(exc, "SpecifyOldestForLog", ErrorCategory.InvalidArgument, logName)); } } @@ -1707,7 +1609,7 @@ private bool ValidateLogName(string logName, EventLogSession eventLogSession) // Returns true and keyLong ref if successful. // Writes an error and returns false if keyString cannot be converted. // - private bool KeywordStringToInt64(string keyString, ref Int64 keyLong) + private bool KeywordStringToInt64(string keyString, ref long keyLong) { try { @@ -1716,7 +1618,7 @@ private bool KeywordStringToInt64(string keyString, ref Int64 keyLong) catch (Exception exc) { string msg = _resourceMgr.GetString("KeywordLongExpected"); - Exception outerExc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, keyString), exc); + Exception outerExc = new(string.Format(CultureInfo.InvariantCulture, msg, keyString), exc); WriteError(new ErrorRecord(outerExc, "KeywordLongExpected", ErrorCategory.InvalidArgument, null)); return false; } @@ -1738,7 +1640,7 @@ private bool StringToDateTime(string dtString, ref DateTime dt) catch (FormatException exc) { string msg = _resourceMgr.GetString("DateTimeExpected"); - Exception outerExc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, dtString), exc); + Exception outerExc = new(string.Format(CultureInfo.InvariantCulture, msg, dtString), exc); WriteError(new ErrorRecord(outerExc, "DateTimeExpected", ErrorCategory.InvalidArgument, null)); return false; } @@ -1754,7 +1656,7 @@ private bool StringToDateTime(string dtString, ref DateTime dt) // private StringCollection ValidateAndResolveFilePath(string path) { - StringCollection retColl = new StringCollection(); + StringCollection retColl = new(); Collection resolvedPathSubset = null; try @@ -1795,7 +1697,7 @@ private StringCollection ValidateAndResolveFilePath(string path) if (pi.Provider.Name != "FileSystem") { string msg = _resourceMgr.GetString("NotAFileSystemPath"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, path)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, path)); WriteError(new ErrorRecord(exc, "NotAFileSystemPath", ErrorCategory.InvalidArgument, path)); continue; } @@ -1812,7 +1714,7 @@ private StringCollection ValidateAndResolveFilePath(string path) if (!WildcardPattern.ContainsWildcardCharacters(path)) { string msg = _resourceMgr.GetString("NotALogFile"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, pi.ProviderPath)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, pi.ProviderPath)); WriteError(new ErrorRecord(exc, "NotALogFile", ErrorCategory.InvalidArgument, path)); } @@ -1834,7 +1736,7 @@ private StringCollection ValidateAndResolveFilePath(string path) // private void CheckHashTablesForNullValues() { - foreach (Hashtable hash in _selector) + foreach (Hashtable hash in FilterHashtable) { foreach (string key in hash.Keys) { @@ -1842,7 +1744,7 @@ private void CheckHashTablesForNullValues() if (value == null) { string msg = _resourceMgr.GetString("NullNotAllowedInHashtable"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, key)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, key)); ThrowTerminatingError(new ErrorRecord(exc, "NullNotAllowedInHashtable", ErrorCategory.InvalidArgument, key)); } else @@ -1855,7 +1757,7 @@ private void CheckHashTablesForNullValues() if (elt == null) { string msg = _resourceMgr.GetString("NullNotAllowedInHashtable"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, key)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, key)); ThrowTerminatingError(new ErrorRecord(exc, "NullNotAllowedInHashtable", ErrorCategory.InvalidArgument, key)); } } @@ -1876,13 +1778,13 @@ private string AddProviderPredicatesToFilter(StringCollection providers) { if (providers.Count == 0) { - return _filter; + return FilterXPath; } - string ret = _filter; + string ret = FilterXPath; string predicate = BuildProvidersPredicate(providers); - if (_filter.Equals("*", StringComparison.OrdinalIgnoreCase)) + if (FilterXPath.Equals("*", StringComparison.OrdinalIgnoreCase)) { ret += "[" + predicate + "]"; } @@ -1891,7 +1793,7 @@ private string AddProviderPredicatesToFilter(StringCollection providers) // // Extend the XPath provided in the _filter // - int lastPredClose = _filter.LastIndexOf(']'); + int lastPredClose = FilterXPath.LastIndexOf(']'); if (lastPredClose == -1) { ret += "[" + predicate + "]"; @@ -1910,24 +1812,24 @@ private string AddProviderPredicatesToFilter(StringCollection providers) // "System/Provider[@Name='a' or @Name='b']" // for all provider names specified in the "providers" argument. // - private string BuildProvidersPredicate(StringCollection providers) + private static string BuildProvidersPredicate(StringCollection providers) { if (providers.Count == 0) { return string.Empty; } - StringBuilder predicate = new StringBuilder("System/Provider["); + StringBuilder predicate = new("System/Provider["); for (int i = 0; i < providers.Count; i++) { - predicate.Append("@Name='").Append(providers[i]).Append("'"); + predicate.Append("@Name='").Append(providers[i]).Append('\''); if (i < (providers.Count - 1)) { predicate.Append(" or "); } } - predicate.Append("]"); + predicate.Append(']'); return predicate.ToString(); } @@ -1946,9 +1848,9 @@ private string BuildAllProvidersPredicate() return string.Empty; } - StringBuilder predicate = new StringBuilder("System/Provider["); + StringBuilder predicate = new("System/Provider["); - List uniqueProviderNames = new List(); + List uniqueProviderNames = new(); foreach (string logKey in _providersByLogMap.Keys) { @@ -1964,14 +1866,14 @@ private string BuildAllProvidersPredicate() for (int i = 0; i < uniqueProviderNames.Count; i++) { - predicate.Append("@Name='").Append(uniqueProviderNames[i]).Append("'"); + predicate.Append("@Name='").Append(uniqueProviderNames[i]).Append('\''); if (i < uniqueProviderNames.Count - 1) { predicate.Append(" or "); } } - predicate.Append("]"); + predicate.Append(']'); return predicate.ToString(); } @@ -1987,7 +1889,7 @@ private void AddLogsForProviderToInternalMap(EventLogSession eventLogSession, st { try { - ProviderMetadata providerMetadata = new ProviderMetadata(providerName, eventLogSession, CultureInfo.CurrentCulture); + ProviderMetadata providerMetadata = new(providerName, eventLogSession, CultureInfo.CurrentCulture); System.Collections.IEnumerable logLinks = providerMetadata.LogLinks; @@ -1999,7 +1901,7 @@ private void AddLogsForProviderToInternalMap(EventLogSession eventLogSession, st // Skip direct ETW channels unless -force is present. // Error out for direct channels unless -oldest is present. // - EventLogConfiguration logObj = new EventLogConfiguration(logLink.LogName, eventLogSession); + EventLogConfiguration logObj = new(logLink.LogName, eventLogSession); if (logObj.LogType == EventLogType.Debug || logObj.LogType == EventLogType.Analytical) { if (!Force.IsPresent) @@ -2012,7 +1914,7 @@ private void AddLogsForProviderToInternalMap(EventLogSession eventLogSession, st WriteVerbose(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderLogLink"), providerName, logLink.LogName)); - StringCollection provColl = new StringCollection(); + StringCollection provColl = new(); provColl.Add(providerName.ToLowerInvariant()); _providersByLogMap.Add(logLink.LogName.ToLowerInvariant(), provColl); @@ -2038,7 +1940,7 @@ private void AddLogsForProviderToInternalMap(EventLogSession eventLogSession, st string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderMetadataUnavailable"), providerName, exc.Message); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "ProviderMetadataUnavailable", ErrorCategory.NotSpecified, null)); return; } @@ -2064,7 +1966,7 @@ private void FindLogNamesMatchingWildcards(EventLogSession eventLogSession, IEnu foreach (string logPattern in logPatterns) { bool bMatched = false; - WildcardPattern wildLogPattern = new WildcardPattern(logPattern, WildcardOptions.IgnoreCase); + WildcardPattern wildLogPattern = new(logPattern, WildcardOptions.IgnoreCase); foreach (string actualLogName in eventLogSession.GetLogNames()) { @@ -2087,7 +1989,7 @@ private void FindLogNamesMatchingWildcards(EventLogSession eventLogSession, IEnu string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("LogInfoUnavailable"), actualLogName, exc.Message); - Exception outerExc = new Exception(msg, exc); + Exception outerExc = new(msg, exc); WriteError(new ErrorRecord(outerExc, "LogInfoUnavailable", ErrorCategory.NotSpecified, null)); continue; } @@ -2114,7 +2016,7 @@ private void FindLogNamesMatchingWildcards(EventLogSession eventLogSession, IEnu if (!bMatched) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, _computerName, logPattern)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, ComputerName, logPattern)); WriteError(new ErrorRecord(exc, "NoMatchingLogsFound", ErrorCategory.ObjectNotFound, logPattern)); } } @@ -2133,7 +2035,7 @@ private void FindProvidersByLogForWildcardPatterns(EventLogSession eventLogSessi foreach (string provPattern in providerPatterns) { bool bMatched = false; - WildcardPattern wildProvPattern = new WildcardPattern(provPattern, WildcardOptions.IgnoreCase); + WildcardPattern wildProvPattern = new(provPattern, WildcardOptions.IgnoreCase); foreach (string provName in eventLogSession.GetProviderNames()) { @@ -2151,11 +2053,10 @@ private void FindProvidersByLogForWildcardPatterns(EventLogSession eventLogSessi if (!bMatched) { string msg = _resourceMgr.GetString("NoMatchingProvidersFound"); - Exception exc = new Exception(string.Format(CultureInfo.InvariantCulture, msg, _computerName, provPattern)); + Exception exc = new(string.Format(CultureInfo.InvariantCulture, msg, ComputerName, provPattern)); WriteError(new ErrorRecord(exc, "NoMatchingProvidersFound", ErrorCategory.ObjectNotFound, provPattern)); } } } } } - diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs index 216e9bca7ea..cb74c292a3e 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs @@ -9,16 +9,15 @@ using System.Globalization; using System.IO; using System.Management.Automation; -using System.Reflection; using System.Resources; using System.Xml; namespace Microsoft.PowerShell.Commands { - /// + /// /// Class that implements the New-WinEvent cmdlet. /// This cmdlet writes a new Etw event using the provider specified in parameter. - /// + /// [Cmdlet(VerbsCommon.New, "WinEvent", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096808")] public sealed class NewWinEventCommand : PSCmdlet { @@ -28,7 +27,7 @@ public sealed class NewWinEventCommand : PSCmdlet private const string TemplateTag = "template"; private const string DataTag = "data"; - private ResourceManager _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager(); + private readonly ResourceManager _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager(); /// /// ProviderName. @@ -37,20 +36,7 @@ public sealed class NewWinEventCommand : PSCmdlet Position = 0, Mandatory = true, ParameterSetName = ParameterAttribute.AllParameterSets)] - public string ProviderName - { - get - { - return _providerName; - } - - set - { - _providerName = value; - } - } - - private string _providerName; + public string ProviderName { get; set; } /// /// Id (EventId defined in manifest file) @@ -110,20 +96,7 @@ public byte Version SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Target = "Microsoft.PowerShell.Commands", Justification = "A string[] is required here because that is the type Powershell supports")] - public object[] Payload - { - get - { - return _payload; - } - - set - { - _payload = value; - } - } - - private object[] _payload; + public object[] Payload { get; set; } /// /// BeginProcessing. @@ -138,16 +111,16 @@ protected override void BeginProcessing() private void LoadProvider() { - if (string.IsNullOrEmpty(_providerName)) + if (string.IsNullOrEmpty(ProviderName)) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderNotSpecified")), "ProviderName"); } - using (EventLogSession session = new EventLogSession()) + using (EventLogSession session = new()) { foreach (string providerName in session.GetProviderNames()) { - if (string.Equals(providerName, _providerName, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(providerName, ProviderName, StringComparison.OrdinalIgnoreCase)) { try { @@ -166,7 +139,7 @@ private void LoadProvider() if (_providerMetadata == null) { - string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoProviderFound"), _providerName); + string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoProviderFound"), ProviderName); throw new ArgumentException(msg); } } @@ -175,7 +148,7 @@ private void LoadEventDescriptor() { if (_idSpecified) { - List matchedEvents = new List(); + List matchedEvents = new(); foreach (EventMetadata emd in _providerMetadata.Events) { if (emd.Id == _id) @@ -189,7 +162,7 @@ private void LoadEventDescriptor() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("IncorrectEventId"), _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -217,7 +190,7 @@ private void LoadEventDescriptor() _resourceMgr.GetString("IncorrectEventVersion"), _version, _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -227,7 +200,7 @@ private void LoadEventDescriptor() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("VersionNotSpecified"), _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -246,7 +219,7 @@ private bool VerifyTemplate(EventMetadata emd) { if (emd.Template != null) { - XmlReaderSettings readerSettings = new XmlReaderSettings + XmlReaderSettings readerSettings = new() { CheckCharacters = false, IgnoreComments = true, @@ -270,8 +243,8 @@ private bool VerifyTemplate(EventMetadata emd) } } - if ((_payload == null && definedParameterCount != 0) - || ((_payload != null) && _payload.Length != definedParameterCount)) + if ((Payload == null && definedParameterCount != 0) + || ((Payload != null) && Payload.Length != definedParameterCount)) { string warning = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("PayloadMismatch"), _id, emd.Template); WriteWarning(warning); @@ -314,25 +287,25 @@ private static EventDescriptor CreateEventDescriptor(ProviderMetadata providerMe /// protected override void ProcessRecord() { - using (EventProvider provider = new EventProvider(_providerMetadata.Id)) + using (EventProvider provider = new(_providerMetadata.Id)) { EventDescriptor ed = _eventDescriptor.Value; - if (_payload != null && _payload.Length > 0) + if (Payload != null && Payload.Length > 0) { - for (int i = 0; i < _payload.Length; i++) + for (int i = 0; i < Payload.Length; i++) { - if (_payload[i] == null) + if (Payload[i] == null) { - _payload[i] = string.Empty; + Payload[i] = string.Empty; } } - provider.WriteEvent(ref ed, _payload); + provider.WriteEvent(in ed, Payload); } else { - provider.WriteEvent(ref ed); + provider.WriteEvent(in ed); } } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/PdhHelper.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/PdhHelper.cs index 1e703d66219..97eff22db0d 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/PdhHelper.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/PdhHelper.cs @@ -2,13 +2,11 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; using Microsoft.PowerShell.Commands.GetCounter; using Microsoft.Win32; @@ -227,7 +225,7 @@ private struct PDH_FMT_COUNTERVALUE_LARGE // [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)] // public string WideStringValue; - }; + } [StructLayout(LayoutKind.Sequential)] private struct PDH_FMT_COUNTERVALUE_DOUBLE @@ -235,7 +233,7 @@ private struct PDH_FMT_COUNTERVALUE_DOUBLE public uint CStatus; public double doubleValue; - }; + } [StructLayout(LayoutKind.Sequential)] private struct PDH_FMT_COUNTERVALUE_UNICODE @@ -244,7 +242,7 @@ private struct PDH_FMT_COUNTERVALUE_UNICODE [MarshalAs(UnmanagedType.LPWStr)] public string WideStringValue; - }; + } [StructLayout(LayoutKind.Sequential)] private struct PDH_RAW_COUNTER @@ -375,7 +373,7 @@ private static extern uint PdhExpandWildCardPathH(PdhSafeDataSourceHandle hDataS private static extern uint PdhValidatePath(string szFullPathBuffer); [DllImport("pdh.dll", CharSet = CharSet.Unicode)] - private static extern uint PdhGetCounterInfo(IntPtr hCounter, [MarshalAs(UnmanagedType.U1)]bool bRetrieveExplainText, ref IntPtr pdwBufferSize, IntPtr lpBuffer); + private static extern uint PdhGetCounterInfo(IntPtr hCounter, [MarshalAs(UnmanagedType.U1)] bool bRetrieveExplainText, ref IntPtr pdwBufferSize, IntPtr lpBuffer); [DllImport("pdh.dll", CharSet = CharSet.Unicode)] private static extern uint PdhGetCounterTimeBase(IntPtr hCounter, out UInt64 pTimeBase); @@ -423,7 +421,7 @@ public void Dispose() // // m_ConsumerPathToHandleAndInstanceMap map is used for reading counter date (live or from files). // - private Dictionary _consumerPathToHandleAndInstanceMap = new Dictionary(); + private readonly Dictionary _consumerPathToHandleAndInstanceMap = new(); /// /// A helper reading in a Unicode string with embedded NULLs and splitting it into a StringCollection. @@ -431,7 +429,7 @@ public void Dispose() /// /// /// - private void ReadPdhMultiString(ref IntPtr strNative, Int32 strSize, ref StringCollection strColl) + private static void ReadPdhMultiString(ref IntPtr strNative, Int32 strSize, ref StringCollection strColl) { Debug.Assert(strSize >= 2); int offset = 0; @@ -454,17 +452,16 @@ private void ReadPdhMultiString(ref IntPtr strNative, Int32 strSize, ref StringC strColl.AddRange(allSubstringsWithNulls.Split('\0')); } - private uint GetCounterInfoPlus(IntPtr hCounter, out UInt32 counterType, out UInt32 defaultScale, out UInt64 timeBase) + private static uint GetCounterInfoPlus(IntPtr hCounter, out UInt32 counterType, out UInt32 defaultScale, out UInt64 timeBase) { - uint res = 0; counterType = 0; defaultScale = 0; timeBase = 0; Debug.Assert(hCounter != IntPtr.Zero); - IntPtr pBufferSize = new IntPtr(0); - res = PdhGetCounterInfo(hCounter, false, ref pBufferSize, IntPtr.Zero); + IntPtr pBufferSize = new(0); + uint res = PdhGetCounterInfo(hCounter, false, ref pBufferSize, IntPtr.Zero); if (res != PdhResults.PDH_MORE_DATA) { return res; @@ -476,7 +473,7 @@ private uint GetCounterInfoPlus(IntPtr hCounter, out UInt32 counterType, out UIn try { res = PdhGetCounterInfo(hCounter, false, ref pBufferSize, bufCounterInfo); - if (res == 0 && bufCounterInfo != IntPtr.Zero) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA && bufCounterInfo != IntPtr.Zero) { PDH_COUNTER_INFO pdhCounterInfo = (PDH_COUNTER_INFO)Marshal.PtrToStructure(bufCounterInfo, typeof(PDH_COUNTER_INFO)); counterType = pdhCounterInfo.dwType; @@ -489,7 +486,7 @@ private uint GetCounterInfoPlus(IntPtr hCounter, out UInt32 counterType, out UIn } res = PdhGetCounterTimeBase(hCounter, out timeBase); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -505,13 +502,13 @@ public uint ConnectToDataSource() } uint res = PdhHelper.PdhBindInputDataSource(out _hDataSource, null); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine("error in PdhBindInputDataSource: " + res); return res; } - return 0; + return PdhResults.PDH_CSTATUS_VALID_DATA; } /// /// Connects to a single named datasource, initializing m_hDataSource variable. @@ -526,7 +523,7 @@ public uint ConnectToDataSource(string dataSourceName) } uint res = PdhHelper.PdhBindInputDataSource(out _hDataSource, dataSourceName); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine("error in PdhBindInputDataSource: " + res); } @@ -556,7 +553,7 @@ public uint OpenQuery() { uint res = PdhOpenQueryH(_hDataSource, IntPtr.Zero, out _hQuery); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine("error in PdhOpenQueryH: " + res); } @@ -588,7 +585,7 @@ public uint SetQueryTimeRange(DateTime startTime, DateTime endTime) Debug.Assert(_hQuery != null); Debug.Assert(endTime >= startTime); - PDH_TIME_INFO pTimeInfo = new PDH_TIME_INFO(); + PDH_TIME_INFO pTimeInfo = new(); if (startTime != DateTime.MinValue && startTime.Kind == DateTimeKind.Local) { @@ -611,7 +608,7 @@ public uint SetQueryTimeRange(DateTime startTime, DateTime endTime) public uint EnumBlgFilesMachines(ref StringCollection machineNames) { - IntPtr MachineListTcharSizePtr = new IntPtr(0); + IntPtr MachineListTcharSizePtr = new(0); uint res = PdhHelper.PdhEnumMachinesH(_hDataSource, IntPtr.Zero, ref MachineListTcharSizePtr); if (res != PdhResults.PDH_MORE_DATA) { @@ -624,7 +621,7 @@ public uint EnumBlgFilesMachines(ref StringCollection machineNames) try { res = PdhHelper.PdhEnumMachinesH(_hDataSource, (IntPtr)strMachineList, ref MachineListTcharSizePtr); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { ReadPdhMultiString(ref strMachineList, MachineListTcharSizePtr.ToInt32(), ref machineNames); } @@ -639,7 +636,7 @@ public uint EnumBlgFilesMachines(ref StringCollection machineNames) public uint EnumObjects(string machineName, ref StringCollection objectNames) { - IntPtr pBufferSize = new IntPtr(0); + IntPtr pBufferSize = new(0); uint res = PdhEnumObjectsH(_hDataSource, machineName, IntPtr.Zero, ref pBufferSize, PerfDetail.PERF_DETAIL_WIZARD, false); if (res != PdhResults.PDH_MORE_DATA) { @@ -652,7 +649,7 @@ public uint EnumObjects(string machineName, ref StringCollection objectNames) try { res = PdhEnumObjectsH(_hDataSource, machineName, (IntPtr)strObjectList, ref pBufferSize, PerfDetail.PERF_DETAIL_WIZARD, false); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { ReadPdhMultiString(ref strObjectList, pBufferSize.ToInt32(), ref objectNames); } @@ -667,8 +664,8 @@ public uint EnumObjects(string machineName, ref StringCollection objectNames) public uint EnumObjectItems(string machineName, string objectName, ref StringCollection counterNames, ref StringCollection instanceNames) { - IntPtr pCounterBufferSize = new IntPtr(0); - IntPtr pInstanceBufferSize = new IntPtr(0); + IntPtr pCounterBufferSize = new(0); + IntPtr pInstanceBufferSize = new(0); uint res = PdhEnumObjectItemsH(_hDataSource, machineName, objectName, IntPtr.Zero, ref pCounterBufferSize, @@ -677,12 +674,12 @@ public uint EnumObjectItems(string machineName, string objectName, ref StringCol if (res == PdhResults.PDH_CSTATUS_NO_INSTANCE) { instanceNames.Clear(); - return 0; // masking the error + return PdhResults.PDH_CSTATUS_VALID_DATA; // masking the error } else if (res == PdhResults.PDH_CSTATUS_NO_OBJECT) { counterNames.Clear(); - return 0; // masking the error + return PdhResults.PDH_CSTATUS_VALID_DATA; // masking the error } else if (res != PdhResults.PDH_MORE_DATA) { @@ -715,7 +712,7 @@ public uint EnumObjectItems(string machineName, string objectName, ref StringCol strCountersList, ref pCounterBufferSize, strInstancesList, ref pInstanceBufferSize, PerfDetail.PERF_DETAIL_WIZARD, 0); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine("error in PdhEnumObjectItemsH 2nd call: " + res + "\n Counter buffer size is " // + pCounterBufferSize.ToInt32() + "\n Instance buffer size is " + pInstanceBufferSize.ToInt32()); @@ -749,18 +746,18 @@ public uint GetValidPathsFromFiles(ref StringCollection validPaths) { Debug.Assert(_hDataSource != null && !_hDataSource.IsInvalid, "Call ConnectToDataSource before GetValidPathsFromFiles"); - StringCollection machineNames = new StringCollection(); + StringCollection machineNames = new(); uint res = this.EnumBlgFilesMachines(ref machineNames); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } foreach (string machine in machineNames) { - StringCollection counterSets = new StringCollection(); + StringCollection counterSets = new(); res = this.EnumObjects(machine, ref counterSets); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -769,17 +766,17 @@ public uint GetValidPathsFromFiles(ref StringCollection validPaths) { // Console.WriteLine("Counter set " + counterSet); - StringCollection counterSetCounters = new StringCollection(); - StringCollection counterSetInstances = new StringCollection(); + StringCollection counterSetCounters = new(); + StringCollection counterSetInstances = new(); res = this.EnumObjectItems(machine, counterSet, ref counterSetCounters, ref counterSetInstances); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } res = this.GetValidPaths(machine, counterSet, ref counterSetCounters, ref counterSetInstances, ref validPaths); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -793,7 +790,7 @@ private bool IsPathValid(ref PDH_COUNTER_PATH_ELEMENTS pathElts, out string outP { bool ret = false; outPath = string.Empty; - IntPtr pPathBufferSize = new IntPtr(0); + IntPtr pPathBufferSize = new(0); uint res = PdhMakeCounterPath(ref pathElts, IntPtr.Zero, ref pPathBufferSize, 0); if (res != PdhResults.PDH_MORE_DATA) @@ -807,11 +804,11 @@ private bool IsPathValid(ref PDH_COUNTER_PATH_ELEMENTS pathElts, out string outP try { res = PdhMakeCounterPath(ref pathElts, strPath, ref pPathBufferSize, 0); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { outPath = Marshal.PtrToStringUni(strPath); - ret = (PdhValidatePathEx(_hDataSource, outPath) == 0); + ret = (PdhValidatePathEx(_hDataSource, outPath) == PdhResults.PDH_CSTATUS_VALID_DATA); } } finally @@ -824,13 +821,13 @@ private bool IsPathValid(ref PDH_COUNTER_PATH_ELEMENTS pathElts, out string outP public bool IsPathValid(string path) { - return (PdhValidatePathEx(_hDataSource, path) == 0); + return (PdhValidatePathEx(_hDataSource, path) == PdhResults.PDH_CSTATUS_VALID_DATA); } - private uint MakePath(PDH_COUNTER_PATH_ELEMENTS pathElts, out string outPath, bool bWildcardInstances) + private static uint MakePath(PDH_COUNTER_PATH_ELEMENTS pathElts, out string outPath, bool bWildcardInstances) { outPath = string.Empty; - IntPtr pPathBufferSize = new IntPtr(0); + IntPtr pPathBufferSize = new(0); if (bWildcardInstances) { @@ -851,7 +848,7 @@ private uint MakePath(PDH_COUNTER_PATH_ELEMENTS pathElts, out string outPath, bo try { res = PdhMakeCounterPath(ref pathElts, strPath, ref pPathBufferSize, 0); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { outPath = Marshal.PtrToStringUni(strPath); } @@ -864,14 +861,14 @@ private uint MakePath(PDH_COUNTER_PATH_ELEMENTS pathElts, out string outPath, bo return res; } - private uint MakeAllInstancePath(string origPath, out string unifiedPath) + private static uint MakeAllInstancePath(string origPath, out string unifiedPath) { unifiedPath = origPath; - PDH_COUNTER_PATH_ELEMENTS elts = new PDH_COUNTER_PATH_ELEMENTS(); + PDH_COUNTER_PATH_ELEMENTS elts = new(); uint res = ParsePath(origPath, ref elts); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -879,15 +876,15 @@ private uint MakeAllInstancePath(string origPath, out string unifiedPath) return MakePath(elts, out unifiedPath, true); } - private uint ParsePath(string fullPath, ref PDH_COUNTER_PATH_ELEMENTS pCounterPathElements) + private static uint ParsePath(string fullPath, ref PDH_COUNTER_PATH_ELEMENTS pCounterPathElements) { - IntPtr bufSize = new IntPtr(0); + IntPtr bufSize = new(0); uint res = PdhParseCounterPath(fullPath, IntPtr.Zero, ref bufSize, 0); - if (res != PdhResults.PDH_MORE_DATA && res != 0) + if (res != PdhResults.PDH_MORE_DATA && res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine("error in PdhParseCounterPath: " + res); return res; @@ -901,7 +898,7 @@ private uint ParsePath(string fullPath, ref PDH_COUNTER_PATH_ELEMENTS pCounterPa structPtr, ref bufSize, 0); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { // // Marshal.PtrToStructure will allocate managed memory for the object, @@ -932,11 +929,11 @@ private uint ParsePath(string fullPath, ref PDH_COUNTER_PATH_ELEMENTS pCounterPa // public uint TranslateLocalCounterPath(string englishPath, out string localizedPath) { - uint res = 0; + uint res = PdhResults.PDH_CSTATUS_VALID_DATA; localizedPath = string.Empty; - PDH_COUNTER_PATH_ELEMENTS pathElts = new PDH_COUNTER_PATH_ELEMENTS(); + PDH_COUNTER_PATH_ELEMENTS pathElts = new(); res = ParsePath(englishPath, ref pathElts); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -996,7 +993,7 @@ public uint TranslateLocalCounterPath(string englishPath, out string localizedPa // Now, call retrieve the localized names of the object and the counter by index: string objNameLocalized; res = LookupPerfNameByIndex(pathElts.MachineName, (uint)objIndex, out objNameLocalized); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -1005,7 +1002,7 @@ public uint TranslateLocalCounterPath(string englishPath, out string localizedPa string ctrNameLocalized; res = LookupPerfNameByIndex(pathElts.MachineName, (uint)counterIndex, out ctrNameLocalized); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { return res; } @@ -1030,7 +1027,7 @@ public uint LookupPerfNameByIndex(string machineName, uint index, out string loc int strSize = 256; IntPtr localizedPathPtr = Marshal.AllocHGlobal(strSize * sizeof(char)); locName = string.Empty; - uint res = 0; + uint res; try { res = PdhLookupPerfNameByIndex(machineName, index, localizedPathPtr, ref strSize); @@ -1041,7 +1038,7 @@ public uint LookupPerfNameByIndex(string machineName, uint index, out string loc res = PdhLookupPerfNameByIndex(machineName, index, localizedPathPtr, ref strSize); } - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { locName = Marshal.PtrToStringUni(localizedPathPtr); } @@ -1060,9 +1057,7 @@ public uint GetValidPaths(string machineName, ref StringCollection instances, ref StringCollection validPaths) { - uint res = 0; - - PDH_COUNTER_PATH_ELEMENTS pathElts = new PDH_COUNTER_PATH_ELEMENTS(); + PDH_COUNTER_PATH_ELEMENTS pathElts = new(); pathElts.MachineName = machineName; pathElts.ObjectName = objectName; @@ -1094,7 +1089,7 @@ public uint GetValidPaths(string machineName, } } - return res; + return PdhResults.PDH_CSTATUS_VALID_DATA; } public uint AddCounters(ref StringCollection validPaths, bool bFlushOldCounters) @@ -1107,21 +1102,21 @@ public uint AddCounters(ref StringCollection validPaths, bool bFlushOldCounters) } bool bAtLeastOneAdded = false; - uint res = 0; + uint res = PdhResults.PDH_CSTATUS_VALID_DATA; foreach (string counterPath in validPaths) { IntPtr counterHandle; res = PdhAddCounter(_hQuery, counterPath, IntPtr.Zero, out counterHandle); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { - CounterHandleNInstance chi = new CounterHandleNInstance(); + CounterHandleNInstance chi = new(); chi.hCounter = counterHandle; chi.InstanceName = null; - PDH_COUNTER_PATH_ELEMENTS pathElts = new PDH_COUNTER_PATH_ELEMENTS(); + PDH_COUNTER_PATH_ELEMENTS pathElts = new(); res = ParsePath(counterPath, ref pathElts); - if (res == 0 && pathElts.InstanceName != null) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA && pathElts.InstanceName != null) { chi.InstanceName = pathElts.InstanceName.ToLowerInvariant(); } @@ -1135,7 +1130,7 @@ public uint AddCounters(ref StringCollection validPaths, bool bFlushOldCounters) } } - return bAtLeastOneAdded ? 0 : res; + return bAtLeastOneAdded ? PdhResults.PDH_CSTATUS_VALID_DATA : res; } public string GetCounterSetHelp(string szMachineName, string szObjectName) @@ -1148,7 +1143,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi { Debug.Assert(_hQuery != null && !_hQuery.IsInvalid); - uint res = 0; + uint res = PdhResults.PDH_CSTATUS_VALID_DATA; nextSet = null; Int64 batchTimeStampFT = 0; @@ -1159,7 +1154,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi return res; } - if (res != 0 && res != PdhResults.PDH_NO_DATA) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA && res != PdhResults.PDH_NO_DATA) { return res; } @@ -1179,11 +1174,11 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi PerformanceCounterSample[] samplesArr = new PerformanceCounterSample[_consumerPathToHandleAndInstanceMap.Count]; uint sampleIndex = 0; uint numInvalidDataSamples = 0; - uint lastErr = 0; + uint lastErr = PdhResults.PDH_CSTATUS_VALID_DATA; foreach (string path in _consumerPathToHandleAndInstanceMap.Keys) { - IntPtr counterTypePtr = new IntPtr(0); + IntPtr counterTypePtr = new(0); UInt32 counterType = (UInt32)PerformanceCounterType.RawBase; UInt32 defaultScale = 0; UInt64 timeBase = 0; @@ -1192,14 +1187,14 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi Debug.Assert(hCounter != IntPtr.Zero); res = GetCounterInfoPlus(hCounter, out counterType, out defaultScale, out timeBase); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { // Console.WriteLine ("GetCounterInfoPlus for " + path + " failed with " + res); } PDH_RAW_COUNTER rawValue; res = PdhGetRawCounterValue(hCounter, out counterTypePtr, out rawValue); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { samplesArr[sampleIndex++] = new PerformanceCounterSample(path, _consumerPathToHandleAndInstanceMap[path].InstanceName, @@ -1212,7 +1207,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi timeBase, batchStamp, (UInt64)batchStamp.ToFileTime(), - (rawValue.CStatus == 0) ? res : rawValue.CStatus); + (rawValue.CStatus == PdhResults.PDH_CSTATUS_VALID_DATA) ? res : rawValue.CStatus); numInvalidDataSamples++; lastErr = res; @@ -1222,14 +1217,14 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi long dtFT = (((long)rawValue.TimeStamp.dwHighDateTime) << 32) + (uint)rawValue.TimeStamp.dwLowDateTime; - DateTime dt = new DateTime(DateTime.FromFileTimeUtc(dtFT).Ticks, DateTimeKind.Local); + DateTime dt = new(DateTime.FromFileTimeUtc(dtFT).Ticks, DateTimeKind.Local); PDH_FMT_COUNTERVALUE_DOUBLE fmtValueDouble; res = PdhGetFormattedCounterValue(hCounter, PdhFormat.PDH_FMT_DOUBLE | PdhFormat.PDH_FMT_NOCAP100, out counterTypePtr, out fmtValueDouble); - if (res != 0) + if (res != PdhResults.PDH_CSTATUS_VALID_DATA) { samplesArr[sampleIndex++] = new PerformanceCounterSample(path, _consumerPathToHandleAndInstanceMap[path].InstanceName, @@ -1242,7 +1237,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi timeBase, dt, (UInt64)dtFT, - (fmtValueDouble.CStatus == 0) ? res : rawValue.CStatus); + (fmtValueDouble.CStatus == PdhResults.PDH_CSTATUS_VALID_DATA) ? res : rawValue.CStatus); numInvalidDataSamples++; lastErr = res; @@ -1275,7 +1270,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi // // Reset the error - any errors are saved per sample in PerformanceCounterSample.Status for kvetching later // - res = 0; + res = PdhResults.PDH_CSTATUS_VALID_DATA; } return res; @@ -1284,7 +1279,7 @@ public uint ReadNextSet(out PerformanceCounterSampleSet nextSet, bool bSkipReadi public uint ExpandWildCardPath(string path, out StringCollection expandedPaths) { expandedPaths = new StringCollection(); - IntPtr pcchPathListLength = new IntPtr(0); + IntPtr pcchPathListLength = new(0); uint res = PdhExpandWildCardPathH(_hDataSource, path, @@ -1303,7 +1298,7 @@ public uint ExpandWildCardPath(string path, out StringCollection expandedPaths) try { res = PdhExpandWildCardPathH(_hDataSource, path, strPathList, ref pcchPathListLength, PdhWildCardFlag.PDH_REFRESHCOUNTERS); - if (res == 0) + if (res == PdhResults.PDH_CSTATUS_VALID_DATA) { ReadPdhMultiString(ref strPathList, pcchPathListLength.ToInt32(), ref expandedPaths); } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/PdhSafeHandle.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/PdhSafeHandle.cs index 14607db670d..2fc58cc00e1 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/PdhSafeHandle.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/PdhSafeHandle.cs @@ -4,8 +4,6 @@ using System; using System.Runtime.InteropServices; -using System.Runtime.ConstrainedExecution; - namespace Microsoft.Powershell.Commands.GetCounter.PdhNative { internal sealed class PdhSafeDataSourceHandle : SafeHandle diff --git a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj index 88727c9d96c..7ab8ecf2825 100644 --- a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj +++ b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs index 9ad44f3a07f..0ec77a18d26 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs @@ -75,16 +75,14 @@ protected virtual void Dispose(bool disposing) [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] protected TSession[] Session { - get { return _session ?? (_session = new TSession[] { this.DefaultSession }); } + get + { + return _session ??= new TSession[] { this.DefaultSession }; + } set { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - _session = value; + _session = value ?? throw new ArgumentNullException(nameof(value)); _sessionWasSpecified = true; } } @@ -126,9 +124,9 @@ public SwitchParameter AsJob /// Doing so will interfere with ThrottleLimit functionality. /// /// - /// (and other methods returning job results) will block to support throttling and flow-control. + /// (and other methods returning job results) will block to support throttling and flow-control. /// Implementations of Job instance returned from this method should make sure that implementation-specific flow-control mechanism pauses further processing, - /// until calls from (and other methods returning job results) return. + /// until calls from (and other methods returning job results) return. /// /// internal abstract StartableJob CreateQueryJob(TSession session, QueryBuilder query); @@ -151,14 +149,15 @@ private StartableJob DoCreateQueryJob(TSession sessionForJob, QueryBuilder query discardNonPipelineResults, actionAgainstResults == null ? (Action)null - : delegate (PSObject pso) - { - var objectInstance = - (TObjectInstance) - LanguagePrimitives.ConvertTo(pso, typeof(TObjectInstance), - CultureInfo.InvariantCulture); - actionAgainstResults(sessionForJob, objectInstance); - }); + : ((PSObject pso) => + { + var objectInstance = + (TObjectInstance)LanguagePrimitives.ConvertTo( + pso, + typeof(TObjectInstance), + CultureInfo.InvariantCulture); + actionAgainstResults(sessionForJob, objectInstance); + })); } return queryJob; @@ -170,16 +169,16 @@ private StartableJob DoCreateQueryJob(TSession sessionForJob, QueryBuilder query /// Remote session to invoke the method in. /// The object on which to invoke the method. /// Method invocation details. - /// true if successful method invocations should emit downstream the being operated on. + /// if successful method invocations should emit downstream the being operated on. /// /// /// This method shouldn't do any processing or interact with the remote session. /// Doing so will interfere with ThrottleLimit functionality. /// /// - /// (and other methods returning job results) will block to support throttling and flow-control. + /// (and other methods returning job results) will block to support throttling and flow-control. /// Implementations of Job instance returned from this method should make sure that implementation-specific flow-control mechanism pauses further processing, - /// until calls from (and other methods returning job results) return. + /// until calls from (and other methods returning job results) return. /// /// internal abstract StartableJob CreateInstanceMethodInvocationJob(TSession session, TObjectInstance objectInstance, MethodInvocationInfo methodInvocationInfo, bool passThru); @@ -212,9 +211,9 @@ private StartableJob DoCreateInstanceMethodInvocationJob(TSession sessionForJob, /// Doing so will interfere with ThrottleLimit functionality. /// /// - /// (and other methods returning job results) will block to support throttling and flow-control. + /// (and other methods returning job results) will block to support throttling and flow-control. /// Implementations of Job instance returned from this method should make sure that implementation-specific flow-control mechanism pauses further processing, - /// until calls from (and other methods returning job results) return. + /// until calls from (and other methods returning job results) return. /// /// internal abstract StartableJob CreateStaticMethodInvocationJob(TSession session, MethodInvocationInfo methodInvocationInfo); @@ -236,24 +235,21 @@ private StartableJob DoCreateStaticMethodInvocationJob(TSession sessionForJob, M return methodInvocationJob; } - private void HandleJobOutput(Job job, TSession sessionForJob, bool discardNonPipelineResults, Action outputAction) + private static void HandleJobOutput(Job job, TSession sessionForJob, bool discardNonPipelineResults, Action outputAction) { Action processOutput = - delegate (PSObject pso) + (PSObject pso) => { if (pso == null) { return; } - if (outputAction != null) - { - outputAction(pso); - } + outputAction?.Invoke(pso); }; job.Output.DataAdded += - delegate (object sender, DataAddedEventArgs eventArgs) + (object sender, DataAddedEventArgs eventArgs) => { var dataCollection = (PSDataCollection)sender; @@ -303,7 +299,7 @@ internal virtual TSession GetSessionOfOriginFromInstance(TObjectInstance instanc private static void DiscardJobOutputs(PSDataCollection psDataCollection) { psDataCollection.DataAdded += - delegate (object sender, DataAddedEventArgs e) + (object sender, DataAddedEventArgs e) => { var localDataCollection = (PSDataCollection)sender; localDataCollection.Clear(); @@ -327,37 +323,37 @@ private enum JobOutputs private static void DiscardJobOutputs(Job job, JobOutputs jobOutputsToDiscard) { - if (JobOutputs.Output == (jobOutputsToDiscard & JobOutputs.Output)) + if ((jobOutputsToDiscard & JobOutputs.Output) == JobOutputs.Output) { DiscardJobOutputs(job.Output); } - if (JobOutputs.Error == (jobOutputsToDiscard & JobOutputs.Error)) + if ((jobOutputsToDiscard & JobOutputs.Error) == JobOutputs.Error) { DiscardJobOutputs(job.Error); } - if (JobOutputs.Warning == (jobOutputsToDiscard & JobOutputs.Warning)) + if ((jobOutputsToDiscard & JobOutputs.Warning) == JobOutputs.Warning) { DiscardJobOutputs(job.Warning); } - if (JobOutputs.Verbose == (jobOutputsToDiscard & JobOutputs.Verbose)) + if ((jobOutputsToDiscard & JobOutputs.Verbose) == JobOutputs.Verbose) { DiscardJobOutputs(job.Verbose); } - if (JobOutputs.Debug == (jobOutputsToDiscard & JobOutputs.Debug)) + if ((jobOutputsToDiscard & JobOutputs.Debug) == JobOutputs.Debug) { DiscardJobOutputs(job.Debug); } - if (JobOutputs.Progress == (jobOutputsToDiscard & JobOutputs.Progress)) + if ((jobOutputsToDiscard & JobOutputs.Progress) == JobOutputs.Progress) { DiscardJobOutputs(job.Progress); } - if (JobOutputs.Results == (jobOutputsToDiscard & JobOutputs.Results)) + if ((jobOutputsToDiscard & JobOutputs.Results) == JobOutputs.Results) { DiscardJobOutputs(job.Results); } @@ -399,7 +395,7 @@ public override void ProcessRecord(QueryBuilder query) /// /// Query parameters. /// Method invocation details. - /// true if successful method invocations should emit downstream the object instance being operated on. + /// if successful method invocations should emit downstream the object instance being operated on. public override void ProcessRecord(QueryBuilder query, MethodInvocationInfo methodInvocationInfo, bool passThru) { _parentJob.DisableFlowControlForPendingJobsQueue(); @@ -412,7 +408,7 @@ public override void ProcessRecord(QueryBuilder query, MethodInvocationInfo meth StartableJob queryJob = this.DoCreateQueryJob( sessionForJob, query, - delegate (TSession sessionForMethodInvocationJob, TObjectInstance objectInstance) + (TSession sessionForMethodInvocationJob, TObjectInstance objectInstance) => { StartableJob methodInvocationJob = this.DoCreateInstanceMethodInvocationJob( sessionForMethodInvocationJob, @@ -578,7 +574,7 @@ private TSession GetImpliedSession() /// /// The object on which to invoke the method. /// Method invocation details. - /// true if successful method invocations should emit downstream the being operated on. + /// if successful method invocations should emit downstream the being operated on. public override void ProcessRecord(TObjectInstance objectInstance, MethodInvocationInfo methodInvocationInfo, bool passThru) { if (objectInstance == null) throw new ArgumentNullException(nameof(objectInstance)); diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CimJobException.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CimJobException.cs index 092103d6fe7..0ffa5bdf98f 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CimJobException.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CimJobException.cs @@ -90,7 +90,7 @@ internal static CimJobException CreateFromCimException( Dbg.Assert(cimException != null, "Caller should verify cimException != null"); string message = BuildErrorMessage(jobDescription, jobContext, cimException.Message); - CimJobException cimJobException = new CimJobException(message, cimException); + CimJobException cimJobException = new(message, cimException); cimJobException.InitializeErrorRecord(jobContext, cimException); return cimJobException; } @@ -111,7 +111,7 @@ internal static CimJobException CreateFromAnyException( } string message = BuildErrorMessage(jobDescription, jobContext, inner.Message); - CimJobException cimJobException = new CimJobException(message, inner); + CimJobException cimJobException = new(message, inner); var containsErrorRecord = inner as IContainsErrorRecord; if (containsErrorRecord != null) { @@ -142,7 +142,7 @@ internal static CimJobException CreateWithFullControl( Dbg.Assert(!string.IsNullOrEmpty(message), "Caller should verify message != null"); Dbg.Assert(!string.IsNullOrEmpty(errorId), "Caller should verify errorId != null"); - CimJobException cimJobException = new CimJobException(jobContext.PrependComputerNameToMessage(message), inner); + CimJobException cimJobException = new(jobContext.PrependComputerNameToMessage(message), inner); cimJobException.InitializeErrorRecord(jobContext, errorId, errorCategory); return cimJobException; } @@ -156,7 +156,7 @@ internal static CimJobException CreateWithoutJobContext( Dbg.Assert(!string.IsNullOrEmpty(message), "Caller should verify message != null"); Dbg.Assert(!string.IsNullOrEmpty(errorId), "Caller should verify errorId != null"); - CimJobException cimJobException = new CimJobException(message, inner); + CimJobException cimJobException = new(message, inner); cimJobException.InitializeErrorRecord(null, errorId, errorCategory); return cimJobException; } @@ -170,7 +170,7 @@ internal static CimJobException CreateFromMethodErrorCode(string jobDescription, string errorMessage = BuildErrorMessage(jobDescription, jobContext, rawErrorMessage); - CimJobException cje = new CimJobException(errorMessage); + CimJobException cje = new(errorMessage); cje.InitializeErrorRecord(jobContext, "CimJob_" + methodName + "_" + errorCodeFromMethod, ErrorCategory.InvalidResult); return cje; @@ -197,15 +197,15 @@ private static string BuildErrorMessage(string jobDescription, CimJobContext job private void InitializeErrorRecordCore(CimJobContext jobContext, Exception exception, string errorId, ErrorCategory errorCategory) { - ErrorRecord coreErrorRecord = new ErrorRecord( + ErrorRecord coreErrorRecord = new( exception: exception, errorId: errorId, errorCategory: errorCategory, - targetObject: jobContext != null ? jobContext.TargetObject : null); + targetObject: jobContext?.TargetObject); if (jobContext != null) { - System.Management.Automation.Remoting.OriginInfo originInfo = new System.Management.Automation.Remoting.OriginInfo( + System.Management.Automation.Remoting.OriginInfo originInfo = new( jobContext.Session.ComputerName, Guid.Empty); @@ -242,7 +242,7 @@ private void InitializeErrorRecord(CimJobContext jobContext, CimException cimExc if (cimException.ErrorData != null) { _errorRecord.CategoryInfo.TargetName = cimException.ErrorSource; - _errorRecord.CategoryInfo.TargetType = jobContext != null ? jobContext.CmdletizationClassName : null; + _errorRecord.CategoryInfo.TargetType = jobContext?.CmdletizationClassName; } } @@ -374,7 +374,7 @@ internal bool IsTerminatingError return false; } - UInt16 perceivedSeverityValue = (UInt16)perceivedSeverityProperty.Value; + ushort perceivedSeverityValue = (ushort)perceivedSeverityProperty.Value; if (perceivedSeverityValue != 7) { /* from CIM Schema: Interop\CIM_Error.mof: diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CreateInstanceJob.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CreateInstanceJob.cs index 7f76ff98574..d8a1bdd44ea 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CreateInstanceJob.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/CreateInstanceJob.cs @@ -67,8 +67,8 @@ internal override IObservable GetCimOperation() } #if DEBUG - Dbg.Assert(_getInstanceOperationGotStarted == false, "CreateInstance should be started *before* GetInstance"); - Dbg.Assert(_createInstanceOperationGotStarted == false, "Should not start CreateInstance operation twice"); + Dbg.Assert(!_getInstanceOperationGotStarted, "CreateInstance should be started *before* GetInstance"); + Dbg.Assert(!_createInstanceOperationGotStarted, "Should not start CreateInstance operation twice"); _createInstanceOperationGotStarted = true; #endif return GetCreateInstanceOperation(); @@ -77,7 +77,7 @@ internal override IObservable GetCimOperation() { #if DEBUG Dbg.Assert(_createInstanceOperationGotStarted, "GetInstance should be started *after* CreateInstance"); - Dbg.Assert(_getInstanceOperationGotStarted == false, "Should not start GetInstance operation twice"); + Dbg.Assert(!_getInstanceOperationGotStarted, "Should not start GetInstance operation twice"); Dbg.Assert(_resultFromGetInstance == null, "GetInstance operation shouldn't happen twice"); _getInstanceOperationGotStarted = true; #endif diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/ExtrinsicMethodInvocationJob.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/ExtrinsicMethodInvocationJob.cs index 3a8b0e2200c..9aa254212a6 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/ExtrinsicMethodInvocationJob.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/ExtrinsicMethodInvocationJob.cs @@ -52,16 +52,16 @@ private void ProcessOutParameter(CimMethodResult methodResult, MethodParameter m { Dbg.Assert(methodResult != null, "Caller should verify methodResult != null"); Dbg.Assert(methodParameter != null, "Caller should verify methodParameter != null"); - Dbg.Assert(0 != (methodParameter.Bindings & (MethodParameterBindings.Out | MethodParameterBindings.Error)), "Caller should verify that this is an out parameter"); + Dbg.Assert((methodParameter.Bindings & (MethodParameterBindings.Out | MethodParameterBindings.Error)) != 0, "Caller should verify that this is an out parameter"); Dbg.Assert(cmdletOutput != null, "Caller should verify cmdletOutput != null"); Dbg.Assert(this.MethodSubject != null, "MethodSubject property should be initialized before starting main job processing"); CimMethodParameter outParameter = methodResult.OutParameters[methodParameter.Name]; - object valueReturnedFromMethod = (outParameter == null) ? null : outParameter.Value; + object valueReturnedFromMethod = outParameter?.Value; object dotNetValue = CimValueConverter.ConvertFromCimToDotNet(valueReturnedFromMethod, methodParameter.ParameterType); - if (MethodParameterBindings.Out == (methodParameter.Bindings & MethodParameterBindings.Out)) + if ((methodParameter.Bindings & MethodParameterBindings.Out) == MethodParameterBindings.Out) { methodParameter.Value = dotNetValue; cmdletOutput.Add(methodParameter.Name, methodParameter); @@ -81,7 +81,7 @@ private void ProcessOutParameter(CimMethodResult methodResult, MethodParameter m CimCmdletAdapter.AssociateSessionOfOriginWithInstance(cimInstance, this.JobContext.Session); } } - else if (MethodParameterBindings.Error == (methodParameter.Bindings & MethodParameterBindings.Error)) + else if ((methodParameter.Bindings & MethodParameterBindings.Error) == MethodParameterBindings.Error) { var gotError = (bool)LanguagePrimitives.ConvertTo(dotNetValue, typeof(bool), CultureInfo.InvariantCulture); if (gotError) @@ -105,7 +105,7 @@ private void OnNext(CimMethodResult methodResult) if (cmdletOutput.Count == 1) { - var singleOutputParameter = cmdletOutput.Values.Single(); + var singleOutputParameter = cmdletOutput.Values.First(); if (singleOutputParameter.Value == null) { return; diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/MethodInvocationJobBase.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/MethodInvocationJobBase.cs index 075e218ea60..84b13b82097 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/MethodInvocationJobBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/MethodInvocationJobBase.cs @@ -66,8 +66,8 @@ private IEnumerable GetMethodInputParametersCore(Func GetMethodInputParameters() { - var allMethodParameters = this.GetMethodInputParametersCore(p => !p.Name.StartsWith(CustomOperationOptionPrefix, StringComparison.OrdinalIgnoreCase)); - var methodParametersWithInputValue = allMethodParameters.Where(p => p.IsValuePresent); + var allMethodParameters = this.GetMethodInputParametersCore(static p => !p.Name.StartsWith(CustomOperationOptionPrefix, StringComparison.OrdinalIgnoreCase)); + var methodParametersWithInputValue = allMethodParameters.Where(static p => p.IsValuePresent); return methodParametersWithInputValue; } @@ -81,7 +81,7 @@ internal override CimCustomOptionsDictionary CalculateJobSpecificCustomOptions() IDictionary result = new Dictionary(StringComparer.OrdinalIgnoreCase); IEnumerable customOptions = this - .GetMethodInputParametersCore(p => p.Name.StartsWith(CustomOperationOptionPrefix, StringComparison.OrdinalIgnoreCase)); + .GetMethodInputParametersCore(static p => p.Name.StartsWith(CustomOperationOptionPrefix, StringComparison.OrdinalIgnoreCase)); foreach (MethodParameter customOption in customOptions) { if (customOption.Value == null) @@ -104,7 +104,7 @@ internal IEnumerable GetMethodOutputParameters() } var outParameters = allParameters_plus_returnValue - .Where(p => (0 != (p.Bindings & (MethodParameterBindings.Out | MethodParameterBindings.Error)))); + .Where(static p => ((p.Bindings & (MethodParameterBindings.Out | MethodParameterBindings.Error)) != 0)); return outParameters; } diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJob.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJob.cs index 4297c00616c..7c7a82ee9ca 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJob.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJob.cs @@ -27,7 +27,7 @@ internal QueryInstancesJob(CimJobContext jobContext, CimQuery cimQuery, string w var wqlQueryBuilder = new StringBuilder(); wqlQueryBuilder.Append("SELECT * FROM "); wqlQueryBuilder.Append(this.JobContext.ClassName); - wqlQueryBuilder.Append(" "); + wqlQueryBuilder.Append(' '); wqlQueryBuilder.Append(wqlCondition); _wqlQuery = wqlQueryBuilder.ToString(); diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJobBase.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJobBase.cs index 8ee336de383..b52c23c3dd4 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJobBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/QueryJobBase.cs @@ -14,7 +14,7 @@ namespace Microsoft.PowerShell.Cmdletization.Cim /// internal abstract class QueryJobBase : CimChildJobBase { - private CimQuery _cimQuery; + private readonly CimQuery _cimQuery; internal QueryJobBase(CimJobContext jobContext, CimQuery cimQuery) : base(jobContext) diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/TerminatingErrorTracker.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/TerminatingErrorTracker.cs index 730e54a6391..deb3a0ff103 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/TerminatingErrorTracker.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/TerminatingErrorTracker.cs @@ -19,12 +19,12 @@ namespace Microsoft.PowerShell.Cmdletization.Cim /// /// Tracks (per-session) terminating errors in a given cmdlet invocation. /// - internal class TerminatingErrorTracker + internal sealed class TerminatingErrorTracker { #region Getting tracker for a given cmdlet invocation private static readonly ConditionalWeakTable s_invocationToTracker = - new ConditionalWeakTable(); + new(); private static int GetNumberOfSessions(InvocationInfo invocationInfo) { @@ -100,7 +100,7 @@ private TerminatingErrorTracker(int numberOfSessions) #region Tracking session's "connectivity" status - private readonly ConcurrentDictionary _sessionToIsConnected = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _sessionToIsConnected = new(); internal void MarkSessionAsConnected(CimSession connectedSession) { @@ -166,7 +166,7 @@ internal Exception GetExceptionIfBrokenSession( #region Tracking session's "terminated" status - private readonly ConcurrentDictionary _sessionToIsTerminated = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _sessionToIsTerminated = new(); internal void MarkSessionAsTerminated(CimSession terminatedSession, out bool sessionWasAlreadyTerminated) { @@ -175,11 +175,11 @@ internal void MarkSessionAsTerminated(CimSession terminatedSession, out bool ses key: terminatedSession, addValue: true, updateValueFactory: - delegate (CimSession key, bool isTerminatedValueInDictionary) - { - closureSafeSessionWasAlreadyTerminated = isTerminatedValueInDictionary; - return true; - }); + (CimSession key, bool isTerminatedValueInDictionary) => + { + closureSafeSessionWasAlreadyTerminated = isTerminatedValueInDictionary; + return true; + }); sessionWasAlreadyTerminated = closureSafeSessionWasAlreadyTerminated; } @@ -196,22 +196,22 @@ internal bool IsSessionTerminated(CimSession session) internal CmdletMethodInvoker GetErrorReportingDelegate(ErrorRecord errorRecord) { - ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim(); - object lockObject = new object(); - Func action = delegate (Cmdlet cmdlet) - { - _numberOfReportedSessionTerminatingErrors++; - if (_numberOfReportedSessionTerminatingErrors >= _numberOfSessions) - { - cmdlet.ThrowTerminatingError(errorRecord); - } - else - { - cmdlet.WriteError(errorRecord); - } - - return false; // not really needed here, but required by CmdletMethodInvoker - }; + ManualResetEventSlim manualResetEventSlim = new(); + object lockObject = new(); + Func action = (Cmdlet cmdlet) => + { + _numberOfReportedSessionTerminatingErrors++; + if (_numberOfReportedSessionTerminatingErrors >= _numberOfSessions) + { + cmdlet.ThrowTerminatingError(errorRecord); + } + else + { + cmdlet.WriteError(errorRecord); + } + + return false; // not really needed here, but required by CmdletMethodInvoker + }; return new CmdletMethodInvoker { diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimChildJobBase.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimChildJobBase.cs index f23c74c142c..cb4786f005e 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimChildJobBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimChildJobBase.cs @@ -57,7 +57,7 @@ internal CimChildJobBase(CimJobContext jobContext) _jobSpecificCustomOptions = new Lazy(this.CalculateJobSpecificCustomOptions); } - private readonly CimSensitiveValueConverter _cimSensitiveValueConverter = new CimSensitiveValueConverter(); + private readonly CimSensitiveValueConverter _cimSensitiveValueConverter = new(); internal CimSensitiveValueConverter CimSensitiveValueConverter { get { return _cimSensitiveValueConverter; } } @@ -84,8 +84,7 @@ private enum WsManErrorCode : uint private static bool IsWsManQuotaReached(Exception exception) { - var cimException = exception as CimException; - if (cimException == null) + if (!(exception is CimException cimException)) { return false; } @@ -112,7 +111,7 @@ private static bool IsWsManQuotaReached(Exception exception) return false; } - WsManErrorCode wsManErrorCode = (WsManErrorCode)(UInt32)(errorCodeProperty.Value); + WsManErrorCode wsManErrorCode = (WsManErrorCode)(uint)(errorCodeProperty.Value); switch (wsManErrorCode) // error codes that should result in sleep-and-retry are based on an email from Ryan { case WsManErrorCode.ERROR_WSMAN_QUOTA_MAX_SHELLS: @@ -159,7 +158,7 @@ public virtual void OnCompleted() }); } - private static readonly Random s_globalRandom = new Random(); + private static readonly Random s_globalRandom = new(); private readonly Random _random; private int _sleepAndRetryDelayRangeMs = 1000; private int _sleepAndRetryExtraDelayMs = 0; @@ -424,11 +423,11 @@ internal CimOperationOptions CreateOperationOptions() (_jobContext.WarningActionPreference == ActionPreference.Ignore) ) && (!_jobContext.IsRunningInBackground)) { - operationOptions.DisableChannel((UInt32)MessageChannel.Warning); + operationOptions.DisableChannel((uint)MessageChannel.Warning); } else { - operationOptions.EnableChannel((UInt32)MessageChannel.Warning); + operationOptions.EnableChannel((uint)MessageChannel.Warning); } if (( @@ -436,11 +435,11 @@ internal CimOperationOptions CreateOperationOptions() (_jobContext.VerboseActionPreference == ActionPreference.Ignore) ) && (!_jobContext.IsRunningInBackground)) { - operationOptions.DisableChannel((UInt32)MessageChannel.Verbose); + operationOptions.DisableChannel((uint)MessageChannel.Verbose); } else { - operationOptions.EnableChannel((UInt32)MessageChannel.Verbose); + operationOptions.EnableChannel((uint)MessageChannel.Verbose); } if (( @@ -448,11 +447,11 @@ internal CimOperationOptions CreateOperationOptions() (_jobContext.DebugActionPreference == ActionPreference.Ignore) ) && (!_jobContext.IsRunningInBackground)) { - operationOptions.DisableChannel((UInt32)MessageChannel.Debug); + operationOptions.DisableChannel((uint)MessageChannel.Debug); } else { - operationOptions.EnableChannel((UInt32)MessageChannel.Debug); + operationOptions.EnableChannel((uint)MessageChannel.Debug); } switch (this.JobContext.ShouldProcessOptimization) @@ -544,7 +543,7 @@ private CimCustomOptionsDictionary GetJobSpecificCustomOptions() #region Controlling job state - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancellationTokenSource = new(); /// /// Stops this job. @@ -579,7 +578,7 @@ public override void StopJob() _cancellationTokenSource.Cancel(); } - private readonly object _jobStateLock = new object(); + private readonly object _jobStateLock = new(); private bool _jobHadErrors; private bool _jobWasStarted; private bool _jobWasStopped; @@ -731,7 +730,7 @@ internal void SetCompletedJobState(JobState state, Exception reason) #region Support for progress reporting - private readonly ConcurrentDictionary _activityIdToLastProgressRecord = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _activityIdToLastProgressRecord = new(); internal override void WriteProgress(ProgressRecord progressRecord) { @@ -764,7 +763,7 @@ internal void FinishProgressReporting() #region Handling extended semantics callbacks - private void WriteProgressCallback(string activity, string currentOperation, string statusDescription, UInt32 percentageCompleted, UInt32 secondsRemaining) + private void WriteProgressCallback(string activity, string currentOperation, string statusDescription, uint percentageCompleted, uint secondsRemaining) { if (string.IsNullOrEmpty(activity)) { @@ -776,28 +775,28 @@ private void WriteProgressCallback(string activity, string currentOperation, str statusDescription = this.StatusMessage; } - Int32 signedSecondsRemaining; - if (secondsRemaining == UInt32.MaxValue) + int signedSecondsRemaining; + if (secondsRemaining == uint.MaxValue) { signedSecondsRemaining = -1; } - else if (secondsRemaining <= Int32.MaxValue) + else if (secondsRemaining <= int.MaxValue) { - signedSecondsRemaining = (Int32)secondsRemaining; + signedSecondsRemaining = (int)secondsRemaining; } else { - signedSecondsRemaining = Int32.MaxValue; + signedSecondsRemaining = int.MaxValue; } - Int32 signedPercentageComplete; - if (percentageCompleted == UInt32.MaxValue) + int signedPercentageComplete; + if (percentageCompleted == uint.MaxValue) { signedPercentageComplete = -1; } else if (percentageCompleted <= 100) { - signedPercentageComplete = (Int32)percentageCompleted; + signedPercentageComplete = (int)percentageCompleted; } else { @@ -826,7 +825,7 @@ private enum MessageChannel Debug = 2, } - private void WriteMessageCallback(UInt32 channel, string message) + private void WriteMessageCallback(uint channel, string message) { this.ExceptionSafeWrapper( delegate @@ -1010,8 +1009,7 @@ private CimResponseType PromptUserCallback(string message, CimPromptType promptT internal static bool IsShowComputerNameMarkerPresent(CimInstance cimInstance) { PSObject pso = PSObject.AsPSObject(cimInstance); - PSPropertyInfo psShowComputerNameProperty = pso.InstanceMembers[RemotingConstants.ShowComputerNameNoteProperty] as PSPropertyInfo; - if (psShowComputerNameProperty == null) + if (!(pso.InstanceMembers[RemotingConstants.ShowComputerNameNoteProperty] is PSPropertyInfo psShowComputerNameProperty)) { return false; } diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimCmdletInvocationContext.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimCmdletInvocationContext.cs index dd7b6ad8d7d..c876184c141 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimCmdletInvocationContext.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimCmdletInvocationContext.cs @@ -76,7 +76,7 @@ private static void WarnAboutUnsupportedActionPreferences( if (actionPreferenceComesFromCommandLineParameter) { Exception exception = new ArgumentException(message); - ErrorRecord errorRecord = new ErrorRecord(exception, "ActionPreferenceNotSupportedByCimCmdletAdapter", ErrorCategory.NotImplemented, null); + ErrorRecord errorRecord = new(exception, "ActionPreferenceNotSupportedByCimCmdletAdapter", ErrorCategory.NotImplemented, null); cmdlet.ThrowTerminatingError(errorRecord); } } @@ -113,7 +113,7 @@ public bool ShowComputerName } } - private readonly Lazy _defaultCimSession = new Lazy(CreateDefaultCimSession); + private readonly Lazy _defaultCimSession = new(CreateDefaultCimSession); private static CimSession CreateDefaultCimSession() { diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimConverter.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimConverter.cs index 033b8813534..74f0f922cc5 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimConverter.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimConverter.cs @@ -26,7 +26,7 @@ namespace Microsoft.PowerShell.Cim { internal class CimSensitiveValueConverter : IDisposable { - private class SensitiveString : IDisposable + private sealed class SensitiveString : IDisposable { private GCHandle _gcHandle; private string _string; @@ -129,7 +129,7 @@ private void Dispose(bool disposing) } } - private readonly List _trackedDisposables = new List(); + private readonly List _trackedDisposables = new(); /// /// Releases resources associated with this object. @@ -399,21 +399,21 @@ internal static object ConvertFromCimToDotNet(object cimObject, Type expectedDot return dotNetObject; } - Func, object> exceptionSafeReturn = delegate (Func innerAction) - { - try - { - return innerAction(); - } - catch (Exception e) - { - throw CimValueConverter.GetInvalidCastException( - e, - "InvalidCimToDotNetCast", - cimObject, - expectedDotNetType.FullName); - } - }; + Func, object> exceptionSafeReturn = (Func innerAction) => + { + try + { + return innerAction(); + } + catch (Exception e) + { + throw CimValueConverter.GetInvalidCastException( + e, + "InvalidCimToDotNetCast", + cimObject, + expectedDotNetType.FullName); + } + }; if (typeof(ObjectSecurity).IsAssignableFrom(expectedDotNetType)) { diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimOperationOptionsHelper.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimOperationOptionsHelper.cs index 17801923bf0..34c708b5f4c 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimOperationOptionsHelper.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimOperationOptionsHelper.cs @@ -14,10 +14,10 @@ namespace Microsoft.PowerShell.Cmdletization.Cim { - internal class CimCustomOptionsDictionary + internal sealed class CimCustomOptionsDictionary { private readonly IDictionary _dict; - private readonly object _dictModificationLock = new object(); + private readonly object _dictModificationLock = new(); private CimCustomOptionsDictionary(IEnumerable> wrappedDictionary) { @@ -42,7 +42,7 @@ internal static CimCustomOptionsDictionary Create(IEnumerable s_cimInstanceToCustomOptions = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable s_cimInstanceToCustomOptions = new(); internal static void AssociateCimInstanceWithCustomOptions(CimInstance cimInstance, CimCustomOptionsDictionary newCustomOptions) { diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimQuery.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimQuery.cs index 34b1cc8ba54..d2e920b7f9d 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimQuery.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimQuery.cs @@ -27,7 +27,7 @@ internal class CimQuery : QueryBuilder, ISessionBoundQueryBuilder private string _resultRole; private string _sourceRole; - internal readonly Dictionary queryOptions = new Dictionary(StringComparer.OrdinalIgnoreCase); + internal readonly Dictionary queryOptions = new(StringComparer.OrdinalIgnoreCase); internal ClientSideQuery ClientSideQuery { get; } @@ -177,7 +177,7 @@ private static string GetMatchCondition(string propertyName, IEnumerable propert .Select(propertyValue => wildcardsEnabled ? GetMatchConditionForLikeOperator(propertyName, propertyValue) : GetMatchConditionForEqualityOperator(propertyName, propertyValue)) - .Where(individualCondition => !string.IsNullOrWhiteSpace(individualCondition)) + .Where(static individualCondition => !string.IsNullOrWhiteSpace(individualCondition)) .ToList(); if (individualConditions.Count == 0) { @@ -196,8 +196,8 @@ private static string GetMatchCondition(string propertyName, IEnumerable propert /// Property name to query on. /// Property values to accept in the query. /// - /// true if should be treated as a containing a wildcard pattern; - /// false otherwise + /// if should be treated as a containing a wildcard pattern; + /// otherwise. /// /// /// Describes how to handle filters that didn't match any objects @@ -219,8 +219,8 @@ public override void FilterByProperty(string propertyName, IEnumerable allowedPr /// Property name to query on. /// Property values to reject in the query. /// - /// true if should be treated as a containing a wildcard pattern; - /// false otherwise + /// if should be treated as a containing a wildcard pattern; + /// otherwise. /// /// /// Describes how to handle filters that didn't match any objects diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimWrapper.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimWrapper.cs index a667e6da2f5..7052b16c768 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimWrapper.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimWrapper.cs @@ -94,11 +94,10 @@ internal CimCmdletInvocationContext CmdletInvocationContext { get { - return _cmdletInvocationContext ?? - (_cmdletInvocationContext = new CimCmdletInvocationContext( - this.CmdletDefinitionContext, - this.Cmdlet, - this.GetDynamicNamespace())); + return _cmdletInvocationContext ??= new CimCmdletInvocationContext( + this.CmdletDefinitionContext, + this.Cmdlet, + this.GetDynamicNamespace()); } } @@ -172,8 +171,7 @@ private CimJobContext CreateJobContext(CimSession session, object targetObject) /// object that performs a query against the wrapped object model. internal override StartableJob CreateQueryJob(CimSession session, QueryBuilder baseQuery) { - CimQuery query = baseQuery as CimQuery; - if (query == null) + if (!(baseQuery is CimQuery query)) { throw new ArgumentNullException(nameof(baseQuery)); } @@ -201,7 +199,7 @@ internal override StartableJob CreateQueryJob(CimSession session, QueryBuilder b /// Remote session to invoke the method in. /// The object on which to invoke the method. /// Method invocation details. - /// true if successful method invocations should emit downstream the being operated on. + /// if successful method invocations should emit downstream the being operated on. /// internal override StartableJob CreateInstanceMethodInvocationJob(CimSession session, CimInstance objectInstance, MethodInvocationInfo methodInvocationInfo, bool passThru) { @@ -283,7 +281,7 @@ private bool IsSupportedSession(CimSession cimSession, TerminatingErrorTracker t cimSession.ComputerName, nameOfUnsupportedSwitch); Exception exception = new NotSupportedException(errorMessage); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( exception, "NoExtendedSemanticsSupportInRemoteDcomProtocol", ErrorCategory.NotImplemented, @@ -340,7 +338,7 @@ internal override StartableJob CreateStaticMethodInvocationJob(CimSession sessio #region Session affinity management - private static readonly ConditionalWeakTable s_cimInstanceToSessionOfOrigin = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable s_cimInstanceToSessionOfOrigin = new(); internal static void AssociateSessionOfOriginWithInstance(CimInstance cimInstance, CimSession sessionOfOrigin) { @@ -396,10 +394,10 @@ object IDynamicParameters.GetDynamicParameters() if (this.CmdletDefinitionContext.ExposeCimNamespaceParameter) { - Collection namespaceAttributes = new Collection(); + Collection namespaceAttributes = new(); namespaceAttributes.Add(new ValidateNotNullOrEmptyAttribute()); namespaceAttributes.Add(new ParameterAttribute()); - RuntimeDefinedParameter namespaceRuntimeParameter = new RuntimeDefinedParameter( + RuntimeDefinedParameter namespaceRuntimeParameter = new( CimNamespaceParameter, typeof(string), namespaceAttributes); diff --git a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/clientSideQuery.cs b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/clientSideQuery.cs index dc94df195e2..731007eb618 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/clientSideQuery.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/clientSideQuery.cs @@ -153,7 +153,7 @@ public virtual IEnumerable GetNotFoundErrors_IfThisIsTheOnlyFilte private abstract class CimInstancePropertyBasedFilter : CimInstanceFilterBase { - private readonly List _propertyValueFilters = new List(); + private readonly List _propertyValueFilters = new(); protected IEnumerable PropertyValueFilters { get { return _propertyValueFilters; } } @@ -181,7 +181,7 @@ protected override bool IsMatchCore(CimInstance cimInstance) } } - private class CimInstanceRegularFilter : CimInstancePropertyBasedFilter + private sealed class CimInstanceRegularFilter : CimInstancePropertyBasedFilter { public CimInstanceRegularFilter(string propertyName, IEnumerable allowedPropertyValues, bool wildcardsEnabled, BehaviorOnNoMatch behaviorOnNoMatch) { @@ -202,7 +202,7 @@ public CimInstanceRegularFilter(string propertyName, IEnumerable allowedProperty if (valueBehaviors.Count == 1) { - this.BehaviorOnNoMatch = valueBehaviors.Single(); + this.BehaviorOnNoMatch = valueBehaviors.First(); } else { @@ -223,7 +223,7 @@ public override bool ShouldReportErrorOnNoMatches_IfMultipleFilters() case BehaviorOnNoMatch.Default: default: return this.PropertyValueFilters - .Any(f => !f.HadMatch && f.BehaviorOnNoMatch == BehaviorOnNoMatch.ReportErrors); + .Any(static f => !f.HadMatch && f.BehaviorOnNoMatch == BehaviorOnNoMatch.ReportErrors); } } @@ -247,7 +247,7 @@ public override IEnumerable GetNotFoundErrors_IfThisIsTheOnlyFilt } } - private class CimInstanceExcludeFilter : CimInstancePropertyBasedFilter + private sealed class CimInstanceExcludeFilter : CimInstancePropertyBasedFilter { public CimInstanceExcludeFilter(string propertyName, IEnumerable excludedPropertyValues, bool wildcardsEnabled, BehaviorOnNoMatch behaviorOnNoMatch) { @@ -272,7 +272,7 @@ public CimInstanceExcludeFilter(string propertyName, IEnumerable excludedPropert } } - private class CimInstanceMinFilter : CimInstancePropertyBasedFilter + private sealed class CimInstanceMinFilter : CimInstancePropertyBasedFilter { public CimInstanceMinFilter(string propertyName, object minPropertyValue, BehaviorOnNoMatch behaviorOnNoMatch) { @@ -293,7 +293,7 @@ public CimInstanceMinFilter(string propertyName, object minPropertyValue, Behavi } } - private class CimInstanceMaxFilter : CimInstancePropertyBasedFilter + private sealed class CimInstanceMaxFilter : CimInstancePropertyBasedFilter { public CimInstanceMaxFilter(string propertyName, object minPropertyValue, BehaviorOnNoMatch behaviorOnNoMatch) { @@ -314,7 +314,7 @@ public CimInstanceMaxFilter(string propertyName, object minPropertyValue, Behavi } } - private class CimInstanceAssociationFilter : CimInstanceFilterBase + private sealed class CimInstanceAssociationFilter : CimInstanceFilterBase { public CimInstanceAssociationFilter(BehaviorOnNoMatch behaviorOnNoMatch) { @@ -572,8 +572,7 @@ private static bool ActualValueGreaterThanOrEqualToExpectedValue(string property { try { - var expectedComparable = expectedPropertyValue as IComparable; - if (expectedComparable == null) + if (!(expectedPropertyValue is IComparable expectedComparable)) { return false; } @@ -608,8 +607,7 @@ private static bool ActualValueLessThanOrEqualToExpectedValue(string propertyNam { try { - var actualComparable = actualPropertyValue as IComparable; - if (actualComparable == null) + if (!(actualPropertyValue is IComparable actualComparable)) { return false; } @@ -626,8 +624,8 @@ private static bool ActualValueLessThanOrEqualToExpectedValue(string propertyNam private int _numberOfResultsFromMi; private int _numberOfMatchingResults; - private readonly List _filters = new List(); - private readonly object _myLock = new object(); + private readonly List _filters = new(); + private readonly object _myLock = new(); #region "Public" interface for client-side filtering @@ -658,7 +656,7 @@ internal IEnumerable GenerateNotFoundErrors() return Enumerable.Empty(); } - if (_filters.All(f => !f.ShouldReportErrorOnNoMatches_IfMultipleFilters())) + if (_filters.All(static f => !f.ShouldReportErrorOnNoMatches_IfMultipleFilters())) { return Enumerable.Empty(); } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/AddContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/AddContentCommand.cs index af8efbd6885..0f9762084d5 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/AddContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/AddContentCommand.cs @@ -6,8 +6,6 @@ using System.Management.Automation; using System.Management.Automation.Internal; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -42,7 +40,7 @@ internal override void SeekContentPosition(List contentHolders) catch (Exception e) // Catch-all OK, 3rd party callout { ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderSeekError", SessionStateStrings.ProviderSeekError, holder.PathInfo.Provider, @@ -84,4 +82,3 @@ internal override bool CallShouldProcess(string path) #endregion protected members } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/CIMHelper.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/CIMHelper.cs index 559af13127b..1b10bbfe7ab 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/CIMHelper.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/CIMHelper.cs @@ -85,8 +85,8 @@ internal static string WqlQueryAll(string from) try { var type = typeof(T); - var binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - T rv = new T(); + const BindingFlags binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + T rv = new(); using (var instance = session.QueryFirstInstance(nameSpace, CIMHelper.WqlQueryAll(wmiClassName))) { @@ -144,11 +144,11 @@ internal static string WqlQueryAll(string from) if (instances != null) { var type = typeof(T); - var binding = BindingFlags.Public | BindingFlags.Instance; + const BindingFlags binding = BindingFlags.Public | BindingFlags.Instance; foreach (var instance in instances) { - T objT = new T(); + T objT = new(); using (instance) { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearContentCommand.cs index 61726686f28..bd6ba2ee726 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearContentCommand.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -101,4 +99,3 @@ internal override object GetDynamicParameters(CmdletProviderContext context) } } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearPropertyCommand.cs index 75ee9a639e3..f63eb8eed91 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearPropertyCommand.cs @@ -4,8 +4,6 @@ using System.Collections.ObjectModel; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -86,7 +84,7 @@ public string Name /// internal override object GetDynamicParameters(CmdletProviderContext context) { - Collection propertyCollection = new Collection(); + Collection propertyCollection = new(); propertyCollection.Add(_property); if (Path != null && Path.Length > 0) @@ -126,7 +124,7 @@ protected override void ProcessRecord() CmdletProviderContext currentContext = CmdletProviderContext; currentContext.PassThru = PassThru; - Collection propertyCollection = new Collection(); + Collection propertyCollection = new(); propertyCollection.Add(_property); foreach (string path in Path) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearRecycleBinCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearRecycleBinCommand.cs index 3925c222eef..78be89b90da 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearRecycleBinCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ClearRecycleBinCommand.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; @@ -155,7 +154,7 @@ private bool ValidDrivePath(string drivePath) /// /// /// - private bool IsValidPattern(string input) + private static bool IsValidPattern(string input) { return Regex.IsMatch(input, @"^[a-z]{1}$|^[a-z]{1}:$|^[a-z]{1}:\\$", RegexOptions.IgnoreCase); } @@ -166,7 +165,7 @@ private bool IsValidPattern(string input) /// /// /// - private string GetDrivePath(string driveName) + private static string GetDrivePath(string driveName) { string drivePath; if (driveName.EndsWith(":\\", StringComparison.OrdinalIgnoreCase)) @@ -221,7 +220,7 @@ private void EmptyRecycleBin(string drivePath) statusDescription = string.Format(CultureInfo.InvariantCulture, ClearRecycleBinResources.ClearRecycleBinStatusDescriptionByDrive, drivePath); } - ProgressRecord progress = new ProgressRecord(0, activity, statusDescription); + ProgressRecord progress = new(0, activity, statusDescription); progress.PercentComplete = 30; progress.RecordType = ProgressRecordType.Processing; WriteProgress(progress); diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs index 38a1b5c48a6..45e2a183b3e 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs @@ -19,18 +19,19 @@ internal static class Clipboard private static string StartProcess( string tool, string args, - string stdin = "") + string stdin = "", + bool readStdout = true) { - ProcessStartInfo startInfo = new ProcessStartInfo(); + ProcessStartInfo startInfo = new(); startInfo.UseShellExecute = false; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.FileName = tool; startInfo.Arguments = args; - string stdout; + string stdout = string.Empty; - using (Process process = new Process()) + using (Process process = new()) { process.StartInfo = startInfo; try @@ -43,15 +44,15 @@ private static string StartProcess( return string.Empty; } - if (!string.IsNullOrEmpty(stdin)) + process.StandardInput.Write(stdin); + process.StandardInput.Close(); + + if (readStdout) { - process.StandardInput.Write(stdin); - process.StandardInput.Close(); + stdout = process.StandardOutput.ReadToEnd(); } - stdout = process.StandardOutput.ReadToEnd(); process.WaitForExit(250); - _clipboardSupported = process.ExitCode == 0; } @@ -93,11 +94,6 @@ public static string GetText() public static void SetText(string text) { - if (string.IsNullOrEmpty(text)) - { - return; - } - if (_clipboardSupported == false) { _internalClipboard = text; @@ -114,7 +110,14 @@ public static void SetText(string text) else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { tool = "xclip"; - args = "-selection clipboard -in"; + if (string.IsNullOrEmpty(text)) + { + args = "-selection clipboard /dev/null"; + } + else + { + args = "-selection clipboard -in"; + } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { @@ -126,7 +129,7 @@ public static void SetText(string text) return; } - StartProcess(tool, args, text); + StartProcess(tool, args, text, readStdout: false); if (_clipboardSupported == false) { _internalClipboard = text; diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/CombinePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/CombinePathCommand.cs index bd97d485cd1..bdeef0dd7a0 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/CombinePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/CombinePathCommand.cs @@ -4,7 +4,6 @@ using System; using System.Collections.ObjectModel; using System.Management.Automation; -using System.Text; using Dbg = System.Management.Automation; @@ -219,4 +218,3 @@ protected override void ProcessRecord() } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs index 6bc54a4748b..73c2f309508 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs @@ -11,21 +11,17 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; +using System.Linq; using System.Management.Automation; using System.Management.Automation.Internal; using System.Net; -using System.Reflection; -using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Cryptography; -using System.Security.Permissions; using System.Text; using System.Threading; -using Microsoft.Win32; -using Microsoft.PowerShell.Commands.Internal; using Microsoft.Management.Infrastructure; using Microsoft.Management.Infrastructure.Options; -using System.Linq; +using Microsoft.Win32; using Dbg = System.Management.Automation; // FxCop suppressions for resource strings: @@ -198,9 +194,9 @@ public class RestartComputerCommand : PSCmdlet, IDisposable [Alias("CN", "__SERVER", "Server", "IPAddress")] public string[] ComputerName { get; set; } = new string[] { "." }; - private List _validatedComputerNames = new List(); - private readonly List _waitOnComputers = new List(); - private readonly HashSet _uniqueComputerNames = new HashSet(StringComparer.OrdinalIgnoreCase); + private List _validatedComputerNames = new(); + private readonly List _waitOnComputers = new(); + private readonly HashSet _uniqueComputerNames = new(StringComparer.OrdinalIgnoreCase); /// /// The following is the definition of the input parameter "Credential". @@ -237,7 +233,10 @@ public class RestartComputerCommand : PSCmdlet, IDisposable [ValidateRange(-1, int.MaxValue)] public int Timeout { - get { return _timeout; } + get + { + return _timeout; + } set { @@ -256,7 +255,10 @@ public int Timeout [Parameter(ParameterSetName = DefaultParameterSet)] public WaitForServiceTypes For { - get { return _waitFor; } + get + { + return _waitFor; + } set { @@ -273,10 +275,13 @@ public WaitForServiceTypes For /// The specific time interval (in second) to wait between network pings or service queries. /// [Parameter(ParameterSetName = DefaultParameterSet)] - [ValidateRange(1, Int16.MaxValue)] - public Int16 Delay + [ValidateRange(1, short.MaxValue)] + public short Delay { - get { return (Int16)_delay; } + get + { + return (short)_delay; + } set { @@ -318,7 +323,7 @@ public Int16 Delay /// /// The indicator to use when show progress. /// - private string[] _indicator = { "|", "/", "-", "\\" }; + private readonly string[] _indicator = { "|", "/", "-", "\\" }; /// /// The activity id. @@ -340,13 +345,13 @@ public Int16 Delay /// Indicate to exit. /// private bool _exit, _timeUp; - private readonly CancellationTokenSource _cancel = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancel = new(); /// /// A waithandler to wait on. Current thread will wait on it during the delay interval. /// - private readonly ManualResetEventSlim _waitHandler = new ManualResetEventSlim(false); - private readonly Dictionary _computerInfos = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly ManualResetEventSlim _waitHandler = new(false); + private readonly Dictionary _computerInfos = new(StringComparer.OrdinalIgnoreCase); // CLR 4.0 Port note - use https://msdn.microsoft.com/library/system.net.networkinformation.ipglobalproperties.hostname(v=vs.110).aspx private readonly string _shortLocalMachineName = Dns.GetHostName(); @@ -445,7 +450,7 @@ private void ValidateComputerNames() if (!InternalTestHooks.TestWaitStopComputer && Wait && containLocalhost) { // The local machine will be ignored, and an error will be emitted. - InvalidOperationException ex = new InvalidOperationException(ComputerResources.CannotWaitLocalComputer); + InvalidOperationException ex = new(ComputerResources.CannotWaitLocalComputer); WriteError(new ErrorRecord(ex, "CannotWaitLocalComputer", ErrorCategory.InvalidOperation, null)); containLocalhost = false; } @@ -467,7 +472,7 @@ private void ValidateComputerNames() /// private void WriteProgress(string activity, string status, int percent, ProgressRecordType progressRecordType) { - ProgressRecord progress = new ProgressRecord(_activityId, activity, status); + ProgressRecord progress = new(_activityId, activity, status); progress.PercentComplete = percent; progress.RecordType = progressRecordType; WriteProgress(progress); @@ -517,7 +522,7 @@ private void OnTimedEvent(object s) } } - private class ComputerInfo + private sealed class ComputerInfo { internal string LastBootUpTime; internal bool RebootComplete; @@ -537,7 +542,7 @@ private List TestRestartStageUsingWsman(IEnumerable computerName { if (token.IsCancellationRequested) { break; } - using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, token, this)) + using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, this, token)) { bool itemRetrieved = false; IEnumerable mCollection = cimSession.QueryInstances( @@ -593,7 +598,7 @@ private List SetUpComputerInfoUsingWsman(IEnumerable computerNam { try { - using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, token, this)) + using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, this, token)) { bool itemRetrieved = false; IEnumerable mCollection = cimSession.QueryInstances( @@ -663,7 +668,7 @@ private void WriteOutTimeoutError(IEnumerable computerNames) #region "Internal Methods" - internal static List TestWmiConnectionUsingWsman(List computerNames, List nextTestList, CancellationToken token, PSCredential credential, string wsmanAuthentication, PSCmdlet cmdlet) + internal static List TestWmiConnectionUsingWsman(List computerNames, List nextTestList, PSCredential credential, string wsmanAuthentication, PSCmdlet cmdlet, CancellationToken token) { // Check if the WMI service "Winmgmt" is started const string wmiServiceQuery = "Select * from " + ComputerWMIHelper.WMI_Class_Service + " Where name = 'Winmgmt'"; @@ -679,7 +684,7 @@ internal static List TestWmiConnectionUsingWsman(List computerNa { if (token.IsCancellationRequested) { break; } - using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, credential, wsmanAuthentication, isLocalHost: false, token, cmdlet)) + using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, credential, wsmanAuthentication, isLocalHost: false, cmdlet, token)) { bool itemRetrieved = false; IEnumerable mCollection = cimSession.QueryInstances( @@ -729,7 +734,7 @@ internal static List TestWmiConnectionUsingWsman(List computerNa /// internal static List TestPowerShell(List computerNames, List nextTestList, System.Management.Automation.PowerShell powershell, PSCredential credential) { - List psList = new List(); + List psList = new(); try { @@ -787,7 +792,7 @@ protected override void BeginProcessing() // Timeout, For, Delay, Progress cannot be present if Wait is not present if ((_timeoutSpecified || _waitForSpecified || _delaySpecified) && !Wait) { - InvalidOperationException ex = new InvalidOperationException(ComputerResources.RestartComputerInvalidParameter); + InvalidOperationException ex = new(ComputerResources.RestartComputerInvalidParameter); ThrowTerminatingError(new ErrorRecord(ex, "RestartComputerInvalidParameter", ErrorCategory.InvalidOperation, null)); } @@ -814,8 +819,8 @@ protected override void BeginProcessing() _powershell.AddScript(TestPowershellScript); break; default: - InvalidOperationException ex = new InvalidOperationException(ComputerResources.NoSupportForCombinedServiceType); - ErrorRecord error = new ErrorRecord(ex, "NoSupportForCombinedServiceType", ErrorCategory.InvalidOperation, (int)_waitFor); + InvalidOperationException ex = new(ComputerResources.NoSupportForCombinedServiceType); + ErrorRecord error = new(ex, "NoSupportForCombinedServiceType", ErrorCategory.InvalidOperation, (int)_waitFor); ThrowTerminatingError(error); break; } @@ -964,7 +969,7 @@ protected override void ProcessRecord() WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing); } - wmiTestList = TestWmiConnectionUsingWsman(wmiTestList, winrmTestList, _cancel.Token, Credential, WsmanAuthentication, this); + wmiTestList = TestWmiConnectionUsingWsman(wmiTestList, winrmTestList, Credential, WsmanAuthentication, this, _cancel.Token); } } @@ -1121,7 +1126,7 @@ public sealed class StopComputerCommand : PSCmdlet, IDisposable { #region Private Members - private readonly CancellationTokenSource _cancel = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancel = new(); private const int forcedShutdown = 5; // See https://msdn.microsoft.com/library/aa394058(v=vs.85).aspx @@ -1392,7 +1397,7 @@ private string ValidateComputerName() { bool isLocalhost = targetComputer.Equals(ComputerWMIHelper.localhostStr, StringComparison.OrdinalIgnoreCase); string errMsg = StringUtil.Format(ComputerResources.InvalidNewName, isLocalhost ? _shortLocalMachineName : targetComputer, NewName); - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new InvalidOperationException(errMsg), "InvalidNewName", ErrorCategory.InvalidArgument, NewName); WriteError(error); @@ -1434,8 +1439,8 @@ private void DoRenameComputerWsman(string computer, string computerName, string try { - using (CancellationTokenSource cancelTokenSource = new CancellationTokenSource()) - using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, credToUse, WsmanAuthentication, isLocalhost, cancelTokenSource.Token, this)) + using (CancellationTokenSource cancelTokenSource = new()) + using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, credToUse, WsmanAuthentication, isLocalhost, this, cancelTokenSource.Token)) { var operationOptions = new CimOperationOptions { @@ -1457,7 +1462,7 @@ private void DoRenameComputerWsman(string computer, string computerName, string if (oldName.Equals(newName, StringComparison.OrdinalIgnoreCase)) { string errMsg = StringUtil.Format(ComputerResources.NewNameIsOldName, computerName, newName); - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new InvalidOperationException(errMsg), "NewNameIsOldName", ErrorCategory.InvalidArgument, newName); WriteError(error); @@ -1516,7 +1521,7 @@ private void DoRenameComputerWsman(string computer, string computerName, string { var ex = new Win32Exception(retVal); string errMsg = StringUtil.Format(ComputerResources.FailToRename, computerName, newName, ex.Message); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "FailToRenameComputer", ErrorCategory.OperationStopped, computerName); + ErrorRecord error = new(new InvalidOperationException(errMsg), "FailToRenameComputer", ErrorCategory.OperationStopped, computerName); WriteError(error); } else @@ -1557,14 +1562,14 @@ private void DoRenameComputerWsman(string computer, string computerName, string catch (CimException ex) { string errMsg = StringUtil.Format(ComputerResources.FailToConnectToComputer, computerName, ex.Message); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "RenameComputerException", + ErrorRecord error = new(new InvalidOperationException(errMsg), "RenameComputerException", ErrorCategory.OperationStopped, computerName); WriteError(error); } catch (Exception ex) { string errMsg = StringUtil.Format(ComputerResources.FailToConnectToComputer, computerName, ex.Message); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "RenameComputerException", + ErrorRecord error = new(new InvalidOperationException(errMsg), "RenameComputerException", ErrorCategory.OperationStopped, computerName); WriteError(error); } @@ -1643,7 +1648,7 @@ public override string ToString() /// /// /// - private string FormatLine(string HasSucceeded, string computername) + private static string FormatLine(string HasSucceeded, string computername) { return StringUtil.Format(MatchFormat, HasSucceeded, computername); } @@ -1687,7 +1692,7 @@ public override string ToString() /// /// /// - private string FormatLine(string HasSucceeded, string newcomputername, string oldcomputername) + private static string FormatLine(string HasSucceeded, string newcomputername, string oldcomputername) { return StringUtil.Format(MatchFormat, HasSucceeded, newcomputername, oldcomputername); } @@ -1797,7 +1802,7 @@ internal static string GetLocalAdminUserName(string computerName, PSCredential p string localUserName = null; // The format of local admin username should be "ComputerName\AdminName" - if (psLocalCredential.UserName.Contains("\\")) + if (psLocalCredential.UserName.Contains('\\')) { localUserName = psLocalCredential.UserName; } @@ -1810,7 +1815,7 @@ internal static string GetLocalAdminUserName(string computerName, PSCredential p } else { - localUserName = computerName.Substring(0, dotIndex) + "\\" + psLocalCredential.UserName; + localUserName = string.Concat(computerName.AsSpan(0, dotIndex), "\\", psLocalCredential.UserName); } } @@ -1848,7 +1853,7 @@ internal static string GetRandomPassword(int passwordLength) /// internal static string GetScopeString(string computer, string namespaceParameter) { - StringBuilder returnValue = new StringBuilder("\\\\"); + StringBuilder returnValue = new("\\\\"); if (computer.Equals("::1", StringComparison.OrdinalIgnoreCase) || computer.Equals("[::1]", StringComparison.OrdinalIgnoreCase)) { returnValue.Append("localhost"); @@ -1924,7 +1929,7 @@ internal static string GetMachineNames(string[] computerNames) } string compname = string.Empty; - StringBuilder strComputers = new StringBuilder(); + StringBuilder strComputers = new(); int i = 0; foreach (string computer in computerNames) { @@ -1954,7 +1959,7 @@ internal static string GetMachineNames(string[] computerNames) internal static ComputerChangeInfo GetComputerStatusObject(int errorcode, string computername) { - ComputerChangeInfo computerchangeinfo = new ComputerChangeInfo(); + ComputerChangeInfo computerchangeinfo = new(); computerchangeinfo.ComputerName = computername; if (errorcode != 0) { @@ -1970,7 +1975,7 @@ internal static ComputerChangeInfo GetComputerStatusObject(int errorcode, string internal static RenameComputerChangeInfo GetRenameComputerStatusObject(int errorcode, string newcomputername, string oldcomputername) { - RenameComputerChangeInfo renamecomputerchangeinfo = new RenameComputerChangeInfo(); + RenameComputerChangeInfo renamecomputerchangeinfo = new(); renamecomputerchangeinfo.OldComputerName = oldcomputername; renamecomputerchangeinfo.NewComputerName = newcomputername; if (errorcode != 0) @@ -1987,7 +1992,7 @@ internal static RenameComputerChangeInfo GetRenameComputerStatusObject(int error internal static void WriteNonTerminatingError(int errorcode, PSCmdlet cmdlet, string computername) { - Win32Exception ex = new Win32Exception(errorcode); + Win32Exception ex = new(errorcode); string additionalmessage = string.Empty; if (ex.NativeErrorCode.Equals(0x00000035)) { @@ -1995,7 +2000,7 @@ internal static void WriteNonTerminatingError(int errorcode, PSCmdlet cmdlet, st } string message = StringUtil.Format(ComputerResources.OperationFailed, ex.Message, computername, additionalmessage); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, computername); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, computername); cmdlet.WriteError(er); } @@ -2105,12 +2110,12 @@ internal static bool InvokeWin32ShutdownUsingWsman( string message = StringUtil.Format(ComputerResources.PrivilegeNotEnabled, computerName, isLocalhost ? ComputerWMIHelper.SE_SHUTDOWN_NAME : ComputerWMIHelper.SE_REMOTE_SHUTDOWN_NAME); - ErrorRecord errorRecord = new ErrorRecord(new InvalidOperationException(message), "PrivilegeNotEnabled", ErrorCategory.InvalidOperation, null); + ErrorRecord errorRecord = new(new InvalidOperationException(message), "PrivilegeNotEnabled", ErrorCategory.InvalidOperation, null); cmdlet.WriteError(errorRecord); return false; } - using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(targetMachine, credInUse, authInUse, isLocalhost, cancelToken, cmdlet)) + using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(targetMachine, credInUse, authInUse, isLocalhost, cmdlet, cancelToken)) { var methodParameters = new CimMethodParametersCollection(); int retVal; @@ -2163,7 +2168,7 @@ internal static bool InvokeWin32ShutdownUsingWsman( { var ex = new Win32Exception(retVal); string errMsg = StringUtil.Format(formatErrorMessage, computerName, ex.Message); - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new InvalidOperationException(errMsg), ErrorFQEID, ErrorCategory.OperationStopped, computerName); cmdlet.WriteError(error); } @@ -2176,14 +2181,14 @@ internal static bool InvokeWin32ShutdownUsingWsman( catch (CimException ex) { string errMsg = StringUtil.Format(formatErrorMessage, computerName, ex.Message); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), ErrorFQEID, + ErrorRecord error = new(new InvalidOperationException(errMsg), ErrorFQEID, ErrorCategory.OperationStopped, computerName); cmdlet.WriteError(error); } catch (Exception ex) { string errMsg = StringUtil.Format(formatErrorMessage, computerName, ex.Message); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), ErrorFQEID, + ErrorRecord error = new(new InvalidOperationException(errMsg), ErrorFQEID, ErrorCategory.OperationStopped, computerName); cmdlet.WriteError(error); } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ComputerUnix.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ComputerUnix.cs index 023fc1d0501..fb01823790f 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ComputerUnix.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ComputerUnix.cs @@ -101,11 +101,28 @@ public class CommandLineCmdletBase : PSCmdlet, IDisposable #region "IDisposable Members" /// - /// Dispose Method. + /// Releases all resources used by the . /// public void Dispose() { - _process?.Dispose(); + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the + /// and optionally releases the managed resources. + /// + /// + /// to release both managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _process?.Dispose(); + } } #endregion "IDisposable Members" @@ -137,14 +154,12 @@ protected override void StopProcessing() /// Run a command. /// protected void RunCommand(String command, String args) { - String cmd = ""; - _process = new Process() { StartInfo = new ProcessStartInfo { FileName = "/sbin/shutdown", - Arguments = cmd, + Arguments = string.Empty, RedirectStandardOutput = false, UseShellExecute = false, CreateNoWindow = true, diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs index b595c0195f9..0c990292b58 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs @@ -34,7 +34,10 @@ public class ContentCommandBase : CoreCommandWithCredentialsBase, IDisposable [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return Path; } + get + { + return Path; + } set { @@ -108,7 +111,7 @@ public override SwitchParameter Force /// An array of content holder objects that contain the path information /// and content readers/writers for the item represented by the path information. /// - internal List contentStreams = new List(); + internal List contentStreams = new(); /// /// Wraps the content into a PSObject and adds context information as notes. @@ -297,7 +300,7 @@ public PSObject AttachNotes(PSObject content) { // Construct a provider qualified path as the Path note - PSNoteProperty note = new PSNoteProperty("PSPath", PSPath); + PSNoteProperty note = new("PSPath", PSPath); content.Properties.Add(note, true); tracer.WriteLine("Attaching {0} = {1}", "PSPath", PSPath); @@ -336,7 +339,7 @@ public PSObject AttachNotes(PSObject content) /// A struct to hold the path information and the content readers/writers /// for an item. /// - internal struct ContentHolder + internal readonly struct ContentHolder { internal ContentHolder( PathInfo pathInfo, @@ -385,7 +388,7 @@ internal void CloseContent(List contentHolders, bool disposing) // and write out an error. ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentCloseError", SessionStateStrings.ProviderContentCloseError, holder.PathInfo.Provider, @@ -422,7 +425,7 @@ internal void CloseContent(List contentHolders, bool disposing) // and write out an error. ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentCloseError", SessionStateStrings.ProviderContentCloseError, holder.PathInfo.Provider, @@ -480,7 +483,7 @@ internal List GetContentReaders( // Create the results array - List results = new List(); + List results = new(); foreach (PathInfo pathInfo in pathInfos) { @@ -538,7 +541,7 @@ internal List GetContentReaders( if (readers.Count == 1 && readers[0] != null) { ContentHolder holder = - new ContentHolder(pathInfo, readers[0], null); + new(pathInfo, readers[0], null); results.Add(holder); } @@ -573,7 +576,7 @@ internal Collection ResolvePaths( bool allowEmptyResult, CmdletProviderContext currentCommandContext) { - Collection results = new Collection(); + Collection results = new(); foreach (string path in pathsToResolve) { @@ -653,7 +656,7 @@ internal Collection ResolvePaths( out drive); PathInfo pathInfo = - new PathInfo( + new( drive, provider, unresolvedPath, @@ -666,7 +669,7 @@ internal Collection ResolvePaths( { // Detect if the path resolution failed to resolve to a file. string error = StringUtil.Format(NavigationResources.ItemNotFound, Path); - Exception e = new Exception(error); + Exception e = new(error); pathNotFoundErrorRecord = new ErrorRecord( e, @@ -705,14 +708,6 @@ public void Dispose() GC.SuppressFinalize(this); } - /// - /// Finalizer. - /// - ~ContentCommandBase() - { - Dispose(false); - } #endregion IDisposable - } } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ConvertPathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ConvertPathCommand.cs index 06add515e1c..c32d0f2aa67 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ConvertPathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ConvertPathCommand.cs @@ -4,8 +4,6 @@ using System.Collections.ObjectModel; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -128,4 +126,3 @@ protected override void ProcessRecord() } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs index 699676acfd6..ff13448bc09 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -36,7 +34,10 @@ public string[] Path [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return paths; } + get + { + return paths; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetChildrenCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetChildrenCommand.cs index 3dcd0d51c4a..d99ece1fb81 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetChildrenCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetChildrenCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; using Dbg = System.Management.Automation; @@ -365,4 +364,3 @@ protected override void ProcessRecord() #endregion command code } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs index dc272f40281..dd878bd72ce 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs @@ -23,7 +23,10 @@ public class GetClipboardCommand : PSCmdlet [Parameter] public SwitchParameter Raw { - get { return _raw; } + get + { + return _raw; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetComputerInfoCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetComputerInfoCommand.cs index d73d191585e..499358389f4 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetComputerInfoCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetComputerInfoCommand.cs @@ -31,7 +31,7 @@ namespace Microsoft.PowerShell.Commands public class GetComputerInfoCommand : PSCmdlet { #region Inner Types - private class OSInfoGroup + private sealed class OSInfoGroup { public WmiOperatingSystem os; public HotFix[] hotFixes; @@ -41,7 +41,7 @@ private class OSInfoGroup public RegWinNtCurrentVersion regCurVer; } - private class SystemInfoGroup + private sealed class SystemInfoGroup { public WmiBaseBoard baseboard; public WmiBios bios; @@ -50,7 +50,7 @@ private class SystemInfoGroup public NetworkAdapter[] networkAdapters; } - private class HyperVInfo + private sealed class HyperVInfo { public bool? Present; public bool? VMMonitorModeExtensions; @@ -59,13 +59,13 @@ private class HyperVInfo public bool? DataExecutionPreventionAvailable; } - private class DeviceGuardInfo + private sealed class DeviceGuardInfo { public DeviceGuardSmartStatus status; public DeviceGuard deviceGuard; } - private class MiscInfoGroup + private sealed class MiscInfoGroup { public ulong? physicallyInstalledMemory; public string timeZone; @@ -85,7 +85,7 @@ private class MiscInfoGroup #endregion Static Data and Constants #region Instance Data - private string _machineName = localMachineName; // we might need to have cmdlet work on another machine + private readonly string _machineName = localMachineName; // we might need to have cmdlet work on another machine /// /// Collection of property names from the Property parameter, @@ -225,7 +225,7 @@ protected override void ProcessRecord() /// private void UpdateProgress(string status) { - ProgressRecord progress = new ProgressRecord(0, activity, status ?? ComputerResources.ProgressStatusCompleted); + ProgressRecord progress = new(0, activity, status ?? ComputerResources.ProgressStatusCompleted); progress.RecordType = status == null ? ProgressRecordType.Completed : ProgressRecordType.Processing; WriteProgress(progress); @@ -486,7 +486,7 @@ private static DeviceGuardInfo GetDeviceGuard(CimSession session) /// private static HyperVInfo GetHyperVisorInfo(CimSession session) { - HyperVInfo info = new HyperVInfo(); + HyperVInfo info = new(); bool ok = false; CimInstance instance = null; @@ -1125,7 +1125,7 @@ internal static string GetLocaleName(string locale) // base-indication prefix. For example, the string "0409" will be // parsed into the base-10 integer value 1033, while the string "0x0409" // will fail to parse due to the "0x" base-indication prefix. - if (UInt32.TryParse(locale, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint localeNum)) + if (uint.TryParse(locale, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint localeNum)) { culture = CultureInfo.GetCultureInfo((int)localeNum); } @@ -1142,7 +1142,7 @@ internal static string GetLocaleName(string locale) } } - return culture == null ? null : culture.Name; + return culture?.Name; } /// @@ -1231,11 +1231,11 @@ internal static class EnumConverter where T : struct, IConvertible internal static class RegistryInfo { - public static Dictionary GetServerLevels() + public static Dictionary GetServerLevels() { const string keyPath = @"Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"; - var rv = new Dictionary(); + var rv = new Dictionary(); using (var key = Registry.LocalMachine.OpenSubKey(keyPath)) { @@ -1335,6 +1335,7 @@ protected static string GetLanguageName(uint? lcid) return null; } } + #pragma warning disable 649 // fields and properties in these class are assigned dynamically [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Class is instantiated directly from a CIM instance")] internal class WmiBaseBoard @@ -1372,7 +1373,7 @@ internal class WmiBaseBoard [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Class is instantiated directly from a CIM instance")] internal class WmiBios : WmiClassBase { - public UInt16[] BiosCharacteristics; + public ushort[] BiosCharacteristics; public string[] BIOSVersion; public string BuildNumber; public string Caption; @@ -1415,11 +1416,11 @@ internal class WmiComputerSystem public ushort? BootOptionOnWatchDog; public bool? BootROMSupported; public string BootupState; - public UInt16[] BootStatus; + public ushort[] BootStatus; public string Caption; public ushort? ChassisBootupState; public string ChassisSKUNumber; - public Int16? CurrentTimeZone; + public short? CurrentTimeZone; public bool? DaylightInEffect; public string Description; public string DNSHostName; @@ -1441,10 +1442,10 @@ internal class WmiComputerSystem public uint? NumberOfProcessors; public string[] OEMStringArray; public bool? PartOfDomain; - public Int64? PauseAfterReset; + public long? PauseAfterReset; public ushort? PCSystemType; public ushort? PCSystemTypeEx; - public UInt16[] PowerManagementCapabilities; + public ushort[] PowerManagementCapabilities; public bool? PowerManagementSupported; public ushort? PowerOnPasswordStatus; public ushort? PowerState; @@ -1452,8 +1453,8 @@ internal class WmiComputerSystem public string PrimaryOwnerContact; public string PrimaryOwnerName; public ushort? ResetCapability; - public Int16? ResetCount; - public Int16? ResetLimit; + public short? ResetCount; + public short? ResetLimit; public string[] Roles; public string Status; public string[] SupportContactDescription; @@ -1490,12 +1491,12 @@ public PowerManagementCapabilities[] GetPowerManagementCapabilities() [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Class is instantiated directly from a CIM instance")] internal class WmiDeviceGuard { - public UInt32[] AvailableSecurityProperties; + public uint[] AvailableSecurityProperties; public uint? CodeIntegrityPolicyEnforcementStatus; public uint? UsermodeCodeIntegrityPolicyEnforcementStatus; - public UInt32[] RequiredSecurityProperties; - public UInt32[] SecurityServicesConfigured; - public UInt32[] SecurityServicesRunning; + public uint[] RequiredSecurityProperties; + public uint[] SecurityServicesConfigured; + public uint[] SecurityServicesRunning; public uint? VirtualizationBasedSecurityStatus; public DeviceGuard AsOutputType @@ -1581,7 +1582,7 @@ internal class WmiKeyboard public ushort? NumberOfFunctionKeys; public ushort? Password; public string PNPDeviceID; - public UInt16[] PowerManagementCapabilities; + public ushort[] PowerManagementCapabilities; public bool? PowerManagementSupported; public string Status; public ushort? StatusInfo; @@ -1612,7 +1613,7 @@ internal class WmiMsftNetAdapter public string ErrorDescription; public uint? LastErrorCode; public string PNPDeviceID; - public UInt16[] PowerManagementCapabilities; + public ushort[] PowerManagementCapabilities; public bool? PowerManagementSupported; public ushort? StatusInfo; public string SystemCreationClassName; @@ -1679,8 +1680,8 @@ internal class WmiMsftNetAdapter public string PnPDeviceID; public string DriverProvider; public string ComponentID; - public UInt32[] LowerLayerInterfaceIndices; - public UInt32[] HigherLayerInterfaceIndices; + public uint[] LowerLayerInterfaceIndices; + public uint[] HigherLayerInterfaceIndices; public bool? AdminLocked; } @@ -1716,7 +1717,7 @@ internal class WmiNetworkAdapter public string PermanentAddress; public bool? PhysicalAdapter; public string PNPDeviceID; - public UInt16[] PowerManagementCapabilities; + public ushort[] PowerManagementCapabilities; public bool? PowerManagementSupported; public string ProductName; public string ServiceName; @@ -1752,7 +1753,7 @@ internal class WmiNetworkAdapterConfiguration public bool? DomainDNSRegistrationEnabled; public uint? ForwardBufferMemory; public bool? FullDNSRegistrationEnabled; - public UInt16[] GatewayCostMetric; + public ushort[] GatewayCostMetric; public byte? IGMPLevel; public uint? Index; public uint? InterfaceIndex; @@ -1768,7 +1769,7 @@ internal class WmiNetworkAdapterConfiguration public bool? IPUseZeroBroadcast; public string IPXAddress; public bool? IPXEnabled; - public UInt32[] IPXFrameType; + public uint[] IPXFrameType; public uint? IPXMediaType; public string[] IPXNetworkNumber; public string IPXVirtualNetNumber; @@ -1806,7 +1807,7 @@ internal class WmiOperatingSystem : WmiClassBase public string CountryCode; public string CSDVersion; public string CSName; - public Int16? CurrentTimeZone; + public short? CurrentTimeZone; public bool? DataExecutionPrevention_Available; public bool? DataExecutionPrevention_32BitApplications; public bool? DataExecutionPrevention_Drivers; @@ -1884,7 +1885,7 @@ public string GetLocale() #endregion Public Methods #region Private Methods - private OSProductSuite[] MakeProductSuites(uint? suiteMask) + private static OSProductSuite[] MakeProductSuites(uint? suiteMask) { if (suiteMask == null) return null; @@ -1893,7 +1894,7 @@ private OSProductSuite[] MakeProductSuites(uint? suiteMask) var list = new List(); foreach (OSProductSuite suite in Enum.GetValues(typeof(OSProductSuite))) - if ((mask & (UInt32)suite) != 0) + if ((mask & (uint)suite) != 0) list.Add(suite); return list.ToArray(); @@ -1953,7 +1954,7 @@ internal class WmiProcessor public string OtherFamilyDescription; public string PartNumber; public string PNPDeviceID; - public UInt16[] PowerManagementCapabilities; + public ushort[] PowerManagementCapabilities; public bool? PowerManagementSupported; public string ProcessorId; public ushort? ProcessorType; @@ -2281,7 +2282,7 @@ public class ComputerInfo /// the System Management BIOS Reference Specification. /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public UInt16[] BiosCharacteristics { get; internal set; } + public ushort[] BiosCharacteristics { get; internal set; } /// /// Array of the complete system BIOS information. In many computers @@ -2319,12 +2320,12 @@ public class ComputerInfo /// /// Major version of the embedded controller firmware. /// - public Int16? BiosEmbeddedControllerMajorVersion { get; internal set; } + public short? BiosEmbeddedControllerMajorVersion { get; internal set; } /// /// Minor version of the embedded controller firmware. /// - public Int16? BiosEmbeddedControllerMinorVersion { get; internal set; } + public short? BiosEmbeddedControllerMinorVersion { get; internal set; } /// /// Firmware type of the local computer. @@ -2495,7 +2496,7 @@ public class ComputerInfo /// Status and Additional Data fields that identify the boot status. /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public UInt16[] CsBootStatus { get; internal set; } + public ushort[] CsBootStatus { get; internal set; } /// /// System is started. Fail-safe boot bypasses the user startup files—also called SafeBoot. @@ -2523,7 +2524,7 @@ public class ComputerInfo /// Amount of time the unitary computer system is offset from Coordinated /// Universal Time (UTC). /// - public Int16? CsCurrentTimeZone { get; internal set; } + public short? CsCurrentTimeZone { get; internal set; } /// /// If True, the daylight savings mode is ON. @@ -2674,7 +2675,7 @@ public class ComputerInfo /// and automatic system reset. A value of –1 (minus one) indicates that /// the pause value is unknown. /// - public Int64? CsPauseAfterReset { get; internal set; } + public long? CsPauseAfterReset { get; internal set; } /// /// Type of the computer in use, such as laptop, desktop, or tablet. @@ -2742,13 +2743,13 @@ public class ComputerInfo /// Number of automatic resets since the last reset. /// A value of –1 (minus one) indicates that the count is unknown. /// - public Int16? CsResetCount { get; internal set; } + public short? CsResetCount { get; internal set; } /// /// Number of consecutive times a system reset is attempted. /// A value of –1 (minus one) indicates that the limit is unknown. /// - public Int16? CsResetLimit { get; internal set; } + public short? CsResetLimit { get; internal set; } /// /// Array that specifies the roles of a system in the information @@ -2908,7 +2909,7 @@ public class ComputerInfo /// Number, in minutes, an operating system is offset from Greenwich /// mean time (GMT). The number is positive, negative, or zero. /// - public Int16? OsCurrentTimeZone { get; internal set; } + public short? OsCurrentTimeZone { get; internal set; } /// /// Language identifier used by the operating system. @@ -5098,7 +5099,7 @@ private static class PInvokeDllNames public const uint POWER_PLATFORM_ROLE_V1 = 0x1; public const uint POWER_PLATFORM_ROLE_V2 = 0x2; - public const UInt32 S_OK = 0; + public const uint S_OK = 0; /// /// Import WINAPI function PowerDeterminePlatformRoleEx. diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs index 86f252fb8fc..f689695fc38 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs @@ -59,13 +59,16 @@ public long TotalCount [Alias("Last")] public int Tail { + get + { + return _backCount; + } + set { _backCount = value; _tailSpecified = true; } - - get { return _backCount; } } private int _backCount = -1; @@ -116,7 +119,7 @@ protected override void ProcessRecord() if (_totalCountSpecified && _tailSpecified) { string errMsg = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, "TotalCount", "Tail"); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "TailAndHeadCannotCoexist", ErrorCategory.InvalidOperation, null); + ErrorRecord error = new(new InvalidOperationException(errMsg), "TailAndHeadCannotCoexist", ErrorCategory.InvalidOperation, null); WriteError(error); return; } @@ -142,10 +145,10 @@ protected override void ProcessRecord() holder.Reader != null, "All holders should have a reader assigned"); - if (_tailSpecified && !(holder.Reader is FileSystemContentReaderWriter)) + if (_tailSpecified && holder.Reader is not FileSystemContentReaderWriter) { string errMsg = SessionStateStrings.GetContent_TailNotSupported; - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "TailNotSupported", ErrorCategory.InvalidOperation, Tail); + ErrorRecord error = new(new InvalidOperationException(errMsg), "TailNotSupported", ErrorCategory.InvalidOperation, Tail); WriteError(error); continue; } @@ -165,7 +168,7 @@ protected override void ProcessRecord() catch (Exception e) { ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentReadError", SessionStateStrings.ProviderContentReadError, holder.PathInfo.Provider, @@ -218,7 +221,7 @@ protected override void ProcessRecord() catch (Exception e) // Catch-all OK. 3rd party callout { ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentReadError", SessionStateStrings.ProviderContentReadError, holder.PathInfo.Provider, @@ -277,7 +280,7 @@ protected override void ProcessRecord() /// true if no error occured /// false if there was an error /// - private bool ScanForwardsForTail(ContentHolder holder, CmdletProviderContext currentContext) + private bool ScanForwardsForTail(in ContentHolder holder, CmdletProviderContext currentContext) { var fsReader = holder.Reader as FileSystemContentReaderWriter; Dbg.Diagnostics.Assert(fsReader != null, "Tail is only supported for FileSystemContentReaderWriter"); @@ -294,7 +297,7 @@ private bool ScanForwardsForTail(ContentHolder holder, CmdletProviderContext cur catch (Exception e) { ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentReadError", SessionStateStrings.ProviderContentReadError, holder.PathInfo.Provider, @@ -416,4 +419,3 @@ protected override void EndProcessing() } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetPropertyCommand.cs index 7f6e4c5b1b4..7523a497390 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetPropertyCommand.cs @@ -5,8 +5,6 @@ using System.Diagnostics.CodeAnalysis; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Hotfix.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Hotfix.cs index c0404fa133c..d6768a1315e 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Hotfix.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Hotfix.cs @@ -66,7 +66,7 @@ public sealed class GetHotFixCommand : PSCmdlet, IDisposable private ManagementObjectSearcher _searchProcess; private bool _inputContainsWildcard = false; - private readonly ConnectionOptions _connectionOptions = new ConnectionOptions(); + private readonly ConnectionOptions _connectionOptions = new(); /// /// Sets connection options. @@ -87,8 +87,8 @@ protected override void ProcessRecord() foreach (string computer in ComputerName) { bool foundRecord = false; - StringBuilder queryString = new StringBuilder(); - ManagementScope scope = new ManagementScope(ComputerWMIHelper.GetScopeString(computer, ComputerWMIHelper.WMI_Path_CIM), _connectionOptions); + StringBuilder queryString = new(); + ManagementScope scope = new(ComputerWMIHelper.GetScopeString(computer, ComputerWMIHelper.WMI_Path_CIM), _connectionOptions); scope.Connect(); if (Id != null) { @@ -97,14 +97,14 @@ protected override void ProcessRecord() { queryString.Append("HotFixID= '"); queryString.Append(Id[i].Replace("'", "\\'")); - queryString.Append("'"); + queryString.Append('\''); if (i < Id.Length - 1) { queryString.Append(" Or "); } } - queryString.Append(")"); + queryString.Append(')'); } else { @@ -134,7 +134,7 @@ protected override void ProcessRecord() { try { - SecurityIdentifier secObj = new SecurityIdentifier(installed); + SecurityIdentifier secObj = new(installed); obj["InstalledBy"] = secObj.Translate(typeof(NTAccount)); } catch (IdentityNotMappedException) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs index 0fcc8a3a244..fb90ec1c502 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs @@ -4,8 +4,6 @@ using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -37,7 +35,10 @@ public string[] Path [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return paths; } + get + { + return paths; + } set { @@ -53,7 +54,10 @@ public string[] LiteralPath [Alias("PSProperty")] public string[] Name { - get { return _property; } + get + { + return _property; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs index dc003cc7562..c00c374611e 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs @@ -39,7 +39,7 @@ internal virtual CmdletProviderContext CmdletProviderContext { get { - CmdletProviderContext coreCommandContext = new CmdletProviderContext(this); + CmdletProviderContext coreCommandContext = new(this); coreCommandContext.Force = Force; @@ -107,7 +107,7 @@ protected bool DoesProviderSupportShouldProcess(string[] paths) // may be getting piped in. bool result = true; - if (paths != null && paths.Length >= 0) + if (paths != null) { foreach (string path in paths) { @@ -165,7 +165,7 @@ protected override void StopProcessing() } internal Collection stopContextCollection = - new Collection(); + new(); /// /// Gets or sets the filter property. @@ -301,7 +301,7 @@ internal override CmdletProviderContext CmdletProviderContext { get { - CmdletProviderContext coreCommandContext = new CmdletProviderContext(this, Credential); + CmdletProviderContext coreCommandContext = new(this, Credential); coreCommandContext.Force = Force; Collection includeFilter = @@ -447,7 +447,7 @@ protected override void ProcessRecord() catch (DriveNotFoundException e) { ErrorRecord errorRecord = - new ErrorRecord( + new( e, "GetLocationNoMatchingDrive", ErrorCategory.ObjectNotFound, @@ -458,7 +458,7 @@ protected override void ProcessRecord() catch (ProviderNotFoundException e) { ErrorRecord errorRecord = - new ErrorRecord( + new( e, "GetLocationNoMatchingProvider", ErrorCategory.ObjectNotFound, @@ -469,7 +469,7 @@ protected override void ProcessRecord() catch (ArgumentException argException) { ErrorRecord errorRecord = - new ErrorRecord( + new( argException, "GetLocationNoMatchingDrive", ErrorCategory.ObjectNotFound, @@ -523,7 +523,7 @@ protected override void ProcessRecord() catch (ProviderNotFoundException e) { ErrorRecord errorRecord = - new ErrorRecord( + new( e, "GetLocationNoMatchingProvider", ErrorCategory.ObjectNotFound, @@ -1237,7 +1237,7 @@ protected override void ProcessRecord() // -Persist switch parameter is supported only for FileSystem provider. if (Persist && !provider.Name.Equals(FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase)) { - ErrorRecord er = new ErrorRecord(new NotSupportedException(FileSystemProviderStrings.PersistNotSupported), "DriveRootNotNetworkPath", ErrorCategory.InvalidArgument, this); + ErrorRecord er = new(new NotSupportedException(FileSystemProviderStrings.PersistNotSupported), "DriveRootNotNetworkPath", ErrorCategory.InvalidArgument, this); ThrowTerminatingError(er); } @@ -1249,7 +1249,7 @@ protected override void ProcessRecord() // Create the new drive PSDriveInfo newDrive = - new PSDriveInfo( + new( Name, provider, Root, @@ -1368,7 +1368,7 @@ internal List GetMatchingDrives( string[] providerNames, string scope) { - List results = new List(); + List results = new(); if (providerNames == null || providerNames.Length == 0) { @@ -1609,8 +1609,7 @@ protected override void ProcessRecord() if (!Force && drive == SessionState.Drive.Current) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.RemoveDriveInUse, drive.Name); @@ -1637,7 +1636,7 @@ protected override void ProcessRecord() if (verifyMatch && !foundMatch) { - DriveNotFoundException e = new DriveNotFoundException( + DriveNotFoundException e = new( driveName, "DriveNotFound", SessionStateStrings.DriveNotFound); @@ -1776,7 +1775,7 @@ protected override void ProcessRecord() if (!WildcardPattern.ContainsWildcardCharacters(driveName)) { DriveNotFoundException driveNotFound = - new DriveNotFoundException( + new( driveName, "DriveNotFound", SessionStateStrings.DriveNotFound); @@ -1793,7 +1792,7 @@ protected override void ProcessRecord() catch (DriveNotFoundException driveNotFound) { ErrorRecord errorRecord = - new ErrorRecord( + new( driveNotFound, "GetLocationNoMatchingDrive", ErrorCategory.ObjectNotFound, @@ -1803,7 +1802,7 @@ protected override void ProcessRecord() catch (ProviderNotFoundException providerNotFound) { ErrorRecord errorRecord = - new ErrorRecord( + new( providerNotFound, "GetLocationNoMatchingDrive", ErrorCategory.ObjectNotFound, @@ -2536,10 +2535,10 @@ protected override void ProcessRecord() try { resolvedPSPaths = SessionState.Path.GetResolvedPSPathFromPSPath(path, currentContext); - if (true == SuppressWildcardExpansion && 0 == resolvedPSPaths.Count) + if (SuppressWildcardExpansion == true && resolvedPSPaths.Count == 0) { ItemNotFoundException pathNotFound = - new ItemNotFoundException( + new( path, "PathNotFound", SessionStateStrings.PathNotFound); @@ -2637,8 +2636,7 @@ protected override void ProcessRecord() if (isCurrentLocationOrAncestor) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.RemoveItemInUse, resolvedPath.Path); @@ -2700,8 +2698,8 @@ protected override void ProcessRecord() { try { - System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(providerPath); - if (di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) + System.IO.DirectoryInfo di = new(providerPath); + if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(di)) { shouldRecurse = false; treatAsFile = true; @@ -2941,7 +2939,7 @@ internal override object GetDynamicParameters(CmdletProviderContext context) private Collection GetResolvedPaths(string path) { - Collection results = new Collection(); + Collection results = new(); try { results = SessionState.Path.GetResolvedPSPathFromPSPath(path, CmdletProviderContext); @@ -3012,8 +3010,7 @@ private void MoveItem(string path, bool literalPath = false) if (!InvokeProvider.Item.Exists(path, currentContext)) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.MoveItemDoesntExist, path); @@ -3099,8 +3096,7 @@ private void MoveItem(string path, bool literalPath = false) if (isCurrentLocationOrAncestor) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.MoveItemInUse, path); @@ -3354,8 +3350,7 @@ private void RenameItem(string path, bool literalPath = false) if (!InvokeProvider.Item.Exists(path, currentContext)) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.RenameItemDoesntExist, path); @@ -3441,8 +3436,7 @@ private void RenameItem(string path, bool literalPath = false) if (isCurrentLocationOrAncestor) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.RenamedItemInUse, path); diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs index e3982d49034..b2b9e6c1a85 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs index a1dd7895fc1..d56a20faba0 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs @@ -184,7 +184,7 @@ public string[] LiteralPath /// protected override void ProcessRecord() { - StringCollection pathsToParse = new StringCollection(); + StringCollection pathsToParse = new(); if (Resolve) { @@ -305,7 +305,7 @@ protected override void ProcessRecord() if (separatorIndex < 0) { FormatException e = - new FormatException( + new( StringUtil.Format(NavigationResources.ParsePathFormatError, pathsToParse[index])); WriteError( new ErrorRecord( diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughContentCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughContentCommandBase.cs index 83ce50d0049..19bad39785b 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughContentCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughContentCommandBase.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -76,4 +74,3 @@ internal CmdletProviderContext GetCurrentContext() #endregion protected members } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughPropertyCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughPropertyCommandBase.cs index f2d18660ee5..8b76ac36786 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughPropertyCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/PassThroughPropertyCommandBase.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -102,4 +100,3 @@ internal CmdletProviderContext GetCurrentContext() #endregion protected members } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs index 29b905cb0ff..9bebcd076ca 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs @@ -4,8 +4,6 @@ using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -64,7 +62,10 @@ public string[] Path [AllowEmptyString] public string[] LiteralPath { - get { return _paths; } + get + { + return _paths; + } set { @@ -247,4 +248,3 @@ protected override void ProcessRecord() } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index b7f97138028..ef4f5b1a7b4 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -12,21 +12,17 @@ using System.Management.Automation; using System.Management.Automation.Internal; using System.Net; -using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; -using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; - using Microsoft.Management.Infrastructure; using Microsoft.PowerShell.Commands.Internal; using Microsoft.Win32.SafeHandles; - -using FileNakedHandle = System.IntPtr; using DWORD = System.UInt32; +using FileNakedHandle = System.IntPtr; namespace Microsoft.PowerShell.Commands { @@ -58,7 +54,7 @@ internal enum MatchMode /// Select the processes specified as input. /// ByInput - }; + } /// /// The current process selection mode. /// @@ -107,8 +103,8 @@ public virtual Process[] InputObject // We use a Dictionary to optimize the check whether the object // is already in the list. - private List _matchingProcesses = new List(); - private Dictionary _keys = new Dictionary(); + private List _matchingProcesses = new(); + private readonly Dictionary _keys = new(); /// /// Retrieve the list of all processes matching the Name, Id @@ -153,7 +149,7 @@ private static int ProcessComparison(Process x, Process y) SafeGetProcessName(x), SafeGetProcessName(y), StringComparison.OrdinalIgnoreCase); - if (0 != diff) + if (diff != 0) return diff; return SafeGetProcessId(x) - SafeGetProcessId(y); } @@ -237,7 +233,7 @@ private void RetrieveMatchingProcessesById() catch (ArgumentException) { WriteNonTerminatingError( - "", + string.Empty, processId, processId, null, @@ -270,30 +266,17 @@ private void RetrieveProcessesByInput() } /// - /// Retrieve the master list of all processes. + /// Gets an array of all processes. /// - /// + /// An array of components that represents all the process resources. /// /// MSDN does not document the list of exceptions, /// but it is reasonable to expect that SecurityException is /// among them. Errors here will terminate the cmdlet. /// - internal Process[] AllProcesses - { - get - { - if (_allProcesses == null) - { - List processes = new List(); - processes.AddRange(Process.GetProcesses()); - _allProcesses = processes.ToArray(); - } + internal Process[] AllProcesses => _allProcesses ??= Process.GetProcesses(); - return _allProcesses; - } - } - - private Process[] _allProcesses = null; + private Process[] _allProcesses; /// /// Add to , @@ -362,7 +345,7 @@ internal void WriteNonTerminatingError( processId, (innerException == null) ? string.Empty : innerException.Message); ProcessCommandException exception = - new ProcessCommandException(message, innerException); + new(message, innerException); exception.ProcessName = processName; WriteError(new ErrorRecord( @@ -480,7 +463,10 @@ public sealed class GetProcessCommand : ProcessBaseCommand [ValidateNotNullOrEmpty] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -654,6 +640,10 @@ protected override void ProcessRecord() WriteNonTerminatingError(process, ex, ProcessResources.CouldNotEnumerateModules, "CouldNotEnumerateModules", ErrorCategory.PermissionDenied); } } + catch (PipelineStoppedException) + { + throw; + } catch (Exception exception) { WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModules, "CouldNotEnumerateModules", ErrorCategory.PermissionDenied); @@ -663,7 +653,7 @@ protected override void ProcessRecord() { try { - ProcessModule mainModule = PsUtils.GetMainModule(process); + ProcessModule mainModule = process.MainModule; if (mainModule != null) { WriteObject(mainModule.FileVersionInfo, true); @@ -683,7 +673,7 @@ protected override void ProcessRecord() { if (exception.HResult == 299) { - WriteObject(PsUtils.GetMainModule(process).FileVersionInfo, true); + WriteObject(process.MainModule?.FileVersionInfo, true); } else { @@ -727,7 +717,7 @@ private static PSObject AddUserNameToProcess(Process process) string userName = RetrieveProcessUserName(process); PSObject processAsPsobj = PSObject.AsPSObject(process); - PSNoteProperty noteProperty = new PSNoteProperty("UserName", userName); + PSNoteProperty noteProperty = new("UserName", userName); processAsPsobj.Properties.Add(noteProperty, true); processAsPsobj.TypeNames.Insert(0, TypeNameForProcessWithUserName); @@ -882,7 +872,10 @@ public int[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -925,7 +918,7 @@ public int Timeout /// public void Dispose() { - if (_disposed == false) + if (!_disposed) { if (_waitHandle != null) { @@ -943,7 +936,7 @@ public void Dispose() // Handle Exited event and display process information. private void myProcess_Exited(object sender, System.EventArgs e) { - if (0 == System.Threading.Interlocked.Decrement(ref _numberOfProcessesToWaitFor)) + if (System.Threading.Interlocked.Decrement(ref _numberOfProcessesToWaitFor) == 0) { if (_waitHandle != null) { @@ -956,7 +949,7 @@ private void myProcess_Exited(object sender, System.EventArgs e) #region Overrides - private List _processList = new List(); + private readonly List _processList = new(); // Wait handle which is used by thread to sleep. private ManualResetEvent _waitHandle; @@ -978,7 +971,7 @@ protected override void ProcessRecord() } // It cannot wait on itself - if (process.Id.Equals(System.Diagnostics.Process.GetCurrentProcess().Id)) + if (process.Id.Equals(Environment.ProcessId)) { WriteNonTerminatingError(process, null, ProcessResources.WaitOnItself, "WaitOnItself", ErrorCategory.ObjectNotFound); continue; @@ -1033,7 +1026,7 @@ protected override void EndProcessing() if (!process.HasExited) { string message = StringUtil.Format(ProcessResources.ProcessNotTerminated, new object[] { process.ProcessName, process.Id }); - ErrorRecord errorRecord = new ErrorRecord(new TimeoutException(message), "ProcessNotTerminated", ErrorCategory.CloseError, process); + ErrorRecord errorRecord = new(new TimeoutException(message), "ProcessNotTerminated", ErrorCategory.CloseError, process); WriteError(errorRecord); } } @@ -1218,7 +1211,7 @@ protected override void ProcessRecord() try { - if (Process.GetCurrentProcess().Id == SafeGetProcessId(process)) + if (Environment.ProcessId == SafeGetProcessId(process)) { _shouldKillCurrentProcess = true; continue; @@ -1391,9 +1384,9 @@ private void StopDependentService(Process process) /// /// Stops the given process throws non terminating error if can't. - /// Process to be stopped. - /// True if process stopped successfully else false. /// + /// Process to be stopped. + /// True if process stopped successfully else false. private void StopProcess(Process process) { Exception exception = null; @@ -1476,7 +1469,10 @@ public int[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -1582,7 +1578,7 @@ private void AttachDebuggerToProcess(Process process) /// /// Map the return code from 'AttachDebugger' to error message. /// - private string MapReturnCodeToErrorMessage(int returnCode) + private static string MapReturnCodeToErrorMessage(int returnCode) { string errorMessage = string.Empty; switch (returnCode) @@ -1639,7 +1635,10 @@ public sealed class StartProcessCommand : PSCmdlet, IDisposable [Credential] public PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -1664,7 +1663,10 @@ public PSCredential Credential [Alias("Lup")] public SwitchParameter LoadUserProfile { - get { return _loaduserprofile; } + get + { + return _loaduserprofile; + } set { @@ -1682,7 +1684,10 @@ public SwitchParameter LoadUserProfile [Alias("nnw")] public SwitchParameter NoNewWindow { - get { return _nonewwindow; } + get + { + return _nonewwindow; + } set { @@ -1707,7 +1712,10 @@ public SwitchParameter NoNewWindow [ValidateNotNullOrEmpty] public string RedirectStandardError { - get { return _redirectstandarderror; } + get + { + return _redirectstandarderror; + } set { @@ -1726,7 +1734,10 @@ public string RedirectStandardError [ValidateNotNullOrEmpty] public string RedirectStandardInput { - get { return _redirectstandardinput; } + get + { + return _redirectstandardinput; + } set { @@ -1745,7 +1756,10 @@ public string RedirectStandardInput [ValidateNotNullOrEmpty] public string RedirectStandardOutput { - get { return _redirectstandardoutput; } + get + { + return _redirectstandardoutput; + } set { @@ -1773,7 +1787,10 @@ public string RedirectStandardOutput [ValidateNotNullOrEmpty] public ProcessWindowStyle WindowStyle { - get { return _windowstyle; } + get + { + return _windowstyle; + } set { @@ -1797,7 +1814,10 @@ public ProcessWindowStyle WindowStyle [Parameter(ParameterSetName = "Default")] public SwitchParameter UseNewEnvironment { - get { return _UseNewEnvironment; } + get + { + return _UseNewEnvironment; + } set { @@ -1826,7 +1846,7 @@ protected override void BeginProcessing() if (_nonewwindow && _windowstyleSpecified) { message = StringUtil.Format(ProcessResources.ContradictParametersSpecified, "-NoNewWindow", "-WindowStyle"); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -1844,12 +1864,12 @@ protected override void BeginProcessing() if (!string.IsNullOrEmpty(message)) { - ErrorRecord er = new ErrorRecord(new NotSupportedException(message), "NotSupportedException", ErrorCategory.NotImplemented, null); + ErrorRecord er = new(new NotSupportedException(message), "NotSupportedException", ErrorCategory.NotImplemented, null); ThrowTerminatingError(er); } } - ProcessStartInfo startInfo = new ProcessStartInfo(); + ProcessStartInfo startInfo = new(); // Use ShellExecute by default if we are running on full windows SKUs startInfo.UseShellExecute = Platform.IsWindowsDesktop; @@ -1887,7 +1907,7 @@ protected override void BeginProcessing() if (!Directory.Exists(WorkingDirectory)) { message = StringUtil.Format(ProcessResources.InvalidInput, "WorkingDirectory"); - ErrorRecord er = new ErrorRecord(new DirectoryNotFoundException(message), "DirectoryNotFoundException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new DirectoryNotFoundException(message), "DirectoryNotFoundException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -1946,7 +1966,7 @@ protected override void BeginProcessing() if (!File.Exists(_redirectstandardinput)) { message = StringUtil.Format(ProcessResources.InvalidInput, "RedirectStandardInput '" + this.RedirectStandardInput + "'"); - ErrorRecord er = new ErrorRecord(new FileNotFoundException(message), "FileNotFoundException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new FileNotFoundException(message), "FileNotFoundException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -1960,7 +1980,7 @@ protected override void BeginProcessing() if (_redirectstandardinput.Equals(_redirectstandardoutput, StringComparison.OrdinalIgnoreCase)) { message = StringUtil.Format(ProcessResources.DuplicateEntry, "RedirectStandardInput", "RedirectStandardOutput"); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -1974,7 +1994,7 @@ protected override void BeginProcessing() if (_redirectstandardinput.Equals(_redirectstandarderror, StringComparison.OrdinalIgnoreCase)) { message = StringUtil.Format(ProcessResources.DuplicateEntry, "RedirectStandardInput", "RedirectStandardError"); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -1988,7 +2008,7 @@ protected override void BeginProcessing() if (_redirectstandardoutput.Equals(_redirectstandarderror, StringComparison.OrdinalIgnoreCase)) { message = StringUtil.Format(ProcessResources.DuplicateEntry, "RedirectStandardOutput", "RedirectStandardError"); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); WriteError(er); return; } @@ -2015,7 +2035,7 @@ protected override void BeginProcessing() else { message = StringUtil.Format(ProcessResources.CannotStarttheProcess); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } } @@ -2032,7 +2052,7 @@ protected override void BeginProcessing() _waithandle = new ManualResetEvent(false); // Create and start the job object - ProcessCollection jobObject = new ProcessCollection(); + ProcessCollection jobObject = new(); if (jobObject.AssignProcessToJobObject(process)) { // Wait for the job object to finish @@ -2051,7 +2071,7 @@ protected override void BeginProcessing() else { message = StringUtil.Format(ProcessResources.CannotStarttheProcess); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } } @@ -2110,7 +2130,7 @@ private string ResolveFilePath(string path) return filepath; } - private void LoadEnvironmentVariable(ProcessStartInfo startinfo, IDictionary EnvironmentVariables) + private static void LoadEnvironmentVariable(ProcessStartInfo startinfo, IDictionary EnvironmentVariables) { var processEnvironment = startinfo.EnvironmentVariables; foreach (DictionaryEntry entry in EnvironmentVariables) @@ -2273,7 +2293,7 @@ private void WriteToStandardInput(Process p) private SafeFileHandle GetSafeFileHandleForRedirection(string RedirectionPath, uint dwCreationDisposition) { System.IntPtr hFileHandle = System.IntPtr.Zero; - ProcessNativeMethods.SECURITY_ATTRIBUTES lpSecurityAttributes = new ProcessNativeMethods.SECURITY_ATTRIBUTES(); + ProcessNativeMethods.SECURITY_ATTRIBUTES lpSecurityAttributes = new(); hFileHandle = ProcessNativeMethods.CreateFileW(RedirectionPath, ProcessNativeMethods.GENERIC_READ | ProcessNativeMethods.GENERIC_WRITE, @@ -2285,19 +2305,19 @@ private SafeFileHandle GetSafeFileHandleForRedirection(string RedirectionPath, u if (hFileHandle == System.IntPtr.Zero) { int error = Marshal.GetLastWin32Error(); - Win32Exception win32ex = new Win32Exception(error); + Win32Exception win32ex = new(error); string message = StringUtil.Format(ProcessResources.InvalidStartProcess, win32ex.Message); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } - SafeFileHandle sf = new SafeFileHandle(hFileHandle, true); + SafeFileHandle sf = new(hFileHandle, true); return sf; } private static StringBuilder BuildCommandLine(string executableFileName, string arguments) { - StringBuilder builder = new StringBuilder(); + StringBuilder builder = new(); string str = executableFileName.Trim(); bool flag = str.StartsWith('"') && str.EndsWith('"'); if (!flag) @@ -2328,10 +2348,10 @@ private static byte[] ConvertEnvVarsToByteArray(StringDictionary sd) string[] strArray2 = new string[sd.Count]; sd.Values.CopyTo(strArray2, 0); Array.Sort(array, strArray2, StringComparer.OrdinalIgnoreCase); - StringBuilder builder = new StringBuilder(); + StringBuilder builder = new(); for (int i = 0; i < sd.Count; i++) { - builder.Append(array[i]);// + builder.Append(array[i]); builder.Append('='); builder.Append(strArray2[i]); builder.Append('\0'); @@ -2341,92 +2361,88 @@ private static byte[] ConvertEnvVarsToByteArray(StringDictionary sd) // Use Unicode encoding bytes = Encoding.Unicode.GetBytes(builder.ToString()); - if (bytes.Length > 0xffff) - { - throw new InvalidOperationException("EnvironmentBlockTooLong"); - } return bytes; } private void SetStartupInfo(ProcessStartInfo startinfo, ref ProcessNativeMethods.STARTUPINFO lpStartupInfo, ref int creationFlags) { - // RedirectionStandardInput - if (_redirectstandardinput != null) - { - startinfo.RedirectStandardInput = true; - _redirectstandardinput = ResolveFilePath(_redirectstandardinput); - lpStartupInfo.hStdInput = GetSafeFileHandleForRedirection(_redirectstandardinput, ProcessNativeMethods.OPEN_EXISTING); - } - else - { - lpStartupInfo.hStdInput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-10), false); - } + // RedirectionStandardInput + if (_redirectstandardinput != null) + { + startinfo.RedirectStandardInput = true; + _redirectstandardinput = ResolveFilePath(_redirectstandardinput); + lpStartupInfo.hStdInput = GetSafeFileHandleForRedirection(_redirectstandardinput, ProcessNativeMethods.OPEN_EXISTING); + } + else + { + lpStartupInfo.hStdInput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-10), false); + } - // RedirectionStandardOutput - if (_redirectstandardoutput != null) - { - startinfo.RedirectStandardOutput = true; - _redirectstandardoutput = ResolveFilePath(_redirectstandardoutput); - lpStartupInfo.hStdOutput = GetSafeFileHandleForRedirection(_redirectstandardoutput, ProcessNativeMethods.CREATE_ALWAYS); - } - else - { - lpStartupInfo.hStdOutput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-11), false); - } + // RedirectionStandardOutput + if (_redirectstandardoutput != null) + { + startinfo.RedirectStandardOutput = true; + _redirectstandardoutput = ResolveFilePath(_redirectstandardoutput); + lpStartupInfo.hStdOutput = GetSafeFileHandleForRedirection(_redirectstandardoutput, ProcessNativeMethods.CREATE_ALWAYS); + } + else + { + lpStartupInfo.hStdOutput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-11), false); + } - // RedirectionStandardError - if (_redirectstandarderror != null) - { - startinfo.RedirectStandardError = true; - _redirectstandarderror = ResolveFilePath(_redirectstandarderror); - lpStartupInfo.hStdError = GetSafeFileHandleForRedirection(_redirectstandarderror, ProcessNativeMethods.CREATE_ALWAYS); - } - else - { - lpStartupInfo.hStdError = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-12), false); - } + // RedirectionStandardError + if (_redirectstandarderror != null) + { + startinfo.RedirectStandardError = true; + _redirectstandarderror = ResolveFilePath(_redirectstandarderror); + lpStartupInfo.hStdError = GetSafeFileHandleForRedirection(_redirectstandarderror, ProcessNativeMethods.CREATE_ALWAYS); + } + else + { + lpStartupInfo.hStdError = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-12), false); + } - // STARTF_USESTDHANDLES - lpStartupInfo.dwFlags = 0x100; + // STARTF_USESTDHANDLES + lpStartupInfo.dwFlags = 0x100; - if (startinfo.CreateNoWindow) - { - // No new window: Inherit the parent process's console window - creationFlags = 0x00000000; - } - else - { - // CREATE_NEW_CONSOLE - creationFlags |= 0x00000010; + if (startinfo.CreateNoWindow) + { + // No new window: Inherit the parent process's console window + creationFlags = 0x00000000; + } + else + { + // CREATE_NEW_CONSOLE + creationFlags |= 0x00000010; - // STARTF_USESHOWWINDOW - lpStartupInfo.dwFlags |= 0x00000001; + // STARTF_USESHOWWINDOW + lpStartupInfo.dwFlags |= 0x00000001; - // On headless SKUs like NanoServer and IoT, window style can only be the default value 'Normal'. - switch (startinfo.WindowStyle) - { - case ProcessWindowStyle.Normal: - // SW_SHOWNORMAL - lpStartupInfo.wShowWindow = 1; - break; - case ProcessWindowStyle.Minimized: - // SW_SHOWMINIMIZED - lpStartupInfo.wShowWindow = 2; - break; - case ProcessWindowStyle.Maximized: - // SW_SHOWMAXIMIZED - lpStartupInfo.wShowWindow = 3; - break; - case ProcessWindowStyle.Hidden: - // SW_HIDE - lpStartupInfo.wShowWindow = 0; - break; - } + // On headless SKUs like NanoServer and IoT, window style can only be the default value 'Normal'. + switch (startinfo.WindowStyle) + { + case ProcessWindowStyle.Normal: + // SW_SHOWNORMAL + lpStartupInfo.wShowWindow = 1; + break; + case ProcessWindowStyle.Minimized: + // SW_SHOWMINIMIZED + lpStartupInfo.wShowWindow = 2; + break; + case ProcessWindowStyle.Maximized: + // SW_SHOWMAXIMIZED + lpStartupInfo.wShowWindow = 3; + break; + case ProcessWindowStyle.Hidden: + // SW_HIDE + lpStartupInfo.wShowWindow = 0; + break; } + } - // Create the new process suspended so we have a chance to get a corresponding Process object in case it terminates quickly. - creationFlags |= 0x00000004; + // Create the new process suspended so we have a chance to get a corresponding Process object in case it terminates quickly. + creationFlags |= 0x00000004; } /// @@ -2434,10 +2450,10 @@ private void SetStartupInfo(ProcessStartInfo startinfo, ref ProcessNativeMethods /// private Process StartWithCreateProcess(ProcessStartInfo startinfo) { - ProcessNativeMethods.STARTUPINFO lpStartupInfo = new ProcessNativeMethods.STARTUPINFO(); - SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation = new SafeNativeMethods.PROCESS_INFORMATION(); + ProcessNativeMethods.STARTUPINFO lpStartupInfo = new(); + SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation = new(); int error = 0; - GCHandle pinnedEnvironmentBlock = new GCHandle(); + GCHandle pinnedEnvironmentBlock = new(); IntPtr AddressOfEnvironmentBlock = IntPtr.Zero; string message = string.Empty; @@ -2501,11 +2517,11 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) } else { - Win32Exception win32ex = new Win32Exception(error); + Win32Exception win32ex = new(error); message = StringUtil.Format(ProcessResources.InvalidStartProcess, win32ex.Message); } - er = er ?? new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + er ??= new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } @@ -2529,23 +2545,23 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) IntPtr token = WindowsIdentity.GetCurrent().Token; if (!ProcessNativeMethods.CreateEnvironmentBlock(out AddressOfEnvironmentBlock, token, false)) { - Win32Exception win32ex = new Win32Exception(error); + Win32Exception win32ex = new(error); message = StringUtil.Format(ProcessResources.InvalidStartProcess, win32ex.Message); var errorRecord = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(errorRecord); } } - ProcessNativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new ProcessNativeMethods.SECURITY_ATTRIBUTES(); - ProcessNativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new ProcessNativeMethods.SECURITY_ATTRIBUTES(); + ProcessNativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new(); + ProcessNativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new(); flag = ProcessNativeMethods.CreateProcess(null, cmdLine, lpProcessAttributes, lpThreadAttributes, true, creationFlags, AddressOfEnvironmentBlock, startinfo.WorkingDirectory, lpStartupInfo, lpProcessInformation); if (!flag) { error = Marshal.GetLastWin32Error(); - Win32Exception win32ex = new Win32Exception(error); + Win32Exception win32ex = new(error); message = StringUtil.Format(ProcessResources.InvalidStartProcess, win32ex.Message); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } @@ -2587,7 +2603,7 @@ private Process StartWithShellExecute(ProcessStartInfo startInfo) catch (Win32Exception ex) { string message = StringUtil.Format(ProcessResources.InvalidStartProcess, ex.Message); - ErrorRecord er = new ErrorRecord(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + ErrorRecord er = new(new InvalidOperationException(message), "InvalidOperationException", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(er); } @@ -2607,7 +2623,7 @@ internal class ProcessCollection /// JobObjectHandle is a reference to the job object used to track /// the child processes created by the main process hosted by the Start-Process cmdlet. /// - private Microsoft.PowerShell.Commands.SafeJobHandle _jobObjectHandle; + private readonly Microsoft.PowerShell.Commands.SafeJobHandle _jobObjectHandle; /// /// ProcessCollection constructor. @@ -2638,7 +2654,7 @@ internal void CheckJobStatus(object stateInfo) ManualResetEvent emptyJobAutoEvent = (ManualResetEvent)stateInfo; int dwSize = 0; const int JOB_OBJECT_BASIC_PROCESS_ID_LIST = 3; - JOBOBJECT_BASIC_PROCESS_ID_LIST JobList = new JOBOBJECT_BASIC_PROCESS_ID_LIST(); + JOBOBJECT_BASIC_PROCESS_ID_LIST JobList = new(); dwSize = Marshal.SizeOf(JobList); if (NativeMethods.QueryInformationJobObject(_jobObjectHandle, @@ -2663,7 +2679,7 @@ internal void CheckJobStatus(object stateInfo) internal void WaitOne(ManualResetEvent waitHandleToUse) { TimerCallback jobObjectStatusCb = this.CheckJobStatus; - using (Timer stateTimer = new Timer(jobObjectStatusCb, waitHandleToUse, 0, 1000)) + using (Timer stateTimer = new(jobObjectStatusCb, waitHandleToUse, 0, 1000)) { waitHandleToUse.WaitOne(); } @@ -3029,4 +3045,3 @@ public string ProcessName #endregion ProcessCommandException } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/PropertyCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/PropertyCommandBase.cs index 5a73d16e40e..edc0bbc3a91 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/PropertyCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/PropertyCommandBase.cs @@ -4,8 +4,6 @@ using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/RemovePropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/RemovePropertyCommand.cs index 1f02a4fc6d1..cc60d91adbe 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/RemovePropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/RemovePropertyCommand.cs @@ -4,8 +4,6 @@ using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/RenamePropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/RenamePropertyCommand.cs index 3bed667fb0f..bdefc6b2c64 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/RenamePropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/RenamePropertyCommand.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ResolvePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ResolvePathCommand.cs index 8fa26142c5b..fcc9aef195f 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ResolvePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ResolvePathCommand.cs @@ -5,8 +5,6 @@ using System.Collections.ObjectModel; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -175,4 +173,3 @@ protected override void ProcessRecord() } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs index cf3de736631..a089f204654 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs @@ -5,18 +5,17 @@ using System; using System.Collections.Generic; -using System.ServiceProcess; +using System.ComponentModel; // Win32Exception using System.Diagnostics.CodeAnalysis; -using Dbg = System.Management.Automation.Diagnostics; using System.Management.Automation; using System.Management.Automation.Internal; -using System.ComponentModel; // Win32Exception -using System.Runtime.Serialization; using System.Runtime.InteropServices; // Marshal, DllImport -using System.Security.Permissions; +using System.Runtime.Serialization; using System.Security.AccessControl; -using NakedWin32Handle = System.IntPtr; +using System.ServiceProcess; +using Dbg = System.Management.Automation.Diagnostics; using DWORD = System.UInt32; +using NakedWin32Handle = System.IntPtr; namespace Microsoft.PowerShell.Commands { @@ -135,7 +134,7 @@ internal void SetServiceSecurityDescriptor( if (!status) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); bool accessDenied = exception.NativeErrorCode == NativeMethods.ERROR_ACCESS_DENIED; WriteNonTerminatingError( service, @@ -180,7 +179,7 @@ internal enum SelectionMode /// Select services by Service name. /// ServiceName = 3 - }; + } /// /// Holds the selection mode setting. /// @@ -291,28 +290,19 @@ public ServiceController[] InputObject #region Internal /// - /// Retrieve the master list of all services. + /// Gets an array of all services. /// - /// + /// + /// An array of components that represents all the service resources. + /// /// /// MSDN does not document the list of exceptions, /// but it is reasonable to expect that SecurityException is /// among them. Errors here will terminate the cmdlet. /// - internal ServiceController[] AllServices - { - get - { - if (_allServices == null) - { - _allServices = ServiceController.GetServices(); - } + internal ServiceController[] AllServices => _allServices ??= ServiceController.GetServices(); - return _allServices; - } - } - - private ServiceController[] _allServices = null; + private ServiceController[] _allServices; internal ServiceController GetOneService(string nameOfService) { @@ -381,7 +371,7 @@ private static int ServiceComparison(ServiceController x, ServiceController y) /// private List MatchingServicesByServiceName() { - List matchingServices = new List(); + List matchingServices = new(); if (serviceNames == null) { @@ -444,7 +434,7 @@ private List MatchingServicesByServiceName() /// private List MatchingServicesByDisplayName() { - List matchingServices = new List(); + List matchingServices = new(); if (DisplayName == null) { Diagnostics.Assert(false, "null DisplayName"); @@ -487,7 +477,7 @@ private List MatchingServicesByDisplayName() /// private List MatchingServicesByInput() { - List matchingServices = new List(); + List matchingServices = new(); if (InputObject == null) { Diagnostics.Assert(false, "null InputObject"); @@ -667,10 +657,10 @@ private PSObject AddProperties(ServiceController service) lpDatabaseName: null, dwDesiredAccess: NativeMethods.SC_MANAGER_CONNECT ); - if (IntPtr.Zero == hScManager) + if (hScManager == IntPtr.Zero) { lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -684,10 +674,10 @@ private PSObject AddProperties(ServiceController service) service.ServiceName, NativeMethods.SERVICE_QUERY_CONFIG ); - if (IntPtr.Zero == hService) + if (hService == IntPtr.Zero) { lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -696,13 +686,13 @@ private PSObject AddProperties(ServiceController service) ErrorCategory.PermissionDenied); } - NativeMethods.SERVICE_DESCRIPTIONW description = new NativeMethods.SERVICE_DESCRIPTIONW(); + NativeMethods.SERVICE_DESCRIPTIONW description = new(); bool querySuccessful = NativeMethods.QueryServiceConfig2(hService, NativeMethods.SERVICE_CONFIG_DESCRIPTION, out description); - NativeMethods.SERVICE_DELAYED_AUTO_START_INFO autostartInfo = new NativeMethods.SERVICE_DELAYED_AUTO_START_INFO(); + NativeMethods.SERVICE_DELAYED_AUTO_START_INFO autostartInfo = new(); querySuccessful = querySuccessful && NativeMethods.QueryServiceConfig2(hService, NativeMethods.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, out autostartInfo); - NativeMethods.QUERY_SERVICE_CONFIG serviceInfo = new NativeMethods.QUERY_SERVICE_CONFIG(); + NativeMethods.QUERY_SERVICE_CONFIG serviceInfo = new(); querySuccessful = querySuccessful && NativeMethods.QueryServiceConfig(hService, out serviceInfo); if (!querySuccessful) @@ -716,7 +706,7 @@ private PSObject AddProperties(ServiceController service) ); } - PSProperty noteProperty = new PSProperty("UserName", serviceInfo.lpServiceStartName); + PSProperty noteProperty = new("UserName", serviceInfo.lpServiceStartName); serviceAsPSObj.Properties.Add(noteProperty, true); serviceAsPSObj.TypeNames.Insert(0, "System.Service.ServiceController#UserName"); @@ -738,7 +728,7 @@ private PSObject AddProperties(ServiceController service) } finally { - if (IntPtr.Zero != hService) + if (hService != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hService); if (!succeeded) @@ -747,7 +737,7 @@ private PSObject AddProperties(ServiceController service) } } - if (IntPtr.Zero != hScManager) + if (hScManager != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hScManager); if (!succeeded) @@ -908,14 +898,14 @@ internal bool DoStartService(ServiceController serviceController) } catch (Win32Exception e) { - if (NativeMethods.ERROR_SERVICE_ALREADY_RUNNING != e.NativeErrorCode) + if (e.NativeErrorCode != NativeMethods.ERROR_SERVICE_ALREADY_RUNNING) exception = e; } catch (InvalidOperationException e) { Win32Exception eInner = e.InnerException as Win32Exception; if (eInner == null - || NativeMethods.ERROR_SERVICE_ALREADY_RUNNING != eInner.NativeErrorCode) + || eInner.NativeErrorCode != NativeMethods.ERROR_SERVICE_ALREADY_RUNNING) { exception = e; } @@ -961,7 +951,7 @@ internal List DoStopService(ServiceController serviceControll // Ignore ServiceController.CanStop. CanStop will be set false // if the service is not running, but this is not an error. - List stoppedServices = new List(); + List stoppedServices = new(); ServiceController[] dependentServices = null; try @@ -1025,7 +1015,7 @@ internal List DoStopService(ServiceController serviceControll } catch (Win32Exception e) { - if (NativeMethods.ERROR_SERVICE_NOT_ACTIVE != e.NativeErrorCode) + if (e.NativeErrorCode != NativeMethods.ERROR_SERVICE_NOT_ACTIVE) exception = e; } catch (InvalidOperationException e) @@ -1033,7 +1023,7 @@ internal List DoStopService(ServiceController serviceControll Win32Exception eInner = e.InnerException as Win32Exception; if (eInner == null - || NativeMethods.ERROR_SERVICE_NOT_ACTIVE != eInner.NativeErrorCode) + || eInner.NativeErrorCode != NativeMethods.ERROR_SERVICE_NOT_ACTIVE) { exception = e; } @@ -1086,9 +1076,9 @@ internal List DoStopService(ServiceController serviceControll /// True if all dependent services are stopped /// False if not all dependent services are stopped /// - private bool HaveAllDependentServicesStopped(ServiceController[] dependentServices) + private static bool HaveAllDependentServicesStopped(ServiceController[] dependentServices) { - return Array.TrueForAll(dependentServices, service => service.Status == ServiceControllerStatus.Stopped); + return Array.TrueForAll(dependentServices, static service => service.Status == ServiceControllerStatus.Stopped); } /// @@ -1118,7 +1108,7 @@ internal bool DoPauseService(ServiceController serviceController) } catch (Win32Exception e) { - if (NativeMethods.ERROR_SERVICE_NOT_ACTIVE == e.NativeErrorCode) + if (e.NativeErrorCode == NativeMethods.ERROR_SERVICE_NOT_ACTIVE) { serviceNotRunning = true; } @@ -1129,7 +1119,7 @@ internal bool DoPauseService(ServiceController serviceController) { Win32Exception eInner = e.InnerException as Win32Exception; if (eInner != null - && NativeMethods.ERROR_SERVICE_NOT_ACTIVE == eInner.NativeErrorCode) + && eInner.NativeErrorCode == NativeMethods.ERROR_SERVICE_NOT_ACTIVE) { serviceNotRunning = true; } @@ -1199,7 +1189,7 @@ internal bool DoResumeService(ServiceController serviceController) } catch (Win32Exception e) { - if (NativeMethods.ERROR_SERVICE_NOT_ACTIVE == e.NativeErrorCode) + if (e.NativeErrorCode == NativeMethods.ERROR_SERVICE_NOT_ACTIVE) { serviceNotRunning = true; } @@ -1210,7 +1200,7 @@ internal bool DoResumeService(ServiceController serviceController) { Win32Exception eInner = e.InnerException as Win32Exception; if (eInner != null - && NativeMethods.ERROR_SERVICE_NOT_ACTIVE == eInner.NativeErrorCode) + && eInner.NativeErrorCode == NativeMethods.ERROR_SERVICE_NOT_ACTIVE) { serviceNotRunning = true; } @@ -1496,7 +1486,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [Alias("ServiceName", "SN")] public new string Name { - get { return serviceName; } + get + { + return serviceName; + } set { @@ -1524,7 +1517,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [Alias("DN")] public new string DisplayName { - get { return displayName; } + get + { + return displayName; + } set { @@ -1553,7 +1549,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [ValidateNotNullOrEmpty] public string Description { - get { return description; } + get + { + return description; + } set { @@ -1576,7 +1575,10 @@ public string Description [ValidateNotNullOrEmpty] public ServiceStartupType StartupType { - get { return startupType; } + get + { + return startupType; + } set { @@ -1612,7 +1614,10 @@ public string SecurityDescriptorSddl [ValidateSetAttribute(new string[] { "Running", "Stopped", "Paused" })] public string Status { - get { return serviceStatus; } + get + { + return serviceStatus; + } set { @@ -1706,14 +1711,14 @@ protected override void ProcessRecord() catch (ArgumentException ex) { // cannot use WriteNonterminatingError as service is null - ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.ObjectNotFound, Name); + ErrorRecord er = new(ex, "ArgumentException", ErrorCategory.ObjectNotFound, Name); WriteError(er); return; } catch (InvalidOperationException ex) { // cannot use WriteNonterminatingError as service is null - ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.ObjectNotFound, Name); + ErrorRecord er = new(ex, "InvalidOperationException", ErrorCategory.ObjectNotFound, Name); WriteError(er); return; } @@ -1738,10 +1743,10 @@ protected override void ProcessRecord() NativeMethods.SC_MANAGER_CONNECT ); - if (IntPtr.Zero == hScManager) + if (hScManager == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1757,10 +1762,10 @@ protected override void ProcessRecord() NativeMethods.SERVICE_CHANGE_CONFIG | NativeMethods.WRITE_DAC | NativeMethods.WRITE_OWNER ); - if (IntPtr.Zero == hService) + if (hService == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1771,7 +1776,7 @@ protected override void ProcessRecord() } // Modify startup type or display name or credential if (!string.IsNullOrEmpty(DisplayName) - || ServiceStartupType.InvalidValue != StartupType || Credential != null) + || StartupType != ServiceStartupType.InvalidValue || Credential != null) { DWORD dwStartType = NativeMethods.SERVICE_NO_CHANGE; if (!NativeMethods.TryGetNativeStartupType(StartupType, out dwStartType)) @@ -1806,7 +1811,7 @@ protected override void ProcessRecord() if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1817,7 +1822,7 @@ protected override void ProcessRecord() } } - NativeMethods.SERVICE_DESCRIPTIONW sd = new NativeMethods.SERVICE_DESCRIPTIONW(); + NativeMethods.SERVICE_DESCRIPTIONW sd = new(); sd.lpDescription = Description; int size = Marshal.SizeOf(sd); IntPtr buffer = Marshal.AllocCoTaskMem(size); @@ -1831,7 +1836,7 @@ protected override void ProcessRecord() if (!status) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1841,7 +1846,7 @@ protected override void ProcessRecord() } // Set the delayed auto start - NativeMethods.SERVICE_DELAYED_AUTO_START_INFO ds = new NativeMethods.SERVICE_DELAYED_AUTO_START_INFO(); + NativeMethods.SERVICE_DELAYED_AUTO_START_INFO ds = new(); ds.fDelayedAutostart = StartupType == ServiceStartupType.AutomaticDelayedStart; size = Marshal.SizeOf(ds); delayedAutoStartInfoBuffer = Marshal.AllocCoTaskMem(size); @@ -1855,7 +1860,7 @@ protected override void ProcessRecord() if (!status) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -1915,24 +1920,24 @@ protected override void ProcessRecord() if (PassThru.IsPresent) { // To display the service, refreshing the service would not show the display name after updating - ServiceController displayservice = new ServiceController(Name); + ServiceController displayservice = new(Name); WriteObject(displayservice); } } finally { - if (IntPtr.Zero != delayedAutoStartInfoBuffer) + if (delayedAutoStartInfoBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(delayedAutoStartInfoBuffer); } - if (IntPtr.Zero != hService) + if (hService != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hService); if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1942,13 +1947,13 @@ protected override void ProcessRecord() } } - if (IntPtr.Zero != hScManager) + if (hScManager != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hScManager); if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -1961,7 +1966,7 @@ protected override void ProcessRecord() } finally { - if (IntPtr.Zero != password) + if (password != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(password); } @@ -2134,10 +2139,10 @@ protected override void BeginProcessing() null, NativeMethods.SC_MANAGER_CONNECT | NativeMethods.SC_MANAGER_CREATE_SERVICE ); - if (IntPtr.Zero == hScManager) + if (hScManager == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2211,10 +2216,10 @@ protected override void BeginProcessing() username, password ); - if (IntPtr.Zero == hService) + if (hService == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2227,7 +2232,7 @@ protected override void BeginProcessing() } // Set the service description - NativeMethods.SERVICE_DESCRIPTIONW sd = new NativeMethods.SERVICE_DESCRIPTIONW(); + NativeMethods.SERVICE_DESCRIPTIONW sd = new(); sd.lpDescription = Description; int size = Marshal.SizeOf(sd); IntPtr buffer = Marshal.AllocCoTaskMem(size); @@ -2241,7 +2246,7 @@ protected override void BeginProcessing() if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2255,7 +2260,7 @@ protected override void BeginProcessing() // Set the delayed auto start if (StartupType == ServiceStartupType.AutomaticDelayedStart) { - NativeMethods.SERVICE_DELAYED_AUTO_START_INFO ds = new NativeMethods.SERVICE_DELAYED_AUTO_START_INFO(); + NativeMethods.SERVICE_DELAYED_AUTO_START_INFO ds = new(); ds.fDelayedAutostart = true; size = Marshal.SizeOf(ds); delayedAutoStartInfoBuffer = Marshal.AllocCoTaskMem(size); @@ -2269,7 +2274,7 @@ protected override void BeginProcessing() if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2293,23 +2298,23 @@ protected override void BeginProcessing() } finally { - if (IntPtr.Zero != delayedAutoStartInfoBuffer) + if (delayedAutoStartInfoBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(delayedAutoStartInfoBuffer); } - if (IntPtr.Zero != password) + if (password != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(password); } - if (IntPtr.Zero != hService) + if (hService != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hService); if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2321,13 +2326,13 @@ protected override void BeginProcessing() } } - if (IntPtr.Zero != hScManager) + if (hScManager != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hScManager); if (!succeeded) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( Name, DisplayName, @@ -2403,14 +2408,14 @@ protected override void ProcessRecord() catch (ArgumentException ex) { // Cannot use WriteNonterminatingError as service is null - ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.ObjectNotFound, Name); + ErrorRecord er = new(ex, "ArgumentException", ErrorCategory.ObjectNotFound, Name); WriteError(er); return; } catch (InvalidOperationException ex) { // Cannot use WriteNonterminatingError as service is null - ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.ObjectNotFound, Name); + ErrorRecord er = new(ex, "InvalidOperationException", ErrorCategory.ObjectNotFound, Name); WriteError(er); return; } @@ -2433,10 +2438,10 @@ protected override void ProcessRecord() lpDatabaseName: null, dwDesiredAccess: NativeMethods.SC_MANAGER_ALL_ACCESS ); - if (IntPtr.Zero == hScManager) + if (hScManager == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteObject(exception); WriteNonTerminatingError( service, @@ -2452,10 +2457,10 @@ protected override void ProcessRecord() Name, NativeMethods.SERVICE_DELETE ); - if (IntPtr.Zero == hService) + if (hService == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -2470,7 +2475,7 @@ protected override void ProcessRecord() if (!status) { int lastError = Marshal.GetLastWin32Error(); - Win32Exception exception = new Win32Exception(lastError); + Win32Exception exception = new(lastError); WriteNonTerminatingError( service, exception, @@ -2481,7 +2486,7 @@ protected override void ProcessRecord() } finally { - if (IntPtr.Zero != hService) + if (hService != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hService); if (!succeeded) @@ -2491,7 +2496,7 @@ protected override void ProcessRecord() } } - if (IntPtr.Zero != hScManager) + if (hScManager != IntPtr.Zero) { bool succeeded = NativeMethods.CloseServiceHandle(hScManager); if (!succeeded) @@ -2707,7 +2712,7 @@ internal struct SERVICE_DESCRIPTIONW { [MarshalAs(UnmanagedType.LPWStr)] internal string lpDescription; - }; + } [StructLayout(LayoutKind.Sequential)] internal struct QUERY_SERVICE_CONFIG @@ -2721,13 +2726,13 @@ internal struct QUERY_SERVICE_CONFIG [MarshalAs(UnmanagedType.LPWStr)] internal string lpDependencies; [MarshalAs(UnmanagedType.LPWStr)] internal string lpServiceStartName; [MarshalAs(UnmanagedType.LPWStr)] internal string lpDisplayName; - }; + } [StructLayout(LayoutKind.Sequential)] internal struct SERVICE_DELAYED_AUTO_START_INFO { internal bool fDelayedAutostart; - }; + } [DllImport(PinvokeDllNames.CreateServiceWDllName, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern @@ -2830,7 +2835,7 @@ internal static bool QueryServiceConfig(NakedWin32Handle hService, out NativeMet cbBufSize: 0, pcbBytesNeeded: out bufferSizeNeeded); - if (status != true && Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) + if (!status && Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) { return status; } @@ -2868,7 +2873,7 @@ internal static bool QueryServiceConfig2(NakedWin32Handle hService, DWORD inf cbBufSize: 0, pcbBytesNeeded: out bufferSizeNeeded); - if (status != true && Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) + if (!status && Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) { return status; } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs index bcb7330c674..69cea8361a8 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs @@ -17,9 +17,10 @@ namespace Microsoft.PowerShell.Commands /// [Cmdlet(VerbsCommon.Set, "Clipboard", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium, HelpUri = "https://go.microsoft.com/fwlink/?LinkId=2109826")] [Alias("scb")] + [OutputType(typeof(string))] public class SetClipboardCommand : PSCmdlet { - private List _contentList = new List(); + private readonly List _contentList = new(); /// /// Property that sets clipboard content. @@ -37,6 +38,12 @@ public class SetClipboardCommand : PSCmdlet [Parameter] public SwitchParameter Append { get; set; } + /// + /// Gets or sets if the values sent down the pipeline. + /// + [Parameter] + public SwitchParameter PassThru { get; set; } + /// /// This method implements the BeginProcessing method for Set-Clipboard command. /// @@ -53,6 +60,11 @@ protected override void ProcessRecord() if (Value != null) { _contentList.AddRange(Value); + + if (PassThru) + { + WriteObject(Value); + } } } @@ -84,7 +96,7 @@ private void SetClipboardContent(List contentList, bool append) return; } - StringBuilder content = new StringBuilder(); + StringBuilder content = new(); if (append) { content.AppendLine(Clipboard.GetText()); @@ -102,7 +114,7 @@ private void SetClipboardContent(List contentList, bool append) if (verboseString.Length >= 20) { verboseString = verboseString.Substring(0, 20); - verboseString = verboseString + " ..."; + verboseString += " ..."; } } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetContentCommand.cs index 4e040517b02..44f4d904d33 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetContentCommand.cs @@ -4,8 +4,6 @@ using System.Management.Automation; using System.Management.Automation.Internal; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -31,7 +29,7 @@ internal override void BeforeOpenStreams(string[] paths) throw PSTraceSource.NewArgumentNullException(nameof(paths)); } - CmdletProviderContext context = new CmdletProviderContext(GetCurrentContext()); + CmdletProviderContext context = new(GetCurrentContext()); foreach (string path in paths) { @@ -90,4 +88,3 @@ internal override bool CallShouldProcess(string path) #endregion protected members } } - diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs index 9e2018342ba..7c5f43aad2b 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs @@ -1,11 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -46,7 +43,10 @@ public string[] Path [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return paths; } + get + { + return paths; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs index 6875f7a2164..e6b33142457 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs @@ -4,7 +4,6 @@ #nullable enable using System; -using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Management.Automation; @@ -58,7 +57,7 @@ public class TestConnectionCommand : PSCmdlet, IDisposable private static byte[]? s_DefaultSendBuffer; - private readonly CancellationTokenSource _dnsLookupCancel = new CancellationTokenSource(); + private readonly CancellationTokenSource _dnsLookupCancel = new(); private bool _disposed; @@ -294,7 +293,7 @@ private void ProcessConnectionByTCPPort(string targetNameOrAddress) return; } - TcpClient client = new TcpClient(); + TcpClient client = new(); try { @@ -351,11 +350,11 @@ private void ProcessTraceroute(string targetNameOrAddress) } int currentHop = 1; - PingOptions pingOptions = new PingOptions(currentHop, DontFragment.IsPresent); + PingOptions pingOptions = new(currentHop, DontFragment.IsPresent); PingReply reply; PingReply discoveryReply; int timeout = TimeoutSeconds * 1000; - Stopwatch timer = new Stopwatch(); + Stopwatch timer = new(); IPAddress hopAddress; do @@ -437,7 +436,7 @@ private void ProcessTraceroute(string targetNameOrAddress) resolvedTargetName, ex.Message); Exception pingException = new PingException(message, ex.InnerException); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -500,7 +499,7 @@ private void ProcessMTUSize(string targetNameOrAddress) try { - PingOptions pingOptions = new PingOptions(MaxHops, true); + PingOptions pingOptions = new(MaxHops, true); int retry = 1; while (LowMTUSize < (HighMTUSize - 1)) @@ -536,7 +535,7 @@ private void ProcessMTUSize(string targetNameOrAddress) targetAddress, reply.Status.ToString()); Exception pingException = new PingException(message); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -561,7 +560,7 @@ private void ProcessMTUSize(string targetNameOrAddress) { string message = StringUtil.Format(TestConnectionResources.NoPingResult, targetAddress, ex.Message); Exception pingException = new PingException(message, ex.InnerException); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -604,7 +603,7 @@ private void ProcessPing(string targetNameOrAddress) byte[] buffer = GetSendBuffer(BufferSize); PingReply reply; - PingOptions pingOptions = new PingOptions(MaxHops, DontFragment.IsPresent); + PingOptions pingOptions = new(MaxHops, DontFragment.IsPresent); int timeout = TimeoutSeconds * 1000; int delay = Delay * 1000; @@ -618,7 +617,7 @@ private void ProcessPing(string targetNameOrAddress) { string message = StringUtil.Format(TestConnectionResources.NoPingResult, resolvedTargetName, ex.Message); Exception pingException = new PingException(message, ex.InnerException); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -679,7 +678,7 @@ private bool TryResolveNameOrAddress( resolvedTargetName, TestConnectionResources.TargetAddressAbsent); Exception pingException = new PingException(message, null); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -723,7 +722,7 @@ private bool TryResolveNameOrAddress( resolvedTargetName, TestConnectionResources.CannotResolveTargetName); Exception pingException = new PingException(message, ex); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -745,7 +744,7 @@ private bool TryResolveNameOrAddress( resolvedTargetName, TestConnectionResources.TargetAddressAbsent); Exception pingException = new PingException(message, null); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, @@ -794,7 +793,7 @@ private IPHostEntry GetCancellableHostEntry(string targetNameOrAddress) // Users most often use the default buffer size so we cache the buffer. // Creates and fills a send buffer. This follows the ping.exe and CoreFX model. - private byte[] GetSendBuffer(int bufferSize) + private static byte[] GetSendBuffer(int bufferSize) { if (bufferSize == DefaultSendBufferSize && s_DefaultSendBuffer != null) { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs index 106c9038981..69e8860f3ab 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs @@ -82,7 +82,7 @@ protected override void ProcessRecord() foreach (string tzname in Name) { TimeZoneInfo[] timeZones = TimeZoneHelper.LookupSystemTimeZoneInfoByName(tzname); - if (0 < timeZones.Length) + if (timeZones.Length > 0) { // manually process each object in the array, so if there is only a single // entry then the returned type is TimeZoneInfo and not TimeZoneInfo[], and @@ -188,7 +188,7 @@ protected override void ProcessRecord() { // lookup the time zone name and make sure we have one (and only one) match TimeZoneInfo[] timeZones = TimeZoneHelper.LookupSystemTimeZoneInfoByName(Name); - if (0 == timeZones.Length) + if (timeZones.Length == 0) { string message = string.Format(CultureInfo.InvariantCulture, TimeZoneResources.TimeZoneNameNotFound, Name); @@ -198,7 +198,7 @@ protected override void ProcessRecord() ErrorCategory.InvalidArgument, "Name")); } - else if (1 < timeZones.Length) + else if (timeZones.Length > 1) { string message = string.Format(CultureInfo.InvariantCulture, TimeZoneResources.MultipleMatchingTimeZones, Name); @@ -254,14 +254,14 @@ protected override void ProcessRecord() try { // construct and populate a new DYNAMIC_TIME_ZONE_INFORMATION structure - NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION dtzi = new NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION(); + NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION dtzi = new(); dtzi.Bias -= (int)InputObject.BaseUtcOffset.TotalMinutes; dtzi.StandardName = InputObject.StandardName; dtzi.DaylightName = InputObject.DaylightName; dtzi.TimeZoneKeyName = InputObject.Id; // Request time zone transition information for the current year - NativeMethods.TIME_ZONE_INFORMATION tzi = new NativeMethods.TIME_ZONE_INFORMATION(); + NativeMethods.TIME_ZONE_INFORMATION tzi = new(); if (!NativeMethods.GetTimeZoneInformationForYear((ushort)DateTime.Now.Year, ref dtzi, ref tzi)) { ThrowWin32Error(); @@ -343,7 +343,7 @@ protected bool HasAccess try { // setup the privileges being checked - NativeMethods.PRIVILEGE_SET ps = new NativeMethods.PRIVILEGE_SET() + NativeMethods.PRIVILEGE_SET ps = new() { PrivilegeCount = 1, Control = 1, @@ -390,7 +390,7 @@ protected void SetAccessToken(bool enable) try { // setup the privileges being requested - NativeMethods.TOKEN_PRIVILEGES tp = new NativeMethods.TOKEN_PRIVILEGES() + NativeMethods.TOKEN_PRIVILEGES tp = new() { PrivilegeCount = 1, Luid = 0, @@ -428,15 +428,8 @@ protected void ThrowWin32Error() #region Win32 interop helper - internal class NativeMethods + internal static class NativeMethods { - /// - /// Private constructor to prevent instantiation. - /// - private NativeMethods() - { - } - #region Native DLL locations private const string SetDynamicTimeZoneApiDllName = "api-ms-win-core-timezone-l1-1-0.dll"; @@ -779,8 +772,8 @@ internal static class TimeZoneHelper /// A TimeZoneInfo object array containing information about the specified system time zones. internal static TimeZoneInfo[] LookupSystemTimeZoneInfoByName(string name) { - WildcardPattern namePattern = new WildcardPattern(name, WildcardOptions.IgnoreCase); - List tzi = new List(); + WildcardPattern namePattern = new(name, WildcardOptions.IgnoreCase); + List tzi = new(); // get the available system time zones ReadOnlyCollection zones = TimeZoneInfo.GetSystemTimeZones(); diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/WriteContentCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/WriteContentCommandBase.cs index 7ccf63cdf8e..25ecd672c4c 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/WriteContentCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/WriteContentCommandBase.cs @@ -8,8 +8,6 @@ using System.Management.Automation; using System.Management.Automation.Provider; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -145,7 +143,7 @@ protected override void ProcessRecord() catch (Exception e) // Catch-all OK. 3rd party callout { ProviderInvocationException providerException = - new ProviderInvocationException( + new( "ProviderContentWriteError", SessionStateStrings.ProviderContentWriteError, holder.PathInfo.Provider, @@ -260,7 +258,7 @@ internal List GetContentWriters( // Create the results array - List results = new List(); + List results = new(); foreach (PathInfo pathInfo in pathInfos) { @@ -313,7 +311,7 @@ internal List GetContentWriters( if (writers.Count == 1 && writers[0] != null) { ContentHolder holder = - new ContentHolder(pathInfo, null, writers[0]); + new(pathInfo, null, writers[0]); results.Add(holder); } 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 0f2f59cdc08..bff5cc802d0 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -8,7 +8,7 @@ - + @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddMember.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddMember.cs index 2ea6d6e20ae..efb035b7785 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddMember.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddMember.cs @@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.Commands HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097109", RemotingCapability = RemotingCapability.None)] public class AddMemberCommand : PSCmdlet { - private static readonly object s_notSpecified = new object(); + private static readonly object s_notSpecified = new(); private static bool HasBeenSpecified(object obj) { @@ -37,9 +37,9 @@ private static bool HasBeenSpecified(object obj) [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = NotePropertyMultiMemberSet)] public PSObject InputObject { - set { _inputObject = value; } - get { return _inputObject; } + + set { _inputObject = value; } } private PSMemberTypes _memberType; @@ -50,9 +50,9 @@ public PSObject InputObject [Alias("Type")] public PSMemberTypes MemberType { - set { _memberType = value; } - get { return _memberType; } + + set { _memberType = value; } } private string _memberName; @@ -62,9 +62,9 @@ public PSMemberTypes MemberType [Parameter(Mandatory = true, Position = 1, ParameterSetName = "MemberSet")] public string Name { - set { _memberName = value; } - get { return _memberName; } + + set { _memberName = value; } } private object _value1 = s_notSpecified; @@ -74,9 +74,9 @@ public string Name [Parameter(Position = 2, ParameterSetName = "MemberSet")] public object Value { - set { _value1 = value; } - get { return _value1; } + + set { _value1 = value; } } private object _value2 = s_notSpecified; @@ -86,9 +86,9 @@ public object Value [Parameter(Position = 3, ParameterSetName = "MemberSet")] public object SecondValue { - set { _value2 = value; } - get { return _value2; } + + set { _value2 = value; } } private string _typeName; @@ -102,9 +102,9 @@ public object SecondValue [ValidateNotNullOrEmpty] public string TypeName { - set { _typeName = value; } - get { return _typeName; } + + set { _typeName = value; } } private bool _force; @@ -116,9 +116,9 @@ public string TypeName [Parameter(ParameterSetName = NotePropertyMultiMemberSet)] public SwitchParameter Force { - set { _force = value; } - get { return _force; } + + set { _force = value; } } private bool _passThru /* = false */; @@ -132,9 +132,9 @@ public SwitchParameter Force [Parameter(ParameterSetName = NotePropertyMultiMemberSet)] public SwitchParameter PassThru { - set { _passThru = value; } - get { return _passThru; } + + set { _passThru = value; } } #region Simplifying NoteProperty Declaration @@ -152,9 +152,9 @@ public SwitchParameter PassThru [ValidateNotNullOrEmpty] public string NotePropertyName { - set { _notePropertyName = value; } - get { return _notePropertyName; } + + set { _notePropertyName = value; } } private object _notePropertyValue; @@ -165,9 +165,9 @@ public string NotePropertyName [AllowNull] public object NotePropertyValue { - set { _notePropertyValue = value; } - get { return _notePropertyValue; } + + set { _notePropertyValue = value; } } // Use IDictionary to support both Hashtable and OrderedHashtable @@ -221,7 +221,7 @@ private void EnsureValue1HasBeenSpecified() { if (!HasBeenSpecified(_value1)) { - Collection fdc = new Collection(); + Collection fdc = new(); fdc.Add(new FieldDescription("Value")); string prompt = StringUtil.Format(AddMember.Value1Prompt, _memberType); Dictionary result = this.Host.UI.Prompt(prompt, null, fdc); @@ -388,7 +388,7 @@ protected override void ProcessRecord() memberCount++; } - memberCountHelper = memberCountHelper >> 1; + memberCountHelper >>= 1; } if (memberCount != 1) @@ -531,9 +531,9 @@ private void UpdateTypeNames() private ErrorRecord NewError(string errorId, string resourceId, object targetObject, params object[] args) { - ErrorDetails details = new ErrorDetails(this.GetType().GetTypeInfo().Assembly, + ErrorDetails details = new(this.GetType().GetTypeInfo().Assembly, "Microsoft.PowerShell.Commands.Utility.resources.AddMember", resourceId, args); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.InvalidOperation, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs index 54a841c5f43..5ce91a36a48 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Management.Automation; using System.Management.Automation.Internal; +using System.Management.Automation.Security; using System.Reflection; using System.Runtime.Loader; using System.Security; @@ -153,7 +154,7 @@ public string[] Path string[] pathValue = value; - List resolvedPaths = new List(); + List resolvedPaths = new(); // Verify that the paths are resolved and valid foreach (string path in pathValue) @@ -198,7 +199,7 @@ public string[] LiteralPath return; } - List resolvedPaths = new List(); + List resolvedPaths = new(); foreach (string path in value) { string literalPath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); @@ -230,7 +231,7 @@ private void ProcessPaths(List resolvedPaths) // Throw an error if it is an unrecognized extension default: - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception( StringUtil.Format(AddTypeStrings.FileExtensionNotSupported, currentExtension)), "EXTENSION_NOT_SUPPORTED", @@ -248,7 +249,7 @@ private void ProcessPaths(List resolvedPaths) else if (!string.Equals(activeExtension, currentExtension, StringComparison.OrdinalIgnoreCase)) { // All files must have the same extension otherwise throw. - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception( StringUtil.Format(AddTypeStrings.MultipleExtensionsNotSupported)), "MULTIPLE_EXTENSION_NOT_SUPPORTED", @@ -292,7 +293,10 @@ private void ProcessPaths(List resolvedPaths) [Alias("RA")] public string[] ReferencedAssemblies { - get { return _referencedAssemblies; } + get + { + return _referencedAssemblies; + } set { @@ -327,7 +331,7 @@ public string OutputAssembly // Try to resolve the path ProviderInfo provider = null; - Collection newPaths = new Collection(); + Collection newPaths = new(); try { @@ -336,7 +340,7 @@ public string OutputAssembly // Ignore the ItemNotFound -- we handle it. catch (ItemNotFoundException) { } - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception( StringUtil.Format(AddTypeStrings.OutputAssemblyDidNotResolve, _outputAssembly)), "INVALID_OUTPUT_ASSEMBLY", @@ -470,7 +474,7 @@ private string GenerateTypeSource(string typeNamespace, string typeName, string } // Get the -FromMember template for a given language - private string GetMethodTemplate(Language language) + private static string GetMethodTemplate(Language language) { switch (language) { @@ -486,7 +490,7 @@ private string GetMethodTemplate(Language language) } // Get the -FromMember namespace template for a given language - private string GetNamespaceTemplate(Language language) + private static string GetNamespaceTemplate(Language language) { switch (language) { @@ -502,7 +506,7 @@ private string GetNamespaceTemplate(Language language) } // Get the -FromMember namespace template for a given language - private string GetUsingTemplate(Language language) + private static string GetUsingTemplate(Language language) { switch (language) { @@ -520,7 +524,7 @@ private string GetUsingTemplate(Language language) // Generate the code for the using statements private string GetUsingSet(Language language) { - StringBuilder usingNamespaceSet = new StringBuilder(); + StringBuilder usingNamespaceSet = new(); switch (language) { @@ -546,8 +550,10 @@ private string GetUsingSet(Language language) /// protected override void BeginProcessing() { - // Prevent code compilation in ConstrainedLanguage mode - if (SessionState.LanguageMode == PSLanguageMode.ConstrainedLanguage) + // Prevent code compilation in ConstrainedLanguage mode, or NoLanguage mode under system lock down. + if (SessionState.LanguageMode == PSLanguageMode.ConstrainedLanguage || + (SessionState.LanguageMode == PSLanguageMode.NoLanguage && + SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce)) { ThrowTerminatingError( new ErrorRecord( @@ -578,7 +584,7 @@ protected override void EndProcessing() // assembly type without an output assembly if (string.IsNullOrEmpty(_outputAssembly) && this.MyInvocation.BoundParameters.ContainsKey(nameof(OutputType))) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception( string.Format( CultureInfo.CurrentCulture, @@ -630,21 +636,21 @@ protected override void EndProcessing() private static readonly string s_frameworkFolder = PathType.GetDirectoryName(typeof(object).Assembly.Location); // These assemblies are always automatically added to ReferencedAssemblies. - private static readonly Lazy s_autoReferencedAssemblies = new Lazy(InitAutoIncludedRefAssemblies); + private static readonly Lazy s_autoReferencedAssemblies = new(InitAutoIncludedRefAssemblies); // A HashSet of assembly names to be ignored if they are specified in '-ReferencedAssemblies' - private static readonly Lazy> s_refAssemblyNamesToIgnore = new Lazy>(InitRefAssemblyNamesToIgnore); + private static readonly Lazy> s_refAssemblyNamesToIgnore = new(InitRefAssemblyNamesToIgnore); // These assemblies are used, when ReferencedAssemblies parameter is not specified. - private static readonly Lazy> s_defaultAssemblies = new Lazy>(InitDefaultRefAssemblies); + private static readonly Lazy> s_defaultAssemblies = new(InitDefaultRefAssemblies); private bool InMemory { get { return string.IsNullOrEmpty(_outputAssembly); } } // These dictionaries prevent reloading already loaded and unchanged code. // We don't worry about unbounded growing of the cache because in .Net Core 2.0 we can not unload assemblies. // TODO: review if we will be able to unload assemblies after migrating to .Net Core 2.1. - private static readonly HashSet s_sourceTypesCache = new HashSet(); - private static readonly Dictionary s_sourceAssemblyCache = new Dictionary(); + private static readonly HashSet s_sourceTypesCache = new(); + private static readonly Dictionary s_sourceAssemblyCache = new(); private static readonly string s_defaultSdkDirectory = Utils.DefaultPowerShellAppBase; @@ -840,7 +846,7 @@ private string ResolveAssemblyName(string assembly, bool isForReferenceAssembly) // However, this does give us a massive usability improvement, as users can just say // Add-Type -AssemblyName Forms (instead of System.Windows.Forms) // This is just long, not unmaintainable. - private Assembly LoadAssemblyHelper(string assemblyName) + private static Assembly LoadAssemblyHelper(string assemblyName) { Assembly loadedAssembly = null; @@ -898,7 +904,7 @@ private void WriteTypes(Assembly assembly) #region SourceCodeProcessing - private OutputKind OutputAssemblyTypeToOutputKind(OutputAssemblyType outputType) + private static OutputKind OutputAssemblyTypeToOutputKind(OutputAssemblyType outputType) { switch (outputType) { @@ -914,12 +920,11 @@ private CommandLineArguments ParseCompilerOption(IEnumerable args) { string sdkDirectory = s_defaultSdkDirectory; string baseDirectory = this.SessionState.Path.CurrentLocation.Path; - string additionalReferenceDirectories = null; switch (Language) { case Language.CSharp: - return CSharpCommandLineParser.Default.Parse(args, baseDirectory, sdkDirectory, additionalReferenceDirectories); + return CSharpCommandLineParser.Default.Parse(args, baseDirectory, sdkDirectory); default: throw PSTraceSource.NewNotSupportedException(); @@ -996,7 +1001,7 @@ private void SourceCodeProcessing() } SourceText sourceText; - List syntaxTrees = new List(); + List syntaxTrees = new(); switch (ParameterSetName) { @@ -1075,12 +1080,12 @@ private void CompileToAssembly(List syntaxTrees, CompilationOptions private void CheckDuplicateTypes(Compilation compilation, out ConcurrentBag newTypes) { - AllNamedTypeSymbolsVisitor visitor = new AllNamedTypeSymbolsVisitor(); + AllNamedTypeSymbolsVisitor visitor = new(); visitor.Visit(compilation.Assembly.GlobalNamespace); foreach (var symbolName in visitor.DuplicateSymbols) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception( string.Format(AddTypeStrings.TypeAlreadyExists, symbolName)), "TYPE_ALREADY_EXISTS", @@ -1089,9 +1094,9 @@ private void CheckDuplicateTypes(Compilation compilation, out ConcurrentBag 0) + if (!visitor.DuplicateSymbols.IsEmpty) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(AddTypeStrings.CompilerErrors), "COMPILER_ERRORS", ErrorCategory.InvalidData, @@ -1105,10 +1110,10 @@ private void CheckDuplicateTypes(Compilation compilation, out ConcurrentBag DuplicateSymbols = new ConcurrentBag(); - public readonly ConcurrentBag UniqueSymbols = new ConcurrentBag(); + public readonly ConcurrentBag DuplicateSymbols = new(); + public readonly ConcurrentBag UniqueSymbols = new(); public override void VisitNamespace(INamespaceSymbol symbol) { @@ -1136,7 +1141,7 @@ public override void VisitNamedType(INamedTypeSymbol symbol) } } - private void CacheNewTypes(ConcurrentBag newTypes) + private static void CacheNewTypes(ConcurrentBag newTypes) { foreach (var typeName in newTypes) { @@ -1244,7 +1249,7 @@ private void HandleCompilerErrors(ImmutableArray compilerDiagnostics } else { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new Exception(errorText), "SOURCE_CODE_ERROR", ErrorCategory.InvalidData, @@ -1256,7 +1261,7 @@ private void HandleCompilerErrors(ImmutableArray compilerDiagnostics if (IsError) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(AddTypeStrings.CompilerErrors), "COMPILER_ERRORS", ErrorCategory.InvalidData, @@ -1266,7 +1271,7 @@ private void HandleCompilerErrors(ImmutableArray compilerDiagnostics } } - private string BuildErrorMessage(Diagnostic diagnisticRecord) + private static string BuildErrorMessage(Diagnostic diagnisticRecord) { var location = diagnisticRecord.Location; @@ -1289,7 +1294,7 @@ private string BuildErrorMessage(Diagnostic diagnisticRecord) var errorLineString = textLines[errorLineNumber].ToString(); var errorPosition = lineSpan.StartLinePosition.Character; - StringBuilder sb = new StringBuilder(diagnisticMessage.Length + errorLineString.Length * 2 + 4); + StringBuilder sb = new(diagnisticMessage.Length + errorLineString.Length * 2 + 4); sb.AppendLine(diagnisticMessage); sb.AppendLine(errorLineString); @@ -1315,7 +1320,7 @@ private string BuildErrorMessage(Diagnostic diagnisticRecord) private static int SyntaxTreeArrayGetHashCode(IEnumerable sts) { // We use our extension method EnumerableExtensions.SequenceGetHashCode(). - List stHashes = new List(); + List stHashes = new(); foreach (var st in sts) { stHashes.Add(SyntaxTreeGetHashCode(st)); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs index 5a1b944792d..54a5b07cf5d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs @@ -32,8 +32,8 @@ public sealed class CompareObjectCommand : ObjectCmdletBase /// /// [Parameter] - [ValidateRange(0, Int32.MaxValue)] - public int SyncWindow { get; set; } = Int32.MaxValue; + [ValidateRange(0, int.MaxValue)] + public int SyncWindow { get; set; } = int.MaxValue; /// /// @@ -72,7 +72,10 @@ public SwitchParameter ExcludeDifferent [Parameter] public SwitchParameter IncludeEqual { - get { return _includeEqual; } + get + { + return _includeEqual; + } set { @@ -101,10 +104,10 @@ public SwitchParameter PassThru private List _referenceEntries; private readonly List _referenceEntryBacklog - = new List(); + = new(); private readonly List _differenceEntryBacklog - = new List(); + = new(); private OrderByProperty _orderByProperty = null; private OrderByPropertyComparer _comparer = null; @@ -168,7 +171,7 @@ private void Process(OrderByPropertyEntry differenceEntry) // 2005/07/19 Switched order of referenceEntry and differenceEntry // so that we cast differenceEntry to the type of referenceEntry. if (referenceEntry != null && differenceEntry != null && - 0 == _comparer.Compare(referenceEntry, differenceEntry)) + _comparer.Compare(referenceEntry, differenceEntry) == 0) { EmitMatch(referenceEntry); return; @@ -208,7 +211,7 @@ private void Process(OrderByPropertyEntry differenceEntry) // Add differenceEntry to differenceEntryBacklog if (differenceEntry != null) { - if (0 < SyncWindow) + if (SyncWindow > 0) { while (_differenceEntryBacklog.Count >= SyncWindow) { @@ -234,7 +237,7 @@ private void Process(OrderByPropertyEntry differenceEntry) // Add referenceEntry to referenceEntryBacklog if (referenceEntry != null) { - if (0 < SyncWindow) + if (SyncWindow > 0) { while (_referenceEntryBacklog.Count >= SyncWindow) { @@ -256,7 +259,7 @@ private void InitComparer() if (_comparer != null) return; - List referenceObjectList = new List(ReferenceObject); + List referenceObjectList = new(ReferenceObject); _orderByProperty = new OrderByProperty( this, referenceObjectList, Property, true, _cultureInfo, CaseSensitive); Diagnostics.Assert(_orderByProperty.Comparer != null, "no comparer"); @@ -284,7 +287,7 @@ private OrderByPropertyEntry MatchAndRemove( { OrderByPropertyEntry listEntry = list[i]; Diagnostics.Assert(listEntry != null, "null listEntry " + i); - if (0 == _comparer.Compare(match, listEntry)) + if (_comparer.Compare(match, listEntry) == 0) { list.RemoveAt(i); return listEntry; @@ -325,9 +328,9 @@ private void Emit(OrderByPropertyEntry entry, string sideIndicator) else { mshobj = new PSObject(); - if (Property == null || 0 == Property.Length) + if (Property == null || Property.Length == 0) { - PSNoteProperty inputNote = new PSNoteProperty( + PSNoteProperty inputNote = new( InputObjectPropertyName, entry.inputObject); mshobj.Properties.Add(inputNote); } @@ -348,7 +351,7 @@ private void Emit(OrderByPropertyEntry entry, string sideIndicator) object prop = hash[FormatParameterDefinitionKeys.ExpressionEntryKey]; Diagnostics.Assert(prop != null, "null prop"); string propName = prop.ToString(); - PSNoteProperty propertyNote = new PSNoteProperty( + PSNoteProperty propertyNote = new( propName, entry.orderValues[i].PropertyValue); try @@ -364,7 +367,7 @@ private void Emit(OrderByPropertyEntry entry, string sideIndicator) } mshobj.Properties.Remove(SideIndicatorPropertyName); - PSNoteProperty sideNote = new PSNoteProperty( + PSNoteProperty sideNote = new( SideIndicatorPropertyName, sideIndicator); mshobj.Properties.Add(sideNote); WriteObject(mshobj); @@ -406,12 +409,12 @@ protected override void ProcessRecord() return; } - if (_comparer == null && 0 < DifferenceObject.Length) + if (_comparer == null && DifferenceObject.Length > 0) { InitComparer(); } - List differenceList = new List(DifferenceObject); + List differenceList = new(DifferenceObject); List differenceEntries = OrderByProperty.CreateOrderMatrix( this, differenceList, _orderByProperty.MshParameterList); @@ -459,7 +462,7 @@ private void HandleDifferenceObjectOnly() return; } - List differenceList = new List(DifferenceObject); + List differenceList = new(DifferenceObject); _orderByProperty = new OrderByProperty( this, differenceList, Property, true, _cultureInfo, CaseSensitive); List differenceEntries = diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConsoleColorCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConsoleColorCmdlet.cs index bb6a35746c6..e4d36c66106 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConsoleColorCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConsoleColorCmdlet.cs @@ -14,7 +14,7 @@ namespace Microsoft.PowerShell.Commands class ConsoleColorCmdlet : PSCmdlet { /// - /// Default ctor. + /// Initializes a new instance of the class. /// public ConsoleColorCmdlet() { @@ -92,7 +92,7 @@ public ConsoleColorCmdlet() private static ErrorRecord BuildOutOfRangeErrorRecord(object val, string errorId) { string msg = StringUtil.Format(HostStrings.InvalidColorErrorTemplate, val.ToString()); - ArgumentOutOfRangeException e = new ArgumentOutOfRangeException("value", val, msg); + ArgumentOutOfRangeException e = new("value", val, msg); return new ErrorRecord(e, errorId, ErrorCategory.InvalidArgument, null); } #endregion helper @@ -106,4 +106,3 @@ private static ErrorRecord BuildOutOfRangeErrorRecord(object val, string errorId private readonly Type _consoleColorEnumType; } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs index 1e64dfe7754..22c1e5ef46b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; using System.Management.Automation; using System.Security.AccessControl; using System.Security.Principal; @@ -33,7 +31,10 @@ public sealed class ConvertFromSddlStringCommand : PSCmdlet [Parameter] public AccessRightTypeNames Type { - get { return _type; } + get + { + return _type; + } set { @@ -45,7 +46,7 @@ public AccessRightTypeNames Type private AccessRightTypeNames _type; private bool _isTypeSet = false; - private string ConvertToNTAccount(SecurityIdentifier securityIdentifier) + private static string ConvertToNTAccount(SecurityIdentifier securityIdentifier) { try { @@ -57,11 +58,11 @@ private string ConvertToNTAccount(SecurityIdentifier securityIdentifier) } } - private List GetApplicableAccessRights(int accessMask, AccessRightTypeNames? typeName) + private static List GetApplicableAccessRights(int accessMask, AccessRightTypeNames? typeName) { - List typesToExamine = new List(); - List foundAccessRightNames = new List(); - HashSet foundAccessRightValues = new HashSet(); + List typesToExamine = new(); + List foundAccessRightNames = new(); + HashSet foundAccessRightValues = new(); if (typeName != null) { @@ -95,7 +96,7 @@ private List GetApplicableAccessRights(int accessMask, AccessRightTypeNa return foundAccessRightNames; } - private Type GetRealAccessRightType(AccessRightTypeNames typeName) + private static Type GetRealAccessRightType(AccessRightTypeNames typeName) { switch (typeName) { @@ -116,17 +117,17 @@ private Type GetRealAccessRightType(AccessRightTypeNames typeName) } } - private string[] ConvertAccessControlListToStrings(CommonAcl acl, AccessRightTypeNames? typeName) + private static string[] ConvertAccessControlListToStrings(CommonAcl acl, AccessRightTypeNames? typeName) { if (acl == null || acl.Count == 0) { return Array.Empty(); } - List aceStringList = new List(acl.Count); + List aceStringList = new(acl.Count); foreach (CommonAce ace in acl) { - StringBuilder aceString = new StringBuilder(); + StringBuilder aceString = new(); string ntAccount = ConvertToNTAccount(ace.SecurityIdentifier); aceString.Append($"{ntAccount}: {ace.AceQualifier}"); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-StringData.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-StringData.cs index 2daa22a4f69..16bb4be012d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-StringData.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-StringData.cs @@ -47,7 +47,7 @@ public string StringData /// protected override void ProcessRecord() { - Hashtable result = new Hashtable(StringComparer.OrdinalIgnoreCase); + Hashtable result = new(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(_stringData)) { @@ -95,4 +95,3 @@ protected override void ProcessRecord() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs index dfa6bd6c4b0..28d117f639f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.IO; using System.Management.Automation; using System.Management.Automation.Internal; @@ -12,8 +11,6 @@ using Microsoft.PowerShell.MarkdownRender; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// @@ -109,7 +106,7 @@ protected override void ProcessRecord() else { string errorMessage = StringUtil.Format(ConvertMarkdownStrings.InvalidInputObjectType, baseObj.GetType()); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidDataException(errorMessage), "InvalidInputObject", ErrorCategory.InvalidData, @@ -153,7 +150,7 @@ private async Task ReadContentFromFile(string filePath) try { - using (StreamReader reader = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))) + using (StreamReader reader = new(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))) { string mdContent = await reader.ReadToEndAsync(); return mdContent; @@ -192,7 +189,7 @@ private List ResolvePath(string path, bool isLiteral) { ProviderInfo provider = null; PSDriveInfo drive = null; - List resolvedPaths = new List(); + List resolvedPaths = new(); try { @@ -219,7 +216,7 @@ private List ResolvePath(string path, bool isLiteral) if (!provider.Name.Equals("FileSystem", StringComparison.OrdinalIgnoreCase)) { string errorMessage = StringUtil.Format(ConvertMarkdownStrings.FileSystemPathsOnly, path); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(), "OnlyFileSystemPathsSupported", ErrorCategory.InvalidArgument, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertTo-Html.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertTo-Html.cs index 4ca99f45ae2..e72fc825e7c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertTo-Html.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertTo-Html.cs @@ -4,7 +4,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.Management.Automation; using System.Management.Automation.Internal; @@ -341,9 +340,9 @@ protected override void SetEntries() /// private List ProcessParameter(object[] properties) { - TerminatingErrorContext invocationContext = new TerminatingErrorContext(this); + TerminatingErrorContext invocationContext = new(this); ParameterProcessor processor = - new ParameterProcessor(new ConvertHTMLExpressionParameterDefinition()); + new(new ConvertHTMLExpressionParameterDefinition()); if (properties == null) { properties = new object[] { "*" }; @@ -395,7 +394,7 @@ private static Hashtable CreateAuxPropertyHT( string alignment, string width) { - Hashtable ht = new Hashtable(); + Hashtable ht = new(); if (label != null) { ht.Add(ConvertHTMLParameterDefinitionKeys.LabelEntryKey, label); @@ -445,8 +444,8 @@ protected override void BeginProcessing() // ValidateNotNullOrEmpty attribute is not working for System.Uri datatype, so handling it here if ((_cssuriSpecified) && (string.IsNullOrEmpty(_cssuri.OriginalString.Trim()))) { - ArgumentException ex = new ArgumentException(StringUtil.Format(UtilityCommonStrings.EmptyCSSUri, "CSSUri")); - ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.InvalidArgument, "CSSUri"); + ArgumentException ex = new(StringUtil.Format(UtilityCommonStrings.EmptyCSSUri, "CSSUri")); + ErrorRecord er = new(ex, "ArgumentException", ErrorCategory.InvalidArgument, "CSSUri"); ThrowTerminatingError(er); } @@ -481,7 +480,7 @@ protected override void BeginProcessing() if (_metaSpecified) { - List useditems = new List(); + List useditems = new(); foreach (string s in _meta.Keys) { if (!useditems.Contains(s)) @@ -504,7 +503,7 @@ protected override void BeginProcessing() default: MshCommandRuntime mshCommandRuntime = this.CommandRuntime as MshCommandRuntime; string Message = StringUtil.Format(ConvertHTMLStrings.MetaPropertyNotFound, s, _meta[s]); - WarningRecord record = new WarningRecord(Message); + WarningRecord record = new(Message); InvocationInfo invocationInfo = GetVariableValue(SpecialVariables.MyInvocation) as InvocationInfo; if (invocationInfo != null) @@ -550,7 +549,7 @@ protected override void BeginProcessing() /// private void WriteColumns(List mshParams) { - StringBuilder COLTag = new StringBuilder(); + StringBuilder COLTag = new(); COLTag.Append(""); foreach (MshParameter p in mshParams) @@ -561,7 +560,7 @@ private void WriteColumns(List mshParams) { COLTag.Append(" width = \""); COLTag.Append(width); - COLTag.Append("\""); + COLTag.Append('"'); } string alignment = p.GetEntry(ConvertHTMLParameterDefinitionKeys.AlignmentEntryKey) as string; @@ -569,7 +568,7 @@ private void WriteColumns(List mshParams) { COLTag.Append(" align = \""); COLTag.Append(alignment); - COLTag.Append("\""); + COLTag.Append('"'); } COLTag.Append("/>"); @@ -588,12 +587,12 @@ private void WriteListEntry() { foreach (MshParameter p in _resolvedNameMshParameters) { - StringBuilder Listtag = new StringBuilder(); + StringBuilder Listtag = new(); Listtag.Append(""); // for writing the property name WritePropertyName(Listtag, p); - Listtag.Append(":"); + Listtag.Append(':'); Listtag.Append(""); // for writing the property value @@ -608,7 +607,7 @@ private void WriteListEntry() /// /// To write the Property name. /// - private void WritePropertyName(StringBuilder Listtag, MshParameter p) + private static void WritePropertyName(StringBuilder Listtag, MshParameter p) { // for writing the property name string label = p.GetEntry(ConvertHTMLParameterDefinitionKeys.LabelEntryKey) as string; @@ -653,7 +652,7 @@ private void WritePropertyValue(StringBuilder Listtag, MshParameter p) /// /// To write the Table header for the object property names. /// - private void WriteTableHeader(StringBuilder THtag, List resolvedNameMshParameters) + private static void WriteTableHeader(StringBuilder THtag, List resolvedNameMshParameters) { // write the property names foreach (MshParameter p in resolvedNameMshParameters) @@ -714,7 +713,7 @@ protected override void ProcessRecord() { WriteColumns(_resolvedNameMshParameters); - StringBuilder THtag = new StringBuilder(""); + StringBuilder THtag = new(""); // write the table header WriteTableHeader(THtag, _resolvedNameMshParameters); @@ -727,7 +726,7 @@ protected override void ProcessRecord() // if the As parameter is Table, write the property values if (_as.Equals("Table", StringComparison.OrdinalIgnoreCase)) { - StringBuilder TRtag = new StringBuilder(""); + StringBuilder TRtag = new(""); // write the table row WriteTableRow(TRtag, _resolvedNameMshParameters); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Csv.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Csv.cs index 3bb626ca06e..9590cd7c771 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Csv.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Csv.cs @@ -28,7 +28,7 @@ internal CSVHelper(char delimiter) /// internal Collection ParseCsv(string csv) { - Collection result = new Collection(); + Collection result = new(); string tempString = string.Empty; csv = csv.Trim(); if (csv.Length == 0 || csv[0] == '#') diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs index bea8b55d7c1..19ac076deaf 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; @@ -11,8 +12,6 @@ using System.Management.Automation; using System.Text; -using Dbg = System.Management.Automation.Diagnostics; - #pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings namespace Microsoft.PowerShell.Commands @@ -110,15 +109,15 @@ protected override void BeginProcessing() { if (this.MyInvocation.BoundParameters.ContainsKey(nameof(QuoteFields)) && this.MyInvocation.BoundParameters.ContainsKey(nameof(UseQuotes))) { - InvalidOperationException exception = new InvalidOperationException(CsvCommandStrings.CannotSpecifyQuoteFieldsAndUseQuotes); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotSpecifyQuoteFieldsAndUseQuotes", ErrorCategory.InvalidData, null); + InvalidOperationException exception = new(CsvCommandStrings.CannotSpecifyQuoteFieldsAndUseQuotes); + ErrorRecord errorRecord = new(exception, "CannotSpecifyQuoteFieldsAndUseQuotes", ErrorCategory.InvalidData, null); this.ThrowTerminatingError(errorRecord); } if (this.MyInvocation.BoundParameters.ContainsKey(nameof(IncludeTypeInformation)) && this.MyInvocation.BoundParameters.ContainsKey(nameof(NoTypeInformation))) { - InvalidOperationException exception = new InvalidOperationException(CsvCommandStrings.CannotSpecifyIncludeTypeInformationAndNoTypeInformation); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotSpecifyIncludeTypeInformationAndNoTypeInformation", ErrorCategory.InvalidData, null); + InvalidOperationException exception = new(CsvCommandStrings.CannotSpecifyIncludeTypeInformationAndNoTypeInformation); + ErrorRecord errorRecord = new(exception, "CannotSpecifyIncludeTypeInformationAndNoTypeInformation", ErrorCategory.InvalidData, null); this.ThrowTerminatingError(errorRecord); } @@ -260,8 +259,8 @@ protected override void BeginProcessing() // Validate that they don't provide both Path and LiteralPath, but have provided at least one. if (!(_specifiedPath ^ _isLiteralPath)) { - InvalidOperationException exception = new InvalidOperationException(CsvCommandStrings.CannotSpecifyPathAndLiteralPath); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotSpecifyPathAndLiteralPath", ErrorCategory.InvalidData, null); + InvalidOperationException exception = new(CsvCommandStrings.CannotSpecifyPathAndLiteralPath); + ErrorRecord errorRecord = new(exception, "CannotSpecifyPathAndLiteralPath", ErrorCategory.InvalidData, null); this.ThrowTerminatingError(errorRecord); } @@ -360,7 +359,7 @@ private void CreateFileStream() { using (StreamReader streamReader = PathUtils.OpenStreamReader(this, this.Path, Encoding, _isLiteralPath)) { - isCsvFileEmpty = streamReader.Peek() == -1 ? true : false; + isCsvFileEmpty = streamReader.Peek() == -1; } } @@ -373,7 +372,7 @@ private void CreateFileStream() using (StreamReader streamReader = PathUtils.OpenStreamReader(this, this.Path, Encoding, _isLiteralPath)) { - ImportCsvHelper readingHelper = new ImportCsvHelper( + ImportCsvHelper readingHelper = new( this, this.Delimiter, null /* header */, null /* typeName */, streamReader); readingHelper.ReadHeader(); _preexistingPropertyNames = readingHelper.Header; @@ -448,7 +447,7 @@ private void ReconcilePreexistingPropertyNames() throw new InvalidOperationException(CsvCommandStrings.ReconcilePreexistingPropertyNamesMethodShouldOnlyGetCalledWhenPreexistingPropertyNamesHaveBeenReadSuccessfully); } - HashSet appendedPropertyNames = new HashSet(StringComparer.OrdinalIgnoreCase); + HashSet appendedPropertyNames = new(StringComparer.OrdinalIgnoreCase); foreach (string appendedPropertyName in _propertyNames) { appendedPropertyNames.Add(appendedPropertyName); @@ -465,8 +464,8 @@ private void ReconcilePreexistingPropertyNames() CsvCommandStrings.CannotAppendCsvWithMismatchedPropertyNames, preexistingPropertyName, this.Path); - InvalidOperationException exception = new InvalidOperationException(errorMessage); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotAppendCsvWithMismatchedPropertyNames", ErrorCategory.InvalidData, preexistingPropertyName); + InvalidOperationException exception = new(errorMessage); + ErrorRecord errorRecord = new(exception, "CannotAppendCsvWithMismatchedPropertyNames", ErrorCategory.InvalidData, preexistingPropertyName); this.ThrowTerminatingError(errorRecord); } } @@ -504,7 +503,7 @@ public override void WriteCsvLine(string line) /// public void Dispose() { - if (_disposed == false) + if (!_disposed) { CleanUp(); } @@ -646,8 +645,8 @@ protected override void ProcessRecord() // Validate that they don't provide both Path and LiteralPath, but have provided at least one. if (!(_specifiedPath ^ _isLiteralPath)) { - InvalidOperationException exception = new InvalidOperationException(CsvCommandStrings.CannotSpecifyPathAndLiteralPath); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotSpecifyPathAndLiteralPath", ErrorCategory.InvalidData, null); + InvalidOperationException exception = new(CsvCommandStrings.CannotSpecifyPathAndLiteralPath); + ErrorRecord errorRecord = new(exception, "CannotSpecifyPathAndLiteralPath", ErrorCategory.InvalidData, null); this.ThrowTerminatingError(errorRecord); } @@ -657,7 +656,7 @@ protected override void ProcessRecord() { using (StreamReader streamReader = PathUtils.OpenStreamReader(this, path, this.Encoding, _isLiteralPath)) { - ImportCsvHelper helper = new ImportCsvHelper(this, Delimiter, Header, null /* typeName */, streamReader); + ImportCsvHelper helper = new(this, Delimiter, Header, null /* typeName */, streamReader); try { @@ -665,7 +664,7 @@ protected override void ProcessRecord() } catch (ExtendedTypeSystemException exception) { - ErrorRecord errorRecord = new ErrorRecord(exception, "AlreadyPresentPSMemberInfoInternalCollectionAdd", ErrorCategory.NotSpecified, null); + ErrorRecord errorRecord = new(exception, "AlreadyPresentPSMemberInfoInternalCollectionAdd", ErrorCategory.NotSpecified, null); this.ThrowTerminatingError(errorRecord); } } @@ -739,14 +738,18 @@ protected override void ProcessRecord() // Write property information string properties = _helper.ConvertPropertyNamesCSV(_propertyNames); if (!properties.Equals(string.Empty)) + { WriteCsvLine(properties); + } } string csv = _helper.ConvertPSObjectToCSV(InputObject, _propertyNames); - // write to the console + // Write to the output stream if (csv != string.Empty) + { WriteCsvLine(csv); + } } #endregion Overrides @@ -835,10 +838,10 @@ protected override void ProcessRecord() { foreach (PSObject inputObject in InputObject) { - using (MemoryStream memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(inputObject.ToString()))) - using (StreamReader streamReader = new StreamReader(memoryStream, System.Text.Encoding.Unicode)) + using (MemoryStream memoryStream = new(Encoding.Unicode.GetBytes(inputObject.ToString()))) + using (StreamReader streamReader = new(memoryStream, System.Text.Encoding.Unicode)) { - ImportCsvHelper helper = new ImportCsvHelper(this, Delimiter, Header, _typeName, streamReader); + ImportCsvHelper helper = new(this, Delimiter, Header, _typeName, streamReader); try { @@ -846,7 +849,7 @@ protected override void ProcessRecord() } catch (ExtendedTypeSystemException exception) { - ErrorRecord errorRecord = new ErrorRecord(exception, "AlreadyPresentPSMemberInfoInternalCollectionAdd", ErrorCategory.NotSpecified, null); + ErrorRecord errorRecord = new(exception, "AlreadyPresentPSMemberInfoInternalCollectionAdd", ErrorCategory.NotSpecified, null); this.ThrowTerminatingError(errorRecord); } @@ -879,13 +882,13 @@ protected override void ProcessRecord() /// internal class ExportCsvHelper : IDisposable { - private char _delimiter; + private readonly char _delimiter; private readonly BaseCsvWritingCommand.QuoteKind _quoteKind; private readonly HashSet _quoteFields; private readonly StringBuilder _outputString; /// - /// Create ExportCsvHelper instance. + /// Initializes a new instance of the class. /// /// Delimiter char. /// Kind of quoting. @@ -910,16 +913,36 @@ internal static IList BuildPropertyNames(PSObject source, IList throw new InvalidOperationException(CsvCommandStrings.BuildPropertyNamesMethodShouldBeCalledOnlyOncePerCmdletInstance); } - // serialize only Extended and Adapted properties.. - PSMemberInfoCollection srcPropertiesToSearch = - new PSMemberInfoIntegratingCollection( + propertyNames = new Collection(); + if (source.BaseObject is IDictionary dictionary) + { + foreach (var key in dictionary.Keys) + { + propertyNames.Add(LanguagePrimitives.ConvertTo(key)); + } + + // Add additional extended members added to the dictionary object, if any + var propertiesToSearch = new PSMemberInfoIntegratingCollection( source, - PSObject.GetPropertyCollection(PSMemberViewTypes.Extended | PSMemberViewTypes.Adapted)); + PSObject.GetPropertyCollection(PSMemberViewTypes.Extended)); - propertyNames = new Collection(); - foreach (PSPropertyInfo prop in srcPropertiesToSearch) + foreach (var prop in propertiesToSearch) + { + propertyNames.Add(prop.Name); + } + } + else { - propertyNames.Add(prop.Name); + // serialize only Extended and Adapted properties. + PSMemberInfoCollection srcPropertiesToSearch = + new PSMemberInfoIntegratingCollection( + source, + PSObject.GetPropertyCollection(PSMemberViewTypes.Extended | PSMemberViewTypes.Adapted)); + + foreach (PSPropertyInfo prop in srcPropertiesToSearch) + { + propertyNames.Add(prop.Name); + } } return propertyNames; @@ -969,7 +992,8 @@ internal string ConvertPropertyNamesCSV(IList propertyNames) AppendStringWithEscapeAlways(_outputString, propertyName); break; case BaseCsvWritingCommand.QuoteKind.AsNeeded: - if (propertyName.Contains(_delimiter)) + + if (propertyName.AsSpan().IndexOfAny(_delimiter, '\n', '"') != -1) { AppendStringWithEscapeAlways(_outputString, propertyName); } @@ -1016,11 +1040,26 @@ internal string ConvertPSObjectToCSV(PSObject mshObject, IList propertyN _outputString.Append(_delimiter); } - // If property is not present, assume value is null and skip it. - if (mshObject.Properties[propertyName] is PSPropertyInfo property) + string value = null; + if (mshObject.BaseObject is IDictionary dictionary) + { + if (dictionary.Contains(propertyName)) + { + value = dictionary[propertyName].ToString(); + } + else if (mshObject.Properties[propertyName] is PSPropertyInfo property) + { + value = GetToStringValueForProperty(property); + } + } + else if (mshObject.Properties[propertyName] is PSPropertyInfo property) { - var value = GetToStringValueForProperty(property); + value = GetToStringValueForProperty(property); + } + // If value is null, assume property is not present and skip it. + if (value != null) + { if (_quoteFields != null) { if (_quoteFields.TryGetValue(propertyName, out _)) @@ -1040,7 +1079,7 @@ internal string ConvertPSObjectToCSV(PSObject mshObject, IList propertyN AppendStringWithEscapeAlways(_outputString, value); break; case BaseCsvWritingCommand.QuoteKind.AsNeeded: - if (value != null && value.Contains(_delimiter)) + if (value != null && value.AsSpan().IndexOfAny(_delimiter, '\n', '"') != -1) { AppendStringWithEscapeAlways(_outputString, value); } @@ -1171,7 +1210,7 @@ internal static void AppendStringWithEscapeAlways(StringBuilder dest, string sou /// public void Dispose() { - if (_disposed == false) + if (!_disposed) { GC.SuppressFinalize(this); } @@ -1386,7 +1425,7 @@ private static void ValidatePropertyNames(IList names) } else { - HashSet headers = new HashSet(StringComparer.OrdinalIgnoreCase); + HashSet headers = new(StringComparer.OrdinalIgnoreCase); foreach (string currentHeader in names) { if (!string.IsNullOrEmpty(currentHeader)) @@ -1404,7 +1443,7 @@ private static void ValidatePropertyNames(IList names) ExtendedTypeSystem.MemberAlreadyPresent, currentHeader); - ExtendedTypeSystemException exception = new ExtendedTypeSystemException(memberAlreadyPresentMsg); + ExtendedTypeSystemException exception = new(memberAlreadyPresentMsg); throw exception; } } @@ -1638,7 +1677,7 @@ private bool IsNewLine(char ch, out string newLine) /// private void ReadTillNextDelimiter(StringBuilder current, ref bool endOfRecord, bool eatTrailingBlanks) { - StringBuilder temp = new StringBuilder(); + StringBuilder temp = new(); // Did we see any non-whitespace character bool nonWhiteSpace = false; @@ -1686,7 +1725,7 @@ private void ReadTillNextDelimiter(StringBuilder current, ref bool endOfRecord, private PSObject BuildMshobject(string type, IList names, List values, char delimiter, bool preValidated = false) { - PSObject result = new PSObject(names.Count); + PSObject result = new(names.Count); char delimiterlocal = delimiter; int unspecifiedNameIndex = 1; for (int i = 0; i <= names.Count - 1; i++) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CustomSerialization.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CustomSerialization.cs index 2c85a64cf18..6ad8b02a558 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CustomSerialization.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CustomSerialization.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Collections.Generic; using System.Management.Automation.Internal; @@ -21,17 +20,17 @@ internal class CustomSerialization /// /// Depth of serialization. /// - private int _depth; + private readonly int _depth; /// /// XmlWriter to be used for writing. /// - private XmlWriter _writer; + private readonly XmlWriter _writer; /// /// Whether type information should be included in the xml. /// - private bool _notypeinformation; + private readonly bool _notypeinformation; /// /// CustomerSerializer used for formatting the output for _writer. @@ -39,7 +38,7 @@ internal class CustomSerialization private CustomInternalSerializer _serializer; /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// writer to be used for serialization. @@ -75,7 +74,7 @@ internal CustomSerialization(XmlWriter writer, bool notypeinformation, int depth public static int MshDefaultSerializationDepth { get; } = 1; /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// writer to be used for serialization. @@ -191,7 +190,7 @@ internal class /// /// Xml writer to be used. /// - private XmlWriter _writer; + private readonly XmlWriter _writer; /// /// Check first call for every pipeline object to write Object tag else property tag. @@ -201,7 +200,7 @@ internal class /// /// Should the type information to be shown. /// - private bool _notypeinformation; + private readonly bool _notypeinformation; /// /// Check object call. @@ -209,7 +208,7 @@ internal class private bool _firstobjectcall = true; /// - /// Constructor. + /// Initializes a new instance of the class. /// /// /// Xml writer to be used. @@ -442,7 +441,7 @@ private bool HandleKnownContainerTypes(object source, string property, int depth /// /// /// - private void GetKnownContainerTypeInfo( + private static void GetKnownContainerTypeInfo( object source, out ContainerType ct, out IDictionary dictionary, out IEnumerable enumerable) { Dbg.Assert(source != null, "caller should validate the parameter"); @@ -676,7 +675,7 @@ private void WriteStartOfPSObject( /// /// /// - private bool PSObjectHasNotes(PSObject source) + private static bool PSObjectHasNotes(PSObject source) { if (source.InstanceMembers != null && source.InstanceMembers.Count > 0) { @@ -710,8 +709,7 @@ private void WriteMemberInfoCollection( continue; } - PSPropertyInfo property = info as PSPropertyInfo; - if (property == null) + if (!(info is PSPropertyInfo property)) { continue; } @@ -743,7 +741,7 @@ private void WritePSObjectProperties(PSObject source, int depth) Dbg.Assert(depth >= 0, "depth should be greater or equal to zero"); if (source.GetSerializationMethod(null) == SerializationMethod.SpecificProperties) { - PSMemberInfoInternalCollection specificProperties = new PSMemberInfoInternalCollection(); + PSMemberInfoInternalCollection specificProperties = new(); foreach (string propertyName in source.GetSpecificPropertiesToSerialize(null)) { PSPropertyInfo property = source.Properties[propertyName]; @@ -956,7 +954,7 @@ private void HandlePSObjectAsString(PSObject source, string property, int depth) /// /// string value to use for serializing this PSObject. /// - private string GetStringFromPSObject(PSObject source) + private static string GetStringFromPSObject(PSObject source) { Dbg.Assert(source != null, "caller should have validated the information"); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/DebugRunspaceCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/DebugRunspaceCommand.cs index 355d94912af..f6ba764662f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/DebugRunspaceCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/DebugRunspaceCommand.cs @@ -43,7 +43,7 @@ public sealed class DebugRunspaceCommand : PSCmdlet // Debugging to persist until Ctrl+C or Debugger 'Exit' stops cmdlet. private bool _debugging; - private ManualResetEventSlim _newRunningScriptEvent = new ManualResetEventSlim(true); + private readonly ManualResetEventSlim _newRunningScriptEvent = new(true); private RunspaceAvailability _previousRunspaceAvailability = RunspaceAvailability.None; #endregion @@ -103,7 +103,6 @@ public Guid InstanceId /// /// Gets or sets a flag that tells PowerShell to automatically perform a BreakAll when the debugger is attached to the remote target. /// - [Experimental("Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace", ExperimentAction.Show)] [Parameter] public SwitchParameter BreakAll { get; set; } @@ -549,7 +548,7 @@ private void EnableHostDebugger(Runspace runspace, bool enabled) } } - private void SetLocalMode(System.Management.Automation.Debugger debugger, bool localMode) + private static void SetLocalMode(System.Management.Automation.Debugger debugger, bool localMode) { ServerRemoteDebugger remoteDebugger = debugger as ServerRemoteDebugger; if (remoteDebugger != null) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/EnableDisableRunspaceDebugCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/EnableDisableRunspaceDebugCommand.cs index 62e7b4a8d0f..c37d83ecf84 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/EnableDisableRunspaceDebugCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/EnableDisableRunspaceDebugCommand.cs @@ -51,7 +51,7 @@ public sealed class PSRunspaceDebug #region Constructors /// - /// Constructor. + /// Initializes a new instance of the class. /// /// Enable debugger option. /// BreakAll option. @@ -291,7 +291,7 @@ protected void SetDebugPreferenceHelper(string processName, string[] appDomainNa } catch (Exception ex) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, Debugger.PersistDebugPreferenceFailure, processName), ex), fullyQualifiedErrorId, ErrorCategory.InvalidOperation, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs index 1ac3e781ab7..e01d8c28e0c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs @@ -55,7 +55,10 @@ public string Path [Alias("PSPath", "LP")] public string LiteralPath { - get { return _path; } + get + { + return _path; + } set { @@ -244,7 +247,7 @@ protected override void ProcessRecord() // that doesn't exist and they are not globbing. ItemNotFoundException itemNotFound = - new ItemNotFoundException( + new( aliasName, "AliasNotFound", SessionStateStrings.AliasNotFound); @@ -310,7 +313,7 @@ protected override void EndProcessing() /// /// Holds all the matching aliases for writing to the file. /// - private Collection _matchingAliases = new Collection(); + private readonly Collection _matchingAliases = new(); private static string GetAliasLine(AliasInfo alias, string formatString) { @@ -406,7 +409,7 @@ private void ThrowFileOpenError(Exception e, string pathWithError) { string message = StringUtil.Format(AliasCommandStrings.ExportAliasFileOpenFailed, pathWithError, e.Message); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( e, "FileOpenFailure", ErrorCategory.OpenError, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ColumnInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ColumnInfo.cs index 0d2db93302a..a42462737ea 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ColumnInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ColumnInfo.cs @@ -48,8 +48,7 @@ internal Type GetValueType(PSObject liveObject, out object columnValue) /// The source string limited in the number of lines. internal static object LimitString(object src) { - string srcString = src as string; - if (srcString == null) + if (!(src is string srcString)) { return src; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ExpressionColumnInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ExpressionColumnInfo.cs index a9d60def958..e905f5d64b6 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ExpressionColumnInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ExpressionColumnInfo.cs @@ -1,17 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Management.Automation; -using Microsoft.PowerShell.Commands.Internal.Format; - namespace Microsoft.PowerShell.Commands { internal class ExpressionColumnInfo : ColumnInfo { - private PSPropertyExpression _expression; + private readonly PSPropertyExpression _expression; internal ExpressionColumnInfo(string staleObjectPropertyName, string displayName, PSPropertyExpression expression) : base(staleObjectPropertyName, displayName) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/HeaderInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/HeaderInfo.cs index d7d863e29b8..d811ce32303 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/HeaderInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/HeaderInfo.cs @@ -9,7 +9,7 @@ namespace Microsoft.PowerShell.Commands { internal class HeaderInfo { - private List _columns = new List(); + private readonly List _columns = new(); internal void AddColumn(ColumnInfo col) { @@ -18,7 +18,7 @@ internal void AddColumn(ColumnInfo col) internal PSObject AddColumnsToWindow(OutWindowProxy windowProxy, PSObject liveObject) { - PSObject staleObject = new PSObject(); + PSObject staleObject = new(); // Initiate arrays to be of the same size. int count = _columns.Count; @@ -47,7 +47,7 @@ internal PSObject AddColumnsToWindow(OutWindowProxy windowProxy, PSObject liveOb internal PSObject CreateStalePSObject(PSObject liveObject) { - PSObject staleObject = new PSObject(); + PSObject staleObject = new(); foreach (ColumnInfo column in _columns) { // Add a property to the stale PSObject. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OriginalColumnInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OriginalColumnInfo.cs index 48a9004e604..3db37f3528e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OriginalColumnInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OriginalColumnInfo.cs @@ -11,8 +11,8 @@ namespace Microsoft.PowerShell.Commands { internal class OriginalColumnInfo : ColumnInfo { - private string _liveObjectPropertyName; - private OutGridViewCommand _parentCmdlet; + private readonly string _liveObjectPropertyName; + private readonly OutGridViewCommand _parentCmdlet; internal OriginalColumnInfo(string staleObjectPropertyName, string displayName, string liveObjectPropertyName, OutGridViewCommand parentCmdlet) : base(staleObjectPropertyName, displayName) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutGridViewCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutGridViewCommand.cs index b95e9968c5c..e606e58e9e4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutGridViewCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutGridViewCommand.cs @@ -54,7 +54,7 @@ public class OutGridViewCommand : PSCmdlet, IDisposable #region Constructors /// - /// Constructor for OutGridView. + /// Initializes a new instance of the class. /// public OutGridViewCommand() { @@ -88,7 +88,7 @@ public OutGridViewCommand() /// and if it should be possible to select multiple or single list items. /// [Parameter(ParameterSetName = "OutputMode")] - public OutputModeOption OutputMode { set; get; } + public OutputModeOption OutputMode { get; set; } /// /// Gets or sets a value indicating whether the selected items should be written to the pipeline. @@ -97,9 +97,9 @@ public OutGridViewCommand() [Parameter(ParameterSetName = "PassThru")] public SwitchParameter PassThru { - set { this.OutputMode = value.IsPresent ? OutputModeOption.Multiple : OutputModeOption.None; } - get { return OutputMode == OutputModeOption.Multiple ? new SwitchParameter(true) : new SwitchParameter(false); } + + set { this.OutputMode = value.IsPresent ? OutputModeOption.Multiple : OutputModeOption.None; } } #endregion Input Parameters @@ -212,7 +212,7 @@ protected override void StopProcessing() /// PSObject to be converted to a string. internal string ConvertToString(PSObject liveObject) { - StringFormatError formatErrorObject = new StringFormatError(); + StringFormatError formatErrorObject = new(); string smartToString = PSObjectHelper.SmartToString(liveObject, _expressionFactory, InnerFormatShapeCommand.FormatEnumerationLimit(), @@ -265,7 +265,7 @@ baseObject is PSReference || baseObject is FormatInfoData || baseObject is PSObject) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new FormatException(StringUtil.Format(FormatAndOut_out_gridview.DataNotQualifiedForGridView)), DataNotQualifiedForGridView, ErrorCategory.InvalidType, @@ -289,7 +289,7 @@ baseObject is FormatInfoData || Exception exception = _windowProxy.GetLastException(); if (exception != null) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( exception, "ManagementListInvocationException", ErrorCategory.OperationStopped, @@ -326,7 +326,7 @@ internal static GridHeader ConstructGridHeader(PSObject input, OutGridViewComman internal class ScalarTypeHeader : GridHeader { - private Type _originalScalarType; + private readonly Type _originalScalarType; internal ScalarTypeHeader(OutGridViewCommand parentCmd, PSObject input) : base(parentCmd) { @@ -352,12 +352,12 @@ internal override void ProcessInputObject(PSObject input) internal class NonscalarTypeHeader : GridHeader { - private AppliesTo _appliesTo = null; + private readonly AppliesTo _appliesTo = null; internal NonscalarTypeHeader(OutGridViewCommand parentCmd, PSObject input) : base(parentCmd) { // Prepare a table view. - TableView tableView = new TableView(); + TableView tableView = new(); tableView.Initialize(parentCmd._expressionFactory, parentCmd._typeInfoDataBase); // Request a view definition from the type database. @@ -492,13 +492,5 @@ public void Dispose() this.Dispose(true); GC.SuppressFinalize(this); } - - /// - /// Finalizer. - /// - ~OutGridViewCommand() - { - Dispose(false); - } } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutWindowProxy.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutWindowProxy.cs index 55158034368..3f22caf1e7b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutWindowProxy.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/OutWindowProxy.cs @@ -28,18 +28,18 @@ internal class OutWindowProxy : IDisposable private bool _isWindowStarted; - private string _title; + private readonly string _title; - private OutputModeOption _outputMode; + private readonly OutputModeOption _outputMode; private AutoResetEvent _closedEvent; - private OutGridViewCommand _parentCmdlet; + private readonly OutGridViewCommand _parentCmdlet; - private GraphicalHostReflectionWrapper _graphicalHostReflectionWrapper; + private readonly GraphicalHostReflectionWrapper _graphicalHostReflectionWrapper; /// - /// Initializes a new instance of the OutWindowProxy class. + /// Initializes a new instance of the class. /// internal OutWindowProxy(string title, OutputModeOption outPutMode, OutGridViewCommand parentCmdlet) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ScalarTypeColumnInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ScalarTypeColumnInfo.cs index b72c9b7d439..77f80c269a3 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ScalarTypeColumnInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/ScalarTypeColumnInfo.cs @@ -8,7 +8,7 @@ namespace Microsoft.PowerShell.Commands { internal class ScalarTypeColumnInfo : ColumnInfo { - private Type _type; + private readonly Type _type; internal ScalarTypeColumnInfo(Type type) : base(type.Name, type.Name) @@ -45,7 +45,7 @@ internal override object GetValue(PSObject liveObject) internal class ToStringColumnInfo : ColumnInfo { - private OutGridViewCommand _parentCmdlet; + private readonly OutGridViewCommand _parentCmdlet; internal ToStringColumnInfo(string staleObjectPropertyName, string displayName, OutGridViewCommand parentCmdlet) : base(staleObjectPropertyName, displayName) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/TableView.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/TableView.cs index dc967889e69..216d9121d54 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/TableView.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/OutGridView/TableView.cs @@ -25,7 +25,7 @@ internal void Initialize(PSPropertyExpressionFactory expressionFactory, _typeInfoDatabase = db; // Initialize Format Error Manager. - FormatErrorPolicy formatErrorPolicy = new FormatErrorPolicy(); + FormatErrorPolicy formatErrorPolicy = new(); formatErrorPolicy.ShowErrorsAsMessages = _typeInfoDatabase.defaultSettingsSection.formatErrorPolicy.ShowErrorsAsMessages; formatErrorPolicy.ShowErrorsInFormattedOutput = _typeInfoDatabase.defaultSettingsSection.formatErrorPolicy.ShowErrorsInFormattedOutput; @@ -35,7 +35,7 @@ internal void Initialize(PSPropertyExpressionFactory expressionFactory, internal HeaderInfo GenerateHeaderInfo(PSObject input, TableControlBody tableBody, OutGridViewCommand parentCmdlet) { - HeaderInfo headerInfo = new HeaderInfo(); + HeaderInfo headerInfo = new(); // This verification is needed because the database returns "LastWriteTime" value for file system objects // as strings and it is used to detect this situation and use the actual field value. @@ -124,7 +124,7 @@ internal HeaderInfo GenerateHeaderInfo(PSObject input, TableControlBody tableBod internal HeaderInfo GenerateHeaderInfo(PSObject input, OutGridViewCommand parentCmdlet) { - HeaderInfo headerInfo = new HeaderInfo(); + HeaderInfo headerInfo = new(); List activeAssociationList; // Get properties from the default property set of the object @@ -191,17 +191,17 @@ internal HeaderInfo GenerateHeaderInfo(PSObject input, OutGridViewCommand parent /// /// None. /// This method updates "activeAssociationList" instance property. - private void FilterActiveAssociationList(List activeAssociationList) + private static void FilterActiveAssociationList(List activeAssociationList) { // we got a valid set of properties from the default property set // make sure we do not have too many properties // NOTE: this is an arbitrary number, chosen to be a sensitive default - int nMax = 256; + const int nMax = 256; if (activeAssociationList.Count > nMax) { - List tmp = new List(activeAssociationList); + List tmp = new(activeAssociationList); activeAssociationList.Clear(); for (int k = 0; k < nMax; k++) activeAssociationList.Add(tmp[k]); @@ -222,7 +222,7 @@ private List GetActiveTableRowDefinition(TableControlBod TableRowDefinition matchingRowDefinition = null; var typeNames = so.InternalTypeNames; - TypeMatch match = new TypeMatch(_expressionFactory, _typeInfoDatabase, typeNames); + TypeMatch match = new(_expressionFactory, _typeInfoDatabase, typeNames); foreach (TableRowDefinition x in tableBody.optionalDefinitionList) { @@ -268,7 +268,7 @@ private List GetActiveTableRowDefinition(TableControlBod } // we have an override, we need to compute the merge of the active cells - List activeRowItemDefinitionList = new List(); + List activeRowItemDefinitionList = new(); int col = 0; foreach (TableRowItemDefinition rowItem in matchingRowDefinition.rowItemDefinitionList) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/GetFormatDataCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/GetFormatDataCommand.cs index 70967aa897b..21c078648f2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/GetFormatDataCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/GetFormatDataCommand.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Management.Automation; using System.Management.Automation.Remoting; using System.Management.Automation.Runspaces; @@ -85,7 +84,7 @@ private static Dictionary> GetTypeGroupMap(IEnumerable typeReference.name).ToList(); + var typesInGroup = typeGroup.typeReferenceList.ConvertAll(static typeReference => typeReference.name); typeGroupMap.Add(typeGroup.name, typesInGroup); } } @@ -98,7 +97,7 @@ private static Dictionary> GetTypeGroupMap(IEnumerable protected override void ProcessRecord() { - // Remoting detection: + // Remoting detection: // * Automatic variable $PSSenderInfo is defined in true remoting contexts as well as in background jobs. // * $PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion contains the client version, as a [version] instance. // Note: Even though $PSVersionTable.PSVersion is of type [semver] in PowerShell 6+, it is of type [version] here, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/WriteFormatDataCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/WriteFormatDataCommand.cs index 919264ad180..3ccbe942829 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/WriteFormatDataCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/WriteFormatDataCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Management.Automation; @@ -75,7 +74,7 @@ public string LiteralPath private bool _isLiteralPath = false; - private List _typeDefinitions = new List(); + private readonly List _typeDefinitions = new(); private bool _force; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs index d370110b8f2..091903f011a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs @@ -27,7 +27,7 @@ public sealed class FormatHex : PSCmdlet /// For cases where a homogenous collection of bytes or other items are directly piped in, we collect all the /// bytes in a List<byte> and then output the formatted result all at once in EndProcessing(). /// - private readonly List _inputBuffer = new List(); + private readonly List _inputBuffer = new(); /// /// Expect to group s by default. When receiving input that should not be grouped, @@ -77,6 +77,7 @@ public Encoding Encoding { return _encoding; } + set { EncodingConversion.WarnIfObsolete(this, value); @@ -152,12 +153,12 @@ protected override void EndProcessing() /// private List ResolvePaths(string[] path, bool literalPath) { - List pathsToProcess = new List(); + List pathsToProcess = new(); ProviderInfo provider = null; foreach (string currentPath in path) { - List newPaths = new List(); + List newPaths = new(); if (literalPath) { @@ -173,7 +174,7 @@ private List ResolvePaths(string[] path, bool literalPath) { if (!WildcardPattern.ContainsWildcardCharacters(currentPath)) { - ErrorRecord errorRecord = new ErrorRecord(e, "FileNotFound", ErrorCategory.ObjectNotFound, path); + ErrorRecord errorRecord = new(e, "FileNotFound", ErrorCategory.ObjectNotFound, path); WriteError(errorRecord); continue; } @@ -184,7 +185,7 @@ private List ResolvePaths(string[] path, bool literalPath) { // Write a non-terminating error message indicating that path specified is not supported. string errorMessage = StringUtil.Format(UtilityCommonStrings.FormatHexOnlySupportsFileSystemPaths, currentPath); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(errorMessage), "FormatHexOnlySupportsFileSystemPaths", ErrorCategory.InvalidArgument, @@ -292,7 +293,7 @@ private void ProcessString(string originalString) } } - private static readonly Random _idGenerator = new Random(); + private static readonly Random _idGenerator = new(); private static string GetGroupLabel(Type inputType) => string.Format("{0} ({1}) <{2:X8}>", inputType.Name, inputType.FullName, _idGenerator.Next()); @@ -369,7 +370,7 @@ private void ProcessInputObjects(PSObject inputObject) else { string errorMessage = StringUtil.Format(UtilityCommonStrings.FormatHexTypeNotSupported, obj.GetType()); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(errorMessage), "FormatHexTypeNotSupported", ErrorCategory.InvalidArgument, @@ -485,7 +486,7 @@ private byte[] ConvertToBytes(object inputObject) /// Offset in the file. private void WriteHexadecimal(Span inputBytes, string path, long offset) { - var bytesPerObject = 16; + const int bytesPerObject = 16; for (int index = 0; index < inputBytes.Length; index += bytesPerObject) { var count = inputBytes.Length - index < bytesPerObject @@ -507,7 +508,7 @@ private void WriteHexadecimal(Span inputBytes, string path, long offset) /// private void WriteHexadecimal(Span inputBytes, long offset, string label) { - var bytesPerObject = 16; + const int bytesPerObject = 16; for (int index = 0; index < inputBytes.Length; index += bytesPerObject) { var count = inputBytes.Length - index < bytesPerObject diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-list/Format-List.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-list/Format-List.cs index 202250f33a1..7237cd46834 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-list/Format-List.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-list/Format-List.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands public class FormatListCommand : OuterFormatTableAndListBase { /// - /// Constructor to set the inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public FormatListCommand() { @@ -22,4 +23,3 @@ public FormatListCommand() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-object/Format-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-object/Format-Object.cs index 813bfad23c0..9e064ba37db 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-object/Format-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-object/Format-Object.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands public class FormatCustomCommand : OuterFormatShapeCommandBase { /// - /// Constructor to se the inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public FormatCustomCommand() { @@ -57,12 +58,12 @@ public int Depth internal override FormattingCommandLineParameters GetCommandLineParameters() { - FormattingCommandLineParameters parameters = new FormattingCommandLineParameters(); + FormattingCommandLineParameters parameters = new(); if (_props != null) { - ParameterProcessor processor = new ParameterProcessor(new FormatObjectParameterDefinition()); - TerminatingErrorContext invocationContext = new TerminatingErrorContext(this); + ParameterProcessor processor = new(new FormatObjectParameterDefinition()); + TerminatingErrorContext invocationContext = new(this); parameters.mshParameterList = processor.ProcessParameters(_props, invocationContext); } @@ -86,7 +87,7 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() parameters.expansion = ProcessExpandParameter(); - ComplexSpecificParameters csp = new ComplexSpecificParameters(); + ComplexSpecificParameters csp = new(); csp.maxDepth = _depth; parameters.shapeParameters = csp; @@ -94,4 +95,3 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-table/Format-Table.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-table/Format-Table.cs index 6939c38643d..e831981568e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-table/Format-Table.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-table/Format-Table.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands public class FormatTableCommand : OuterFormatTableBase { /// - /// Constructor to set the inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public FormatTableCommand() { @@ -22,4 +23,3 @@ public FormatTableCommand() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-wide/Format-Wide.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-wide/Format-Wide.cs index 5927244d896..b3e593160b5 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-wide/Format-Wide.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-wide/Format-Wide.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.IO; using System.Management.Automation; using System.Management.Automation.Internal; @@ -17,7 +16,8 @@ namespace Microsoft.PowerShell.Commands public class FormatWideCommand : OuterFormatShapeCommandBase { /// - /// Constructor to se the inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public FormatWideCommand() { @@ -47,14 +47,8 @@ public object Property [Parameter] public SwitchParameter AutoSize { - get - { - if (_autosize.HasValue) - return _autosize.Value; - return false; - } - - set { _autosize = value; } + get => _autosize.GetValueOrDefault(); + set => _autosize = value; } private bool? _autosize = null; @@ -67,14 +61,8 @@ public SwitchParameter AutoSize [ValidateRangeAttribute(1, int.MaxValue)] public int Column { - get - { - if (_column.HasValue) - return _column.Value; - return -1; - } - - set { _column = value; } + get => _column.GetValueOrDefault(-1); + set => _column = value; } private int? _column = null; @@ -83,12 +71,12 @@ public int Column internal override FormattingCommandLineParameters GetCommandLineParameters() { - FormattingCommandLineParameters parameters = new FormattingCommandLineParameters(); + FormattingCommandLineParameters parameters = new(); if (_prop != null) { - ParameterProcessor processor = new ParameterProcessor(new FormatWideParameterDefinition()); - TerminatingErrorContext invocationContext = new TerminatingErrorContext(this); + ParameterProcessor processor = new(new FormatWideParameterDefinition()); + TerminatingErrorContext invocationContext = new(this); parameters.mshParameterList = processor.ProcessParameters(new object[] { _prop }, invocationContext); } @@ -104,22 +92,19 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() } // we cannot specify -column and -autosize, they are mutually exclusive - if (_autosize.HasValue && _column.HasValue) + if (AutoSize && _column.HasValue) { - if (_autosize.Value) - { - // the user specified -autosize:true AND a column number - string msg = StringUtil.Format(FormatAndOut_format_xxx.CannotSpecifyAutosizeAndColumnsError); + // the user specified -autosize:true AND a column number + string msg = StringUtil.Format(FormatAndOut_format_xxx.CannotSpecifyAutosizeAndColumnsError); - ErrorRecord errorRecord = new ErrorRecord( - new InvalidDataException(), - "FormatCannotSpecifyAutosizeAndColumns", - ErrorCategory.InvalidArgument, - null); + ErrorRecord errorRecord = new( + new InvalidDataException(), + "FormatCannotSpecifyAutosizeAndColumns", + ErrorCategory.InvalidArgument, + null); - errorRecord.ErrorDetails = new ErrorDetails(msg); - this.ThrowTerminatingError(errorRecord); - } + errorRecord.ErrorDetails = new ErrorDetails(msg); + this.ThrowTerminatingError(errorRecord); } parameters.groupByParameter = this.ProcessGroupByParameter(); @@ -134,7 +119,7 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() if (_autosize.HasValue) parameters.autosize = _autosize.Value; - WideSpecificParameters wideSpecific = new WideSpecificParameters(); + WideSpecificParameters wideSpecific = new(); parameters.shapeParameters = wideSpecific; if (_column.HasValue) { @@ -145,4 +130,3 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() } } } - diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-file/Out-File.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-file/Out-File.cs index 9885cbcaa47..2fbdb73dc9c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-file/Out-File.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-file/Out-File.cs @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.IO; using System.Management.Automation; -using System.Management.Automation.Host; using System.Management.Automation.Internal; using System.Text; @@ -27,7 +25,8 @@ internal static FileMode Convert(OpenMode openMode) public class OutFileCommand : FrontEndCommandBase { /// - /// Set inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public OutFileCommand() { @@ -229,7 +228,7 @@ private LineOutput InstantiateLineOutputInterface() } // use the stream writer to create and initialize the Line Output writer - TextWriterLineOutput twlo = new TextWriterLineOutput(_sw, computedWidth, _suppressNewline); + TextWriterLineOutput twlo = new(_sw, computedWidth, _suppressNewline); // finally have the ILineOutput interface extracted return (LineOutput)twlo; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/Out-Printer.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/Out-Printer.cs index 33416cdea0a..58342172906 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/Out-Printer.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/Out-Printer.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands public class OutPrinterCommand : FrontEndCommandBase { /// - /// Set inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public OutPrinterCommand() { @@ -55,7 +56,7 @@ protected override void BeginProcessing() /// private LineOutput InstantiateLineOutputInterface() { - PrinterLineOutput printOutput = new PrinterLineOutput(_printerName); + PrinterLineOutput printOutput = new(_printerName); return (LineOutput)printOutput; } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/PrinterLineOutput.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/PrinterLineOutput.cs index e38a22ac98c..cbd19a17f4f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/PrinterLineOutput.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-printer/PrinterLineOutput.cs @@ -70,6 +70,7 @@ internal override void WriteLine(string s) #endregion /// + /// Initializes static members of the class. /// Used for static initializations like DefaultPrintFontName. /// static PrinterLineOutput() @@ -81,7 +82,7 @@ static PrinterLineOutput() } /// - /// Constructor for the class. + /// Initializes a new instance of the class. /// /// Name of printer, if null use default printer. internal PrinterLineOutput(string printerName) @@ -89,8 +90,8 @@ internal PrinterLineOutput(string printerName) _printerName = printerName; // instantiate the helper to do the line processing when LineOutput.WriteXXX() is called - WriteLineHelper.WriteCallback wl = new WriteLineHelper.WriteCallback(this.OnWriteLine); - WriteLineHelper.WriteCallback w = new WriteLineHelper.WriteCallback(this.OnWrite); + WriteLineHelper.WriteCallback wl = new(this.OnWriteLine); + WriteLineHelper.WriteCallback w = new(this.OnWrite); _writeLineHelper = new WriteLineHelper(true, wl, w, this.DisplayCells); } @@ -123,7 +124,7 @@ private void DoPrint() try { // create a new print document object and set the printer name, if available - PrintDocument pd = new PrintDocument(); + PrintDocument pd = new(); if (!string.IsNullOrEmpty(_printerName)) { @@ -187,9 +188,9 @@ private void VerifyFont(Graphics g) // we compute the length of two strings, one made of "large" characters // one made of "narrow" ones. If they are the same length, we assume that // the font is fixed pitch. - string large = "ABCDEF"; + const string large = "ABCDEF"; float wLarge = g.MeasureString(large, _printFont).Width / large.Length; - string narrow = ".;'}l|"; + const string narrow = ".;'}l|"; float wNarrow = g.MeasureString(narrow, _printFont).Width / narrow.Length; if (Math.Abs((float)(wLarge - wNarrow)) < 0.001F) @@ -229,7 +230,7 @@ private void pd_PrintPage(object sender, PrintPageEventArgs ev) // on the first page we have to initialize the metrics for LineOutput // work out the number of columns per page assuming fixed pitch font - string s = "ABCDEF"; + const string s = "ABCDEF"; float w = ev.Graphics.MeasureString(s, _printFont).Width / s.Length; float columnsPerPage = ev.MarginBounds.Width / w; @@ -276,7 +277,7 @@ private void pd_PrintPage(object sender, PrintPageEventArgs ev) /// /// Name of the printer to print to. Null means default printer. /// - private string _printerName = null; + private readonly string _printerName = null; /// /// Name of the font to use, if null the default is used. @@ -315,13 +316,13 @@ private void pd_PrintPage(object sender, PrintPageEventArgs ev) /// /// Text lines ready to print (after output cache playback). /// - private Queue _lines = new Queue(); + private readonly Queue _lines = new(); /// /// Cached font object. /// private Font _printFont = null; - private WriteLineHelper _writeLineHelper; + private readonly WriteLineHelper _writeLineHelper; } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-string/Out-String.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-string/Out-String.cs index 5dcb3c4f588..512bf1048e0 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-string/Out-String.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/out-string/Out-String.cs @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; -using System.Management.Automation.Host; using System.Text; using Microsoft.PowerShell.Commands.Internal.Format; @@ -63,7 +61,8 @@ public SwitchParameter NoNewline #endregion /// - /// Set inner command. + /// Initializes a new instance of the class + /// and sets the inner command. /// public OutStringCommand() { @@ -91,7 +90,7 @@ protected override void BeginProcessing() private LineOutput InstantiateLineOutputInterface() { // set up the streaming text writer - StreamingTextWriter.WriteLineCallback callback = new StreamingTextWriter.WriteLineCallback(this.OnWriteLine); + StreamingTextWriter.WriteLineCallback callback = new(this.OnWriteLine); _writer = new StreamingTextWriter(callback, Host.CurrentCulture); @@ -105,7 +104,7 @@ private LineOutput InstantiateLineOutputInterface() } // use it to create and initialize the Line Output writer - TextWriterLineOutput twlo = new TextWriterLineOutput(_writer, computedWidth); + TextWriterLineOutput twlo = new(_writer, computedWidth); // finally have the LineOutput interface extracted return (LineOutput)twlo; @@ -166,6 +165,6 @@ protected override void EndProcessing() /// /// Buffer used when buffering until the end. /// - private StringBuilder _buffer = new StringBuilder(); + private readonly StringBuilder _buffer = new(); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-Error.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-Error.cs index 7c2fdbe0c14..053f99f897d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-Error.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-Error.cs @@ -72,7 +72,7 @@ protected override void ProcessRecord() } index = 0; - bool addErrorIdentifier = errorRecords.Count > 1 ? true : false; + bool addErrorIdentifier = errorRecords.Count > 1; foreach (object errorRecord in errorRecords) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-PSBreakpoint.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-PSBreakpoint.cs index 4f8903facfd..448e3edf3bd 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-PSBreakpoint.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Get-PSBreakpoint.cs @@ -22,7 +22,7 @@ public enum BreakpointType /// Breakpoint on a command Command - }; + } /// /// This class implements Get-PSBreakpoint. @@ -107,22 +107,16 @@ protected override void ProcessRecord() breakpoints = Filter( breakpoints, Id, - delegate (Breakpoint breakpoint, int id) - { - return breakpoint.Id == id; - } - ); + static (Breakpoint breakpoint, int id) => breakpoint.Id == id); } else if (ParameterSetName.Equals(CommandParameterSetName, StringComparison.OrdinalIgnoreCase)) { breakpoints = Filter( breakpoints, Command, - delegate (Breakpoint breakpoint, string command) + (Breakpoint breakpoint, string command) => { - CommandBreakpoint commandBreakpoint = breakpoint as CommandBreakpoint; - - if (commandBreakpoint == null) + if (!(breakpoint is CommandBreakpoint commandBreakpoint)) { return false; } @@ -135,11 +129,9 @@ protected override void ProcessRecord() breakpoints = Filter( breakpoints, Variable, - delegate (Breakpoint breakpoint, string variable) + (Breakpoint breakpoint, string variable) => { - VariableBreakpoint variableBreakpoint = breakpoint as VariableBreakpoint; - - if (variableBreakpoint == null) + if (!(breakpoint is VariableBreakpoint variableBreakpoint)) { return false; } @@ -152,7 +144,7 @@ protected override void ProcessRecord() breakpoints = Filter( breakpoints, Type, - delegate (Breakpoint breakpoint, BreakpointType type) + (Breakpoint breakpoint, BreakpointType type) => { switch (type) { @@ -195,7 +187,7 @@ protected override void ProcessRecord() breakpoints = Filter( breakpoints, Script, - delegate (Breakpoint breakpoint, string script) + (Breakpoint breakpoint, string script) => { if (breakpoint.Script == null) { @@ -230,9 +222,9 @@ protected override void ProcessRecord() /// Returns the items in the input list that match an item in the filter array according to /// the given selection criterion. /// - private List Filter(List input, T[] filter, FilterSelector selector) + private static List Filter(List input, T[] filter, FilterSelector selector) { - List output = new List(); + List output = new(); for (int i = 0; i < input.Count; i++) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetAliasCommand.cs index 49baa9bd296..bf4c8a39db4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetAliasCommand.cs @@ -118,7 +118,7 @@ private void WriteMatches(string value, string parametersetname) _excludes, WildcardOptions.IgnoreCase); - List results = new List(); + List results = new(); foreach (KeyValuePair tableEntry in aliasTable) { if (parametersetname.Equals("Definition", StringComparison.OrdinalIgnoreCase)) @@ -181,10 +181,7 @@ private void WriteMatches(string value, string parametersetname) } results.Sort( - delegate (AliasInfo left, AliasInfo right) - { - return StringComparer.CurrentCultureIgnoreCase.Compare(left.Name, right.Name); - }); + static (AliasInfo left, AliasInfo right) => StringComparer.CurrentCultureIgnoreCase.Compare(left.Name, right.Name)); foreach (AliasInfo alias in results) { this.WriteObject(alias); @@ -195,8 +192,8 @@ private void WriteMatches(string value, string parametersetname) // Need to write an error if the user tries to get an alias // tat doesn't exist and they are not globbing. - ItemNotFoundException itemNotFound = new ItemNotFoundException(StringUtil.Format(AliasCommandStrings.NoAliasFound, displayString, value)); - ErrorRecord er = new ErrorRecord(itemNotFound, "ItemNotFoundException", ErrorCategory.ObjectNotFound, value); + ItemNotFoundException itemNotFound = new(StringUtil.Format(AliasCommandStrings.NoAliasFound, displayString, value)); + ErrorRecord er = new(itemNotFound, "ItemNotFoundException", ErrorCategory.ObjectNotFound, value); WriteError(er); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs index 06034a29d73..40e0bbeefd7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs @@ -368,15 +368,15 @@ protected override void ProcessRecord() else { // output DateTime object wrapped in an PSObject with DisplayHint attached - PSObject outputObj = new PSObject(dateToUse); - PSNoteProperty note = new PSNoteProperty("DisplayHint", DisplayHint); + PSObject outputObj = new(dateToUse); + PSNoteProperty note = new("DisplayHint", DisplayHint); outputObj.Properties.Add(note); WriteObject(outputObj); } } - private static readonly DateTime s_epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + private static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); /// /// This is more an implementation of the UNIX strftime. @@ -384,7 +384,7 @@ protected override void ProcessRecord() private string UFormatDateString(DateTime dateTime) { int offset = 0; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); // folks may include the "+" as part of the format string if (UFormat[0] == '+') @@ -440,11 +440,12 @@ private string UFormatDateString(DateTime dateTime) break; case 'G': - sb.Append("{0:yyyy}"); + sb.Append(StringUtil.Format("{0:0000}", ISOWeek.GetYear(dateTime))); break; case 'g': - sb.Append("{0:yy}"); + int isoYearWithoutCentury = ISOWeek.GetYear(dateTime) % 100; + sb.Append(StringUtil.Format("{0:00}", isoYearWithoutCentury)); break; case 'H': @@ -480,7 +481,7 @@ private string UFormatDateString(DateTime dateTime) break; case 'n': - sb.Append("\n"); + sb.Append('\n'); break; case 'p': @@ -508,7 +509,7 @@ private string UFormatDateString(DateTime dateTime) break; case 't': - sb.Append("\t"); + sb.Append('\t'); break; case 'U': @@ -516,7 +517,8 @@ private string UFormatDateString(DateTime dateTime) break; case 'u': - sb.Append((int)dateTime.DayOfWeek); + int dayOfWeek = dateTime.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)dateTime.DayOfWeek; + sb.Append(dayOfWeek); break; case 'V': diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventCommand.cs index faf16d384f7..42360983c4e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventCommand.cs @@ -124,7 +124,7 @@ protected override void EndProcessing() error = EventingStrings.EventIdentifierNotFound; } - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(string.Format(System.Globalization.CultureInfo.CurrentCulture, error, identifier)), "INVALID_SOURCE_IDENTIFIER", ErrorCategory.InvalidArgument, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventSubscriberCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventSubscriberCommand.cs index cde73b2914d..b3bd99b7bdf 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventSubscriberCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetEventSubscriberCommand.cs @@ -67,7 +67,7 @@ protected override void ProcessRecord() // Go through all the received events and write them to the output // pipeline - List subscribers = new List(Events.Subscribers); + List subscribers = new(Events.Subscribers); foreach (PSEventSubscriber subscriber in subscribers) { // If they specified a event identifier and we don't match, continue @@ -118,7 +118,7 @@ protected override void ProcessRecord() error = EventingStrings.EventSubscriptionNotFound; } - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(string.Format(System.Globalization.CultureInfo.CurrentCulture, error, identifier)), "INVALID_SOURCE_IDENTIFIER", ErrorCategory.InvalidArgument, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHash.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHash.cs index 65e55a86ab1..40ea1d187d5 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHash.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHash.cs @@ -83,7 +83,7 @@ protected override void BeginProcessing() /// protected override void ProcessRecord() { - List pathsToProcess = new List(); + List pathsToProcess = new(); ProviderInfo provider = null; switch (ParameterSetName) @@ -104,7 +104,7 @@ protected override void ProcessRecord() { if (!WildcardPattern.ContainsWildcardCharacters(path)) { - ErrorRecord errorRecord = new ErrorRecord(e, + ErrorRecord errorRecord = new(e, "FileNotFound", ErrorCategory.ObjectNotFound, path); @@ -211,7 +211,7 @@ private bool ComputeFileHash(string path, out string hash) /// private void WriteHashResult(string Algorithm, string hash, string path) { - FileHashInfo result = new FileHashInfo(); + FileHashInfo result = new(); result.Algorithm = Algorithm; result.Hash = hash; result.Path = path; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHostCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHostCmdlet.cs index 444e085591f..fec8bafe34a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHostCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHostCmdlet.cs @@ -3,8 +3,6 @@ using System.Management.Automation; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetMember.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetMember.cs index daa870d9b1a..cfd380853b9 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetMember.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetMember.cs @@ -6,7 +6,6 @@ using System.Collections.Specialized; using System.Management.Automation; using System.Management.Automation.Internal; -using System.Reflection; namespace Microsoft.PowerShell.Commands { @@ -23,7 +22,7 @@ public override string ToString() return Definition; } /// - /// Initializes a new instance of this class. + /// Initializes a new instance of the class. /// public MemberDefinition(string typeName, string name, PSMemberTypes memberType, string definition) { @@ -65,21 +64,21 @@ public class GetMemberCommand : PSCmdlet /// The object to retrieve properties from. /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } + public PSObject InputObject { get; set; } /// /// The member names to be retrieved. /// [Parameter(Position = 0)] [ValidateNotNullOrEmpty] - public string[] Name { set; get; } = new string[] { "*" }; + public string[] Name { get; set; } = new string[] { "*" }; /// /// The member types to be retrieved. /// [Parameter] [Alias("Type")] - public PSMemberTypes MemberType { set; get; } = PSMemberTypes.All; + public PSMemberTypes MemberType { get; set; } = PSMemberTypes.All; /// /// View from which the members are retrieved. @@ -94,9 +93,9 @@ public class GetMemberCommand : PSCmdlet [Parameter] public SwitchParameter Static { - set { _staticParameter = value; } - get { return _staticParameter; } + + set { _staticParameter = value; } } /// @@ -132,7 +131,7 @@ public SwitchParameter Force private MshMemberMatchOptions _matchOptions = MshMemberMatchOptions.None; - private HybridDictionary _typesAlreadyDisplayed = new HybridDictionary(); + private readonly HybridDictionary _typesAlreadyDisplayed = new(); /// /// This method implements the ProcessRecord method for get-member command. @@ -250,7 +249,7 @@ protected override void ProcessRecord() } } - private class MemberComparer : System.Collections.Generic.IComparer + private sealed class MemberComparer : System.Collections.Generic.IComparer { public int Compare(MemberDefinition first, MemberDefinition second) { @@ -272,7 +271,7 @@ protected override void EndProcessing() { if (_typesAlreadyDisplayed.Count == 0) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(GetMember.NoObjectSpecified), "NoObjectInGetMember", ErrorCategory.CloseError, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs index 01cf6534c48..a8ad9deb22b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerShell.Commands /// [Cmdlet(VerbsCommon.Get, "Random", DefaultParameterSetName = GetRandomCommand.RandomNumberParameterSet, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097016", RemotingCapability = RemotingCapability.None)] - [OutputType(typeof(Int32), typeof(Int64), typeof(double))] + [OutputType(typeof(int), typeof(long), typeof(double))] public class GetRandomCommand : PSCmdlet { #region Parameter set handling @@ -95,7 +95,7 @@ private void ThrowMinGreaterThanOrEqualMax(object minValue, object maxValue) throw PSTraceSource.NewArgumentNullException("max"); } - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(string.Format( CultureInfo.InvariantCulture, GetRandomCommandStrings.MinGreaterThanOrEqualMax, minValue, maxValue)), "MinGreaterThanOrEqualMax", @@ -109,10 +109,10 @@ private void ThrowMinGreaterThanOrEqualMax(object minValue, object maxValue) #region Random generator state - private static ReaderWriterLockSlim s_runspaceGeneratorMapLock = new ReaderWriterLockSlim(); + private static readonly ReaderWriterLockSlim s_runspaceGeneratorMapLock = new(); // 1-to-1 mapping of runspaces and random number generators - private static Dictionary s_runspaceGeneratorMap = new Dictionary(); + private static readonly Dictionary s_runspaceGeneratorMap = new(); private static void CurrentRunspace_StateChanged(object sender, RunspaceStateEventArgs e) { @@ -217,7 +217,7 @@ private PolymorphicRandomNumberGenerator Generator [Parameter(ParameterSetName = RandomNumberParameterSet)] public object Minimum { get; set; } - private bool IsInt(object o) + private static bool IsInt(object o) { if (o == null || o is int) { @@ -227,9 +227,9 @@ private bool IsInt(object o) return false; } - private bool IsInt64(object o) + private static bool IsInt64(object o) { - if (o == null || o is Int64) + if (o == null || o is long) { return true; } @@ -237,7 +237,7 @@ private bool IsInt64(object o) return false; } - private object ProcessOperand(object o) + private static object ProcessOperand(object o) { if (o == null) { @@ -257,7 +257,7 @@ private object ProcessOperand(object o) return baseObject; } - private double ConvertToDouble(object o, double defaultIfNull) + private static double ConvertToDouble(object o, double defaultIfNull) { if (o == null) { @@ -334,7 +334,7 @@ private double GetRandomDouble(double minValue, double maxValue) { double r = Generator.NextDouble(); randomNumber = minValue + r * diff; - diff = diff * r; + diff *= r; } while (randomNumber >= maxValue); } @@ -348,11 +348,11 @@ private double GetRandomDouble(double minValue, double maxValue) /// /// /// - private Int64 GetRandomInt64(Int64 minValue, Int64 maxValue) + private long GetRandomInt64(long minValue, long maxValue) { // Randomly generate eight bytes and convert the byte array to UInt64 - var buffer = new byte[sizeof(UInt64)]; - UInt64 randomUint64; + var buffer = new byte[sizeof(ulong)]; + ulong randomUint64; BigInteger bigIntegerDiff = (BigInteger)maxValue - (BigInteger)minValue; @@ -364,17 +364,17 @@ private Int64 GetRandomInt64(Int64 minValue, Int64 maxValue) } // The difference of two Int64 numbers would not exceed UInt64.MaxValue, so it can be represented by a UInt64 number. - UInt64 uint64Diff = (UInt64)bigIntegerDiff; + ulong uint64Diff = (ulong)bigIntegerDiff; // Calculate the number of bits to represent the diff in type UInt64 int bitsToRepresentDiff = 0; - UInt64 diffCopy = uint64Diff; + ulong diffCopy = uint64Diff; for (; diffCopy != 0; bitsToRepresentDiff++) { diffCopy >>= 1; } // Get the mask for the number of bits - UInt64 mask = (0xffffffffffffffff >> (64 - bitsToRepresentDiff)); + ulong mask = (0xffffffffffffffff >> (64 - bitsToRepresentDiff)); do { // Randomly fill the buffer @@ -386,7 +386,7 @@ private Int64 GetRandomInt64(Int64 minValue, Int64 maxValue) } while (uint64Diff <= randomUint64); double randomNumber = minValue * 1.0 + randomUint64 * 1.0; - return (Int64)randomNumber; + return (long)randomNumber; } /// @@ -425,8 +425,8 @@ protected override void BeginProcessing() } else if ((IsInt64(maxOperand) || IsInt(maxOperand)) && (IsInt64(minOperand) || IsInt(minOperand))) { - Int64 minValue = minOperand != null ? ((minOperand is Int64) ? (Int64)minOperand : (int)minOperand) : 0; - Int64 maxValue = maxOperand != null ? ((maxOperand is Int64) ? (Int64)maxOperand : (int)maxOperand) : Int64.MaxValue; + long minValue = minOperand != null ? ((minOperand is long) ? (long)minOperand : (int)minOperand) : 0; + long maxValue = maxOperand != null ? ((maxOperand is long) ? (long)maxOperand : (int)maxOperand) : long.MaxValue; if (minValue >= maxValue) { @@ -435,7 +435,7 @@ protected override void BeginProcessing() for (int i = 0; i < Count; i++) { - Int64 randomNumber = GetRandomInt64(minValue, maxValue); + long randomNumber = GetRandomInt64(minValue, maxValue); Debug.Assert(minValue <= randomNumber, "lower bound <= random number"); Debug.Assert(randomNumber < maxValue, "random number < upper bound"); @@ -583,7 +583,7 @@ protected override void EndProcessing() internal class PolymorphicRandomNumberGenerator { /// - /// Constructor. + /// Initializes a new instance of the class. /// public PolymorphicRandomNumberGenerator() { @@ -597,8 +597,8 @@ internal PolymorphicRandomNumberGenerator(int seed) _pseudoGenerator = new Random(seed); } - private Random _pseudoGenerator = null; - private RandomNumberGenerator _cryptographicGenerator = null; + private readonly Random _pseudoGenerator = null; + private readonly RandomNumberGenerator _cryptographicGenerator = null; /// /// Generates a random floating-point number that is greater than or equal to 0.0, and less than 1.0. @@ -608,7 +608,7 @@ internal double NextDouble() { // According to the CLR source: // "Including this division at the end gives us significantly improved random number distribution." - return Next() * (1.0 / Int32.MaxValue); + return Next() * (1.0 / int.MaxValue); } /// @@ -626,11 +626,11 @@ internal int Next() { randomNumber = InternalSample(); } - while (randomNumber == Int32.MaxValue); + while (randomNumber == int.MaxValue); if (randomNumber < 0) { - randomNumber += Int32.MaxValue; + randomNumber += int.MaxValue; } return randomNumber; @@ -673,7 +673,7 @@ public int Next(int minValue, int maxValue) } else { - double largeSample = InternalSampleLargeRange() * (1.0 / (2 * ((uint)Int32.MaxValue))); + double largeSample = InternalSampleLargeRange() * (1.0 / (2 * ((uint)int.MaxValue))); randomNumber = (int)((long)(largeSample * range) + minValue); } @@ -724,9 +724,9 @@ private double InternalSampleLargeRange() do { randomNumber = InternalSample(); - } while (randomNumber == Int32.MaxValue); + } while (randomNumber == int.MaxValue); - randomNumber += Int32.MaxValue; + randomNumber += int.MaxValue; return randomNumber; } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRunspaceCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRunspaceCommand.cs index 0aedd4c9d06..10c050a4562 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRunspaceCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRunspaceCommand.cs @@ -126,7 +126,7 @@ internal static IReadOnlyList GetAllRunspaces() internal static IReadOnlyList GetRunspacesByName(string[] names) { - List rtnRunspaces = new List(); + List rtnRunspaces = new(); IReadOnlyList runspaces = Runspace.RunspaceList; foreach (string name in names) @@ -146,7 +146,7 @@ internal static IReadOnlyList GetRunspacesByName(string[] names) internal static IReadOnlyList GetRunspacesById(int[] ids) { - List rtnRunspaces = new List(); + List rtnRunspaces = new(); foreach (int id in ids) { @@ -167,7 +167,7 @@ internal static IReadOnlyList GetRunspacesById(int[] ids) internal static IReadOnlyList GetRunspacesByInstanceId(Guid[] instanceIds) { - List rtnRunspaces = new List(); + List rtnRunspaces = new(); IReadOnlyList runspaces = Runspace.RunspaceList; foreach (Guid instanceId in instanceIds) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUnique.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUnique.cs index ea33f7c28d7..b43a870dccb 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUnique.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUnique.cs @@ -19,7 +19,7 @@ public sealed class GetUniqueCommand : PSCmdlet /// /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// This parameter specifies that objects should be converted to @@ -99,7 +99,7 @@ protected override void ProcessRecord() true); // case-sensitive } - isUnique = (0 != _comparer.Compare(InputObject, _lastObject)); + isUnique = (_comparer.Compare(InputObject, _lastObject) != 0); } if (isUnique) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetVerbCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetVerbCommand.cs index 766b38116c0..1ec93b0f1d7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetVerbCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetVerbCommand.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Management.Automation; using System.Reflection; @@ -71,7 +70,7 @@ protected override void ProcessRecord() } } - VerbInfo verb = new VerbInfo(); + VerbInfo verb = new(); verb.Verb = field.Name; verb.AliasPrefix = VerbAliasPrefixes.GetVerbAliasPrefix(field.Name); verb.Group = groupName; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs index 9938dc15c7f..961826b30fc 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Group-Object.cs @@ -5,7 +5,6 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -141,7 +140,7 @@ internal virtual void Add(PSObject groupValue) private static string BuildName(List propValues) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); foreach (ObjectCommandPropertyValue propValue in propValues) { var propValuePropertyValue = propValue?.PropertyValue; @@ -149,7 +148,7 @@ private static string BuildName(List propValues) { if (propValuePropertyValue is ICollection propertyValueItems) { - sb.Append("{"); + sb.Append('{'); var length = sb.Length; foreach (object item in propertyValueItems) @@ -177,7 +176,7 @@ public ArrayList Values { get { - ArrayList values = new ArrayList(); + ArrayList values = new(); foreach (ObjectCommandPropertyValue propValue in GroupValue.orderValues) { values.Add(propValue.PropertyValue); @@ -249,10 +248,10 @@ public class GroupObjectCommand : ObjectBase [Parameter(ParameterSetName = "HashTable")] public SwitchParameter AsString { get; set; } - private readonly List _groups = new List(); - private readonly OrderByProperty _orderByProperty = new OrderByProperty(); - private readonly Dictionary _tupleToGroupInfoMappingDictionary = new Dictionary(); - private readonly List _entriesToOrder = new List(); + private readonly List _groups = new(); + private readonly OrderByProperty _orderByProperty = new(); + private readonly Dictionary _tupleToGroupInfoMappingDictionary = new(); + private readonly List _entriesToOrder = new(); private OrderByPropertyComparer _orderByPropertyComparer; private bool _hasProcessedFirstInputObject; private bool _hasDifferentValueTypes; @@ -376,7 +375,7 @@ private static void DoOrderedGrouping( private void WriteNonTerminatingError(Exception exception, string resourceIdAndErrorId, ErrorCategory category) { - Exception ex = new Exception(StringUtil.Format(resourceIdAndErrorId), exception); + Exception ex = new(StringUtil.Format(resourceIdAndErrorId), exception); WriteError(new ErrorRecord(ex, resourceIdAndErrorId, category, null)); } @@ -402,15 +401,15 @@ protected override void ProcessRecord() if (AsString && !AsHashTable) { - ArgumentException ex = new ArgumentException(UtilityCommonStrings.GroupObjectWithHashTable); - ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.InvalidArgument, AsString); + ArgumentException ex = new(UtilityCommonStrings.GroupObjectWithHashTable); + ErrorRecord er = new(ex, "ArgumentException", ErrorCategory.InvalidArgument, AsString); ThrowTerminatingError(er); } if (AsHashTable && !AsString && (Property != null && (Property.Length > 1 || _orderByProperty.MshParameterList.Count > 1))) { - ArgumentException ex = new ArgumentException(UtilityCommonStrings.GroupObjectSingleProperty); - ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.InvalidArgument, Property); + ArgumentException ex = new(UtilityCommonStrings.GroupObjectSingleProperty); + ErrorRecord er = new(ex, "ArgumentException", ErrorCategory.InvalidArgument, Property); ThrowTerminatingError(er); } @@ -444,7 +443,7 @@ private void UpdateOrderPropertyTypeInfo(List curren { if (_propertyTypesCandidate == null) { - _propertyTypesCandidate = currentEntryOrderValues.Select(c => PSObject.Base(c.PropertyValue)?.GetType()).ToArray(); + _propertyTypesCandidate = currentEntryOrderValues.Select(static c => PSObject.Base(c.PropertyValue)?.GetType()).ToArray(); return; } @@ -492,7 +491,7 @@ protected override void EndProcessing() { // using OrderBy to get stable sort. // fast path when we only have the same object types to group - foreach (var entry in _entriesToOrder.OrderBy(e => e, _orderByPropertyComparer)) + foreach (var entry in _entriesToOrder.OrderBy(static e => e, _orderByPropertyComparer)) { DoOrderedGrouping(entry, NoElement, _groups, _tupleToGroupInfoMappingDictionary, _orderByPropertyComparer); if (Stopping) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs index 2171dd66aec..325632c44ce 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs @@ -127,7 +127,7 @@ protected override void BeginProcessing() if (IsModuleSpecified && IsFullyQualifiedModuleSpecified) { string errMsg = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, nameof(Module), nameof(FullyQualifiedModule)); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "ModuleAndFullyQualifiedModuleCannotBeSpecifiedTogether", ErrorCategory.InvalidOperation, null); + ErrorRecord error = new(new InvalidOperationException(errMsg), "ModuleAndFullyQualifiedModuleCannotBeSpecifiedTogether", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(error); } @@ -257,9 +257,9 @@ private PSModuleInfo CreateModule(string manifestFile) [ValidateNotNullOrEmpty] public new string Prefix { - set { base.Prefix = value; } - get { return base.Prefix; } + + set { base.Prefix = value; } } /// @@ -289,7 +289,7 @@ protected override void BeginProcessing() if (IsModuleSpecified && IsFullyQualifiedModuleSpecified) { string errMsg = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, nameof(Module), nameof(FullyQualifiedModule)); - ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "ModuleAndFullyQualifiedModuleCannotBeSpecifiedTogether", ErrorCategory.InvalidOperation, null); + ErrorRecord error = new(new InvalidOperationException(errMsg), "ModuleAndFullyQualifiedModuleCannotBeSpecifiedTogether", ErrorCategory.InvalidOperation, null); ThrowTerminatingError(error); } @@ -480,7 +480,7 @@ public ModuleSpecification[] FullyQualifiedModule } } - private ModuleSpecification[] _moduleSpecifications = new ModuleSpecification[0]; + private ModuleSpecification[] _moduleSpecifications = Array.Empty(); internal bool IsFullyQualifiedModuleSpecified = false; private bool _commandParameterSpecified; // initialized to default value in the constructor @@ -521,7 +521,7 @@ public string[] FormatTypeName /// /// This parameter specified a prefix used to modify names of imported commands. /// - internal string Prefix { set; get; } = string.Empty; + internal string Prefix { get; set; } = string.Empty; /// /// Gets or sets the certificate with which to sign the format file and psm1 file. @@ -559,11 +559,11 @@ internal ErrorDetails GetErrorDetails(string errorId, params object[] args) private ErrorRecord GetErrorNoCommandsImportedBecauseOfSkipping() { - string errorId = "ErrorNoCommandsImportedBecauseOfSkipping"; + const string errorId = "ErrorNoCommandsImportedBecauseOfSkipping"; ErrorDetails details = this.GetErrorDetails(errorId); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(details.Message), errorId, ErrorCategory.InvalidResult, @@ -580,11 +580,11 @@ private ErrorRecord GetErrorMalformedDataFromRemoteCommand(string commandName) throw PSTraceSource.NewArgumentNullException(nameof(commandName)); } - string errorId = "ErrorMalformedDataFromRemoteCommand"; + const string errorId = "ErrorMalformedDataFromRemoteCommand"; ErrorDetails details = this.GetErrorDetails(errorId, commandName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(details.Message), errorId, ErrorCategory.InvalidResult, @@ -601,11 +601,11 @@ private ErrorRecord GetErrorCommandSkippedBecauseOfShadowing(string commandNames throw PSTraceSource.NewArgumentNullException(nameof(commandNames)); } - string errorId = "ErrorCommandSkippedBecauseOfShadowing"; + const string errorId = "ErrorCommandSkippedBecauseOfShadowing"; ErrorDetails details = this.GetErrorDetails(errorId, commandNames); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.InvalidData, @@ -622,11 +622,11 @@ private ErrorRecord GetErrorSkippedNonRequestedCommand(string commandName) throw PSTraceSource.NewArgumentNullException(nameof(commandName)); } - string errorId = "ErrorSkippedNonRequestedCommand"; + const string errorId = "ErrorSkippedNonRequestedCommand"; ErrorDetails details = this.GetErrorDetails(errorId, commandName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.ResourceExists, @@ -643,11 +643,11 @@ private ErrorRecord GetErrorSkippedNonRequestedTypeDefinition(string typeName) throw PSTraceSource.NewArgumentNullException(nameof(typeName)); } - string errorId = "ErrorSkippedNonRequestedTypeDefinition"; + const string errorId = "ErrorSkippedNonRequestedTypeDefinition"; ErrorDetails details = this.GetErrorDetails(errorId, typeName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.ResourceExists, @@ -664,11 +664,11 @@ private ErrorRecord GetErrorSkippedUnsafeCommandName(string commandName) throw PSTraceSource.NewArgumentNullException(nameof(commandName)); } - string errorId = "ErrorSkippedUnsafeCommandName"; + const string errorId = "ErrorSkippedUnsafeCommandName"; ErrorDetails details = this.GetErrorDetails(errorId, commandName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.InvalidData, @@ -700,7 +700,7 @@ private ErrorRecord GetErrorSkippedUnsafeNameInMetadata(string commandName, stri ErrorDetails details = this.GetErrorDetails(errorId, commandName, name); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.InvalidData, @@ -771,11 +771,11 @@ private ErrorRecord GetErrorCouldntResolvedAlias(string aliasName) throw PSTraceSource.NewArgumentNullException(nameof(aliasName)); } - string errorId = "ErrorCouldntResolveAlias"; + const string errorId = "ErrorCouldntResolveAlias"; ErrorDetails details = this.GetErrorDetails(errorId, aliasName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(details.Message), errorId, ErrorCategory.OperationTimeout, @@ -792,11 +792,11 @@ private ErrorRecord GetErrorNoResultsFromRemoteEnd(string commandName) throw PSTraceSource.NewArgumentNullException(nameof(commandName)); } - string errorId = "ErrorNoResultsFromRemoteEnd"; + const string errorId = "ErrorNoResultsFromRemoteEnd"; ErrorDetails details = this.GetErrorDetails(errorId, commandName); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(details.Message), errorId, ErrorCategory.InvalidResult, @@ -806,7 +806,7 @@ private ErrorRecord GetErrorNoResultsFromRemoteEnd(string commandName) return errorRecord; } - private List _commandsSkippedBecauseOfShadowing = new List(); + private readonly List _commandsSkippedBecauseOfShadowing = new(); private void ReportSkippedCommands() { @@ -847,7 +847,7 @@ private Dictionary ExistingCommands if (_existingCommands == null) { _existingCommands = new Dictionary(StringComparer.OrdinalIgnoreCase); - CommandSearcher searcher = new CommandSearcher( + CommandSearcher searcher = new( "*", SearchResolutionOptions.CommandNameIsPattern | SearchResolutionOptions.ResolveAliasPatterns | SearchResolutionOptions.ResolveFunctionPatterns, CommandTypes.All, @@ -866,7 +866,7 @@ private bool IsShadowingExistingCommands(string commandName) { commandName = ModuleCmdletBase.AddPrefixToCommandName(commandName, this.Prefix); - CommandSearcher searcher = new CommandSearcher(commandName, SearchResolutionOptions.None, CommandTypes.All, this.Context); + CommandSearcher searcher = new(commandName, SearchResolutionOptions.None, CommandTypes.All, this.Context); foreach (string expandedCommandName in searcher.ConstructSearchPatternsFromName(commandName)) { if (this.ExistingCommands.ContainsKey(expandedCommandName)) @@ -1046,7 +1046,7 @@ private List RehydrateList(string commandName, object deserializedList, Fu { if (itemRehydrator == null) { - itemRehydrator = delegate (PSObject pso) { return ConvertTo(commandName, pso); }; + itemRehydrator = (PSObject pso) => ConvertTo(commandName, pso); } List result = null; @@ -1066,17 +1066,21 @@ private List RehydrateList(string commandName, object deserializedList, Fu return result; } - private Dictionary RehydrateDictionary(string commandName, PSObject deserializedObject, string propertyName, Func valueRehydrator) + private Dictionary RehydrateDictionary( + string commandName, + PSObject deserializedObject, + string propertyName, + Func valueRehydrator) { Dbg.Assert(deserializedObject != null, "deserializedObject parameter != null"); Dbg.Assert(!string.IsNullOrEmpty(propertyName), "propertyName parameter != null"); if (valueRehydrator == null) { - valueRehydrator = delegate (PSObject pso) { return ConvertTo(commandName, pso); }; + valueRehydrator = (PSObject pso) => ConvertTo(commandName, pso); } - Dictionary result = new Dictionary(); + Dictionary result = new(); PSPropertyInfo deserializedDictionaryProperty = deserializedObject.Properties[propertyName]; if (deserializedDictionaryProperty != null) { @@ -1085,10 +1089,10 @@ private Dictionary RehydrateDictionary(string commandName, PSObject { foreach (DictionaryEntry deserializedItem in deserializedDictionary) { - K itemKey = ConvertTo(commandName, deserializedItem.Key); + TKey itemKey = ConvertTo(commandName, deserializedItem.Key); PSObject deserializedItemValue = ConvertTo(commandName, deserializedItem.Value); - V itemValue = valueRehydrator(deserializedItemValue); + TValue itemValue = valueRehydrator(deserializedItemValue); result.Add(itemKey, itemValue); } @@ -1107,7 +1111,7 @@ private Dictionary RehydrateDictionary(string commandName, PSObject /// (i.e. it can't be used for code injection attacks). /// /// Name to validate. - /// true if the name is safe; false otherwise. + /// if the name is safe; otherwise. private static bool IsSafeNameOrIdentifier(string name) { // '.' is needed for stuff like net.exe @@ -1125,10 +1129,10 @@ private static bool IsSafeNameOrIdentifier(string name) /// (i.e. it can't be used for code injection attacks). /// /// Parameter name to validate. - /// true if the name is safe; false otherwise. + /// if the name is safe; otherwise. private static bool IsSafeParameterName(string parameterName) { - return IsSafeNameOrIdentifier(parameterName) && !parameterName.Contains(":"); + return IsSafeNameOrIdentifier(parameterName) && !parameterName.Contains(':'); } /// @@ -1136,7 +1140,7 @@ private static bool IsSafeParameterName(string parameterName) /// (i.e. it doesn't introduce any side effects on the client). /// /// Type to validate. - /// true if the type is safe; false otherwise. + /// if the type is safe; otherwise. private static bool IsSafeTypeConstraint(Type type) { if (type == null) @@ -1179,7 +1183,7 @@ private static bool IsSafeTypeConstraint(Type type) /// Writes error messages if necessary. Modifies command metadata to make it safe if necessary. /// /// Command metadata to verify. - /// true if the command metadata is safe; false otherwise. + /// if the command metadata is safe; otherwise. private bool IsSafeCommandMetadata(CommandMetadata commandMetadata) { if (!IsCommandNameMatchingParameters(commandMetadata.Name)) @@ -1205,7 +1209,7 @@ private bool IsSafeCommandMetadata(CommandMetadata commandMetadata) } Dbg.Assert(commandMetadata.CommandType == null, "CommandType shouldn't get rehydrated"); - Dbg.Assert(commandMetadata.ImplementsDynamicParameters == false, "Proxies shouldn't do dynamic parameters"); + Dbg.Assert(!commandMetadata.ImplementsDynamicParameters, "Proxies shouldn't do dynamic parameters"); if (commandMetadata.Parameters != null) { @@ -1294,8 +1298,8 @@ private ParameterMetadata RehydrateParameterMetadata(PSObject deserializedParame Type parameterType = RehydrateParameterType(deserializedParameterMetadata); List aliases = RehydrateList("Get-Command", deserializedParameterMetadata, "Aliases", null); - ParameterSetMetadata parameterSetMetadata = new ParameterSetMetadata(int.MinValue, 0, null); - Dictionary parameterSets = new Dictionary(StringComparer.OrdinalIgnoreCase); + ParameterSetMetadata parameterSetMetadata = new(int.MinValue, 0, null); + Dictionary parameterSets = new(StringComparer.OrdinalIgnoreCase); parameterSets.Add(ParameterAttribute.AllParameterSets, parameterSetMetadata); return new ParameterMetadata( @@ -1306,7 +1310,7 @@ private ParameterMetadata RehydrateParameterMetadata(PSObject deserializedParame parameterType); } - private bool IsProxyForCmdlet(Dictionary parameters) + private static bool IsProxyForCmdlet(Dictionary parameters) { // we are not sending CmdletBinding/DefaultParameterSet over the wire anymore // we need to infer IsProxyForCmdlet from presence of all common parameters @@ -1349,13 +1353,13 @@ private CommandMetadata RehydrateCommandMetadata(PSObject deserializedCommandInf // add client-side AsJob parameter parameters.Remove("AsJob"); - ParameterMetadata asJobParameter = new ParameterMetadata("AsJob", typeof(SwitchParameter)); + ParameterMetadata asJobParameter = new("AsJob", typeof(SwitchParameter)); parameters.Add(asJobParameter.Name, asJobParameter); return new CommandMetadata( name: name, commandType: commandType, - isProxyForCmdlet: this.IsProxyForCmdlet(parameters), + isProxyForCmdlet: IsProxyForCmdlet(parameters), defaultParameterSetName: ParameterAttribute.AllParameterSets, supportsShouldProcess: false, confirmImpact: ConfirmImpact.None, @@ -1365,7 +1369,7 @@ private CommandMetadata RehydrateCommandMetadata(PSObject deserializedCommandInf parameters: parameters); } - private int GetCommandTypePriority(CommandTypes commandType) + private static int GetCommandTypePriority(CommandTypes commandType) { switch (commandType) { @@ -1434,8 +1438,8 @@ private void AddRemoteCommandMetadata( CommandMetadata previousCommandWithSameName; if (name2commandMetadata.TryGetValue(commandMetadata.Name, out previousCommandWithSameName)) { - int previousCommandPriority = this.GetCommandTypePriority(previousCommandWithSameName.WrappedCommandType); - int currentCommandPriority = this.GetCommandTypePriority(commandMetadata.WrappedCommandType); + int previousCommandPriority = GetCommandTypePriority(previousCommandWithSameName.WrappedCommandType); + int currentCommandPriority = GetCommandTypePriority(commandMetadata.WrappedCommandType); if (previousCommandPriority < currentCommandPriority) { return; @@ -1622,12 +1626,12 @@ internal List GetRemoteFormatData() { DateTime startTime = DateTime.UtcNow; - PSDataCollection asyncOutput = new PSDataCollection(); + PSDataCollection asyncOutput = new(); // process output and errors as soon as possible asyncResult = powerShell.BeginInvoke(null, asyncOutput); int numberOfReceivedObjects = 0; - List result = new List(); + List result = new(); foreach (PSObject deserializedFormatData in asyncOutput) { AddRemoteTypeDefinition(result, deserializedFormatData); @@ -1733,14 +1737,14 @@ internal List GetRemoteCommandMetadata(out Dictionary name2commandMetadata = - new Dictionary(StringComparer.OrdinalIgnoreCase); + new(StringComparer.OrdinalIgnoreCase); // invoke using (new PowerShellStopper(this.Context, powerShell)) { DateTime startTime = DateTime.UtcNow; - PSDataCollection asyncOutput = new PSDataCollection(); + PSDataCollection asyncOutput = new(); // process output and errors as soon as possible asyncResult = powerShell.BeginInvoke(null, asyncOutput); @@ -1815,7 +1819,7 @@ private void WriteProgress(string statusDescription, int? percentComplete, int? _lastTimeProgressWasWritten = DateTime.UtcNow; string activityDescription = StringUtil.Format(ImplicitRemotingStrings.ProgressActivity); - ProgressRecord progressRecord = new ProgressRecord( + ProgressRecord progressRecord = new( 1905347799, // unique id for ImplicitRemoting (I just picked a random number) activityDescription, statusDescription); @@ -1890,7 +1894,7 @@ internal List GenerateProxyModule( } } - ImplicitRemotingCodeGenerator codeGenerator = new ImplicitRemotingCodeGenerator( + ImplicitRemotingCodeGenerator codeGenerator = new( this.Session, this.ModuleGuid, this.MyInvocation); @@ -1915,13 +1919,13 @@ internal List GenerateProxyModule( internal class ImplicitRemotingCodeGenerator { - internal static readonly Version VersionOfScriptWriter = new Version(1, 0); + internal static readonly Version VersionOfScriptWriter = new(1, 0); #region Constructor and shared private data - private PSSession _remoteRunspaceInfo; - private Guid _moduleGuid; - private InvocationInfo _invocationInfo; + private readonly PSSession _remoteRunspaceInfo; + private readonly Guid _moduleGuid; + private readonly InvocationInfo _invocationInfo; internal ImplicitRemotingCodeGenerator( PSSession remoteRunspaceInfo, @@ -1975,19 +1979,19 @@ private string GetConnectionString() return null; } - private string EscapeFunctionNameForRemoteHelp(string name) + private static string EscapeFunctionNameForRemoteHelp(string name) { if (name == null) { throw PSTraceSource.NewArgumentNullException(nameof(name)); } - StringBuilder result = new StringBuilder(name.Length); + StringBuilder result = new(name.Length); foreach (char c in name) { - if (("\"'`$".IndexOf(c) == (-1)) && - (!char.IsControl(c)) && - (!char.IsWhiteSpace(c))) + if (!"\"'`$".Contains(c) + && !char.IsControl(c) + && !char.IsWhiteSpace(c)) { result.Append(c); } @@ -2000,7 +2004,7 @@ private string EscapeFunctionNameForRemoteHelp(string name) ############################################################################## "; - private void GenerateSectionSeparator(TextWriter writer) + private static void GenerateSectionSeparator(TextWriter writer) { writer.Write(SectionSeparator); } @@ -2020,7 +2024,6 @@ private void GenerateSectionSeparator(TextWriter writer) PrivateData = @{{ ImplicitRemoting = $true - ImplicitSessionId = '{4}' }} }} "; @@ -2039,8 +2042,7 @@ private void GenerateManifest(TextWriter writer, string psm1fileName, string for CodeGeneration.EscapeSingleQuotedStringContent(_moduleGuid.ToString()), CodeGeneration.EscapeSingleQuotedStringContent(StringUtil.Format(ImplicitRemotingStrings.ProxyModuleDescription, this.GetConnectionString())), CodeGeneration.EscapeSingleQuotedStringContent(Path.GetFileName(psm1fileName)), - CodeGeneration.EscapeSingleQuotedStringContent(Path.GetFileName(formatPs1xmlFileName)), - _remoteRunspaceInfo.InstanceId); + CodeGeneration.EscapeSingleQuotedStringContent(Path.GetFileName(formatPs1xmlFileName))); } #endregion @@ -2135,7 +2137,7 @@ function Write-PSImplicitRemotingMessage } "; - private void GenerateHelperFunctionsWriteMessage(TextWriter writer) + private static void GenerateHelperFunctionsWriteMessage(TextWriter writer) { if (writer == null) { @@ -2190,7 +2192,7 @@ function Set-PSImplicitRemotingSession if ($PSSessionOverride) {{ Set-PSImplicitRemotingSession $PSSessionOverride }} "; - private void GenerateHelperFunctionsSetImplicitRunspace(TextWriter writer) + private static void GenerateHelperFunctionsSetImplicitRunspace(TextWriter writer) { if (writer == null) { @@ -2247,7 +2249,7 @@ private PSPrimitiveDictionary GetApplicationArguments() private string GenerateNewPSSessionOption() { - StringBuilder result = new StringBuilder("& $script:NewPSSessionOption "); + StringBuilder result = new("& $script:NewPSSessionOption "); RunspaceConnectionInfo runspaceConnectionInfo = _remoteRunspaceInfo.Runspace.ConnectionInfo as RunspaceConnectionInfo; if (runspaceConnectionInfo != null) @@ -2316,7 +2318,7 @@ private string GenerateNewPSSessionOption() result.Append("-ApplicationArguments $("); result.Append("& $script:ImportCliXml -Path $("); result.Append("& $script:JoinPath -Path $PSScriptRoot -ChildPath ApplicationArguments.xml"); - result.Append(")"); + result.Append(')'); result.Append(") "); } @@ -2430,7 +2432,7 @@ private void GenerateHelperFunctionsGetImplicitRunspace(TextWriter writer) out hashString, ImplicitRemotingCommandBase.ImplicitRemotingKey, ImplicitRemotingCommandBase.ImplicitRemotingHashKey); - hashString = hashString ?? string.Empty; + hashString ??= string.Empty; writer.Write( HelperFunctionsGetImplicitRunspaceTemplate, @@ -2455,7 +2457,7 @@ private void GenerateHelperFunctionsGetImplicitRunspace(TextWriter writer) private string GenerateReimportingOfModules() { - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); if (_invocationInfo.BoundParameters.ContainsKey(nameof(Module))) { @@ -2623,8 +2625,7 @@ private string GenerateConnectionStringForNewRunspace() private string GenerateAllowRedirectionParameter() { - WSManConnectionInfo wsmanConnectionInfo = _remoteRunspaceInfo.Runspace.ConnectionInfo as WSManConnectionInfo; - if (wsmanConnectionInfo == null) + if (!(_remoteRunspaceInfo.Runspace.ConnectionInfo is WSManConnectionInfo wsmanConnectionInfo)) { return string.Empty; } @@ -2650,8 +2651,7 @@ private string GenerateAuthenticationMechanismParameter() return string.Empty; } - WSManConnectionInfo wsmanConnectionInfo = _remoteRunspaceInfo.Runspace.ConnectionInfo as WSManConnectionInfo; - if (wsmanConnectionInfo == null) + if (!(_remoteRunspaceInfo.Runspace.ConnectionInfo is WSManConnectionInfo wsmanConnectionInfo)) { return string.Empty; } @@ -2769,7 +2769,7 @@ function Get-PSImplicitRemotingClientSideParameters } "; - private void GenerateHelperFunctionsClientSideParameters(TextWriter writer) + private static void GenerateHelperFunctionsClientSideParameters(TextWriter writer) { if (writer == null) { @@ -2783,12 +2783,12 @@ private void GenerateHelperFunctionsClientSideParameters(TextWriter writer) private void GenerateHelperFunctions(TextWriter writer) { - this.GenerateSectionSeparator(writer); - this.GenerateHelperFunctionsWriteMessage(writer); + GenerateSectionSeparator(writer); + GenerateHelperFunctionsWriteMessage(writer); this.GenerateHelperFunctionsGetSessionOption(writer); - this.GenerateHelperFunctionsSetImplicitRunspace(writer); + GenerateHelperFunctionsSetImplicitRunspace(writer); this.GenerateHelperFunctionsGetImplicitRunspace(writer); - this.GenerateHelperFunctionsClientSideParameters(writer); + GenerateHelperFunctionsClientSideParameters(writer); } #endregion @@ -2848,7 +2848,7 @@ private void GenerateHelperFunctions(TextWriter writer) }} "; - private void GenerateCommandProxy(TextWriter writer, CommandMetadata commandMetadata) + private static void GenerateCommandProxy(TextWriter writer, CommandMetadata commandMetadata) { if (writer == null) { @@ -2856,7 +2856,7 @@ private void GenerateCommandProxy(TextWriter writer, CommandMetadata commandMeta } string functionNameForString = CodeGeneration.EscapeSingleQuotedStringContent(commandMetadata.Name); - string functionNameForHelp = this.EscapeFunctionNameForRemoteHelp(commandMetadata.Name); + string functionNameForHelp = EscapeFunctionNameForRemoteHelp(commandMetadata.Name); writer.Write( CommandProxyTemplate, /* 0 */ functionNameForString, @@ -2870,7 +2870,7 @@ private void GenerateCommandProxy(TextWriter writer, CommandMetadata commandMeta /* 8 */ commandMetadata.WrappedAnyCmdlet); } - private void GenerateCommandProxy(TextWriter writer, IEnumerable listOfCommandMetadata) + private static void GenerateCommandProxy(TextWriter writer, IEnumerable listOfCommandMetadata) { if (writer == null) { @@ -2882,7 +2882,7 @@ private void GenerateCommandProxy(TextWriter writer, IEnumerable listOfCommandMetadata) + private static void GenerateExportDeclaration(TextWriter writer, IEnumerable listOfCommandMetadata) { if (writer == null) { @@ -2909,21 +2909,21 @@ private void GenerateExportDeclaration(TextWriter writer, IEnumerable listOfCommandNames = GetListOfCommandNames(listOfCommandMetadata); string exportString = GenerateArrayString(listOfCommandNames); writer.Write(ExportFunctionsTemplate, exportString); } - private List GetListOfCommandNames(IEnumerable listOfCommandMetadata) + private static List GetListOfCommandNames(IEnumerable listOfCommandMetadata) { if (listOfCommandMetadata == null) { throw PSTraceSource.NewArgumentNullException(nameof(listOfCommandMetadata)); } - List listOfCommandNames = new List(); + List listOfCommandNames = new(); foreach (CommandMetadata commandMetadata in listOfCommandMetadata) { listOfCommandNames.Add(commandMetadata.Name); @@ -2932,14 +2932,14 @@ private List GetListOfCommandNames(IEnumerable listOfCo return listOfCommandNames; } - private string GenerateArrayString(IEnumerable listOfStrings) + private static string GenerateArrayString(IEnumerable listOfStrings) { if (listOfStrings == null) { throw PSTraceSource.NewArgumentNullException(nameof(listOfStrings)); } - StringBuilder arrayString = new StringBuilder(); + StringBuilder arrayString = new(); foreach (string s in listOfStrings) { if (arrayString.Length != 0) @@ -2953,7 +2953,7 @@ private string GenerateArrayString(IEnumerable listOfStrings) } arrayString.Insert(0, "@("); - arrayString.Append(")"); + arrayString.Append(')'); return arrayString.ToString(); } @@ -2970,9 +2970,9 @@ private string GenerateArrayString(IEnumerable listOfStrings) & $script:ExportModuleMember -Alias {0} "; - private void GenerateAliases(TextWriter writer, Dictionary alias2resolvedCommandName) + private static void GenerateAliases(TextWriter writer, Dictionary alias2resolvedCommandName) { - this.GenerateSectionSeparator(writer); + GenerateSectionSeparator(writer); foreach (KeyValuePair pair in alias2resolvedCommandName) { @@ -2993,7 +2993,7 @@ private void GenerateAliases(TextWriter writer, Dictionary alias #region Generating format.ps1xml file - private void GenerateFormatFile(TextWriter writer, List listOfFormatData) + private static void GenerateFormatFile(TextWriter writer, List listOfFormatData) { if (writer == null) { @@ -3005,7 +3005,7 @@ private void GenerateFormatFile(TextWriter writer, List throw PSTraceSource.NewArgumentNullException(nameof(listOfFormatData)); } - XmlWriterSettings settings = new XmlWriterSettings(); + XmlWriterSettings settings = new(); settings.CloseOutput = false; settings.ConformanceLevel = ConformanceLevel.Document; settings.Encoding = writer.Encoding; @@ -3040,7 +3040,7 @@ internal List GenerateProxyModule( List listOfFormatData, X509Certificate2 certificate) { - List result = new List(); + List result = new(); Dbg.Assert(moduleRootDirectory != null, "Caller should validate moduleRootDirectory != null"); Dbg.Assert(Directory.Exists(moduleRootDirectory.FullName), "Caller should validate moduleRootDirectory exists"); @@ -3050,7 +3050,7 @@ internal List GenerateProxyModule( FileMode fileMode = force ? FileMode.OpenOrCreate : FileMode.CreateNew; result.Add(baseName + ".psm1"); - FileStream psm1 = new FileStream( + FileStream psm1 = new( baseName + ".psm1", fileMode, FileAccess.Write, @@ -3071,7 +3071,7 @@ internal List GenerateProxyModule( } result.Add(baseName + ".format.ps1xml"); - FileStream formatPs1xml = new FileStream( + FileStream formatPs1xml = new( baseName + ".format.ps1xml", fileMode, FileAccess.Write, @@ -3116,8 +3116,8 @@ internal List GenerateProxyModule( } result.Add(baseName + ".psd1"); - FileInfo manifestFile = new FileInfo(baseName + ".psd1"); - FileStream psd1 = new FileStream( + FileInfo manifestFile = new(baseName + ".psd1"); + FileStream psd1 = new( manifestFile.FullName, fileMode, FileAccess.Write, @@ -3137,7 +3137,7 @@ internal List GenerateProxyModule( using (var stream = new FileStream(applicationArgumentsFile, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var xmlWriter = XmlWriter.Create(stream)) { - Serializer serializer = new Serializer(xmlWriter); + Serializer serializer = new(xmlWriter); serializer.Serialize(applicationArguments); serializer.Done(); } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Import-LocalizedData.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Import-LocalizedData.cs index 4749d28322c..53ab8d32c2f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Import-LocalizedData.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Import-LocalizedData.cs @@ -186,7 +186,7 @@ protected override void ProcessRecord() if (_bindingVariable != null) { - VariablePath variablePath = new VariablePath(_bindingVariable); + VariablePath variablePath = new(_bindingVariable); if (variablePath.IsUnscopedVariable) { variablePath = variablePath.CloneAndSetLocal(); @@ -340,8 +340,8 @@ private string GetScript(string filePath) // 197751: WR BUG BASH: Powershell: localized text display as garbage // leaving the encoding to be decided by the StreamReader. StreamReader // will read the preamble and decide proper encoding. - using (FileStream scriptStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) - using (StreamReader scriptReader = new StreamReader(scriptStream)) + using (FileStream scriptStream = new(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + using (StreamReader scriptReader = new(scriptStream)) { return scriptReader.ReadToEnd(); } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportAliasCommand.cs index 3da62e88d25..9a647d4c72b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportAliasCommand.cs @@ -154,7 +154,7 @@ protected override void ProcessRecord() // Since the alias already exists, write an error. SessionStateException aliasExists = - new SessionStateException( + new( alias.Name, SessionStateCategory.Alias, "AliasAlreadyExists", @@ -233,7 +233,7 @@ private Dictionary ExistingCommands if (_existingCommands == null) { _existingCommands = new Dictionary(StringComparer.OrdinalIgnoreCase); - CommandSearcher searcher = new CommandSearcher( + CommandSearcher searcher = new( "*", SearchResolutionOptions.CommandNameIsPattern | SearchResolutionOptions.ResolveAliasPatterns | SearchResolutionOptions.ResolveFunctionPatterns, CommandTypes.All ^ CommandTypes.Alias, @@ -260,7 +260,7 @@ private Dictionary ExistingCommands private bool VerifyShadowingExistingCommandsAndWriteError(string aliasName) { - CommandSearcher searcher = new CommandSearcher(aliasName, SearchResolutionOptions.None, CommandTypes.All ^ CommandTypes.Alias, this.Context); + CommandSearcher searcher = new(aliasName, SearchResolutionOptions.None, CommandTypes.All ^ CommandTypes.Alias, this.Context); foreach (string expandedCommandName in searcher.ConstructSearchPatternsFromName(aliasName)) { CommandTypes commandTypeOfExistingCommand; @@ -268,7 +268,7 @@ private bool VerifyShadowingExistingCommandsAndWriteError(string aliasName) { // Since the alias already exists, write an error. SessionStateException aliasExists = - new SessionStateException( + new( aliasName, SessionStateCategory.Alias, "AliasAlreadyExists", @@ -289,14 +289,14 @@ private bool VerifyShadowingExistingCommandsAndWriteError(string aliasName) private Collection GetAliasesFromFile(bool isLiteralPath) { - Collection result = new Collection(); + Collection result = new(); string filePath = null; using (StreamReader reader = OpenFile(out filePath, isLiteralPath)) { - CSVHelper csvHelper = new CSVHelper(','); + CSVHelper csvHelper = new(','); - Int64 lineNumber = 0; + long lineNumber = 0; string line = null; while ((line = reader.ReadLine()) != null) { @@ -327,10 +327,10 @@ private Collection GetAliasesFromFile(bool isLiteralPath) string message = StringUtil.Format(AliasCommandStrings.ImportAliasFileInvalidFormat, filePath, lineNumber); FormatException formatException = - new FormatException(message); + new(message); ErrorRecord errorRecord = - new ErrorRecord( + new( formatException, "ImportAliasFileFormatError", ErrorCategory.ReadError, @@ -352,7 +352,7 @@ private Collection GetAliasesFromFile(bool isLiteralPath) string message = StringUtil.Format(AliasCommandStrings.ImportAliasOptionsError, filePath, lineNumber); ErrorRecord errorRecord = - new ErrorRecord( + new( argException, "ImportAliasOptionsError", ErrorCategory.ReadError, @@ -364,7 +364,7 @@ private Collection GetAliasesFromFile(bool isLiteralPath) } AliasInfo newAlias = - new AliasInfo( + new( values[0], values[1], Context, @@ -427,7 +427,7 @@ private StreamReader OpenFile(out string filePath, bool isLiteralPath) try { - FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + FileStream file = new(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); result = new StreamReader(file); } catch (IOException ioException) @@ -451,7 +451,7 @@ private void ThrowFileOpenError(Exception e, string pathWithError) string message = StringUtil.Format(AliasCommandStrings.ImportAliasFileOpenFailed, pathWithError, e.Message); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( e, "FileOpenFailure", ErrorCategory.OpenError, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs index 694e82686be..5661df24fa9 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs @@ -39,6 +39,12 @@ public string[] LiteralPath set { _isLiteralPath = true; Path = value; } } + /// + /// Gets or sets switch that determines if built-in limits are applied to the data. + /// + [Parameter] + public SwitchParameter SkipLimitCheck { get; set; } + /// /// For each path, resolve it, parse it and write all hashtables to the output stream. /// @@ -58,10 +64,10 @@ protected override void ProcessRecord() } else { - var data = ast.Find(a => a is HashtableAst, false); + var data = ast.Find(static a => a is HashtableAst, false); if (data != null) { - WriteObject(data.SafeGetValue()); + WriteObject(data.SafeGetValue(SkipLimitCheck)); } else { @@ -78,8 +84,8 @@ protected override void ProcessRecord() private void WritePathNotFoundError(string path) { - var errorId = "PathNotFound"; - var errorCategory = ErrorCategory.InvalidArgument; + const string errorId = "PathNotFound"; + const ErrorCategory errorCategory = ErrorCategory.InvalidArgument; var errorMessage = string.Format(UtilityCommonStrings.PathDoesNotExist, path); var exception = new ArgumentException(errorMessage); var errorRecord = new ErrorRecord(exception, errorId, errorCategory, path); @@ -88,7 +94,7 @@ private void WritePathNotFoundError(string path) private void WriteInvalidDataFileError(string resolvedPath, string errorId) { - var errorCategory = ErrorCategory.InvalidData; + const ErrorCategory errorCategory = ErrorCategory.InvalidData; var errorMessage = string.Format(UtilityCommonStrings.CouldNotParseAsPowerShellDataFile, resolvedPath); var exception = new InvalidOperationException(errorMessage); var errorRecord = new ErrorRecord(exception, errorId, errorCategory, resolvedPath); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs index 652e32652ce..0aebabe94c7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Management.Automation; @@ -23,7 +24,7 @@ public sealed class JoinStringCommand : PSCmdlet /// A bigger default to not get re-allocations in common use cases. private const int DefaultOutputStringCapacity = 256; - private readonly StringBuilder _outputBuilder = new StringBuilder(DefaultOutputStringCapacity); + private readonly StringBuilder _outputBuilder = new(DefaultOutputStringCapacity); private CultureInfo _cultureInfo = CultureInfo.InvariantCulture; private string _separator; private char _quoteChar; @@ -93,7 +94,7 @@ public string Separator [Parameter(ValueFromPipeline = true)] public PSObject[] InputObject { get; set; } - /// + /// protected override void BeginProcessing() { _quoteChar = SingleQuote ? '\'' : DoubleQuote ? '"' : char.MinValue; @@ -104,7 +105,7 @@ protected override void BeginProcessing() } } - /// + /// protected override void ProcessRecord() { if (InputObject != null) @@ -151,7 +152,7 @@ protected override void ProcessRecord() } } - /// + /// protected override void EndProcessing() { _outputBuilder.Append(OutputSuffix); @@ -159,6 +160,10 @@ protected override void EndProcessing() } } + [SuppressMessage( + "Microsoft.Performance", + "CA1812:AvoidUninstantiatedInternalClasses", + Justification = "Class is instantiated through late-bound reflection")] internal class JoinItemCompleter : IArgumentCompleter { public IEnumerable CompleteArgument( @@ -177,7 +182,7 @@ public IEnumerable CompleteArgument( return null; } - private IEnumerable CompleteFormatString(string wordToComplete) + private static IEnumerable CompleteFormatString(string wordToComplete) { var res = new List(); void AddMatching(string completionText) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs index 0ee80712123..cd18f33c41d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs @@ -3,13 +3,9 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; using System.Management.Automation; using System.Management.Automation.Internal; using System.Management.Automation.Runspaces; -using System.Threading.Tasks; using Microsoft.PowerShell.MarkdownRender; @@ -159,7 +155,7 @@ protected override void EndProcessing() { var errorMessage = StringUtil.Format(ConvertMarkdownStrings.InvalidInputObjectType, baseObj.GetType()); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(errorMessage), "InvalidObject", ErrorCategory.InvalidArgument, @@ -271,7 +267,7 @@ protected override void EndProcessing() /// internal static class PSMarkdownOptionInfoCache { - private static ConcurrentDictionary markdownOptionInfoCache; + private static readonly ConcurrentDictionary markdownOptionInfoCache; private const string MarkdownOptionInfoVariableName = "PSMarkdownOptionInfo"; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs index 667f55e50cf..b6b8cc9bfb6 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs @@ -142,7 +142,7 @@ public string Filename return s_inputStream; } - return _filename ?? (_filename = System.IO.Path.GetFileName(_path)); + return _filename ??= System.IO.Path.GetFileName(_path); } } @@ -275,7 +275,7 @@ private string ToString(string directory, string line) } // Otherwise, render the full context. - List lines = new List(Context.DisplayPreContext.Length + Context.DisplayPostContext.Length + 1); + List lines = new(Context.DisplayPreContext.Length + Context.DisplayPostContext.Length + 1); int displayLineNumber = this.LineNumber - Context.DisplayPreContext.Length; foreach (string contextLine in Context.DisplayPreContext) @@ -366,7 +366,7 @@ private string FormatLine(string lineStr, int displayLineNumber, string displayP /// /// Gets or sets a list of all Regex matches on the matching line. /// - public Match[] Matches { get; set; } = new Match[] { }; + public Match[] Matches { get; set; } = Array.Empty(); /// /// Create a deep copy of this MatchInfo instance. @@ -410,7 +410,7 @@ public sealed class SelectStringCommand : PSCmdlet /// A generic circular buffer. /// /// The type of items that are buffered. - private class CircularBuffer : ICollection + private sealed class CircularBuffer : ICollection { // Ring of items private readonly T[] _items; @@ -425,7 +425,7 @@ private class CircularBuffer : ICollection /// Initializes a new instance of the class. /// /// The maximum capacity of the buffer. - /// If is negative. + /// If is negative. public CircularBuffer(int capacity) { if (capacity < 0) @@ -455,9 +455,9 @@ public CircularBuffer(int capacity) /// has been properly offset and wrapped. /// /// The index to wrap. - /// If is out of range. + /// If is out of range. /// - /// The actual index that + /// The actual index that /// maps to. /// private int WrapIndex(int zeroBasedIndex) @@ -627,7 +627,7 @@ private interface IContextTracker /// /// A state machine to track display context for each match. /// - private class DisplayContextTracker : IContextTracker + private sealed class DisplayContextTracker : IContextTracker { private enum ContextState { @@ -784,12 +784,12 @@ private void Reset() /// and other matching lines (since they will appear /// as their own match entries.). /// - private class LogicalContextTracker : IContextTracker + private sealed class LogicalContextTracker : IContextTracker { // A union: string | MatchInfo. Needed since // context lines could be either proper matches // or non-matching lines. - private class ContextEntry + private sealed class ContextEntry { public readonly string Line; public readonly MatchInfo Match; @@ -851,14 +851,14 @@ public LogicalContextTracker(int preContext, int postContext) public void TrackLine(string line) { - ContextEntry entry = new ContextEntry(line); + ContextEntry entry = new(line); _collectedContext.Add(entry); UpdateQueue(); } public void TrackMatch(MatchInfo match) { - ContextEntry entry = new ContextEntry(match); + ContextEntry entry = new(match); _collectedContext.Add(entry); UpdateQueue(); } @@ -989,7 +989,7 @@ private string[] CopyContext(int startIndex, int length) /// /// A class to track both logical and display contexts. /// - private class ContextTracker : IContextTracker + private sealed class ContextTracker : IContextTracker { private readonly IContextTracker _displayTracker; private readonly IContextTracker _logicalTracker; @@ -1058,7 +1058,7 @@ private void UpdateQueue() /// /// ContextTracker that does not work for the case when pre- and post context is 0. /// - private class NoContextTracker : IContextTracker + private sealed class NoContextTracker : IContextTracker { private readonly IList _matches = new List(1); @@ -1376,7 +1376,7 @@ public Encoding Encoding [Parameter] [ValidateNotNullOrEmpty] [ValidateCount(1, 2)] - [ValidateRange(0, Int32.MaxValue)] + [ValidateRange(0, int.MaxValue)] public new int[] Context { get => _context; @@ -1436,8 +1436,8 @@ protected override void BeginProcessing() { if (this.MyInvocation.BoundParameters.ContainsKey(nameof(Culture)) && !this.MyInvocation.BoundParameters.ContainsKey(nameof(SimpleMatch))) { - InvalidOperationException exception = new InvalidOperationException(MatchStringStrings.CannotSpecifyCultureWithoutSimpleMatch); - ErrorRecord errorRecord = new ErrorRecord(exception, "CannotSpecifyCultureWithoutSimpleMatch", ErrorCategory.InvalidData, null); + InvalidOperationException exception = new(MatchStringStrings.CannotSpecifyCultureWithoutSimpleMatch); + ErrorRecord errorRecord = new(exception, "CannotSpecifyCultureWithoutSimpleMatch", ErrorCategory.InvalidData, null); this.ThrowTerminatingError(errorRecord); } @@ -1471,7 +1471,7 @@ protected override void BeginProcessing() _globalContextTracker = GetContextTracker(); } - private readonly List _inputObjectFileList = new List(1) { string.Empty }; + private readonly List _inputObjectFileList = new(1) { string.Empty }; /// /// Process the input. @@ -1600,9 +1600,9 @@ private bool ProcessFile(string filename) return false; } - using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (FileStream fs = new(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - using (StreamReader sr = new StreamReader(fs, Encoding)) + using (StreamReader sr = new(fs, Encoding)) { string line; int lineNo = 0; @@ -1897,8 +1897,8 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI if (matchInfo.Context != null) { matchResult = matchInfo.Clone(); - matchResult.Context.DisplayPreContext = new string[] { }; - matchResult.Context.DisplayPostContext = new string[] { }; + matchResult.Context.DisplayPreContext = Array.Empty(); + matchResult.Context.DisplayPostContext = Array.Empty(); } else { @@ -1924,7 +1924,7 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI // Matches should be an empty list, rather than null, // in the cases of notMatch and simpleMatch. - matchResult.Matches = matches ?? new Match[] { }; + matchResult.Matches = matches ?? Array.Empty(); return true; } @@ -1940,7 +1940,7 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI /// The resolved (absolute) paths. private List ResolveFilePaths(string[] filePaths, bool isLiteralPath) { - List allPaths = new List(); + List allPaths = new(); foreach (string path in filePaths) { @@ -1983,7 +1983,7 @@ private static ErrorRecord BuildErrorRecord(string messageId, string arg0, strin private static ErrorRecord BuildErrorRecord(string messageId, object[] arguments, string errorId, Exception innerException) { string fmtedMsg = StringUtil.Format(messageId, arguments); - ArgumentException e = new ArgumentException(fmtedMsg, innerException); + ArgumentException e = new(fmtedMsg, innerException); return new ErrorRecord(e, errorId, ErrorCategory.InvalidArgument, null); } @@ -1996,7 +1996,7 @@ private void WarnFilterContext() /// /// Magic class that works around the limitations on ToString() for FileInfo. /// - private class FileinfoToStringAttribute : ArgumentTransformationAttribute + private sealed class FileinfoToStringAttribute : ArgumentTransformationAttribute { public override object Transform(EngineIntrinsics engineIntrinsics, object inputData) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs index 230f985c19e..e6a99c38cb0 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -8,8 +8,6 @@ using System.Management.Automation; using System.Management.Automation.Internal; -using Microsoft.PowerShell.Commands.Internal.Format; - namespace Microsoft.PowerShell.Commands { /// @@ -20,7 +18,7 @@ public abstract class MeasureInfo /// /// Property name. /// - public string Property { get; set; } = null; + public string Property { get; set; } } /// @@ -29,7 +27,7 @@ public abstract class MeasureInfo public sealed class GenericMeasureInfo : MeasureInfo { /// - /// Default ctor. + /// Initializes a new instance of the class. /// public GenericMeasureInfo() { @@ -79,6 +77,7 @@ public GenericMeasureInfo() public sealed class GenericObjectMeasureInfo : MeasureInfo { /// + /// Initializes a new instance of the class. /// Default ctor. /// public GenericObjectMeasureInfo() @@ -124,6 +123,7 @@ public GenericObjectMeasureInfo() public sealed class TextMeasureInfo : MeasureInfo { /// + /// Initializes a new instance of the class. /// Default ctor. /// public TextMeasureInfo() @@ -159,11 +159,12 @@ public sealed class MeasureObjectCommand : PSCmdlet /// Dictionary to be used by Measure-Object implementation. /// Keys are strings. Keys are compared with OrdinalIgnoreCase. /// - /// Value type. - private class MeasureObjectDictionary : Dictionary - where V : new() + /// Value type. + private sealed class MeasureObjectDictionary : Dictionary + where TValue : new() { /// + /// Initializes a new instance of the class. /// Default ctor. /// internal MeasureObjectDictionary() : base(StringComparer.OrdinalIgnoreCase) @@ -180,12 +181,12 @@ internal MeasureObjectDictionary() : base(StringComparer.OrdinalIgnoreCase) /// /// The existing value, or a newly-created value. /// - public V EnsureEntry(string key) + public TValue EnsureEntry(string key) { - V val; + TValue val; if (!TryGetValue(key, out val)) { - val = new V(); + val = new TValue(); this[key] = val; } @@ -199,7 +200,7 @@ public V EnsureEntry(string key) /// what mode we're in. /// [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - private class Statistics + private sealed class Statistics { // Common properties internal int count = 0; @@ -218,6 +219,7 @@ private class Statistics } /// + /// Initializes a new instance of the class. /// Default constructor. /// public MeasureObjectCommand() @@ -234,7 +236,7 @@ public MeasureObjectCommand() /// /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// Properties to be examined. @@ -242,7 +244,7 @@ public MeasureObjectCommand() /// [ValidateNotNullOrEmpty] [Parameter(Position = 0)] - public PSPropertyExpression[] Property { get; set; } = null; + public PSPropertyExpression[] Property { get; set; } #endregion Common parameters in both sets @@ -494,14 +496,14 @@ protected override void ProcessRecord() /// Analyze an object on a property-by-property basis instead /// of as a simple value. /// Side effects: Updates statistics. - /// The object to analyze. /// + /// The object to analyze. private void AnalyzeObjectProperties(PSObject inObj) { // Keep track of which properties are counted for an // input object so that repeated properties won't be // counted twice. - MeasureObjectDictionary countedProperties = new MeasureObjectDictionary(); + MeasureObjectDictionary countedProperties = new(); // First iterate over the user-specified list of // properties... @@ -554,9 +556,9 @@ private void AnalyzeObjectProperties(PSObject inObj) /// /// Analyze a value for generic/text statistics. /// Side effects: Updates statistics. May set nonNumericError. + /// /// The property this value corresponds to. /// The value to analyze. - /// private void AnalyzeValue(string propertyName, object objValue) { if (propertyName == null) @@ -579,7 +581,7 @@ private void AnalyzeValue(string propertyName, object objValue) if (!LanguagePrimitives.TryConvertTo(objValue, out numValue)) { _nonNumericError = true; - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewInvalidOperationException(MeasureObjectStrings.NonNumericInputObject, objValue), "NonNumericInputObject", ErrorCategory.InvalidType, @@ -617,11 +619,10 @@ private void AnalyzeValue(string propertyName, object objValue) /// If true is passed in then the minimum of the two values would be returned. /// If false is passed in then maximum of the two values will be returned. /// - private object Compare(object objValue, object statMinOrMaxValue, bool isMin) + private static object Compare(object objValue, object statMinOrMaxValue, bool isMin) { object currentValue = objValue; object statValue = statMinOrMaxValue; - int factor = isMin ? 1 : -1; double temp; currentValue = ((objValue != null) && LanguagePrimitives.TryConvertTo(objValue, out temp)) ? temp : currentValue; @@ -633,13 +634,15 @@ private object Compare(object objValue, object statMinOrMaxValue, bool isMin) statValue = PSObject.AsPSObject(statValue).ToString(); } - if ((statValue == null) || - ((LanguagePrimitives.Compare(statValue, currentValue, false, CultureInfo.CurrentCulture) * factor) > 0)) + if (statValue == null) { return objValue; } - return statMinOrMaxValue; + int comparisonResult = LanguagePrimitives.Compare(statValue, currentValue, ignoreCase: false, CultureInfo.CurrentCulture); + return (isMin ? comparisonResult : -comparisonResult) > 0 + ? objValue + : statMinOrMaxValue; } /// @@ -744,9 +747,9 @@ internal static int CountLine(string inStr) /// /// Update text statistics. + /// /// The text to analyze. /// The Statistics object to update. - /// private void AnalyzeString(string strValue, Statistics stat) { if (_measureCharacters) @@ -759,9 +762,9 @@ private void AnalyzeString(string strValue, Statistics stat) /// /// Update number statistics. + /// /// The number to analyze. /// The Statistics object to update. - /// private void AnalyzeNumber(double numValue, Statistics stat) { if (_measureSum || _measureAverage || _measureStandardDeviation) @@ -788,7 +791,7 @@ private void AnalyzeNumber(double numValue, Statistics stat) private void WritePropertyNotFoundError(string propertyName, string errorId) { Diagnostics.Assert(Property != null, "no property and no InputObject should have been addressed"); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewArgumentException("Property"), errorId, ErrorCategory.InvalidArgument, @@ -850,10 +853,10 @@ protected override void EndProcessing() /// /// Create a MeasureInfo object for generic stats. - /// The statistics to use. - /// A new GenericMeasureInfo object. /// + /// The statistics to use. /// + /// A new GenericMeasureInfo object. private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGenericMeasureInfo) { double? sum = null; @@ -906,7 +909,7 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene if (shouldUseGenericMeasureInfo) { - GenericMeasureInfo gmi = new GenericMeasureInfo(); + GenericMeasureInfo gmi = new(); gmi.Count = stat.count; gmi.Sum = sum; gmi.Average = average; @@ -925,7 +928,7 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene } else { - GenericObjectMeasureInfo gomi = new GenericObjectMeasureInfo(); + GenericObjectMeasureInfo gomi = new(); gomi.Count = stat.count; gomi.Sum = sum; gomi.Average = average; @@ -938,12 +941,12 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene /// /// Create a MeasureInfo object for text stats. + /// /// The statistics to use. /// A new TextMeasureInfo object. - /// private TextMeasureInfo CreateTextMeasureInfo(Statistics stat) { - TextMeasureInfo tmi = new TextMeasureInfo(); + TextMeasureInfo tmi = new(); if (_measureCharacters) tmi.Characters = stat.characters; @@ -959,7 +962,7 @@ private TextMeasureInfo CreateTextMeasureInfo(Statistics stat) /// The observed statistics keyed by property name. /// If Property is not set, then the key used will be the value of thisObject. /// - private MeasureObjectDictionary _statistics = new MeasureObjectDictionary(); + private readonly MeasureObjectDictionary _statistics = new(); /// /// Whether or not a numeric conversion error occurred. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs index 39fd390b1ce..370f4574b5c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs @@ -13,7 +13,9 @@ using System.Management.Automation.Security; using System.Reflection; using System.Runtime.InteropServices; +#if !UNIX using System.Threading; +#endif using Dbg = System.Management.Automation.Diagnostics; @@ -30,7 +32,7 @@ public sealed class NewObjectCommand : PSCmdlet /// the number [Parameter(ParameterSetName = netSetName, Mandatory = true, Position = 0)] [ValidateTrustedData] - public string TypeName { get; set; } = null; + public string TypeName { get; set; } #if !UNIX private Guid _comObjectClsId = Guid.Empty; @@ -39,7 +41,7 @@ public sealed class NewObjectCommand : PSCmdlet /// [Parameter(ParameterSetName = "Com", Mandatory = true, Position = 0)] [ValidateTrustedData] - public string ComObject { get; set; } = null; + public string ComObject { get; set; } #endif /// @@ -49,7 +51,7 @@ public sealed class NewObjectCommand : PSCmdlet [Parameter(ParameterSetName = netSetName, Mandatory = false, Position = 1)] [ValidateTrustedData] [Alias("Args")] - public object[] ArgumentList { get; set; } = null; + public object[] ArgumentList { get; set; } /// /// True if we should have an error when Com objects will use an interop assembly. @@ -102,7 +104,7 @@ private void CreateMemberNotFoundError(PSObject pso, DictionaryEntry property, T private void CreateMemberSetValueError(SetValueException e) { - Exception ex = new Exception(StringUtil.Format(NewObjectStrings.InvalidValue, e)); + Exception ex = new(StringUtil.Format(NewObjectStrings.InvalidValue, e)); ThrowTerminatingError( new ErrorRecord(ex, "SetValueException", ErrorCategory.InvalidData, null)); } @@ -195,6 +197,25 @@ protected override void BeginProcessing() } } + switch (Context.LanguageMode) + { + case PSLanguageMode.NoLanguage: + case PSLanguageMode.RestrictedLanguage: + if (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce + && !CoreTypes.Contains(type)) + { + ThrowTerminatingError( + new ErrorRecord( + new PSNotSupportedException( + string.Format(NewObjectStrings.CannotCreateTypeLanguageMode, Context.LanguageMode.ToString())), + nameof(NewObjectStrings.CannotCreateTypeLanguageMode), + ErrorCategory.PermissionDenied, + targetObject: null)); + } + + break; + } + // WinRT does not support creating instances of attribute & delegate WinRT types. if (WinRTHelper.IsWinRTType(type) && ((typeof(System.Attribute)).IsAssignableFrom(type) || (typeof(System.Delegate)).IsAssignableFrom(type))) { @@ -207,7 +228,7 @@ protected override void BeginProcessing() ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes); if (ci != null && ci.IsPublic) { - _newObject = CallConstructor(type, new ConstructorInfo[] { ci }, new object[] { }); + _newObject = CallConstructor(type, new ConstructorInfo[] { ci }, Array.Empty()); if (_newObject != null && Property != null) { // The method invocation is disabled for "Hashtable to Object conversion" (Win8:649519), but we need to keep it enabled for New-Object for compatibility to PSv2 @@ -217,7 +238,7 @@ protected override void BeginProcessing() WriteObject(_newObject); return; } - else if (type.GetTypeInfo().IsValueType) + else if (type.IsValueType) { // This is for default parameterless struct ctor which is not returned by // Type.GetConstructor(System.Type.EmptyTypes). @@ -330,12 +351,12 @@ protected override void BeginProcessing() #if !UNIX #region Com - private object SafeCreateInstance(Type t, object[] args) + private object SafeCreateInstance(Type t) { object result = null; try { - result = Activator.CreateInstance(t, args); + result = Activator.CreateInstance(t); } // Does not catch InvalidComObjectException because ComObject is obtained from GetTypeFromProgID catch (ArgumentException e) @@ -395,7 +416,7 @@ private object SafeCreateInstance(Type t, object[] args) return result; } - private class ComCreateInfo + private sealed class ComCreateInfo { public object objectCreated; public bool success; @@ -409,13 +430,10 @@ private void STAComCreateThreadProc(object createstruct) ComCreateInfo info = (ComCreateInfo)createstruct; try { - Type type = null; - PSArgumentException mshArgE = null; - - type = Type.GetTypeFromCLSID(_comObjectClsId); + Type type = Type.GetTypeFromCLSID(_comObjectClsId); if (type == null) { - mshArgE = PSTraceSource.NewArgumentException( + PSArgumentException mshArgE = PSTraceSource.NewArgumentException( "ComObject", NewObjectStrings.CannotLoadComObjectType, ComObject); @@ -425,7 +443,7 @@ private void STAComCreateThreadProc(object createstruct) return; } - info.objectCreated = SafeCreateInstance(type, ArgumentList); + info.objectCreated = SafeCreateInstance(type); info.success = true; } catch (Exception e) @@ -437,20 +455,25 @@ private void STAComCreateThreadProc(object createstruct) private object CreateComObject() { - Type type = null; - PSArgumentException mshArgE = null; - try { - type = Marshal.GetTypeFromCLSID(_comObjectClsId); + Type type = Marshal.GetTypeFromCLSID(_comObjectClsId); if (type == null) { - mshArgE = PSTraceSource.NewArgumentException("ComObject", NewObjectStrings.CannotLoadComObjectType, ComObject); + PSArgumentException mshArgE = PSTraceSource.NewArgumentException( + "ComObject", + NewObjectStrings.CannotLoadComObjectType, + ComObject); + ThrowTerminatingError( - new ErrorRecord(mshArgE, "CannotLoadComObjectType", ErrorCategory.InvalidType, null)); + new ErrorRecord( + mshArgE, + "CannotLoadComObjectType", + ErrorCategory.InvalidType, + targetObject: null)); } - return SafeCreateInstance(type, ArgumentList); + return SafeCreateInstance(type); } catch (COMException e) { @@ -459,7 +482,7 @@ private object CreateComObject() { createInfo = new ComCreateInfo(); - Thread thread = new Thread(new ParameterizedThreadStart(STAComCreateThreadProc)); + Thread thread = new(new ParameterizedThreadStart(STAComCreateThreadProc)); thread.SetApartmentState(ApartmentState.STA); thread.Start(createInfo); @@ -498,12 +521,8 @@ private object CreateComObject() /// /// Native methods for dealing with COM objects. /// - internal class NewObjectNativeMethods + internal static class NewObjectNativeMethods { - private NewObjectNativeMethods() - { - } - /// Return Type: HRESULT->LONG->int [DllImport(PinvokeDllNames.CLSIDFromProgIDDllName)] internal static extern int CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] string lpszProgID, out Guid pclsid); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewAliasCommand.cs index 3c95ebbc7de..8ae43a6e4fd 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewAliasCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; using System.Management.Automation.Internal; @@ -44,7 +43,7 @@ protected override void ProcessRecord() // Since the alias already exists, write an error. SessionStateException aliasExists = - new SessionStateException( + new( Name, SessionStateCategory.Alias, "AliasAlreadyExists", @@ -62,7 +61,7 @@ protected override void ProcessRecord() // Create the alias info AliasInfo newAlias = - new AliasInfo( + new( Name, Value, Context, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTemporaryFileCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTemporaryFileCommand.cs index f8bb3d4e6ea..93b3eb209af 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTemporaryFileCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTemporaryFileCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.IO; using System.Management.Automation; @@ -41,7 +40,7 @@ protected override void EndProcessing() if (!string.IsNullOrEmpty(filePath)) { - FileInfo file = new FileInfo(filePath); + FileInfo file = new(filePath); WriteObject(file); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTimeSpanCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTimeSpanCommand.cs index 0e633ca5b2e..53c39250763 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTimeSpanCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/NewTimeSpanCommand.cs @@ -68,25 +68,25 @@ public DateTime End /// Allows the user to override the day. /// [Parameter(ParameterSetName = "Time")] - public int Days { get; set; } = 0; + public int Days { get; set; } /// /// Allows the user to override the hour. /// [Parameter(ParameterSetName = "Time")] - public int Hours { get; set; } = 0; + public int Hours { get; set; } /// /// Allows the user to override the minute. /// [Parameter(ParameterSetName = "Time")] - public int Minutes { get; set; } = 0; + public int Minutes { get; set; } /// /// Allows the user to override the second. /// [Parameter(ParameterSetName = "Time")] - public int Seconds { get; set; } = 0; + public int Seconds { get; set; } #endregion diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ObjectCommandComparer.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ObjectCommandComparer.cs index fd69a2011fb..39986943c99 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ObjectCommandComparer.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ObjectCommandComparer.cs @@ -30,7 +30,7 @@ internal ObjectCommandPropertyValue(object propVal) } /// - /// ObjectCommandPropertyValue constructor. + /// Initializes a new instance of the class. /// /// Property Value. /// Indicates if the Property value comparison has to be case sensitive or not. @@ -65,9 +65,9 @@ internal CultureInfo Culture } } - internal static readonly ObjectCommandPropertyValue NonExistingProperty = new ObjectCommandPropertyValue(); - internal static readonly ObjectCommandPropertyValue ExistingNullProperty = new ObjectCommandPropertyValue(null); - private bool _caseSensitive; + internal static readonly ObjectCommandPropertyValue NonExistingProperty = new(); + internal static readonly ObjectCommandPropertyValue ExistingNullProperty = new(null); + private readonly bool _caseSensitive; internal CultureInfo cultureInfo = null; /// @@ -77,8 +77,7 @@ internal CultureInfo Culture /// True if both the objects are same or else returns false. public override bool Equals(object inputObject) { - ObjectCommandPropertyValue objectCommandPropertyValueObject = inputObject as ObjectCommandPropertyValue; - if (objectCommandPropertyValueObject == null) + if (!(inputObject is ObjectCommandPropertyValue objectCommandPropertyValueObject)) { return false; } @@ -140,6 +139,7 @@ public override int GetHashCode() internal class ObjectCommandComparer : IComparer { /// + /// Initializes a new instance of the class. /// Constructor that doesn't set any private field. /// Necessary because compareTo can compare two objects by calling /// ((ICompare)obj1).CompareTo(obj2) without using a key. @@ -210,26 +210,26 @@ public int Compare(object first, object second) second = secondMsh.BaseObject; } - if (LanguagePrimitives.TryCompare(first, second, !_caseSensitive, _cultureInfo, out int result)) + if (!LanguagePrimitives.TryCompare(first, second, !_caseSensitive, _cultureInfo, out int result)) { - return result * (_ascendingOrder ? 1 : -1); - } + // Note that this will occur if the objects do not support + // IComparable. We fall back to comparing as strings. - // Note that this will occur if the objects do not support - // IComparable. We fall back to comparing as strings. + // being here means the first object doesn't support ICompare + string firstString = PSObject.AsPSObject(first).ToString(); + string secondString = PSObject.AsPSObject(second).ToString(); - // being here means the first object doesn't support ICompare - string firstString = PSObject.AsPSObject(first).ToString(); - string secondString = PSObject.AsPSObject(second).ToString(); + result = _cultureInfo.CompareInfo.Compare(firstString, secondString, _caseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase); + } - return _cultureInfo.CompareInfo.Compare(firstString, secondString, _caseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase) * (_ascendingOrder ? 1 : -1); + return _ascendingOrder ? result : -result; } - private CultureInfo _cultureInfo = null; + private readonly CultureInfo _cultureInfo = null; - private bool _ascendingOrder = true; + private readonly bool _ascendingOrder = true; - private bool _caseSensitive = false; + private readonly bool _caseSensitive = false; } #endregion } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/OrderObjectBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/OrderObjectBase.cs index c2ebc9261a1..40f06e58eca 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/OrderObjectBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/OrderObjectBase.cs @@ -57,7 +57,10 @@ public class ObjectCmdletBase : PSCmdlet [System.Diagnostics.CodeAnalysis.SuppressMessage("GoldMan", "#pw17903:UseOfLCID", Justification = "The CultureNumber is only used if the property has been set with a hex string starting with 0x")] public string Culture { - get { return _cultureInfo != null ? _cultureInfo.ToString() : null; } + get + { + return _cultureInfo?.ToString(); + } set { @@ -117,7 +120,7 @@ public abstract class ObjectBase : ObjectCmdletBase /// /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// Gets or Sets the Properties that would be used for Grouping, Sorting and Comparison. @@ -182,9 +185,9 @@ internal sealed class OrderByProperty /// /// A logical matrix where each row is an input object and its property values specified by Properties. /// - internal List OrderMatrix { get; } = null; + internal List OrderMatrix { get; } - internal OrderByPropertyComparer Comparer { get; } = null; + internal OrderByPropertyComparer Comparer { get; } internal List MshParameterList { @@ -211,7 +214,7 @@ private static void ProcessExpressionParameter( out List mshParameterList) { mshParameterList = null; - TerminatingErrorContext invocationContext = new TerminatingErrorContext(cmdlet); + TerminatingErrorContext invocationContext = new(cmdlet); // compare-object and group-object use the same definition here ParameterProcessor processor = cmdlet is SortObjectCommand ? new ParameterProcessor(new SortObjectExpressionParameterDefinition()) : @@ -235,7 +238,7 @@ internal void ProcessExpressionParameter( PSCmdlet cmdlet, object[] expr) { - TerminatingErrorContext invocationContext = new TerminatingErrorContext(cmdlet); + TerminatingErrorContext invocationContext = new(cmdlet); // compare-object and group-object use the same definition here ParameterProcessor processor = cmdlet is SortObjectCommand ? new ParameterProcessor(new SortObjectExpressionParameterDefinition()) : @@ -272,7 +275,7 @@ internal void ProcessExpressionParameter( // match property names on the incoming objects. private static List ExpandExpressions(List inputObjects, List unexpandedParameterList) { - List expandedParameterList = new List(); + List expandedParameterList = new(); if (unexpandedParameterList != null) { @@ -285,7 +288,7 @@ private static List ExpandExpressions(List inputObjects, } else { - SortedDictionary expandedPropertyNames = new SortedDictionary(StringComparer.OrdinalIgnoreCase); + SortedDictionary expandedPropertyNames = new(StringComparer.OrdinalIgnoreCase); if (inputObjects != null) { foreach (object inputObject in inputObjects) @@ -304,7 +307,7 @@ private static List ExpandExpressions(List inputObjects, foreach (PSPropertyExpression expandedExpression in expandedPropertyNames.Values) { - MshParameter expandedParameter = new MshParameter(); + MshParameter expandedParameter = new(); expandedParameter.hash = (Hashtable)unexpandedParameter.hash.Clone(); expandedParameter.hash[FormatParameterDefinitionKeys.ExpressionEntryKey] = expandedExpression; @@ -327,7 +330,7 @@ private static void ExpandExpressions(PSObject inputObject, List U { PSPropertyExpression ex = (PSPropertyExpression)unexpandedParameter.GetEntry(FormatParameterDefinitionKeys.ExpressionEntryKey); - SortedDictionary expandedPropertyNames = new SortedDictionary(StringComparer.OrdinalIgnoreCase); + SortedDictionary expandedPropertyNames = new(StringComparer.OrdinalIgnoreCase); if (inputObject == null) { continue; @@ -340,7 +343,7 @@ private static void ExpandExpressions(PSObject inputObject, List U foreach (PSPropertyExpression expandedExpression in expandedPropertyNames.Values) { - MshParameter expandedParameter = new MshParameter(); + MshParameter expandedParameter = new(); expandedParameter.hash = (Hashtable)unexpandedParameter.hash.Clone(); expandedParameter.hash[FormatParameterDefinitionKeys.ExpressionEntryKey] = expandedExpression; @@ -358,9 +361,7 @@ internal static string[] GetDefaultKeyPropertySet(PSObject mshObj) return null; } - PSPropertySet defaultKeys = standardNames.Members["DefaultKeyPropertySet"] as PSPropertySet; - - if (defaultKeys == null) + if (!(standardNames.Members["DefaultKeyPropertySet"] is PSPropertySet defaultKeys)) { return null; } @@ -378,14 +379,14 @@ internal static List CreateOrderMatrix( List mshParameterList ) { - List orderMatrixToCreate = new List(); + List orderMatrixToCreate = new(); for (int index = 0; index < inputObjects.Count; index++) { PSObject so = inputObjects[index]; if (so == null || so == AutomationNull.Value) continue; - List evaluationErrors = new List(); - List propertyNotFoundMsgs = new List(); + List evaluationErrors = new(); + List propertyNotFoundMsgs = new(); OrderByPropertyEntry result = OrderByPropertyEntryEvaluationHelper.ProcessObject(so, mshParameterList, evaluationErrors, propertyNotFoundMsgs, originalIndex: index); foreach (ErrorRecord err in evaluationErrors) @@ -480,7 +481,7 @@ bool caseSensitive } /// - /// OrderByProperty constructor. + /// Initializes a new instance of the class. /// internal OrderByProperty() { @@ -509,8 +510,8 @@ internal OrderByPropertyEntry CreateOrderByPropertyEntry( ExpandExpressions(inputObject, _unExpandedParametersWithWildCardPattern, _mshParameterList); } - List evaluationErrors = new List(); - List propertyNotFoundMsgs = new List(); + List evaluationErrors = new(); + List propertyNotFoundMsgs = new(); OrderByPropertyEntry result = OrderByPropertyEntryEvaluationHelper.ProcessObject(inputObject, _mshParameterList, evaluationErrors, propertyNotFoundMsgs, isCaseSensitive, cultureInfo); foreach (ErrorRecord err in evaluationErrors) @@ -529,7 +530,7 @@ internal OrderByPropertyEntry CreateOrderByPropertyEntry( #endregion Utils // list of processed parameters obtained from the Expression array - private List _mshParameterList = null; + private readonly List _mshParameterList = null; // list of unprocessed parameters obtained from the Expression array. private List _unexpandedParameterList = null; @@ -545,7 +546,7 @@ internal static OrderByPropertyEntry ProcessObject(PSObject inputObject, List orderValues = new List(); + internal List orderValues = new(); // The originalIndex field was added to enable stable heap-sorts (Top N/Bottom N) internal int originalIndex = -1; @@ -698,7 +699,7 @@ internal static OrderByPropertyComparer CreateComparer(List @@ -727,6 +728,6 @@ public int Compare(OrderByPropertyEntry lhs, OrderByPropertyEntry rhs) return result; } - private OrderByPropertyComparer _orderByPropertyComparer = null; + private readonly OrderByPropertyComparer _orderByPropertyComparer = null; } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointAccessorCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointAccessorCommandBase.cs index 88b3cde9acf..d3dfd30f9e5 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointAccessorCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointAccessorCommandBase.cs @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Management.Automation; -using System.Management.Automation.Runspaces; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointCommandBase.cs index bc01f341861..e3590e380d4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointCommandBase.cs @@ -16,7 +16,6 @@ public abstract class PSBreakpointCommandBase : PSCmdlet /// /// Gets or sets the runspace where the breakpoints will be used. /// - [Experimental("Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace", ExperimentAction.Show)] [Parameter] [ValidateNotNull] [Runspace] diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointUpdaterCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointUpdaterCommandBase.cs index 0b1452b0709..f186fbe1baa 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointUpdaterCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/PSBreakpointUpdaterCommandBase.cs @@ -88,7 +88,7 @@ protected override void ProcessRecord() #region private data - private readonly Dictionary runspaces = new Dictionary(); + private readonly Dictionary runspaces = new(); #endregion private data diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ReadConsoleCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ReadConsoleCmdlet.cs index 2eb71f1ca5d..3fabe75de24 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ReadConsoleCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ReadConsoleCmdlet.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -21,7 +20,7 @@ namespace Microsoft.PowerShell.Commands public sealed class ReadHostCommand : PSCmdlet { /// - /// Constructs a new instance. + /// Initializes a new instance of the class. /// public ReadHostCommand() @@ -98,7 +97,7 @@ protected override void BeginProcessing() IEnumerator e = LanguagePrimitives.GetEnumerator(_prompt); if (e != null) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); while (e.MoveNext()) { @@ -126,7 +125,7 @@ protected override void BeginProcessing() promptString = (string)LanguagePrimitives.ConvertTo(_prompt, typeof(string), CultureInfo.InvariantCulture); } - FieldDescription fd = new FieldDescription(promptString); + FieldDescription fd = new(promptString); if (AsSecureString || MaskInput) { fd.SetParameterType(typeof(SecureString)); @@ -136,7 +135,7 @@ protected override void BeginProcessing() fd.SetParameterType(typeof(string)); } - Collection fdc = new Collection(); + Collection fdc = new(); fdc.Add(fd); Dictionary result = Host.UI.Prompt(string.Empty, string.Empty, fdc); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterObjectEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterObjectEventCommand.cs index ce72dac51fe..d4e7dc784c1 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterObjectEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterObjectEventCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; namespace Microsoft.PowerShell.Commands diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterPSEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterPSEventCommand.cs index f04124e9a4c..6e4ced90760 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterPSEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RegisterPSEventCommand.cs @@ -42,7 +42,7 @@ protected override object GetSourceObject() (!(bool)Forward) ) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException(EventingStrings.ActionMandatoryForLocal), "ACTION_MANDATORY_FOR_LOCAL", ErrorCategory.InvalidArgument, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveAliasCommand.cs index 7b44a0c2664..cd0c4fce327 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveAliasCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; using System.Management.Automation.Internal; @@ -10,7 +9,7 @@ namespace Microsoft.PowerShell.Commands /// /// The implementation of the "Remove-Alias" cmdlet. /// - [Cmdlet(VerbsCommon.Remove, "Alias", DefaultParameterSetName = "Default", HelpUri = "")] + [Cmdlet(VerbsCommon.Remove, "Alias", DefaultParameterSetName = "Default", HelpUri = "https://go.microsoft.com/fwlink/?linkid=2097127")] [Alias("ral")] public class RemoveAliasCommand : PSCmdlet { @@ -62,8 +61,8 @@ protected override void ProcessRecord() } else { - ItemNotFoundException notAliasFound = new ItemNotFoundException(StringUtil.Format(AliasCommandStrings.NoAliasFound, "name", aliasName)); - ErrorRecord error = new ErrorRecord(notAliasFound, "ItemNotFoundException", ErrorCategory.ObjectNotFound, aliasName); + ItemNotFoundException notAliasFound = new(StringUtil.Format(AliasCommandStrings.NoAliasFound, "name", aliasName)); + ErrorRecord error = new(notAliasFound, "ItemNotFoundException", ErrorCategory.ObjectNotFound, aliasName); WriteError(error); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveEventCommand.cs index 14acbbdf6af..4b8ade4a94a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/RemoveEventCommand.cs @@ -111,7 +111,7 @@ protected override void ProcessRecord() (!WildcardPattern.ContainsWildcardCharacters(_sourceIdentifier)) && (!foundMatch)) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException( string.Format( System.Globalization.CultureInfo.CurrentCulture, @@ -124,7 +124,7 @@ protected override void ProcessRecord() } else if ((_eventIdentifier >= 0) && (!foundMatch)) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException( string.Format( System.Globalization.CultureInfo.CurrentCulture, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs index bba2ac2873d..b57be43f25f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs @@ -18,7 +18,8 @@ namespace Microsoft.PowerShell.Commands internal sealed class PSPropertyExpressionFilter { /// - /// Construct the class, using an array of patterns. + /// Initializes a new instance of the class + /// with the specified array of patterns. /// /// Array of pattern strings to use. internal PSPropertyExpressionFilter(string[] wildcardPatternsStrings) @@ -52,7 +53,7 @@ internal bool IsMatch(PSPropertyExpression expression) return false; } - private WildcardPattern[] _wildcardPatterns; + private readonly WildcardPattern[] _wildcardPatterns; } internal class SelectObjectExpressionParameterDefinition : CommandParameterDefinition @@ -76,7 +77,7 @@ public sealed class SelectObjectCommand : PSCmdlet /// /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// @@ -90,14 +91,14 @@ public sealed class SelectObjectCommand : PSCmdlet /// [Parameter(ParameterSetName = "DefaultParameter")] [Parameter(ParameterSetName = "SkipLastParameter")] - public string[] ExcludeProperty { get; set; } = null; + public string[] ExcludeProperty { get; set; } /// /// /// [Parameter(ParameterSetName = "DefaultParameter")] [Parameter(ParameterSetName = "SkipLastParameter")] - public string ExpandProperty { get; set; } = null; + public string ExpandProperty { get; set; } /// /// @@ -151,14 +152,14 @@ public int First /// [Parameter(ParameterSetName = "DefaultParameter")] [ValidateRange(0, int.MaxValue)] - public int Skip { get; set; } = 0; + public int Skip { get; set; } /// /// Skip the specified number of items from end. /// [Parameter(ParameterSetName = "SkipLastParameter")] [ValidateRange(0, int.MaxValue)] - public int SkipLast { get; set; } = 0; + public int SkipLast { get; set; } /// /// With this switch present, the cmdlet won't "short-circuit" @@ -222,7 +223,7 @@ public int[] SkipIndex private SelectObjectQueue _selectObjectQueue; - private class SelectObjectQueue : Queue + private sealed class SelectObjectQueue : Queue { internal SelectObjectQueue(int first, int last, int skip, int skipLast, bool firstOrLastSpecified) { @@ -304,8 +305,11 @@ public PSObject StreamingDequeue() } private int _streamedObjectCount; - private int _first, _last, _skip, _skipLast; - private bool _firstOrLastSpecified; + private readonly int _first; + private readonly int _last; + private int _skip; + private readonly int _skipLast; + private readonly bool _firstOrLastSpecified; } /// @@ -320,7 +324,7 @@ public PSObject StreamingDequeue() private PSPropertyExpressionFilter _exclusionFilter; - private class UniquePSObjectHelper + private sealed class UniquePSObjectHelper { internal UniquePSObjectHelper(PSObject o, int notePropertyCount) { @@ -337,9 +341,9 @@ internal UniquePSObjectHelper(PSObject o, int notePropertyCount) private void ProcessExpressionParameter() { - TerminatingErrorContext invocationContext = new TerminatingErrorContext(this); + TerminatingErrorContext invocationContext = new(this); ParameterProcessor processor = - new ParameterProcessor(new SelectObjectExpressionParameterDefinition()); + new(new SelectObjectExpressionParameterDefinition()); if ((Property != null) && (Property.Length != 0)) { // Build property list taking into account the wildcards and @{name=;expression=} @@ -378,7 +382,7 @@ private void ProcessObject(PSObject inputObject) } // If property parameter is mentioned - List matchedProperties = new List(); + List matchedProperties = new(); foreach (MshParameter p in _propertyMshParameterList) { ProcessParameter(p, inputObject, matchedProperties); @@ -386,10 +390,10 @@ private void ProcessObject(PSObject inputObject) if (string.IsNullOrEmpty(ExpandProperty)) { - PSObject result = new PSObject(); + PSObject result = new(); if (matchedProperties.Count != 0) { - HashSet propertyNames = new HashSet(StringComparer.OrdinalIgnoreCase); + HashSet propertyNames = new(StringComparer.OrdinalIgnoreCase); foreach (PSNoteProperty noteProperty in matchedProperties) { @@ -427,7 +431,7 @@ private void ProcessParameter(MshParameter p, PSObject inputObject, List expressionResults = new List(); + List expressionResults = new(); foreach (PSPropertyExpression resolvedName in ex.ResolveNames(inputObject)) { if (_exclusionFilter == null || !_exclusionFilter.IsMatch(resolvedName)) @@ -452,7 +456,7 @@ private void ProcessParameter(MshParameter p, PSObject inputObject, List 1) { string errorMsg = SelectObjectStrings.RenamingMultipleResults; - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(errorMsg), "RenamingMultipleResults", ErrorCategory.InvalidOperation, @@ -502,7 +506,7 @@ private void ProcessExpandParameter(MshParameter p, PSObject inputObject, if (expressionResults.Count == 0) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewArgumentException("ExpandProperty", SelectObjectStrings.PropertyNotFound, ExpandProperty), "ExpandPropertyNotFound", ErrorCategory.InvalidArgument, @@ -512,7 +516,7 @@ private void ProcessExpandParameter(MshParameter p, PSObject inputObject, if (expressionResults.Count > 1) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewArgumentException("ExpandProperty", SelectObjectStrings.MutlipleExpandProperties, ExpandProperty), "MutlipleExpandProperties", ErrorCategory.InvalidArgument, @@ -559,7 +563,7 @@ private void ProcessExpandParameter(MshParameter p, PSObject inputObject, } else { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( r.Exception, "PropertyEvaluationExpand", ErrorCategory.InvalidResult, @@ -592,7 +596,7 @@ private void AddNoteProperties(PSObject expandedObject, PSObject inputObject, IE private void WriteAlreadyExistingPropertyError(string name, object inputObject, string errorId) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewArgumentException("Property", SelectObjectStrings.AlreadyExistingProperty, name), errorId, ErrorCategory.InvalidOperation, @@ -620,7 +624,7 @@ private void FilteredWriteObject(PSObject obj, List addedNotePro bool isObjUnique = true; foreach (UniquePSObjectHelper uniqueObj in _uniques) { - ObjectCommandComparer comparer = new ObjectCommandComparer(true, CultureInfo.CurrentCulture, true); + ObjectCommandComparer comparer = new(true, CultureInfo.CurrentCulture, true); if ((comparer.Compare(obj.BaseObject, uniqueObj.WrittenObject.BaseObject) == 0) && (uniqueObj.NotePropertyCount == addedNoteProperties.Count)) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Send-MailMessage.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Send-MailMessage.cs index 957c21d465d..64ee818a6bd 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Send-MailMessage.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Send-MailMessage.cs @@ -165,7 +165,7 @@ public Encoding Encoding /// Value must be greater than zero. /// [Parameter(ValueFromPipelineByPropertyName = true)] - [ValidateRange(0, Int32.MaxValue)] + [ValidateRange(0, int.MaxValue)] public int Port { get; set; } #endregion @@ -173,7 +173,7 @@ public Encoding Encoding #region Private variables and methods // Instantiate a new instance of MailMessage - private MailMessage _mMailMessage = new MailMessage(); + private readonly MailMessage _mMailMessage = new(); private SmtpClient _mSmtpClient = null; @@ -216,7 +216,7 @@ private void AddAddressesToMailMessage(object address, string param) } catch (FormatException e) { - ErrorRecord er = new ErrorRecord(e, "FormatException", ErrorCategory.InvalidType, null); + ErrorRecord er = new(e, "FormatException", ErrorCategory.InvalidType, null); WriteError(er); continue; } @@ -239,7 +239,7 @@ protected override void BeginProcessing() } catch (FormatException e) { - ErrorRecord er = new ErrorRecord(e, "FormatException", ErrorCategory.InvalidType, From); + ErrorRecord er = new(e, "FormatException", ErrorCategory.InvalidType, From); ThrowTerminatingError(er); } @@ -294,7 +294,7 @@ protected override void BeginProcessing() if (string.IsNullOrEmpty(SmtpServer)) { - ErrorRecord er = new ErrorRecord(new InvalidOperationException(SendMailMessageStrings.HostNameValue), null, ErrorCategory.InvalidArgument, null); + ErrorRecord er = new(new InvalidOperationException(SendMailMessageStrings.HostNameValue), null, ErrorCategory.InvalidArgument, null); this.ThrowTerminatingError(er); } @@ -344,7 +344,7 @@ protected override void ProcessRecord() PathUtils.ReportFileOpenFailure(this, filepath, e); } - Attachment mailAttachment = new Attachment(filepath); + Attachment mailAttachment = new(filepath); _mMailMessage.Attachments.Add(mailAttachment); } } @@ -362,30 +362,30 @@ protected override void EndProcessing() } catch (SmtpFailedRecipientsException ex) { - ErrorRecord er = new ErrorRecord(ex, "SmtpFailedRecipientsException", ErrorCategory.InvalidOperation, _mSmtpClient); + ErrorRecord er = new(ex, "SmtpFailedRecipientsException", ErrorCategory.InvalidOperation, _mSmtpClient); WriteError(er); } catch (SmtpException ex) { if (ex.InnerException != null) { - ErrorRecord er = new ErrorRecord(new SmtpException(ex.InnerException.Message), "SmtpException", ErrorCategory.InvalidOperation, _mSmtpClient); + ErrorRecord er = new(new SmtpException(ex.InnerException.Message), "SmtpException", ErrorCategory.InvalidOperation, _mSmtpClient); WriteError(er); } else { - ErrorRecord er = new ErrorRecord(ex, "SmtpException", ErrorCategory.InvalidOperation, _mSmtpClient); + ErrorRecord er = new(ex, "SmtpException", ErrorCategory.InvalidOperation, _mSmtpClient); WriteError(er); } } catch (InvalidOperationException ex) { - ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.InvalidOperation, _mSmtpClient); + ErrorRecord er = new(ex, "InvalidOperationException", ErrorCategory.InvalidOperation, _mSmtpClient); WriteError(er); } catch (System.Security.Authentication.AuthenticationException ex) { - ErrorRecord er = new ErrorRecord(ex, "AuthenticationException", ErrorCategory.InvalidOperation, _mSmtpClient); + ErrorRecord er = new(ex, "AuthenticationException", ErrorCategory.InvalidOperation, _mSmtpClient); WriteError(er); } finally diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Set-PSBreakpoint.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Set-PSBreakpoint.cs index e628da48244..ccf17652c79 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Set-PSBreakpoint.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Set-PSBreakpoint.cs @@ -123,7 +123,7 @@ protected override void BeginProcessing() protected override void ProcessRecord() { // If there is a script, resolve its path - Collection scripts = new Collection(); + Collection scripts = new(); if (Script != null) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetAliasCommand.cs index b2746625375..6c0007fa2a2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetAliasCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetAliasCommand.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; using System.Management.Automation.Internal; @@ -24,7 +23,7 @@ protected override void ProcessRecord() // Create the alias info AliasInfo aliasToSet = - new AliasInfo( + new( Name, Value, Context, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetDateCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetDateCommand.cs index e00a3bda2d9..8128c1a84ca 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetDateCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/SetDateCommand.cs @@ -77,14 +77,14 @@ protected override void ProcessRecord() } #else // build up the SystemTime struct to pass to SetSystemTime - NativeMethods.SystemTime systemTime = new NativeMethods.SystemTime(); - systemTime.Year = (UInt16)dateToUse.Year; - systemTime.Month = (UInt16)dateToUse.Month; - systemTime.Day = (UInt16)dateToUse.Day; - systemTime.Hour = (UInt16)dateToUse.Hour; - systemTime.Minute = (UInt16)dateToUse.Minute; - systemTime.Second = (UInt16)dateToUse.Second; - systemTime.Milliseconds = (UInt16)dateToUse.Millisecond; + NativeMethods.SystemTime systemTime = new(); + systemTime.Year = (ushort)dateToUse.Year; + systemTime.Month = (ushort)dateToUse.Month; + systemTime.Day = (ushort)dateToUse.Day; + systemTime.Hour = (ushort)dateToUse.Hour; + systemTime.Minute = (ushort)dateToUse.Minute; + systemTime.Second = (ushort)dateToUse.Second; + systemTime.Milliseconds = (ushort)dateToUse.Millisecond; #pragma warning disable 56523 if (!NativeMethods.SetLocalTime(ref systemTime)) { @@ -102,8 +102,8 @@ protected override void ProcessRecord() } // output DateTime object wrapped in an PSObject with DisplayHint attached - PSObject outputObj = new PSObject(dateToUse); - PSNoteProperty note = new PSNoteProperty("DisplayHint", DisplayHint); + PSObject outputObj = new(dateToUse); + PSNoteProperty note = new("DisplayHint", DisplayHint); outputObj.Properties.Add(note); WriteObject(outputObj); @@ -118,14 +118,14 @@ internal static class NativeMethods [StructLayout(LayoutKind.Sequential)] public struct SystemTime { - public UInt16 Year; - public UInt16 Month; - public UInt16 DayOfWeek; - public UInt16 Day; - public UInt16 Hour; - public UInt16 Minute; - public UInt16 Second; - public UInt16 Milliseconds; + public ushort Year; + public ushort Month; + public ushort DayOfWeek; + public ushort Day; + public ushort Hour; + public ushort Minute; + public ushort Second; + public ushort Milliseconds; } [DllImport(PinvokeDllNames.SetLocalTimeDllName, SetLastError = true)] diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommand.cs index d9556753fb1..60b05807d48 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommand.cs @@ -50,7 +50,7 @@ public class ShowCommandCommand : PSCmdlet, IDisposable /// /// Record the EndProcessing error. /// - private PSDataCollection _errors = new PSDataCollection(); + private PSDataCollection _errors = new(); /// /// Field used for the NoCommonParameter parameter. @@ -63,14 +63,6 @@ public class ShowCommandCommand : PSCmdlet, IDisposable private object _commandViewModelObj; #endregion - /// - /// Finalizes an instance of the ShowCommandCommand class. - /// - ~ShowCommandCommand() - { - this.Dispose(false); - } - #region Input Cmdlet Parameter /// /// Gets or sets the command name. @@ -83,14 +75,14 @@ public class ShowCommandCommand : PSCmdlet, IDisposable /// Gets or sets the Width. /// [Parameter] - [ValidateRange(300, Int32.MaxValue)] + [ValidateRange(300, int.MaxValue)] public double Height { get; set; } /// /// Gets or sets the Width. /// [Parameter] - [ValidateRange(300, Int32.MaxValue)] + [ValidateRange(300, int.MaxValue)] public double Width { get; set; } /// @@ -182,7 +174,7 @@ protected override void BeginProcessing() if (_showCommandProxy.ScreenHeight < this.Height) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new NotSupportedException(string.Format(CultureInfo.CurrentUICulture, FormatAndOut_out_gridview.PropertyValidate, "Height", _showCommandProxy.ScreenHeight)), "PARAMETER_DATA_ERROR", ErrorCategory.InvalidData, @@ -192,7 +184,7 @@ protected override void BeginProcessing() if (_showCommandProxy.ScreenWidth < this.Width) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new NotSupportedException(string.Format(CultureInfo.CurrentUICulture, FormatAndOut_out_gridview.PropertyValidate, "Width", _showCommandProxy.ScreenWidth)), "PARAMETER_DATA_ERROR", ErrorCategory.InvalidData, @@ -241,7 +233,7 @@ protected override void EndProcessing() return; } - StringBuilder errorString = new StringBuilder(); + StringBuilder errorString = new(); for (int i = 0; i < _errors.Count; i++) { @@ -276,7 +268,7 @@ protected override void StopProcessing() private void RunScriptSilentlyAndWithErrorHookup(string script) { // errors are not created here, because there is a field for it used in the final pop up - PSDataCollection output = new PSDataCollection(); + PSDataCollection output = new(); output.DataAdded += this.Output_DataAdded; _errors.DataAdded += this.Error_DataAdded; @@ -294,7 +286,7 @@ private void RunScriptSilentlyAndWithErrorHookup(string script) /// private void IssueErrorForNoCommand() { - InvalidOperationException errorException = new InvalidOperationException( + InvalidOperationException errorException = new( string.Format( CultureInfo.CurrentUICulture, FormatAndOut_out_gridview.CommandNotFound, @@ -307,7 +299,7 @@ private void IssueErrorForNoCommand() /// private void IssueErrorForMoreThanOneCommand() { - InvalidOperationException errorException = new InvalidOperationException( + InvalidOperationException errorException = new( string.Format( CultureInfo.CurrentUICulture, FormatAndOut_out_gridview.MoreThanOneCommand, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandCommandInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandCommandInfo.cs index 1450555d8d7..163b5d5028c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandCommandInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandCommandInfo.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands.ShowCommandExtension public class ShowCommandCommandInfo { /// - /// Creates an instance of the ShowCommandCommandInfo class based on a CommandInfo object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -38,7 +39,7 @@ public ShowCommandCommandInfo(CommandInfo other) { this.ParameterSets = other.ParameterSets - .Select(x => new ShowCommandParameterSetInfo(x)) + .Select(static x => new ShowCommandParameterSetInfo(x)) .ToList() .AsReadOnly(); } @@ -62,7 +63,8 @@ public ShowCommandCommandInfo(CommandInfo other) } /// - /// Creates an instance of the ShowCommandCommandInfo class based on a PSObject object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -90,7 +92,7 @@ public ShowCommandCommandInfo(PSObject other) this.CommandType = (CommandTypes)((other.Members["CommandType"].Value as PSObject).BaseObject); var parameterSets = (other.Members["ParameterSets"].Value as PSObject).BaseObject as System.Collections.ArrayList; - this.ParameterSets = GetObjectEnumerable(parameterSets).Cast().Select(x => new ShowCommandParameterSetInfo(x)).ToList().AsReadOnly(); + this.ParameterSets = GetObjectEnumerable(parameterSets).Cast().Select(static x => new ShowCommandParameterSetInfo(x)).ToList().AsReadOnly(); if (other.Members["Module"]?.Value is PSObject) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandModuleInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandModuleInfo.cs index 6e0f7c97012..b12cc5651f4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandModuleInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandModuleInfo.cs @@ -12,7 +12,8 @@ namespace Microsoft.PowerShell.Commands.ShowCommandExtension public class ShowCommandModuleInfo { /// - /// Creates an instance of the ShowCommandModuleInfo class based on a CommandInfo object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -28,7 +29,8 @@ public ShowCommandModuleInfo(PSModuleInfo other) } /// - /// Creates an instance of the ShowCommandModuleInfo class based on a PSObject object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterInfo.cs index 22b3f692694..88a75dfe610 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterInfo.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands.ShowCommandExtension public class ShowCommandParameterInfo { /// - /// Creates an instance of the ShowCommandParameterInfo class based on a CommandParameterInfo object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -32,7 +33,7 @@ public ShowCommandParameterInfo(CommandParameterInfo other) this.ParameterType = new ShowCommandParameterType(other.ParameterType); this.Position = other.Position; - var validateSetAttribute = other.Attributes.Where(x => typeof(ValidateSetAttribute).IsAssignableFrom(x.GetType())).Cast().LastOrDefault(); + var validateSetAttribute = other.Attributes.Where(static x => typeof(ValidateSetAttribute).IsAssignableFrom(x.GetType())).Cast().LastOrDefault(); if (validateSetAttribute != null) { this.HasParameterSet = true; @@ -41,6 +42,7 @@ public ShowCommandParameterInfo(CommandParameterInfo other) } /// + /// Initializes a new instance of the class. /// Creates an instance of the ShowCommandParameterInfo class based on a PSObject object. /// /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterSetInfo.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterSetInfo.cs index b8c906a2266..75f0675eb87 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterSetInfo.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterSetInfo.cs @@ -14,7 +14,8 @@ namespace Microsoft.PowerShell.Commands.ShowCommandExtension public class ShowCommandParameterSetInfo { /// - /// Creates an instance of the ShowCommandParameterSetInfo class based on a CommandParameterSetInfo object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -28,11 +29,12 @@ public ShowCommandParameterSetInfo(CommandParameterSetInfo other) this.Name = other.Name; this.IsDefault = other.IsDefault; - this.Parameters = other.Parameters.Select(x => new ShowCommandParameterInfo(x)).ToArray(); + this.Parameters = other.Parameters.Select(static x => new ShowCommandParameterInfo(x)).ToArray(); } /// - /// Creates an instance of the ShowCommandParameterSetInfo class based on a PSObject object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -47,7 +49,7 @@ public ShowCommandParameterSetInfo(PSObject other) this.Name = other.Members["Name"].Value as string; this.IsDefault = (bool)(other.Members["IsDefault"].Value); var parameters = (other.Members["Parameters"].Value as PSObject).BaseObject as System.Collections.ArrayList; - this.Parameters = ShowCommandCommandInfo.GetObjectEnumerable(parameters).Cast().Select(x => new ShowCommandParameterInfo(x)).ToArray(); + this.Parameters = ShowCommandCommandInfo.GetObjectEnumerable(parameters).Cast().Select(static x => new ShowCommandParameterInfo(x)).ToArray(); } /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterType.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterType.cs index c0bbb644d3c..1daf0350dbc 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterType.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandParameterType.cs @@ -13,7 +13,8 @@ namespace Microsoft.PowerShell.Commands.ShowCommandExtension public class ShowCommandParameterType { /// - /// Creates an instance of the ShowCommandParameterType class based on a Type object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. @@ -42,7 +43,8 @@ public ShowCommandParameterType(Type other) } /// - /// Creates an instance of the ShowCommandParameterType class based on a Type object. + /// Initializes a new instance of the class + /// with the specified . /// /// /// The object to wrap. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandProxy.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandProxy.cs index 4a5700bdf7a..a8a9c8f194d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandProxy.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowCommand/ShowCommandProxy.cs @@ -20,9 +20,9 @@ internal class ShowCommandProxy { private const string ShowCommandHelperName = "Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper"; - private ShowCommandCommand _cmdlet; + private readonly ShowCommandCommand _cmdlet; - private GraphicalHostReflectionWrapper _graphicalHostReflectionWrapper; + private readonly GraphicalHostReflectionWrapper _graphicalHostReflectionWrapper; internal ShowCommandProxy(ShowCommandCommand cmdlet) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs index 2203fbb20a7..63ee15f6f59 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.Collections; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; @@ -170,7 +168,7 @@ private void ProcessMarkdownInfo(MarkdownInfo markdownInfo) try { - ProcessStartInfo startInfo = new ProcessStartInfo(); + ProcessStartInfo startInfo = new(); startInfo.FileName = tmpFilePath; startInfo.UseShellExecute = true; Process.Start(startInfo); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Sort-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Sort-Object.cs index 5f66b39753f..06f5ebfffad 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Sort-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Sort-Object.cs @@ -53,14 +53,14 @@ public SwitchParameter Descending /// [Parameter(ParameterSetName = "Top", Mandatory = true)] [ValidateRange(1, int.MaxValue)] - public int Top { get; set; } = 0; + public int Top { get; set; } /// /// Gets or sets the number of items to return in a Bottom N sort. /// [Parameter(ParameterSetName = "Bottom", Mandatory = true)] [ValidateRange(1, int.MaxValue)] - public int Bottom { get; set; } = 0; + public int Bottom { get; set; } /// /// Moves unique entries to the front of the list. @@ -239,7 +239,7 @@ private int Heapify(List dataToSort, OrderByPropertyCompar /// protected override void EndProcessing() { - OrderByProperty orderByProperty = new OrderByProperty( + OrderByProperty orderByProperty = new( this, InputObjects, Property, !Descending, ConvertedCulture, CaseSensitive); var dataToProcess = orderByProperty.OrderMatrix; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/StartSleepCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/StartSleepCommand.cs index 4fe5c641ff9..a57d635f3eb 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/StartSleepCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/StartSleepCommand.cs @@ -23,7 +23,7 @@ public sealed class StartSleepCommand : PSCmdlet, IDisposable /// public void Dispose() { - if (_disposed == false) + if (!_disposed) { if (_waitHandle != null) { @@ -64,7 +64,7 @@ public void Dispose() // object used for synchronizes pipeline thread and stop thread // access to waitHandle - private object _syncObject = new object(); + private readonly object _syncObject = new(); // this is set to true by stopProcessing private bool _stopping = false; @@ -76,7 +76,7 @@ private void Sleep(int milliSecondsToSleep) { lock (_syncObject) { - if (_stopping == false) + if (!_stopping) { _waitHandle = new ManualResetEvent(false); } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Tee-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Tee-Object.cs index 32048362b06..a23b0be61dc 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Tee-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Tee-Object.cs @@ -3,6 +3,7 @@ using System; using System.Management.Automation; +using System.Text; using Microsoft.PowerShell.Commands.Internal.Format; @@ -72,6 +73,16 @@ public SwitchParameter Append private bool _append; + /// + /// Gets or sets the Encoding. + /// + [Parameter(ParameterSetName = "File")] + [Parameter(ParameterSetName = "LiteralFile")] + [ArgumentToEncodingTransformationAttribute] + [ArgumentEncodingCompletionsAttribute] + [ValidateNotNullOrEmpty] + public Encoding Encoding { get; set; } = ClrFacade.GetDefaultEncoding(); + /// /// Variable parameter. /// @@ -95,12 +106,14 @@ protected override void BeginProcessing() _commandWrapper.Initialize(Context, "out-file", typeof(OutFileCommand)); _commandWrapper.AddNamedParameter("filepath", _fileName); _commandWrapper.AddNamedParameter("append", _append); + _commandWrapper.AddNamedParameter("encoding", Encoding); } else if (string.Equals(ParameterSetName, "LiteralFile", StringComparison.OrdinalIgnoreCase)) { _commandWrapper.Initialize(Context, "out-file", typeof(OutFileCommand)); _commandWrapper.AddNamedParameter("LiteralPath", _fileName); _commandWrapper.AddNamedParameter("append", _append); + _commandWrapper.AddNamedParameter("encoding", Encoding); } else { @@ -111,6 +124,7 @@ protected override void BeginProcessing() // the values to be written } } + /// /// protected override void ProcessRecord() @@ -148,13 +162,6 @@ public void Dispose() GC.SuppressFinalize(this); } - /// - /// Finalizer. - /// - ~TeeObjectCommand() - { - Dispose(false); - } #region private private CommandWrapper _commandWrapper; private bool _alreadyDisposed; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TestJsonCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TestJsonCommand.cs index 668c5072841..cfee0f78aa4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TestJsonCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TestJsonCommand.cs @@ -41,7 +41,7 @@ public class TestJsonCommand : PSCmdlet public string Schema { get; set; } /// - /// Gets or sets path to the file containg schema to validate the JSON string against. + /// Gets or sets path to the file containing schema to validate the JSON string against. /// This is optional parameter. /// [Parameter(Position = 1, ParameterSetName = SchemaFileParameterSet)] @@ -59,7 +59,7 @@ public class TestJsonCommand : PSCmdlet /// Return value is unreachable since we always rethrow. private static bool UnwrapException(Exception e) { - if (e is TargetInvocationException) + if (e.InnerException != null && e is TargetInvocationException) { ExceptionDispatchInfo.Capture(e.InnerException).Throw(); } @@ -115,7 +115,7 @@ e is NotSupportedException || e is SecurityException ) { - Exception exception = new Exception( + Exception exception = new( string.Format( CultureInfo.CurrentUICulture, TestJsonCmdletStrings.JsonSchemaFileOpenFailure, @@ -125,7 +125,7 @@ e is SecurityException } catch (Exception e) { - Exception exception = new Exception(TestJsonCmdletStrings.InvalidJsonSchema, e); + Exception exception = new(TestJsonCmdletStrings.InvalidJsonSchema, e); ThrowTerminatingError(new ErrorRecord(exception, "InvalidJsonSchema", ErrorCategory.InvalidData, resolvedpath)); } } @@ -149,11 +149,11 @@ protected override void ProcessRecord() { result = false; - Exception exception = new Exception(TestJsonCmdletStrings.InvalidJsonAgainstSchema); + Exception exception = new(TestJsonCmdletStrings.InvalidJsonAgainstSchema); foreach (var message in errorMessages) { - ErrorRecord errorRecord = new ErrorRecord(exception, "InvalidJsonAgainstSchema", ErrorCategory.InvalidData, null); + ErrorRecord errorRecord = new(exception, "InvalidJsonAgainstSchema", ErrorCategory.InvalidData, null); errorRecord.ErrorDetails = new ErrorDetails(message.ToString()); WriteError(errorRecord); } @@ -164,7 +164,7 @@ protected override void ProcessRecord() { result = false; - Exception exception = new Exception(TestJsonCmdletStrings.InvalidJson, exc); + Exception exception = new(TestJsonCmdletStrings.InvalidJson, exc); WriteError(new ErrorRecord(exception, "InvalidJson", ErrorCategory.InvalidData, Json)); } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TimeExpressionCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TimeExpressionCommand.cs index d7071a06605..24ed81995d1 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TimeExpressionCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/TimeExpressionCommand.cs @@ -25,19 +25,19 @@ public sealed class MeasureCommandCommand : PSCmdlet /// This parameter specifies the current pipeline object. /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// The script block to apply. /// [Parameter(Position = 0, Mandatory = true)] - public ScriptBlock Expression { set; get; } + public ScriptBlock Expression { get; set; } #endregion #region private members - private System.Diagnostics.Stopwatch _stopWatch = new System.Diagnostics.Stopwatch(); + private readonly System.Diagnostics.Stopwatch _stopWatch = new(); #endregion diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnblockFile.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnblockFile.cs index fad330212ed..5c297ed86d5 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnblockFile.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnblockFile.cs @@ -6,14 +6,15 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +#if UNIX using System.Globalization; -using System.IO; using System.Management.Automation; -using System.Management.Automation.Internal; using System.Runtime.InteropServices; +#else +using System.Management.Automation; +using System.Management.Automation.Internal; +#endif #endregion @@ -73,7 +74,7 @@ public string[] LiteralPath /// protected override void ProcessRecord() { - List pathsToProcess = new List(); + List pathsToProcess = new(); ProviderInfo provider = null; if (string.Equals(this.ParameterSetName, "ByLiteralPath", StringComparison.OrdinalIgnoreCase)) @@ -109,7 +110,7 @@ protected override void ProcessRecord() { if (!WildcardPattern.ContainsWildcardCharacters(path)) { - ErrorRecord errorRecord = new ErrorRecord(e, + ErrorRecord errorRecord = new(e, "FileNotFound", ErrorCategory.ObjectNotFound, path); @@ -146,10 +147,10 @@ protected override void ProcessRecord() foreach (string path in pathsToProcess) { - if(IsBlocked(path)) + if (IsBlocked(path)) { UInt32 result = RemoveXattr(path, MacBlockAttribute, RemovexattrFollowSymLink); - if(result != 0) + if (result != 0) { string errorMessage = string.Format(CultureInfo.CurrentUICulture, UnblockFileStrings.UnblockError, path); Exception e = new InvalidOperationException(errorMessage); @@ -179,7 +180,7 @@ private bool IsValidFileForUnblocking(string resolvedpath) { if (!System.IO.File.Exists(resolvedpath)) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new System.IO.FileNotFoundException(resolvedpath), "FileNotFound", ErrorCategory.ObjectNotFound, @@ -196,9 +197,9 @@ private bool IsValidFileForUnblocking(string resolvedpath) } #if UNIX - private bool IsBlocked(string path) + private static bool IsBlocked(string path) { - uint valueSize = 1024; + const uint valueSize = 1024; IntPtr value = Marshal.AllocHGlobal((int)valueSize); try { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnregisterEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnregisterEventCommand.cs index f89b3d6e4cc..f0f87eb9f66 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnregisterEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UnregisterEventCommand.cs @@ -97,7 +97,7 @@ protected override void ProcessRecord() (!WildcardPattern.ContainsWildcardCharacters(_sourceIdentifier)) && (!_foundMatch)) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException( string.Format( System.Globalization.CultureInfo.CurrentCulture, @@ -111,7 +111,7 @@ protected override void ProcessRecord() else if ((SubscriptionId >= 0) && (!_foundMatch)) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new ArgumentException( string.Format( System.Globalization.CultureInfo.CurrentCulture, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-Data.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-Data.cs index d19810522d0..4a3198d2911 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-Data.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-Data.cs @@ -24,18 +24,18 @@ public class UpdateData : PSCmdlet ParameterSetName = FileParameterSet)] [Alias("PSPath", "Path")] [ValidateNotNull] - public string[] AppendPath { set; get; } = Array.Empty(); + public string[] AppendPath { get; set; } = Array.Empty(); /// /// Files to prepend to the existing set. /// [Parameter(ParameterSetName = FileParameterSet)] [ValidateNotNull] - public string[] PrependPath { set; get; } = Array.Empty(); + public string[] PrependPath { get; set; } = Array.Empty(); private static void ReportWrongExtension(string file, string errorId, PSCmdlet cmdlet) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewInvalidOperationException(UpdateDataStrings.UpdateData_WrongExtension, file, "ps1xml"), errorId, ErrorCategory.InvalidArgument, @@ -45,7 +45,7 @@ private static void ReportWrongExtension(string file, string errorId, PSCmdlet c private static void ReportWrongProviderType(string providerId, string errorId, PSCmdlet cmdlet) { - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( PSTraceSource.NewInvalidOperationException(UpdateDataStrings.UpdateData_WrongProviderError, providerId), errorId, ErrorCategory.InvalidArgument, @@ -61,7 +61,7 @@ private static void ReportWrongProviderType(string providerId, string errorId, P /// internal static Collection Glob(string[] files, string errorId, PSCmdlet cmdlet) { - Collection retValue = new Collection(); + Collection retValue = new(); foreach (string file in files) { Collection providerPaths; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-List.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-List.cs index dbff09ef36a..5850eaca7db 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-List.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-List.cs @@ -129,7 +129,7 @@ protected override void EndProcessing() private Hashtable CreateHashtable() { - Hashtable hash = new Hashtable(2); + Hashtable hash = new(2); if (Add != null) { hash.Add("Add", Add); @@ -150,7 +150,7 @@ private Hashtable CreateHashtable() private PSListModifier CreatePSListModifier() { - PSListModifier listModifier = new PSListModifier(); + PSListModifier listModifier = new(); if (Add != null) { foreach (object obj in Add) @@ -180,8 +180,8 @@ private PSListModifier CreatePSListModifier() private ErrorRecord NewError(string errorId, string resourceId, object targetObject, params object[] args) { - ErrorDetails details = new ErrorDetails(this.GetType().Assembly, "UpdateListStrings", resourceId, args); - ErrorRecord errorRecord = new ErrorRecord( + ErrorDetails details = new(this.GetType().Assembly, "UpdateListStrings", resourceId, args); + ErrorRecord errorRecord = new( new InvalidOperationException(details.Message), errorId, ErrorCategory.InvalidOperation, diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs index de7d2590176..d137524629d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs @@ -28,7 +28,7 @@ public class UpdateTypeDataCommand : UpdateData private const string DynamicTypeSet = "DynamicTypeSet"; private const string TypeDataSet = "TypeDataSet"; - private static object s_notSpecified = new object(); + private static readonly object s_notSpecified = new(); private static bool HasBeenSpecified(object obj) { @@ -50,13 +50,16 @@ private static bool HasBeenSpecified(object obj) System.Management.Automation.Runspaces.TypeData.CodeMethod, IgnoreCase = true)] public PSMemberTypes MemberType { + get + { + return _memberType; + } + set { _memberType = value; _isMemberTypeSet = true; } - - get { return _memberType; } } private string _memberName; @@ -67,9 +70,9 @@ public PSMemberTypes MemberType [ValidateNotNullOrEmpty] public string MemberName { - set { _memberName = value; } - get { return _memberName; } + + set { _memberName = value; } } private object _value1 = s_notSpecified; @@ -80,9 +83,9 @@ public string MemberName [Parameter(ParameterSetName = DynamicTypeSet)] public object Value { - set { _value1 = value; } - get { return _value1; } + + set { _value1 = value; } } private object _value2; @@ -94,9 +97,9 @@ public object Value [ValidateNotNull] public object SecondValue { - set { _value2 = value; } - get { return _value2; } + + set { _value2 = value; } } private Type _typeConverter; @@ -107,9 +110,9 @@ public object SecondValue [ValidateNotNull] public Type TypeConverter { - set { _typeConverter = value; } - get { return _typeConverter; } + + set { _typeConverter = value; } } private Type _typeAdapter; @@ -120,9 +123,9 @@ public Type TypeConverter [ValidateNotNull] public Type TypeAdapter { - set { _typeAdapter = value; } - get { return _typeAdapter; } + + set { _typeAdapter = value; } } /// @@ -132,9 +135,9 @@ public Type TypeAdapter [ValidateNotNullOrEmpty] public string SerializationMethod { - set { _serializationMethod = value; } - get { return _serializationMethod; } + + set { _serializationMethod = value; } } /// @@ -144,9 +147,9 @@ public string SerializationMethod [ValidateNotNull] public Type TargetTypeForDeserialization { - set { _targetTypeForDeserialization = value; } - get { return _targetTypeForDeserialization; } + + set { _targetTypeForDeserialization = value; } } /// @@ -157,9 +160,9 @@ public Type TargetTypeForDeserialization [ValidateRange(0, int.MaxValue)] public int SerializationDepth { - set { _serializationDepth = value; } - get { return _serializationDepth; } + + set { _serializationDepth = value; } } /// @@ -169,9 +172,9 @@ public int SerializationDepth [ValidateNotNullOrEmpty] public string DefaultDisplayProperty { - set { _defaultDisplayProperty = value; } - get { return _defaultDisplayProperty; } + + set { _defaultDisplayProperty = value; } } /// @@ -181,9 +184,9 @@ public string DefaultDisplayProperty [ValidateNotNull] public bool? InheritPropertySerializationSet { - set { _inheritPropertySerializationSet = value; } - get { return _inheritPropertySerializationSet; } + + set { _inheritPropertySerializationSet = value; } } /// @@ -193,9 +196,9 @@ public bool? InheritPropertySerializationSet [ValidateNotNullOrEmpty] public string StringSerializationSource { - set { _stringSerializationSource = value; } - get { return _stringSerializationSource; } + + set { _stringSerializationSource = value; } } /// @@ -206,9 +209,9 @@ public string StringSerializationSource [ValidateNotNullOrEmpty] public string[] DefaultDisplayPropertySet { - set { _defaultDisplayPropertySet = value; } - get { return _defaultDisplayPropertySet; } + + set { _defaultDisplayPropertySet = value; } } /// @@ -219,9 +222,9 @@ public string[] DefaultDisplayPropertySet [ValidateNotNullOrEmpty] public string[] DefaultKeyPropertySet { - set { _defaultKeyPropertySet = value; } - get { return _defaultKeyPropertySet; } + + set { _defaultKeyPropertySet = value; } } /// @@ -232,9 +235,9 @@ public string[] DefaultKeyPropertySet [ValidateNotNullOrEmpty] public string[] PropertySerializationSet { - set { _propertySerializationSet = value; } - get { return _propertySerializationSet; } + + set { _propertySerializationSet = value; } } // These members are represented as NoteProperty in types.ps1xml @@ -261,9 +264,9 @@ public string[] PropertySerializationSet [ValidateNotNullOrEmpty] public string TypeName { - set { _typeName = value; } - get { return _typeName; } + + set { _typeName = value; } } private bool _force = false; @@ -274,9 +277,9 @@ public string TypeName [Parameter(ParameterSetName = TypeDataSet)] public SwitchParameter Force { - set { _force = value; } - get { return _force; } + + set { _force = value; } } #endregion dynamic type set @@ -291,9 +294,9 @@ public SwitchParameter Force [Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, ParameterSetName = TypeDataSet)] public TypeData[] TypeData { - set { _typeData = value; } - get { return _typeData; } + + set { _typeData = value; } } #endregion strong type data set @@ -368,11 +371,11 @@ private void ProcessStrongTypeData() var errors = new ConcurrentBag(); this.Context.TypeTable.Update(type, errors, false); // Write out errors... - if (errors.Count > 0) + if (!errors.IsEmpty) { foreach (string s in errors) { - RuntimeException rte = new RuntimeException(s); + RuntimeException rte = new(s); this.WriteError(new ErrorRecord(rte, "TypesDynamicUpdateException", ErrorCategory.InvalidOperation, null)); } } @@ -411,7 +414,7 @@ private void ProcessDynamicType() ThrowTerminatingError(NewError("TargetTypeNameEmpty", UpdateDataStrings.TargetTypeNameEmpty, _typeName)); } - TypeData type = new TypeData(_typeName) { IsOverride = _force }; + TypeData type = new(_typeName) { IsOverride = _force }; GetMembers(type.Members); @@ -457,19 +460,19 @@ private void ProcessDynamicType() if (_defaultDisplayPropertySet != null) { - PropertySetData defaultDisplayPropertySet = new PropertySetData(_defaultDisplayPropertySet); + PropertySetData defaultDisplayPropertySet = new(_defaultDisplayPropertySet); type.DefaultDisplayPropertySet = defaultDisplayPropertySet; } if (_defaultKeyPropertySet != null) { - PropertySetData defaultKeyPropertySet = new PropertySetData(_defaultKeyPropertySet); + PropertySetData defaultKeyPropertySet = new(_defaultKeyPropertySet); type.DefaultKeyPropertySet = defaultKeyPropertySet; } if (_propertySerializationSet != null) { - PropertySetData propertySerializationSet = new PropertySetData(_propertySerializationSet); + PropertySetData propertySerializationSet = new(_propertySerializationSet); type.PropertySerializationSet = propertySerializationSet; } @@ -492,11 +495,11 @@ private void ProcessDynamicType() var errors = new ConcurrentBag(); this.Context.TypeTable.Update(type, errors, false); // Write out errors... - if (errors.Count > 0) + if (!errors.IsEmpty) { foreach (string s in errors) { - RuntimeException rte = new RuntimeException(s); + RuntimeException rte = new(s); this.WriteError(new ErrorRecord(rte, "TypesDynamicUpdateException", ErrorCategory.InvalidOperation, null)); } } @@ -570,7 +573,7 @@ private void GetMembers(Dictionary members) } } - private T GetParameterType(object sourceValue) + private static T GetParameterType(object sourceValue) { return (T)LanguagePrimitives.ConvertTo(sourceValue, typeof(T), CultureInfo.InvariantCulture); } @@ -690,7 +693,7 @@ private ScriptPropertyData GetScriptProperty() value2ScriptBlock = GetParameterType(_value2); } - ScriptPropertyData scriptProperty = new ScriptPropertyData(_memberName, value1ScriptBlock, value2ScriptBlock); + ScriptPropertyData scriptProperty = new(_memberName, value1ScriptBlock, value2ScriptBlock); return scriptProperty; } @@ -712,7 +715,7 @@ private CodePropertyData GetCodeProperty() value2CodeReference = GetParameterType(_value2); } - CodePropertyData codeProperty = new CodePropertyData(_memberName, value1CodeReference, value2CodeReference); + CodePropertyData codeProperty = new(_memberName, value1CodeReference, value2CodeReference); return codeProperty; } @@ -723,7 +726,7 @@ private ScriptMethodData GetScriptMethod() EnsureValue2HasNotBeenSpecified(); ScriptBlock method = GetParameterType(_value1); - ScriptMethodData scriptMethod = new ScriptMethodData(_memberName, method); + ScriptMethodData scriptMethod = new(_memberName, method); return scriptMethod; } @@ -734,7 +737,7 @@ private CodeMethodData GetCodeMethod() EnsureValue2HasNotBeenSpecified(); MethodInfo codeReference = GetParameterType(_value1); - CodeMethodData codeMethod = new CodeMethodData(_memberName, codeReference); + CodeMethodData codeMethod = new(_memberName, codeReference); return codeMethod; } @@ -746,10 +749,10 @@ private CodeMethodData GetCodeMethod() /// /// /// - private ErrorRecord NewError(string errorId, string template, object targetObject, params object[] args) + private static ErrorRecord NewError(string errorId, string template, object targetObject, params object[] args) { string message = string.Format(CultureInfo.CurrentCulture, template, args); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(message), errorId, ErrorCategory.InvalidOperation, @@ -862,11 +865,11 @@ private void ProcessTypeFiles() Context.InitialSessionState.Types.Add(sste); // Write out any errors... - if (errors.Count > 0) + if (!errors.IsEmpty) { foreach (string s in errors) { - RuntimeException rte = new RuntimeException(s); + RuntimeException rte = new(s); this.WriteError(new ErrorRecord(rte, "TypesXmlUpdateException", ErrorCategory.InvalidOperation, null)); } @@ -1119,8 +1122,8 @@ protected override void ProcessRecord() // Key of the map is the name of the file that is in the cache. Value of the map is a index list. Duplicate files might // exist in the cache because the user can add arbitrary files to the cache by $host.Runspace.InitialSessionState.Types.Add() - Dictionary> fileToIndexMap = new Dictionary>(StringComparer.OrdinalIgnoreCase); - List indicesToRemove = new List(); + Dictionary> fileToIndexMap = new(StringComparer.OrdinalIgnoreCase); + List indicesToRemove = new(); if (Context.InitialSessionState != null) { @@ -1209,7 +1212,7 @@ protected override void ProcessRecord() } Dbg.Assert(!string.IsNullOrEmpty(typeNameToRemove), "TypeNameToRemove should be not null and not empty at this point"); - TypeData type = new TypeData(typeNameToRemove); + TypeData type = new(typeNameToRemove); string removeTypeFormattedTarget = string.Format(CultureInfo.InvariantCulture, removeTypeTarget, typeNameToRemove); if (ShouldProcess(removeTypeFormattedTarget, removeTypeAction)) @@ -1219,11 +1222,11 @@ protected override void ProcessRecord() var errors = new ConcurrentBag(); Context.TypeTable.Update(type, errors, true); // Write out errors... - if (errors.Count > 0) + if (!errors.IsEmpty) { foreach (string s in errors) { - RuntimeException rte = new RuntimeException(s); + RuntimeException rte = new(s); this.WriteError(new ErrorRecord(rte, "TypesDynamicRemoveException", ErrorCategory.InvalidOperation, null)); } } @@ -1255,10 +1258,10 @@ protected override void EndProcessing() this.Context.TypeTable.ClearConsolidatedMembers(); } - private ErrorRecord NewError(string errorId, string template, object targetObject, params object[] args) + private static ErrorRecord NewError(string errorId, string template, object targetObject, params object[] args) { string message = string.Format(CultureInfo.CurrentCulture, template, args); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(message), errorId, ErrorCategory.InvalidOperation, @@ -1334,7 +1337,7 @@ protected override void ProcessRecord() ValidateTypeName(); Dictionary alltypes = Context.TypeTable.GetAllTypeData(); - Collection typedefs = new Collection(); + Collection typedefs = new(); foreach (string type in alltypes.Keys) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs index 37a18ef1080..3906405d916 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs @@ -5,10 +5,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Management.Automation; -using System.Management.Automation.Runspaces; using System.Text; -[module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope = "type", Target = "Microsoft.PowerShell.Commands.ByteCollection")] +[module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope = "type", Target = "~T:Microsoft.PowerShell.Commands.ByteCollection")] namespace Microsoft.PowerShell.Commands { @@ -79,7 +78,7 @@ public static class UtilityResources public static string FileReadError { get { return UtilityCommonStrings.FileReadError; } } /// - /// The resource string used to indicate 'PATH:' in the formating header. + /// The resource string used to indicate 'PATH:' in the formatting header. /// public static string FormatHexPathPrefix { get { return UtilityCommonStrings.FormatHexPathPrefix; } } @@ -189,11 +188,11 @@ public ByteCollection(byte[] value) /// Gets the Offset address to be used while displaying the bytes in the collection. /// [Obsolete("The property is deprecated, please use Offset64 instead.", true)] - public UInt32 Offset + public uint Offset { get { - return (UInt32)Offset64; + return (uint)Offset64; } private set @@ -205,7 +204,7 @@ private set /// /// Gets the Offset address to be used while displaying the bytes in the collection. /// - public UInt64 Offset64 { get; private set; } + public ulong Offset64 { get; private set; } /// /// Gets underlying bytes stored in the collection. @@ -242,7 +241,7 @@ public string HexBytes { if (_hexBytes == string.Empty) { - StringBuilder line = new StringBuilder(BytesPerLine * 3); + StringBuilder line = new(BytesPerLine * 3); foreach (var currentByte in Bytes) { @@ -268,7 +267,7 @@ public string Ascii { if (_ascii == string.Empty) { - StringBuilder ascii = new StringBuilder(BytesPerLine); + StringBuilder ascii = new(BytesPerLine); foreach (var currentByte in Bytes) { @@ -305,11 +304,11 @@ public override string ToString() // '16 + 3' comes from format "{0:X16} ". // '16' comes from '[Uint64]::MaxValue.ToString("X").Length'. - StringBuilder nextLine = new StringBuilder(16 + 3 + (BytesPerLine * 3)); - StringBuilder asciiEnd = new StringBuilder(BytesPerLine); + StringBuilder nextLine = new(16 + 3 + (BytesPerLine * 3)); + StringBuilder asciiEnd = new(BytesPerLine); // '+1' comes from 'result.Append(nextLine.ToString() + " " + asciiEnd.ToString());' below. - StringBuilder result = new StringBuilder(nextLine.Capacity + asciiEnd.Capacity + 1); + StringBuilder result = new(nextLine.Capacity + asciiEnd.Capacity + 1); if (Bytes.Length > 0) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Var.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Var.cs index fd121fc5fb2..e228b309df2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Var.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Var.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Management.Automation; @@ -100,7 +99,7 @@ internal List GetMatchingVariables(string name, string lookupScope, { wasFiltered = false; - List result = new List(); + List result = new(); if (string.IsNullOrEmpty(name)) { @@ -337,10 +336,7 @@ protected override void ProcessRecord() GetMatchingVariables(varName, Scope, out wasFiltered, /*quiet*/ false); matchingVariables.Sort( - delegate (PSVariable left, PSVariable right) - { - return StringComparer.CurrentCultureIgnoreCase.Compare(left.Name, right.Name); - }); + static (PSVariable left, PSVariable right) => StringComparer.CurrentCultureIgnoreCase.Compare(left.Name, right.Name)); bool matchFound = false; foreach (PSVariable matchingVariable in matchingVariables) @@ -359,7 +355,7 @@ protected override void ProcessRecord() if (!matchFound && !wasFiltered) { ItemNotFoundException itemNotFound = - new ItemNotFoundException( + new( varName, "VariableNotFound", SessionStateStrings.VariableNotFound); @@ -494,7 +490,7 @@ protected override void ProcessRecord() if (varFound != null) { SessionStateException sessionStateException = - new SessionStateException( + new( Name, SessionStateCategory.Variable, "VariableAlreadyExists", @@ -518,7 +514,7 @@ protected override void ProcessRecord() if (ShouldProcess(target, action)) { - PSVariable newVariable = new PSVariable(Name, Value, Option); + PSVariable newVariable = new(Name, Value, Option); if (_visibility != null) { @@ -814,7 +810,7 @@ private void SetVariable(string[] varNames, object varValue) { // First look for existing variables to set. - List matchingVariables = new List(); + List matchingVariables = new(); bool wasFiltered = false; @@ -869,7 +865,7 @@ private void SetVariable(string[] varNames, object varValue) } PSVariable varToSet = - new PSVariable( + new( varName, newVarValue, newOptions); @@ -1125,7 +1121,7 @@ protected override void ProcessRecord() // characters were specified, write an error. ItemNotFoundException itemNotFound = - new ItemNotFoundException( + new( varName, "VariableNotFound", SessionStateStrings.VariableNotFound); @@ -1287,7 +1283,7 @@ protected override void ProcessRecord() // characters were specified, write an error. ItemNotFoundException itemNotFound = - new ItemNotFoundException( + new( varName, "VariableNotFound", SessionStateStrings.VariableNotFound); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WaitEventCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WaitEventCommand.cs index 7aeb864e2ba..a8ca247671c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WaitEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WaitEventCommand.cs @@ -42,7 +42,7 @@ public string SourceIdentifier /// [Parameter] [Alias("TimeoutSec")] - [ValidateRangeAttribute(-1, Int32.MaxValue)] + [ValidateRangeAttribute(-1, int.MaxValue)] public int Timeout { get @@ -60,9 +60,9 @@ public int Timeout #endregion parameters - private AutoResetEvent _eventArrived = new AutoResetEvent(false); + private readonly AutoResetEvent _eventArrived = new(false); private PSEventArgs _receivedEvent = null; - private object _receivedEventLock = new object(); + private readonly object _receivedEventLock = new(); private WildcardPattern _matchPattern; /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs index 1d33957d624..969dd8231c8 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/BasicHtmlWebResponseObject.Common.cs @@ -1,12 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Management.Automation; -using System.Net; using System.Net.Http; using System.Text; using System.Text.RegularExpressions; @@ -32,7 +30,7 @@ public class BasicHtmlWebResponseObject : WebResponseObject #region Constructors /// - /// Constructor for BasicHtmlWebResponseObject. + /// Initializes a new instance of the class. /// /// public BasicHtmlWebResponseObject(HttpResponseMessage response) @@ -40,7 +38,8 @@ public BasicHtmlWebResponseObject(HttpResponseMessage response) { } /// - /// Constructor for HtmlWebResponseObject with memory stream. + /// Initializes a new instance of the class + /// with the specified . /// /// /// @@ -62,7 +61,7 @@ public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentSt /// /// Content of the response body, decoded using , /// if the Content-Type response header is a recognized text - /// type. Otherwise null. + /// type. Otherwise . /// public new string Content { get; private set; } @@ -71,7 +70,7 @@ public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentSt /// /// /// Encoding of the response body from the Content-Type header, - /// or null if the encoding could not be determined. + /// or if the encoding could not be determined. /// public Encoding Encoding { get; private set; } @@ -88,7 +87,7 @@ public WebCmdletElementCollection InputFields { EnsureHtmlParser(); - List parsedFields = new List(); + List parsedFields = new(); MatchCollection fieldMatch = s_inputFieldRegex.Matches(Content); foreach (Match field in fieldMatch) { @@ -115,7 +114,7 @@ public WebCmdletElementCollection Links { EnsureHtmlParser(); - List parsedLinks = new List(); + List parsedLinks = new(); MatchCollection linkMatch = s_linkRegex.Matches(Content); foreach (Match link in linkMatch) { @@ -142,7 +141,7 @@ public WebCmdletElementCollection Images { EnsureHtmlParser(); - List parsedImages = new List(); + List parsedImages = new(); MatchCollection imageMatch = s_imageRegex.Matches(Content); foreach (Match image in imageMatch) { @@ -186,9 +185,9 @@ protected void InitializeContent() } } - private PSObject CreateHtmlObject(string html, string tagName) + private static PSObject CreateHtmlObject(string html, string tagName) { - PSObject elementObject = new PSObject(); + PSObject elementObject = new(); elementObject.Properties.Add(new PSNoteProperty("outerHTML", html)); elementObject.Properties.Add(new PSNoteProperty("tagName", tagName)); @@ -198,7 +197,7 @@ private PSObject CreateHtmlObject(string html, string tagName) return elementObject; } - private void EnsureHtmlParser() + private static void EnsureHtmlParser() { if (s_tagRegex == null) { @@ -244,7 +243,7 @@ private void InitializeRawContent(HttpResponseMessage baseResponse) this.RawContent = raw.ToString(); } - private void ParseAttributes(string outerHtml, PSObject elementObject) + private static void ParseAttributes(string outerHtml, PSObject elementObject) { // We might get an empty input for a directive from the HTML file if (!string.IsNullOrEmpty(outerHtml)) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs index 8e28c630e17..f16ad99d2a1 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/ContentHelper.Common.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Linq; using System.Management.Automation; using System.Net.Http; using System.Net.Http.Headers; @@ -69,7 +68,7 @@ internal static Encoding GetEncodingOrDefault(string characterSet) internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) { - StringBuilder raw = new StringBuilder(); + StringBuilder raw = new(); string protocol = WebResponseHelper.GetProtocol(response); if (!string.IsNullOrEmpty(protocol)) @@ -83,7 +82,7 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) HttpHeaders[] headerCollections = { response.Headers, - response.Content == null ? null : response.Content.Headers + response.Content?.Headers }; foreach (var headerCollection in headerCollections) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs index 273fae835c3..8c1ec228bb4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs @@ -60,7 +60,7 @@ public SwitchParameter FollowRelLink /// [Parameter] [Alias("ML")] - [ValidateRange(1, Int32.MaxValue)] + [ValidateRange(1, int.MaxValue)] public int MaximumFollowRelLink { get { return base._maximumFollowRelLink; } @@ -110,7 +110,7 @@ private bool TryProcessFeedStream(Stream responseStream) if (isRssOrFeed) { - XmlDocument workingDocument = new XmlDocument(); + XmlDocument workingDocument = new(); // performing a Read() here to avoid rrechecking // "rss" or "feed" items reader.Read(); @@ -143,9 +143,9 @@ private bool TryProcessFeedStream(Stream responseStream) } // Mostly cribbed from Serialization.cs#GetXmlReaderSettingsForCliXml() - private XmlReaderSettings GetSecureXmlReaderSettings() + private static XmlReaderSettings GetSecureXmlReaderSettings() { - XmlReaderSettings xrs = new XmlReaderSettings(); + XmlReaderSettings xrs = new(); xrs.CheckCharacters = false; xrs.CloseInput = false; @@ -159,7 +159,7 @@ private XmlReaderSettings GetSecureXmlReaderSettings() return xrs; } - private bool TryConvertToXml(string xml, out object doc, ref Exception exRef) + private static bool TryConvertToXml(string xml, out object doc, ref Exception exRef) { try { @@ -181,7 +181,7 @@ private bool TryConvertToXml(string xml, out object doc, ref Exception exRef) return (doc != null); } - private bool TryConvertToJson(string json, out object obj, ref Exception exRef) + private static bool TryConvertToJson(string json, out object obj, ref Exception exRef) { bool converted = false; try @@ -261,9 +261,9 @@ internal BufferingStreamReader(Stream baseStream) _copyBuffer = new byte[4096]; } - private Stream _baseStream; - private MemoryStream _streamBuffer; - private byte[] _copyBuffer; + private readonly Stream _baseStream; + private readonly MemoryStream _streamBuffer; + private readonly byte[] _copyBuffer; public override bool CanRead { @@ -478,7 +478,7 @@ internal override void ProcessResponse(HttpResponseMessage response) #region Helper Methods - private RestReturnType CheckReturnType(HttpResponseMessage response) + private static RestReturnType CheckReturnType(HttpResponseMessage response) { if (response == null) { throw new ArgumentNullException(nameof(response)); } 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 74692cedc49..85860aa19e6 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 @@ -7,7 +7,6 @@ using System.Collections.ObjectModel; using System.Globalization; using System.IO; -using System.Linq; using System.Management.Automation; using System.Net; using System.Net.Http; @@ -22,8 +21,6 @@ using System.Threading.Tasks; using System.Xml; -using Microsoft.Win32; - namespace Microsoft.PowerShell.Commands { /// @@ -135,7 +132,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet public virtual SwitchParameter AllowUnencryptedAuthentication { get; set; } /// - /// Gets or sets the Authentication property used to determin the Authentication method for the web session. + /// Gets or sets the Authentication property used to determine the Authentication method for the web session. /// Authentication does not work with UseDefaultCredentials. /// Authentication over unencrypted sessions requires AllowUnencryptedAuthentication. /// Basic: Requires Credential. @@ -209,7 +206,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet /// Gets or sets the TimeOut property. /// [Parameter] - [ValidateRange(0, Int32.MaxValue)] + [ValidateRange(0, int.MaxValue)] public virtual int TimeoutSec { get; set; } /// @@ -227,7 +224,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet /// Gets or sets the RedirectMax property. /// [Parameter] - [ValidateRange(0, Int32.MaxValue)] + [ValidateRange(0, int.MaxValue)] public virtual int MaximumRedirection { get { return _maximumRedirection; } @@ -241,14 +238,14 @@ public virtual int MaximumRedirection /// Gets or sets the MaximumRetryCount property, which determines the number of retries of a failed web request. /// [Parameter] - [ValidateRange(0, Int32.MaxValue)] - public virtual int MaximumRetryCount { get; set; } = 0; + [ValidateRange(0, int.MaxValue)] + public virtual int MaximumRetryCount { get; set; } /// /// Gets or sets the RetryIntervalSec property, which determines the number seconds between retries. /// [Parameter] - [ValidateRange(1, Int32.MaxValue)] + [ValidateRange(1, int.MaxValue)] public virtual int RetryIntervalSec { get; set; } = 5; #endregion @@ -598,7 +595,7 @@ internal virtual void PrepareSession() // supplying a credential overrides the UseDefaultCredentials setting WebSession.UseDefaultCredentials = false; } - else if ((Credential != null || null != Token) && Authentication != WebAuthenticationType.None) + else if ((Credential != null || Token != null) && Authentication != WebAuthenticationType.None) { ProcessAuthentication(); } @@ -609,13 +606,13 @@ internal virtual void PrepareSession() if (CertificateThumbprint != null) { - X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); + X509Store store = new(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates; X509Certificate2Collection tbCollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByThumbprint, CertificateThumbprint, false); if (tbCollection.Count == 0) { - CryptographicException ex = new CryptographicException(WebCmdletStrings.ThumbprintNotFound); + CryptographicException ex = new(WebCmdletStrings.ThumbprintNotFound); throw ex; } @@ -642,7 +639,7 @@ internal virtual void PrepareSession() if (Proxy != null) { - WebProxy webProxy = new WebProxy(Proxy); + WebProxy webProxy = new(Proxy); webProxy.BypassProxyOnLocal = false; if (ProxyCredential != null) { @@ -658,7 +655,7 @@ internal virtual void PrepareSession() WebSession.Proxy = webProxy; } - if (-1 < MaximumRedirection) + if (MaximumRedirection > -1) { WebSession.MaximumRedirection = MaximumRedirection; } @@ -736,10 +733,10 @@ private Uri PrepareUri(Uri uri) && ((IsStandardMethodSet() && (Method == WebRequestMethod.Default || Method == WebRequestMethod.Get)) || (IsCustomMethodSet() && CustomMethod.ToUpperInvariant() == "GET"))) { - UriBuilder uriBuilder = new UriBuilder(uri); + UriBuilder uriBuilder = new(uri); if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) { - uriBuilder.Query = uriBuilder.Query.Substring(1) + "&" + FormatDictionary(bodyAsDictionary); + uriBuilder.Query = string.Concat(uriBuilder.Query.AsSpan(1), "&", FormatDictionary(bodyAsDictionary)); } else { @@ -754,7 +751,7 @@ private Uri PrepareUri(Uri uri) return uri; } - private Uri CheckProtocol(Uri uri) + private static Uri CheckProtocol(Uri uri) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } @@ -772,17 +769,17 @@ private string QualifyFilePath(string path) return resolvedFilePath; } - private string FormatDictionary(IDictionary content) + private static string FormatDictionary(IDictionary content) { if (content == null) throw new ArgumentNullException(nameof(content)); - StringBuilder bodyBuilder = new StringBuilder(); + StringBuilder bodyBuilder = new(); foreach (string key in content.Keys) { - if (0 < bodyBuilder.Length) + if (bodyBuilder.Length > 0) { - bodyBuilder.Append("&"); + bodyBuilder.Append('&'); } object value = content[key]; @@ -818,12 +815,12 @@ private ErrorRecord GetValidationError(string msg, string errorId, params object private bool IsStandardMethodSet() { - return (ParameterSetName == "StandardMethod"); + return (ParameterSetName == "StandardMethod" || ParameterSetName == "StandardMethodNoProxy"); } private bool IsCustomMethodSet() { - return (ParameterSetName == "CustomMethod"); + return (ParameterSetName == "CustomMethod" || ParameterSetName == "CustomMethodNoProxy"); } private string GetBasicAuthorizationHeader() @@ -866,7 +863,7 @@ private void ProcessAuthentication() public sealed class HttpResponseException : HttpRequestException { /// - /// Constructor for HttpResponseException. + /// Initializes a new instance of the class. /// /// Message for the exception. /// Response from the HTTP server. @@ -943,7 +940,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet /// /// Maximum number of Rel Links to follow. /// - internal int _maximumFollowRelLink = Int32.MaxValue; + internal int _maximumFollowRelLink = int.MaxValue; /// /// The remote endpoint returned a 206 status code indicating successful resume. @@ -987,7 +984,7 @@ private HttpMethod GetHttpMethod(WebRequestMethod method) internal virtual HttpClient GetHttpClient(bool handleRedirect) { // By default the HttpClientHandler will automatically decompress GZip and Deflate content - HttpClientHandler handler = new HttpClientHandler(); + HttpClientHandler handler = new(); handler.CookieContainer = WebSession.Cookies; // set the credentials used by this request @@ -1040,7 +1037,7 @@ internal virtual HttpClient GetHttpClient(bool handleRedirect) handler.SslProtocols = (SslProtocols)SslProtocol; - HttpClient httpClient = new HttpClient(handler); + HttpClient httpClient = new(handler); // check timeout setting (in seconds instead of milliseconds as in HttpWebRequest) if (TimeoutSec == 0) @@ -1287,7 +1284,7 @@ internal virtual void FillRequestStream(HttpRequestMessage request) catch (FormatException ex) { var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex); - ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); + ErrorRecord er = new(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); ThrowTerminatingError(er); } } @@ -1511,7 +1508,6 @@ protected override void ProcessRecord() string reqVerboseMsg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.WebMethodInvocationVerboseMsg, request.Method, - request.RequestUri, requestContentLength); WriteVerbose(reqVerboseMsg); @@ -1543,8 +1539,8 @@ protected override void ProcessRecord() { string message = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, (int)response.StatusCode, response.ReasonPhrase); - HttpResponseException httpEx = new HttpResponseException(message, response); - ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + HttpResponseException httpEx = new(message, response); + ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); string detailMsg = string.Empty; StreamReader reader = null; try @@ -1591,7 +1587,7 @@ protected override void ProcessRecord() response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.MovedPermanently) { - ErrorRecord er = new ErrorRecord(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request); + ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request); er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded); WriteError(er); } @@ -1599,7 +1595,7 @@ protected override void ProcessRecord() } catch (HttpRequestException ex) { - ErrorRecord er = new ErrorRecord(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); if (ex.InnerException != null) { er.ErrorDetails = new ErrorDetails(ex.InnerException.Message); @@ -1625,12 +1621,12 @@ protected override void ProcessRecord() } catch (CryptographicException ex) { - ErrorRecord er = new ErrorRecord(ex, "WebCmdletCertificateException", ErrorCategory.SecurityError, null); + ErrorRecord er = new(ex, "WebCmdletCertificateException", ErrorCategory.SecurityError, null); ThrowTerminatingError(er); } catch (NotSupportedException ex) { - ErrorRecord er = new ErrorRecord(ex, "WebCmdletIEDomNotSupportedException", ErrorCategory.NotImplemented, null); + ErrorRecord er = new(ex, "WebCmdletIEDomNotSupportedException", ErrorCategory.NotImplemented, null); ThrowTerminatingError(er); } } @@ -1710,7 +1706,7 @@ internal long SetRequestContent(HttpRequestMessage request, string content) if (!SkipHeaderValidation) { var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex); - ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); + ErrorRecord er = new(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); ThrowTerminatingError(er); } } @@ -1719,7 +1715,7 @@ internal long SetRequestContent(HttpRequestMessage request, string content) if (!SkipHeaderValidation) { var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex); - ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); + ErrorRecord er = new(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType); ThrowTerminatingError(er); } } @@ -1834,13 +1830,13 @@ internal void ParseLinkHeader(HttpResponseMessage response, System.Uri requestUr // we only support the URL in angle brackets and `rel`, other attributes are ignored // user can still parse it themselves via the Headers property - string pattern = "<(?.*?)>;\\s*rel=(\"?)(?.*?)\\1[^\\w -.]?"; + const string pattern = "<(?.*?)>;\\s*rel=(\"?)(?.*?)\\1[^\\w -.]?"; IEnumerable links; if (response.Headers.TryGetValues("Link", out links)) { foreach (string linkHeader in links) { - foreach (string link in linkHeader.Split(",")) + foreach (string link in linkHeader.Split(',')) { Match match = Regex.Match(link, pattern); if (match.Success) @@ -1849,7 +1845,7 @@ internal void ParseLinkHeader(HttpResponseMessage response, System.Uri requestUr string rel = match.Groups["rel"].Value; if (url != string.Empty && rel != string.Empty && !_relationLink.ContainsKey(rel)) { - Uri absoluteUri = new Uri(requestUri, url); + Uri absoluteUri = new(requestUri, url); _relationLink.Add(rel, absoluteUri.AbsoluteUri); } } @@ -1859,17 +1855,17 @@ internal void ParseLinkHeader(HttpResponseMessage response, System.Uri requestUr } /// - /// Adds content to a . Object type detection is used to determine if the value is string, File, or Collection. + /// Adds content to a . Object type detection is used to determine if the value is string, File, or Collection. /// /// The Field Name to use. /// The Field Value to use. - /// The > to update. - /// If true, collection types in will be enumerated. If false, collections will be treated as single value. + /// The > to update. + /// If true, collection types in will be enumerated. If false, collections will be treated as single value. private void AddMultipartContent(object fieldName, object fieldValue, MultipartFormDataContent formData, bool enumerate) { if (formData == null) { - throw new ArgumentNullException("formDate"); + throw new ArgumentNullException(nameof(formData)); } // It is possible that the dictionary keys or values are PSObject wrapped depending on how the dictionary is defined and assigned. @@ -1897,7 +1893,7 @@ private void AddMultipartContent(object fieldName, object fieldValue, MultipartF // Treat Strings and other single values as a StringContent. // If enumeration is false, also treat IEnumerables as StringContents. // String implements IEnumerable so the explicit check is required. - if (enumerate == false || fieldValue is string || !(fieldValue is IEnumerable)) + if (!enumerate || fieldValue is string || fieldValue is not IEnumerable) { formData.Add(GetMultipartStringContent(fieldName: fieldName, fieldValue: fieldValue)); return; @@ -1915,11 +1911,11 @@ private void AddMultipartContent(object fieldName, object fieldValue, MultipartF } /// - /// Gets a from the supplied field name and field value. Uses to convert the objects to strings. + /// Gets a from the supplied field name and field value. Uses to convert the objects to strings. /// - /// The Field Name to use for the - /// The Field Value to use for the - private StringContent GetMultipartStringContent(object fieldName, object fieldValue) + /// The Field Name to use for the + /// The Field Value to use for the + private static StringContent GetMultipartStringContent(object fieldName, object fieldValue) { var contentDisposition = new ContentDispositionHeaderValue("form-data"); // .NET does not enclose field names in quotes, however, modern browsers and curl do. @@ -1932,11 +1928,11 @@ private StringContent GetMultipartStringContent(object fieldName, object fieldVa } /// - /// Gets a from the supplied field name and . Uses to convert the fieldname to a string. + /// Gets a from the supplied field name and . Uses to convert the fieldname to a string. /// - /// The Field Name to use for the - /// The to use for the - private StreamContent GetMultipartStreamContent(object fieldName, Stream stream) + /// The Field Name to use for the + /// The to use for the + private static StreamContent GetMultipartStreamContent(object fieldName, Stream stream) { var contentDisposition = new ContentDispositionHeaderValue("form-data"); // .NET does not enclose field names in quotes, however, modern browsers and curl do. @@ -1950,11 +1946,11 @@ private StreamContent GetMultipartStreamContent(object fieldName, Stream stream) } /// - /// Gets a from the supplied field name and file. Calls to create the and then sets the file name. + /// Gets a from the supplied field name and file. Calls to create the and then sets the file name. /// - /// The Field Name to use for the - /// The file to use for the - private StreamContent GetMultipartFileContent(object fieldName, FileInfo file) + /// The Field Name to use for the + /// The file to use for the + private static StreamContent GetMultipartFileContent(object fieldName, FileInfo file) { var result = GetMultipartStreamContent(fieldName: fieldName, stream: new FileStream(file.FullName, FileMode.Open)); // .NET does not enclose field names in quotes, however, modern browsers and curl do. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebResponseObject.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebResponseObject.Common.cs index 70c5721dbc1..98e7c397e45 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebResponseObject.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebResponseObject.Common.cs @@ -76,7 +76,7 @@ private void InitializeContent() this.Content = this.RawContentStream.ToArray(); } - private bool IsPrintable(char c) + private static bool IsPrintable(char c) { return (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSeparator(c) || char.IsSymbol(c) || char.IsWhiteSpace(c)); } @@ -144,7 +144,7 @@ public Dictionary> Headers #region Constructors /// - /// Constructor for WebResponseObject. + /// Initializes a new instance of the class. /// /// public WebResponseObject(HttpResponseMessage response) @@ -152,7 +152,8 @@ public WebResponseObject(HttpResponseMessage response) { } /// - /// Constructor for WebResponseObject with contentStream. + /// Initializes a new instance of the class + /// with the specified . /// /// /// @@ -200,7 +201,7 @@ private void SetResponse(HttpResponseMessage response, Stream contentStream) } long contentLength = response.Content.Headers.ContentLength.Value; - if (0 >= contentLength) + if (contentLength <= 0) { contentLength = StreamHelper.DefaultReadBuffer; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertFromJsonCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertFromJsonCommand.cs index 955786248f7..0af97b061a9 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertFromJsonCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertFromJsonCommand.cs @@ -27,7 +27,7 @@ public class ConvertFromJsonCommand : Cmdlet /// /// InputObjectBuffer buffers all InputObject contents available in the pipeline. /// - private List _inputObjectBuffer = new List(); + private readonly List _inputObjectBuffer = new(); /// /// Returned data structure is a Hashtable instead a CustomPSObject. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs index 92e67f5681a..36e8acdfd6e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerShell.Commands /// This command converts an object to a Json string representation. /// [Cmdlet(VerbsData.ConvertTo, "Json", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096925", RemotingCapability = RemotingCapability.None)] - public class ConvertToJsonCommand : PSCmdlet + public class ConvertToJsonCommand : PSCmdlet, IDisposable { /// /// Gets or sets the InputObject property. @@ -29,13 +29,13 @@ public class ConvertToJsonCommand : PSCmdlet private const int maxDepthAllowed = 100; - private readonly CancellationTokenSource _cancellationSource = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancellationSource = new(); /// /// Gets or sets the Depth property. /// [Parameter] - [ValidateRange(1, int.MaxValue)] + [ValidateRange(0, int.MaxValue)] public int Depth { get { return _depth; } @@ -72,11 +72,34 @@ public int Depth /// /// Specifies how strings are escaped when writing JSON text. /// If the EscapeHandling property is set to EscapeHtml, the result JSON string will - /// be returned with HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. + /// be returned with HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. /// [Parameter] public StringEscapeHandling EscapeHandling { get; set; } = StringEscapeHandling.Default; + /// + /// IDisposable implementation, dispose of any disposable resources created by the cmdlet. + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Implementation of IDisposable for both manual Dispose() and finalizer-called disposal of resources. + /// + /// + /// Specified as true when Dispose() was called, false if this is called from the finalizer. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _cancellationSource.Dispose(); + } + } + /// /// Prerequisite checks. /// @@ -93,7 +116,7 @@ protected override void BeginProcessing() } } - private List _inputObjects = new List(); + private readonly List _inputObjects = new(); /// /// Caching the input objects for the command. @@ -116,9 +139,9 @@ protected override void EndProcessing() Depth, EnumsAsStrings.IsPresent, Compress.IsPresent, - _cancellationSource.Token, EscapeHandling, - targetCmdlet: this); + targetCmdlet: this, + _cancellationSource.Token); // null is returned only if the pipeline is stopping (e.g. ctrl+c is signaled). // in that case, we shouldn't write the null to the output pipe. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/HttpKnownHeaderNames.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/HttpKnownHeaderNames.cs index 80d07a54ddf..0acd7c33567 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/HttpKnownHeaderNames.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/HttpKnownHeaderNames.cs @@ -78,31 +78,29 @@ internal static class HttpKnownHeaderNames #endregion Known_HTTP_Header_Names - private static HashSet s_contentHeaderSet = null; + private static readonly HashSet s_contentHeaderSet; - internal static HashSet ContentHeaders + static HttpKnownHeaderNames() { - get - { - if (s_contentHeaderSet == null) - { - s_contentHeaderSet = new HashSet(StringComparer.OrdinalIgnoreCase); + // Thread-safe initialization. + s_contentHeaderSet = new HashSet(StringComparer.OrdinalIgnoreCase); - s_contentHeaderSet.Add(HttpKnownHeaderNames.Allow); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentDisposition); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentEncoding); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLanguage); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLength); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLocation); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentMD5); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentRange); - s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentType); - s_contentHeaderSet.Add(HttpKnownHeaderNames.Expires); - s_contentHeaderSet.Add(HttpKnownHeaderNames.LastModified); - } + s_contentHeaderSet.Add(HttpKnownHeaderNames.Allow); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentDisposition); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentEncoding); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLanguage); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLength); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentLocation); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentMD5); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentRange); + s_contentHeaderSet.Add(HttpKnownHeaderNames.ContentType); + s_contentHeaderSet.Add(HttpKnownHeaderNames.Expires); + s_contentHeaderSet.Add(HttpKnownHeaderNames.LastModified); + } - return s_contentHeaderSet; - } + internal static HashSet ContentHeaders + { + get => s_contentHeaderSet; } } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/InvokeWebRequestCommand.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/InvokeWebRequestCommand.CoreClr.cs index b0f849490cd..dafcf3b4295 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/InvokeWebRequestCommand.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/InvokeWebRequestCommand.CoreClr.cs @@ -18,7 +18,7 @@ public class InvokeWebRequestCommand : WebRequestPSCmdlet #region Virtual Method Overrides /// - /// Default constructor for InvokeWebRequestCommand. + /// Initializes a new instance of the class. /// public InvokeWebRequestCommand() : base() { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebProxy.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebProxy.cs index 5cb4f2b4fde..226a981f8a2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebProxy.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebProxy.cs @@ -9,7 +9,7 @@ namespace Microsoft.PowerShell.Commands internal class WebProxy : IWebProxy { private ICredentials _credentials; - private Uri _proxyAddress; + private readonly Uri _proxyAddress; internal WebProxy(Uri address) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FormObject.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FormObject.cs index ff9122dc395..b8f7d252711 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FormObject.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FormObject.cs @@ -31,7 +31,7 @@ public class FormObject public Dictionary Fields { get; } /// - /// Constructor for FormObject. + /// Initializes a new instance of the class. /// /// /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs index 2b15f150984..ff576c7e68f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs @@ -68,7 +68,7 @@ public readonly struct ConvertToJsonContext /// Indicates whether to use enum names for the JSON conversion. /// Indicates whether to get the compressed output. public ConvertToJsonContext(int maxDepth, bool enumsAsStrings, bool compressOutput) - : this(maxDepth, enumsAsStrings, compressOutput, CancellationToken.None, StringEscapeHandling.Default, targetCmdlet: null) + : this(maxDepth, enumsAsStrings, compressOutput, StringEscapeHandling.Default, targetCmdlet: null, CancellationToken.None) { } @@ -78,16 +78,16 @@ public ConvertToJsonContext(int maxDepth, bool enumsAsStrings, bool compressOutp /// The maximum depth to visit the object. /// Indicates whether to use enum names for the JSON conversion. /// Indicates whether to get the compressed output. - /// Specifies the cancellation token for cancelling the operation. /// Specifies how strings are escaped when writing JSON text. /// Specifies the cmdlet that is calling this method. + /// Specifies the cancellation token for cancelling the operation. public ConvertToJsonContext( int maxDepth, bool enumsAsStrings, bool compressOutput, - CancellationToken cancellationToken, StringEscapeHandling stringEscapeHandling, - PSCmdlet targetCmdlet) + PSCmdlet targetCmdlet, + CancellationToken cancellationToken) { this.MaxDepth = maxDepth; this.CancellationToken = cancellationToken; @@ -98,7 +98,7 @@ public ConvertToJsonContext( } } - private class DuplicateMemberHashSet : HashSet + private sealed class DuplicateMemberHashSet : HashSet { public DuplicateMemberHashSet(int capacity) : base(capacity, StringComparer.OrdinalIgnoreCase) @@ -344,7 +344,7 @@ private static ICollection PopulateFromJArray(JArray list, out ErrorReco private static Hashtable PopulateHashTableFromJDictionary(JObject entries, out ErrorRecord error) { error = null; - Hashtable result = new Hashtable(entries.Count); + Hashtable result = new(entries.Count); foreach (var entry in entries) { // Case sensitive duplicates should normally not occur since JsonConvert.DeserializeObject @@ -457,6 +457,7 @@ public static string ConvertToJson(object objectToProcess, in ConvertToJsonConte { // Pre-process the object so that it serializes the same, except that properties whose // values cannot be evaluated are treated as having the value null. + _maxDepthWarningWritten = false; object preprocessedObject = ProcessValue(objectToProcess, currentDepth: 0, in context); var jsonSettings = new JsonSerializerSettings { @@ -484,6 +485,8 @@ public static string ConvertToJson(object objectToProcess, in ConvertToJsonConte } } + private static bool _maxDepthWarningWritten; + /// /// Return an alternate representation of the specified object that serializes the same JSON, except /// that properties that cannot be evaluated are treated as having the value null. @@ -548,7 +551,7 @@ private static object ProcessValue(object obj, int currentDepth, in ConvertToJso // Win8:378368 Enums based on System.Int64 or System.UInt64 are not JSON-serializable // because JavaScript does not support the necessary precision. Type enumUnderlyingType = Enum.GetUnderlyingType(obj.GetType()); - if (enumUnderlyingType.Equals(typeof(Int64)) || enumUnderlyingType.Equals(typeof(UInt64))) + if (enumUnderlyingType.Equals(typeof(long)) || enumUnderlyingType.Equals(typeof(ulong))) { rv = obj.ToString(); } @@ -561,6 +564,16 @@ private static object ProcessValue(object obj, int currentDepth, in ConvertToJso { if (currentDepth > context.MaxDepth) { + if (!_maxDepthWarningWritten && context.Cmdlet != null) + { + _maxDepthWarningWritten = true; + string maxDepthMessage = string.Format( + CultureInfo.CurrentCulture, + WebCmdletStrings.JsonMaxDepthReached, + context.MaxDepth); + context.Cmdlet.WriteWarning(maxDepthMessage); + } + if (pso != null && pso.ImmediateBaseObjectIsEmpty) { // The obj is a pure PSObject, we convert the original PSObject to a string, @@ -620,9 +633,7 @@ private static object ProcessValue(object obj, int currentDepth, in ConvertToJso /// private static object AddPsProperties(object psObj, object obj, int depth, bool isPurePSObj, bool isCustomObj, in ConvertToJsonContext context) { - PSObject pso = psObj as PSObject; - - if (pso == null) + if (!(psObj is PSObject pso)) { return obj; } @@ -645,7 +656,7 @@ private static object AddPsProperties(object psObj, object obj, int depth, bool AppendPsProperties(pso, dict, depth, isCustomObj, in context); - if (wasDictionary == false && dict.Count == 1) + if (!wasDictionary && dict.Count == 1) { return obj; } @@ -667,6 +678,12 @@ private static object AddPsProperties(object psObj, object obj, int depth, bool /// The context for the operation. private static void AppendPsProperties(PSObject psObj, IDictionary receiver, int depth, bool isCustomObject, in ConvertToJsonContext context) { + // if the psObj is a DateTime or String type, we don't serialize any extended or adapted properties + if (psObj.BaseObject is string || psObj.BaseObject is DateTime) + { + return; + } + // serialize only Extended and Adapted properties.. PSMemberInfoCollection srcPropertiesToSearch = new PSMemberInfoIntegratingCollection(psObj, @@ -697,7 +714,7 @@ private static void AppendPsProperties(PSObject psObj, IDictionary receiver, int /// private static object ProcessDictionary(IDictionary dict, int depth, in ConvertToJsonContext context) { - Dictionary result = new Dictionary(dict.Count); + Dictionary result = new(dict.Count); foreach (DictionaryEntry entry in dict) { @@ -734,7 +751,7 @@ private static object ProcessDictionary(IDictionary dict, int depth, in ConvertT /// private static object ProcessEnumerable(IEnumerable enumerable, int depth, in ConvertToJsonContext context) { - List result = new List(); + List result = new(); foreach (object o in enumerable) { @@ -754,7 +771,7 @@ private static object ProcessEnumerable(IEnumerable enumerable, int depth, in Co /// private static object ProcessCustomObject(object o, int depth, in ConvertToJsonContext context) { - Dictionary result = new Dictionary(); + Dictionary result = new(); Type t = o.GetType(); foreach (FieldInfo info in t.GetFields(BindingFlags.Public | BindingFlags.Instance)) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/PSUserAgent.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/PSUserAgent.cs index a730c043216..2ea29e73fa3 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/PSUserAgent.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/PSUserAgent.cs @@ -131,9 +131,9 @@ internal static string PlatformName if (s_windowsUserAgent == null) { // find the version in the windows operating system description - Regex pattern = new Regex(@"\d+(\.\d+)+"); + Regex pattern = new(@"\d+(\.\d+)+"); string versionText = pattern.Match(OS).Value; - Version windowsPlatformversion = new Version(versionText); + Version windowsPlatformversion = new(versionText); s_windowsUserAgent = $"Windows NT {windowsPlatformversion.Major}.{windowsPlatformversion.Minor}"; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs index 58d63c36ca3..43b625311b9 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs @@ -24,14 +24,15 @@ internal class WebResponseContentMemoryStream : MemoryStream { #region Data - private Stream _originalStreamToProxy; + private readonly Stream _originalStreamToProxy; private bool _isInitialized = false; - private Cmdlet _ownerCmdlet; + private readonly Cmdlet _ownerCmdlet; #endregion #region Constructors /// + /// Initializes a new instance of the class. /// /// /// @@ -219,8 +220,8 @@ private void Initialize() { long totalLength = 0; byte[] buffer = new byte[StreamHelper.ChunkSize]; - ProgressRecord record = new ProgressRecord(StreamHelper.ActivityId, WebCmdletStrings.ReadResponseProgressActivity, "statusDescriptionPlaceholder"); - for (int read = 1; 0 < read; totalLength += read) + ProgressRecord record = new(StreamHelper.ActivityId, WebCmdletStrings.ReadResponseProgressActivity, "statusDescriptionPlaceholder"); + for (int read = 1; read > 0; totalLength += read) { if (_ownerCmdlet != null) { @@ -235,7 +236,7 @@ private void Initialize() read = _originalStreamToProxy.Read(buffer, 0, buffer.Length); - if (0 < read) + if (read > 0) { base.Write(buffer, 0, read); } @@ -284,7 +285,7 @@ internal static void WriteToStream(Stream input, Stream output, PSCmdlet cmdlet, Task copyTask = input.CopyToAsync(output, cancellationToken); - ProgressRecord record = new ProgressRecord( + ProgressRecord record = new( ActivityId, WebCmdletStrings.WriteRequestProgressActivity, WebCmdletStrings.WriteRequestProgressStatus); @@ -322,13 +323,13 @@ internal static void SaveStreamToFile(Stream stream, string filePath, PSCmdlet c { // If the web cmdlet should resume, append the file instead of overwriting. FileMode fileMode = cmdlet is WebRequestPSCmdlet webCmdlet && webCmdlet.ShouldResume ? FileMode.Append : FileMode.Create; - using FileStream output = new FileStream(filePath, fileMode, FileAccess.Write, FileShare.Read); + using FileStream output = new(filePath, fileMode, FileAccess.Write, FileShare.Read); WriteToStream(stream, output, cmdlet, cancellationToken); } private static string StreamToString(Stream stream, Encoding encoding) { - StringBuilder result = new StringBuilder(capacity: ChunkSize); + StringBuilder result = new(capacity: ChunkSize); Decoder decoder = encoding.GetDecoder(); int useBufferSize = 64; @@ -410,7 +411,7 @@ internal static bool TryGetEncoding(string characterSet, out Encoding encoding) return result; } - private static readonly Regex s_metaexp = new Regex( + private static readonly Regex s_metaexp = new( @"<]*charset\s*=\s*[""'\n]?(?[A-Za-z].[^\s""'\n<>]*)[\s""'\n>]", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase ); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/WebRequestSession.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/WebRequestSession.cs index a28f07c842c..ae08babe17f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/WebRequestSession.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/WebRequestSession.cs @@ -75,7 +75,7 @@ public class WebRequestSession public int RetryIntervalInSeconds { get; set; } /// - /// Construct a new instance of a WebRequestSession object. + /// Initializes a new instance of the class. /// public WebRequestSession() { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs index 6f374336da5..40c4ec63568 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs @@ -21,7 +21,7 @@ public sealed class WriteDebugCommand : PSCmdlet [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)] [AllowEmptyString] [Alias("Msg")] - public string Message { get; set; } = null; + public string Message { get; set; } /// /// This method implements the ProcessRecord method for Write-Debug command. @@ -37,7 +37,7 @@ protected override void ProcessRecord() if (mshCommandRuntime != null) { - DebugRecord record = new DebugRecord(Message); + DebugRecord record = new(Message); InvocationInfo invocationInfo = GetVariableValue(SpecialVariables.MyInvocation) as InvocationInfo; @@ -69,7 +69,7 @@ public sealed class WriteVerboseCommand : PSCmdlet [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)] [AllowEmptyString] [Alias("Msg")] - public string Message { get; set; } = null; + public string Message { get; set; } /// /// This method implements the ProcessRecord method for Write-verbose command. @@ -85,7 +85,7 @@ protected override void ProcessRecord() if (mshCommandRuntime != null) { - VerboseRecord record = new VerboseRecord(Message); + VerboseRecord record = new(Message); InvocationInfo invocationInfo = GetVariableValue(SpecialVariables.MyInvocation) as InvocationInfo; @@ -117,7 +117,7 @@ public sealed class WriteWarningCommand : PSCmdlet [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)] [AllowEmptyString] [Alias("Msg")] - public string Message { get; set; } = null; + public string Message { get; set; } /// /// This method implements the ProcessRecord method for Write-Warning command. @@ -133,7 +133,7 @@ protected override void ProcessRecord() if (mshCommandRuntime != null) { - WarningRecord record = new WarningRecord(Message); + WarningRecord record = new(Message); InvocationInfo invocationInfo = GetVariableValue(SpecialVariables.MyInvocation) as InvocationInfo; @@ -184,7 +184,7 @@ protected override void BeginProcessing() { if (tag.StartsWith("PS", StringComparison.OrdinalIgnoreCase)) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( new InvalidOperationException(StringUtil.Format(UtilityCommonStrings.PSPrefixReservedInInformationTag, tag)), "PSPrefixReservedInInformationTag", ErrorCategory.InvalidArgument, tag); ThrowTerminatingError(er); @@ -214,8 +214,8 @@ public class WriteOrThrowErrorCommand : PSCmdlet /// /// ErrorRecord.Exception -- if not specified, ErrorRecord.Exception is System.Exception. /// - [Parameter(ParameterSetName = "WithException", Mandatory = true)] - public Exception Exception { get; set; } = null; + [Parameter(Position = 0, ParameterSetName = "WithException", Mandatory = true)] + public Exception Exception { get; set; } /// /// If Exception is specified, this is ErrorRecord.ErrorDetails.Message; @@ -226,15 +226,15 @@ public class WriteOrThrowErrorCommand : PSCmdlet [AllowNull] [AllowEmptyString] [Alias("Msg")] - public string Message { get; set; } = null; + public string Message { get; set; } /// /// If Exception is specified, this is ErrorRecord.ErrorDetails.Message; /// otherwise, the Exception is System.Exception, and this is Exception.Message. /// - [Parameter(ParameterSetName = "ErrorRecord", Mandatory = true)] - public ErrorRecord ErrorRecord { get; set; } = null; - + [Parameter(Position = 0, ParameterSetName = "ErrorRecord", Mandatory = true)] + public ErrorRecord ErrorRecord { get; set; } + /// /// ErrorRecord.CategoryInfo.Category. /// @@ -254,7 +254,7 @@ public class WriteOrThrowErrorCommand : PSCmdlet /// [Parameter(ParameterSetName = "NoException")] [Parameter(ParameterSetName = "WithException")] - public object TargetObject { get; set; } = null; + public object TargetObject { get; set; } /// /// ErrorRecord.ErrorDetails.RecommendedAction. @@ -393,7 +393,7 @@ protected override void ProcessRecord() public sealed class WriteErrorCommand : WriteOrThrowErrorCommand { /// - /// Constructor. + /// Initializes a new instance of the class. /// public WriteErrorCommand() { @@ -433,7 +433,7 @@ public class WriteErrorException : SystemException { #region ctor /// - /// Constructor for class WriteErrorException. + /// Initializes a new instance of the class. /// /// Constructed object. public WriteErrorException() @@ -442,7 +442,7 @@ public WriteErrorException() } /// - /// Constructor for class WriteErrorException. + /// Initializes a new instance of the class. /// /// /// Constructed object. @@ -452,7 +452,7 @@ public WriteErrorException(string message) } /// - /// Constructor for class WriteErrorException. + /// Initializes a new instance of the class. /// /// /// @@ -466,7 +466,7 @@ public WriteErrorException(string message, #region Serialization /// - /// Serialization constructor for class WriteErrorException. + /// Initializes a new instance of the class for serialization. /// /// Serialization information. /// Streaming context. diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteAliasCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteAliasCommandBase.cs index 3dbb2e378ad..82c9c9f6557 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteAliasCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteAliasCommandBase.cs @@ -1,11 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Management.Automation; -using Dbg = System.Management.Automation; - namespace Microsoft.PowerShell.Commands { /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs index 7c2f2e44bf9..2d2009e56bc 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteConsoleCmdlet.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Management.Automation; using System.Text; @@ -19,7 +18,7 @@ public sealed class WriteHostCommand : ConsoleColorCmdlet /// [Parameter(Position = 0, ValueFromRemainingArguments = true, ValueFromPipeline = true)] [Alias("Msg", "Message")] - public object Object { get; set; } = null; + public object Object { get; set; } /// /// False to add a newline to the end of the output string, true if not. @@ -67,7 +66,7 @@ private string ProcessObject(object o) // unroll enumerables, including arrays. bool printSeparator = false; - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); foreach (object element in enumerable) { @@ -103,7 +102,7 @@ protected override void ProcessRecord() { string result = ProcessObject(Object) ?? string.Empty; - HostInformationMessage informationMessage = new HostInformationMessage(); + HostInformationMessage informationMessage = new(); informationMessage.Message = result; informationMessage.NoNewLine = NoNewline.IsPresent; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteProgressCmdlet.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteProgressCmdlet.cs index 070c1275aa8..fd5476751ad 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteProgressCmdlet.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WriteProgressCmdlet.cs @@ -4,8 +4,6 @@ using System; using System.Management.Automation; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell.Commands { /// @@ -38,8 +36,8 @@ public sealed class WriteProgressCommand : PSCmdlet /// Uniquely identifies this activity for purposes of chaining subordinate activities. /// [Parameter(Position = 2)] - [ValidateRange(0, Int32.MaxValue)] - public int Id { get; set; } = 0; + [ValidateRange(0, int.MaxValue)] + public int Id { get; set; } /// /// Percentage completion of the activity, or -1 if n/a. @@ -64,7 +62,7 @@ public sealed class WriteProgressCommand : PSCmdlet /// Identifies the parent Id of this activity, or -1 if none. /// [Parameter] - [ValidateRange(-1, Int32.MaxValue)] + [ValidateRange(-1, int.MaxValue)] public int ParentId { get; set; } = -1; /// @@ -98,7 +96,7 @@ protected override void ProcessRecord() { - ProgressRecord pr = new ProgressRecord(Id, Activity, Status); + ProgressRecord pr = new(Id, Activity, Status); pr.ParentActivityId = ParentId; pr.PercentComplete = PercentComplete; pr.SecondsRemaining = SecondsRemaining; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs index 9d4264b8b18..8db56196a68 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs @@ -32,7 +32,7 @@ public sealed class ExportClixmlCommand : PSCmdlet, IDisposable /// [Parameter] [ValidateRange(1, int.MaxValue)] - public int Depth { get; set; } = 0; + public int Depth { get; set; } /// /// Mandatory file name to write to. @@ -226,7 +226,7 @@ private void CreateFileStream() ); // create xml writer - XmlWriterSettings xmlSettings = new XmlWriterSettings(); + XmlWriterSettings xmlSettings = new(); xmlSettings.CloseOutput = true; xmlSettings.Encoding = sw.Encoding; xmlSettings.Indent = true; @@ -275,7 +275,7 @@ private void CreateFileStream() void Dispose() { - if (_disposed == false) + if (!_disposed) { CleanUp(); } @@ -388,7 +388,7 @@ public sealed class ConvertToXmlCommand : PSCmdlet, IDisposable /// [Parameter(HelpMessage = "Specifies how many levels of contained objects should be included in the XML representation")] [ValidateRange(1, int.MaxValue)] - public int Depth { get; set; } = 0; + public int Depth { get; set; } /// /// Input Object which is written to XML format. @@ -463,7 +463,7 @@ protected override void ProcessRecord() } // Loading to the XML Document _ms.Position = 0; - StreamReader read = new StreamReader(_ms); + StreamReader read = new(_ms); string data = read.ReadToEnd(); WriteObject(data); @@ -498,13 +498,13 @@ protected override void EndProcessing() if (As.Equals("Document", StringComparison.OrdinalIgnoreCase)) { // this is a trusted xml doc - the cmdlet generated the doc into a private memory stream - XmlDocument xmldoc = new XmlDocument(); + XmlDocument xmldoc = new(); xmldoc.Load(_ms); WriteObject(xmldoc); } else if (As.Equals("String", StringComparison.OrdinalIgnoreCase)) { - StreamReader read = new StreamReader(_ms); + StreamReader read = new(_ms); string data = read.ReadToEnd(); WriteObject(data); } @@ -620,7 +620,7 @@ private void CleanUp() void Dispose() { - if (_disposed == false) + if (!_disposed) { CleanUp(); } @@ -647,7 +647,7 @@ internal class ImportXmlHelper : IDisposable /// Reference to cmdlet which is using this helper class. /// private readonly PSCmdlet _cmdlet; - private bool _isLiteralPath; + private readonly bool _isLiteralPath; internal ImportXmlHelper(string fileName, PSCmdlet cmdlet, bool isLiteralPath) { @@ -719,7 +719,7 @@ private void CleanUp() /// public void Dispose() { - if (_disposed == false) + if (!_disposed) { CleanUp(); } @@ -836,7 +836,10 @@ public class SelectXmlCommand : PSCmdlet [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return Path; } + get + { + return Path; + } set { @@ -892,7 +895,7 @@ private void WriteResults(XmlNodeList foundXmlNodes, string filePath) foreach (XmlNode foundXmlNode in foundXmlNodes) { - SelectXmlInfo selectXmlInfo = new SelectXmlInfo(); + SelectXmlInfo selectXmlInfo = new(); selectXmlInfo.Node = foundXmlNode; selectXmlInfo.Pattern = XPath; selectXmlInfo.Path = filePath; @@ -968,8 +971,8 @@ private void WriteFileReadError(string filePath, Exception exception) filePath, exception.Message); - ArgumentException argumentException = new ArgumentException(errorMessage, exception); - ErrorRecord errorRecord = new ErrorRecord(argumentException, "ProcessingFile", ErrorCategory.InvalidArgument, filePath); + ArgumentException argumentException = new(errorMessage, exception); + ErrorRecord errorRecord = new(argumentException, "ProcessingFile", ErrorCategory.InvalidArgument, filePath); this.WriteError(errorRecord); } @@ -996,15 +999,15 @@ private XmlNamespaceManager AddNameSpaceTable(string parametersetname, XmlDocume catch (NullReferenceException) { string message = StringUtil.Format(UtilityCommonStrings.SearchXMLPrefixNullError); - InvalidOperationException e = new InvalidOperationException(message); - ErrorRecord er = new ErrorRecord(e, "PrefixError", ErrorCategory.InvalidOperation, namespacetable); + InvalidOperationException e = new(message); + ErrorRecord er = new(e, "PrefixError", ErrorCategory.InvalidOperation, namespacetable); WriteError(er); } catch (ArgumentNullException) { string message = StringUtil.Format(UtilityCommonStrings.SearchXMLPrefixNullError); - InvalidOperationException e = new InvalidOperationException(message); - ErrorRecord er = new ErrorRecord(e, "PrefixError", ErrorCategory.InvalidOperation, namespacetable); + InvalidOperationException e = new(message); + ErrorRecord er = new(e, "PrefixError", ErrorCategory.InvalidOperation, namespacetable); WriteError(er); } } @@ -1033,7 +1036,7 @@ protected override void ProcessRecord() (ParameterSetName.Equals("LiteralPath", StringComparison.OrdinalIgnoreCase)))) { // If any file not resolved, execution stops. this is to make consistent with select-string. - List fullresolvedPaths = new List(); + List fullresolvedPaths = new(); foreach (string fpath in Path) { if (_isLiteralPath) @@ -1049,8 +1052,8 @@ protected override void ProcessRecord() { // Cannot open File error string message = StringUtil.Format(UtilityCommonStrings.FileOpenError, provider.FullName); - InvalidOperationException e = new InvalidOperationException(message); - ErrorRecord er = new ErrorRecord(e, "ProcessingFile", ErrorCategory.InvalidOperation, fpath); + InvalidOperationException e = new(message); + ErrorRecord er = new(e, "ProcessingFile", ErrorCategory.InvalidOperation, fpath); WriteError(er); continue; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/GetTracerCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/GetTracerCommand.cs index b37f06b2b2f..491aaf85361 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/GetTracerCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/GetTracerCommand.cs @@ -51,7 +51,7 @@ public string[] Name protected override void ProcessRecord() { var sources = GetMatchingTraceSource(_names, true); - var result = sources.OrderBy(source => source.Name); + var result = sources.OrderBy(static source => source.Name); WriteObject(result, true); } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/MshHostTraceListener.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/MshHostTraceListener.cs index 60bbe552e50..357e0222b6d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/MshHostTraceListener.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/MshHostTraceListener.cs @@ -4,7 +4,6 @@ using System; using System.Management.Automation; using System.Management.Automation.Internal.Host; -using System.Security.Permissions; using System.Text; namespace Microsoft.PowerShell.Commands @@ -24,7 +23,7 @@ internal class PSHostTraceListener #region TraceListener constructors and disposer /// - /// Default constructor used if no. + /// Initializes a new instance of the class. /// internal PSHostTraceListener(PSCmdlet cmdlet) : base(string.Empty) @@ -88,7 +87,7 @@ public override void Write(string output) } } - private StringBuilder _cachedWrite = new StringBuilder(); + private readonly StringBuilder _cachedWrite = new(); /// /// Sends the given output string to the host for processing. @@ -116,6 +115,6 @@ public override void WriteLine(string output) /// /// The host interface to write the debug line to. /// - private InternalHostUserInterface _ui; + private readonly InternalHostUserInterface _ui; } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/SetTracerCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/SetTracerCommand.cs index d05a535145d..a17ee0fdbef 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/SetTracerCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/SetTracerCommand.cs @@ -34,7 +34,10 @@ public string[] Name [Parameter(Position = 1, ValueFromPipelineByPropertyName = true, ParameterSetName = "optionsSet")] public PSTraceSourceOptions Option { - get { return base.OptionsInternal; } + get + { + return base.OptionsInternal; + } set { @@ -48,7 +51,10 @@ public PSTraceSourceOptions Option [Parameter(ParameterSetName = "optionsSet")] public TraceOptions ListenerOption { - get { return base.ListenerOptionsInternal; } + get + { + return base.ListenerOptionsInternal; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceCommandBase.cs index a2e04f79ae1..9118fd773fd 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceCommandBase.cs @@ -1,13 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Management.Automation; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell.Commands { /// @@ -59,7 +56,7 @@ internal Collection GetMatchingTraceSource( { notMatched = new Collection(); - Collection results = new Collection(); + Collection results = new(); foreach (string patternToMatch in patternsToMatch) { bool matchFound = false; @@ -105,12 +102,12 @@ internal Collection GetMatchingTraceSource( !WildcardPattern.ContainsWildcardCharacters(patternToMatch)) { ItemNotFoundException itemNotFound = - new ItemNotFoundException( + new( patternToMatch, "TraceSourceNotFound", SessionStateStrings.TraceSourceNotFound); - ErrorRecord errorRecord = new ErrorRecord(itemNotFound.ErrorRecord, itemNotFound); + ErrorRecord errorRecord = new(itemNotFound.ErrorRecord, itemNotFound); WriteError(errorRecord); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs index 04e35a9018d..412f4a2d150 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs @@ -10,8 +10,6 @@ using System.Management.Automation.Runspaces; using System.Threading; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell.Commands { /// @@ -27,7 +25,7 @@ public class TraceCommandCommand : TraceListenerCommandBase, IDisposable /// This parameter specifies the current pipeline object. /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// The TraceSource parameter determines which TraceSource categories the @@ -48,7 +46,10 @@ public string[] Name [Parameter(Position = 2)] public PSTraceSourceOptions Option { - get { return base.OptionsInternal; } + get + { + return base.OptionsInternal; + } set { @@ -84,7 +85,10 @@ public PSTraceSourceOptions Option [Parameter] public TraceOptions ListenerOption { - get { return base.ListenerOptionsInternal; } + get + { + return base.ListenerOptionsInternal; + } set { @@ -540,9 +544,9 @@ private static ErrorRecord ConvertToErrorRecord(object obj) return result; } - private TraceListenerCommandBase _cmdlet; - private bool _writeError; + private readonly TraceListenerCommandBase _cmdlet; + private readonly bool _writeError; private bool _isOpen = true; - private Collection _matchingSources = new Collection(); + private readonly Collection _matchingSources = new(); } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs index 3eecdd51cba..f1e4fe2dfa0 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs @@ -10,8 +10,6 @@ using System.Management.Automation.Internal; using System.Security; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell.Commands { /// @@ -34,7 +32,10 @@ public class TraceListenerCommandBase : TraceCommandBase /// internal PSTraceSourceOptions OptionsInternal { - get { return _options; } + get + { + return _options; + } set { @@ -55,7 +56,10 @@ internal PSTraceSourceOptions OptionsInternal /// internal TraceOptions ListenerOptionsInternal { - get { return _traceOptions; } + get + { + return _traceOptions; + } set { @@ -231,7 +235,7 @@ internal void AddTraceListenersToSources(Collection matchingSourc try { - Collection resolvedPaths = new Collection(); + Collection resolvedPaths = new(); try { // Resolve the file path @@ -289,7 +293,7 @@ internal void AddTraceListenersToSources(Collection matchingSourc if (ForceWrite && System.IO.File.Exists(resolvedPath)) { // remove readonly attributes on the file - System.IO.FileInfo fInfo = new System.IO.FileInfo(resolvedPath); + System.IO.FileInfo fInfo = new(resolvedPath); if (fInfo != null) { // Save some disk write time by checking whether file is readonly.. @@ -302,13 +306,13 @@ internal void AddTraceListenersToSources(Collection matchingSourc } // Trace commands always append..So there is no need to set overwrite with force.. - FileStream fileStream = new FileStream(resolvedPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + FileStream fileStream = new(resolvedPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); FileStreams.Add(fileStream); // Open the file stream TextWriterTraceListener fileListener = - new TextWriterTraceListener(fileStream, resolvedPath); + new(fileStream, resolvedPath); fileListener.Name = FileListener; @@ -330,7 +334,7 @@ internal void AddTraceListenersToSources(Collection matchingSourc if (fileOpenError != null) { ErrorRecord errorRecord = - new ErrorRecord( + new( fileOpenError, "FileListenerPathResolutionFailed", ErrorCategory.OpenError, @@ -355,7 +359,7 @@ internal void AddTraceListenersToSources(Collection matchingSourc if (error != null) { ErrorRecord errorRecord = - new ErrorRecord( + new( error, "FileListenerPathResolutionFailed", ErrorCategory.InvalidArgument, @@ -419,7 +423,7 @@ internal static void RemoveListenersByName( { TraceListener listenerToRemove = source.Listeners[index]; - if (fileListenersOnly && !(listenerToRemove is TextWriterTraceListener)) + if (fileListenersOnly && listenerToRemove is not TextWriterTraceListener) { // Since we only want to remove file listeners, skip any that // aren't file listeners @@ -493,7 +497,7 @@ internal void TurnOnTracing(Collection matchingSources, bool preC { // Copy the listeners into a different collection - Collection listenerCollection = new Collection(); + Collection listenerCollection = new(); foreach (TraceListener listener in source.Listeners) { listenerCollection.Add(listener); @@ -597,8 +601,8 @@ protected void ClearStoredState() _storedTraceSourceState.Clear(); } - private Dictionary>> _storedTraceSourceState = - new Dictionary>>(); + private readonly Dictionary>> _storedTraceSourceState = + new(); #endregion stored state } diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/NewObjectStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/NewObjectStrings.resx index 63b4271c382..07c2a6d8c9e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/NewObjectStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/NewObjectStrings.resx @@ -144,6 +144,9 @@ Cannot create type. Only core types are supported in this language mode. + + Cannot create type. Only core types are supported in {0} language mode on a policy locked down machine. + {0} Please note that Single-Threaded Apartment is not supported in PowerShell. diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 397718a09bb..e3c64bd5ca3 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx @@ -196,7 +196,7 @@ The cmdlet cannot run because the following conflicting parameters are specified: ProxyCredential and ProxyUseDefaultCredentials. Specify either ProxyCredential or ProxyUseDefaultCredentials, then retry. - The cmdlet cannot run because the following parameter is missing: Proxy. Provide a valid proxy URI for the Proxy parameter when using the ProxyCredential or UseDefaultProxyCredentials parameters, then retry. + The cmdlet cannot run because the following parameter is missing: Proxy. Provide a valid proxy URI for the Proxy parameter when using the ProxyCredential or ProxyUseDefaultCredentials parameters, then retry. Reading web response completed. (Number of bytes read: {0}) @@ -250,7 +250,7 @@ Following rel link {0} - {0} {1} with {2}-byte payload + {0} with {1}-byte payload The remote server indicated it could not resume downloading. The local file will be overwritten. @@ -261,4 +261,7 @@ Retrying after interval of {0} seconds. Status code for previous attempt: {1} + + Resulting JSON is truncated as serialization has exceeded the set depth of {0}. + diff --git a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/ComInterfaces.cs b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/ComInterfaces.cs index 761c6f6e26f..7aa0b634474 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/ComInterfaces.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/ComInterfaces.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -19,22 +18,22 @@ internal static class ComInterfaces /// string fields at all, nothing is lost. /// [StructLayout(LayoutKind.Sequential)] - internal struct StartUpInfo + internal readonly struct StartUpInfo { - public readonly UInt32 cb; + public readonly uint cb; private readonly IntPtr lpReserved; public readonly IntPtr lpDesktop; public readonly IntPtr lpTitle; - public readonly UInt32 dwX; - public readonly UInt32 dwY; - public readonly UInt32 dwXSize; - public readonly UInt32 dwYSize; - public readonly UInt32 dwXCountChars; - public readonly UInt32 dwYCountChars; - public readonly UInt32 dwFillAttribute; - public readonly UInt32 dwFlags; - public readonly UInt16 wShowWindow; - private readonly UInt16 cbReserved2; + public readonly uint dwX; + public readonly uint dwY; + public readonly uint dwXSize; + public readonly uint dwYSize; + public readonly uint dwXCountChars; + public readonly uint dwYCountChars; + public readonly uint dwFillAttribute; + public readonly uint dwFlags; + public readonly ushort wShowWindow; + private readonly ushort cbReserved2; private readonly IntPtr lpReserved2; public readonly IntPtr hStdInput; public readonly IntPtr hStdOutput; @@ -58,6 +57,7 @@ void GetPath( uint fFlags); void GetIDList(out IntPtr ppidl); + void SetIDList(IntPtr pidl); void GetDescription( @@ -83,8 +83,11 @@ void SetArguments( [MarshalAs(UnmanagedType.LPWStr)] string pszArgs); void GetHotKey(out short wHotKey); + void SetHotKey(short wHotKey); + void GetShowCmd(out uint iShowCmd); + void SetShowCmd(uint iShowCmd); void GetIconLocation( @@ -138,7 +141,7 @@ internal interface IPropertyStore /// /// [PreserveSig] - HResult GetValue([In] ref PropertyKey key, [Out] PropVariant pv); + HResult GetValue([In] in PropertyKey key, [Out] PropVariant pv); /// /// Sets the value of a property in the store. @@ -147,7 +150,7 @@ internal interface IPropertyStore /// /// [PreserveSig] - HResult SetValue([In] ref PropertyKey key, [In] PropVariant pv); + HResult SetValue([In] in PropertyKey key, [In] PropVariant pv); /// /// Commits the changes. @@ -235,6 +238,7 @@ void AddFromArray( [MarshalAs(UnmanagedType.Interface)] IObjectArray poaSource); void RemoveObject(uint uiIndex); + void Clear(); } @@ -244,15 +248,16 @@ void AddFromArray( internal interface IShellLinkDataListW { [PreserveSig] - Int32 AddDataBlock(IntPtr pDataBlock); + int AddDataBlock(IntPtr pDataBlock); [PreserveSig] - Int32 CopyDataBlock(UInt32 dwSig, out IntPtr ppDataBlock); + int CopyDataBlock(uint dwSig, out IntPtr ppDataBlock); [PreserveSig] - Int32 RemoveDataBlock(UInt32 dwSig); + int RemoveDataBlock(uint dwSig); void GetFlags(out uint pdwFlags); + void SetFlags(uint dwFlags); } diff --git a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs index 5c76d6051b8..10db7912b4a 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs @@ -19,10 +19,10 @@ internal sealed class PropVariant : IDisposable { // This is actually a VarEnum value, but the VarEnum type requires 4 bytes instead of the expected 2. [FieldOffset(0)] - private ushort _valueType; + private readonly ushort _valueType; [FieldOffset(8)] - private IntPtr _ptr; + private readonly IntPtr _ptr; /// /// Set a string value. @@ -51,14 +51,14 @@ public void Dispose() } /// - /// Finalizer. + /// Finalizes an instance of the class. /// ~PropVariant() { Dispose(); } - private class PropVariantNativeMethods + private static class PropVariantNativeMethods { [DllImport("Ole32.dll", PreserveSig = false)] internal static extern void PropVariantClear([In, Out] PropVariant pvar); diff --git a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropertyKey.cs b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropertyKey.cs index 6e12fcb0f63..93346424dc5 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropertyKey.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropertyKey.cs @@ -10,7 +10,7 @@ namespace Microsoft.PowerShell /// Defines a unique key for a Shell Property. /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal struct PropertyKey : IEquatable + internal readonly struct PropertyKey : IEquatable { #region Public Properties /// @@ -21,7 +21,7 @@ internal struct PropertyKey : IEquatable /// /// Property identifier (PID) /// - public Int32 PropertyId { get; } + public int PropertyId { get; } #endregion @@ -32,7 +32,7 @@ internal struct PropertyKey : IEquatable /// /// A unique GUID for the property. /// Property identifier (PID). - internal PropertyKey(Guid formatId, Int32 propertyId) + internal PropertyKey(Guid formatId, int propertyId) { this.FormatId = formatId; this.PropertyId = propertyId; diff --git a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/TaskbarJumpList.cs b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/TaskbarJumpList.cs index 5b7572c94b2..90c6c811bb1 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/TaskbarJumpList.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/TaskbarJumpList.cs @@ -59,8 +59,8 @@ private static void CreateElevatedEntry(string title) // Check startupInfo first to know if the current shell is interactive and owns a window before proceeding // This check is fast (less than 1ms) and allows for quick-exit GetStartupInfo(out StartUpInfo startupInfo); - var STARTF_USESHOWWINDOW = 0x00000001; - var SW_HIDE = 0; + const uint STARTF_USESHOWWINDOW = 0x00000001; + const ushort SW_HIDE = 0; if (((startupInfo.dwFlags & STARTF_USESHOWWINDOW) == 1) && (startupInfo.wShowWindow != SW_HIDE)) { string cmdPath = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe"); @@ -97,7 +97,7 @@ private static void CreateElevatedEntry(string title) flags |= 0x00002000; // SLDF_RUNAS_USER shellLinkDataList.SetFlags(flags); var PKEY_TITLE = new PropertyKey(new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 2); - hResult = nativePropertyStore.SetValue(ref PKEY_TITLE, new PropVariant(title)); + hResult = nativePropertyStore.SetValue(in PKEY_TITLE, new PropVariant(title)); if (hResult < 0) { pCustDestList.AbortList(); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs index 55b0f1182c3..6908320db53 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs @@ -327,6 +327,7 @@ internal string? ConfigurationName AssertArgumentsParsed(); return _configurationName; } + set { if (!string.IsNullOrEmpty(value)) @@ -476,7 +477,7 @@ internal bool StaMode } else { - return true; + return Platform.IsStaSupported; } } } @@ -601,13 +602,14 @@ internal static string GetConfigurationNameFromGroupPolicy() /// private (string switchKey, bool shouldBreak) GetSwitchKey(string[] args, ref int argIndex, ref bool noexitSeen) { - string switchKey = args[argIndex].Trim().ToLowerInvariant(); + string switchKey = args[argIndex].Trim(); if (string.IsNullOrEmpty(switchKey)) { return (switchKey: string.Empty, shouldBreak: false); } - if (!CharExtensions.IsDash(switchKey[0]) && switchKey[0] != '/') + char firstChar = switchKey[0]; + if (!CharExtensions.IsDash(firstChar) && firstChar != '/') { // then it's a file --argIndex; @@ -621,7 +623,7 @@ internal static string GetConfigurationNameFromGroupPolicy() switchKey = switchKey.Substring(1); // chop off the second dash so we're agnostic wrt specifying - or -- - if (!string.IsNullOrEmpty(switchKey) && CharExtensions.IsDash(switchKey[0])) + if (!string.IsNullOrEmpty(switchKey) && CharExtensions.IsDash(firstChar) && switchKey[0] == firstChar) { switchKey = switchKey.Substring(1); } @@ -647,7 +649,7 @@ private static bool MatchSwitch(string switchKey, string match, string smallestU Dbg.Assert(match.Contains(smallestUnambiguousMatch), "sUM should be a substring of match"); return (switchKey.Length >= smallestUnambiguousMatch.Length - && match.IndexOf(switchKey, StringComparison.Ordinal) == 0); + && match.StartsWith(switchKey, StringComparison.OrdinalIgnoreCase)); } #endregion @@ -927,7 +929,7 @@ private void ParseHelper(string[] args) } else if (MatchSwitch(switchKey, "sta", "sta")) { - if (!Platform.IsWindowsDesktop) + if (!Platform.IsWindowsDesktop || !Platform.IsStaSupported) { SetCommandLineError( CommandLineParameterParserStrings.STANotImplemented); @@ -1073,10 +1075,10 @@ private void ParseExecutionPolicy(string[] args, ref int i, ref string? executio private bool ParseFile(string[] args, ref int i, bool noexitSeen) { // Try parse '$true', 'true', '$false' and 'false' values. - object ConvertToBoolIfPossible(string arg) + static object ConvertToBoolIfPossible(string arg) { // Before parsing we skip '$' if present. - return arg.Length > 0 && bool.TryParse(arg.AsSpan().Slice(arg[0] == '$' ? 1 : 0), out bool boolValue) + return arg.Length > 0 && bool.TryParse(arg.AsSpan(arg[0] == '$' ? 1 : 0), out bool boolValue) ? (object)boolValue : (object)arg; } @@ -1130,11 +1132,11 @@ object ConvertToBoolIfPossible(string arg) { if (args[i].StartsWith('-') && args[i].Length > 1) { - string param = args[i].Substring(1, args[i].Length - 1).ToLower(); + string param = args[i].Substring(1, args[i].Length - 1); StringBuilder possibleParameters = new StringBuilder(); foreach (string validParameter in s_validParameters) { - if (validParameter.Contains(param)) + if (validParameter.Contains(param, StringComparison.OrdinalIgnoreCase)) { possibleParameters.Append("\n -"); possibleParameters.Append(validParameter); @@ -1157,6 +1159,14 @@ object ConvertToBoolIfPossible(string arg) showHelp: true); return false; } +#if !UNIX + // Only do the .ps1 extension check on Windows since shebang is not supported + if (!_file.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase)) + { + SetCommandLineError(string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.InvalidFileArgumentExtension, args[i])); + return false; + } +#endif i++; @@ -1351,7 +1361,7 @@ private bool CollectArgs(string[] args, ref int i) private Serialization.DataFormat _outFormat = Serialization.DataFormat.Text; private bool _outputFormatSpecified = false; private Serialization.DataFormat _inFormat = Serialization.DataFormat.Text; - private Collection _collectedArgs = new Collection(); + private readonly Collection _collectedArgs = new Collection(); private string? _file; private string? _executionPolicy; private string? _settingsFile; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs index 26bdc72a851..88964ea7a25 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs @@ -275,13 +275,13 @@ internal struct MouseInput /// The absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member. /// Absolute data is specified as the x coordinate of the mouse; relative data is specified as the number of pixels moved. /// - internal Int32 X; + internal int X; /// /// The absolute position of the mouse, or the amount of motion since the last mouse event was generated, depending on the value of the dwFlags member. /// Absolute data is specified as the y coordinate of the mouse; relative data is specified as the number of pixels moved. /// - internal Int32 Y; + internal int Y; /// /// If dwFlags contains MOUSEEVENTF_WHEEL, then mouseData specifies the amount of wheel movement. A positive value indicates that the wheel was rotated forward, away from the user; @@ -450,7 +450,7 @@ internal enum KeyboardFlag : uint /// True if it was successful. [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); + internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); internal static void SetConsoleMode(ProcessWindowStyle style) { @@ -513,7 +513,7 @@ internal static void AddBreakHandler(BreakHandler handlerDelegate) { bool result = NativeMethods.SetConsoleCtrlHandler(handlerDelegate, true); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -533,7 +533,7 @@ internal static void RemoveBreakHandler() { bool result = NativeMethods.SetConsoleCtrlHandler(null, false); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -551,8 +551,7 @@ internal static void RemoveBreakHandler() { var handle = NativeMethods.CreateFile( "CONIN$", - (UInt32) - (NativeMethods.AccessQualifiers.GenericRead | NativeMethods.AccessQualifiers.GenericWrite), + (UInt32)(NativeMethods.AccessQualifiers.GenericRead | NativeMethods.AccessQualifiers.GenericWrite), (UInt32)NativeMethods.ShareModes.ShareRead, (IntPtr)0, (UInt32)NativeMethods.CreationDisposition.OpenExisting, @@ -661,7 +660,7 @@ internal static ConsoleModes GetMode(ConsoleHandle consoleHandle) UInt32 m = 0; bool result = NativeMethods.GetConsoleMode(consoleHandle.DangerousGetHandle(), out m); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -692,7 +691,7 @@ internal static void SetMode(ConsoleHandle consoleHandle, ConsoleModes mode) bool result = NativeMethods.SetConsoleMode(consoleHandle.DangerousGetHandle(), (DWORD)mode); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -770,7 +769,7 @@ internal static string ReadConsole( out charsReaded, ref control); keyState = control.dwControlKeyState; - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -818,7 +817,7 @@ internal static int ReadConsoleInput(ConsoleHandle consoleHandle, ref INPUT_RECO buffer, (DWORD)buffer.Length, out recordsRead); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -862,7 +861,7 @@ ref INPUT_RECORD[] buffer (DWORD)buffer.Length, out recordsRead); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -894,7 +893,7 @@ internal static int GetNumberOfConsoleInputEvents(ConsoleHandle consoleHandle) DWORD numEvents; bool result = NativeMethods.GetNumberOfConsoleInputEvents(consoleHandle.DangerousGetHandle(), out numEvents); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -924,7 +923,7 @@ internal static void FlushConsoleInputBuffer(ConsoleHandle consoleHandle) NakedWin32Handle h = consoleHandle.DangerousGetHandle(); result = NativeMethods.FlushConsoleInputBuffer(h); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -959,7 +958,7 @@ internal static CONSOLE_SCREEN_BUFFER_INFO GetConsoleScreenBufferInfo(ConsoleHan CONSOLE_SCREEN_BUFFER_INFO bufferInfo; bool result = NativeMethods.GetConsoleScreenBufferInfo(consoleHandle.DangerousGetHandle(), out bufferInfo); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -991,7 +990,7 @@ internal static void SetConsoleScreenBufferSize(ConsoleHandle consoleHandle, Siz bool result = NativeMethods.SetConsoleScreenBufferSize(consoleHandle.DangerousGetHandle(), s); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -1503,7 +1502,7 @@ private static void WriteConsoleOutputCJK(ConsoleHandle consoleHandle, Coordinat ref writeRegion); } - if (result == false) + if (!result) { // When WriteConsoleOutput fails, half bufferLimit if (bufferLimit < 2) @@ -1631,7 +1630,7 @@ private static void WriteConsoleOutputPlain(ConsoleHandle consoleHandle, Coordin bufferCoord, ref writeRegion); - if (result == false) + if (!result) { // When WriteConsoleOutput fails, half bufferLimit if (bufferLimit < 2) @@ -1959,7 +1958,7 @@ internal static void ReadConsoleOutputCJK new Coordinates(readRegion.Left, readRegion.Top), atContents, ref contents); - if (result == false) + if (!result) { // When WriteConsoleOutput fails, half bufferLimit if (bufferLimit < 2) @@ -2131,7 +2130,7 @@ private static void ReadConsoleOutputPlain bufferCoord, ref readRegion); - if (result == false) + if (!result) { // When WriteConsoleOutput fails, half bufferLimit if (bufferLimit < 2) @@ -2171,8 +2170,7 @@ private static void ReadConsoleOutputPlain { for (int c = atContentsCol; c < bufferSize.X + atContentsCol; c++, characterBufferIndex++) { - contents[r, c].Character = (char) - characterBuffer[characterBufferIndex].UnicodeChar; + contents[r, c].Character = (char)characterBuffer[characterBufferIndex].UnicodeChar; ConsoleColor fgColor, bgColor; WORDToColor(characterBuffer[characterBufferIndex].Attributes, out fgColor, @@ -2280,7 +2278,7 @@ Coordinates origin (DWORD)numberToWrite, c, out unused); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2335,7 +2333,7 @@ Coordinates origin c, out unused); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2385,7 +2383,7 @@ internal static void ScrollConsoleScreenBuffer destOrigin, ref fill); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2423,7 +2421,7 @@ internal static void SetConsoleWindowInfo(ConsoleHandle consoleHandle, bool abso bool result = NativeMethods.SetConsoleWindowInfo(consoleHandle.DangerousGetHandle(), absolute, ref windowInfo); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2477,7 +2475,7 @@ internal static Size GetLargestConsoleWindowSize(ConsoleHandle consoleHandle) internal static string GetConsoleWindowTitle() { const int MaxWindowTitleLength = 1024; - DWORD bufferSize = MaxWindowTitleLength; + const DWORD bufferSize = MaxWindowTitleLength; DWORD result; StringBuilder consoleTitle = new StringBuilder((int)bufferSize); @@ -2509,7 +2507,7 @@ internal static void SetConsoleWindowTitle(string consoleTitle) { bool result = NativeMethods.SetConsoleTitle(consoleTitle); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2602,7 +2600,7 @@ private static void WriteConsole(ConsoleHandle consoleHandle, ReadOnlySpan out charsWritten, IntPtr.Zero); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2634,7 +2632,7 @@ internal static void SetConsoleTextAttribute(ConsoleHandle consoleHandle, WORD a bool result = NativeMethods.SetConsoleTextAttribute(consoleHandle.DangerousGetHandle(), attribute); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2656,7 +2654,7 @@ internal static void SetConsoleTextAttribute(ConsoleHandle consoleHandle, WORD a // CSI params? '#' [{}pq] // XTPUSHSGR ('{'), XTPOPSGR ('}'), or their aliases ('p' and 'q') // // Where: - // params: digit+ (';' params)? + // params: digit+ ((';' | ':') params)? // CSI: C0_CSI | C1_CSI // C0_CSI: \x001b '[' // ESC '[' // C1_CSI: \x009b @@ -2701,7 +2699,7 @@ internal static int ControlSequenceLength(string str, ref int offset) { c = str[offset++]; } - while ((offset < str.Length) && (char.IsDigit(c) || c == ';')); + while ((offset < str.Length) && (char.IsDigit(c) || (c == ';') || (c == ':'))); // Finally, handle the command characters for the specific sequences we // handle: @@ -2820,40 +2818,6 @@ internal static bool IsCJKOutputCodePage(out uint codePage) #region Cursor - /// - /// Wraps Win32 SetConsoleCursorPosition. - /// - /// - /// handle for the console where cursor position is set - /// - /// - /// location to which the cursor will be set - /// - /// - /// If Win32's SetConsoleCursorPosition fails - /// - internal static void SetConsoleCursorPosition(ConsoleHandle consoleHandle, Coordinates cursorPosition) - { - Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid"); - Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed"); - - ConsoleControl.COORD c; - - c.X = (short)cursorPosition.X; - c.Y = (short)cursorPosition.Y; - - bool result = NativeMethods.SetConsoleCursorPosition(consoleHandle.DangerousGetHandle(), c); - - if (result == false) - { - int err = Marshal.GetLastWin32Error(); - - HostException e = CreateHostException(err, "SetConsoleCursorPosition", - ErrorCategory.ResourceUnavailable, ConsoleControlStrings.SetConsoleCursorPositionExceptionTemplate); - throw e; - } - } - /// /// Wraps Win32 GetConsoleCursorInfo. /// @@ -2875,7 +2839,7 @@ internal static CONSOLE_CURSOR_INFO GetConsoleCursorInfo(ConsoleHandle consoleHa bool result = NativeMethods.GetConsoleCursorInfo(consoleHandle.DangerousGetHandle(), out cursorInfo); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2896,7 +2860,7 @@ internal static CONSOLE_FONT_INFO_EX GetConsoleFontInfo(ConsoleHandle consoleHan fontInfo.cbSize = Marshal.SizeOf(fontInfo); bool result = NativeMethods.GetCurrentConsoleFontEx(consoleHandle.DangerousGetHandle(), false, ref fontInfo); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -2927,7 +2891,7 @@ internal static void SetConsoleCursorInfo(ConsoleHandle consoleHandle, CONSOLE_C bool result = NativeMethods.SetConsoleCursorInfo(consoleHandle.DangerousGetHandle(), ref cursorInfo); - if (result == false) + if (!result) { int err = Marshal.GetLastWin32Error(); @@ -3161,10 +3125,6 @@ out DWORD numberOfEventsRead [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetConsoleCtrlHandler(BreakHandler handlerRoutine, bool add); - [DllImport(PinvokeDllNames.SetConsoleCursorPositionDllName, SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SetConsoleCursorPosition(NakedWin32Handle consoleOutput, COORD cursorPosition); - [DllImport(PinvokeDllNames.SetConsoleModeDllName, SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetConsoleMode(NakedWin32Handle consoleHandle, DWORD mode); @@ -3215,7 +3175,7 @@ ref CHAR_INFO fill ); [DllImport(PinvokeDllNames.SendInputDllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern UInt32 SendInput(UInt32 inputNumbers, INPUT[] inputs, Int32 sizeOfInput); + internal static extern UInt32 SendInput(UInt32 inputNumbers, INPUT[] inputs, int sizeOfInput); // There is no GetCurrentConsoleFontEx on Core [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] @@ -3248,7 +3208,7 @@ internal enum CHAR_INFO_Attributes : uint } [TraceSourceAttribute("ConsoleControl", "Console control methods")] - private static PSTraceSource tracer = PSTraceSource.GetTracer("ConsoleControl", "Console control methods"); + private static readonly PSTraceSource tracer = PSTraceSource.GetTracer("ConsoleControl", "Console control methods"); #endif } } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index 5522f419300..c2206ac7de8 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -23,16 +23,14 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading; -using Microsoft.PowerShell.Telemetry; using Microsoft.PowerShell.Commands; - -using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; -using Dbg = System.Management.Automation.Diagnostics; -using Debugger = System.Management.Automation.Debugger; - +using Microsoft.PowerShell.Telemetry; #if LEGACYTELEMETRY using Microsoft.PowerShell.Telemetry.Internal; #endif +using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; +using Dbg = System.Management.Automation.Diagnostics; +using Debugger = System.Management.Automation.Debugger; namespace Microsoft.PowerShell { @@ -56,6 +54,10 @@ internal sealed partial class ConsoleHost internal const int ExitCodeInitFailure = 70; // Internal Software Error internal const int ExitCodeBadCommandLineParameter = 64; // Command Line Usage Error private const uint SPI_GETSCREENREADER = 0x0046; +#if UNIX + internal const string DECCKM_ON = "\x1b[?1h"; + internal const string DECCKM_OFF = "\x1b[?1l"; +#endif [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] @@ -118,7 +120,7 @@ internal static int Start(string bannerText, string helpText) { Environment.SetEnvironmentVariable("PATH", pshome); } - else if (!path.StartsWith(pshome)) + else if (!path.StartsWith(pshome, StringComparison.Ordinal)) { Environment.SetEnvironmentVariable("PATH", pshome + path); } @@ -126,7 +128,7 @@ internal static int Start(string bannerText, string helpText) try { string profileDir = Platform.CacheDirectory; -#if ! UNIX +#if !UNIX if (!Directory.Exists(profileDir)) { Directory.CreateDirectory(profileDir); @@ -191,7 +193,20 @@ internal static int Start(string bannerText, string helpText) { ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("ServerMode"); ProfileOptimization.StartProfile("StartupProfileData-ServerMode"); - System.Management.Automation.Remoting.Server.OutOfProcessMediator.Run(s_cpp.InitialCommand, s_cpp.WorkingDirectory); + System.Management.Automation.Remoting.Server.StdIOProcessMediator.Run( + initialCommand: s_cpp.InitialCommand, + workingDirectory: s_cpp.WorkingDirectory, + configurationName: null); + exitCode = 0; + } + else if (s_cpp.SSHServerMode) + { + ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("SSHServer"); + ProfileOptimization.StartProfile("StartupProfileData-SSHServerMode"); + System.Management.Automation.Remoting.Server.StdIOProcessMediator.Run( + initialCommand: s_cpp.InitialCommand, + workingDirectory: null, + configurationName: null); exitCode = 0; } else if (s_cpp.NamedPipeServerMode) @@ -199,22 +214,16 @@ internal static int Start(string bannerText, string helpText) ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("NamedPipe"); ProfileOptimization.StartProfile("StartupProfileData-NamedPipeServerMode"); System.Management.Automation.Remoting.RemoteSessionNamedPipeServer.RunServerMode( - s_cpp.ConfigurationName); - exitCode = 0; - } - else if (s_cpp.SSHServerMode) - { - ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("SSHServer"); - ProfileOptimization.StartProfile("StartupProfileData-SSHServerMode"); - System.Management.Automation.Remoting.Server.SSHProcessMediator.Run(s_cpp.InitialCommand); + configurationName: s_cpp.ConfigurationName); exitCode = 0; } else if (s_cpp.SocketServerMode) { ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("SocketServerMode"); ProfileOptimization.StartProfile("StartupProfileData-SocketServerMode"); - System.Management.Automation.Remoting.Server.HyperVSocketMediator.Run(s_cpp.InitialCommand, - s_cpp.ConfigurationName); + System.Management.Automation.Remoting.Server.HyperVSocketMediator.Run( + initialCommand: s_cpp.InitialCommand, + configurationName: s_cpp.ConfigurationName); exitCode = 0; } else @@ -226,7 +235,7 @@ internal static int Start(string bannerText, string helpText) throw hostException; } - if (s_theConsoleHost.LoadPSReadline()) + if (LoadPSReadline()) { ProfileOptimization.StartProfile("StartupProfileData-Interactive"); @@ -256,6 +265,14 @@ internal static int Start(string bannerText, string helpText) { #if LEGACYTELEMETRY TelemetryAPI.ReportExitTelemetry(s_theConsoleHost); +#endif +#if UNIX + if (s_theConsoleHost.IsInteractive && s_theConsoleHost.UI.SupportsVirtualTerminal) + { + // https://github.com/dotnet/runtime/issues/27626 leaves terminal in application mode + // for now, we explicitly emit DECRST 1 sequence + s_theConsoleHost.UI.Write(DECCKM_OFF); + } #endif s_theConsoleHost.Dispose(); } @@ -415,7 +432,7 @@ private static void SpinUpBreakHandlerThread(bool shouldEndSession) host.ShouldEndSession = shouldEndSession; } - // Creation of the tread and starting it should be an atomic operation. + // Creation of the thread and starting it should be an atomic operation. // otherwise the code in Run method can get instance of the breakhandlerThread // after it is created and before started and call join on it. This will result // in ThreadStateException. @@ -739,7 +756,7 @@ internal LocalRunspace LocalRunspace public class ConsoleColorProxy { - private ConsoleHostUserInterface _ui; + private readonly ConsoleHostUserInterface _ui; public ConsoleColorProxy(ConsoleHostUserInterface ui) { @@ -937,7 +954,7 @@ public override PSObject PrivateData get { if (ui == null) return null; - return _consoleColorProxy ?? (_consoleColorProxy = PSObject.AsPSObject(new ConsoleColorProxy(ui))); + return _consoleColorProxy ??= PSObject.AsPSObject(new ConsoleColorProxy(ui)); } } @@ -1158,6 +1175,10 @@ internal ConsoleHost() AppDomain.CurrentDomain.UnhandledException += handler; } + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Performance", + "CA1822:Mark members as static", + Justification = "Accesses instance members in preprocessor branch.")] private void BindBreakHandler() { #if UNIX @@ -1192,14 +1213,6 @@ private void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArg ui.WriteLine(); } - /// - /// Finalizes the instance. - /// - ~ConsoleHost() - { - Dispose(false); - } - /// /// Disposes of this instance, per the IDisposable pattern. /// @@ -1258,6 +1271,14 @@ private void Dispose(bool isDisposingNotFinalizing) _isDisposed = true; } + /// + /// Finalizes an instance of the class. + /// + ~ConsoleHost() + { + Dispose(false); + } + /// /// Indicates if the session should be terminated or not. Typically set by the break handler for Close, Logoff, and /// Shutdown events. Note that the only valid transition for this property is from false to true: it is not legal to @@ -1287,7 +1308,7 @@ internal bool ShouldEndSession { // If ShouldEndSession is already true, you can't set it back - Dbg.Assert(_shouldEndSession != true || value, + Dbg.Assert(!_shouldEndSession || value, "ShouldEndSession can only be set from false to true"); _shouldEndSession = value; @@ -1321,7 +1342,7 @@ internal WrappedDeserializer.DataFormat ErrorFormat // If this shell is invoked in non-interactive, error is redirected, and OutputFormat was not // specified write data in error stream in xml format assuming PowerShell->PowerShell usage. - if (!OutputFormatSpecified && IsInteractive == false && Console.IsErrorRedirected && _wasInitialCommandEncoded) + if (!OutputFormatSpecified && !IsInteractive && Console.IsErrorRedirected && _wasInitialCommandEncoded) { format = Serialization.DataFormat.XML; } @@ -1600,7 +1621,7 @@ private bool IsScreenReaderActive() return _screenReaderActive.Value; } - private bool LoadPSReadline() + private static bool LoadPSReadline() { // Don't load PSReadline if: // * we don't think the process will be interactive, e.g. -command or -file @@ -1708,7 +1729,7 @@ private void DoCreateRunspace(string initialCommand, bool skipProfiles, bool sta DoRunspaceInitialization(skipProfiles, initialCommand, configurationName, initialCommandArgs); } - private void OpenConsoleRunspace(Runspace runspace, bool staMode) + private static void OpenConsoleRunspace(Runspace runspace, bool staMode) { if (staMode && Platform.IsWindowsDesktop) { @@ -1777,7 +1798,7 @@ private void DoRunspaceInitialization(bool skipProfiles, string initialCommand, } else { - string shellId = "Microsoft.PowerShell"; + const string shellId = "Microsoft.PowerShell"; // If the system lockdown policy says "Enforce", do so. Do this after types / formatting, default functions, etc // are loaded so that they are trusted. (Validation of their signatures is done in F&O) @@ -1843,13 +1864,15 @@ private void DoRunspaceInitialization(bool skipProfiles, string initialCommand, Pipeline tempPipeline = exec.CreatePipeline(); Command c; +#if UNIX // if file doesn't have .ps1 extension, we read the contents and treat it as a script to support shebang with no .ps1 extension usage - if (!Path.GetExtension(filePath).Equals(".ps1", StringComparison.OrdinalIgnoreCase)) + if (!filePath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase)) { string script = File.ReadAllText(filePath); c = new Command(script, isScript: true, useLocalScope: false); } else +#endif { c = new Command(filePath, false, false); } @@ -1868,7 +1891,7 @@ private void DoRunspaceInitialization(bool skipProfiles, string initialCommand, // If we're not going to continue, then get the exit code out of the runspace and // and indicate that it should be returned... - if (!_noExit && !(this.Runspace is RemoteRunspace)) + if (!_noExit && this.Runspace is not RemoteRunspace) { this.Runspace.ExecutionContext.ScriptCommandProcessorShouldRethrowExit = true; } @@ -2027,7 +2050,7 @@ internal static string EscapeSingleQuotes(string str) private void WriteErrorLine(string line) { - ConsoleColor fg = ConsoleColor.Red; + const ConsoleColor fg = ConsoleColor.Red; ConsoleColor bg = UI.RawUI.BackgroundColor; UI.WriteLine(fg, bg, line); @@ -2308,7 +2331,7 @@ private void WriteDebuggerMessage(string line) /// Neither this class' instances nor its static data is threadsafe. Caller is responsible for ensuring threadsafe /// access. /// - private class InputLoop + private sealed class InputLoop { internal static void RunNewInputLoop(ConsoleHost parent, bool isNested) { @@ -2428,6 +2451,14 @@ internal void Run(bool inputLoopIsNested) while (!_parent.ShouldEndSession && !_shouldExit) { +#if !UNIX + if (ui.SupportsVirtualTerminal) + { + // need to re-enable VT mode if it was previously enabled as native commands may have turned it off + ui.TryTurnOnVtMode(); + } +#endif + try { _parent._isRunningPromptLoop = true; @@ -2471,6 +2502,14 @@ internal void Run(bool inputLoopIsNested) ui.Write(prompt); } +#if UNIX + if (c.SupportsVirtualTerminal) + { + // enable DECCKM as .NET requires cursor keys to emit VT for Console class + c.Write(DECCKM_ON); + } +#endif + previousResponseWasEmpty = false; // There could be a profile. So there could be a user defined custom readline command line = ui.ReadLineWithTabCompletion(_exec); @@ -2523,7 +2562,7 @@ internal void Run(bool inputLoopIsNested) if (inBlockMode) { s_tracer.WriteLine("adding line to block"); - inputBlock.Append("\n"); + inputBlock.Append('\n'); inputBlock.Append(line); continue; } @@ -2574,6 +2613,14 @@ e is RemoteException || } else { +#if UNIX + if (c.SupportsVirtualTerminal) + { + // disable DECCKM to standard mode as applications may not expect VT for cursor keys + c.Write(DECCKM_OFF); + } +#endif + if (_parent.IsRunningAsync && !_parent.IsNested) { _exec.ExecuteCommandAsync(line, out e, Executor.ExecutionOptions.AddOutputter | Executor.ExecutionOptions.AddToHistory); @@ -2675,7 +2722,7 @@ private bool HandleErrors(Exception e, string line, bool inBlockMode, ref String } else { - // an exception ocurred when the command was executed. Tell the user about it. + // an exception occurred when the command was executed. Tell the user about it. _parent.ReportException(e, _exec); } @@ -2728,7 +2775,7 @@ private DebuggerCommandResults ProcessDebugCommand(string cmd, out Exception e) return results ?? new DebuggerCommandResults(DebuggerResumeAction.Continue, false); } - private bool IsIncompleteParseException(Exception e) + private static bool IsIncompleteParseException(Exception e) { // Check e's type. if (e is IncompleteParseException) @@ -2743,7 +2790,7 @@ private bool IsIncompleteParseException(Exception e) return false; } - return remoteException.ErrorRecord.CategoryInfo.Reason == typeof(IncompleteParseException).Name; + return remoteException.ErrorRecord.CategoryInfo.Reason == nameof(IncompleteParseException); } private void EvaluateSuggestions(ConsoleHostUserInterface ui) @@ -2844,12 +2891,12 @@ private string EvaluateDebugPrompt() return promptString; } - private ConsoleHost _parent; - private bool _isNested; + private readonly ConsoleHost _parent; + private readonly bool _isNested; private bool _shouldExit; - private Executor _exec; - private Executor _promptExec; - private object _syncObject = new object(); + private readonly Executor _exec; + private readonly Executor _promptExec; + private readonly object _syncObject = new object(); private bool _isRunspacePushed = false; private bool _runspacePopped = false; @@ -2858,41 +2905,37 @@ private string EvaluateDebugPrompt() // threadsafety guaranteed by enclosing class - private static Stack s_instanceStack = new Stack(); + private static readonly Stack s_instanceStack = new Stack(); } [Serializable] [SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic", Justification = "This exception cannot be used outside of the console host application. It is not thrown by a library routine, only by an application.")] - private class ConsoleHostStartupException : Exception + private sealed class ConsoleHostStartupException : Exception { internal ConsoleHostStartupException() - : - base() + : base() { } internal ConsoleHostStartupException(string message) - : - base(message) + : base(message) { } - protected + private ConsoleHostStartupException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) - : - base(info, context) + : base(info, context) { } internal ConsoleHostStartupException(string message, Exception innerException) - : - base(message, innerException) + : base(message, innerException) { } } @@ -2913,16 +2956,16 @@ private class ConsoleHostStartupException : Exception // Set to Unknown so that we avoid saving/restoring the console mode if we don't have a console. private ConsoleControl.ConsoleModes _savedConsoleMode = ConsoleControl.ConsoleModes.Unknown; - private ConsoleControl.ConsoleModes _initialConsoleMode = ConsoleControl.ConsoleModes.Unknown; + private readonly ConsoleControl.ConsoleModes _initialConsoleMode = ConsoleControl.ConsoleModes.Unknown; #endif private Thread _breakHandlerThread; private bool _isDisposed; internal ConsoleHostUserInterface ui; - internal Lazy ConsoleIn { get; } = new Lazy(() => Console.In); + internal Lazy ConsoleIn { get; } = new Lazy(static () => Console.In); private string _savedWindowTitle = string.Empty; - private Version _ver = PSVersionInfo.PSVersion; + private readonly Version _ver = PSVersionInfo.PSVersion; private int _exitCodeFromRunspace; private bool _noExit = true; private bool _setShouldExitCalled; @@ -2942,7 +2985,7 @@ private class ConsoleHostStartupException : Exception private bool _shouldEndSession; private int _beginApplicationNotifyCount; - private ConsoleTextWriter _consoleWriter; + private readonly ConsoleTextWriter _consoleWriter; private WrappedSerializer _outputSerializer; private WrappedSerializer _errorSerializer; private bool _displayDebuggerBanner; @@ -2958,11 +3001,10 @@ private class ConsoleHostStartupException : Exception internal static InitialSessionState DefaultInitialSessionState; [TraceSource("ConsoleHost", "ConsoleHost subclass of S.M.A.PSHost")] - private static - PSTraceSource s_tracer = PSTraceSource.GetTracer("ConsoleHost", "ConsoleHost subclass of S.M.A.PSHost"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("ConsoleHost", "ConsoleHost subclass of S.M.A.PSHost"); [TraceSource("ConsoleHostRunspaceInit", "Initialization code for ConsoleHost's Runspace")] - private static PSTraceSource s_runspaceInitTracer = + private static readonly PSTraceSource s_runspaceInitTracer = PSTraceSource.GetTracer("ConsoleHostRunspaceInit", "Initialization code for ConsoleHost's Runspace", false); } @@ -2989,10 +3031,13 @@ internal RunspaceCreationEventArgs( } internal string InitialCommand { get; set; } + internal bool SkipProfiles { get; set; } + internal bool StaMode { get; set; } + internal string ConfigurationName { get; set; } + internal Collection InitialCommandArgs { get; set; } } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs index dbf1ec61587..41053ecea7a 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs @@ -4,18 +4,17 @@ #if !UNIX using System; -using System.Management.Automation; -using System.Management.Automation.Internal; -using System.Management.Automation.Host; using System.ComponentModel; using System.Globalization; +using System.Management.Automation; +using System.Management.Automation.Host; +using System.Management.Automation.Internal; using System.Security.Principal; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Dbg = System.Management.Automation.Diagnostics; using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; +using Dbg = System.Management.Automation.Diagnostics; using WORD = System.UInt16; -using DWORD = System.UInt32; namespace Microsoft.PowerShell { @@ -191,14 +190,15 @@ public override set { - // cursor position can't be outside the buffer area - - ConsoleControl.CONSOLE_SCREEN_BUFFER_INFO bufferInfo; - - ConsoleHandle handle = GetBufferInfo(out bufferInfo); - - CheckCoordinateWithinBuffer(ref value, ref bufferInfo, "value"); - ConsoleControl.SetConsoleCursorPosition(handle, value); + try + { + Console.SetCursorPosition(value.X, value.Y); + } + catch (ArgumentOutOfRangeException) + { + // if screen buffer has changed, we cannot set it anywhere reasonable as the screen buffer + // might change again, so we ignore this + } } } @@ -457,7 +457,7 @@ public override } // if the new size will extend past the edge of screen buffer, then move the window position to try to - // accomodate that. + // accommodate that. ConsoleControl.SMALL_RECT r = bufferInfo.WindowRect; @@ -549,7 +549,7 @@ public override /// Helper method to create and trace PipelineStoppedException. /// /// - private PipelineStoppedException NewPipelineStoppedException() + private static PipelineStoppedException NewPipelineStoppedException() { PipelineStoppedException e = new PipelineStoppedException(); return e; @@ -1299,17 +1299,16 @@ private static #endregion helpers - private ConsoleColor defaultForeground = ConsoleColor.Gray; + private readonly ConsoleColor defaultForeground = ConsoleColor.Gray; - private ConsoleColor defaultBackground = ConsoleColor.Black; + private readonly ConsoleColor defaultBackground = ConsoleColor.Black; - private ConsoleHostUserInterface parent = null; + private readonly ConsoleHostUserInterface parent = null; private ConsoleControl.KEY_EVENT_RECORD cachedKeyEvent; [TraceSourceAttribute("ConsoleHostRawUserInterface", "Console host's subclass of S.M.A.Host.RawConsole")] - private static - PSTraceSource tracer = PSTraceSource.GetTracer("ConsoleHostRawUserInterface", "Console host's subclass of S.M.A.Host.RawConsole"); + private static readonly PSTraceSource tracer = PSTraceSource.GetTracer("ConsoleHostRawUserInterface", "Console host's subclass of S.M.A.Host.RawConsole"); } } // namespace @@ -1336,7 +1335,7 @@ namespace Microsoft.PowerShell internal sealed class ConsoleHostRawUserInterface : PSHostRawUserInterface { - private ConsoleHostUserInterface _parent = null; + private readonly ConsoleHostUserInterface _parent = null; internal ConsoleHostRawUserInterface(ConsoleHostUserInterface mshConsole) : base() { @@ -1371,7 +1370,10 @@ public override Size BufferSize : new Size(Console.BufferWidth, Console.BufferHeight); } - set { Console.SetBufferSize(value.Width, value.Height); } + set + { + Console.SetBufferSize(value.Width, value.Height); + } } /// @@ -1379,7 +1381,10 @@ public override Size BufferSize /// public override Coordinates CursorPosition { - get { return new Coordinates(Console.CursorLeft, Console.CursorTop); } + get + { + return new Coordinates(Console.CursorLeft, Console.CursorTop); + } set { @@ -1477,7 +1482,10 @@ public override Size WindowSize : new Size(Console.WindowWidth, Console.WindowHeight); } - set { Console.SetWindowSize(value.Width, value.Height); } + set + { + Console.SetWindowSize(value.Width, value.Height); + } } /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostTranscript.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostTranscript.cs index fd1b91574b4..3ac758ff86c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostTranscript.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostTranscript.cs @@ -6,8 +6,6 @@ using System.Management.Automation.Host; using System.Management.Automation.Internal; -using Dbg = System.Management.Automation.Diagnostics; - namespace Microsoft.PowerShell { internal sealed partial class ConsoleHost : PSHost, IDisposable @@ -61,7 +59,7 @@ internal void StartTranscribing(string transcriptFilename, bool shouldAppend) } } */ - private string _transcriptFileName = string.Empty; + private readonly string _transcriptFileName = string.Empty; internal string StopTranscribing() { @@ -127,7 +125,6 @@ internal void WriteToTranscript(ReadOnlySpan text, bool newLine) } private StreamWriter _transcriptionWriter; - private object _transcriptionStateLock = new object(); + private readonly object _transcriptionStateLock = new object(); } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs index 2d494cf701c..ad20eadf3d8 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs @@ -42,7 +42,7 @@ internal partial class ConsoleHostUserInterface : System.Management.Automation.H /// /// This is a test hook for programmatically reading and writing ConsoleHost I/O. /// - private static PSHostUserInterface s_h = null; + private static readonly PSHostUserInterface s_h = null; /// /// Return true if the console supports a VT100 like virtual terminal. @@ -60,9 +60,41 @@ internal ConsoleHostUserInterface(ConsoleHost parent) _parent = parent; _rawui = new ConsoleHostRawUserInterface(this); + SupportsVirtualTerminal = true; + _isInteractiveTestToolListening = false; + + // check if TERM env var is set + // `dumb` means explicitly don't use VT + // `xterm-mono` and `xtermm` means support VT, but emit plaintext + switch (Environment.GetEnvironmentVariable("TERM")) + { + case "dumb": + SupportsVirtualTerminal = false; + break; + case "xterm-mono": + case "xtermm": + PSStyle.Instance.OutputRendering = OutputRendering.PlainText; + break; + default: + break; + } + + // widely supported by CLI tools via https://no-color.org/ + if (Environment.GetEnvironmentVariable("NO_COLOR") != null) + { + PSStyle.Instance.OutputRendering = OutputRendering.PlainText; + } + if (SupportsVirtualTerminal) + { + SupportsVirtualTerminal = TryTurnOnVtMode(); + } + } + + internal bool TryTurnOnVtMode() + { #if UNIX - SupportsVirtualTerminal = true; + return true; #else try { @@ -76,15 +108,16 @@ internal ConsoleHostUserInterface(ConsoleHost parent) // We only know if vt100 is supported if the previous call actually set the new flag, older // systems ignore the setting. m = ConsoleControl.GetMode(handle); - this.SupportsVirtualTerminal = (m & ConsoleControl.ConsoleModes.VirtualTerminal) != 0; + return (m & ConsoleControl.ConsoleModes.VirtualTerminal) != 0; } } catch { + // Do nothing if failed } -#endif - _isInteractiveTestToolListening = false; + return false; +#endif } /// @@ -315,7 +348,7 @@ private object ReadLineSafe(bool isSecureString, char? printToken) // Handle Ctrl-C ending input if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control)) #else - if (string.IsNullOrEmpty(key) || (char)3 == key[0]) + if (string.IsNullOrEmpty(key) || key[0] == (char)3) #endif { PipelineStoppedException e = new PipelineStoppedException(); @@ -324,7 +357,7 @@ private object ReadLineSafe(bool isSecureString, char? printToken) #if UNIX if (keyInfo.Key == ConsoleKey.Enter) #else - if ((char)13 == key[0]) + if (key[0] == (char)13) #endif { // @@ -335,7 +368,7 @@ private object ReadLineSafe(bool isSecureString, char? printToken) #if UNIX if (keyInfo.Key == ConsoleKey.Backspace) #else - if ((char)8 == key[0]) + if (key[0] == (char)8) #endif { // @@ -619,7 +652,7 @@ private void WriteToConsole(ConsoleColor foregroundColor, ConsoleColor backgroun } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConsoleOutWriteHelper(ReadOnlySpan value, bool newLine) + private static void ConsoleOutWriteHelper(ReadOnlySpan value, bool newLine) { if (newLine) { @@ -696,6 +729,7 @@ private void WriteImpl(string value, bool newLine) } TextWriter writer = Console.IsOutputRedirected ? Console.Out : _parent.ConsoleTextWriter; + value = GetOutputString(value, SupportsVirtualTerminal, Console.IsOutputRedirected); if (_parent.IsRunningAsync) { @@ -924,7 +958,7 @@ internal List WrapText(string text, int maxWidthInBufferCells) int w = maxWidthInBufferCells - cellCounter; Dbg.Assert(w < e.Current.CellCount, "width remaining should be less than size of word"); - line.Append(e.Current.Text.Substring(0, w)); + line.Append(e.Current.Text.AsSpan(0, w)); l = line.ToString(); Dbg.Assert(RawUI.LengthInBufferCells(l) == maxWidthInBufferCells, "line should exactly fit"); @@ -1179,11 +1213,17 @@ public override void WriteDebugLine(string message) } else { - // NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here... - WriteLine( - DebugForegroundColor, - DebugBackgroundColor, - StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message)); + if (SupportsVirtualTerminal) + { + WriteLine(GetFormatStyleString(FormatStyle.Debug, Console.IsOutputRedirected) + StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message) + PSStyle.Instance.Reset); + } + else + { + WriteLine( + DebugForegroundColor, + DebugBackgroundColor, + StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message)); + } } } @@ -1234,10 +1274,17 @@ public override void WriteVerboseLine(string message) } else { - WriteLine( - VerboseForegroundColor, - VerboseBackgroundColor, - StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message)); + if (SupportsVirtualTerminal) + { + WriteLine(GetFormatStyleString(FormatStyle.Verbose, Console.IsOutputRedirected) + StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message) + PSStyle.Instance.Reset); + } + else + { + WriteLine( + VerboseForegroundColor, + VerboseBackgroundColor, + StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message)); + } } } @@ -1271,45 +1318,53 @@ public override void WriteWarningLine(string message) } else { - WriteLine( - WarningForegroundColor, - WarningBackgroundColor, - StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message)); + if (SupportsVirtualTerminal) + { + WriteLine(GetFormatStyleString(FormatStyle.Warning, Console.IsOutputRedirected) + StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message) + PSStyle.Instance.Reset); + } + else + { + WriteLine( + WarningForegroundColor, + WarningBackgroundColor, + StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message)); + } } } /// /// Invoked by CommandBase.WriteProgress to display a progress record. /// - public override void WriteProgress(Int64 sourceId, ProgressRecord record) + public override void WriteProgress(long sourceId, ProgressRecord record) { - if (record == null) + Dbg.Assert(record != null, "WriteProgress called with null ProgressRecord"); + + if (Console.IsOutputRedirected) { - Dbg.Assert(false, "WriteProgress called with null ProgressRecord"); + // Do not write progress bar when the stdout is redirected. + return; } - else + + bool matchPattern; + string currentOperation = HostUtilities.RemoveIdentifierInfoFromMessage(record.CurrentOperation, out matchPattern); + if (matchPattern) { - bool matchPattern; - string currentOperation = HostUtilities.RemoveIdentifierInfoFromMessage(record.CurrentOperation, out matchPattern); - if (matchPattern) - { - record = new ProgressRecord(record) { CurrentOperation = currentOperation }; - } + record = new ProgressRecord(record) { CurrentOperation = currentOperation }; + } - // We allow only one thread at a time to update the progress state.) - if (_parent.ErrorFormat == Serialization.DataFormat.XML) - { - PSObject obj = new PSObject(); - obj.Properties.Add(new PSNoteProperty("SourceId", sourceId)); - obj.Properties.Add(new PSNoteProperty("Record", record)); - _parent.ErrorSerializer.Serialize(obj, "progress"); - } - else + // We allow only one thread at a time to update the progress state.) + if (_parent.ErrorFormat == Serialization.DataFormat.XML) + { + PSObject obj = new PSObject(); + obj.Properties.Add(new PSNoteProperty("SourceId", sourceId)); + obj.Properties.Add(new PSNoteProperty("Record", record)); + _parent.ErrorSerializer.Serialize(obj, "progress"); + } + else + { + lock (_instanceLock) { - lock (_instanceLock) - { - HandleIncomingProgressRecord(sourceId, record); - } + HandleIncomingProgressRecord(sourceId, record); } } } @@ -1334,34 +1389,45 @@ public override void WriteErrorLine(string value) else { if (writer == _parent.ConsoleTextWriter) - WriteLine(ErrorForegroundColor, ErrorBackgroundColor, value); + { + if (SupportsVirtualTerminal) + { + WriteLine(value); + } + else + { + WriteLine(ErrorForegroundColor, ErrorBackgroundColor, value); + } + } else + { Console.Error.WriteLine(value); + } } } - // Format colors public ConsoleColor FormatAccentColor { get; set; } = ConsoleColor.Green; - // Error colors public ConsoleColor ErrorAccentColor { get; set; } = ConsoleColor.Cyan; + public ConsoleColor ErrorForegroundColor { get; set; } = ConsoleColor.Red; + public ConsoleColor ErrorBackgroundColor { get; set; } = Console.BackgroundColor; - // Warning colors public ConsoleColor WarningForegroundColor { get; set; } = ConsoleColor.Yellow; + public ConsoleColor WarningBackgroundColor { get; set; } = Console.BackgroundColor; - // Debug colors public ConsoleColor DebugForegroundColor { get; set; } = ConsoleColor.Yellow; + public ConsoleColor DebugBackgroundColor { get; set; } = Console.BackgroundColor; - // Verbose colors public ConsoleColor VerboseForegroundColor { get; set; } = ConsoleColor.Yellow; + public ConsoleColor VerboseBackgroundColor { get; set; } = Console.BackgroundColor; - // Progress colors public ConsoleColor ProgressForegroundColor { get; set; } = ConsoleColor.Black; + public ConsoleColor ProgressBackgroundColor { get; set; } = ConsoleColor.Yellow; #endregion Line-oriented interaction @@ -1847,7 +1913,7 @@ private char GetCharacterUnderCursor(Coordinates cursorPosition) /// /// The string to process. /// The string with any \0 characters removed... - private string RemoveNulls(string input) + private static string RemoveNulls(string input) { if (input.Contains('\0')) { @@ -1950,8 +2016,7 @@ internal string ReadLineWithTabCompletion(Executor exec) var completionResult = commandCompletion.GetNextResult(rlResult == ReadLineResult.endedOnTab); if (completionResult != null) { - completedInput = completionInput.Substring(0, commandCompletion.ReplacementIndex) - + completionResult.CompletionText; + completedInput = string.Concat(completionInput.AsSpan(0, commandCompletion.ReplacementIndex), completionResult.CompletionText); } else { @@ -2042,26 +2107,26 @@ internal string ReadLineWithTabCompletion(Executor exec) } #if !UNIX - private void SendLeftArrows(int length) + private static void SendLeftArrows(int length) { var inputs = new ConsoleControl.INPUT[length * 2]; for (int i = 0; i < length; i++) { var down = new ConsoleControl.INPUT(); - down.Type = (UInt32)ConsoleControl.InputType.Keyboard; + down.Type = (uint)ConsoleControl.InputType.Keyboard; down.Data.Keyboard = new ConsoleControl.KeyboardInput(); - down.Data.Keyboard.Vk = (UInt16)ConsoleControl.VirtualKeyCode.Left; + down.Data.Keyboard.Vk = (ushort)ConsoleControl.VirtualKeyCode.Left; down.Data.Keyboard.Scan = 0; down.Data.Keyboard.Flags = 0; down.Data.Keyboard.Time = 0; down.Data.Keyboard.ExtraInfo = IntPtr.Zero; var up = new ConsoleControl.INPUT(); - up.Type = (UInt32)ConsoleControl.InputType.Keyboard; + up.Type = (uint)ConsoleControl.InputType.Keyboard; up.Data.Keyboard = new ConsoleControl.KeyboardInput(); - up.Data.Keyboard.Vk = (UInt16)ConsoleControl.VirtualKeyCode.Left; + up.Data.Keyboard.Vk = (ushort)ConsoleControl.VirtualKeyCode.Left; up.Data.Keyboard.Scan = 0; - up.Data.Keyboard.Flags = (UInt32)ConsoleControl.KeyboardFlag.KeyUp; + up.Data.Keyboard.Flags = (uint)ConsoleControl.KeyboardFlag.KeyUp; up.Data.Keyboard.Time = 0; up.Data.Keyboard.ExtraInfo = IntPtr.Zero; @@ -2158,7 +2223,7 @@ private bool TryInvokeUserDefinedReadLine(out string input) // used to serialize access to instance data - private object _instanceLock = new object(); + private readonly object _instanceLock = new object(); // If this is true, class throws on read or prompt method which require // access to console. @@ -2182,16 +2247,14 @@ internal void HandleThrowOnReadAndPrompt() // this is a test hook for the ConsoleInteractiveTestTool, which sets this field to true. - private bool _isInteractiveTestToolListening; + private readonly bool _isInteractiveTestToolListening; // This instance data is "read-only" and need not have access serialized. - private ConsoleHostRawUserInterface _rawui; - private ConsoleHost _parent; + private readonly ConsoleHostRawUserInterface _rawui; + private readonly ConsoleHost _parent; [TraceSourceAttribute("ConsoleHostUserInterface", "Console host's subclass of S.M.A.Host.Console")] - private static - PSTraceSource s_tracer = PSTraceSource.GetTracer("ConsoleHostUserInterface", "Console host's subclass of S.M.A.Host.Console"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("ConsoleHostUserInterface", "Console host's subclass of S.M.A.Host.Console"); } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceProgress.cs index 75954bddca8..ff0117c6e99 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceProgress.cs @@ -47,6 +47,13 @@ class ConsoleHostUserInterface : System.Management.Automation.Host.PSHostUserInt } _pendingProgress = null; + + if (SupportsVirtualTerminal && PSStyle.Instance.Progress.UseOSCIndicator) + { + // OSC sequence to turn off progress indicator + // https://github.com/microsoft/terminal/issues/6700 + Console.Write("\x1b]9;4;0\x1b\\"); + } } } @@ -56,7 +63,7 @@ class ConsoleHostUserInterface : System.Management.Automation.Host.PSHostUserInt /// private void - HandleIncomingProgressRecord(Int64 sourceId, ProgressRecord record) + HandleIncomingProgressRecord(long sourceId, ProgressRecord record) { Dbg.Assert(record != null, "record should not be null"); @@ -92,6 +99,27 @@ class ConsoleHostUserInterface : System.Management.Automation.Host.PSHostUserInt { // Update the progress pane only when the timer set up the update flag or WriteProgress is completed. // As a result, we do not block WriteProgress and whole script and eliminate unnecessary console locks and updates. + if (SupportsVirtualTerminal && PSStyle.Instance.Progress.UseOSCIndicator) + { + int percentComplete = record.PercentComplete; + if (percentComplete < 0) + { + // Write-Progress allows for negative percent complete, but not greater than 100 + // but OSC sequence is limited from 0 to 100. + percentComplete = 0; + } + + // OSC sequence to turn on progress indicator + // https://github.com/microsoft/terminal/issues/6700 + Console.Write($"\x1b]9;4;1;{percentComplete}\x1b\\"); + } + + // If VT is not supported, we change ProgressView to classic + if (!SupportsVirtualTerminal) + { + PSStyle.Instance.Progress.View = ProgressView.Classic; + } + _progPane.Show(_pendingProgress); } } @@ -195,4 +223,3 @@ class ConsoleHostUserInterface : System.Management.Automation.Host.PSHostUserInt private int progPaneUpdateFlag = 0; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePrompt.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePrompt.cs index cd7c7c90e67..6d7caefec36 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePrompt.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePrompt.cs @@ -147,8 +147,6 @@ public override string fieldPrompt = null; fieldPrompt = desc.Name; - bool fieldEchoOnPrompt = true; - // FieldDescription.ParameterAssemblyFullName never returns null. But this is // defense in depth. if (string.IsNullOrEmpty(desc.ParameterAssemblyFullName)) @@ -201,18 +199,28 @@ public override StringBuilder fieldPromptList = new StringBuilder(fieldPrompt); // fieldPromptList = fieldPrompt + "[i] :" - fieldPromptList.Append("["); + fieldPromptList.Append('['); while (true) { fieldPromptList.Append( string.Format(CultureInfo.InvariantCulture, "{0}]: ", inputList.Count)); - bool inputListEnd = false; + bool endListInput = false; object convertedObj = null; - string inputString = PromptForSingleItem(elementType, fieldPromptList.ToString(), fieldPrompt, caption, message, - desc, fieldEchoOnPrompt, true, out inputListEnd, out cancelInput, out convertedObj); - - if (cancelInput || inputListEnd) + _ = PromptForSingleItem( + elementType, + fieldPromptList.ToString(), + fieldPrompt, + caption, + message, + desc, + fieldEchoOnPrompt: true, + listInput: true, + out endListInput, + out cancelInput, + out convertedObj); + + if (cancelInput || endListInput) { break; } @@ -243,10 +251,20 @@ public override fieldPrompt); // field is not a list object convertedObj = null; - bool dummy = false; - PromptForSingleItem(fieldType, printFieldPrompt, fieldPrompt, caption, message, desc, - fieldEchoOnPrompt, false, out dummy, out cancelInput, out convertedObj); + _ = PromptForSingleItem( + fieldType, + printFieldPrompt, + fieldPrompt, + caption, + message, + desc, + fieldEchoOnPrompt: true, + listInput: false, + endListInput: out _, + out cancelInput, + out convertedObj); + if (!cancelInput) { inputPSObject = PSObject.AsPSObject(convertedObj); @@ -542,4 +560,3 @@ private void ReportUnrecognizedPromptCommand(string command) private const string PromptCommandPrefix = "!"; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs index b22845c2d56..872aaa19a9c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs @@ -9,10 +9,7 @@ using System.Management.Automation.Host; using System.Management.Automation.Internal; using System.Text; - using Dbg = System.Management.Automation.Diagnostics; -using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; -using NakedWin32Handle = System.IntPtr; namespace Microsoft.PowerShell { @@ -255,7 +252,7 @@ public Collection PromptForChoice(string caption, // choices to be picked. // user did not pick up any choices..choose the default - if ((result.Count == 0) && (defaultChoiceKeys.Keys.Count >= 0)) + if (result.Count == 0) { // if there's a default, pick that one. foreach (int defaultChoice in defaultChoiceKeys.Keys) @@ -300,7 +297,7 @@ private void WriteChoicePrompt(string[,] hotkeysAndPlainLabels, int lineLenMax = RawUI.WindowSize.Width - 1; int lineLen = 0; - string choiceTemplate = "[{0}] {1} "; + const string choiceTemplate = "[{0}] {1} "; for (int i = 0; i < hotkeysAndPlainLabels.GetLength(1); ++i) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs index 7f34c789fc7..1e934553f18 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; -using System.Globalization; using System.Management.Automation; using System.Management.Automation.Internal; using System.Security; -using Microsoft.Win32; - namespace Microsoft.PowerShell { /// @@ -101,17 +97,26 @@ public override PSCredential PromptForCredential( passwordPrompt = StringUtil.Format(ConsoleHostUserInterfaceSecurityResources.PromptForCredential_Password, userName ); - // - // now, prompt for the password - // - WriteToConsole(passwordPrompt, true); - password = ReadLineAsSecureString(); - if (password == null) + if (!InternalTestHooks.NoPromptForPassword) + { + WriteToConsole(passwordPrompt, transcribeResult: true); + password = ReadLineAsSecureString(); + if (password == null) + { + return null; + } + + WriteLineToConsole(); + } + else { - return null; + password = new SecureString(); } - WriteLineToConsole(); + if (!string.IsNullOrEmpty(targetName)) + { + userName = StringUtil.Format("{0}\\{1}", targetName, userName); + } cred = new PSCredential(userName, password); @@ -119,4 +124,3 @@ public override PSCredential PromptForCredential( } } } - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs index c875bc0c506..97a02cb7123 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs @@ -4,12 +4,7 @@ using System; using System.IO; using System.Text; - -using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; using Dbg = System.Management.Automation.Diagnostics; -using DWORD = System.UInt32; -using HRESULT = System.UInt32; -using NakedWin32Handle = System.IntPtr; namespace Microsoft.PowerShell { @@ -18,8 +13,7 @@ class ConsoleTextWriter : TextWriter { internal ConsoleTextWriter(ConsoleHostUserInterface ui) - : - base(System.Globalization.CultureInfo.CurrentCulture) + : base(System.Globalization.CultureInfo.CurrentCulture) { Dbg.Assert(ui != null, "ui needs a value"); @@ -93,6 +87,6 @@ public override _ui.WriteToConsole(a, transcribeResult: true); } - private ConsoleHostUserInterface _ui; + private readonly ConsoleHostUserInterface _ui; } } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Executor.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Executor.cs index e5b3ba9f41d..25eca0d5fd6 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Executor.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Executor.cs @@ -2,12 +2,10 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Management.Automation; -using System.Management.Automation.Language; using System.Management.Automation.Runspaces; using Dbg = System.Management.Automation.Diagnostics; @@ -126,7 +124,7 @@ private void AsyncPipelineFailureHandler(Exception ex) _parent.ErrorSerializer.Serialize(er); } - private class PipelineFinishedWaitHandle + private sealed class PipelineFinishedWaitHandle { internal PipelineFinishedWaitHandle(Pipeline p) { @@ -149,7 +147,7 @@ private void PipelineStateChangedHandler(object sender, PipelineStateEventArgs e } } - private System.Threading.ManualResetEvent _eventHandle = new System.Threading.ManualResetEvent(false); + private readonly System.Threading.ManualResetEvent _eventHandle = new System.Threading.ManualResetEvent(false); } internal void ExecuteCommandAsync(string command, out Exception exceptionThrown, ExecutionOptions options) @@ -323,28 +321,12 @@ internal Collection ExecuteCommand(string command, out Exception excep { Dbg.Assert(!string.IsNullOrEmpty(command), "command should have a value"); - // Experimental: - // Check for implicit remoting commands that can be batched, and execute as batched if able. - if (ExperimentalFeature.IsEnabled("PSImplicitRemotingBatching")) - { - var addOutputter = ((options & ExecutionOptions.AddOutputter) > 0); - if (addOutputter && - !_parent.RunspaceRef.IsRunspaceOverridden && - _parent.RunspaceRef.Runspace.ExecutionContext.Modules != null && - _parent.RunspaceRef.Runspace.ExecutionContext.Modules.IsImplicitRemotingModuleLoaded && - Utils.TryRunAsImplicitBatch(command, _parent.RunspaceRef.Runspace)) - { - exceptionThrown = null; - return null; - } - } - Pipeline tempPipeline = CreatePipeline(command, (options & ExecutionOptions.AddToHistory) > 0); return ExecuteCommandHelper(tempPipeline, out exceptionThrown, options); } - private Command GetOutDefaultCommand(bool endOfStatement) + private static Command GetOutDefaultCommand(bool endOfStatement) { return new Command(command: "Out-Default", isScript: false, @@ -729,14 +711,13 @@ internal static void CancelCurrentExecutor() // to currentExecutor is guarded by staticStateLock, and static initializers are run by the CLR at program init time. private static Executor s_currentExecutor; - private static object s_staticStateLock = new object(); + private static readonly object s_staticStateLock = new object(); - private ConsoleHost _parent; + private readonly ConsoleHost _parent; private Pipeline _pipeline; private bool _cancelled; internal bool useNestedPipelines; - private object _instanceStateLock = new object(); - private bool _isPromptFunctionExecutor; + private readonly object _instanceStateLock = new object(); + private readonly bool _isPromptFunctionExecutor; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs index d0ee497307a..6dbc21ab242 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs @@ -33,7 +33,7 @@ public sealed class UnmanagedPSEntry /// Length of the passed in argument array. /// [Obsolete("Callers should now use UnmanagedPSEntry.Start(string[], int)", error: true)] - public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]string[] args, int argc) + public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] args, int argc) { return Start(args, argc); } @@ -47,7 +47,7 @@ public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray /// /// Length of the passed in argument array. /// - public static int Start([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)]string[] args, int argc) + public static int Start([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] args, int argc) { if (args == null) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index 153f99b1b20..6bb85c64729 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -43,7 +43,7 @@ class PendingProgress /// internal void - Update(Int64 sourceId, ProgressRecord record) + Update(long sourceId, ProgressRecord record) { Dbg.Assert(record != null, "record should not be null"); @@ -265,8 +265,7 @@ class PendingProgress #endif } - private - class FindOldestNodeVisitor : NodeVisitor + private sealed class FindOldestNodeVisitor : NodeVisitor { internal override bool @@ -298,6 +297,10 @@ internal override private int _oldestSoFar; } + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Performance", + "CA1822:Mark members as static", + Justification = "Accesses instance members in preprocessor branch.")] private ProgressNode FindOldestLeafmostNodeHelper(ArrayList treeToSearch, out ArrayList listWhereFound, out int indexWhereFound) @@ -354,7 +357,7 @@ internal override /// private ProgressNode - FindNodeById(Int64 sourceId, int activityId) + FindNodeById(long sourceId, int activityId) { ArrayList listWhereFound = null; int indexWhereFound = -1; @@ -362,11 +365,10 @@ internal override FindNodeById(sourceId, activityId, out listWhereFound, out indexWhereFound); } - private - class FindByIdNodeVisitor : NodeVisitor + private sealed class FindByIdNodeVisitor : NodeVisitor { internal - FindByIdNodeVisitor(Int64 sourceIdToFind, int activityIdToFind) + FindByIdNodeVisitor(long sourceIdToFind, int activityIdToFind) { _sourceIdToFind = sourceIdToFind; _idToFind = activityIdToFind; @@ -399,8 +401,8 @@ internal override int IndexWhereFound = -1; - private int _idToFind = -1; - private Int64 _sourceIdToFind; + private readonly int _idToFind = -1; + private readonly long _sourceIdToFind; } /// @@ -424,7 +426,7 @@ internal override /// private ProgressNode - FindNodeById(Int64 sourceId, int activityId, out ArrayList listWhereFound, out int indexWhereFound) + FindNodeById(long sourceId, int activityId, out ArrayList listWhereFound, out int indexWhereFound) { listWhereFound = null; indexWhereFound = -1; @@ -504,15 +506,18 @@ internal override return found; } - private - class AgeAndResetStyleVisitor : NodeVisitor + private sealed class AgeAndResetStyleVisitor : NodeVisitor { internal override bool Visit(ProgressNode node, ArrayList unused, int unusedToo) { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); - node.Style = ProgressNode.RenderStyle.FullPlus; + + node.Style = ProgressNode.IsMinimalProgressRenderingEnabled() + ? ProgressNode.RenderStyle.Ansi + : node.Style = ProgressNode.RenderStyle.FullPlus; + return true; } } @@ -578,6 +583,13 @@ internal override } ArrayList result = new ArrayList(); + + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + RenderHelper(result, _topLevelNodes, indentation: 0, maxWidth, rawUI); + return (string[])result.ToArray(typeof(string)); + } + string border = StringUtil.Padding(maxWidth); result.Add(border); @@ -651,8 +663,7 @@ internal override } } - private - class HeightTallyer : NodeVisitor + private sealed class HeightTallyer : NodeVisitor { internal HeightTallyer(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { @@ -676,9 +687,9 @@ internal override return true; } - private PSHostRawUserInterface _rawUi; - private int _maxHeight; - private int _maxWidth; + private readonly PSHostRawUserInterface _rawUi; + private readonly int _maxHeight; + private readonly int _maxWidth; internal int Tally; } @@ -821,11 +832,9 @@ internal override { nodesCompressed = 0; - int age = 0; - while (true) { - ProgressNode node = FindOldestNodeOfGivenStyle(_topLevelNodes, age, priorStyle); + ProgressNode node = FindOldestNodeOfGivenStyle(_topLevelNodes, oldestSoFar: 0, priorStyle); if (node == null) { // We've compressed every node of the prior style already. @@ -1000,10 +1009,9 @@ internal static #endregion - private ArrayList _topLevelNodes = new ArrayList(); + private readonly ArrayList _topLevelNodes = new ArrayList(); private int _nodeCount; private const int maxNodeCount = 128; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 92fc1316240..c8f542052a1 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -6,6 +6,9 @@ using System.Management.Automation; using System.Management.Automation.Host; using System.Management.Automation.Internal; +using System.Text; + +using Microsoft.PowerShell.Commands.Internal.Format; using Dbg = System.Management.Automation.Diagnostics; @@ -20,7 +23,7 @@ namespace Microsoft.PowerShell ProgressNode : ProgressRecord { /// - /// Indicates the various layouts for rendering a particular node. Each style is progressively less terse. + /// Indicates the various layouts for rendering a particular node. /// internal enum @@ -40,15 +43,19 @@ namespace Microsoft.PowerShell /// The node will be displayed the same as Full, plus, the whole StatusDescription and CurrentOperation will be displayed (in multiple lines if needed). /// FullPlus = 4, - }; + + /// + /// The node will be displayed using ANSI escape sequences. + /// + Ansi = 5, + } /// /// Constructs an instance from a ProgressRecord. /// internal - ProgressNode(Int64 sourceId, ProgressRecord record) - : - base(record.ActivityId, record.Activity, record.StatusDescription) + ProgressNode(long sourceId, ProgressRecord record) + : base(record.ActivityId, record.Activity, record.StatusDescription) { Dbg.Assert(record.RecordType == ProgressRecordType.Processing, "should only create node for Processing records"); @@ -57,7 +64,11 @@ namespace Microsoft.PowerShell this.PercentComplete = Math.Min(record.PercentComplete, 100); this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - this.Style = RenderStyle.FullPlus; + + this.Style = IsMinimalProgressRenderingEnabled() + ? RenderStyle.Ansi + : this.Style = RenderStyle.FullPlus; + this.SourceId = sourceId; } @@ -99,6 +110,9 @@ namespace Microsoft.PowerShell case RenderStyle.Minimal: RenderMinimal(strCollection, indentation, maxWidth, rawUI); break; + case RenderStyle.Ansi: + RenderAnsi(strCollection, indentation, maxWidth); + break; case RenderStyle.Invisible: // do nothing break; @@ -337,6 +351,108 @@ private static void RenderFullDescription(string description, string indent, int maxWidth)); } + internal static bool IsMinimalProgressRenderingEnabled() + { + return PSStyle.Instance.Progress.View == ProgressView.Minimal; + } + + /// + /// Renders a node in the "ANSI" style. + /// + /// + /// List of strings to which the node's rendering will be appended. + /// + /// + /// The indentation level in chars at which the node should be rendered. + /// + /// + /// The maximum number of chars that the rendering is allowed to consume. + /// + private + void + RenderAnsi(ArrayList strCollection, int indentation, int maxWidth) + { + string indent = StringUtil.Padding(indentation); + string secRemain = string.Empty; + if (SecondsRemaining >= 0) + { + secRemain = SecondsRemaining.ToString() + "s"; + } + + int secRemainLength = secRemain.Length + 1; + + // limit progress bar to 120 chars as no need to render full width + if (PSStyle.Instance.Progress.MaxWidth > 0 && maxWidth > PSStyle.Instance.Progress.MaxWidth) + { + maxWidth = PSStyle.Instance.Progress.MaxWidth; + } + + // if the activity is really long, only use up to half the width + string activity; + if (Activity.Length > maxWidth / 2) + { + activity = Activity.Substring(0, maxWidth / 2) + PSObjectHelper.Ellipsis; + } + else + { + activity = Activity; + } + + // 4 is for the extra space and square brackets below and one extra space + int barWidth = maxWidth - activity.Length - indentation - 4; + + var sb = new StringBuilder(); + int padding = maxWidth + PSStyle.Instance.Progress.Style.Length + PSStyle.Instance.Reverse.Length + PSStyle.Instance.ReverseOff.Length; + sb.Append(PSStyle.Instance.Reverse); + + int maxStatusLength = barWidth - secRemainLength - 1; + if (maxStatusLength > 0 && StatusDescription.Length > barWidth - secRemainLength) + { + sb.Append(StatusDescription.AsSpan(0, barWidth - secRemainLength - 1)); + sb.Append(PSObjectHelper.Ellipsis); + } + else + { + sb.Append(StatusDescription); + } + + int emptyPadLength = barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength; + if (emptyPadLength > 0) + { + sb.Append(string.Empty.PadRight(emptyPadLength)); + } + + sb.Append(secRemain); + + if (PercentComplete > 0 && PercentComplete < 100 && barWidth > 0) + { + int barLength = PercentComplete * barWidth / 100; + if (barLength >= barWidth) + { + barLength = barWidth - 1; + } + + if (barLength < sb.Length) + { + sb.Insert(barLength + PSStyle.Instance.Reverse.Length, PSStyle.Instance.ReverseOff); + } + } + else + { + sb.Append(PSStyle.Instance.ReverseOff); + } + + strCollection.Add( + StringUtil.Format( + "{0}{1}{2} [{3}]{4}", + indent, + PSStyle.Instance.Progress.Style, + activity, + sb.ToString(), + PSStyle.Instance.Reset) + .PadRight(padding)); + } + /// /// The nodes that have this node as their parent. /// @@ -369,7 +485,7 @@ private static void RenderFullDescription(string description, string indent, int /// Identifies the source of the progress record. /// internal - Int64 + long SourceId; /// @@ -397,6 +513,9 @@ internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth) case RenderStyle.Invisible: return 0; + case RenderStyle.Ansi: + return 1; + default: Dbg.Assert(false, "Unknown RenderStyle value"); break; @@ -490,4 +609,3 @@ private int LinesRequiredInFullStyleMethod(PSHostRawUserInterface rawUi, int max } } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index f65beebd542..a3be724b7c4 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Management.Automation; using System.Management.Automation.Host; using Dbg = System.Management.Automation.Diagnostics; @@ -70,65 +71,89 @@ class ProgressPane int rows = tempProgressRegion.GetLength(0); int cols = tempProgressRegion.GetLength(1); + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + rows = _content.Length; + cols = PSStyle.Instance.Progress.MaxWidth; + if (cols > _bufSize.Width) + { + cols = _bufSize.Width; + } + } + _savedCursor = _rawui.CursorPosition; _location.X = 0; -#if UNIX - _location.Y = _rawui.CursorPosition.Y; - - // if cursor is not on left edge already move down one line - if (_rawui.CursorPosition.X != 0) + if (!Platform.IsWindows || ProgressNode.IsMinimalProgressRenderingEnabled()) { - _location.Y++; - _rawui.CursorPosition = _location; - } + _location.Y = _rawui.CursorPosition.Y; - // if the cursor is at the bottom, create screen buffer space by scrolling - int scrollRows = rows - ((_rawui.BufferSize.Height - 1) - _location.Y); - if (scrollRows > 0) - { - // Scroll the console screen up by 'scrollRows' - var bottomLocation = _location; - bottomLocation.Y = _rawui.BufferSize.Height; - _rawui.CursorPosition = bottomLocation; - for (int i = 0; i < scrollRows; i++) + // if cursor is not on left edge already move down one line + if (_rawui.CursorPosition.X != 0) { - Console.Out.Write('\n'); + _location.Y++; + _rawui.CursorPosition = _location; } - _location.Y -= scrollRows; - _savedCursor.Y -= scrollRows; - } + // if the cursor is at the bottom, create screen buffer space by scrolling + int scrollRows = rows - ((_rawui.BufferSize.Height - 1) - _location.Y); + if (scrollRows > 0) + { + // Scroll the console screen up by 'scrollRows' + var bottomLocation = _location; + bottomLocation.Y = _rawui.BufferSize.Height - 1; + + _rawui.CursorPosition = bottomLocation; + for (int i = 0; i < scrollRows; i++) + { + Console.Out.Write('\n'); + } + + _location.Y -= scrollRows; + _savedCursor.Y -= scrollRows; + } - // create cleared region to clear progress bar later - _savedRegion = tempProgressRegion; - for(int row = 0; row < rows; row++) - { - for(int col = 0; col < cols; col++) + // create cleared region to clear progress bar later + _savedRegion = tempProgressRegion; + if (PSStyle.Instance.Progress.View != ProgressView.Minimal) { - _savedRegion[row, col].Character = ' '; + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + _savedRegion[row, col].Character = ' '; + } + } } - } - // put cursor back to where output should be - _rawui.CursorPosition = _location; -#else - _location = _rawui.WindowPosition; + // put cursor back to where output should be + _rawui.CursorPosition = _location; + } + else + { + _location = _rawui.WindowPosition; - // We have to show the progress pane in the first column, as the screen buffer at any point might contain - // a CJK double-cell characters, which makes it impractical to try to find a position where the pane would - // not slice a character. Column 0 is the only place where we know for sure we can place the pane. + // We have to show the progress pane in the first column, as the screen buffer at any point might contain + // a CJK double-cell characters, which makes it impractical to try to find a position where the pane would + // not slice a character. Column 0 is the only place where we know for sure we can place the pane. - _location.Y = Math.Min(_location.Y + 2, _bufSize.Height); + _location.Y = Math.Min(_location.Y + 2, _bufSize.Height); - // Save off the current contents of the screen buffer in the region that we will occupy - _savedRegion = - _rawui.GetBufferContents( - new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); -#endif + // Save off the current contents of the screen buffer in the region that we will occupy + _savedRegion = + _rawui.GetBufferContents( + new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); + } - // replace the saved region in the screen buffer with our progress display - _rawui.SetBufferContents(_location, tempProgressRegion); + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + WriteContent(); + } + else + { + // replace the saved region in the screen buffer with our progress display + _rawui.SetBufferContents(_location, tempProgressRegion); + } } } @@ -142,12 +167,37 @@ class ProgressPane { if (IsShowing) { - // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, - // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that - // detecting a change would be at least as expensive as chucking the savedRegion and rebuilding it. And it would - // be very complicated. + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + _rawui.CursorPosition = _location; + int maxWidth = PSStyle.Instance.Progress.MaxWidth; + if (maxWidth > _bufSize.Width) + { + maxWidth = _bufSize.Width; + } + + for (int i = 0; i < _savedRegion.GetLength(1); i++) + { + if (i < _savedRegion.GetLength(1) - 1) + { + Console.Out.WriteLine(string.Empty.PadRight(maxWidth)); + } + else + { + Console.Out.Write(string.Empty.PadRight(maxWidth)); + } + } + } + else + { + // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, + // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that + // detecting a change would be at least as expensive as chucking the savedRegion and rebuilding it. And it would + // be very complicated. + + _rawui.SetBufferContents(_location, _savedRegion); + } - _rawui.SetBufferContents(_location, _savedRegion); _savedRegion = null; _rawui.CursorPosition = _savedCursor; } @@ -173,8 +223,8 @@ class ProgressPane int maxWidth = _bufSize.Width; int maxHeight = Math.Max(5, _rawui.WindowSize.Height / 3); - string[] contents = pendingProgress.Render(maxWidth, maxHeight, _rawui); - if (contents == null) + _content = pendingProgress.Render(maxWidth, maxHeight, _rawui); + if (_content == null) { // There's nothing to show. @@ -183,9 +233,21 @@ class ProgressPane return; } - // NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here... + BufferCell[,] newRegion; + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + // Legacy progress rendering relies on a BufferCell which defines a character, foreground color, and background color + // per cell. This model doesn't work with ANSI escape sequences. However, there is existing logic on rendering that + // relies on the existence of the BufferCell to know if something has been rendered previously. Here we are creating + // an empty BufferCell, but using the second dimension to capture the number of rows so that we can clear that many + // elsewhere in Hide(). + newRegion = new BufferCell[0, _content.Length]; + } + else + { + newRegion = _rawui.NewBufferCellArray(_content, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); + } - BufferCell[,] newRegion = _rawui.NewBufferCellArray(contents, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); Dbg.Assert(newRegion != null, "NewBufferCellArray has failed!"); if (_progressRegion == null) @@ -208,8 +270,7 @@ class ProgressPane bool sizeChanged = (newRegion.GetLength(0) != _progressRegion.GetLength(0)) - || (newRegion.GetLength(1) != _progressRegion.GetLength(1)) - ? true : false; + || (newRegion.GetLength(1) != _progressRegion.GetLength(1)); _progressRegion = newRegion; @@ -224,18 +285,51 @@ class ProgressPane } else { - _rawui.SetBufferContents(_location, _progressRegion); + if (ProgressNode.IsMinimalProgressRenderingEnabled()) + { + WriteContent(); + } + else + { + _rawui.SetBufferContents(_location, _progressRegion); + } } } } + private void WriteContent() + { + if (_content is not null) + { + Console.CursorVisible = false; + + var currentPosition = _rawui.CursorPosition; + _rawui.CursorPosition = _location; + + for (int i = 0; i < _content.Length; i++) + { + if (i < _content.Length - 1) + { + Console.Out.WriteLine(_content[i]); + } + else + { + Console.Out.Write(_content[i]); + } + } + + _rawui.CursorPosition = currentPosition; + Console.CursorVisible = true; + } + } + private Coordinates _location = new Coordinates(0, 0); private Coordinates _savedCursor; private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; - private PSHostRawUserInterface _rawui; - private ConsoleHostUserInterface _ui; + private string[] _content; + private readonly PSHostRawUserInterface _rawui; + private readonly ConsoleHostUserInterface _ui; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs index 5340a3950d7..4c1fb4fa4e9 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs @@ -58,8 +58,7 @@ class WrappedSerializer : Serialization { internal WrappedSerializer(DataFormat dataFormat, string streamName, TextWriter output) - : - base(dataFormat, streamName) + : base(dataFormat, streamName) { Dbg.Assert(output != null, "output should have a value"); @@ -137,7 +136,7 @@ class WrappedSerializer : Serialization } internal TextWriter textWriter; - private XmlWriter _xmlWriter; + private readonly XmlWriter _xmlWriter; private Serializer _xmlSerializer; private bool _firstCall = true; } @@ -147,8 +146,7 @@ class WrappedDeserializer : Serialization { internal WrappedDeserializer(DataFormat dataFormat, string streamName, TextReader input) - : - base(dataFormat, streamName) + : base(dataFormat, streamName) { Dbg.Assert(input != null, "input should have a value"); @@ -267,10 +265,9 @@ class WrappedDeserializer : Serialization } internal TextReader textReader; - private XmlReader _xmlReader; - private Deserializer _xmlDeserializer; + private readonly XmlReader _xmlReader; + private readonly Deserializer _xmlDeserializer; private string _firstLine; private bool _atEnd; } } // namespace - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/StartTranscriptCmdlet.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/StartTranscriptCmdlet.cs index 3f413df76ef..dadc5117ab3 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/StartTranscriptCmdlet.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/StartTranscriptCmdlet.cs @@ -346,4 +346,3 @@ private void ReportMultipleFilesNotSupported() private bool _isFilenameSet; } } - diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/StopTranscriptCmdlet.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/StopTranscriptCmdlet.cs index 48b392f98e7..a48fa105437 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/StopTranscriptCmdlet.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/StopTranscriptCmdlet.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerShell.Commands public sealed class StopTranscriptCommand : PSCmdlet { /// - /// Starts the transcription. + /// Stops the transcription. /// protected override void diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/UpdatesNotification.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/UpdatesNotification.cs index 5c202eb32b1..dff3757259f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/UpdatesNotification.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/UpdatesNotification.cs @@ -315,7 +315,7 @@ private static bool TryParseUpdateFile( int dateStartIndex = updateFileName.LastIndexOf('_') + 1; if (!DateTime.TryParse( - updateFileName.AsSpan().Slice(dateStartIndex), + updateFileName.AsSpan(dateStartIndex), CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out lastUpdateDate)) @@ -411,7 +411,7 @@ private static NotificationType GetNotificationType() private enum NotificationType { /// - /// Turn off the udpate notification. + /// Turn off the update notification. /// Off = 0, @@ -428,7 +428,7 @@ private enum NotificationType LTS = 2 } - private class Release + private sealed class Release { internal Release(string publishAt, string tagName) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx b/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx index 390fe346c70..7b13837b294 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx +++ b/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx @@ -153,8 +153,8 @@ Type 'help' to get help. [-EncodedCommand <Base64EncodedCommand>] [-ExecutionPolicy <ExecutionPolicy>] [-InputFormat {Text | XML}] [-Interactive] [-MTA] [-NoExit] [-NoLogo] [-NonInteractive] [-NoProfile] - [-OutputFormat {Text | XML}] [-SettingsFile <filePath>] [-STA] [-Version] - [-WindowStyle <style>] [-WorkingDirectory <directoryPath>] + [-OutputFormat {Text | XML}] [-SettingsFile <filePath>] [-SSHServerMode] [-STA] + [-Version] [-WindowStyle <style>] [-WorkingDirectory <directoryPath>] pwsh[.exe] -h | -Help | -? | /? @@ -183,10 +183,11 @@ All parameters are case-insensitive. omitted. For example, the following command uses the All parameter of the Get-Script.ps1 script file: "-File .\Get-Script.ps1 -All" - In rare cases, you might need to provide a Boolean value for a switch - parameter. To provide a Boolean value for a switch parameter in the value - of the File parameter, enclose the parameter name and value in curly - braces, such as the following: "-File .\Get-Script.ps1 {-All:$False}." + In rare cases, you might need to provide a BOOLEAN value for a switch + parameter. To provide a BOOLEAN value for a switch parameter in the value + of the FILE parameter, Use the parameter normally followed immediately by a + colon and the boolean value, such as the following: + "-File .\Get-Script.ps1 -All:$False". Parameters passed to the script are passed as literal strings, after interpretation by the current shell. For example, if you are in cmd.exe and @@ -197,7 +198,21 @@ All parameters are case-insensitive. cmd.exe results in the script receiving the literal string "$env:windir" because it has no special meaning to the current cmd.exe shell. The "$env:windir" style of environment variable reference can be used inside a - Command parameter, since there it will be interpreted as PowerShell code. + Command parameter, since there it is interpreted as PowerShell code. + + Similarly, if you want to execute the same command from a Batch script, + you would use "%~dp0" instead of ".\" or "$PSScriptRoot" to represent the current + execution directory: "pwsh -File %~dp0test.ps1 -TestParam %windir%". If you + instead used ".\test.ps1", PowerShell would throw an error because it cannot + find the literal path ".\test.ps1". + + When the script file invoked terminates with an exit command, the process + exit code is set to the numeric argument used with the exit command. With + normal termination, the exit code is always 0. + + Similar to -Command, when a script-terminating error occurs, the exit code + is set to 1. However, unlike with -Command, when the execution is + interrupted with Ctrl-C the exit code is 0. -Command | -c @@ -215,8 +230,7 @@ All parameters are case-insensitive. or parsed by the PowerShell host as a literal script block enclosed in curly braces "{}", before being passed to pwsh. - - pwsh -Command {Get-WinEvent -LogName security} + pwsh -Command {Get-WinEvent -LogName security} In cmd.exe, there is no such thing as a script block (or ScriptBlock type), so the value passed to Command will always be a string. You can write a @@ -224,7 +238,7 @@ All parameters are case-insensitive. behave exactly as though you typed it at a typical PowerShell prompt, printing the contents of the script block back out to you. - A string passed to Command will still be executed as PowerShell, so the + A string passed to Command is still executed as PowerShell script, so the script block curly braces are often not required in the first place when running from cmd.exe. To execute an inline script block defined inside a string, the call operator "&" can be used: @@ -235,29 +249,39 @@ All parameters are case-insensitive. pwsh, because all arguments following it are interpreted as part of the command to execute. - The results are returned to the parent shell as deserialized XML objects, - not live objects. + When called from within an existing PowerShell session, the results are + returned to the parent shell as deserialized XML objects, not live objects. + For other shells, the results are returned as strings. If the value of Command is "-", the command text is read from standard input. You must redirect standard input when using the Command parameter with standard input. For example: + @' + "in" - @' - "in" - - "hi" | - % { "$_ there" } + "hi" | + % { "$_ there" } - "out" - '@ | powershell -NoProfile -Command - + "out" + '@ | powershell -NoProfile -Command - This example produces the following output: - """Output - in - hi there - out + in + hi there + out + + The process exit code is determined by status of the last (executed) + command within the script block. The exit code is 0 when $? is $true or 1 + when $? is $false. If the last command is an external program or a + PowerShell script that explicitly sets an exit code other than 0 or 1, that + exit code is converted to 1 for process exit code. To preserve the specific + exit code, add exit $LASTEXITCODE to your command string or script block. + + Similarly, the value 1 is returned when a script-terminating + (runspace-terminating) error, such as a throw or -ErrorAction Stop, occurs + or when execution is interrupted with Ctrl-C. -ConfigurationName | -config @@ -275,34 +299,37 @@ All parameters are case-insensitive. predictable mechanism for connecting to other PowerShell instances. Typically used with the CustomPipeName parameter on "Enter-PSHostProcess". - For example: + This parameter was introduced in PowerShell 6.2. + For example: - # PowerShell instance 1 - pwsh -CustomPipeName mydebugpipe - # PowerShell instance 2 - Enter-PSHostProcess -CustomPipeName mydebugpipe + # PowerShell instance 1 + pwsh -CustomPipeName mydebugpipe + # PowerShell instance 2 + Enter-PSHostProcess -CustomPipeName mydebugpipe -EncodedCommand | -e | -ec - Accepts a base64-encoded string version of a command. Use this parameter to - submit commands to PowerShell that require complex quotation marks or curly - braces. The string must be formatted using UTF-16 character encoding. + Accepts a Base64-encoded string version of a command. Use this parameter to + submit commands to PowerShell that require complex, nested quoting. The + Base64 representation must be a UTF-16 encoded string. For example: - - $command = 'dir "c:\program files" ' - $bytes = [System.Text.Encoding]::Unicode.GetBytes($command) - $encodedCommand = [Convert]::ToBase64String($bytes) - pwsh -encodedcommand $encodedCommand + $command = 'dir "c:\program files" ' + $bytes = [System.Text.Encoding]::Unicode.GetBytes($command) + $encodedCommand = [Convert]::ToBase64String($bytes) + pwsh -encodedcommand $encodedCommand -ExecutionPolicy | -ex | -ep Sets the default execution policy for the current session and saves it in - the "$env:PSExecutionPolicyPreference" environment variable. This parameter - does not change the PowerShell execution policy that is set in the - registry. + the $env:PSExecutionPolicyPreference environment variable. This parameter + does not change the persistently configured execution policies. + + This parameter only applies to Windows computers. The + $env:PSExecutionPolicyPreference environment variable does not exist on + non-Windows platforms. -InputFormat | -inp | -if @@ -316,16 +343,37 @@ All parameters are case-insensitive. -Login | -l - On Linux and macOS, starts PowerShell as a login shell, - using /bin/sh to execute login profiles such as /etc/profile and ~/.profile. - On Windows, this switch does nothing. + On Linux and macOS, starts PowerShell as a login shell, using /bin/sh to + execute login profiles such as /etc/profile and ~/.profile. On Windows, + this switch does nothing. + + [!IMPORTANT] This parameter must come first to start PowerShell as a login + shell. The parameter is ignored if passed in any other position. + + To set up pwsh as the login shell on UNIX-like operating systems: + + - Verify that the full absolute path to pwsh is listed under /etc/shells + + - This path is usually something like /usr/bin/pwsh on Linux or + /usr/local/bin/pwsh on macOS + - With some installation methods, this entry will be added + automatically at installation time + - If pwsh is not present in /etc/shells, use an editor to append the + path to pwsh on the last line. This requires elevated privileges to + edit. - Note that "-Login" is only supported as the first parameter to pwsh. + - Use the chsh utility to set your current user's shell to pwsh: + + chsh -s /usr/bin/pwsh + + [!WARNING] Setting pwsh as the login shell is currently not supported on + Windows Subsystem for Linux (WSL), and attempting to set pwsh as the + login shell there may lead to being unable to start WSL interactively. -MTA - Start the shell using a multi-threaded apartment. - Only available on Windows. + Start PowerShell using a multi-threaded apartment. This switch is only + available on Windows. -NoExit | -noe @@ -335,15 +383,17 @@ All parameters are case-insensitive. -NoLogo | -nol - Hides the copyright banner at startup. + Hides the copyright banner at startup of interactive sessions. -NonInteractive | -noni - Does not present an interactive prompt to the user. + Does not present an interactive prompt to the user. Any attempts to use + interactive features, like Read-Host or confirmation prompts, result in + statement-terminating errors. -NoProfile | -nop - Does not load the PowerShell profile. + Does not load the PowerShell profiles. -OutputFormat | -o | -of @@ -352,6 +402,10 @@ All parameters are case-insensitive. Example: "pwsh -o XML -c Get-Date" + When called withing a PowerShell session, you get deserialized objects as + output rather plain strings. When called from other shells, the output is + string data formatted as CLIXML text. + -SettingsFile | -settings Overrides the system-wide "powershell.config.json" settings file for the @@ -363,10 +417,15 @@ All parameters are case-insensitive. Example: "pwsh -SettingsFile c:\myproject\powershell.config.json" +-SSHServerMode | -sshs + + Used in sshd_config for running PowerShell as an SSH subsystem. It is not + intended or supported for any other use. + -STA - Start the shell using a single-threaded apartment. This is the default. - Only available on Windows. + Start PowerShell using a single-threaded apartment. This is the default. + This switch is only available on Windows. -Version | -v @@ -379,17 +438,15 @@ All parameters are case-insensitive. -WorkingDirectory | -wd - Sets the initial working directory by executing - "Set-Location -LiteralPath <path>" at startup. Any valid PowerShell file - path is supported. + Sets the initial working directory by executing at startup. Any valid + PowerShell file path is supported. - To start PowerShell in your home directory, use: "pwsh -WorkingDirectory ~" + To start PowerShell in your home directory, use: pwsh -WorkingDirectory ~ -Help, -?, /? Displays help for pwsh. If you are typing a pwsh command in PowerShell, prepend the command parameters with a hyphen (-), not a forward slash (/). - You can use either a hyphen or forward slash in Cmd.exe. diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/AssemblyInfo.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/AssemblyInfo.cs index 4d72090e088..2a5b6533d18 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/AssemblyInfo.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/AssemblyInfo.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Reflection; using System.Runtime.CompilerServices; + [assembly: InternalsVisibleTo("System.Management.Automation,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventDescriptor.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventDescriptor.cs index 34fa9105085..723832979f8 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventDescriptor.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventDescriptor.cs @@ -8,28 +8,28 @@ namespace System.Diagnostics.Eventing { [StructLayout(LayoutKind.Explicit, Size = 16)] - public struct EventDescriptor + public readonly struct EventDescriptor { [FieldOffset(0)] - private ushort _id; + private readonly ushort _id; [FieldOffset(2)] - private byte _version; + private readonly byte _version; [FieldOffset(3)] - private byte _channel; + private readonly byte _channel; [FieldOffset(4)] - private byte _level; + private readonly byte _level; [FieldOffset(5)] - private byte _opcode; + private readonly byte _opcode; [FieldOffset(6)] - private ushort _task; + private readonly ushort _task; [FieldOffset(8)] - private long _keywords; + private readonly long _keywords; [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")] public EventDescriptor( diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProvider.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProvider.cs index a1eba143e28..9713ac0b0b5 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProvider.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProvider.cs @@ -20,7 +20,7 @@ public class EventProvider : IDisposable private long _anyKeywordMask; // Trace Enable Flags private long _allKeywordMask; // Match all keyword private int _enabled; // Enabled flag from Trace callback - private Guid _providerId; // Control Guid + private readonly Guid _providerId; // Control Guid private int _disposed; // when 1, provider has unregister [ThreadStatic] @@ -99,7 +99,7 @@ private unsafe void EtwRegister() _etwCallback = new UnsafeNativeMethods.EtwEnableCallback(EtwEnableCallBack); - status = UnsafeNativeMethods.EventRegister(ref _providerId, _etwCallback, null, ref _regHandle); + status = UnsafeNativeMethods.EventRegister(in _providerId, _etwCallback, null, ref _regHandle); if (status != 0) { throw new Win32Exception((int)status); @@ -107,7 +107,7 @@ private unsafe void EtwRegister() } // - // implement Dispose Pattern to early deregister from ETW insted of waiting for + // implement Dispose Pattern to early deregister from ETW instead of waiting for // the finalizer to call deregistration. // Once the user is done with the provider it needs to call Close() or Dispose() // If neither are called the finalizer will unregister the provider anyway @@ -202,7 +202,7 @@ [In] void* callbackContext /// public bool IsEnabled() { - return (_enabled != 0) ? true : false; + return _enabled != 0; } /// @@ -331,10 +331,10 @@ to fill the passed in ETW data descriptor. *uintptr = (uint)data; dataDescriptor->DataPointer = (ulong)uintptr; } - else if (data is UInt64) + else if (data is ulong) { dataDescriptor->Size = (uint)sizeof(ulong); - UInt64* ulongptr = (ulong*)dataBuffer; + ulong* ulongptr = (ulong*)dataBuffer; *ulongptr = (ulong)data; dataDescriptor->DataPointer = (ulong)ulongptr; } @@ -488,9 +488,9 @@ public bool WriteMessageEvent(string eventMessage) /// /// /// - public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] eventPayload) + public bool WriteEvent(in EventDescriptor eventDescriptor, params object[] eventPayload) { - return WriteTransferEvent(ref eventDescriptor, Guid.Empty, eventPayload); + return WriteTransferEvent(in eventDescriptor, Guid.Empty, eventPayload); } /// @@ -504,13 +504,13 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] even /// [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] - public bool WriteEvent(ref EventDescriptor eventDescriptor, string data) + public bool WriteEvent(in EventDescriptor eventDescriptor, string data) { uint status = 0; if (data == null) { - throw new ArgumentNullException("dataString"); + throw new ArgumentNullException(nameof(data)); } if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) @@ -534,7 +534,7 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, string data) userData.DataPointer = (ulong)pdata; status = UnsafeNativeMethods.EventWriteTransfer(_regHandle, - ref eventDescriptor, + in eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, 1, @@ -565,7 +565,7 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, string data) /// pointer do the event data /// [System.Security.SecurityCritical] - protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data) + protected bool WriteEvent(in EventDescriptor eventDescriptor, int dataCount, IntPtr data) { uint status = 0; @@ -575,7 +575,7 @@ protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, In status = UnsafeNativeMethods.EventWriteTransfer( _regHandle, - ref eventDescriptor, + in eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, (uint)dataCount, @@ -602,7 +602,7 @@ protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, In /// /// [System.Security.SecurityCritical] - public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload) + public bool WriteTransferEvent(in EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload) { uint status = 0; @@ -719,7 +719,7 @@ public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid related } status = UnsafeNativeMethods.EventWriteTransfer(_regHandle, - ref eventDescriptor, + in eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, (relatedActivityId == Guid.Empty) ? null : &relatedActivityId, (uint)argCount, @@ -737,7 +737,7 @@ public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid related } [System.Security.SecurityCritical] - protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) + protected bool WriteTransferEvent(in EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) { uint status = 0; @@ -747,7 +747,7 @@ protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid rela { status = UnsafeNativeMethods.EventWriteTransfer( _regHandle, - ref eventDescriptor, + in eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, &relatedActivityId, (uint)dataCount, @@ -779,7 +779,7 @@ public static void SetActivityId(ref Guid id) [System.Security.SecurityCritical] public static Guid CreateActivityId() { - Guid newId = new Guid(); + Guid newId = new(); UnsafeNativeMethods.EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_CREATE_ID, ref newId); return newId; } diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProviderTraceListener.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProviderTraceListener.cs index 97c10d167ef..9e7befb3e38 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProviderTraceListener.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProviderTraceListener.cs @@ -42,7 +42,7 @@ public string Delimiter set { if (value == null) - throw new ArgumentNullException("Delimiter"); + throw new ArgumentNullException(nameof(Delimiter)); if (value.Length == 0) throw new ArgumentException(DotNetEventingStrings.Argument_NeedNonemptyDelimiter); @@ -84,7 +84,7 @@ public EventProviderTraceListener(string providerId, string name, string delimit private void InitProvider(string providerId) { - Guid controlGuid = new Guid(providerId); + Guid controlGuid = new(providerId); // // Create The ETW TraceProvider // @@ -148,7 +148,7 @@ public sealed override void TraceData(TraceEventCache eventCache, string source, return; } - StringBuilder dataString = new StringBuilder(s_defaultPayloadSize); + StringBuilder dataString = new(s_defaultPayloadSize); if (data != null) { @@ -177,7 +177,7 @@ public sealed override void TraceData(TraceEventCache eventCache, string source, } int index; - StringBuilder dataString = new StringBuilder(s_defaultPayloadSize); + StringBuilder dataString = new(s_defaultPayloadSize); if ((data != null) && (data.Length > 0)) { @@ -242,7 +242,7 @@ public sealed override void TraceEvent(TraceEventCache eventCache, string source return; } - StringBuilder dataString = new StringBuilder(s_defaultPayloadSize); + StringBuilder dataString = new(s_defaultPayloadSize); dataString.Append(message); _provider.WriteMessageEvent(dataString.ToString(), @@ -278,10 +278,10 @@ public sealed override void TraceEvent(TraceEventCache eventCache, string source public override void Fail(string message, string detailMessage) { - StringBuilder failMessage = new StringBuilder(message); + StringBuilder failMessage = new(message); if (detailMessage != null) { - failMessage.Append(" "); + failMessage.Append(' '); failMessage.Append(detailMessage); } diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs index 8858b067f8a..df2b064ebd5 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs @@ -17,12 +17,12 @@ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; -using System.Text; using System.Security.Principal; +using System.Text; namespace System.Diagnostics.Eventing.Reader { - internal class NativeWrapper + internal static class NativeWrapper { public class SystemProperties { @@ -307,7 +307,7 @@ public static void EvtClearLog( [System.Security.SecurityCritical] public static EventLogHandle EvtCreateRenderContext( - Int32 valuePathsCount, + int valuePathsCount, string[] valuePaths, UnsafeNativeMethods.EvtRenderContextFlags flags) { @@ -514,7 +514,7 @@ public static string EvtFormatMessage(EventLogHandle handle, uint msgId) { int bufferNeeded; - StringBuilder sb = new StringBuilder(null); + StringBuilder sb = new(null); bool status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, 0, sb, out bufferNeeded); int error = Marshal.GetLastWin32Error(); @@ -672,9 +672,9 @@ public static object EvtGetChannelConfigProperty(EventLogHandle handle, UnsafeNa [System.Security.SecuritySafeCritical] public static void EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType, object val) { - UnsafeNativeMethods.EvtVariant varVal = new UnsafeNativeMethods.EvtVariant(); + UnsafeNativeMethods.EvtVariant varVal = new(); - CoTaskMemSafeHandle taskMem = new CoTaskMemSafeHandle(); + CoTaskMemSafeHandle taskMem = new(); using (taskMem) { @@ -762,7 +762,7 @@ public static void EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNati [System.Security.SecurityCritical] public static string EvtNextChannelPath(EventLogHandle handle, ref bool finish) { - StringBuilder sb = new StringBuilder(null); + StringBuilder sb = new(null); int channelNameNeeded; bool status = UnsafeNativeMethods.EvtNextChannelPath(handle, 0, sb, out channelNameNeeded); @@ -791,7 +791,7 @@ public static string EvtNextChannelPath(EventLogHandle handle, ref bool finish) [System.Security.SecurityCritical] public static string EvtNextPublisherId(EventLogHandle handle, ref bool finish) { - StringBuilder sb = new StringBuilder(null); + StringBuilder sb = new(null); int ProviderIdNeeded; bool status = UnsafeNativeMethods.EvtNextPublisherId(handle, 0, sb, out ProviderIdNeeded); @@ -939,7 +939,7 @@ public static void EvtRenderBufferWithContextSystem(EventLogHandle contextHandle break; } - pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal))); + pointer = new IntPtr(((long)pointer + Marshal.SizeOf(varVal))); } } finally @@ -958,7 +958,7 @@ public static IList EvtRenderBufferWithContextUserOrValues(EventLogHandl IntPtr pointer = IntPtr.Zero; int bufferNeeded; int propCount; - UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues; + const UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues; try { @@ -976,7 +976,7 @@ public static IList EvtRenderBufferWithContextUserOrValues(EventLogHandl if (!status) ThrowEventLogException(win32Error); - List valuesList = new List(propCount); + List valuesList = new(propCount); if (propCount > 0) { pointer = buffer; @@ -984,7 +984,7 @@ public static IList EvtRenderBufferWithContextUserOrValues(EventLogHandl { UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure(pointer); valuesList.Add(ConvertToObject(varVal)); - pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal))); + pointer = new IntPtr(((long)pointer + Marshal.SizeOf(varVal))); } } @@ -1001,7 +1001,7 @@ public static IList EvtRenderBufferWithContextUserOrValues(EventLogHandl public static string EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag) { int bufferNeeded; - StringBuilder sb = new StringBuilder(null); + StringBuilder sb = new(null); bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, sb, out bufferNeeded); int error = Marshal.GetLastWin32Error(); @@ -1059,7 +1059,7 @@ public static IEnumerable EvtFormatMessageRenderKeywords(EventLogHandle try { - List keywordsList = new List(); + List keywordsList = new(); bool status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, 0, IntPtr.Zero, out bufferNeeded); int error = Marshal.GetLastWin32Error(); @@ -1106,7 +1106,7 @@ public static IEnumerable EvtFormatMessageRenderKeywords(EventLogHandle break; keywordsList.Add(s); // nr of bytes = # chars * 2 + 2 bytes for character '\0'. - pointer = new IntPtr((Int64)pointer + (s.Length * 2) + 2); + pointer = new IntPtr((long)pointer + (s.Length * 2) + 2); } return keywordsList.AsReadOnly(); @@ -1124,7 +1124,7 @@ public static string EvtRenderBookmark(EventLogHandle eventHandle) IntPtr buffer = IntPtr.Zero; int bufferNeeded; int propCount; - UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderBookmark; + const UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderBookmark; try { @@ -1164,7 +1164,7 @@ public static string EvtFormatMessageFormatDescription(EventLogHandle handle, Ev stringVariants[i].StringVal = values[i]; } - StringBuilder sb = new StringBuilder(null); + StringBuilder sb = new(null); bool status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, 0, sb, out bufferNeeded); int error = Marshal.GetLastWin32Error(); @@ -1270,23 +1270,23 @@ private static object ConvertToObject(UnsafeNativeMethods.EvtVariant val) Marshal.Copy(val.Reference, arByte, 0, (int)val.Count); return arByte; case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt16): - if (val.Reference == IntPtr.Zero) return Array.Empty(); - Int16[] arInt16 = new Int16[val.Count]; + if (val.Reference == IntPtr.Zero) return Array.Empty(); + short[] arInt16 = new short[val.Count]; Marshal.Copy(val.Reference, arInt16, 0, (int)val.Count); return arInt16; case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt32): - if (val.Reference == IntPtr.Zero) return Array.Empty(); - Int32[] arInt32 = new Int32[val.Count]; + if (val.Reference == IntPtr.Zero) return Array.Empty(); + int[] arInt32 = new int[val.Count]; Marshal.Copy(val.Reference, arInt32, 0, (int)val.Count); return arInt32; case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt64): - if (val.Reference == IntPtr.Zero) return Array.Empty(); - Int64[] arInt64 = new Int64[val.Count]; + if (val.Reference == IntPtr.Zero) return Array.Empty(); + long[] arInt64 = new long[val.Count]; Marshal.Copy(val.Reference, arInt64, 0, (int)val.Count); return arInt64; case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSingle): - if (val.Reference == IntPtr.Zero) return Array.Empty(); - Single[] arSingle = new Single[val.Count]; + if (val.Reference == IntPtr.Zero) return Array.Empty(); + float[] arSingle = new float[val.Count]; Marshal.Copy(val.Reference, arSingle, 0, (int)val.Count); return arSingle; case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeDouble): @@ -1297,13 +1297,13 @@ private static object ConvertToObject(UnsafeNativeMethods.EvtVariant val) case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSByte): return ConvertToArray(val, sizeof(sbyte)); // not CLS-compliant case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16): - return ConvertToArray(val, sizeof(UInt16)); + return ConvertToArray(val, sizeof(ushort)); case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64): case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64): - return ConvertToArray(val, sizeof(UInt64)); + return ConvertToArray(val, sizeof(ulong)); case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32): case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt32): - return ConvertToArray(val, sizeof(UInt32)); + return ConvertToArray(val, sizeof(uint)); case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString): return ConvertToStringArray(val, false); case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeAnsiString): @@ -1375,7 +1375,7 @@ public static Array ConvertToArray(UnsafeNativeMethods.EvtVariant val, int si for (int i = 0; i < val.Count; i++) { array.SetValue(Marshal.PtrToStructure(ptr), i); - ptr = new IntPtr((Int64)ptr + size); + ptr = new IntPtr((long)ptr + size); } return array; @@ -1396,9 +1396,9 @@ public static Array ConvertToBoolArray(UnsafeNativeMethods.EvtVariant val) bool[] array = new bool[val.Count]; for (int i = 0; i < val.Count; i++) { - bool value = (Marshal.ReadInt32(ptr) != 0) ? true : false; + bool value = Marshal.ReadInt32(ptr) != 0; array[i] = value; - ptr = new IntPtr((Int64)ptr + 4); + ptr = new IntPtr((long)ptr + 4); } return array; @@ -1419,7 +1419,7 @@ public static Array ConvertToFileTimeArray(UnsafeNativeMethods.EvtVariant val) for (int i = 0; i < val.Count; i++) { array[i] = DateTime.FromFileTime(Marshal.ReadInt64(ptr)); - ptr = new IntPtr((Int64)ptr + 8 * sizeof(byte)); // FILETIME values are 8 bytes + ptr = new IntPtr((long)ptr + 8 * sizeof(byte)); // FILETIME values are 8 bytes } return array; @@ -1441,7 +1441,7 @@ public static Array ConvertToSysTimeArray(UnsafeNativeMethods.EvtVariant val) { UnsafeNativeMethods.SystemTime sysTime = Marshal.PtrToStructure(ptr); array[i] = new DateTime(sysTime.Year, sysTime.Month, sysTime.Day, sysTime.Hour, sysTime.Minute, sysTime.Second, sysTime.Milliseconds); - ptr = new IntPtr((Int64)ptr + 16 * sizeof(byte)); // SystemTime values are 16 bytes + ptr = new IntPtr((long)ptr + 16 * sizeof(byte)); // SystemTime values are 16 bytes } return array; diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/UnsafeNativeMethods.cs b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/UnsafeNativeMethods.cs index 5da8809897d..b7beee133ed 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/UnsafeNativeMethods.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/UnsafeNativeMethods.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Diagnostics.Eventing.Reader; using System.Runtime.InteropServices; using System.Security; @@ -85,7 +84,7 @@ internal static extern int FormatMessage(int dwFlags, IntPtr lpSource, [SecurityCritical] internal static string GetMessage(int errorCode) { - StringBuilder sb = new StringBuilder(512); + StringBuilder sb = new(512); int result = UnsafeNativeMethods.FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, UnsafeNativeMethods.s_NULL, errorCode, 0, sb, sb.Capacity, UnsafeNativeMethods.s_NULL); @@ -120,10 +119,10 @@ [In] void* callbackContext [DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] [SecurityCritical] internal static extern unsafe uint EventRegister( - [In] ref Guid providerId, - [In]EtwEnableCallback enableCallback, - [In]void* callbackContext, - [In][Out]ref long registrationHandle + [In] in Guid providerId, + [In] EtwEnableCallback enableCallback, + [In] void* callbackContext, + [In][Out] ref long registrationHandle ); [DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] @@ -133,7 +132,7 @@ [In][Out]ref long registrationHandle // Control (Is Enabled) APIs [DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventEnabled", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] [SecurityCritical] - internal static extern int EventEnabled([In] long registrationHandle, [In] ref System.Diagnostics.Eventing.EventDescriptor eventDescriptor); + internal static extern int EventEnabled([In] long registrationHandle, [In] in System.Diagnostics.Eventing.EventDescriptor eventDescriptor); [DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventProviderEnabled", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] [SecurityCritical] @@ -144,7 +143,7 @@ [In][Out]ref long registrationHandle [SecurityCritical] internal static extern unsafe uint EventWrite( [In] long registrationHandle, - [In] ref EventDescriptor eventDescriptor, + [In] in EventDescriptor eventDescriptor, [In] uint userDataCount, [In] void* userData ); @@ -163,7 +162,7 @@ [In] void* userData [SecurityCritical] internal static extern unsafe uint EventWriteTransfer( [In] long registrationHandle, - [In] ref EventDescriptor eventDescriptor, + [In] in EventDescriptor eventDescriptor, [In] Guid* activityId, [In] Guid* relatedActivityId, [In] uint userDataCount, @@ -178,6 +177,7 @@ internal static extern unsafe uint EventWriteString( [In] long keywords, [In] char* message ); + // ActivityId Control APIs [DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] [SecurityCritical] @@ -268,10 +268,10 @@ internal struct SystemTime internal struct EvtVariant { [FieldOffset(0)] - public UInt32 UInteger; + public uint UInteger; [FieldOffset(0)] - public Int32 Integer; + public int Integer; [FieldOffset(0)] public byte UInt8; @@ -283,7 +283,7 @@ internal struct EvtVariant public ushort UShort; [FieldOffset(0)] - public UInt32 Bool; + public uint Bool; [FieldOffset(0)] public byte ByteVal; @@ -292,13 +292,13 @@ internal struct EvtVariant public byte SByte; [FieldOffset(0)] - public UInt64 ULong; + public ulong ULong; [FieldOffset(0)] - public Int64 Long; + public long Long; [FieldOffset(0)] - public Single Single; + public float Single; [FieldOffset(0)] public double Double; @@ -325,7 +325,7 @@ internal struct EvtVariant public IntPtr GuidReference; [FieldOffset(0)] - public UInt64 FileTime; + public ulong FileTime; [FieldOffset(0)] public IntPtr SystemTime; @@ -334,10 +334,10 @@ internal struct EvtVariant public IntPtr SizeT; [FieldOffset(8)] - public UInt32 Count; // number of elements (not length) in bytes. + public uint Count; // number of elements (not length) in bytes. [FieldOffset(12)] - public UInt32 Type; + public uint Type; } internal enum EvtEventPropertyId @@ -404,15 +404,15 @@ internal enum EvtChannelReferenceFlags internal enum EvtEventMetadataPropertyId { - EventMetadataEventID, // EvtVarTypeUInt32 - EventMetadataEventVersion, // EvtVarTypeUInt32 - EventMetadataEventChannel, // EvtVarTypeUInt32 - EventMetadataEventLevel, // EvtVarTypeUInt32 - EventMetadataEventOpcode, // EvtVarTypeUInt32 - EventMetadataEventTask, // EvtVarTypeUInt32 - EventMetadataEventKeyword, // EvtVarTypeUInt64 - EventMetadataEventMessageID,// EvtVarTypeUInt32 - EventMetadataEventTemplate // EvtVarTypeString + EventMetadataEventID, // EvtVarTypeUInt32 + EventMetadataEventVersion, // EvtVarTypeUInt32 + EventMetadataEventChannel, // EvtVarTypeUInt32 + EventMetadataEventLevel, // EvtVarTypeUInt32 + EventMetadataEventOpcode, // EvtVarTypeUInt32 + EventMetadataEventTask, // EvtVarTypeUInt32 + EventMetadataEventKeyword, // EvtVarTypeUInt64 + EventMetadataEventMessageID, // EvtVarTypeUInt32 + EventMetadataEventTemplate // EvtVarTypeString // EvtEventMetadataPropertyIdEND } @@ -553,8 +553,8 @@ internal enum EvtSeekFlags [SecurityCritical] internal static extern EventLogHandle EvtQuery( EventLogHandle session, - [MarshalAs(UnmanagedType.LPWStr)]string path, - [MarshalAs(UnmanagedType.LPWStr)]string query, + [MarshalAs(UnmanagedType.LPWStr)] string path, + [MarshalAs(UnmanagedType.LPWStr)] string query, int flags); // SEEK @@ -566,7 +566,7 @@ internal static extern bool EvtSeek( long position, EventLogHandle bookmark, int timeout, - [MarshalAs(UnmanagedType.I4)]EvtSeekFlags flags + [MarshalAs(UnmanagedType.I4)] EvtSeekFlags flags ); [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)] @@ -603,7 +603,7 @@ IntPtr eventHandle internal static extern bool EvtGetEventInfo( EventLogHandle eventHandle, // int propertyId - [MarshalAs(UnmanagedType.I4)]EvtEventPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtEventPropertyId propertyId, int bufferSize, IntPtr bufferPtr, out int bufferUsed @@ -614,7 +614,7 @@ out int bufferUsed [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtGetQueryInfo( EventLogHandle queryHandle, - [MarshalAs(UnmanagedType.I4)]EvtQueryPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtQueryPropertyId propertyId, int bufferSize, IntPtr buffer, ref int bufferRequired @@ -686,7 +686,7 @@ int flags [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtGetEventMetadataProperty( EventLogHandle eventMetadata, - [MarshalAs(UnmanagedType.I4)] EvtEventMetadataPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtEventMetadataPropertyId propertyId, int flags, int eventMetadataPropertyBufferSize, IntPtr eventMetadataPropertyBuffer, @@ -708,7 +708,7 @@ internal static extern bool EvtNextChannelPath( EventLogHandle channelEnum, int channelPathBufferSize, // StringBuilder channelPathBuffer, - [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder channelPathBuffer, + [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder channelPathBuffer, out int channelPathBufferUsed ); @@ -725,7 +725,7 @@ int flags internal static extern bool EvtNextPublisherId( EventLogHandle publisherEnum, int publisherIdBufferSize, - [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder publisherIdBuffer, + [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder publisherIdBuffer, out int publisherIdBufferUsed ); @@ -733,7 +733,7 @@ out int publisherIdBufferUsed [SecurityCritical] internal static extern EventLogHandle EvtOpenChannelConfig( EventLogHandle session, - [MarshalAs(UnmanagedType.LPWStr)]String channelPath, + [MarshalAs(UnmanagedType.LPWStr)] string channelPath, int flags ); @@ -750,7 +750,7 @@ int flags [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtSetChannelConfigProperty( EventLogHandle channelConfig, - [MarshalAs(UnmanagedType.I4)]EvtChannelConfigPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtChannelConfigPropertyId propertyId, int flags, ref EvtVariant propertyValue ); @@ -760,7 +760,7 @@ ref EvtVariant propertyValue [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtGetChannelConfigProperty( EventLogHandle channelConfig, - [MarshalAs(UnmanagedType.I4)]EvtChannelConfigPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtChannelConfigPropertyId propertyId, int flags, int propertyValueBufferSize, IntPtr propertyValueBuffer, @@ -773,7 +773,7 @@ out int propertyValueBufferUsed internal static extern EventLogHandle EvtOpenLog( EventLogHandle session, [MarshalAs(UnmanagedType.LPWStr)] string path, - [MarshalAs(UnmanagedType.I4)]PathType flags + [MarshalAs(UnmanagedType.I4)] PathType flags ); [DllImport(WEVTAPI, CharSet = CharSet.Unicode, SetLastError = true)] @@ -781,7 +781,7 @@ internal static extern EventLogHandle EvtOpenLog( [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtGetLogInfo( EventLogHandle log, - [MarshalAs(UnmanagedType.I4)]EvtLogPropertyId propertyId, + [MarshalAs(UnmanagedType.I4)] EvtLogPropertyId propertyId, int propertyValueBufferSize, IntPtr propertyValueBuffer, out int propertyValueBufferUsed @@ -793,9 +793,9 @@ out int propertyValueBufferUsed [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtExportLog( EventLogHandle session, - [MarshalAs(UnmanagedType.LPWStr)]string channelPath, - [MarshalAs(UnmanagedType.LPWStr)]string query, - [MarshalAs(UnmanagedType.LPWStr)]string targetFilePath, + [MarshalAs(UnmanagedType.LPWStr)] string channelPath, + [MarshalAs(UnmanagedType.LPWStr)] string query, + [MarshalAs(UnmanagedType.LPWStr)] string targetFilePath, int flags ); @@ -804,7 +804,7 @@ int flags [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtArchiveExportedLog( EventLogHandle session, - [MarshalAs(UnmanagedType.LPWStr)]string logFilePath, + [MarshalAs(UnmanagedType.LPWStr)] string logFilePath, int locale, int flags ); @@ -814,8 +814,8 @@ int flags [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EvtClearLog( EventLogHandle session, - [MarshalAs(UnmanagedType.LPWStr)]string channelPath, - [MarshalAs(UnmanagedType.LPWStr)]string targetFilePath, + [MarshalAs(UnmanagedType.LPWStr)] string channelPath, + [MarshalAs(UnmanagedType.LPWStr)] string targetFilePath, int flags ); @@ -823,10 +823,10 @@ int flags [DllImport(WEVTAPI, CharSet = CharSet.Unicode, SetLastError = true)] [SecurityCritical] internal static extern EventLogHandle EvtCreateRenderContext( - Int32 valuePathsCount, - [MarshalAs(UnmanagedType.LPArray,ArraySubType = UnmanagedType.LPWStr)] + int valuePathsCount, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] valuePaths, - [MarshalAs(UnmanagedType.I4)]EvtRenderContextFlags flags + [MarshalAs(UnmanagedType.I4)] EvtRenderContextFlags flags ); [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)] @@ -837,7 +837,7 @@ internal static extern bool EvtRender( EventLogHandle eventHandle, EvtRenderFlags flags, int buffSize, - [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder buffer, + [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer, out int buffUsed, out int propCount ); @@ -862,11 +862,11 @@ internal struct EvtStringVariant public string StringVal; [FieldOffset(8)] - public UInt32 Count; + public uint Count; [FieldOffset(12)] - public UInt32 Type; - }; + public uint Type; + } [DllImport(WEVTAPI, CharSet = CharSet.Unicode, SetLastError = true)] [SecurityCritical] @@ -877,9 +877,9 @@ internal static extern bool EvtFormatMessage( uint messageId, int valueCount, EvtStringVariant[] values, - [MarshalAs(UnmanagedType.I4)]EvtFormatMessageFlags flags, + [MarshalAs(UnmanagedType.I4)] EvtFormatMessageFlags flags, int bufferSize, - [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder buffer, + [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer, out int bufferUsed ); @@ -892,7 +892,7 @@ internal static extern bool EvtFormatMessageBuffer( uint messageId, int valueCount, IntPtr values, - [MarshalAs(UnmanagedType.I4)]EvtFormatMessageFlags flags, + [MarshalAs(UnmanagedType.I4)] EvtFormatMessageFlags flags, int bufferSize, IntPtr buffer, out int bufferUsed @@ -902,7 +902,7 @@ out int bufferUsed [DllImport(WEVTAPI, CharSet = CharSet.Unicode, SetLastError = true)] [SecurityCritical] internal static extern EventLogHandle EvtOpenSession( - [MarshalAs(UnmanagedType.I4)]EvtLoginClass loginClass, + [MarshalAs(UnmanagedType.I4)] EvtLoginClass loginClass, ref EvtRpcLogin login, int timeout, int flags diff --git a/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj b/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj index 8b3cf14f584..c2dba27c14f 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/Microsoft.PowerShell.CoreCLR.Eventing.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.PowerShell.GlobalTool.Shim/GlobalToolShim.cs b/src/Microsoft.PowerShell.GlobalTool.Shim/GlobalToolShim.cs index 47a66ea8767..3b253582b63 100644 --- a/src/Microsoft.PowerShell.GlobalTool.Shim/GlobalToolShim.cs +++ b/src/Microsoft.PowerShell.GlobalTool.Shim/GlobalToolShim.cs @@ -10,7 +10,7 @@ namespace Microsoft.PowerShell.GlobalTool.Shim /// /// Shim layer to chose the appropriate runtime for PowerShell DotNet Global tool. /// - public class EntryPoint + public static class EntryPoint { private const string PwshDllName = "pwsh.dll"; diff --git a/src/Microsoft.PowerShell.GlobalTool.Shim/Microsoft.PowerShell.GlobalTool.Shim.csproj b/src/Microsoft.PowerShell.GlobalTool.Shim/Microsoft.PowerShell.GlobalTool.Shim.csproj index aa845a7817d..d0203344cc2 100644 --- a/src/Microsoft.PowerShell.GlobalTool.Shim/Microsoft.PowerShell.GlobalTool.Shim.csproj +++ b/src/Microsoft.PowerShell.GlobalTool.Shim/Microsoft.PowerShell.GlobalTool.Shim.csproj @@ -6,6 +6,7 @@ Microsoft.PowerShell.GlobalTool.Shim EXE Microsoft.PowerShell.GlobalTool.Shim + False diff --git a/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Commands/GetLocalGroupMemberCommand.cs b/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Commands/GetLocalGroupMemberCommand.cs index a10300e9065..8be09e1ded5 100644 --- a/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Commands/GetLocalGroupMemberCommand.cs +++ b/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Commands/GetLocalGroupMemberCommand.cs @@ -210,7 +210,7 @@ private IEnumerable ProcessesMembership(IEnumerable string.Compare(p1.Name, p2.Name, StringComparison.CurrentCultureIgnoreCase)); + rv.Sort(static (p1, p2) => string.Compare(p1.Name, p2.Name, StringComparison.CurrentCultureIgnoreCase)); return rv; } diff --git a/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Sam.cs b/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Sam.cs index e87147fd35d..2ec7f41499c 100644 --- a/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Sam.cs +++ b/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Sam.cs @@ -214,7 +214,7 @@ private enum ContextObjectType /// Used primarily by the private ThrowOnFailure method when building /// Exception objects to throw. /// - private class Context + private sealed class Context { public ContextOperation operation; public ContextObjectType type; @@ -308,7 +308,7 @@ public string MemberName /// AccountInfo is the return type from the private /// LookupAccountInfo method. /// - private class AccountInfo + private sealed class AccountInfo { public string AccountName; public string DomainName; diff --git a/src/Microsoft.PowerShell.MarkdownRender/CodeInlineRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/CodeInlineRenderer.cs deleted file mode 100644 index 681c38cc6d8..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/CodeInlineRenderer.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax.Inlines; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for inline code elements. - /// - internal class CodeInlineRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, CodeInline obj) - { - renderer.Write(renderer.EscapeSequences.FormatCode(obj.Content, isInline: true)); - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/EmphasisInlineRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/EmphasisInlineRenderer.cs deleted file mode 100644 index 8a4be614796..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/EmphasisInlineRenderer.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax.Inlines; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for bold and italics elements. - /// - internal class EmphasisInlineRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, EmphasisInline obj) - { - renderer.Write(renderer.EscapeSequences.FormatEmphasis(obj.FirstChild.ToString(), isBold: obj.DelimiterCount == 2 ? true : false)); - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/FencedCodeBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/FencedCodeBlockRenderer.cs deleted file mode 100644 index 121c7ee01fa..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/FencedCodeBlockRenderer.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Helpers; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for code blocks with language type. - /// - internal class FencedCodeBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, FencedCodeBlock obj) - { - if (obj?.Lines.Lines != null) - { - foreach (StringLine codeLine in obj.Lines.Lines) - { - if (!string.IsNullOrWhiteSpace(codeLine.ToString())) - { - // If the code block is of type YAML, then tab to right to improve readability. - // This specifically helps for parameters help content. - if (string.Equals(obj.Info, "yaml", StringComparison.OrdinalIgnoreCase)) - { - renderer.Write("\t").WriteLine(codeLine.ToString()); - } - else - { - renderer.WriteLine(renderer.EscapeSequences.FormatCode(codeLine.ToString(), isInline: false)); - } - } - } - - // Add a blank line after the code block for better readability. - renderer.WriteLine(); - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/HeaderBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/HeaderBlockRenderer.cs deleted file mode 100644 index eb975d6b6a3..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/HeaderBlockRenderer.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for headings. - /// - internal class HeaderBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, HeadingBlock obj) - { - string headerText = obj?.Inline?.FirstChild?.ToString(); - - if (!string.IsNullOrEmpty(headerText)) - { - // Format header and then add blank line to improve readability. - switch (obj.Level) - { - case 1: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader1(headerText)); - renderer.WriteLine(); - break; - - case 2: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader2(headerText)); - renderer.WriteLine(); - break; - - case 3: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader3(headerText)); - renderer.WriteLine(); - break; - - case 4: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader4(headerText)); - renderer.WriteLine(); - break; - - case 5: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader5(headerText)); - renderer.WriteLine(); - break; - - case 6: - renderer.WriteLine(renderer.EscapeSequences.FormatHeader6(headerText)); - renderer.WriteLine(); - break; - } - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/LeafInlineRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/LeafInlineRenderer.cs deleted file mode 100644 index 55a8ff32a73..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/LeafInlineRenderer.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax.Inlines; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for leaf elements like plain text in paragraphs. - /// - internal class LeafInlineRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, LeafInline obj) - { - // If the next sibling is null, then this is the last line in the paragraph. - // Add new line character at the end. - // Else just write without newline at the end. - if (obj.NextSibling == null) - { - renderer.WriteLine(obj.ToString()); - } - else - { - renderer.Write(obj.ToString()); - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/LineBreakRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/LineBreakRenderer.cs deleted file mode 100644 index 1f4c8f4ceaf..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/LineBreakRenderer.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax.Inlines; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for line breaks. - /// - internal class LineBreakRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, LineBreakInline obj) - { - // If it is a hard line break add new line at the end. - // Else, add a space for after the last character to improve readability. - if (obj.IsHard) - { - renderer.WriteLine(); - } - else - { - renderer.Write(" "); - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/LinkInlineRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/LinkInlineRenderer.cs deleted file mode 100644 index 3999fd5f4e1..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/LinkInlineRenderer.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax.Inlines; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for links. - /// - internal class LinkInlineRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, LinkInline obj) - { - string text = obj.FirstChild?.ToString(); - - // Format link as image or link. - if (obj.IsImage) - { - renderer.Write(renderer.EscapeSequences.FormatImage(text)); - } - else - { - renderer.Write(renderer.EscapeSequences.FormatLink(text, obj.Url)); - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/ListBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/ListBlockRenderer.cs deleted file mode 100644 index b65d7c25475..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/ListBlockRenderer.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for list blocks. - /// - internal class ListBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, ListBlock obj) - { - // start index of a numbered block. - int index = 1; - - foreach (var item in obj) - { - if (item is ListItemBlock listItem) - { - if (obj.IsOrdered) - { - RenderNumberedList(renderer, listItem, index++); - } - else - { - renderer.Write(listItem); - } - } - } - - renderer.WriteLine(); - } - - private void RenderNumberedList(VT100Renderer renderer, ListItemBlock block, int index) - { - // For a numbered list, we need to make sure the index is incremented. - foreach (var line in block) - { - if (line is ParagraphBlock paragraphBlock) - { - renderer.Write(index.ToString()).Write(". ").Write(paragraphBlock.Inline); - } - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/ListItemBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/ListItemBlockRenderer.cs deleted file mode 100644 index 281cec47d54..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/ListItemBlockRenderer.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Threading; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for items in a list block. - /// - internal class ListItemBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, ListItemBlock obj) - { - if (obj.Parent is ListBlock parent) - { - if (!parent.IsOrdered) - { - foreach (var line in obj) - { - RenderWithIndent(renderer, line, parent.BulletType, 0); - } - } - } - } - - private void RenderWithIndent(VT100Renderer renderer, MarkdownObject block, char listBullet, int indentLevel) - { - // Indent left by 2 for each level on list. - string indent = Padding(indentLevel * 2); - - if (block is ParagraphBlock paragraphBlock) - { - renderer.Write(indent).Write(listBullet).Write(" ").Write(paragraphBlock.Inline); - } - else - { - // If there is a sublist, the block is a ListBlock instead of ParagraphBlock. - if (block is ListBlock subList) - { - foreach (var subListItem in subList) - { - if (subListItem is ListItemBlock subListItemBlock) - { - foreach (var line in subListItemBlock) - { - // Increment indent level for sub list. - RenderWithIndent(renderer, line, listBullet, indentLevel + 1); - } - } - } - } - } - } - - // Typical padding is at most a screen's width, any more than that and we won't bother caching. - private const int IndentCacheMax = 120; - - private static readonly string[] IndentCache = new string[IndentCacheMax]; - - internal static string Padding(int countOfSpaces) - { - if (countOfSpaces >= IndentCacheMax) - { - return new string(' ', countOfSpaces); - } - - var result = IndentCache[countOfSpaces]; - - if (result == null) - { - Interlocked.CompareExchange(ref IndentCache[countOfSpaces], new string(' ', countOfSpaces), comparand: null); - result = IndentCache[countOfSpaces]; - } - - return result; - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs b/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs deleted file mode 100644 index c68d9af3d3b..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Type of conversion from Markdown. - /// - [Flags] - public enum MarkdownConversionType - { - /// - /// Convert to HTML. - /// - HTML = 1, - - /// - /// Convert to VT100 encoded string. - /// - VT100 = 2 - } - - /// - /// Object representing the conversion from Markdown. - /// - public class MarkdownInfo - { - /// - /// Gets the Html content after conversion. - /// - public string Html { get; internal set; } - - /// - /// Gets the VT100 encoded string after conversion. - /// - public string VT100EncodedString { get; internal set; } - - /// - /// Gets the AST of the Markdown string. - /// - public Markdig.Syntax.MarkdownDocument Tokens { get; internal set; } - } - - /// - /// Class to convert a Markdown string to VT100, HTML or AST. - /// - public sealed class MarkdownConverter - { - /// - /// Convert from Markdown string to VT100 encoded string or HTML. Returns MarkdownInfo object. - /// - /// String with Markdown content to be converted. - /// Specifies type of conversion, either VT100 or HTML. - /// Specifies the rendering options for VT100 rendering. - /// MarkdownInfo object with the converted output. - public static MarkdownInfo Convert(string markdownString, MarkdownConversionType conversionType, PSMarkdownOptionInfo optionInfo) - { - var renderInfo = new MarkdownInfo(); - var writer = new StringWriter(); - MarkdownPipeline pipeline = null; - - if (conversionType.HasFlag(MarkdownConversionType.HTML)) - { - pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); - var renderer = new Markdig.Renderers.HtmlRenderer(writer); - renderInfo.Html = Markdig.Markdown.Convert(markdownString, renderer, pipeline).ToString(); - } - - if (conversionType.HasFlag(MarkdownConversionType.VT100)) - { - pipeline = new MarkdownPipelineBuilder().Build(); - - // Use the VT100 renderer. - var renderer = new VT100Renderer(writer, optionInfo); - renderInfo.VT100EncodedString = Markdig.Markdown.Convert(markdownString, renderer, pipeline).ToString(); - } - - // Always have AST available. - var parsed = Markdig.Markdown.Parse(markdownString, pipeline); - renderInfo.Tokens = parsed; - - return renderInfo; - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj b/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj deleted file mode 100644 index af8bd52e2a0..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - PowerShell's Markdown Rendering project - Microsoft.PowerShell.MarkdownRender - - - - - - - - - diff --git a/src/Microsoft.PowerShell.MarkdownRender/ParagraphBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/ParagraphBlockRenderer.cs deleted file mode 100644 index 26986311614..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/ParagraphBlockRenderer.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for paragraphs. - /// - internal class ParagraphBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, ParagraphBlock obj) - { - // Call the renderer for children, leaf inline or line breaks. - renderer.WriteChildren(obj.Inline); - - // Add new line at the end of the paragraph. - renderer.WriteLine(); - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/QuoteBlockRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/QuoteBlockRenderer.cs deleted file mode 100644 index 1f26adc5883..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/QuoteBlockRenderer.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Renderer for adding VT100 escape sequences for quote blocks. - /// - internal class QuoteBlockRenderer : VT100ObjectRenderer - { - protected override void Write(VT100Renderer renderer, QuoteBlock obj) - { - // Iterate through each item and add the quote character before the content. - foreach (var item in obj) - { - renderer.Write(obj.QuoteChar).Write(" ").Write(item); - } - - // Add blank line after the quote block. - renderer.WriteLine(); - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs b/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs deleted file mode 100644 index 0827fdf049f..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Management.Automation; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Enum to name all the properties of PSMarkdownOptionInfo. - /// - public enum MarkdownOptionInfoProperty - { - /// - /// Property name Header1. - /// - Header1, - - /// - /// Property name Header2. - /// - Header2, - - /// - /// Property name Header3. - /// - Header3, - - /// - /// Property name Header4. - /// - Header4, - - /// - /// Property name Header5. - /// - Header5, - - /// - /// Property name Header6. - /// - Header6, - - /// - /// Property name Code. - /// - Code, - - /// - /// Property name Link. - /// - Link, - - /// - /// Property name Image. - /// - Image, - - /// - /// Property name EmphasisBold. - /// - EmphasisBold, - - /// - /// Property name EmphasisItalics. - /// - EmphasisItalics - } - - /// - /// Class to represent color preference options for various Markdown elements. - /// - public sealed class PSMarkdownOptionInfo - { - private const char Esc = (char)0x1b; - private const string EndSequence = "[0m"; - - /// - /// Gets or sets current VT100 escape sequence for header 1. - /// - public string Header1 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for header 2. - /// - public string Header2 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for header 3. - /// - public string Header3 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for header 4. - /// - public string Header4 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for header 5. - /// - public string Header5 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for header 6. - /// - public string Header6 { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for code inline and code blocks. - /// - public string Code { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for links. - /// - public string Link { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for images. - /// - public string Image { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for bold text. - /// - public string EmphasisBold { get; set; } - - /// - /// Gets or sets current VT100 escape sequence for italics text. - /// - public string EmphasisItalics { get; set; } - - /// - /// Gets or sets a value indicating whether VT100 escape sequences should be added. Default it true. - /// - public bool EnableVT100Encoding { get; set; } - - /// - /// Get the property as an rendered escape sequence. - /// This is used by formatting system for displaying. - /// - /// Name of the property to get as escape sequence. - /// Specified property name as escape sequence. - public string AsEscapeSequence(MarkdownOptionInfoProperty propertyName) - { - switch (propertyName) - { - case MarkdownOptionInfoProperty.Header1: - return string.Concat(Esc, Header1, Header1, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Header2: - return string.Concat(Esc, Header2, Header2, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Header3: - return string.Concat(Esc, Header3, Header3, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Header4: - return string.Concat(Esc, Header4, Header4, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Header5: - return string.Concat(Esc, Header5, Header5, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Header6: - return string.Concat(Esc, Header6, Header6, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Code: - return string.Concat(Esc, Code, Code, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Link: - return string.Concat(Esc, Link, Link, Esc, EndSequence); - - case MarkdownOptionInfoProperty.Image: - return string.Concat(Esc, Image, Image, Esc, EndSequence); - - case MarkdownOptionInfoProperty.EmphasisBold: - return string.Concat(Esc, EmphasisBold, EmphasisBold, Esc, EndSequence); - - case MarkdownOptionInfoProperty.EmphasisItalics: - return string.Concat(Esc, EmphasisItalics, EmphasisItalics, Esc, EndSequence); - - default: - break; - } - - return null; - } - - /// - /// Initializes a new instance of the class and sets dark as the default theme. - /// - public PSMarkdownOptionInfo() - { - SetDarkTheme(); - EnableVT100Encoding = true; - } - - private const string Header1Dark = "[7m"; - private const string Header2Dark = "[4;93m"; - private const string Header3Dark = "[4;94m"; - private const string Header4Dark = "[4;95m"; - private const string Header5Dark = "[4;96m"; - private const string Header6Dark = "[4;97m"; - private const string CodeDark = "[48;2;155;155;155;38;2;30;30;30m"; - private const string CodeMacOS = "[107;95m"; - private const string LinkDark = "[4;38;5;117m"; - private const string ImageDark = "[33m"; - private const string EmphasisBoldDark = "[1m"; - private const string EmphasisItalicsDark = "[36m"; - - private const string Header1Light = "[7m"; - private const string Header2Light = "[4;33m"; - private const string Header3Light = "[4;34m"; - private const string Header4Light = "[4;35m"; - private const string Header5Light = "[4;36m"; - private const string Header6Light = "[4;30m"; - private const string CodeLight = "[48;2;155;155;155;38;2;30;30;30m"; - private const string LinkLight = "[4;38;5;117m"; - private const string ImageLight = "[33m"; - private const string EmphasisBoldLight = "[1m"; - private const string EmphasisItalicsLight = "[36m"; - - /// - /// Set all preference for dark theme. - /// - public void SetDarkTheme() - { - Header1 = Header1Dark; - Header2 = Header2Dark; - Header3 = Header3Dark; - Header4 = Header4Dark; - Header5 = Header5Dark; - Header6 = Header6Dark; - Link = LinkDark; - Image = ImageDark; - EmphasisBold = EmphasisBoldDark; - EmphasisItalics = EmphasisItalicsDark; - SetCodeColor(isDarkTheme: true); - } - - /// - /// Set all preference for light theme. - /// - public void SetLightTheme() - { - Header1 = Header1Light; - Header2 = Header2Light; - Header3 = Header3Light; - Header4 = Header4Light; - Header5 = Header5Light; - Header6 = Header6Light; - Link = LinkLight; - Image = ImageLight; - EmphasisBold = EmphasisBoldLight; - EmphasisItalics = EmphasisItalicsLight; - SetCodeColor(isDarkTheme: false); - } - - private void SetCodeColor(bool isDarkTheme) - { - // MacOS terminal app does not support extended colors for VT100, so we special case for it. - Code = Platform.IsMacOS ? CodeMacOS : isDarkTheme ? CodeDark : CodeLight; - } - } - - /// - /// Class to represent default VT100 escape sequences. - /// - public class VT100EscapeSequences - { - private const char Esc = (char)0x1B; - - private string endSequence = Esc + "[0m"; - - // For code blocks, [500@ make sure that the whole line has background color. - private const string LongBackgroundCodeBlock = "[500@"; - - private PSMarkdownOptionInfo options; - - /// - /// Initializes a new instance of the class. - /// - /// PSMarkdownOptionInfo object to initialize with. - public VT100EscapeSequences(PSMarkdownOptionInfo optionInfo) - { - if (optionInfo == null) - { - throw new ArgumentNullException(nameof(optionInfo)); - } - - options = optionInfo; - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 1 string. - public string FormatHeader1(string headerText) - { - return FormatHeader(headerText, options.Header1); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 2 string. - public string FormatHeader2(string headerText) - { - return FormatHeader(headerText, options.Header2); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 3 string. - public string FormatHeader3(string headerText) - { - return FormatHeader(headerText, options.Header3); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 4 string. - public string FormatHeader4(string headerText) - { - return FormatHeader(headerText, options.Header4); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 5 string. - public string FormatHeader5(string headerText) - { - return FormatHeader(headerText, options.Header5); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the header to format. - /// Formatted Header 6 string. - public string FormatHeader6(string headerText) - { - return FormatHeader(headerText, options.Header6); - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the code block to format. - /// True if it is a inline code block, false otherwise. - /// Formatted code block string. - public string FormatCode(string codeText, bool isInline) - { - bool isVT100Enabled = options.EnableVT100Encoding; - - if (isInline) - { - if (isVT100Enabled) - { - return string.Concat(Esc, options.Code, codeText, endSequence); - } - else - { - return codeText; - } - } - else - { - if (isVT100Enabled) - { - return string.Concat(Esc, options.Code, codeText, Esc, LongBackgroundCodeBlock, endSequence); - } - else - { - return codeText; - } - } - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the link to format. - /// URL of the link. - /// True url should be hidden, false otherwise. Default is true. - /// Formatted link string. - public string FormatLink(string linkText, string url, bool hideUrl = true) - { - bool isVT100Enabled = options.EnableVT100Encoding; - - if (hideUrl) - { - if (isVT100Enabled) - { - return string.Concat(Esc, options.Link, "\"", linkText, "\"", endSequence); - } - else - { - return string.Concat("\"", linkText, "\""); - } - } - else - { - if (isVT100Enabled) - { - return string.Concat("\"", linkText, "\" (", Esc, options.Link, url, endSequence, ")"); - } - else - { - return string.Concat("\"", linkText, "\" (", url, ")"); - } - } - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text to format as emphasis. - /// True if it is to be formatted as bold, false to format it as italics. - /// Formatted emphasis string. - public string FormatEmphasis(string emphasisText, bool isBold) - { - var sequence = isBold ? options.EmphasisBold : options.EmphasisItalics; - - if (options.EnableVT100Encoding) - { - return string.Concat(Esc, sequence, emphasisText, endSequence); - } - else - { - return emphasisText; - } - } - - /// - /// Class to represent default VT100 escape sequences. - /// - /// Text of the image to format. - /// Formatted image string. - public string FormatImage(string altText) - { - var text = altText; - - if (string.IsNullOrEmpty(altText)) - { - text = "Image"; - } - - if (options.EnableVT100Encoding) - { - return string.Concat(Esc, options.Image, "[", text, "]", endSequence); - } - else - { - return string.Concat("[", text, "]"); - } - } - - private string FormatHeader(string headerText, string headerEscapeSequence) - { - if (options.EnableVT100Encoding) - { - return string.Concat(Esc, headerEscapeSequence, headerText, endSequence); - } - else - { - return headerText; - } - } - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/VT100ObjectRenderer.cs b/src/Microsoft.PowerShell.MarkdownRender/VT100ObjectRenderer.cs deleted file mode 100644 index 566a086015d..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/VT100ObjectRenderer.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Implement the MarkdownObjectRenderer with VT100Renderer. - /// - /// The element type of the renderer. - public abstract class VT100ObjectRenderer : MarkdownObjectRenderer where T : MarkdownObject - { - } -} diff --git a/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs b/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs deleted file mode 100644 index 8663b018ffd..00000000000 --- a/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; - -using Markdig; -using Markdig.Renderers; -using Markdig.Syntax; - -namespace Microsoft.PowerShell.MarkdownRender -{ - /// - /// Initializes an instance of the VT100 renderer. - /// - public sealed class VT100Renderer : TextRendererBase - { - /// - /// Initializes a new instance of the class. - /// - /// TextWriter to write to. - /// PSMarkdownOptionInfo object with options. - public VT100Renderer(TextWriter writer, PSMarkdownOptionInfo optionInfo) : base(writer) - { - EscapeSequences = new VT100EscapeSequences(optionInfo); - - // Add the various element renderers. - ObjectRenderers.Add(new HeaderBlockRenderer()); - ObjectRenderers.Add(new LineBreakRenderer()); - ObjectRenderers.Add(new CodeInlineRenderer()); - ObjectRenderers.Add(new FencedCodeBlockRenderer()); - ObjectRenderers.Add(new EmphasisInlineRenderer()); - ObjectRenderers.Add(new ParagraphBlockRenderer()); - ObjectRenderers.Add(new LeafInlineRenderer()); - ObjectRenderers.Add(new LinkInlineRenderer()); - ObjectRenderers.Add(new ListBlockRenderer()); - ObjectRenderers.Add(new ListItemBlockRenderer()); - ObjectRenderers.Add(new QuoteBlockRenderer()); - } - - /// - /// Gets the current escape sequences. - /// - public VT100EscapeSequences EscapeSequences { get; } - } -} diff --git a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index 72119525b65..b79ab533b88 100644 --- a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj +++ b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj @@ -16,21 +16,21 @@ - + - - - + + + - - - - - - + + + + + + - + diff --git a/src/Microsoft.PowerShell.ScheduledJob/ScheduledJob.cs b/src/Microsoft.PowerShell.ScheduledJob/ScheduledJob.cs index 4c7dcb146a9..85680da94a4 100644 --- a/src/Microsoft.PowerShell.ScheduledJob/ScheduledJob.cs +++ b/src/Microsoft.PowerShell.ScheduledJob/ScheduledJob.cs @@ -953,7 +953,7 @@ private void RemoveSetShouldExitFromHost() #region Private ResultsInfo class [Serializable] - private class ResultsInfo : ISerializable + private sealed class ResultsInfo : ISerializable { // Private Members private Collection _output; diff --git a/src/Microsoft.PowerShell.Security/security/AclCommands.cs b/src/Microsoft.PowerShell.Security/security/AclCommands.cs index 37dd52d7ebe..c0994a57a53 100644 --- a/src/Microsoft.PowerShell.Security/security/AclCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/AclCommands.cs @@ -5,18 +5,18 @@ #pragma warning disable 56506 using System; -using System.Management.Automation; -using Dbg = System.Management.Automation; -using System.Management.Automation.Security; -using System.Security.AccessControl; -using System.Security.Principal; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; using System.Globalization; -using System.ComponentModel; -using System.Reflection; +using System.Management.Automation; +using System.Management.Automation.Security; +using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Security.Principal; + +using Dbg = System.Management.Automation; namespace Microsoft.PowerShell.Commands { @@ -87,8 +87,7 @@ internal CmdletProviderContext CmdletProviderContext { get { - CmdletProviderContext coreCommandContext = - new CmdletProviderContext(this); + CmdletProviderContext coreCommandContext = new(this); Collection includeFilter = SessionStateUtilities.ConvertArrayToCollection(Include); @@ -208,8 +207,7 @@ public static string GetOwner(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - ObjectSecurity sd = instance.BaseObject as ObjectSecurity; - if (sd == null) + if (!(instance.BaseObject is ObjectSecurity sd)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -248,8 +246,7 @@ public static string GetGroup(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - ObjectSecurity sd = instance.BaseObject as ObjectSecurity; - if (sd == null) + if (!(instance.BaseObject is ObjectSecurity sd)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -294,20 +291,17 @@ public static AuthorizationRuleCollection GetAccess(PSObject instance) } // Get DACL - AuthorizationRuleCollection dacl; CommonObjectSecurity cos = sd as CommonObjectSecurity; if (cos != null) { - dacl = cos.GetAccessRules(true, true, typeof(NTAccount)); + return cos.GetAccessRules(true, true, typeof(NTAccount)); } else { DirectoryObjectSecurity dos = sd as DirectoryObjectSecurity; Dbg.Diagnostics.Assert(dos != null, "Acl should be of type CommonObjectSecurity or DirectoryObjectSecurity"); - dacl = dos.GetAccessRules(true, true, typeof(NTAccount)); + return dos.GetAccessRules(true, true, typeof(NTAccount)); } - - return dacl; } /// @@ -332,20 +326,17 @@ public static AuthorizationRuleCollection GetAudit(PSObject instance) PSTraceSource.NewArgumentException(nameof(instance)); } - AuthorizationRuleCollection sacl; CommonObjectSecurity cos = sd as CommonObjectSecurity; if (cos != null) { - sacl = cos.GetAuditRules(true, true, typeof(NTAccount)); + return cos.GetAuditRules(true, true, typeof(NTAccount)); } else { DirectoryObjectSecurity dos = sd as DirectoryObjectSecurity; Dbg.Diagnostics.Assert(dos != null, "Acl should be of type CommonObjectSecurity or DirectoryObjectSecurity"); - sacl = dos.GetAuditRules(true, true, typeof(NTAccount)); + return dos.GetAuditRules(true, true, typeof(NTAccount)); } - - return sacl; } /// @@ -359,11 +350,10 @@ public static AuthorizationRuleCollection GetAudit(PSObject instance) /// public static SecurityIdentifier GetCentralAccessPolicyId(PSObject instance) { - SessionState sessionState = new SessionState(); + SessionState sessionState = new(); string path = sessionState.Path.GetUnresolvedProviderPathFromPSPath( GetPath(instance)); - IntPtr pOwner = IntPtr.Zero, pGroup = IntPtr.Zero; - IntPtr pDacl = IntPtr.Zero, pSacl = IntPtr.Zero, pSd = IntPtr.Zero; + IntPtr pSd = IntPtr.Zero; try { @@ -372,10 +362,10 @@ public static SecurityIdentifier GetCentralAccessPolicyId(PSObject instance) path, NativeMethods.SeObjectType.SE_FILE_OBJECT, NativeMethods.SecurityInformation.SCOPE_SECURITY_INFORMATION, - out pOwner, - out pGroup, - out pDacl, - out pSacl, + out IntPtr pOwner, + out IntPtr pGroup, + out IntPtr pDacl, + out IntPtr pSacl, out pSd); if (rs != NativeMethods.ERROR_SUCCESS) { @@ -387,8 +377,7 @@ public static SecurityIdentifier GetCentralAccessPolicyId(PSObject instance) return null; } - NativeMethods.ACL sacl = new NativeMethods.ACL(); - sacl = Marshal.PtrToStructure(pSacl); + NativeMethods.ACL sacl = Marshal.PtrToStructure(pSacl); if (sacl.AceCount == 0) { return null; @@ -398,8 +387,7 @@ public static SecurityIdentifier GetCentralAccessPolicyId(PSObject instance) IntPtr pAce = pSacl + Marshal.SizeOf(new NativeMethods.ACL()); for (ushort aceIdx = 0; aceIdx < sacl.AceCount; aceIdx++) { - NativeMethods.ACE_HEADER ace = new NativeMethods.ACE_HEADER(); - ace = Marshal.PtrToStructure(pAce); + NativeMethods.ACE_HEADER ace = Marshal.PtrToStructure(pAce); Dbg.Diagnostics.Assert(ace.AceType == NativeMethods.SYSTEM_SCOPED_POLICY_ID_ACE_TYPE, "Unexpected ACE type: " + ace.AceType.ToString(CultureInfo.CurrentCulture)); @@ -460,12 +448,11 @@ public static string GetCentralAccessPolicyName(PSObject instance) Marshal.Copy(capIdArray, 0, pCapId, capIdSize); IntPtr[] ppCapId = new IntPtr[1]; ppCapId[0] = pCapId; - uint capCount = 0; uint rs = NativeMethods.LsaQueryCAPs( ppCapId, 1, out caps, - out capCount); + out uint capCount); if (rs != NativeMethods.STATUS_SUCCESS) { throw new Win32Exception((int)rs); @@ -477,8 +464,7 @@ public static string GetCentralAccessPolicyName(PSObject instance) } // Get the CAP name. - NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY(); - cap = Marshal.PtrToStructure(caps); + NativeMethods.CENTRAL_ACCESS_POLICY cap = Marshal.PtrToStructure(caps); // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes. return Marshal.PtrToStringUni(cap.Name.Buffer, cap.Name.Length / 2); } @@ -510,12 +496,11 @@ public static string[] GetAllCentralAccessPolicies(PSObject instance) try { // Retrieve all CAPs. - uint capCount = 0; uint rs = NativeMethods.LsaQueryCAPs( null, 0, out caps, - out capCount); + out uint capCount); if (rs != NativeMethods.STATUS_SUCCESS) { throw new Win32Exception((int)rs); @@ -530,14 +515,13 @@ public static string[] GetAllCentralAccessPolicies(PSObject instance) // Add CAP names and IDs to a string array. string[] policies = new string[capCount]; - NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY(); IntPtr capPtr = caps; for (uint capIdx = 0; capIdx < capCount; capIdx++) { // Retrieve CAP name. Dbg.Diagnostics.Assert(capPtr != IntPtr.Zero, "Invalid central access policies array"); - cap = Marshal.PtrToStructure(capPtr); + NativeMethods.CENTRAL_ACCESS_POLICY cap = Marshal.PtrToStructure(capPtr); // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes. policies[capIdx] = "\"" + Marshal.PtrToStringUni( cap.Name.Buffer, @@ -588,8 +572,7 @@ public static string GetSddl(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - ObjectSecurity sd = instance.BaseObject as ObjectSecurity; - if (sd == null) + if (!(instance.BaseObject is ObjectSecurity sd)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -656,7 +639,7 @@ public string[] Path } } - private PSObject _inputObject = null; + private PSObject _inputObject; /// /// InputObject Parameter @@ -698,7 +681,7 @@ public string[] LiteralPath } } - private bool _isLiteralPath = false; + private bool _isLiteralPath; /// /// Gets or sets the audit flag of the command. This flag @@ -761,7 +744,6 @@ public SwitchParameter AllCentralAccessPolicies /// protected override void ProcessRecord() { - Collection sd = null; AccessControlSections sections = AccessControlSections.Owner | AccessControlSections.Group | @@ -818,7 +800,7 @@ protected override void ProcessRecord() { foreach (string p in Path) { - List pathsToProcess = new List(); + List pathsToProcess = new(); string currentPath = null; try @@ -841,7 +823,7 @@ protected override void ProcessRecord() { currentPath = rp; - CmdletProviderContext context = new CmdletProviderContext(this.Context); + CmdletProviderContext context = new(this.Context); context.SuppressWildcardExpansion = true; if (!InvokeProvider.Item.Exists(rp, false, _isLiteralPath)) @@ -858,7 +840,7 @@ protected override void ProcessRecord() InvokeProvider.SecurityDescriptor.Get(rp, sections, context); - sd = context.GetAccumulatedObjects(); + Collection sd = context.GetAccumulatedObjects(); if (sd != null) { AddBrokeredProperties( @@ -924,7 +906,7 @@ public string[] Path } } - private PSObject _inputObject = null; + private PSObject _inputObject; /// /// InputObject Parameter @@ -965,7 +947,7 @@ public string[] LiteralPath } } - private bool _isLiteralPath = false; + private bool _isLiteralPath; private object _securityDescriptor; @@ -1063,7 +1045,7 @@ public SwitchParameter Passthru /// Returns a newly allocated SACL with no ACEs in it. /// Free the returned SACL by calling Marshal.FreeHGlobal. /// - private IntPtr GetEmptySacl() + private static IntPtr GetEmptySacl() { IntPtr pSacl = IntPtr.Zero; bool ret = true; @@ -1128,12 +1110,11 @@ private IntPtr GetSaclWithCapId(string capStr) // be deallocated separately (but with the entire buffer // returned by LsaQueryCAPs). freeCapId = false; - uint capCount = 0; rs = NativeMethods.LsaQueryCAPs( null, 0, out caps, - out capCount); + out uint capCount); if (rs != NativeMethods.STATUS_SUCCESS) { throw new Win32Exception((int)rs); @@ -1147,13 +1128,12 @@ private IntPtr GetSaclWithCapId(string capStr) } // Find the supplied string among available CAP names, use the corresponding CAPID. - NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY(); IntPtr capPtr = caps; for (uint capIdx = 0; capIdx < capCount; capIdx++) { Dbg.Diagnostics.Assert(capPtr != IntPtr.Zero, "Invalid central access policies array"); - cap = Marshal.PtrToStructure(capPtr); + NativeMethods.CENTRAL_ACCESS_POLICY cap = Marshal.PtrToStructure(capPtr); // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes. string capName = Marshal.PtrToStringUni( cap.Name.Buffer, @@ -1249,7 +1229,7 @@ private IntPtr GetSaclWithCapId(string capStr) /// and the previous state of this privilege. Free the returned token /// by calling NativeMethods.CloseHandle. /// - private IntPtr GetTokenWithEnabledPrivilege( + private static IntPtr GetTokenWithEnabledPrivilege( string privilege, NativeMethods.TOKEN_PRIVILEGE previousState) { @@ -1283,7 +1263,7 @@ private IntPtr GetTokenWithEnabledPrivilege( } // Get the LUID of the specified privilege. - NativeMethods.LUID luid = new NativeMethods.LUID(); + NativeMethods.LUID luid = new(); ret = NativeMethods.LookupPrivilegeValue( null, privilege, @@ -1294,7 +1274,7 @@ private IntPtr GetTokenWithEnabledPrivilege( } // Enable the privilege. - NativeMethods.TOKEN_PRIVILEGE newState = new NativeMethods.TOKEN_PRIVILEGE(); + NativeMethods.TOKEN_PRIVILEGE newState = new(); newState.PrivilegeCount = 1; newState.Privilege.Attributes = NativeMethods.SE_PRIVILEGE_ENABLED; newState.Privilege.Luid = luid; @@ -1337,14 +1317,13 @@ protected override void ProcessRecord() if (methodInfo != null) { - CommonSecurityDescriptor aclCommonSD = _securityDescriptor as CommonSecurityDescriptor; string sddl; if (aclObjectSecurity != null) { sddl = aclObjectSecurity.GetSecurityDescriptorSddlForm(AccessControlSections.All); } - else if (aclCommonSD != null) + else if (_securityDescriptor is CommonSecurityDescriptor aclCommonSD) { sddl = aclCommonSD.GetSddlForm(AccessControlSections.All); } @@ -1439,7 +1418,7 @@ protected override void ProcessRecord() } IntPtr pSacl = IntPtr.Zero; - NativeMethods.TOKEN_PRIVILEGE previousState = new NativeMethods.TOKEN_PRIVILEGE(); + NativeMethods.TOKEN_PRIVILEGE previousState = new(); try { if (CentralAccessPolicy != null) @@ -1447,8 +1426,7 @@ protected override void ProcessRecord() pSacl = GetSaclWithCapId(CentralAccessPolicy); if (pSacl == IntPtr.Zero) { - SystemException e = new SystemException( - UtilsStrings.GetSaclWithCapIdFail); + SystemException e = new(UtilsStrings.GetSaclWithCapIdFail); WriteError(new ErrorRecord(e, "SetAcl_CentralAccessPolicy", ErrorCategory.InvalidResult, @@ -1461,8 +1439,7 @@ protected override void ProcessRecord() pSacl = GetEmptySacl(); if (pSacl == IntPtr.Zero) { - SystemException e = new SystemException( - UtilsStrings.GetEmptySaclFail); + SystemException e = new(UtilsStrings.GetEmptySaclFail); WriteError(new ErrorRecord(e, "SetAcl_ClearCentralAccessPolicy", ErrorCategory.InvalidResult, @@ -1473,15 +1450,14 @@ protected override void ProcessRecord() foreach (string p in Path) { - Collection pathsToProcess = new Collection(); + Collection pathsToProcess = new(); CmdletProviderContext context = this.CmdletProviderContext; context.PassThru = Passthru; if (_isLiteralPath) { - ProviderInfo Provider = null; - PSDriveInfo Drive = null; - string pathStr = SessionState.Path.GetUnresolvedProviderPathFromPSPath(p, out Provider, out Drive); + string pathStr = SessionState.Path.GetUnresolvedProviderPathFromPSPath( + p, out ProviderInfo Provider, out PSDriveInfo Drive); pathsToProcess.Add(new PathInfo(Drive, Provider, pathStr, SessionState)); context.SuppressWildcardExpansion = true; } @@ -1517,8 +1493,7 @@ protected override void ProcessRecord() IntPtr pToken = GetTokenWithEnabledPrivilege("SeSecurityPrivilege", previousState); if (pToken == IntPtr.Zero) { - SystemException e = new SystemException( - UtilsStrings.GetTokenWithEnabledPrivilegeFail); + SystemException e = new(UtilsStrings.GetTokenWithEnabledPrivilegeFail); WriteError(new ErrorRecord(e, "SetAcl_AdjustTokenPrivileges", ErrorCategory.InvalidResult, @@ -1539,7 +1514,7 @@ protected override void ProcessRecord() // Restore privileges to the previous state. if (pToken != IntPtr.Zero) { - NativeMethods.TOKEN_PRIVILEGE newState = new NativeMethods.TOKEN_PRIVILEGE(); + NativeMethods.TOKEN_PRIVILEGE newState = new(); uint newSize = 0; NativeMethods.AdjustTokenPrivileges( pToken, @@ -1591,4 +1566,3 @@ protected override void ProcessRecord() } #pragma warning restore 56506 - diff --git a/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs b/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs index 5d094413904..a86bf657853 100644 --- a/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs @@ -4,14 +4,10 @@ #if !UNIX using System; +using System.Collections.ObjectModel; +using System.IO; using System.Management.Automation; using Dbg = System.Management.Automation.Diagnostics; -using System.Collections; -using System.IO; -using System.Management.Automation.Provider; -using System.Runtime.InteropServices; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; namespace Microsoft.PowerShell.Commands { @@ -60,7 +56,7 @@ public string[] Path // // name of this command // - private string commandName; + private readonly string commandName; /// /// Initializes a new instance of the CatalogCommandsBase class, @@ -90,7 +86,7 @@ protected override void ProcessRecord() Dbg.Assert((CatalogFilePath != null) && (CatalogFilePath.Length > 0), "CatalogCommands: Param binder did not bind catalogFilePath"); - Collection paths = new Collection(); + Collection paths = new(); if (Path != null) { @@ -186,7 +182,7 @@ protected override void PerformAction(Collection path, string catalogFil path.Add(SessionState.Path.CurrentFileSystemLocation.Path); } - FileInfo catalogFileInfo = new FileInfo(catalogFilePath); + FileInfo catalogFileInfo = new(catalogFilePath); // If Path points to the expected cat file make sure // parent Directory exists other wise CryptoAPI fails to create a .cat file diff --git a/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs b/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs index 28163845d22..4723aa7fbf0 100644 --- a/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs @@ -1,11 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Management.Automation; using System.Security; using System.Security.Cryptography; @@ -80,7 +77,7 @@ public string[] LiteralPath // // list of files that were not found // - private List _filesNotFound = new List(); + private readonly List _filesNotFound = new(); /// /// Initializes a new instance of the GetPfxCertificateCommand @@ -108,7 +105,7 @@ protected override void ProcessRecord() foreach (string p in FilePath) { - List paths = new List(); + List paths = new(); // Expand wildcard characters if (_isLiteralPath) @@ -163,11 +160,11 @@ protected override void ProcessRecord() } catch (CryptographicException e) { - ErrorRecord er = - new ErrorRecord(e, - "GetPfxCertificateUnknownCryptoError", - ErrorCategory.NotSpecified, - null); + ErrorRecord er = new( + e, + "GetPfxCertificateUnknownCryptoError", + ErrorCategory.NotSpecified, + targetObject: null); WriteError(er); continue; } @@ -216,4 +213,3 @@ private static X509Certificate2 GetCertFromPfxFile(string path, SecureString pas } } } - diff --git a/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs b/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs index ff66e7c9932..1292ecb9b55 100644 --- a/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs +++ b/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs @@ -4,28 +4,29 @@ #if !UNIX using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; using System.Management.Automation; using System.Management.Automation.Host; using System.Management.Automation.Internal; -using Runspaces = System.Management.Automation.Runspaces; -using Dbg = System.Management.Automation; -using Security = System.Management.Automation.Security; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections; -using System.Runtime.InteropServices; using System.Management.Automation.Provider; +using System.Runtime.InteropServices; +using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text.RegularExpressions; -using System.Globalization; -using System.IO; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Xml; using System.Xml.XPath; -using System.Security; + +using Dbg = System.Management.Automation; using DWORD = System.UInt32; +using Runspaces = System.Management.Automation.Runspaces; +using Security = System.Management.Automation.Security; namespace Microsoft.PowerShell.Commands { @@ -50,7 +51,7 @@ public SwitchParameter CodeSigningCert set { _codeSigningCert = value; } } - private SwitchParameter _codeSigningCert = new SwitchParameter(); + private SwitchParameter _codeSigningCert = new(); /// /// Gets or sets a filter that controls whether we only return @@ -122,17 +123,17 @@ public int ExpiringInDays /// The structure contains punycode name and unicode name. /// [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] - public struct DnsNameRepresentation + public readonly struct DnsNameRepresentation { /// /// Punycode version of DNS name. /// - private string _punycodeName; + private readonly string _punycodeName; /// /// Unicode version of DNS name. /// - private string _unicodeName; + private readonly string _unicodeName; /// /// Ambiguous constructor of a DnsNameRepresentation. @@ -213,9 +214,9 @@ public override string ToString() // to differ only by upper/lower case. If they do, that's really // a code bug, and the effect is to just display both strings. - return string.Equals(_punycodeName, _unicodeName) ? - _punycodeName : - _unicodeName + " (" + _punycodeName + ")"; + return string.Equals(_punycodeName, _unicodeName, StringComparison.Ordinal) + ? _punycodeName + : _unicodeName + " (" + _punycodeName + ")"; } } @@ -249,7 +250,7 @@ public SwitchParameter DeleteKey } } - private SwitchParameter _deleteKey = new SwitchParameter(); + private SwitchParameter _deleteKey = new(); } /// @@ -272,7 +273,7 @@ protected override bool ReleaseHandle() { bool fResult = false; - if (IntPtr.Zero != handle) + if (handle != IntPtr.Zero) { fResult = Security.NativeMethods.CertCloseStore(handle, 0); handle = IntPtr.Zero; @@ -349,7 +350,7 @@ public void Open(bool includeArchivedCerts) IntPtr.Zero, // hCryptProv StoreFlags, _storeName); - if (IntPtr.Zero == hCertStore) + if (hCertStore == IntPtr.Zero) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } @@ -441,12 +442,12 @@ public IntPtr GetCertByName(string Name) while (true) { certContext = GetNextCert(certContext); - if (IntPtr.Zero == certContext) + if (certContext == IntPtr.Zero) { break; } - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); if (string.Equals( cert.Thumbprint, Name, @@ -511,8 +512,8 @@ public bool Valid } private bool _archivedCerts = false; - private X509StoreLocation _storeLocation = null; - private string _storeName = null; + private readonly X509StoreLocation _storeLocation = null; + private readonly string _storeName = null; private CertificateStoreHandle _storeHandle = null; private bool _valid = false; private bool _open = false; @@ -581,7 +582,7 @@ public sealed class CertificateProvider : NavigationCmdletProvider, ICmdletProvi /// -- storeLocations /// -- pathCache. /// - private static object s_staticLock = new object(); + private static readonly object s_staticLock = new(); /// /// List of store locations. They do not change once initialized. @@ -634,7 +635,7 @@ private static Regex CertPathRegex { if (s_certPathRegex == null) { - RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled; + const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled; s_certPathRegex = new Regex(certPathPattern, options); } } @@ -663,8 +664,7 @@ public CertificateProvider() // // create and cache CurrentUser store-location // - X509StoreLocation user = - new X509StoreLocation(StoreLocation.CurrentUser); + X509StoreLocation user = new(StoreLocation.CurrentUser); s_storeLocations.Add(user); AddItemToCache(nameof(StoreLocation.CurrentUser), user); @@ -672,8 +672,7 @@ public CertificateProvider() // // create and cache LocalMachine store-location // - X509StoreLocation machine = - new X509StoreLocation(StoreLocation.LocalMachine); + X509StoreLocation machine = new(StoreLocation.LocalMachine); s_storeLocations.Add(machine); AddItemToCache(nameof(StoreLocation.LocalMachine), machine); @@ -720,7 +719,7 @@ protected override void RemoveItem( string.Equals(pathElements[1], "ROOT", StringComparison.OrdinalIgnoreCase)) { string message = CertificateProviderStrings.UINotAllowed; - string errorId = "UINotAllowed"; + const string errorId = "UINotAllowed"; ThrowInvalidOperation(errorId, message); } @@ -745,7 +744,7 @@ protected override void RemoveItem( if (fUserContext) { string message = CertificateProviderStrings.CannotDeleteUserStore; - string errorId = "CannotDeleteUserStore"; + const string errorId = "CannotDeleteUserStore"; ThrowInvalidOperation(errorId, message); } @@ -755,7 +754,7 @@ protected override void RemoveItem( else // other container than a store { string message = CertificateProviderStrings.CannotRemoveContainer; - string errorId = "CannotRemoveContainer"; + const string errorId = "CannotRemoveContainer"; ThrowInvalidOperation(errorId, message); } } @@ -826,7 +825,7 @@ protected override void MoveItem( if (isContainer) { string message = CertificateProviderStrings.CannotMoveContainer; - string errorId = "CannotMoveContainer"; + const string errorId = "CannotMoveContainer"; ThrowInvalidOperation(errorId, message); } @@ -843,7 +842,7 @@ protected override void MoveItem( else { string message = CertificateProviderStrings.InvalidDestStore; - string errorId = "InvalidDestStore"; + const string errorId = "InvalidDestStore"; ThrowInvalidOperation(errorId, message); } } @@ -855,14 +854,14 @@ protected override void MoveItem( if (!string.Equals(pathElements[0], destElements[0], StringComparison.OrdinalIgnoreCase)) { string message = CertificateProviderStrings.CannotMoveCrossContext; - string errorId = "CannotMoveCrossContext"; + const string errorId = "CannotMoveCrossContext"; ThrowInvalidOperation(errorId, message); } if (string.Equals(pathElements[1], destElements[1], StringComparison.OrdinalIgnoreCase)) { string message = CertificateProviderStrings.CannotMoveToSameStore; - string errorId = "CannotMoveToSameStore"; + const string errorId = "CannotMoveToSameStore"; ThrowInvalidOperation(errorId, message); } @@ -876,7 +875,7 @@ protected override void MoveItem( string.Equals(destElements[1], "ROOT", StringComparison.OrdinalIgnoreCase))) { string message = CertificateProviderStrings.UINotAllowed; - string errorId = "UINotAllowed"; + const string errorId = "UINotAllowed"; ThrowInvalidOperation(errorId, message); } } @@ -960,7 +959,7 @@ protected override void NewItem( if (pathElements.Length != 2) { string message = CertificateProviderStrings.CannotCreateItem; - string errorId = "CannotCreateItem"; + const string errorId = "CannotCreateItem"; ThrowInvalidOperation(errorId, message); } @@ -970,11 +969,11 @@ protected override void NewItem( if (fUserContext) { string message = CertificateProviderStrings.CannotCreateUserStore; - string errorId = "CannotCreateUserStore"; + const string errorId = "CannotCreateUserStore"; ThrowInvalidOperation(errorId, message); } - Security.NativeMethods.CertOpenStoreFlags StoreFlags = + const Security.NativeMethods.CertOpenStoreFlags StoreFlags = Security.NativeMethods.CertOpenStoreFlags.CERT_STORE_CREATE_NEW_FLAG | Security.NativeMethods.CertOpenStoreFlags.CERT_STORE_MAXIMUM_ALLOWED_FLAG | Security.NativeMethods.CertOpenStoreFlags.CERT_SYSTEM_STORE_LOCAL_MACHINE; @@ -986,7 +985,7 @@ protected override void NewItem( IntPtr.Zero, // hCryptProv StoreFlags, pathElements[1]); - if (IntPtr.Zero == hCertStore) + if (hCertStore == IntPtr.Zero) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } @@ -996,9 +995,7 @@ protected override void NewItem( fResult = Security.NativeMethods.CertCloseStore(hCertStore, 0); } - X509Store outStore = new X509Store( - pathElements[1], - StoreLocation.LocalMachine); + X509Store outStore = new(pathElements[1], StoreLocation.LocalMachine); WriteItemObject(outStore, path, true); } @@ -1015,15 +1012,14 @@ protected override Collection InitializeDefaultDrives() { string providerDescription = CertificateProviderStrings.CertProvidername; - PSDriveInfo drive = - new PSDriveInfo( - "Cert", // drive name - ProviderInfo,// provider name - @"\", // root path - providerDescription, - null); + PSDriveInfo drive = new( + name: "Cert", + provider: ProviderInfo, + root: @"\", + providerDescription, + credential: null); - Collection drives = new Collection(); + Collection drives = new(); drives.Add(drive); return drives; @@ -1083,7 +1079,7 @@ protected override bool HasChildItems(string path) { store.Open(IncludeArchivedCerts()); IntPtr certContext = store.GetFirstCert(); - if (IntPtr.Zero != certContext) + if (certContext != IntPtr.Zero) { store.FreeCert(certContext); result = true; @@ -1273,9 +1269,7 @@ protected override void GetItem(string path) if (store != null) { // create X509Store - X509Store outStore = new X509Store( - store.StoreName, - store.Location.Location); + X509Store outStore = new(store.StoreName, store.Location.Location); WriteItemObject(outStore, path, isContainer); } } @@ -1348,7 +1342,7 @@ private void AttemptToImportPkiModule() new CmdletInfo( "Import-Module", typeof(Microsoft.PowerShell.Commands.ImportModuleCommand)); - Runspaces.Command importModuleCommand = new Runspaces.Command(commandInfo); + Runspaces.Command importModuleCommand = new(commandInfo); s_tracer.WriteLine("Attempting to load module: {0}", moduleName); @@ -1373,7 +1367,7 @@ private void AttemptToImportPkiModule() _hasAttemptedToLoadPkiModule = true; } - private string MyGetChildName(string path) + private static string MyGetChildName(string path) { // Verify the parameters @@ -1414,7 +1408,7 @@ protected override void InvokeDefaultAction(string path) { path = NormalizePath(path); string action = CertificateProviderStrings.Action_Invoke; - string certmgr = "certmgr.msc"; + const string certmgr = "certmgr.msc"; string certPath = System.IO.Path.Combine( System.Environment.ExpandEnvironmentVariables("%windir%"), "system32"); @@ -1481,7 +1475,7 @@ private static ErrorRecord CreateErrorRecord(string path, message = string.Format( System.Globalization.CultureInfo.CurrentCulture, message, path); - ErrorDetails ed = new ErrorDetails(message); + ErrorDetails ed = new(message); // // create appropriate exception type @@ -1505,11 +1499,11 @@ private static ErrorRecord CreateErrorRecord(string path, break; } - ErrorRecord er = - new ErrorRecord(e, - "CertProviderItemNotFound", - ErrorCategory.ObjectNotFound, - null); + ErrorRecord er = new( + e, + "CertProviderItemNotFound", + ErrorCategory.ObjectNotFound, + targetObject: null); er.ErrorDetails = ed; @@ -1525,7 +1519,7 @@ private void ThrowErrorRemoting(int stat) string message = CertificateProviderStrings.RemoteErrorMessage; error += message; - Exception e2 = new Exception(error); + Exception e2 = new(error); ThrowTerminatingError( new ErrorRecord( e2, @@ -1541,11 +1535,11 @@ private void ThrowErrorRemoting(int stat) private void ThrowInvalidOperation(string errorId, string message) { - ErrorRecord errorRecord = new ErrorRecord( - new InvalidOperationException(message), - errorId, - ErrorCategory.InvalidOperation, - null); + ErrorRecord errorRecord = new( + new InvalidOperationException(message), + errorId, + ErrorCategory.InvalidOperation, + targetObject: null); errorRecord.ErrorDetails = new ErrorDetails(message); ThrowTerminatingError(errorRecord); @@ -1584,7 +1578,7 @@ private static string[] GetPathElements(string path) string[] allElts = path.Split(s_pathSeparators); string[] result = null; - Stack elts = new Stack(); + Stack elts = new(); foreach (string e in allElts) { @@ -1703,7 +1697,7 @@ private void DoDeleteKey(IntPtr pProvInfo) ThrowErrorRemoting(stat); } - if (0 != (cngKeyFlag & (uint)Security.NativeMethods.NCryptDeletKeyFlag.NCRYPT_SILENT_FLAG)) + if ((cngKeyFlag & (uint)Security.NativeMethods.NCryptDeletKeyFlag.NCRYPT_SILENT_FLAG) != 0) { unsafe { @@ -1749,7 +1743,7 @@ private void RemoveCertStore(string storeName, bool fDeleteKey, string sourcePat // if recurse is true, remove every cert in the store IntPtr localName = Security.NativeMethods.CryptFindLocalizedName(storeName); string[] pathElements = GetPathElements(sourcePath); - if (IntPtr.Zero == localName)//not find, we can remove + if (localName == IntPtr.Zero)//not find, we can remove { X509NativeStore store = null; @@ -1763,16 +1757,16 @@ private void RemoveCertStore(string storeName, bool fDeleteKey, string sourcePat // enumerate over each cert and remove it // IntPtr certContext = store.GetFirstCert(); - while (IntPtr.Zero != certContext) + while (certContext != IntPtr.Zero) { - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); string certPath = sourcePath + cert.Thumbprint; RemoveCertItem(cert, fDeleteKey, true, certPath); certContext = store.GetNextCert(certContext); } // remove the cert store - Security.NativeMethods.CertOpenStoreFlags StoreFlags = + const Security.NativeMethods.CertOpenStoreFlags StoreFlags = Security.NativeMethods.CertOpenStoreFlags.CERT_STORE_READONLY_FLAG | Security.NativeMethods.CertOpenStoreFlags.CERT_STORE_OPEN_EXISTING_FLAG | Security.NativeMethods.CertOpenStoreFlags.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | @@ -1793,7 +1787,7 @@ private void RemoveCertStore(string storeName, bool fDeleteKey, string sourcePat CultureInfo.CurrentCulture, CertificateProviderStrings.RemoveStoreTemplate, storeName); - string errorId = "CannotRemoveSystemStore"; + const string errorId = "CannotRemoveSystemStore"; ThrowInvalidOperation(errorId, message); } } @@ -1919,7 +1913,7 @@ private void DoRemove(X509Certificate2 cert, bool fDeleteKey, bool fMachine, str /// /// An IntPtr for store handle. /// No return. - private void CommitUserDS(IntPtr storeHandle) + private static void CommitUserDS(IntPtr storeHandle) { if (!Security.NativeMethods.CertControlStore( storeHandle, @@ -1985,7 +1979,7 @@ private void DoMove(string destination, X509Certificate2 cert, X509NativeStore s } // get the output object - X509Certificate2 outObj = new X509Certificate2(outCert); + X509Certificate2 outObj = new(outCert); string certName = GetCertName(outObj); string certPath = MakePath(destination, certName); WriteItemObject((object)outObj, certPath, false); @@ -2016,16 +2010,14 @@ private object GetItemAtPath(string path, bool test, out bool isContainer) // // Thus lengths 1 & 2 are container items. // - isContainer = (pathElements.Length >= 0) && - (pathElements.Length <= 2); + isContainer = pathElements.Length <= 2; X509NativeStore store = null; // // handle invalid path depth // - if ((pathElements.Length > 3) || - (pathElements.Length < 0)) + if (pathElements.Length > 3) { if (test) { @@ -2098,7 +2090,7 @@ private object GetItemAtPath(string path, bool test, out bool isContainer) store.Open(IncludeArchivedCerts()); IntPtr certContext = store.GetCertByName(pathElements[2]); - if (IntPtr.Zero == certContext) + if (certContext == IntPtr.Zero) { if (test) { @@ -2449,9 +2441,9 @@ private void GetCertificatesOrNames(string path, // IntPtr certContext = store.GetFirstCert(); - while (IntPtr.Zero != certContext) + while (certContext != IntPtr.Zero) { - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); if (MatchesFilter(cert, filter)) { @@ -2464,7 +2456,7 @@ private void GetCertificatesOrNames(string path, } else { - PSObject myPsObj = new PSObject(cert); + PSObject myPsObj = new(cert); thingToReturn = (object)myPsObj; } @@ -2594,9 +2586,7 @@ private void GetStoresOrNames( else { X509NativeStore store = GetStore(storePath, name, location); - X509Store ManagedStore = new X509Store( - store.StoreName, - store.Location.Location); + X509Store ManagedStore = new(store.StoreName, store.Location.Location); thingToReturn = ManagedStore; } @@ -2670,19 +2660,19 @@ private CertificateFilterInfo GetFilter() if (dp.DocumentEncryptionCert) { - filter = filter ?? new CertificateFilterInfo(); + filter ??= new CertificateFilterInfo(); filter.Purpose = CertificatePurpose.DocumentEncryption; } if (dp.DnsName != null) { - filter = filter ?? new CertificateFilterInfo(); + filter ??= new CertificateFilterInfo(); filter.DnsName = new WildcardPattern(dp.DnsName, WildcardOptions.IgnoreCase); } if (dp.Eku != null) { - filter = filter ?? new CertificateFilterInfo(); + filter ??= new CertificateFilterInfo(); filter.Eku = new List(); foreach (var pattern in dp.Eku) { @@ -2692,13 +2682,13 @@ private CertificateFilterInfo GetFilter() if (dp.ExpiringInDays >= 0) { - filter = filter ?? new CertificateFilterInfo(); + filter ??= new CertificateFilterInfo(); filter.Expiring = DateTime.Now.AddDays(dp.ExpiringInDays); } if (dp.SSLServerAuthentication) { - filter = filter ?? new CertificateFilterInfo(); + filter ??= new CertificateFilterInfo(); filter.SSLServerAuthentication = true; } } @@ -2827,7 +2817,7 @@ internal static bool CertContainsEku(X509Certificate2 cert, List /// Gets the location as a - /// + /// /// public StoreLocation Location { @@ -3063,17 +3053,17 @@ public X509StoreLocation(StoreLocation location) /// The structure contains friendly name and EKU oid. /// [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] - public struct EnhancedKeyUsageRepresentation + public readonly struct EnhancedKeyUsageRepresentation { /// /// Localized friendly name of EKU. /// - private string _friendlyName; + private readonly string _friendlyName; /// /// OID of EKU. /// - private string _oid; + private readonly string _oid; /// /// Constructor of an EnhancedKeyUsageRepresentation. @@ -3193,7 +3183,7 @@ public static void WriteSendAsTrustedIssuerProperty(X509Certificate2 cert, strin if (DownLevelHelper.TrustedIssuerSupported()) { IntPtr propertyPtr = IntPtr.Zero; - Security.NativeMethods.CRYPT_DATA_BLOB dataBlob = new Security.NativeMethods.CRYPT_DATA_BLOB(); + Security.NativeMethods.CRYPT_DATA_BLOB dataBlob = new(); dataBlob.cbData = 0; dataBlob.pbData = IntPtr.Zero; X509Certificate certFromStore = null; @@ -3216,7 +3206,7 @@ public static void WriteSendAsTrustedIssuerProperty(X509Certificate2 cert, strin bool fUserContext = string.Equals(pathElements[1], "Certificate::CurrentUser", StringComparison.OrdinalIgnoreCase); X509StoreLocation storeLocation = - new X509StoreLocation(fUserContext ? StoreLocation.CurrentUser : StoreLocation.LocalMachine); + new(fUserContext ? StoreLocation.CurrentUser : StoreLocation.LocalMachine); // get certificate from the store pathElements[2] X509NativeStore store = null; @@ -3270,7 +3260,7 @@ private static string[] GetPathElements(string path) string[] allElts = path.Split(s_separators); string[] result = null; - Stack elts = new Stack(); + Stack elts = new(); foreach (string e in allElts) { @@ -3302,7 +3292,7 @@ private static string[] GetPathElements(string path) /// public sealed class EnhancedKeyUsageProperty { - private List _ekuList = new List(); + private readonly List _ekuList = new(); /// /// Get property of EKUList. @@ -3331,7 +3321,7 @@ public EnhancedKeyUsageProperty(X509Certificate2 cert) OidCollection oids = ext.EnhancedKeyUsages; foreach (Oid oid in oids) { - EnhancedKeyUsageRepresentation ekuString = new EnhancedKeyUsageRepresentation(oid.FriendlyName, oid.Value); + EnhancedKeyUsageRepresentation ekuString = new(oid.FriendlyName, oid.Value); _ekuList.Add(ekuString); } } @@ -3345,8 +3335,8 @@ public EnhancedKeyUsageProperty(X509Certificate2 cert) /// public sealed class DnsNameProperty { - private List _dnsList = new List(); - private System.Globalization.IdnMapping idnMapping = new System.Globalization.IdnMapping(); + private readonly List _dnsList = new(); + private readonly System.Globalization.IdnMapping idnMapping = new(); private const string dnsNamePrefix = "DNS Name="; private const string distinguishedNamePrefix = "CN="; @@ -3552,9 +3542,9 @@ internal static class Crypt32Helpers /// Lock that guards access to the following static members /// -- storeNames. /// - private static object s_staticLock = new object(); + private static readonly object s_staticLock = new(); - internal static readonly List storeNames = new List(); + internal static readonly List storeNames = new(); /// /// Get a list of store names at the specified location. @@ -3580,12 +3570,11 @@ internal static List GetStoreNamesAtLocation(StoreLocation location) break; } - Security.NativeMethods.CertEnumSystemStoreCallBackProto callBack = - new Security.NativeMethods.CertEnumSystemStoreCallBackProto(CertEnumSystemStoreCallBack); + Security.NativeMethods.CertEnumSystemStoreCallBackProto callBack = new(CertEnumSystemStoreCallBack); // Return a new list to avoid synchronization issues. - List names = new List(); + List names = new(); lock (s_staticLock) { storeNames.Clear(); diff --git a/src/Microsoft.PowerShell.Security/security/CmsCommands.cs b/src/Microsoft.PowerShell.Security/security/CmsCommands.cs index 4c90c02e941..9fde804d220 100644 --- a/src/Microsoft.PowerShell.Security/security/CmsCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CmsCommands.cs @@ -43,7 +43,7 @@ public PSObject Content set; } - private PSDataCollection _inputObjects = new PSDataCollection(); + private readonly PSDataCollection _inputObjects = new(); /// /// Gets or sets the content of the CMS Message by path. @@ -94,11 +94,15 @@ protected override void BeginProcessing() if ((resolvedPaths.Count > 1) || (!string.Equals(provider.Name, "FileSystem", StringComparison.OrdinalIgnoreCase))) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new ArgumentException( - string.Format(CultureInfo.InvariantCulture, - CmsCommands.FilePathMustBeFileSystemPath, Path)), - "FilePathMustBeFileSystemPath", ErrorCategory.ObjectNotFound, provider); + string.Format( + CultureInfo.InvariantCulture, + CmsCommands.FilePathMustBeFileSystemPath, + Path)), + "FilePathMustBeFileSystemPath", + ErrorCategory.ObjectNotFound, + provider); ThrowTerminatingError(error); } @@ -141,7 +145,7 @@ protected override void EndProcessing() if (_inputObjects.Count > 0) { - StringBuilder outputString = new StringBuilder(); + StringBuilder outputString = new(); Collection output = System.Management.Automation.PowerShell.Create() .AddCommand("Microsoft.PowerShell.Utility\\Out-String") @@ -206,7 +210,7 @@ public string Content set; } - private StringBuilder _contentBuffer = new StringBuilder(); + private readonly StringBuilder _contentBuffer = new(); /// /// Gets or sets the CMS Message by path. @@ -245,11 +249,15 @@ protected override void BeginProcessing() if ((resolvedPaths.Count > 1) || (!string.Equals(provider.Name, "FileSystem", StringComparison.OrdinalIgnoreCase))) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new ArgumentException( - string.Format(CultureInfo.InvariantCulture, - CmsCommands.FilePathMustBeFileSystemPath, Path)), - "FilePathMustBeFileSystemPath", ErrorCategory.ObjectNotFound, provider); + string.Format( + CultureInfo.InvariantCulture, + CmsCommands.FilePathMustBeFileSystemPath, + Path)), + "FilePathMustBeFileSystemPath", + ErrorCategory.ObjectNotFound, + provider); ThrowTerminatingError(error); } @@ -304,17 +312,17 @@ protected override void EndProcessing() byte[] contentBytes = CmsUtils.RemoveAsciiArmor(actualContent, CmsUtils.BEGIN_CMS_SIGIL, CmsUtils.END_CMS_SIGIL, out startIndex, out endIndex); if (contentBytes == null) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new ArgumentException(CmsCommands.InputContainedNoEncryptedContent), "InputContainedNoEncryptedContent", ErrorCategory.ObjectNotFound, null); ThrowTerminatingError(error); } - EnvelopedCms cms = new EnvelopedCms(); + EnvelopedCms cms = new(); cms.Decode(contentBytes); - PSObject result = new PSObject(cms); - List recipients = new List(); + PSObject result = new(cms); + List recipients = new(); foreach (RecipientInfo recipient in cms.RecipientInfos) { recipients.Add(recipient.RecipientIdentifier.Value); @@ -351,7 +359,7 @@ public string Content set; } - private StringBuilder _contentBuffer = new StringBuilder(); + private readonly StringBuilder _contentBuffer = new(); /// /// Gets or sets the Windows Event Log Message with contents to be decrypted. @@ -422,11 +430,15 @@ protected override void BeginProcessing() if ((resolvedPaths.Count > 1) || (!string.Equals(provider.Name, "FileSystem", StringComparison.OrdinalIgnoreCase))) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new ArgumentException( - string.Format(CultureInfo.InvariantCulture, - CmsCommands.FilePathMustBeFileSystemPath, Path)), - "FilePathMustBeFileSystemPath", ErrorCategory.ObjectNotFound, provider); + string.Format( + CultureInfo.InvariantCulture, + CmsCommands.FilePathMustBeFileSystemPath, + Path)), + "FilePathMustBeFileSystemPath", + ErrorCategory.ObjectNotFound, + provider); ThrowTerminatingError(error); } @@ -512,11 +524,15 @@ private string Decrypt(string actualContent) byte[] messageBytes = CmsUtils.RemoveAsciiArmor(actualContent, CmsUtils.BEGIN_CMS_SIGIL, CmsUtils.END_CMS_SIGIL, out startIndex, out endIndex); if ((messageBytes == null) && (!IncludeContext)) { - ErrorRecord error = new ErrorRecord( + ErrorRecord error = new( new ArgumentException( - string.Format(CultureInfo.InvariantCulture, - CmsCommands.InputContainedNoEncryptedContentIncludeContext, "-IncludeContext")), - "InputContainedNoEncryptedContentIncludeContext", ErrorCategory.ObjectNotFound, null); + string.Format( + CultureInfo.InvariantCulture, + CmsCommands.InputContainedNoEncryptedContentIncludeContext, + "-IncludeContext")), + "InputContainedNoEncryptedContentIncludeContext", + ErrorCategory.ObjectNotFound, + targetObject: null); ThrowTerminatingError(error); } @@ -536,8 +552,8 @@ private string Decrypt(string actualContent) } } - EnvelopedCms cms = new EnvelopedCms(); - X509Certificate2Collection certificates = new X509Certificate2Collection(); + EnvelopedCms cms = new(); + X509Certificate2Collection certificates = new(); if ((To != null) && (To.Length > 0)) { @@ -577,7 +593,7 @@ private string Decrypt(string actualContent) if (postContext != null) { - resultString = resultString + postContext; + resultString += postContext; } } @@ -585,4 +601,3 @@ private string Decrypt(string actualContent) } } } - diff --git a/src/Microsoft.PowerShell.Security/security/CredentialCommands.cs b/src/Microsoft.PowerShell.Security/security/CredentialCommands.cs index cb23979c77f..33238c0ca6c 100644 --- a/src/Microsoft.PowerShell.Security/security/CredentialCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CredentialCommands.cs @@ -104,7 +104,11 @@ protected override void BeginProcessing() } catch (ArgumentException exception) { - ErrorRecord errorRecord = new ErrorRecord(exception, "CouldNotPromptForCredential", ErrorCategory.InvalidOperation, null); + ErrorRecord errorRecord = new( + exception, + "CouldNotPromptForCredential", + ErrorCategory.InvalidOperation, + targetObject: null); WriteError(errorRecord); } diff --git a/src/Microsoft.PowerShell.Security/security/ExecutionPolicyCommands.cs b/src/Microsoft.PowerShell.Security/security/ExecutionPolicyCommands.cs index 7924fcd7652..dc526425c74 100644 --- a/src/Microsoft.PowerShell.Security/security/ExecutionPolicyCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/ExecutionPolicyCommands.cs @@ -65,11 +65,11 @@ protected override void BeginProcessing() { string message = ExecutionPolicyCommands.ListAndScopeSpecified; - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(), "ListAndScopeSpecified", ErrorCategory.InvalidOperation, - null); + targetObject: null); errorRecord.ErrorDetails = new ErrorDetails(message); ThrowTerminatingError(errorRecord); @@ -83,11 +83,10 @@ protected override void BeginProcessing() { foreach (ExecutionPolicyScope scope in SecuritySupport.ExecutionPolicyScopePreferences) { - PSObject outputObject = new PSObject(); + PSObject outputObject = new(); ExecutionPolicy policy = SecuritySupport.GetExecutionPolicy(shellId, scope); - PSNoteProperty inputNote = new PSNoteProperty( - "Scope", scope); + PSNoteProperty inputNote = new("Scope", scope); outputObject.Properties.Add(inputNote); inputNote = new PSNoteProperty( "ExecutionPolicy", policy); @@ -176,11 +175,11 @@ protected override void BeginProcessing() { string message = ExecutionPolicyCommands.CantSetGroupPolicy; - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new InvalidOperationException(), "CantSetGroupPolicy", ErrorCategory.InvalidOperation, - null); + targetObject: null); errorRecord.ErrorDetails = new ErrorDetails(message); ThrowTerminatingError(errorRecord); @@ -221,11 +220,11 @@ protected override void ProcessRecord() string message = StringUtil.Format(ExecutionPolicyCommands.ExecutionPolicyOverridden, effectiveExecutionPolicy); string recommendedAction = ExecutionPolicyCommands.ExecutionPolicyOverriddenRecommendedAction; - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( new System.Security.SecurityException(), "ExecutionPolicyOverride", ErrorCategory.PermissionDenied, - null); + targetObject: null); errorRecord.ErrorDetails = new ErrorDetails(message); errorRecord.ErrorDetails.RecommendedAction = recommendedAction; @@ -329,11 +328,11 @@ private bool IsProcessInteractive() private void OnAccessDeniedError(Exception exception) { string message = StringUtil.Format(ExecutionPolicyCommands.SetExecutionPolicyAccessDeniedError, exception.Message); - ErrorRecord errorRecord = new ErrorRecord( + ErrorRecord errorRecord = new( exception, exception.GetType().FullName, ErrorCategory.PermissionDenied, - null); + targetObject: null); errorRecord.ErrorDetails = new ErrorDetails(message); ThrowTerminatingError(errorRecord); diff --git a/src/Microsoft.PowerShell.Security/security/SecureStringCommands.cs b/src/Microsoft.PowerShell.Security/security/SecureStringCommands.cs index 74dee890cdf..821fe608efa 100644 --- a/src/Microsoft.PowerShell.Security/security/SecureStringCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/SecureStringCommands.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.Globalization; -using System.IO; using System.Management.Automation; using System.Runtime.InteropServices; using System.Security; @@ -35,7 +33,7 @@ protected SecureString SecureStringData // // name of this command // - private string _commandName; + private readonly string _commandName; /// /// Initializes a new instance of the SecureStringCommandBase @@ -241,7 +239,7 @@ public ConvertToSecureStringCommand() : base("ConvertTo-SecureString") { } /// Gets or sets the unsecured string to be imported. /// [Parameter(Position = 0, ValueFromPipeline = true, Mandatory = true)] - public String String + public string String { get { @@ -361,8 +359,7 @@ protected override void ProcessRecord() } else { - importedString = new SecureString(); - foreach (char currentChar in String) { importedString.AppendChar(currentChar); } + importedString = SecureStringHelper.FromPlainTextString(String); } } catch (ArgumentException e) @@ -391,4 +388,3 @@ protected override void ProcessRecord() } } } - diff --git a/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs b/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs index 91a3e8e3a83..5d5bb06b667 100644 --- a/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs @@ -2,22 +2,15 @@ // Licensed under the MIT License. using System; -using System.Collections; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Management.Automation; using System.Management.Automation.Internal; -using System.Management.Automation.Provider; -using System.Runtime.InteropServices; -using System.Security; using System.Security.Cryptography.X509Certificates; using Dbg = System.Management.Automation.Diagnostics; -using DWORD = System.UInt32; - namespace Microsoft.PowerShell.Commands { /// @@ -111,7 +104,10 @@ public string[] SourcePathOrExtension [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public byte[] Content { - get { return _content; } + get + { + return _content; + } set { @@ -124,7 +120,7 @@ public byte[] Content // // name of this command // - private string _commandName; + private readonly string _commandName; /// /// Initializes a new instance of the SignatureCommandsBase class, @@ -162,7 +158,7 @@ protected override void ProcessRecord() foreach (string p in FilePath) { - Collection paths = new Collection(); + Collection paths = new(); // Expand wildcard characters if (_isLiteralPath) @@ -471,7 +467,7 @@ protected override Signature PerformAction(string filePath) try { // remove readonly attributes on the file - FileInfo fInfo = new FileInfo(filePath); + FileInfo fInfo = new(filePath); if (fInfo != null) { // Save some disk write time by checking whether file is readonly.. @@ -487,56 +483,51 @@ protected override Signature PerformAction(string filePath) // These are the known exceptions for File.Load and StreamWriter.ctor catch (ArgumentException e) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( e, "ForceArgumentException", ErrorCategory.WriteError, - filePath - ); + filePath); WriteError(er); return null; } catch (IOException e) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( e, "ForceIOException", ErrorCategory.WriteError, - filePath - ); + filePath); WriteError(er); return null; } catch (UnauthorizedAccessException e) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( e, "ForceUnauthorizedAccessException", ErrorCategory.PermissionDenied, - filePath - ); + filePath); WriteError(er); return null; } catch (NotSupportedException e) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( e, "ForceNotSupportedException", ErrorCategory.WriteError, - filePath - ); + filePath); WriteError(er); return null; } catch (System.Security.SecurityException e) { - ErrorRecord er = new ErrorRecord( + ErrorRecord er = new( e, "ForceSecurityException", ErrorCategory.PermissionDenied, - filePath - ); + filePath); WriteError(er); return null; } @@ -555,7 +546,7 @@ protected override Signature PerformAction(string filePath) System.Globalization.CultureInfo.CurrentCulture, UtilsStrings.FileSmallerThan4Bytes, filePath); - PSArgumentException e = new PSArgumentException(message, nameof(filePath)); + PSArgumentException e = new(message, nameof(filePath)); ErrorRecord er = SecurityUtils.CreateInvalidArgumentErrorRecord( e, "SignatureCommandsBaseFileSmallerThan4Bytes" diff --git a/src/Microsoft.PowerShell.Security/security/Utils.cs b/src/Microsoft.PowerShell.Security/security/Utils.cs index f8eb7243285..702b44a8518 100644 --- a/src/Microsoft.PowerShell.Security/security/Utils.cs +++ b/src/Microsoft.PowerShell.Security/security/Utils.cs @@ -21,7 +21,7 @@ internal static long GetFileSize(string filePath) { long size = 0; - using (FileStream fs = new FileStream(filePath, FileMode.Open)) + using (FileStream fs = new(filePath, FileMode.Open)) { size = fs.Length; } @@ -64,14 +64,13 @@ ErrorRecord CreateFileNotFoundErrorRecord(string resourceStr, args ); - FileNotFoundException e = - new FileNotFoundException(message); + FileNotFoundException e = new(message); - ErrorRecord er = - new ErrorRecord(e, - errorId, - ErrorCategory.ObjectNotFound, - null); + ErrorRecord er = new( + e, + errorId, + ErrorCategory.ObjectNotFound, + targetObject: null); return er; } @@ -85,14 +84,13 @@ internal static ErrorRecord CreatePathNotFoundErrorRecord(string path, string errorId) { - ItemNotFoundException e = - new ItemNotFoundException(path, "PathNotFound", SessionStateStrings.PathNotFound); + ItemNotFoundException e = new(path, "PathNotFound", SessionStateStrings.PathNotFound); - ErrorRecord er = - new ErrorRecord(e, - errorId, - ErrorCategory.ObjectNotFound, - null); + ErrorRecord er = new( + e, + errorId, + ErrorCategory.ObjectNotFound, + targetObject: null); return er; } @@ -111,14 +109,13 @@ ErrorRecord CreateNotSupportedErrorRecord(string resourceStr, { string message = StringUtil.Format(resourceStr, args); - NotSupportedException e = - new NotSupportedException(message); + NotSupportedException e = new(message); - ErrorRecord er = - new ErrorRecord(e, - errorId, - ErrorCategory.NotImplemented, - null); + ErrorRecord er = new( + e, + errorId, + ErrorCategory.NotImplemented, + targetObject: null); return er; } @@ -133,11 +130,11 @@ internal static ErrorRecord CreateInvalidArgumentErrorRecord(Exception e, string errorId) { - ErrorRecord er = - new ErrorRecord(e, - errorId, - ErrorCategory.InvalidArgument, - null); + ErrorRecord er = new( + e, + errorId, + ErrorCategory.InvalidArgument, + targetObject: null); return er; } diff --git a/src/Microsoft.WSMan.Management/ConfigProvider.cs b/src/Microsoft.WSMan.Management/ConfigProvider.cs index 326f53d4d94..de99812b01d 100644 --- a/src/Microsoft.WSMan.Management/ConfigProvider.cs +++ b/src/Microsoft.WSMan.Management/ConfigProvider.cs @@ -43,12 +43,12 @@ public sealed class WSManConfigProvider : NavigationCmdletProvider, ICmdletProvi /// /// Object contains the cache of the enumerate results for the cmdlet to execute. /// - private Dictionary enumerateMapping = new Dictionary(); + private readonly Dictionary enumerateMapping = new Dictionary(); /// /// Mapping of ResourceURI with the XML returned by the Get call. /// - private Dictionary getMapping = new Dictionary(); + private readonly Dictionary getMapping = new Dictionary(); #region ICmdletProviderSupportsHelp Members @@ -193,7 +193,7 @@ protected override PSDriveInfo NewDrive(PSDriveInfo drive) return null; } - if (string.IsNullOrEmpty(drive.Root) == false) + if (!string.IsNullOrEmpty(drive.Root)) { AssertError(helper.GetResourceMsgFromResourcetext("NewDriveRootDoesNotExist"), false); return null; @@ -439,7 +439,7 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether it has Chi // 3. Plugin and its internal structure Checks else if (WsManURI.Contains(WSManStringLiterals.containerPlugin)) { - strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + strPathCheck += WSManStringLiterals.containerPlugin; // Check for Plugin path XmlDocument xmlPlugins = FindResourceValue(sessionobj, WsManURI, null); string currentpluginname = string.Empty; @@ -477,7 +477,7 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether it has Chi ArrayList arrSecurities = null; ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurities); ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); - strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + strPathCheck += WSManStringLiterals.DefaultPathSeparator; if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) { if (arrResources != null && arrResources.Count > 0) @@ -856,7 +856,7 @@ protected override void GetItem(string path) } } } - catch (PSArgumentNullException) { return;/*Leaving this known exception for no value found. Not Throwing error.*/} + catch (PSArgumentNullException) { return; /*Leaving this known exception for no value found. Not Throwing error.*/} catch (NullReferenceException) { return; /*Leaving this known exception for no value found. Not Throwing error.*/} } } @@ -1033,7 +1033,7 @@ protected override void SetItem(string path, object value) pluginConfiguration.UpdateOneConfiguration( ".", WSManStringLiterals.ConfigRunAsPasswordName, - this.GetStringFromSecureString(runAsCredentials.Password)); + GetStringFromSecureString(runAsCredentials.Password)); } } @@ -1050,7 +1050,7 @@ protected override void SetItem(string path, object value) AssertError(helper.GetResourceMsgFromResourcetext("SetItemOnRunAsPasswordNoRunAsUser"), false); } - value = this.GetStringFromSecureString(value); + value = GetStringFromSecureString(value); } pluginConfiguration.UpdateOneConfiguration(".", ChildName, value.ToString()); @@ -1237,7 +1237,7 @@ protected override void SetItem(string path, object value) pluginConfiguration.PutConfigurationOnServer(resourceUri); // Show Win RM service restart warning only when the changed setting is not picked up dynamically - if (settingPickedUpDynamically == false) + if (!settingPickedUpDynamically) { if (IsPathLocalMachine(host)) { @@ -1284,7 +1284,7 @@ protected override void SetItem(string path, object value) { if (!Force) { - string query = ""; + string query = string.Empty; string caption = helper.GetResourceMsgFromResourcetext("SetItemGeneralSecurityCaption"); if (ChildName.Equals("TrustedHosts", StringComparison.OrdinalIgnoreCase)) { @@ -1473,7 +1473,7 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether Item is Co strPathCheck = host + WSManStringLiterals.DefaultPathSeparator; if (WsManURI.Contains(WSManStringLiterals.containerListener)) { - strPathCheck = strPathCheck + WSManStringLiterals.containerListener; + strPathCheck += WSManStringLiterals.containerListener; if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) { return true; @@ -1494,7 +1494,7 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether Item is Co // 2. Client Certificate Checks else if (WsManURI.Contains(WSManStringLiterals.containerCertMapping)) { - strPathCheck = strPathCheck + WSManStringLiterals.containerClientCertificate; + strPathCheck += WSManStringLiterals.containerClientCertificate; if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) { return true; @@ -1514,19 +1514,19 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether Item is Co // 3. Plugin and its internal structure Checks else if (WsManURI.Contains(WSManStringLiterals.containerPlugin)) { - strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + strPathCheck += WSManStringLiterals.containerPlugin; // Check for Plugin path if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) { return true; } - strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + strPathCheck += WSManStringLiterals.DefaultPathSeparator; XmlDocument xmlPlugins = FindResourceValue(sessionobj, WsManURI, null); string currentpluginname = string.Empty; GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path); - strPathCheck = strPathCheck + currentpluginname; + strPathCheck += currentpluginname; if (path.EndsWith(currentpluginname, StringComparison.OrdinalIgnoreCase)) { return true; @@ -1541,7 +1541,7 @@ WsMan Config Can be divided in to Four Fixed Regions to Check Whether Item is Co return true; } - strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + strPathCheck += WSManStringLiterals.DefaultPathSeparator; if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) { return true; @@ -1695,7 +1695,7 @@ protected override void RemoveItem(string path, bool recurse) return; } - strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + strPathCheck += WSManStringLiterals.containerPlugin; int pos = 0; string pName = null; pos = path.LastIndexOf(strPathCheck + WSManStringLiterals.DefaultPathSeparator, StringComparison.OrdinalIgnoreCase) + strPathCheck.Length + 1; @@ -2152,7 +2152,7 @@ private void NewItemPluginOrPluginChild(object sessionobj, string path, string h strPathChk = strPathChk + WSManStringLiterals.DefaultPathSeparator + pName + WSManStringLiterals.DefaultPathSeparator; if (path.Contains(strPathChk + WSManStringLiterals.containerResources)) { - strPathChk = strPathChk + WSManStringLiterals.containerResources; + strPathChk += WSManStringLiterals.containerResources; if (path.EndsWith(strPathChk, StringComparison.OrdinalIgnoreCase)) { WSManProviderNewItemResourceParameters niParams = DynamicParameters as WSManProviderNewItemResourceParameters; @@ -2290,7 +2290,7 @@ private void NewItemPluginOrPluginChild(object sessionobj, string path, string h /// /// /// - private PSObject GetItemPSObjectWithTypeName(string Name, string TypeNameOfElement, object Value, string[] keys, string ExtendedTypeName, WsManElementObjectTypes WSManElementObjectType, PSObject input = null) + private static PSObject GetItemPSObjectWithTypeName(string Name, string TypeNameOfElement, object Value, string[] keys, string ExtendedTypeName, WsManElementObjectTypes WSManElementObjectType, PSObject input = null) { PSObject mshObject = null; if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigElement)) @@ -2328,7 +2328,7 @@ private PSObject GetItemPSObjectWithTypeName(string Name, string TypeNameOfEleme if (mshObject != null) { types.Append(mshObject.ImmediateBaseObject.GetType().FullName); - types.Append("#"); + types.Append('#'); types.Append(ExtendedTypeName); mshObject.TypeNames.Insert(0, types.ToString()); } @@ -2410,7 +2410,7 @@ private void SetItemListenerOrClientCertificate(object sessionObj, string Resour /// /// /// - private string GetInputStringForCreate(string ResourceURI, Hashtable value, string host) + private static string GetInputStringForCreate(string ResourceURI, Hashtable value, string host) { string putstr = string.Empty; string nilns = string.Empty; @@ -2426,16 +2426,16 @@ private string GetInputStringForCreate(string ResourceURI, Hashtable value, stri sbvalues.Append(key); if (value[key] == null) { - sbvalues.Append(" "); + sbvalues.Append(' '); sbvalues.Append(WSManStringLiterals.ATTR_NIL); nilns = " " + WSManStringLiterals.NS_XSI; } - sbvalues.Append(">"); + sbvalues.Append('>'); sbvalues.Append(EscapeValuesForXML(((Hashtable)value)[key].ToString())); sbvalues.Append(""); + sbvalues.Append('>'); } } } @@ -2523,7 +2523,7 @@ private string GetHostName(string path) return sHostname; } - private string GetRootNodeName(string ResourceURI) + private static string GetRootNodeName(string ResourceURI) { string tempuri = string.Empty; if (ResourceURI.Contains('?')) @@ -2531,7 +2531,7 @@ private string GetRootNodeName(string ResourceURI) ResourceURI = ResourceURI.Split('?').GetValue(0).ToString(); } - string PTRN_URI_LAST = "([a-z_][-a-z0-9._]*)$"; + const string PTRN_URI_LAST = "([a-z_][-a-z0-9._]*)$"; Regex objregex = new Regex(PTRN_URI_LAST, RegexOptions.IgnoreCase); MatchCollection regexmatch = objregex.Matches(ResourceURI); if (regexmatch.Count > 0) @@ -2542,7 +2542,7 @@ private string GetRootNodeName(string ResourceURI) return tempuri; } - private string EscapeValuesForXML(string value) + private static string EscapeValuesForXML(string value) { StringBuilder esc_str = new StringBuilder(); for (int i = 0; i <= value.Length - 1; i++) @@ -2585,7 +2585,7 @@ private string EscapeValuesForXML(string value) return esc_str.ToString(); } - private bool IsItemContainer(XmlNodeList nodes) + private static bool IsItemContainer(XmlNodeList nodes) { bool result = false; if (nodes.Count != 0) @@ -2768,7 +2768,7 @@ private XmlDocument EnumerateResourceValue(object sessionobj, string ResourceURI while (!((IWSManEnumerator)value).AtEndOfStream) { - strXmlValue = strXmlValue + ((IWSManEnumerator)value).ReadItem(); + strXmlValue += ((IWSManEnumerator)value).ReadItem(); } Marshal.ReleaseComObject(value); @@ -2900,7 +2900,7 @@ private bool ContainResourceValue(object sessionobj, string ResourceURI, string while (!((IWSManEnumerator)value).AtEndOfStream) { - valuexml = valuexml + ((IWSManEnumerator)value).ReadItem(); + valuexml += ((IWSManEnumerator)value).ReadItem(); } if ((valuexml != string.Empty) && !(string.IsNullOrEmpty(valuexml))) @@ -2935,24 +2935,24 @@ private bool ContainResourceValue(object sessionobj, string ResourceURI, string #endregion "WsMan linking Operations" - private string GetURIWithFilter(string uri, Hashtable cmdlinevalues) + private static string GetURIWithFilter(string uri, Hashtable cmdlinevalues) { StringBuilder sburi = new StringBuilder(uri); if (cmdlinevalues != null) { if (uri.Contains("Config/Listener")) { - sburi.Append("?"); + sburi.Append('?'); sburi.Append(GetFilterString(cmdlinevalues, PKeyListener)); } else if (uri.Contains("Config/Service/certmapping")) { - sburi.Append("?"); + sburi.Append('?'); sburi.Append(GetFilterString(cmdlinevalues, PKeyCertMapping)); } else if (uri.Contains("Config/Plugin")) { - sburi.Append("?"); + sburi.Append('?'); sburi.Append(GetFilterString(cmdlinevalues, PKeyPlugin)); } } @@ -2960,7 +2960,7 @@ private string GetURIWithFilter(string uri, Hashtable cmdlinevalues) return sburi.ToString(); } - private string GetFilterString(Hashtable cmdlinevalues, string[] pkey) + private static string GetFilterString(Hashtable cmdlinevalues, string[] pkey) { StringBuilder filter = new StringBuilder(); foreach (string key in pkey) @@ -2968,9 +2968,9 @@ private string GetFilterString(Hashtable cmdlinevalues, string[] pkey) if (cmdlinevalues.Contains(key)) { filter.Append(key); - filter.Append("="); + filter.Append('='); filter.Append(cmdlinevalues[key].ToString()); - filter.Append("+"); + filter.Append('+'); } } @@ -2979,7 +2979,7 @@ private string GetFilterString(Hashtable cmdlinevalues, string[] pkey) return filter.ToString(); } - private bool IsPKey(string value, string ResourceURI) + private static bool IsPKey(string value, string ResourceURI) { bool result = false; if (ResourceURI.Contains(WSManStringLiterals.containerListener)) @@ -2998,7 +2998,7 @@ private bool IsPKey(string value, string ResourceURI) return result; } - private bool CheckPkeysArray(Hashtable values, string value, string[] pkeys) + private static bool CheckPkeysArray(Hashtable values, string value, string[] pkeys) { bool result = false; if (values != null) @@ -3102,7 +3102,7 @@ private void WritePSObjectPropertiesAsWSManElementObjects(PSObject psobject, str if (mshObject != null) { types.Append(mshObject.ImmediateBaseObject.GetType().FullName); - types.Append("#"); + types.Append('#'); types.Append(ExtendedTypeName); mshObject.TypeNames.Insert(0, types.ToString()); } @@ -3239,7 +3239,7 @@ private PSObject BuildHostLevelPSObjectArrayList(object objSessionObject, string /// /// /// - private PSObject ConvertToPSObject(XmlNode xmlnode) + private static PSObject ConvertToPSObject(XmlNode xmlnode) { PSObject mshObject = new PSObject(); foreach (XmlNode node in xmlnode.ChildNodes) @@ -3275,7 +3275,7 @@ private PSObject ConvertToPSObject(XmlNode xmlnode) return mshObject; } - private string SetXPathString(string uri) + private static string SetXPathString(string uri) { string parent = uri.Substring(uri.LastIndexOf(WSManStringLiterals.WinrmPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase) + 1); if (parent.Equals(WSManStringLiterals.containerWinrs, StringComparison.OrdinalIgnoreCase)) @@ -3307,7 +3307,7 @@ private string SetXPathString(string uri) return parent; } - private string SetSchemaPath(string uri) + private static string SetSchemaPath(string uri) { string schemapath = string.Empty; uri = uri.Remove(0, WinrmRootName[0].Length); @@ -3334,7 +3334,7 @@ private string SetSchemaPath(string uri) /// /// /// - private string NormalizePath(string path, string host) + private static string NormalizePath(string path, string host) { string uri = string.Empty; if (path.StartsWith(host, StringComparison.OrdinalIgnoreCase)) @@ -3573,7 +3573,7 @@ private string GetCorrectCaseOfName(string ChildName, string hostname, string pa string result = ChildName; if (ChildName != null) { - if (!ChildName.Contains("_")) + if (!ChildName.Contains('_')) { if (ChildName.Equals(WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) result = WSManStringLiterals.containerQuotasParameters; @@ -3647,20 +3647,20 @@ private string GetCorrectCaseOfName(string ChildName, string hostname, string pa else { if (ChildName.StartsWith(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) - result = WSManStringLiterals.containerListener + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + result = string.Concat(WSManStringLiterals.containerListener, "_", ChildName.AsSpan(ChildName.IndexOf('_') + 1)); if (ChildName.StartsWith(WSManStringLiterals.containerSingleResource, StringComparison.OrdinalIgnoreCase)) - result = WSManStringLiterals.containerSingleResource + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + result = string.Concat(WSManStringLiterals.containerSingleResource, "_", ChildName.AsSpan(ChildName.IndexOf('_') + 1)); if (ChildName.StartsWith(WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) - result = WSManStringLiterals.containerSecurity + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + result = string.Concat(WSManStringLiterals.containerSecurity, "_", ChildName.AsSpan(ChildName.IndexOf('_') + 1)); if (ChildName.StartsWith(WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) - result = WSManStringLiterals.containerClientCertificate + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + result = string.Concat(WSManStringLiterals.containerClientCertificate, "_", ChildName.AsSpan(ChildName.IndexOf('_') + 1)); } } return result; } - private ArrayList RemoveItemfromResourceArray(ArrayList resourceArray, string ChildName, string type, string property) + private static ArrayList RemoveItemfromResourceArray(ArrayList resourceArray, string ChildName, string type, string property) { if (resourceArray != null) { @@ -4089,7 +4089,7 @@ private bool ItemExistListenerOrClientCertificate(object sessionobj, string Reso CurrentNode = RemainingPath.Substring(0, pos); } - if (objcache.Contains(CurrentNode) == false) + if (!objcache.Contains(CurrentNode)) { return false; } @@ -4519,7 +4519,7 @@ private void GetChildItemsOrNames(string path, ProviderMethods methodname, bool /// /// /// - private int GetPluginNames(XmlDocument xmlPlugins, out PSObject PluginNames, out string CurrentPluginName, string path) + private static int GetPluginNames(XmlDocument xmlPlugins, out PSObject PluginNames, out string CurrentPluginName, string path) { PluginNames = new PSObject(); CurrentPluginName = string.Empty; @@ -4627,7 +4627,7 @@ private void StartWSManService(bool force) /// /// /// - private bool IsPathLocalMachine(string host) + private static bool IsPathLocalMachine(string host) { bool hostfound = false; // Check is Localhost @@ -4684,7 +4684,7 @@ private bool IsPathLocalMachine(string host) #region Plugin private functions - private void GenerateObjectNameAndKeys(Hashtable InputAttributes, string ResourceURI, string ContainerItem, out string ItemName, out string[] keys) + private static void GenerateObjectNameAndKeys(Hashtable InputAttributes, string ResourceURI, string ContainerItem, out string ItemName, out string[] keys) { StringBuilder sbHashKey = new StringBuilder(); string keysColumns = string.Empty; @@ -4717,7 +4717,7 @@ private void GenerateObjectNameAndKeys(Hashtable InputAttributes, string Resourc keys = keysColumns.Split('|'); } - private void ProcessCertMappingObjects(XmlDocument xmlCerts, out Hashtable Certcache, out Hashtable Keyscache) + private static void ProcessCertMappingObjects(XmlDocument xmlCerts, out Hashtable Certcache, out Hashtable Keyscache) { Hashtable lCache = new Hashtable(); Hashtable kCache = new Hashtable(); @@ -4775,7 +4775,7 @@ private void ProcessCertMappingObjects(XmlDocument xmlCerts, out Hashtable Certc Keyscache = kCache; } - private void ProcessListenerObjects(XmlDocument xmlListeners, out Hashtable listenercache, out Hashtable Keyscache) + private static void ProcessListenerObjects(XmlDocument xmlListeners, out Hashtable listenercache, out Hashtable Keyscache) { Hashtable lCache = new Hashtable(); Hashtable kCache = new Hashtable(); @@ -4836,7 +4836,7 @@ private void ProcessListenerObjects(XmlDocument xmlListeners, out Hashtable list Keyscache = kCache; } - private PSObject ProcessPluginConfigurationLevel(XmlDocument xmldoc, bool setRunasPasswordAsSecureString = false) + private static PSObject ProcessPluginConfigurationLevel(XmlDocument xmldoc, bool setRunasPasswordAsSecureString = false) { PSObject objConfiglvl = null; @@ -4877,7 +4877,7 @@ private PSObject ProcessPluginConfigurationLevel(XmlDocument xmldoc, bool setRun return objConfiglvl; } - private ArrayList ProcessPluginResourceLevel(XmlDocument xmldoc, out ArrayList arrSecurity) + private static ArrayList ProcessPluginResourceLevel(XmlDocument xmldoc, out ArrayList arrSecurity) { ArrayList Resources = null; ArrayList nSecurity = null; @@ -4963,7 +4963,7 @@ private ArrayList ProcessPluginResourceLevel(XmlDocument xmldoc, out ArrayList a return Resources; } - private ArrayList ProcessPluginInitParamLevel(XmlDocument xmldoc) + private static ArrayList ProcessPluginInitParamLevel(XmlDocument xmldoc) { ArrayList InitParamLvl = null; if (xmldoc != null) @@ -5001,7 +5001,7 @@ private ArrayList ProcessPluginInitParamLevel(XmlDocument xmldoc) return InitParamLvl; } - private ArrayList ProcessPluginSecurityLevel(ArrayList arrSecurity, XmlDocument xmlSecurity, string UniqueResourceID, string ParentResourceUri) + private static ArrayList ProcessPluginSecurityLevel(ArrayList arrSecurity, XmlDocument xmlSecurity, string UniqueResourceID, string ParentResourceUri) { // ArrayList SecurityLvl = null; if (xmlSecurity != null) @@ -5063,7 +5063,7 @@ private ArrayList ProcessPluginSecurityLevel(ArrayList arrSecurity, XmlDocument ///List of Securities ///List of initialization parameters. /// An Configuration XML, ready to send to server. - private string ConstructPluginXml(PSObject objinputparam, string ResourceURI, string host, string Operation, ArrayList resources, ArrayList securities, ArrayList initParams) + private static string ConstructPluginXml(PSObject objinputparam, string ResourceURI, string host, string Operation, ArrayList resources, ArrayList securities, ArrayList initParams) { StringBuilder sbvalues = new StringBuilder(); sbvalues.Append(" /// Value to append. - private string GetStringFromSecureString(object propertyValue) + private static string GetStringFromSecureString(object propertyValue) { SecureString value = propertyValue as SecureString; string passwordValueToAdd = string.Empty; @@ -5206,7 +5206,7 @@ private string GetStringFromSecureString(object propertyValue) return passwordValueToAdd; } - private string ConstructResourceXml(PSObject objinputparams, ArrayList resources, ArrayList securities) + private static string ConstructResourceXml(PSObject objinputparams, ArrayList resources, ArrayList securities) { StringBuilder sbvalues = new StringBuilder(string.Empty); if (objinputparams == null && resources == null) @@ -5293,7 +5293,7 @@ private string ConstructResourceXml(PSObject objinputparams, ArrayList resources return sbvalues.ToString(); } - private string ConstructSecurityXml(PSObject objinputparams, ArrayList securities, string strResourceIdentity) + private static string ConstructSecurityXml(PSObject objinputparams, ArrayList securities, string strResourceIdentity) { // StringBuilder sbvalues = new StringBuilder(string.Empty); @@ -5320,7 +5320,7 @@ private string ConstructSecurityXml(PSObject objinputparams, ArrayList securitie return sbvalues.ToString(); } - private void AddSecurityProperties( + private static void AddSecurityProperties( PSMemberInfoCollection properties, StringBuilder sbValues) { @@ -5345,7 +5345,7 @@ private void AddSecurityProperties( sbValues.Append(""); } - private string ConstructInitParamsXml(PSObject objinputparams, ArrayList initparams) + private static string ConstructInitParamsXml(PSObject objinputparams, ArrayList initparams) { // // @@ -5397,7 +5397,7 @@ private string ConstructInitParamsXml(PSObject objinputparams, ArrayList initpar return sbvalues.ToString(); } - private string ConstructCapabilityXml(object[] capabilities) + private static string ConstructCapabilityXml(object[] capabilities) { StringBuilder sbvalues = new StringBuilder(string.Empty); foreach (object cap in capabilities) @@ -5413,7 +5413,7 @@ private string ConstructCapabilityXml(object[] capabilities) return sbvalues.ToString(); } - private bool IsValueOfParamList(string name, string[] paramcontainer) + private static bool IsValueOfParamList(string name, string[] paramcontainer) { bool result = false; foreach (string value in paramcontainer) @@ -5434,14 +5434,14 @@ private enum ProviderMethods { GetChildItems, GetChildNames - }; + } private enum WsManElementObjectTypes { WSManConfigElement, WSManConfigContainerElement, WSManConfigLeafElement - }; + } #region def private static readonly string[] WinrmRootName = new string[] { "winrm/Config" }; @@ -5607,15 +5607,15 @@ public string ApplicationName [Parameter] [ValidateNotNullOrEmpty] [Parameter(ParameterSetName = "nameSet")] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "UseSSL". @@ -6585,4 +6585,3 @@ public string[] Keys #endregion "WsMan Output Objects" } - diff --git a/src/Microsoft.WSMan.Management/CredSSP.cs b/src/Microsoft.WSMan.Management/CredSSP.cs index 60d8795ac54..cd5e6d3fc4d 100644 --- a/src/Microsoft.WSMan.Management/CredSSP.cs +++ b/src/Microsoft.WSMan.Management/CredSSP.cs @@ -227,7 +227,7 @@ private void DeleteUserDelegateSettings() GPO.OpenLocalMachineGPO(1); KeyHandle = GPO.GetRegistryKey(2); RegistryKey rootKey = Registry.CurrentUser; - string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; + const string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; RegistryKey GPOKey = rootKey.OpenSubKey(GPOpath, true); foreach (string keyname in GPOKey.GetSubKeyNames()) { @@ -508,7 +508,7 @@ private void EnableClientSideSettings() return; } - string newxmlcontent = @"true"; + const string newxmlcontent = @"true"; try { XmlDocument xmldoc = new XmlDocument(); @@ -626,7 +626,7 @@ private void UpdateCurrentUserRegistrySettings() GPO.OpenLocalMachineGPO(1); KeyHandle = GPO.GetRegistryKey(2); RegistryKey rootKey = Registry.CurrentUser; - string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; + const string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; RegistryKey GPOKey = rootKey.OpenSubKey(GPOpath, true); foreach (string keyname in GPOKey.GetSubKeyNames()) { @@ -827,7 +827,7 @@ protected override void BeginProcessing() } // The application name MUST be "wsman" as wsman got approval from security // folks who suggested to register the SPN with name "wsman". - string applicationname = "wsman"; + const string applicationname = "wsman"; string credsspResult = GetDelegateSettings(applicationname); if (string.IsNullOrEmpty(credsspResult)) { diff --git a/src/Microsoft.WSMan.Management/CurrentConfigurations.cs b/src/Microsoft.WSMan.Management/CurrentConfigurations.cs index 01ba71f68a7..0129554c30b 100644 --- a/src/Microsoft.WSMan.Management/CurrentConfigurations.cs +++ b/src/Microsoft.WSMan.Management/CurrentConfigurations.cs @@ -21,7 +21,7 @@ internal class CurrentConfigurations /// /// This holds the current configurations XML. /// - private XmlDocument rootDocument; + private readonly XmlDocument rootDocument; /// /// Holds the reference to the current document element. @@ -36,7 +36,7 @@ internal class CurrentConfigurations /// /// Session of the WsMan sserver. /// - private IWSManSession serverSession; + private readonly IWSManSession serverSession; /// /// Gets the server session associated with the configuration. @@ -131,7 +131,7 @@ public void RemoveOneConfiguration(string pathToNodeFromRoot) { if (nodeToRemove is XmlAttribute) { - this.RemoveAttribute(nodeToRemove as XmlAttribute); + RemoveAttribute(nodeToRemove as XmlAttribute); } } else @@ -217,7 +217,7 @@ public string GetOneConfiguration(string pathFromRoot) /// Removes the attribute from OwnerNode. /// /// Attribute to Remove. - private void RemoveAttribute(XmlAttribute attributeToRemove) + private static void RemoveAttribute(XmlAttribute attributeToRemove) { XmlElement ownerElement = attributeToRemove.OwnerElement; ownerElement.RemoveAttribute(attributeToRemove.Name); diff --git a/src/Microsoft.WSMan.Management/Interop.cs b/src/Microsoft.WSMan.Management/Interop.cs index 6e813ef17e1..6685770b0ef 100644 --- a/src/Microsoft.WSMan.Management/Interop.cs +++ b/src/Microsoft.WSMan.Management/Interop.cs @@ -376,7 +376,7 @@ void SetProxy(int accessType, /// ProxyAuthenticationUseDigest method of IWSManConnectionOptionsEx2 interface. [DispId(11)] int ProxyAuthenticationUseDigest(); - }; + } #endregion IWSManConnectionOptions @@ -734,19 +734,18 @@ public interface IWSManResourceLocator [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] string ResourceUri { - // IDL: HRESULT resourceUri (BSTR value); + // IDL: HRESULT resourceUri ([out, retval] BSTR* ReturnValue); [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] [DispId(1)] - set; - - // IDL: HRESULT resourceUri ([out, retval] BSTR* ReturnValue); + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT resourceUri (BSTR value); [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] [DispId(1)] - [return: MarshalAs(UnmanagedType.BStr)] - get; + set; } /// AddSelector method of IWSManResourceLocator interface. Add selector to resource locator diff --git a/src/Microsoft.WSMan.Management/InvokeWSManAction.cs b/src/Microsoft.WSMan.Management/InvokeWSManAction.cs index 1472a26f016..16e91cceae9 100644 --- a/src/Microsoft.WSMan.Management/InvokeWSManAction.cs +++ b/src/Microsoft.WSMan.Management/InvokeWSManAction.cs @@ -68,7 +68,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -143,15 +146,15 @@ public Hashtable OptionSet /// [Parameter(ParameterSetName = "ComputerName")] [ValidateNotNullOrEmpty] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "SelectorSet". @@ -244,7 +247,7 @@ public Uri ResourceURI private Uri resourceuri; private WSManHelper helper; - private IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + private readonly IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); private IWSManSession m_session = null; private string connectionStr = string.Empty; diff --git a/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj b/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj index 96fd6a0a7ef..d6b7c281f9e 100644 --- a/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj +++ b/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Microsoft.WSMan.Management/NewWSManSession.cs b/src/Microsoft.WSMan.Management/NewWSManSession.cs index 2bb367aeecc..25f5bdd5989 100644 --- a/src/Microsoft.WSMan.Management/NewWSManSession.cs +++ b/src/Microsoft.WSMan.Management/NewWSManSession.cs @@ -60,7 +60,10 @@ public ProxyAccessType ProxyAccessType [ValidateNotNullOrEmpty] public ProxyAuthentication ProxyAuthentication { - get { return proxyauthentication; } + get + { + return proxyauthentication; + } set { @@ -78,7 +81,10 @@ public ProxyAuthentication ProxyAuthentication [Credential] public PSCredential ProxyCredential { - get { return _proxycredential; } + get + { + return _proxycredential; + } set { @@ -99,7 +105,10 @@ public PSCredential ProxyCredential [Parameter] public SwitchParameter SkipCACheck { - get { return skipcacheck; } + get + { + return skipcacheck; + } set { @@ -118,7 +127,10 @@ public SwitchParameter SkipCACheck [Parameter] public SwitchParameter SkipCNCheck { - get { return skipcncheck; } + get + { + return skipcncheck; + } set { @@ -137,7 +149,10 @@ public SwitchParameter SkipCNCheck [Parameter] public SwitchParameter SkipRevocationCheck { - get { return skiprevocationcheck; } + get + { + return skiprevocationcheck; + } set { @@ -155,10 +170,13 @@ public SwitchParameter SkipRevocationCheck /// [Parameter] [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")] - [ValidateRange(0, Int32.MaxValue)] - public Int32 SPNPort + [ValidateRange(0, int.MaxValue)] + public int SPNPort { - get { return spnport; } + get + { + return spnport; + } set { @@ -166,7 +184,7 @@ public Int32 SPNPort } } - private Int32 spnport; + private int spnport; /// /// The following is the definition of the input parameter "Timeout". @@ -174,10 +192,13 @@ public Int32 SPNPort /// [Parameter] [Alias("OperationTimeoutMSec")] - [ValidateRange(0, Int32.MaxValue)] - public Int32 OperationTimeout + [ValidateRange(0, int.MaxValue)] + public int OperationTimeout { - get { return operationtimeout; } + get + { + return operationtimeout; + } set { @@ -185,7 +206,7 @@ public Int32 OperationTimeout } } - private Int32 operationtimeout; + private int operationtimeout; /// /// The following is the definition of the input parameter "UnEncrypted". @@ -196,7 +217,10 @@ public Int32 OperationTimeout [Parameter] public SwitchParameter NoEncryption { - get { return noencryption; } + get + { + return noencryption; + } set { @@ -215,7 +239,10 @@ public SwitchParameter NoEncryption [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "UTF")] public SwitchParameter UseUTF16 { - get { return useutf16; } + get + { + return useutf16; + } set { diff --git a/src/Microsoft.WSMan.Management/PingWSMan.cs b/src/Microsoft.WSMan.Management/PingWSMan.cs index 47ca6ef738b..b9a0e21f1f4 100644 --- a/src/Microsoft.WSMan.Management/PingWSMan.cs +++ b/src/Microsoft.WSMan.Management/PingWSMan.cs @@ -35,7 +35,10 @@ public class TestWSManCommand : AuthenticatingWSManCommand, IDisposable [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -72,7 +75,10 @@ public string ComputerName [Alias("auth", "am")] public override AuthenticationMechanism Authentication { - get { return authentication; } + get + { + return authentication; + } set { @@ -89,15 +95,15 @@ public override AuthenticationMechanism Authentication /// [Parameter(ParameterSetName = "ComputerName")] [ValidateNotNullOrEmpty] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "UseSSL". diff --git a/src/Microsoft.WSMan.Management/WSManConnections.cs b/src/Microsoft.WSMan.Management/WSManConnections.cs index 6d6c5f6bc0e..c83ed7e9e10 100644 --- a/src/Microsoft.WSMan.Management/WSManConnections.cs +++ b/src/Microsoft.WSMan.Management/WSManConnections.cs @@ -38,7 +38,10 @@ public class AuthenticatingWSManCommand : PSCmdlet [Alias("cred", "c")] public virtual PSCredential Credential { - get { return credential; } + get + { + return credential; + } set { @@ -69,7 +72,10 @@ public virtual PSCredential Credential [Alias("auth", "am")] public virtual AuthenticationMechanism Authentication { - get { return authentication; } + get + { + return authentication; + } set { @@ -88,7 +94,10 @@ public virtual AuthenticationMechanism Authentication [ValidateNotNullOrEmpty] public virtual string CertificateThumbprint { - get { return thumbPrint; } + get + { + return thumbPrint; + } set { @@ -144,7 +153,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -201,15 +213,15 @@ public Hashtable OptionSet [Parameter] [ValidateNotNullOrEmpty] [Parameter(ParameterSetName = "ComputerName")] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "SessionOption". @@ -300,7 +312,10 @@ public class DisconnectWSManCommand : PSCmdlet, IDisposable [Parameter(Position = 0)] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { diff --git a/src/Microsoft.WSMan.Management/WSManInstance.cs b/src/Microsoft.WSMan.Management/WSManInstance.cs index fa96cacf780..a60ba270104 100644 --- a/src/Microsoft.WSMan.Management/WSManInstance.cs +++ b/src/Microsoft.WSMan.Management/WSManInstance.cs @@ -40,7 +40,10 @@ public class GetWSManInstanceCommand : AuthenticatingWSManCommand, IDisposable [Parameter(ParameterSetName = "Enumerate")] public string ApplicationName { - get { return applicationname; } + get + { + return applicationname; + } set { @@ -60,7 +63,10 @@ public string ApplicationName [Alias("UBPO", "Base")] public SwitchParameter BasePropertiesOnly { - get { return basepropertiesonly; } + get + { + return basepropertiesonly; + } set { @@ -81,7 +87,10 @@ public SwitchParameter BasePropertiesOnly [Alias("CN")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -109,7 +118,10 @@ public string ComputerName [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] public Uri ConnectionURI { - get { return connectionuri; } + get + { + return connectionuri; + } set { @@ -126,7 +138,10 @@ public Uri ConnectionURI [Parameter] public Uri Dialect { - get { return dialect; } + get + { + return dialect; + } set { @@ -145,7 +160,10 @@ public Uri Dialect ParameterSetName = "Enumerate")] public SwitchParameter Enumerate { - get { return enumerate; } + get + { + return enumerate; + } set { @@ -163,7 +181,10 @@ public SwitchParameter Enumerate [ValidateNotNullOrEmpty] public string Filter { - get { return filter; } + get + { + return filter; + } set { @@ -182,7 +203,10 @@ public string Filter [ValidateNotNullOrEmpty] public string Fragment { - get { return fragment; } + get + { + return fragment; + } set { @@ -204,7 +228,10 @@ public string Fragment [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public Hashtable OptionSet { - get { return optionset; } + get + { + return optionset; + } set { @@ -220,9 +247,12 @@ public Hashtable OptionSet /// [Parameter(ParameterSetName = "Enumerate")] [Parameter(ParameterSetName = "GetInstance")] - public Int32 Port + public int Port { - get { return port; } + get + { + return port; + } set { @@ -230,7 +260,7 @@ public Int32 Port } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "Associations". @@ -241,7 +271,10 @@ public Int32 Port [Parameter(ParameterSetName = "Enumerate")] public SwitchParameter Associations { - get { return associations; } + get + { + return associations; + } set { @@ -264,7 +297,10 @@ public SwitchParameter Associations [Alias("RURI")] public Uri ResourceURI { - get { return resourceuri; } + get + { + return resourceuri; + } set { @@ -293,7 +329,10 @@ public Uri ResourceURI [Alias("RT")] public string ReturnType { - get { return returntype; } + get + { + return returntype; + } set { @@ -315,7 +354,10 @@ public string ReturnType [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public Hashtable SelectorSet { - get { return selectorset; } + get + { + return selectorset; + } set { @@ -336,7 +378,10 @@ public Hashtable SelectorSet [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public SessionOption SessionOption { - get { return sessionoption; } + get + { + return sessionoption; + } set { @@ -356,7 +401,10 @@ public SessionOption SessionOption public SwitchParameter Shallow { - get { return shallow; } + get + { + return shallow; + } set { @@ -379,7 +427,10 @@ public SwitchParameter Shallow [Alias("SSL")] public SwitchParameter UseSSL { - get { return usessl; } + get + { + return usessl; + } set { @@ -391,7 +442,7 @@ public SwitchParameter UseSSL #endregion parameter - # region private + #region private private WSManHelper helper; private string GetFilter() @@ -413,7 +464,7 @@ private string GetFilter() filter = filter + "" + value + ""; } - filter = filter + ""; + filter += ""; return (filter); } @@ -662,7 +713,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -768,15 +822,15 @@ public Hashtable OptionSet /// [Parameter(ParameterSetName = "ComputerName")] [ValidateNotNullOrEmpty] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "ResourceURI". @@ -1032,7 +1086,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -1089,15 +1146,15 @@ public Hashtable OptionSet /// [Parameter(ParameterSetName = "ComputerName")] [ValidateNotNullOrEmpty] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "ResourceURI". @@ -1294,7 +1351,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -1368,15 +1428,15 @@ public Hashtable OptionSet /// [Parameter(ParameterSetName = "ComputerName")] [ValidateNotNullOrEmpty] - [ValidateRange(1, Int32.MaxValue)] - public Int32 Port + [ValidateRange(1, int.MaxValue)] + public int Port { get { return port; } set { port = value; } } - private Int32 port = 0; + private int port = 0; /// /// The following is the definition of the input parameter "ResourceURI". @@ -1465,7 +1525,7 @@ public Hashtable ValueSet private Hashtable valueset; private WSManHelper helper; - private IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + private readonly IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); private IWSManSession m_session = null; private string connectionStr = string.Empty; diff --git a/src/Microsoft.WSMan.Management/WsManHelper.cs b/src/Microsoft.WSMan.Management/WsManHelper.cs index f09ba2bb233..000cb871abb 100644 --- a/src/Microsoft.WSMan.Management/WsManHelper.cs +++ b/src/Microsoft.WSMan.Management/WsManHelper.cs @@ -78,13 +78,13 @@ internal class WSManHelper // string for operation internal string WSManOp = null; - private PSCmdlet cmdletname; - private NavigationCmdletProvider _provider; + private readonly PSCmdlet cmdletname; + private readonly NavigationCmdletProvider _provider; private FileStream _fs; private StreamReader _sr; - private static ResourceManager _resourceMgr = new ResourceManager("Microsoft.WSMan.Management.resources.WsManResources", typeof(WSManHelper).GetTypeInfo().Assembly); + private static readonly ResourceManager _resourceMgr = new ResourceManager("Microsoft.WSMan.Management.resources.WsManResources", typeof(WSManHelper).GetTypeInfo().Assembly); // // @@ -467,7 +467,7 @@ internal string ProcessInput(IWSManEx wsman, string filepath, string operation, } else { - XmlNode tmpNode = node.ChildNodes[0];//.Item[0]; + XmlNode tmpNode = node.ChildNodes[0]; //.Item[0]; if (!tmpNode.NodeType.ToString().Equals("text", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException(_resourceMgr.GetString("NOAttributeMatch")); @@ -562,7 +562,7 @@ internal IWSManResourceLocator InitializeResourceLocator(Hashtable optionset, Ha if (selectorset != null) { - resource = resource + "?"; + resource += "?"; int i = 0; foreach (DictionaryEntry entry in selectorset) { @@ -656,7 +656,7 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM { if (authentication.Equals(AuthenticationMechanism.None)) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseNoAuthentication; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseNoAuthentication; } if (authentication.Equals(AuthenticationMechanism.Basic)) @@ -666,12 +666,12 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM if (authentication.Equals(AuthenticationMechanism.Negotiate)) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseNegotiate; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseNegotiate; } if (authentication.Equals(AuthenticationMechanism.Kerberos)) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseKerberos; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseKerberos; } if (authentication.Equals(AuthenticationMechanism.Digest)) @@ -686,7 +686,7 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM if (authentication.Equals(AuthenticationMechanism.ClientCertificate)) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseClientCertificate; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseClientCertificate; } } @@ -718,7 +718,7 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM connObject.Password = nwCredential.Password; if (!authentication.Equals(AuthenticationMechanism.Credssp) || !authentication.Equals(AuthenticationMechanism.Digest) || authentication.Equals(AuthenticationMechanism.Basic)) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagCredUserNamePassword; + sessionFlags |= (int)WSManSessionFlags.WSManFlagCredUserNamePassword; } } } @@ -726,7 +726,7 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM if (certificateThumbprint != null) { connObject.CertificateThumbprint = certificateThumbprint; - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseClientCertificate; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseClientCertificate; } if (sessionoption != null) @@ -784,48 +784,48 @@ internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationM if (sessionoption.SkipCACheck) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipCACheck; + sessionFlags |= (int)WSManSessionFlags.WSManFlagSkipCACheck; } if (sessionoption.SkipCNCheck) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipCNCheck; + sessionFlags |= (int)WSManSessionFlags.WSManFlagSkipCNCheck; } if (sessionoption.SPNPort > 0) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagEnableSpnServerPort; + sessionFlags |= (int)WSManSessionFlags.WSManFlagEnableSpnServerPort; } if (sessionoption.UseUtf16) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf16; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUtf16; } else { // If UseUtf16 is false, then default Encoding is Utf8 - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf8; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUtf8; } if (!sessionoption.UseEncryption) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagNoEncryption; + sessionFlags |= (int)WSManSessionFlags.WSManFlagNoEncryption; } if (sessionoption.SkipRevocationCheck) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipRevocationCheck; + sessionFlags |= (int)WSManSessionFlags.WSManFlagSkipRevocationCheck; } } else { // If SessionOption is null then, default Encoding is Utf8 - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf8; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUtf8; } if (usessl) { - sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseSsl; + sessionFlags |= (int)WSManSessionFlags.WSManFlagUseSsl; } IWSManSession m_SessionObj = null; @@ -871,9 +871,9 @@ internal string GetFilterString(Hashtable seletorset) if (entry.Key != null && entry.Value != null) { filter.Append(entry.Key.ToString()); - filter.Append("="); + filter.Append('='); filter.Append(entry.Value.ToString()); - filter.Append("+"); + filter.Append('+'); } } @@ -917,7 +917,7 @@ internal string GetURIWithFilter(string uri, string filter, Hashtable selectorse { StringBuilder sburi = new StringBuilder(); sburi.Append(uri); - sburi.Append("?"); + sburi.Append('?'); if (operation.Equals("remove", StringComparison.OrdinalIgnoreCase)) { @@ -1092,7 +1092,7 @@ internal static void LoadResourceData() while (!_sr.EndOfStream) { string Line = _sr.ReadLine(); - if (Line.Contains("=")) + if (Line.Contains('=')) { string[] arr = Line.Split('=', count: 2); if (!ResourceValueCache.ContainsKey(arr[0].Trim())) @@ -1135,6 +1135,6 @@ internal static string GetResourceString(string Key) /// /// - private static Dictionary ResourceValueCache = new Dictionary(); + private static readonly Dictionary ResourceValueCache = new Dictionary(); } } diff --git a/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs b/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs index d8681a54618..13dc8bbea2c 100644 --- a/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs +++ b/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs @@ -2,19 +2,8 @@ // Licensed under the MIT License. using System; -using System.ComponentModel; -using System.IO; -using System.Net; -using System.Reflection; -using System.Resources; -using System.Xml; - -using System.Collections; -using System.Collections.Generic; - -using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; +using System.Net; [assembly: CLSCompliant(true)] @@ -28,153 +17,53 @@ public sealed class SessionOption /// /// Property. /// - public bool SkipCACheck - { - get { return _SkipCACheck; } - - set - { - _SkipCACheck = value; - } - } - - private bool _SkipCACheck; + public bool SkipCACheck { get; set; } /// /// Property. /// - public bool SkipCNCheck - { - get { return _SkipCNCheck; } - - set - { - _SkipCNCheck = value; - } - } - - private bool _SkipCNCheck; + public bool SkipCNCheck { get; set; } /// /// Property. /// - public bool SkipRevocationCheck - { - get { return _SkipRevocationCheck; } - - set - { - _SkipRevocationCheck = value; - } - } - - private bool _SkipRevocationCheck; + public bool SkipRevocationCheck { get; set; } /// /// Property. /// - public bool UseEncryption - { - get { return _useencryption; } - - set - { - _useencryption = value; - } - } - - private bool _useencryption = true; + public bool UseEncryption { get; set; } = true; /// /// Property. /// - public bool UseUtf16 - { - get { return _UTF16; } - - set - { - _UTF16 = value; - } - } - - private bool _UTF16; + public bool UseUtf16 { get; set; } /// /// Property. /// - public ProxyAuthentication ProxyAuthentication - { - get { return _ProxyAuthentication; } - - set - { - _ProxyAuthentication = value; - } - } - - private ProxyAuthentication _ProxyAuthentication; + public ProxyAuthentication ProxyAuthentication { get; set; } /// /// Property. /// [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")] - public int SPNPort - { - get { return _SPNPort; } - - set - { - _SPNPort = value; - } - } - - private int _SPNPort; + public int SPNPort { get; set; } /// /// Property. /// - public int OperationTimeout - { - get { return _OperationTimeout; } - - set - { - _OperationTimeout = value; - } - } - - private int _OperationTimeout; + public int OperationTimeout { get; set; } /// /// Property. /// - public NetworkCredential ProxyCredential - { - get { return _ProxyCredential; } - - set - { - _ProxyCredential = value; - } - } - - private NetworkCredential _ProxyCredential; + public NetworkCredential ProxyCredential { get; set; } /// /// Property. /// - public ProxyAccessType ProxyAccessType - { - get { return _proxyaccesstype; } - - set - { - _proxyaccesstype = value; - } - } - - private ProxyAccessType _proxyaccesstype; + public ProxyAccessType ProxyAccessType { get; set; } } /// diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index a046dc67701..ca1c34df8b5 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -1,14 +1,21 @@ - + + PowerShell + Microsoft Corporation + (c) Microsoft Corporation. + + net6.0 + + true + - + - diff --git a/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 index 1ef5f3328e0..b883acdd0d6 100644 --- a/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 +++ b/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -38,6 +38,10 @@ PrivateData = @{ Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace' Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger. Enables -Runspace parameter on *-PSBreakpoint cmdlets to support management of breakpoints in another runspace.' } + @{ + Name = 'Microsoft.PowerShell.Utility.PSImportPSDataFileSkipLimitCheck' + Description = 'Enable -SkipLimitCheck switch for Import-PowerShellDataFile to not enforce built-in hashtable limits' + } ) } } diff --git a/src/Modules/Windows/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Modules/Windows/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 index 3b401f039e9..5ea504197fa 100644 --- a/src/Modules/Windows/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 +++ b/src/Modules/Windows/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -37,6 +37,10 @@ PrivateData = @{ Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace' Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger. Enables -Runspace parameter on *-PSBreakpoint cmdlets to support management of breakpoints in another runspace.' } + @{ + Name = 'Microsoft.PowerShell.Utility.PSImportPSDataFileSkipLimitCheck' + Description = 'Enable -NoLimit switch for Import-PowerShellDataFile to not enforce built-in hashtable limits' + } ) } } diff --git a/src/Modules/nuget.config b/src/Modules/nuget.config new file mode 100644 index 00000000000..b0fc73009da --- /dev/null +++ b/src/Modules/nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/ResGen/ResGen.csproj b/src/ResGen/ResGen.csproj index 70170d7c1cb..5c736ad9ed9 100644 --- a/src/ResGen/ResGen.csproj +++ b/src/ResGen/ResGen.csproj @@ -2,7 +2,7 @@ Generates C# typed bindings for .resx files - net5.0 + net6.0 resgen Exe true diff --git a/src/System.Management.Automation/AssemblyInfo.cs b/src/System.Management.Automation/AssemblyInfo.cs index 279feede65b..3c03c22e045 100644 --- a/src/System.Management.Automation/AssemblyInfo.cs +++ b/src/System.Management.Automation/AssemblyInfo.cs @@ -6,28 +6,18 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("powershell-tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: InternalsVisibleTo("powershell-perf,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.Test.Management.Automation.GPowershell.Analyzers,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] - -#if NOT_SIGNED -// These attributes aren't every used, it's just a hack to get VS to not complain -// about access when editing using the project files that don't actually build. -[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Commands.Utility")] -[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Commands.Management")] -[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Security")] -[assembly: InternalsVisibleTo(@"System.Management.Automation.Remoting")] -[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.ConsoleHost")] -#else [assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Commands.Utility" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Commands.Management" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Security" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo(@"System.Management.Automation.Remoting" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo(@"Microsoft.PowerShell.ConsoleHost" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -#endif +[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.DscSubsystem" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] namespace System.Management.Automation { - internal class NTVerpVars + internal static class NTVerpVars { internal const int PRODUCTMAJORVERSION = 10; internal const int PRODUCTMINORVERSION = 0; diff --git a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs index 293c3599267..43e6ad17eb4 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs @@ -15,7 +15,7 @@ namespace System.Management.Automation /// /// The powershell custom AssemblyLoadContext implementation. /// - internal partial class PowerShellAssemblyLoadContext + internal sealed partial class PowerShellAssemblyLoadContext { #region Resource_Strings @@ -105,7 +105,7 @@ private PowerShellAssemblyLoadContext(string basePaths) #region Fields - private static readonly object s_syncObj = new object(); + private static readonly object s_syncObj = new(); private readonly string[] _probingPaths; private readonly string[] _extensions = new string[] { ".ni.dll", ".dll" }; // CoreCLR type catalog dictionary @@ -114,9 +114,8 @@ private PowerShellAssemblyLoadContext(string basePaths) private readonly Dictionary _coreClrTypeCatalog; private readonly Lazy> _availableDotNetAssemblyNames; - private readonly HashSet _denyListedAssemblies = new HashSet(StringComparer.OrdinalIgnoreCase){ - "System.Windows.Forms" - }; + private readonly HashSet _denyListedAssemblies = + new(StringComparer.OrdinalIgnoreCase) { "System.Windows.Forms" }; #if !UNIX private string _winDir; @@ -140,7 +139,7 @@ private PowerShellAssemblyLoadContext(string basePaths) /// Therefore, there is no need to use the full assembly name as the key. Short assembly name is sufficient. /// private static readonly ConcurrentDictionary s_assemblyCache = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + new(StringComparer.OrdinalIgnoreCase); #endregion Fields @@ -393,7 +392,7 @@ private bool TryFindInGAC(AssemblyName assemblyName, out string assemblyFilePath } // Find the assembly under 'gacRoot' and select the latest version. - private bool FindInGac(string gacRoot, AssemblyName assemblyName, out string assemblyPath) + private static bool FindInGac(string gacRoot, AssemblyName assemblyName, out string assemblyPath) { bool assemblyFound = false; assemblyPath = null; @@ -404,12 +403,12 @@ private bool FindInGac(string gacRoot, AssemblyName assemblyName, out string ass if (Directory.Exists(tempAssemblyDirPath)) { // Enumerate all directories, sort by name and select the last. This selects the latest version. - var chosenVersionDirectory = Directory.GetDirectories(tempAssemblyDirPath).OrderBy(d => d).LastOrDefault(); + var chosenVersionDirectory = Directory.EnumerateDirectories(tempAssemblyDirPath).OrderBy(static d => d).LastOrDefault(); if (!string.IsNullOrEmpty(chosenVersionDirectory)) { // Select first or default as the directory will contain only one assembly. If nothing then default is null; - var foundAssemblyPath = Directory.GetFiles(chosenVersionDirectory, $"{assemblyName.Name}*").FirstOrDefault(); + var foundAssemblyPath = Directory.EnumerateFiles(chosenVersionDirectory, $"{assemblyName.Name}*").FirstOrDefault(); if (!string.IsNullOrEmpty(foundAssemblyPath)) { @@ -430,7 +429,7 @@ private bool FindInGac(string gacRoot, AssemblyName assemblyName, out string ass /// /// Try to get the specified assembly from cache. /// - private bool TryGetAssemblyFromCache(AssemblyName assemblyName, out Assembly asmLoaded) + private static bool TryGetAssemblyFromCache(AssemblyName assemblyName, out Assembly asmLoaded) { if (s_assemblyCache.TryGetValue(assemblyName.Name, out asmLoaded)) { @@ -454,7 +453,7 @@ private bool TryGetAssemblyFromCache(AssemblyName assemblyName, out Assembly asm /// AssemblyName of the requested assembly. /// AssemblyName of the loaded assembly. /// - private bool IsAssemblyMatching(AssemblyName requestedAssembly, AssemblyName loadedAssembly) + private static bool IsAssemblyMatching(AssemblyName requestedAssembly, AssemblyName loadedAssembly) { // // We use the same rules as CoreCLR loader to compare the requested assembly and loaded assembly: @@ -501,7 +500,7 @@ private bool IsAssemblyMatching(AssemblyName requestedAssembly, AssemblyName loa /// /// The assembly strong name of a CoreCLR Trusted_Platform_Assembly /// - private Assembly GetTrustedPlatformAssembly(string tpaStrongName) + private static Assembly GetTrustedPlatformAssembly(string tpaStrongName) { // We always depend on the default context to load the TPAs that are recorded in // the type catalog. @@ -509,7 +508,7 @@ private Assembly GetTrustedPlatformAssembly(string tpaStrongName) // it back from the cache of default context. // - If the requested TPA is not loaded yet, then 'Assembly.Load' will make the // default context to load it - AssemblyName assemblyName = new AssemblyName(tpaStrongName); + AssemblyName assemblyName = new(tpaStrongName); Assembly asmLoaded = Assembly.Load(assemblyName); return asmLoaded; } @@ -517,7 +516,7 @@ private Assembly GetTrustedPlatformAssembly(string tpaStrongName) /// /// Throw FileLoadException. /// - private void ThrowFileLoadException(string errorTemplate, params object[] args) + private static void ThrowFileLoadException(string errorTemplate, params object[] args) { string message = string.Format(CultureInfo.CurrentCulture, errorTemplate, args); throw new FileLoadException(message); @@ -526,7 +525,7 @@ private void ThrowFileLoadException(string errorTemplate, params object[] args) /// /// Throw FileNotFoundException. /// - private void ThrowFileNotFoundException(string errorTemplate, params object[] args) + private static void ThrowFileNotFoundException(string errorTemplate, params object[] args) { string message = string.Format(CultureInfo.CurrentCulture, errorTemplate, args); throw new FileNotFoundException(message); @@ -566,7 +565,7 @@ private static string GetNativeDllSubFolderName(out string ext) /// /// This is the managed entry point for Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll. /// - public class PowerShellAssemblyLoadContextInitializer + public static class PowerShellAssemblyLoadContextInitializer { /// /// Create a singleton of PowerShellAssemblyLoadContext. @@ -580,7 +579,7 @@ public class PowerShellAssemblyLoadContextInitializer /// Base directory paths that are separated by semicolon ';'. /// They will be the default paths to probe assemblies. /// - public static void SetPowerShellAssemblyLoadContext([MarshalAs(UnmanagedType.LPWStr)]string basePaths) + public static void SetPowerShellAssemblyLoadContext([MarshalAs(UnmanagedType.LPWStr)] string basePaths) { if (string.IsNullOrEmpty(basePaths)) throw new ArgumentNullException(nameof(basePaths)); @@ -588,4 +587,35 @@ public static void SetPowerShellAssemblyLoadContext([MarshalAs(UnmanagedType.LPW PowerShellAssemblyLoadContext.InitializeSingleton(basePaths); } } + + /// + /// Provides helper functions to faciliate calling managed code from a native PowerShell host. + /// + public static unsafe class PowerShellUnsafeAssemblyLoad + { + /// + /// Load an assembly in memory from unmanaged code. + /// + /// + /// This API is covered by the experimental feature 'PSLoadAssemblyFromNativeCode', + /// and it may be deprecated and removed in future. + /// + /// Unmanaged pointer to assembly data buffer. + /// Size in bytes of the assembly data buffer. + /// Returns zero on success and non-zero on failure. + [UnmanagedCallersOnly] + public static int LoadAssemblyFromNativeMemory(IntPtr data, int size) + { + try + { + using var stream = new UnmanagedMemoryStream((byte*)data, size); + AssemblyLoadContext.Default.LoadFromStream(stream); + return 0; + } + catch + { + return -1; + } + } + } } diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index df416a3dc2b..ce37ae12d17 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -16,8 +16,6 @@ namespace System.Management.Automation /// public static class Platform { - private static string _tempDirectory = null; - /// /// True if the current platform is Linux. /// @@ -140,6 +138,21 @@ public static bool IsWindowsDesktop } } + /// + /// Gets a value indicating whether the underlying system supports single-threaded apartment. + /// + public static bool IsStaSupported + { + get + { +#if UNIX + return false; +#else + return _isStaSupported.Value; +#endif + } + } + #if UNIX // Gets the location for cache and config folders. internal static readonly string CacheDirectory = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE); @@ -148,6 +161,22 @@ public static bool IsWindowsDesktop // Gets the location for cache and config folders. internal static readonly string CacheDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerShell"; internal static readonly string ConfigDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\PowerShell"; + private static readonly Lazy _isStaSupported = new Lazy(() => + { + // See objbase.h + const int COINIT_APARTMENTTHREADED = 0x2; + const int E_NOTIMPL = unchecked((int)0X80004001); + int result = Windows.NativeMethods.CoInitializeEx(IntPtr.Zero, COINIT_APARTMENTTHREADED); + + // If 0 is returned the thread has been initialized for the first time + // as an STA and thus supported and needs to be uninitialized. + if (result > 0) + { + Windows.NativeMethods.CoUninitialize(); + } + + return result != E_NOTIMPL; + }); private static bool? _isNanoServer = null; private static bool? _isIoT = null; @@ -155,20 +184,22 @@ public static bool IsWindowsDesktop #endif // format files - internal static readonly List FormatFileNames = new List - { - "Certificate.format.ps1xml", - "Diagnostics.format.ps1xml", - "DotNetTypes.format.ps1xml", - "Event.format.ps1xml", - "FileSystem.format.ps1xml", - "Help.format.ps1xml", - "HelpV3.format.ps1xml", - "PowerShellCore.format.ps1xml", - "PowerShellTrace.format.ps1xml", - "Registry.format.ps1xml", - "WSMan.format.ps1xml" - }; + internal static readonly List FormatFileNames = new() + { + "Certificate.format.ps1xml", + "Diagnostics.format.ps1xml", + "DotNetTypes.format.ps1xml", + "Event.format.ps1xml", + "FileSystem.format.ps1xml", + "Help.format.ps1xml", + "HelpV3.format.ps1xml", + "PowerShellCore.format.ps1xml", + "PowerShellTrace.format.ps1xml", + "Registry.format.ps1xml", + "WSMan.format.ps1xml" + }; + + private static string _tempDirectory = null; /// /// Some common environment variables used in PS have different @@ -485,11 +516,6 @@ internal static bool NonWindowsIsHardLink(FileSystemInfo fileInfo) return Unix.IsHardLink(fileInfo); } - internal static string NonWindowsInternalGetTarget(string path) - { - return Unix.NativeMethods.FollowSymLink(path); - } - internal static string NonWindowsGetUserFromPid(int path) { return Unix.NativeMethods.GetUserFromPid(path); @@ -557,6 +583,31 @@ internal static int NonWindowsGetProcessParentPid(int pid) return IsMacOS ? Unix.NativeMethods.GetPPid(pid) : Unix.GetProcFSParentPid(pid); } + internal static bool NonWindowsKillProcess(int pid) + { + return Unix.NativeMethods.KillProcess(pid); + } + + internal static int NonWindowsWaitPid(int pid, bool nohang) + { + return Unix.NativeMethods.WaitPid(pid, nohang); + } + + internal static class Windows + { + /// The native methods class. + internal static class NativeMethods + { + private const string ole32Lib = "api-ms-win-core-com-l1-1-0.dll"; + + [DllImport(ole32Lib)] + internal static extern int CoInitializeEx(IntPtr reserve, int coinit); + + [DllImport(ole32Lib)] + internal static extern void CoUninitialize(); + } + } + // Please note that `Win32Exception(Marshal.GetLastWin32Error())` // works *correctly* on Linux in that it creates an exception with // the string perror would give you for the last set value of errno. @@ -566,8 +617,8 @@ internal static int NonWindowsGetProcessParentPid(int pid) /// Unix specific implementations of required functionality. internal static class Unix { - private static Dictionary usernameCache = new Dictionary(); - private static Dictionary groupnameCache = new Dictionary(); + private static readonly Dictionary usernameCache = new(); + private static readonly Dictionary groupnameCache = new(); /// The type of a Unix file system item. public enum ItemType @@ -699,7 +750,7 @@ public class CommonStat private const char CanExecute = 'x'; // helper for getting unix mode - private Dictionary modeMap = new Dictionary() + private readonly Dictionary modeMap = new() { { StatMask.OwnerRead, CanRead }, { StatMask.OwnerWrite, CanWrite }, @@ -712,7 +763,7 @@ public class CommonStat { StatMask.OtherExecute, CanExecute }, }; - private StatMask[] permissions = new StatMask[] + private readonly StatMask[] permissions = new StatMask[] { StatMask.OwnerRead, StatMask.OwnerWrite, @@ -726,7 +777,7 @@ public class CommonStat }; // The item type and the character representation for the first element in the stat string - private Dictionary itemTypeTable = new Dictionary() + private readonly Dictionary itemTypeTable = new() { { ItemType.BlockDevice, 'b' }, { ItemType.CharacterDevice, 'c' }, @@ -860,7 +911,7 @@ public static bool IsHardLink(FileSystemInfo fs) /// A managed common stat class instance. private static CommonStat CopyStatStruct(NativeMethods.CommonStatStruct css) { - CommonStat cs = new CommonStat(); + CommonStat cs = new(); cs.Inode = css.Inode; cs.Mode = css.Mode; cs.UserId = css.UserId; @@ -1008,15 +1059,22 @@ internal static class NativeMethods internal static extern int GetPPid(int pid); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] - internal static extern int GetLinkCount([MarshalAs(UnmanagedType.LPStr)]string filePath, out int linkCount); + internal static extern int GetLinkCount([MarshalAs(UnmanagedType.LPStr)] string filePath, out int linkCount); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] [return: MarshalAs(UnmanagedType.I1)] - internal static extern bool IsExecutable([MarshalAs(UnmanagedType.LPStr)]string filePath); + internal static extern bool IsExecutable([MarshalAs(UnmanagedType.LPStr)] string filePath); [DllImport(psLib, CharSet = CharSet.Ansi)] internal static extern uint GetCurrentThreadId(); + [DllImport(psLib)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool KillProcess(int pid); + + [DllImport(psLib)] + internal static extern int WaitPid(int pid, bool nohang); + // This is a struct tm from . [StructLayout(LayoutKind.Sequential)] internal unsafe struct UnixTm @@ -1069,16 +1127,16 @@ internal static UnixTm DateTimeToUnixTm(DateTime date) internal static extern unsafe int SetDate(UnixTm* tm); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] - internal static extern int CreateSymLink([MarshalAs(UnmanagedType.LPStr)]string filePath, - [MarshalAs(UnmanagedType.LPStr)]string target); + internal static extern int CreateSymLink([MarshalAs(UnmanagedType.LPStr)] string filePath, + [MarshalAs(UnmanagedType.LPStr)] string target); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] - internal static extern int CreateHardLink([MarshalAs(UnmanagedType.LPStr)]string filePath, - [MarshalAs(UnmanagedType.LPStr)]string target); + internal static extern int CreateHardLink([MarshalAs(UnmanagedType.LPStr)] string filePath, + [MarshalAs(UnmanagedType.LPStr)] string target); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] [return: MarshalAs(UnmanagedType.LPStr)] - internal static extern string FollowSymLink([MarshalAs(UnmanagedType.LPStr)]string filePath); + internal static extern string FollowSymLink([MarshalAs(UnmanagedType.LPStr)] string filePath); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] [return: MarshalAs(UnmanagedType.LPStr)] @@ -1086,11 +1144,11 @@ internal static extern int CreateHardLink([MarshalAs(UnmanagedType.LPStr)]string [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] [return: MarshalAs(UnmanagedType.I1)] - internal static extern bool IsSameFileSystemItem([MarshalAs(UnmanagedType.LPStr)]string filePathOne, - [MarshalAs(UnmanagedType.LPStr)]string filePathTwo); + internal static extern bool IsSameFileSystemItem([MarshalAs(UnmanagedType.LPStr)] string filePathOne, + [MarshalAs(UnmanagedType.LPStr)] string filePathTwo); [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] - internal static extern int GetInodeData([MarshalAs(UnmanagedType.LPStr)]string path, + internal static extern int GetInodeData([MarshalAs(UnmanagedType.LPStr)] string path, out UInt64 device, out UInt64 inode); /// diff --git a/src/System.Management.Automation/CoreCLR/CorePsStub.cs b/src/System.Management.Automation/CoreCLR/CorePsStub.cs index 85b775f925b..d99bcbb398b 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsStub.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsStub.cs @@ -417,7 +417,7 @@ public static bool TryBindInvokeMember(InvokeMemberBinder binder, bool isSetProp } } - internal class VarEnumSelector + internal static class VarEnumSelector { internal static Type GetTypeForVarEnum(VarEnum vt) { diff --git a/src/System.Management.Automation/DscSupport/CimDSCParser.cs b/src/System.Management.Automation/DscSupport/CimDSCParser.cs index 9bf847757a5..f518d18fa1c 100644 --- a/src/System.Management.Automation/DscSupport/CimDSCParser.cs +++ b/src/System.Management.Automation/DscSupport/CimDSCParser.cs @@ -22,6 +22,8 @@ using Microsoft.Management.Infrastructure.Serialization; using Microsoft.PowerShell.Commands; +using static Microsoft.PowerShell.SecureStringHelper; + namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal { /// @@ -41,9 +43,7 @@ public static object ConvertCimInstanceToObject(Type targetType, CimInstance ins using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) { - string script = "param($targetType,$moduleName) & (Microsoft.PowerShell.Core\\Get-Module $moduleName) { New-Object $targetType } "; - - powerShell.AddScript(script); + powerShell.AddScript("param($targetType,$moduleName) & (Microsoft.PowerShell.Core\\Get-Module $moduleName) { New-Object $targetType } "); powerShell.AddArgument(targetType); powerShell.AddArgument(moduleName); @@ -73,7 +73,9 @@ public static object ConvertCimInstanceToObject(Type targetType, CimInstance ins MemberInfo[] memberInfo = targetType.GetMember(property.Name, BindingFlags.Public | BindingFlags.Instance); // verify property exists in corresponding class type - if (memberInfo == null || memberInfo.Length > 1 || !(memberInfo[0] is PropertyInfo || memberInfo[0] is FieldInfo)) + if (memberInfo == null + || memberInfo.Length > 1 + || (memberInfo[0] is not PropertyInfo && memberInfo[0] is not FieldInfo)) { errorMessage = string.Format(CultureInfo.CurrentCulture, ParserStrings.PropertyNotDeclaredInPSClass, new object[] { property.Name, className }); var invalidOperationException = new InvalidOperationException(errorMessage); @@ -259,12 +261,7 @@ private static object ConvertCimInstancePsCredential(string providerName, CimIns throw invalidOperationException; } - // Extract the password into a SecureString. - var password = new SecureString(); - foreach (char t in plainPassWord) - { - password.AppendChar(t); - } + SecureString password = SecureStringHelper.FromPlainTextString(plainPassWord); password.MakeReadOnly(); return new PSCredential(userName, password); @@ -320,8 +317,9 @@ public override object Transform(EngineIntrinsics engineIntrinsics, object input /// internal class CimDSCParser { - private CimMofDeserializer _deserializer; - private CimMofDeserializer.OnClassNeeded _onClassNeeded; + private readonly CimMofDeserializer _deserializer; + private readonly CimMofDeserializer.OnClassNeeded _onClassNeeded; + /// /// internal CimDSCParser(CimMofDeserializer.OnClassNeeded onClassNeeded) @@ -531,7 +529,7 @@ public static class DscClassCache private const string reservedProperties = "^(Require|Trigger|Notify|Before|After|Subscribe)$"; - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("DSC", "DSC Class Cache"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("DSC", "DSC Class Cache"); // Constants for items in the module qualified name (Module\Version\ClassName) private const int IndexModuleName = 0; @@ -541,19 +539,19 @@ public static class DscClassCache // Create a list of classes which are not actual DSC resources similar to what we do inside PSDesiredStateConfiguration.psm1 private static readonly string[] s_hiddenResourceList = - { - "MSFT_BaseConfigurationProviderRegistration", - "MSFT_CimConfigurationProviderRegistration", - "MSFT_PSConfigurationProviderRegistration", - }; + { + "MSFT_BaseConfigurationProviderRegistration", + "MSFT_CimConfigurationProviderRegistration", + "MSFT_PSConfigurationProviderRegistration", + }; // Create a HashSet for fast lookup. According to MSDN, the time complexity of search for an element in a HashSet is O(1) - private static readonly HashSet s_hiddenResourceCache = new HashSet(s_hiddenResourceList, - StringComparer.OrdinalIgnoreCase); + private static readonly HashSet s_hiddenResourceCache = + new(s_hiddenResourceList, StringComparer.OrdinalIgnoreCase); // a collection to hold current importing script based resource file // this prevent circular importing case when the script resource existing in the same module with resources it import-dscresource - private static readonly HashSet s_currentImportingScriptFiles = new HashSet(StringComparer.OrdinalIgnoreCase); + private static readonly HashSet s_currentImportingScriptFiles = new(StringComparer.OrdinalIgnoreCase); /// /// DSC class cache for this runspace. @@ -635,18 +633,20 @@ private static HashSet ScriptKeywordFileCache /// /// Default ModuleName and ModuleVersion to use. /// - private static readonly Tuple s_defaultModuleInfoForResource = new Tuple("PSDesiredStateConfiguration", new Version("1.1")); + private static readonly Tuple s_defaultModuleInfoForResource = + new("PSDesiredStateConfiguration", new Version("1.1")); /// /// Default ModuleName and ModuleVersion to use for meta configuration resources. /// - internal static readonly Tuple DefaultModuleInfoForMetaConfigResource = new Tuple("PSDesiredStateConfigurationEngine", new Version("2.0")); + internal static readonly Tuple DefaultModuleInfoForMetaConfigResource = + new("PSDesiredStateConfigurationEngine", new Version("2.0")); /// /// A set of dynamic keywords that can be used in both configuration and meta configuration. /// internal static readonly HashSet SystemResourceNames = - new HashSet(StringComparer.OrdinalIgnoreCase) { "Node", "OMI_ConfigurationDocument" }; + new(StringComparer.OrdinalIgnoreCase) { "Node", "OMI_ConfigurationDocument" }; /// /// When this property is set to true, DSC Cache will cache multiple versions of a resource. @@ -721,7 +721,7 @@ public static void Initialize(Collection errors, List moduleP continue; } - foreach (var schemaFile in Directory.EnumerateDirectories(resources).SelectMany(d => Directory.EnumerateFiles(d, "*.schema.mof"))) + foreach (var schemaFile in Directory.EnumerateDirectories(resources).SelectMany(static d => Directory.EnumerateFiles(d, "*.schema.mof"))) { ImportClasses(schemaFile, s_defaultModuleInfoForResource, errors); } @@ -773,7 +773,7 @@ public static void Initialize(Collection errors, List moduleP continue; } - foreach (var schemaFile in Directory.EnumerateDirectories(resources).SelectMany(d => Directory.EnumerateFiles(d, "*.schema.mof"))) + foreach (var schemaFile in Directory.EnumerateDirectories(resources).SelectMany(static d => Directory.EnumerateFiles(d, "*.schema.mof"))) { ImportClasses(schemaFile, s_defaultModuleInfoForResource, errors); } @@ -781,7 +781,7 @@ public static void Initialize(Collection errors, List moduleP // Load Regular and DSC PS modules bool importInBoxResourcesImplicitly = false; - List modulePaths = new List(); + List modulePaths = new(); if (modulePathList == null || modulePathList.Count == 0) { modulePaths.Add(Path.Combine(configSystemPath, inboxModulePath)); @@ -940,6 +940,20 @@ private static CimClass MyClassCallback(string serverName, string namespaceName, return null; } + /// + /// Reads CIM MOF schema file and returns classes defined in it. + /// This is used MOF->PSClass conversion tool. + /// + /// + /// Path to CIM MOF schema file for reading. + /// + /// List of classes from MOF schema file. + public static List ReadCimSchemaMof(string mofPath) + { + var parser = new Microsoft.PowerShell.DesiredStateConfiguration.CimDSCParser(MyClassCallback); + return parser.ParseSchemaMof(mofPath); + } + /// /// Import CIM classes from the given file. /// @@ -1034,7 +1048,7 @@ public static List ImportClasses(string path, Tuple m foreach (var c in classes) { sb.Append(c.CimSystemProperties.ClassName); - sb.Append(","); + sb.Append(','); } s_tracer.WriteLine("DSC ClassCache: loading file '{0}' added the following classes to the cache: {1}", path, sb.ToString()); @@ -1128,7 +1142,7 @@ private static List GetCachedClasses() /// List of cached cim classes. public static List GetCachedClassesForModule(PSModuleInfo module) { - List cachedClasses = new List(); + List cachedClasses = new(); var moduleQualifiedName = string.Format(CultureInfo.InvariantCulture, "{0}\\{1}", module.Name, module.Version.ToString()); foreach (var dscClassCacheEntry in ClassCache) { @@ -1148,7 +1162,7 @@ private static List GetCachedClasses() /// public static List GetFileDefiningClass(string className) { - List files = new List(); + List files = new(); foreach (var pair in ByFileClassCache) { var file = pair.Key; @@ -1295,7 +1309,7 @@ private static string GetFriendlyName(CimClass cimClass) /// public static Collection GetCachedKeywords() { - Collection keywords = new Collection(); + Collection keywords = new(); foreach (KeyValuePair cachedClass in ClassCache) { @@ -1906,7 +1920,7 @@ private static ParseError[] ImportResourceCheckSemantics(DynamicKeywordStatement // This function performs semantic checks for all DSC Resources keywords. private static ParseError[] CheckMandatoryPropertiesPresent(DynamicKeywordStatementAst kwAst) { - HashSet mandatoryPropertiesNames = new HashSet(StringComparer.OrdinalIgnoreCase); + HashSet mandatoryPropertiesNames = new(StringComparer.OrdinalIgnoreCase); foreach (var pair in kwAst.Keyword.Properties) { if (pair.Value.Mandatory) @@ -2143,7 +2157,7 @@ public static void LoadResourcesFromModule(IScriptExtent scriptExtent, } // resource name without wildcard (*) should be imported only once - if (!resourceToImport.Contains("*") && foundResources) + if (!resourceToImport.Contains('*') && foundResources) { resourcesFound.Add(resourceToImport); } @@ -2165,7 +2179,7 @@ public static void LoadResourcesFromModule(IScriptExtent scriptExtent, { foreach (var resourceNameToImport in resourcesToImport) { - if (!resourceNameToImport.Contains("*")) + if (!resourceNameToImport.Contains('*')) { errorList.Add(new ParseError(scriptExtent, "DscResourcesNotFoundDuringParsing", @@ -2327,7 +2341,7 @@ internal static string MapTypeNameToMofType(ITypeName typeName, string memberNam if (propTypeName._typeDefinitionAst.IsEnum) { - enumNames = propTypeName._typeDefinitionAst.Members.Select(m => m.Name).ToArray(); + enumNames = propTypeName._typeDefinitionAst.Members.Select(static m => m.Name).ToArray(); isArrayType = false; embeddedInstanceType = null; return "string"; @@ -2349,7 +2363,7 @@ private static void GenerateMofForAst(TypeDefinitionAst typeAst, StringBuilder s var className = typeAst.Name; sb.AppendFormat(CultureInfo.InvariantCulture, "[ClassVersion(\"1.0.0\"), FriendlyName(\"{0}\")]\nclass {0}", className); - if (typeAst.Attributes.Any(a => a.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute))) + if (typeAst.Attributes.Any(static a => a.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute))) { sb.Append(" : OMI_BaseResource"); } @@ -2358,7 +2372,7 @@ private static void GenerateMofForAst(TypeDefinitionAst typeAst, StringBuilder s ProcessMembers(sb, embeddedInstanceTypes, typeAst, className); - Queue bases = new Queue(); + Queue bases = new(); foreach (var b in typeAst.BaseTypes) { bases.Enqueue(b); @@ -2456,7 +2470,7 @@ public static bool GetResourceMethodsLinePosition(PSModuleInfo moduleInfo, strin } IEnumerable resourceDefinitions; - List moduleFiles = new List(); + List moduleFiles = new(); if (moduleInfo.RootModule != null) { moduleFiles.Add(moduleInfo.Path); @@ -2464,7 +2478,7 @@ public static bool GetResourceMethodsLinePosition(PSModuleInfo moduleInfo, strin if (moduleInfo.NestedModules != null) { - foreach (var nestedModule in moduleInfo.NestedModules.Where(m => !string.IsNullOrEmpty(m.Path))) + foreach (var nestedModule in moduleInfo.NestedModules.Where(static m => !string.IsNullOrEmpty(m.Path))) { moduleFiles.Add(nestedModule.Path); } @@ -2590,7 +2604,7 @@ private static bool GetResourceDefinitionsFromModule(string fileName, out IEnume { if (errorList != null && extent != null) { - List errorMessages = new List(); + List errorMessages = new(); foreach (var error in errors) { errorMessages.Add(error.ToString()); @@ -2695,19 +2709,19 @@ private static bool ImportKeywordsFromScriptFile(string fileName, PSModuleInfo m return result; } - private static readonly Dictionary s_mapPrimitiveDotNetTypeToMof = new Dictionary() + private static readonly Dictionary s_mapPrimitiveDotNetTypeToMof = new() { { typeof(sbyte), "sint8" }, - { typeof(byte) , "uint8"}, - { typeof(short) , "sint16"}, - { typeof(ushort) , "uint16"}, - { typeof(int) , "sint32"}, - { typeof(uint) , "uint32"}, - { typeof(long) , "sint64"}, + { typeof(byte), "uint8"}, + { typeof(short), "sint16"}, + { typeof(ushort), "uint16"}, + { typeof(int), "sint32"}, + { typeof(uint), "uint32"}, + { typeof(long), "sint64"}, { typeof(ulong), "uint64" }, - { typeof(float) , "real32"}, - { typeof(double) , "real64"}, - { typeof(bool) , "boolean"}, + { typeof(float), "real32"}, + { typeof(double), "real64"}, + { typeof(bool), "boolean"}, { typeof(string), "string" }, { typeof(DateTime), "datetime" }, { typeof(PSCredential), "string" }, @@ -2911,7 +2925,7 @@ private static string MapAttributesToMof(string[] enumNames, IEnumerable { var sb = new StringBuilder(); - sb.Append("["); + sb.Append('['); bool needComma = false; foreach (var attr in customAttributes) { @@ -2943,7 +2957,7 @@ private static string MapAttributesToMof(string[] enumNames, IEnumerable if (validateSet != null) { bool valueMapComma = false; - StringBuilder sbValues = new StringBuilder(", Values{"); + StringBuilder sbValues = new(", Values{"); sb.AppendFormat(CultureInfo.InvariantCulture, "{0}ValueMap{{", needComma ? ", " : string.Empty); needComma = true; @@ -2954,9 +2968,9 @@ private static string MapAttributesToMof(string[] enumNames, IEnumerable valueMapComma = true; } - sb.Append("}"); + sb.Append('}'); sb.Append(sbValues); - sb.Append("}"); + sb.Append('}'); } } @@ -2985,14 +2999,14 @@ private static string MapAttributesToMof(string[] enumNames, IEnumerable needComma = true; } - sb.Append("}"); + sb.Append('}'); } else if (embeddedInstanceType != null) { sb.AppendFormat(CultureInfo.InvariantCulture, "{0}EmbeddedInstance(\"{1}\")", needComma ? ", " : string.Empty, embeddedInstanceType); } - sb.Append("]"); + sb.Append(']'); return sb.ToString(); } @@ -3070,9 +3084,9 @@ private static void GenerateMofForType(Type type, StringBuilder sb, List private static void ProcessMembers(Type type, StringBuilder sb, List embeddedInstanceTypes, string className) { - foreach (var member in type.GetMembers(BindingFlags.Instance | BindingFlags.Public).Where(m => m is PropertyInfo || m is FieldInfo)) + foreach (var member in type.GetMembers(BindingFlags.Instance | BindingFlags.Public).Where(static m => m is PropertyInfo || m is FieldInfo)) { - if (member.CustomAttributes.All(cad => cad.AttributeType != typeof(DscPropertyAttribute))) + if (member.CustomAttributes.All(static cad => cad.AttributeType != typeof(DscPropertyAttribute))) { continue; } @@ -3124,7 +3138,7 @@ private static bool ImportKeywordsFromAssembly(PSModuleInfo module, var parser = new Microsoft.PowerShell.DesiredStateConfiguration.CimDSCParser(MyClassCallback); IEnumerable resourceDefinitions = - assembly.GetTypes().Where(t => t.GetCustomAttributes().Any()); + assembly.GetTypes().Where(static t => t.GetCustomAttributes().Any()); foreach (var r in resourceDefinitions) { @@ -3618,7 +3632,7 @@ public static string GetDSCResourceUsageString(DynamicKeyword keyword) bool listKeyProperties = true; while (true) { - foreach (var prop in keyword.Properties.OrderBy(ob => ob.Key)) + foreach (var prop in keyword.Properties.OrderBy(static ob => ob.Key)) { if (string.Equals(prop.Key, "ResourceId", StringComparison.OrdinalIgnoreCase)) { @@ -3645,7 +3659,7 @@ public static string GetDSCResourceUsageString(DynamicKeyword keyword) } } - usageString.Append("}"); + usageString.Append('}'); return usageString.ToString(); } @@ -3659,7 +3673,7 @@ public static string GetDSCResourceUsageString(DynamicKeyword keyword) private static StringBuilder FormatCimPropertyType(DynamicKeywordProperty prop, bool isOptionalProperty) { string cimTypeName = prop.TypeConstraint; - StringBuilder formattedTypeString = new StringBuilder(); + StringBuilder formattedTypeString = new(); if (string.Equals(cimTypeName, "MSFT_Credential", StringComparison.OrdinalIgnoreCase)) { @@ -3685,16 +3699,16 @@ private static StringBuilder FormatCimPropertyType(DynamicKeywordProperty prop, // Do the property values map if (prop.ValueMap != null && prop.ValueMap.Count > 0) { - formattedTypeString.Append(" { " + string.Join(" | ", prop.ValueMap.Keys.OrderBy(x => x)) + " }"); + formattedTypeString.Append(" { " + string.Join(" | ", prop.ValueMap.Keys.OrderBy(static x => x)) + " }"); } // We prepend optional property with "[" so close out it here. This way it is shown with [ ] to indication optional if (isOptionalProperty) { - formattedTypeString.Append("]"); + formattedTypeString.Append(']'); } - formattedTypeString.Append("\n"); + formattedTypeString.Append('\n'); return formattedTypeString; } @@ -3707,8 +3721,7 @@ private static ScriptBlock CimKeywordImplementationFunction get { // The scriptblock cache will handle mutual exclusion - return s_cimKeywordImplementationFunction ?? - (s_cimKeywordImplementationFunction = ScriptBlock.Create(CimKeywordImplementationFunctionText)); + return s_cimKeywordImplementationFunction ??= ScriptBlock.Create(CimKeywordImplementationFunctionText); } } diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs index 374cadf31d8..01cba83cd00 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs @@ -42,27 +42,24 @@ internal static IEnumerable GetFormatData() private static IEnumerable ViewsOf_FileSystemTypes(CustomControl[] sharedControls) { #if UNIX - if (ExperimentalFeature.IsEnabled("PSUnixFileStat")) - { - yield return new FormatViewDefinition("childrenWithUnixStat", - TableControl.Create() - .GroupByProperty("PSParentPath", customControl: sharedControls[0]) - .AddHeader(Alignment.Left, label: "UnixMode", width: 10) - .AddHeader(Alignment.Left, label: "User", width: 16) - .AddHeader(Alignment.Left, label: "Group", width: 16) - .AddHeader(Alignment.Right, label: "LastWriteTime", width: 18) - .AddHeader(Alignment.Right, label: "Size", width: 14) - .AddHeader(Alignment.Left, label: "Name") - .StartRowDefinition(wrap: true) - .AddPropertyColumn("UnixMode") - .AddPropertyColumn("User") - .AddPropertyColumn("Group") - .AddScriptBlockColumn(scriptBlock: @"'{0:d} {0:HH}:{0:mm}' -f $_.LastWriteTime") - .AddPropertyColumn("Size") - .AddPropertyColumn("NameString") - .EndRowDefinition() - .EndTable()); - } + yield return new FormatViewDefinition("childrenWithUnixStat", + TableControl.Create() + .GroupByProperty("PSParentPath", customControl: sharedControls[0]) + .AddHeader(Alignment.Left, label: "UnixMode", width: 10) + .AddHeader(Alignment.Left, label: "User", width: 16) + .AddHeader(Alignment.Left, label: "Group", width: 16) + .AddHeader(Alignment.Right, label: "LastWriteTime", width: 18) + .AddHeader(Alignment.Right, label: "Size", width: 14) + .AddHeader(Alignment.Left, label: "Name") + .StartRowDefinition(wrap: true) + .AddPropertyColumn("UnixMode") + .AddPropertyColumn("User") + .AddPropertyColumn("Group") + .AddScriptBlockColumn(scriptBlock: @"'{0:d} {0:HH}:{0:mm}' -f $_.LastWriteTime") + .AddPropertyColumn("Size") + .AddPropertyColumn("NameString") + .EndRowDefinition() + .EndTable()); #endif yield return new FormatViewDefinition("children", diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/HelpV3_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/HelpV3_format_ps1xml.cs index d04ea1bdedf..fc5ddc5ab9a 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/HelpV3_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/HelpV3_format_ps1xml.cs @@ -175,7 +175,7 @@ internal static IEnumerable GetFormatData() .EndControl(); var sharedControls = new CustomControl[] { - null,//MamlParameterValueGroupControl, + null, //MamlParameterValueGroupControl, MamlParameterControl, MamlTypeControl, MamlParameterValueControl, diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 4fa68787787..ef7c40fd37b 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -263,6 +263,30 @@ internal static IEnumerable GetFormatData() yield return new ExtendedTypeDefinition( "Microsoft.PowerShell.Commands.ByteCollection", ViewsOf_Microsoft_PowerShell_Commands_ByteCollection()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle", + ViewsOf_System_Management_Automation_PSStyle()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+FormattingData", + ViewsOf_System_Management_Automation_PSStyleFormattingData()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+ProgressConfiguration", + ViewsOf_System_Management_Automation_PSStyleProgressConfiguration()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+FileInfoFormatting", + ViewsOf_System_Management_Automation_PSStyleFileInfoFormat()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+ForegroundColor", + ViewsOf_System_Management_Automation_PSStyleForegroundColor()); + + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+BackgroundColor", + ViewsOf_System_Management_Automation_PSStyleBackgroundColor()); } private static IEnumerable ViewsOf_System_RuntimeType() @@ -738,7 +762,7 @@ private static IEnumerable ViewsOf_System_Management_Autom "System.Management.Automation.Subsystem.SubsystemInfo", TableControl.Create() .AddHeader(Alignment.Left, width: 17, label: "Kind") - .AddHeader(Alignment.Left, width: 15, label: "SubsystemType") + .AddHeader(Alignment.Left, width: 18, label: "SubsystemType") .AddHeader(Alignment.Right, width: 12, label: "IsRegistered") .AddHeader(Alignment.Left, label: "Implementations") .StartRowDefinition() @@ -786,7 +810,12 @@ private static IEnumerable ViewsOf_System_Management_Autom $maxDepth = 10 $ellipsis = ""`u{2026}"" $resetColor = '' + $errorColor = '' if ($Host.UI.SupportsVirtualTerminal -and ([string]::IsNullOrEmpty($env:__SuppressAnsiEscapeSequences))) { + if ($null -ne $psstyle) { + $errorColor = $psstyle.Formatting.Error + } + $resetColor = [System.Management.Automation.VTUtility]::GetEscapeSequence( [System.Management.Automation.VTUtility+VT]::Reset ) @@ -923,6 +952,13 @@ private static IEnumerable ViewsOf_System_Management_Autom $value = $null if ([System.Management.Automation.LanguagePrimitives]::TryConvertTo($prop.Value, [string], [ref]$value) -and $value -ne $null) { + if ($prop.Name -eq 'PositionMessage') { + $value = $value.Insert($value.IndexOf('~'), $errorColor) + } + elseif ($prop.Name -eq 'Message') { + $value = $errorColor + $value + } + $isFirstLine = $true if ($value.Contains($newline)) { # the 3 is to account for ' : ' @@ -976,7 +1012,7 @@ private static IEnumerable ViewsOf_System_Management_Autom CustomControl.Create(outOfBand: true) .StartEntry() .AddScriptBlockExpressionBinding(@" - if (@('NativeCommandErrorMessage','NativeCommandError') -notcontains $_.FullyQualifiedErrorId -and @('CategoryView','ConciseView') -notcontains $ErrorView) + if (@('NativeCommandErrorMessage','NativeCommandError') -notcontains $_.FullyQualifiedErrorId -and @('CategoryView','ConciseView','DetailedView') -notcontains $ErrorView) { $myinv = $_.InvocationInfo if ($myinv -and $myinv.MyCommand) @@ -1085,7 +1121,8 @@ function Get-ConciseViewPositionMessage { $message = '' $prefix = '' - if ($myinv -and $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1 -or $err.CategoryInfo.Category -eq 'ParserError') { + # Don't show line information if script module + if (($myinv -and $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1 -or $err.CategoryInfo.Category -eq 'ParserError') -and !($myinv.ScriptName.EndsWith('.psm1', [System.StringComparison]::OrdinalIgnoreCase))) { $useTargetObject = $false # Handle case where there is a TargetObject and we can show the error at the target rather than the script source @@ -1265,7 +1302,10 @@ function Get-ConciseViewPositionMessage { else { $myinv = $err.InvocationInfo - if ($ErrorView -eq 'ConciseView') { + if ($ErrorView -eq 'DetailedView') { + return (Get-Error | Out-String) + } + elseif ($ErrorView -eq 'ConciseView') { $posmsg = Get-ConciseViewPositionMessage } elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne 'ParserError'))) { @@ -1317,7 +1357,7 @@ function Get-ConciseViewPositionMessage { $err.CategoryInfo.GetMessage() } elseif (! $err.ErrorDetails -or ! $err.ErrorDetails.Message) { - $err.Exception.Message + $posmsg + $newline + $err.Exception.Message + $posmsg } else { $err.ErrorDetails.Message + $posmsg } @@ -1667,8 +1707,8 @@ private static IEnumerable ViewsOf_Microsoft_PowerShell_Co } private const string PreReleaseStringScriptBlock = @" - if ($_.PrivateData -and - $_.PrivateData.ContainsKey('PSData') -and + if ($_.PrivateData -and + $_.PrivateData.ContainsKey('PSData') -and $_.PrivateData.PSData.ContainsKey('PreRelease')) { $_.PrivateData.PSData.PreRelease @@ -2004,5 +2044,189 @@ private static IEnumerable ViewsOf_Microsoft_PowerShell_Co .GroupByProperty("Label") .EndTable()); } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyle() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Reset)$($_.Reset.Replace(""""`e"""",'`e'))""", label: "Reset") + .AddItemScriptBlock(@"""$($_.BlinkOff)$($_.BlinkOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "BlinkOff") + .AddItemScriptBlock(@"""$($_.Blink)$($_.Blink.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Blink") + .AddItemScriptBlock(@"""$($_.BoldOff)$($_.BoldOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "BoldOff") + .AddItemScriptBlock(@"""$($_.Bold)$($_.Bold.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Bold") + .AddItemScriptBlock(@"""$($_.Hidden)$($_.Hidden.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Hidden") + .AddItemScriptBlock(@"""$($_.HiddenOff)$($_.HiddenOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "HiddenOff") + .AddItemScriptBlock(@"""$($_.Reverse)$($_.Reverse.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Reverse") + .AddItemScriptBlock(@"""$($_.ReverseOff)$($_.ReverseOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "ReverseOff") + .AddItemScriptBlock(@"""$($_.ItalicOff)$($_.ItalicOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "ItalicOff") + .AddItemScriptBlock(@"""$($_.Italic)$($_.Italic.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Italic") + .AddItemScriptBlock(@"""$($_.UnderlineOff)$($_.UnderlineOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "UnderlineOff") + .AddItemScriptBlock(@"""$($_.Underline)$($_.Underline.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Underline") + .AddItemScriptBlock(@"""$($_.StrikethroughOff)$($_.StrikethroughOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "StrikethroughOff") + .AddItemScriptBlock(@"""$($_.Strikethrough)$($_.Strikethrough.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Strikethrough") + .AddItemProperty(@"OutputRendering") + .AddItemScriptBlock(@"""$($_.Formatting.FormatAccent)$($_.Formatting.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.FormatAccent") + .AddItemScriptBlock(@"""$($_.Formatting.TableHeader)$($_.Formatting.TableHeader.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.TableHeader") + .AddItemScriptBlock(@"""$($_.Formatting.ErrorAccent)$($_.Formatting.ErrorAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.ErrorAccent") + .AddItemScriptBlock(@"""$($_.Formatting.Error)$($_.Formatting.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Error") + .AddItemScriptBlock(@"""$($_.Formatting.Warning)$($_.Formatting.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Warning") + .AddItemScriptBlock(@"""$($_.Formatting.Verbose)$($_.Formatting.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Verbose") + .AddItemScriptBlock(@"""$($_.Formatting.Debug)$($_.Formatting.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Debug") + .AddItemScriptBlock(@"""$($_.Progress.Style)$($_.Progress.Style.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Progress.Style") + .AddItemScriptBlock(@"""$($_.Progress.MaxWidth)""", label: "Progress.MaxWidth") + .AddItemScriptBlock(@"""$($_.Progress.View)""", label: "Progress.View") + .AddItemScriptBlock(@"""$($_.Progress.UseOSCIndicator)""", label: "Progress.UseOSCIndicator") + .AddItemScriptBlock(@"""$($_.FileInfo.Directory)$($_.FileInfo.Directory.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FileInfo.Directory") + .AddItemScriptBlock(@"""$($_.FileInfo.SymbolicLink)$($_.FileInfo.SymbolicLink.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FileInfo.SymbolicLink") + .AddItemScriptBlock(@"""$($_.FileInfo.Executable)$($_.FileInfo.Executable.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FileInfo.Executable") + .AddItemScriptBlock(@"""$([string]::Join(',',$_.FileInfo.Extension.Keys))""", label: "FileInfo.Extension") + .AddItemScriptBlock(@"""$($_.Foreground.Black)$($_.Foreground.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Black") + .AddItemScriptBlock(@"""$($_.Foreground.BrightBlack)$($_.Foreground.BrightBlack.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightBlack") + .AddItemScriptBlock(@"""$($_.Foreground.White)$($_.Foreground.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.White") + .AddItemScriptBlock(@"""$($_.Foreground.BrightWhite)$($_.Foreground.BrightWhite.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightWhite") + .AddItemScriptBlock(@"""$($_.Foreground.Red)$($_.Foreground.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Red") + .AddItemScriptBlock(@"""$($_.Foreground.BrightRed)$($_.Foreground.BrightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightRed") + .AddItemScriptBlock(@"""$($_.Foreground.Magenta)$($_.Foreground.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Magenta") + .AddItemScriptBlock(@"""$($_.Foreground.BrightMagenta)$($_.Foreground.BrightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightMagenta") + .AddItemScriptBlock(@"""$($_.Foreground.Blue)$($_.Foreground.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Blue") + .AddItemScriptBlock(@"""$($_.Foreground.BrightBlue)$($_.Foreground.BrightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightBlue") + .AddItemScriptBlock(@"""$($_.Foreground.Cyan)$($_.Foreground.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Cyan") + .AddItemScriptBlock(@"""$($_.Foreground.BrightCyan)$($_.Foreground.BrightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightCyan") + .AddItemScriptBlock(@"""$($_.Foreground.Green)$($_.Foreground.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Green") + .AddItemScriptBlock(@"""$($_.Foreground.BrightGreen)$($_.Foreground.BrightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightGreen") + .AddItemScriptBlock(@"""$($_.Foreground.Yellow)$($_.Foreground.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Yellow") + .AddItemScriptBlock(@"""$($_.Foreground.BrightYellow)$($_.Foreground.BrightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.BrightYellow") + .AddItemScriptBlock(@"""$($_.Background.Black)$($_.Background.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Black") + .AddItemScriptBlock(@"""$($_.Background.BrightBlack)$($_.Background.BrightBlack.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightBlack") + .AddItemScriptBlock(@"""$($_.Background.White)$($_.Background.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.White") + .AddItemScriptBlock(@"""$($_.Background.BrightWhite)$($_.Background.BrightWhite.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightWhite") + .AddItemScriptBlock(@"""$($_.Background.Red)$($_.Background.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Red") + .AddItemScriptBlock(@"""$($_.Background.BrightRed)$($_.Background.BrightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightRed") + .AddItemScriptBlock(@"""$($_.Background.Magenta)$($_.Background.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Magenta") + .AddItemScriptBlock(@"""$($_.Background.BrightMagenta)$($_.Background.BrightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightMagenta") + .AddItemScriptBlock(@"""$($_.Background.Blue)$($_.Background.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Blue") + .AddItemScriptBlock(@"""$($_.Background.BrightBlue)$($_.Background.BrightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightBlue") + .AddItemScriptBlock(@"""$($_.Background.Cyan)$($_.Background.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Cyan") + .AddItemScriptBlock(@"""$($_.Background.BrightCyan)$($_.Background.BrightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightCyan") + .AddItemScriptBlock(@"""$($_.Background.Green)$($_.Background.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Green") + .AddItemScriptBlock(@"""$($_.Background.BrightGreen)$($_.Background.BrightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightGreen") + .AddItemScriptBlock(@"""$($_.Background.Yellow)$($_.Background.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Yellow") + .AddItemScriptBlock(@"""$($_.Background.BrightYellow)$($_.Background.BrightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.BrightYellow") + .EndEntry() + .EndList()); + } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleFormattingData() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+FormattingData", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.FormatAccent)$($_.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FormatAccent") + .AddItemScriptBlock(@"""$($_.TableHeader)$($_.TableHeader.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "TableHeader") + .AddItemScriptBlock(@"""$($_.ErrorAccent)$($_.ErrorAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "ErrorAccent") + .AddItemScriptBlock(@"""$($_.Error)$($_.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Error") + .AddItemScriptBlock(@"""$($_.Warning)$($_.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Warning") + .AddItemScriptBlock(@"""$($_.Verbose)$($_.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Verbose") + .AddItemScriptBlock(@"""$($_.Debug)$($_.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Debug") + .EndEntry() + .EndList()); + } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleProgressConfiguration() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ProgressConfiguration", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Style)$($_.Style.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Style") + .AddItemProperty(@"MaxWidth") + .AddItemProperty(@"View") + .AddItemProperty(@"UseOSCIndicator") + .EndEntry() + .EndList()); + } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleFileInfoFormat() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+FileInfoFormatting", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Directory)$($_.Directory.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Directory") + .AddItemScriptBlock(@"""$($_.SymbolicLink)$($_.SymbolicLink.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "SymbolicLink") + .AddItemScriptBlock(@"""$($_.Executable)$($_.Executable.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Executable") + .AddItemScriptBlock(@" + $sb = [System.Text.StringBuilder]::new() + $maxKeyLength = 0 + foreach ($key in $_.Extension.Keys) { + if ($key.Length -gt $maxKeyLength) { + $maxKeyLength = $key.Length + } + } + + foreach ($key in $_.Extension.Keys) { + $null = $sb.Append($key.PadRight($maxKeyLength)) + $null = $sb.Append(' = ""') + $null = $sb.Append($_.Extension[$key]) + $null = $sb.Append($_.Extension[$key].Replace(""`e"",'`e')) + $null = $sb.Append($PSStyle.Reset) + $null = $sb.Append('""') + $null = $sb.Append([Environment]::NewLine) + } + + $sb.ToString()", + label: "Extension") + .EndEntry() + .EndList()); + } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleForegroundColor() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ForegroundColor", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Black)$($_.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Black") + .AddItemScriptBlock(@"""$($_.BrightBlack)$($_.BrightBlack.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightBlack") + .AddItemScriptBlock(@"""$($_.White)$($_.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "White") + .AddItemScriptBlock(@"""$($_.BrightWhite)$($_.BrightWhite.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightWhite") + .AddItemScriptBlock(@"""$($_.Red)$($_.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Red") + .AddItemScriptBlock(@"""$($_.BrightRed)$($_.BrightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightRed") + .AddItemScriptBlock(@"""$($_.Magenta)$($_.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Magenta") + .AddItemScriptBlock(@"""$($_.BrightMagenta)$($_.BrightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightMagenta") + .AddItemScriptBlock(@"""$($_.Blue)$($_.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Blue") + .AddItemScriptBlock(@"""$($_.BrightBlue)$($_.BrightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightBlue") + .AddItemScriptBlock(@"""$($_.Cyan)$($_.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Cyan") + .AddItemScriptBlock(@"""$($_.BrightCyan)$($_.BrightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightCyan") + .AddItemScriptBlock(@"""$($_.Green)$($_.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Green") + .AddItemScriptBlock(@"""$($_.BrightGreen)$($_.BrightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightGreen") + .AddItemScriptBlock(@"""$($_.Yellow)$($_.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Yellow") + .AddItemScriptBlock(@"""$($_.BrightYellow)$($_.BrightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightYellow") + .EndEntry() + .EndList()); + } + + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleBackgroundColor() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+BackgroundColor", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Black)$($_.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Black") + .AddItemScriptBlock(@"""$($_.BrightBlack)$($_.BrightBlack.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightBlack") + .AddItemScriptBlock(@"""$($_.White)$($_.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "White") + .AddItemScriptBlock(@"""$($_.BrightWhite)$($_.BrightWhite.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightWhite") + .AddItemScriptBlock(@"""$($_.Red)$($_.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Red") + .AddItemScriptBlock(@"""$($_.BrightRed)$($_.BrightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightRed") + .AddItemScriptBlock(@"""$($_.Magenta)$($_.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Magenta") + .AddItemScriptBlock(@"""$($_.BrightMagenta)$($_.BrightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightMagenta") + .AddItemScriptBlock(@"""$($_.Blue)$($_.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Blue") + .AddItemScriptBlock(@"""$($_.BrightBlue)$($_.BrightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightBlue") + .AddItemScriptBlock(@"""$($_.Cyan)$($_.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Cyan") + .AddItemScriptBlock(@"""$($_.BrightCyan)$($_.BrightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightCyan") + .AddItemScriptBlock(@"""$($_.Green)$($_.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Green") + .AddItemScriptBlock(@"""$($_.BrightGreen)$($_.BrightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightGreen") + .AddItemScriptBlock(@"""$($_.Yellow)$($_.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Yellow") + .AddItemScriptBlock(@"""$($_.BrightYellow)$($_.BrightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "BrightYellow") + .EndEntry() + .EndList()); + } } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/BaseCommand.cs b/src/System.Management.Automation/FormatAndOutput/common/BaseCommand.cs index e03b4ae61eb..e59cae40146 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/BaseCommand.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/BaseCommand.cs @@ -22,12 +22,13 @@ internal TerminatingErrorContext(PSCmdlet command) _command = command; } + [System.Diagnostics.CodeAnalysis.DoesNotReturn] internal void ThrowTerminatingError(ErrorRecord errorRecord) { _command.ThrowTerminatingError(errorRecord); } - private PSCmdlet _command; + private readonly PSCmdlet _command; } /// @@ -133,7 +134,7 @@ public void Dispose() private string _commandName = null; private Type _commandType; - private List _commandParameterList = new List(); + private readonly List _commandParameterList = new List(); private ExecutionContext _context = null; } @@ -150,7 +151,7 @@ public abstract class FrontEndCommandBase : PSCmdlet, IDisposable /// This parameter specifies the current pipeline object. /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; #endregion @@ -404,4 +405,3 @@ protected virtual void InternalDispose() } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs index ffccf13f4e1..18b74cbcfe1 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs @@ -517,7 +517,7 @@ private void PopGroup() /// /// The formatting shape this formatter emits. /// - private FormatShape _shape; + private readonly FormatShape _shape; #region expression factory @@ -537,7 +537,7 @@ internal ScriptBlock CreateScriptBlock(string scriptText) private TypeInfoDataBase _typeInfoDataBase = null; private FormattingCommandLineParameters _parameters = null; - private FormatViewManager _viewManager = new FormatViewManager(); + private readonly FormatViewManager _viewManager = new FormatViewManager(); private int _enumerationLimit = InitialSessionState.DefaultFormatEnumerationLimit; } @@ -576,7 +576,10 @@ public SwitchParameter ShowError return false; } - set { showErrorsAsMessages = value; } + set + { + showErrorsAsMessages = value; + } } internal bool? showErrorsAsMessages = null; @@ -595,7 +598,10 @@ public SwitchParameter DisplayError return false; } - set { showErrorsInFormattedOutput = value; } + set + { + showErrorsInFormattedOutput = value; + } } internal bool? showErrorsInFormattedOutput = null; @@ -792,7 +798,10 @@ public SwitchParameter AutoSize return false; } - set { _autosize = value; } + set + { + _autosize = value; + } } private bool? _autosize = null; @@ -817,7 +826,10 @@ public SwitchParameter HideTableHeaders return false; } - set { _hideHeaders = value; } + set + { + _hideHeaders = value; + } } private bool? _hideHeaders = null; @@ -836,7 +848,10 @@ public SwitchParameter Wrap return false; } - set { _multiLine = value; } + set + { + _multiLine = value; + } } private bool? _multiLine = null; @@ -882,4 +897,3 @@ internal override FormattingCommandLineParameters GetCommandLineParameters() } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommandParameters.cs b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommandParameters.cs index cdd60637a7a..95c58353457 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommandParameters.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommandParameters.cs @@ -249,7 +249,7 @@ private void ProcessGlobbingCharactersError(bool originalParameterWasHashTable, #endregion - private bool _noGlobbing; + private readonly bool _noGlobbing; } internal class AlignmentEntryDefinition : HashtableEntryDefinition @@ -489,4 +489,3 @@ protected override void SetEntries() } #endregion } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/BaseOutputtingCommand.cs b/src/System.Management.Automation/FormatAndOutput/common/BaseOutputtingCommand.cs index bb8305b2fdc..136b7a26ef5 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/BaseOutputtingCommand.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/BaseOutputtingCommand.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Management.Automation; using System.Management.Automation.Internal; @@ -181,7 +180,7 @@ private FormatShape ActiveFormattingShape { // we assume that the format context // contains the information - FormatShape shape = FormatShape.Table; // default + const FormatShape shape = FormatShape.Table; // default FormatOutputContext foc = this.FormatContext; if (foc == null || foc.Data.shapeInfo == null) @@ -596,9 +595,9 @@ private void ProcessOutOfBandPayload(FormatEntryData fed) internal LineOutput LineOutput { - set { _lo = value; } - get { return _lo; } + + set { _lo = value; } } private ShapeInfo ShapeInfoOnFormatContext @@ -637,7 +636,7 @@ private FormatOutputContext FormatContext /// /// Context manager instance to guide the message traversal. /// - private FormatMessagesContextManager _ctxManager = new FormatMessagesContextManager(); + private readonly FormatMessagesContextManager _ctxManager = new FormatMessagesContextManager(); private FormattedObjectsCache _cache = null; @@ -848,7 +847,7 @@ private FormattingHint RetrieveFormattingHint() /// /// Context for the outer scope of the format sequence. /// - private class FormatOutputContext : FormatMessagesContextManager.OutputContext + private sealed class FormatOutputContext : FormatMessagesContextManager.OutputContext { /// /// Construct a context to push on the stack. @@ -940,7 +939,7 @@ internal TableOutputContextBase(OutCommandInner cmd, /// /// Helper class to properly write a table using text output. /// - private TableWriter _tableWriter = new TableWriter(); + private readonly TableWriter _tableWriter = new TableWriter(); } private sealed class TableOutputContext : TableOutputContextBase @@ -951,7 +950,7 @@ private sealed class TableOutputContext : TableOutputContextBase private const int WhitespaceAndPagerLineCount = 2; - private bool _repeatHeader = false; + private readonly bool _repeatHeader = false; /// /// Construct a context to push on the stack. @@ -1117,33 +1116,40 @@ private void InternalInitialize(ListViewEntry lve) internal static string[] GetProperties(ListViewEntry lve) { - StringCollection props = new StringCollection(); - foreach (ListViewField lvf in lve.listViewFieldList) + int count = lve.listViewFieldList.Count; + + if (count == 0) { - props.Add(lvf.label ?? lvf.propertyName); + return null; } - if (props.Count == 0) - return null; - string[] retVal = new string[props.Count]; - props.CopyTo(retVal, 0); - return retVal; + string[] result = new string[count]; + for (int index = 0; index < result.Length; ++index) + { + ListViewField lvf = lve.listViewFieldList[index]; + result[index] = lvf.label ?? lvf.propertyName; + } + + return result; } internal static string[] GetValues(ListViewEntry lve) { - StringCollection vals = new StringCollection(); + int count = lve.listViewFieldList.Count; - foreach (ListViewField lvf in lve.listViewFieldList) + if (count == 0) { - vals.Add(lvf.formatPropertyField.propertyValue); + return null; } - if (vals.Count == 0) - return null; - string[] retVal = new string[vals.Count]; - vals.CopyTo(retVal, 0); - return retVal; + string[] result = new string[count]; + for (int index = 0; index < result.Length; ++index) + { + ListViewField lvf = lve.listViewFieldList[index]; + result[index] = lvf.formatPropertyField.propertyValue; + } + + return result; } /// @@ -1174,7 +1180,7 @@ internal override void ProcessPayload(FormatEntryData fed) /// /// Writer to do the actual formatting. /// - private ListWriter _listWriter = new ListWriter(); + private readonly ListWriter _listWriter = new ListWriter(); } private sealed class WideOutputContext : TableOutputContextBase @@ -1296,7 +1302,7 @@ private void WriteStringBuffer() /// Helper class to accumulate the display values so that when the end /// of a line is reached, a full line can be composed. /// - private class StringValuesBuffer + private sealed class StringValuesBuffer { /// /// Construct the buffer. @@ -1357,7 +1363,7 @@ internal void Reset() _arr[k] = null; } - private string[] _arr; + private readonly string[] _arr; private int _lastEmptySpot; } } @@ -1395,8 +1401,7 @@ internal override void ProcessPayload(FormatEntryData fed) _writer.WriteObject(cve.formatValueList); } - private ComplexWriter _writer = new ComplexWriter(); + private readonly ComplexWriter _writer = new ComplexWriter(); } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/ColumnWidthManager.cs b/src/System.Management.Automation/FormatAndOutput/common/ColumnWidthManager.cs index d2e44c4ad60..68ccc7ebc59 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/ColumnWidthManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/ColumnWidthManager.cs @@ -201,8 +201,8 @@ private static int GetLastVisibleColumn(Span columnWidths) return columnWidths.Length - 1; } - private int _tableWidth; - private int _minimumColumnWidth; - private int _separatorWidth; + private readonly int _tableWidth; + private readonly int _minimumColumnWidth; + private readonly int _separatorWidth; } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/ComplexWriter.cs b/src/System.Management.Automation/FormatAndOutput/common/ComplexWriter.cs index 74031dc515c..187775d3072 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/ComplexWriter.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/ComplexWriter.cs @@ -206,7 +206,7 @@ private void WriteToScreen() /// /// Helper object to manage the frame-based indentation and margins. /// - private IndentationManager _indentationManager = new IndentationManager(); + private readonly IndentationManager _indentationManager = new IndentationManager(); /// /// Buffer to accumulate partially constructed text. @@ -243,7 +243,7 @@ public void Dispose() } } - private IndentationManager _mgr; + private readonly IndentationManager _mgr; } internal void Clear() @@ -311,7 +311,7 @@ private int ComputeLeftIndentation() return val; } - private Stack _frameInfoStack = new Stack(); + private readonly Stack _frameInfoStack = new Stack(); } /// @@ -331,7 +331,7 @@ internal sealed class StringManipulationHelper private static readonly char s_softHyphen = '\u00AD'; private static readonly char s_hardHyphen = '\u2011'; private static readonly char s_nonBreakingSpace = '\u00A0'; - private static Collection s_cultureCollection = new Collection(); + private static readonly Collection s_cultureCollection = new Collection(); static StringManipulationHelper() { @@ -416,10 +416,12 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa for (int k = 0; k < lines.Length; k++) { - if (lines[k] == null || displayCells.Length(lines[k]) <= firstLineLen) + string currentLine = lines[k]; + + if (currentLine == null || displayCells.Length(currentLine) <= firstLineLen) { // we do not need to split further, just add - retVal.Add(lines[k]); + retVal.Add(currentLine); continue; } @@ -432,7 +434,7 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa int offset = 0; // offset into the line we are splitting - while (true) + while (offset < currentLine.Length) { // acquire the current active display line length (it can very from call to call) int currentDisplayLen = accumulator.ActiveLen; @@ -440,7 +442,7 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa // determine if the current tail would fit or not // for the remaining part of the string, determine its display cell count - int currentCellsToFit = displayCells.Length(lines[k], offset); + int currentCellsToFit = displayCells.Length(currentLine, offset); // determine if we fit into the line int excessCells = currentCellsToFit - currentDisplayLen; @@ -449,7 +451,7 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa { // we are not at the end of the string, select a sub string // that would fit in the remaining display length - int charactersToAdd = displayCells.GetHeadSplitLength(lines[k], offset, currentDisplayLen); + int charactersToAdd = displayCells.GetHeadSplitLength(currentLine, offset, currentDisplayLen); if (charactersToAdd <= 0) { @@ -463,7 +465,7 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa else { // of the given length, add it to the accumulator - accumulator.AddLine(lines[k].Substring(offset, charactersToAdd)); + accumulator.AddLine(currentLine.Substring(offset, charactersToAdd)); } // increase the offset by the # of characters added @@ -472,7 +474,7 @@ private static StringCollection GenerateLinesWithoutWordWrap(DisplayCells displa else { // we reached the last (partial) line, we add it all - accumulator.AddLine(lines[k].Substring(offset)); + accumulator.AddLine(currentLine.Substring(offset)); break; } } @@ -510,10 +512,10 @@ internal int ActiveLen } } - private StringCollection _retVal; + private readonly StringCollection _retVal; private bool _addedFirstLine; - private int _firstLineLen; - private int _followingLinesLen; + private readonly int _firstLineLen; + private readonly int _followingLinesLen; } private static StringCollection GenerateLinesWithWordWrap(DisplayCells displayCells, string val, int firstLineLen, int followingLinesLen) @@ -730,4 +732,3 @@ internal static string PadLeft(string val, int count) private static readonly char[] s_lineBreakChars = new char[] { '\n', '\r' }; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs index 504325f26d4..43cab48d003 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs @@ -25,14 +25,15 @@ namespace System.Management.Automation.Runspaces [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "FormatTable")] public class FormatTableLoadException : RuntimeException { - private Collection _errors; + private readonly Collection _errors; #region Constructors /// /// This is the default constructor. /// - public FormatTableLoadException() : base() + public FormatTableLoadException() + : base() { SetDefaultErrorRecord(); } @@ -43,7 +44,8 @@ public FormatTableLoadException() : base() /// /// A localized error message. /// - public FormatTableLoadException(string message) : base(message) + public FormatTableLoadException(string message) + : base(message) { SetDefaultErrorRecord(); } @@ -70,8 +72,8 @@ public FormatTableLoadException(string message, Exception innerException) /// /// The errors that occured /// - internal FormatTableLoadException(ConcurrentBag loadErrors) : - base(StringUtil.Format(FormatAndOutXmlLoadingStrings.FormatTableLoadErrors)) + internal FormatTableLoadException(ConcurrentBag loadErrors) + : base(StringUtil.Format(FormatAndOutXmlLoadingStrings.FormatTableLoadErrors)) { _errors = new Collection(loadErrors.ToArray()); SetDefaultErrorRecord(); @@ -160,7 +162,7 @@ public sealed class FormatTable { #region Private Data - private TypeInfoDataBaseManager _formatDBMgr; + private readonly TypeInfoDataBaseManager _formatDBMgr; #endregion diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/XmlLoaderBase.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/XmlLoaderBase.cs index 02d60731e43..a7e7df0a5d7 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/XmlLoaderBase.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/XmlLoaderBase.cs @@ -44,7 +44,7 @@ internal class TooManyErrorsException : TypeInfoDataBaseLoaderException /// internal class XmlLoaderLoggerEntry { - internal enum EntryType { Error, Trace }; + internal enum EntryType { Error, Trace } /// /// Type of information being logged. @@ -81,7 +81,7 @@ internal class XmlLoaderLogger : IDisposable #region tracer // PSS/end-user tracer [TraceSource("FormatFileLoading", "Loading format files")] - private static PSTraceSource s_formatFileLoadingtracer = PSTraceSource.GetTracer("FormatFileLoading", "Loading format files", false); + private static readonly PSTraceSource s_formatFileLoadingtracer = PSTraceSource.GetTracer("FormatFileLoading", "Loading format files", false); #endregion tracer /// @@ -100,7 +100,7 @@ internal void LogEntry(XmlLoaderLoggerEntry entry) WriteToTracer(entry); } - private void WriteToTracer(XmlLoaderLoggerEntry entry) + private static void WriteToTracer(XmlLoaderLoggerEntry entry) { if (entry.entryType == XmlLoaderLoggerEntry.EntryType.Error) { @@ -149,12 +149,12 @@ internal bool HasErrors /// /// If true, log entries to memory. /// - private bool _saveInMemory = true; + private readonly bool _saveInMemory = true; /// /// List of entries logged if saveInMemory is true. /// - private List _entries = new List(); + private readonly List _entries = new List(); /// /// True if we ever logged an error. @@ -170,7 +170,7 @@ internal abstract class XmlLoaderBase : IDisposable { #region tracer [TraceSource("XmlLoaderBase", "XmlLoaderBase")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("XmlLoaderBase", "XmlLoaderBase"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("XmlLoaderBase", "XmlLoaderBase"); #endregion tracer /// @@ -378,7 +378,7 @@ private bool MatchNodeNameHelper(XmlNode n, string s, bool allowAttributes) // we differ only in case: flag this as an ERROR for the time being // and accept the comparison - string fmtString = "XML tag differ in case only {0} {1}"; + const string fmtString = "XML tag differ in case only {0} {1}"; ReportTrace(string.Format(CultureInfo.InvariantCulture, fmtString, n.Name, s)); match = true; @@ -420,7 +420,7 @@ internal bool MatchAttributeName(XmlAttribute a, string s) // we differ only in case: flag this as an ERROR for the time being // and accept the comparison - string fmtString = "XML attribute differ in case only {0} {1}"; + const string fmtString = "XML attribute differ in case only {0} {1}"; ReportTrace(string.Format(CultureInfo.InvariantCulture, fmtString, a.Name, s)); return true; } @@ -690,7 +690,7 @@ protected void SetLoadingInfoIsProductCode(bool isProductCode) _loadingInfo.isProductCode = isProductCode; } - private DatabaseLoadingInfo _loadingInfo = new DatabaseLoadingInfo(); + private readonly DatabaseLoadingInfo _loadingInfo = new DatabaseLoadingInfo(); protected DatabaseLoadingInfo LoadingInfo { @@ -711,13 +711,13 @@ protected DatabaseLoadingInfo LoadingInfo internal bool VerifyStringResources { get; } = true; - private int _maxNumberOfErrors = 30; + private readonly int _maxNumberOfErrors = 30; private int _currentErrorCount = 0; - private bool _logStackActivity = false; + private readonly bool _logStackActivity = false; - private Stack _executionStack = new Stack(); + private readonly Stack _executionStack = new Stack(); private XmlLoaderLogger _logger = new XmlLoaderLogger(); } diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/commands.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/commands.cs index 1402fbbbc8a..acf540246d5 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/commands.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/commands.cs @@ -38,4 +38,3 @@ internal static bool Convert(string expansionString, out EnumerableExpansion exp } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData.cs index 64d59dbc83e..f126dddcadc 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData.cs @@ -102,6 +102,13 @@ internal sealed class DefaultSettingsSection { internal bool MultilineTables { + get + { + if (_multilineTables.HasValue) + return _multilineTables.Value; + return false; + } + set { if (!_multilineTables.HasValue) @@ -109,13 +116,6 @@ internal bool MultilineTables _multilineTables = value; } } - - get - { - if (_multilineTables.HasValue) - return _multilineTables.Value; - return false; - } } private bool? _multilineTables; @@ -132,6 +132,13 @@ internal sealed class FormatErrorPolicy /// internal bool ShowErrorsAsMessages { + get + { + if (_showErrorsAsMessages.HasValue) + return _showErrorsAsMessages.Value; + return false; + } + set { if (!_showErrorsAsMessages.HasValue) @@ -139,13 +146,6 @@ internal bool ShowErrorsAsMessages _showErrorsAsMessages = value; } } - - get - { - if (_showErrorsAsMessages.HasValue) - return _showErrorsAsMessages.Value; - return false; - } } private bool? _showErrorsAsMessages; @@ -156,6 +156,13 @@ internal bool ShowErrorsAsMessages /// internal bool ShowErrorsInFormattedOutput { + get + { + if (_showErrorsInFormattedOutput.HasValue) + return _showErrorsInFormattedOutput.Value; + return false; + } + set { if (!_showErrorsInFormattedOutput.HasValue) @@ -163,13 +170,6 @@ internal bool ShowErrorsInFormattedOutput _showErrorsInFormattedOutput = value; } } - - get - { - if (_showErrorsInFormattedOutput.HasValue) - return _showErrorsInFormattedOutput.Value; - return false; - } } private bool? _showErrorsInFormattedOutput; @@ -191,6 +191,13 @@ internal sealed class ShapeSelectionDirectives { internal int PropertyCountForTable { + get + { + if (_propertyCountForTable.HasValue) + return _propertyCountForTable.Value; + return 4; + } + set { if (!_propertyCountForTable.HasValue) @@ -198,13 +205,6 @@ internal int PropertyCountForTable _propertyCountForTable = value; } } - - get - { - if (_propertyCountForTable.HasValue) - return _propertyCountForTable.Value; - return 4; - } } private int? _propertyCountForTable; @@ -774,7 +774,7 @@ internal static PSControlGroupBy Get(GroupBy groupBy) return new PSControlGroupBy { Expression = new DisplayEntry(expressionToken), - Label = (groupBy.startGroup.labelTextToken != null) ? groupBy.startGroup.labelTextToken.text : null + Label = groupBy.startGroup.labelTextToken?.text }; } diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Table.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Table.cs index b9d1e897068..e509530538d 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Table.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Table.cs @@ -263,7 +263,7 @@ internal TableControl(TableControlBody tcb, ViewDefinition viewDefinition) : thi this.OutOfBand = viewDefinition.outOfBand; this.GroupBy = PSControlGroupBy.Get(viewDefinition.groupBy); - this.AutoSize = tcb.autosize.HasValue && tcb.autosize.Value; + this.AutoSize = tcb.autosize.GetValueOrDefault(); this.HideTableHeaders = tcb.header.hideHeader; TableControlRow row = new TableControlRow(tcb.defaultDefinition); diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs index 05e3e79923b..4f87998fd1e 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs @@ -130,7 +130,7 @@ internal WideControl(WideControlBody widecontrolbody, ViewDefinition viewDefinit OutOfBand = viewDefinition.outOfBand; GroupBy = PSControlGroupBy.Get(viewDefinition.groupBy); - AutoSize = widecontrolbody.autosize.HasValue && widecontrolbody.autosize.Value; + AutoSize = widecontrolbody.autosize.GetValueOrDefault(); Columns = (uint)widecontrolbody.columns; Entries.Add(new WideControlEntryItem(widecontrolbody.defaultEntryDefinition)); diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayResourceManagerCache.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayResourceManagerCache.cs index 52e1043cb2c..b5eb4d456e8 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayResourceManagerCache.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayResourceManagerCache.cs @@ -13,7 +13,7 @@ internal sealed class DisplayResourceManagerCache { internal enum LoadingResult { NoError, AssemblyNotFound, ResourceNotFound, StringNotFound } - internal enum AssemblyBindingStatus { NotFound, FoundInGac, FoundInPath }; + internal enum AssemblyBindingStatus { NotFound, FoundInGac, FoundInPath } internal string GetTextTokenString(TextToken tt) { @@ -142,7 +142,7 @@ private sealed class AssemblyLoadResult /// Helper class to resolve an assembly name to an assembly reference /// The class caches previous results for faster lookup. /// - private class AssemblyNameResolver + private sealed class AssemblyNameResolver { /// /// Resolve the assembly name against the set of loaded assemblies. @@ -176,7 +176,7 @@ internal Assembly ResolveAssemblyName(string assemblyName) return retVal; } - private Assembly ResolveAssemblyNameInLoadedAssemblies(string assemblyName, bool fullName) + private static Assembly ResolveAssemblyNameInLoadedAssemblies(string assemblyName, bool fullName) { Assembly result = null; @@ -216,11 +216,10 @@ private Assembly ResolveAssemblyNameInLoadedAssemblies(string assemblyName, bool return result; } - private Hashtable _assemblyReferences = new Hashtable(StringComparer.OrdinalIgnoreCase); + private readonly Hashtable _assemblyReferences = new Hashtable(StringComparer.OrdinalIgnoreCase); } - private AssemblyNameResolver _assemblyNameResolver = new AssemblyNameResolver(); - private Hashtable _resourceReferenceToAssemblyCache = new Hashtable(); + private readonly AssemblyNameResolver _assemblyNameResolver = new AssemblyNameResolver(); + private readonly Hashtable _resourceReferenceToAssemblyCache = new Hashtable(); } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataManager.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataManager.cs index 65dd6934682..c42bd21adc7 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataManager.cs @@ -33,7 +33,7 @@ internal sealed class TypeInfoDataBaseManager internal object updateDatabaseLock = new object(); // this is used to throw errors when updating a shared TypeTable. internal bool isShared; - private List _formatFileList; + private readonly List _formatFileList; internal bool DisableFormatTableUpdates { get; set; } @@ -57,7 +57,7 @@ internal TypeInfoDataBaseManager() /// /// Host passed to . Can be null if no interactive questions should be asked. /// - /// + /// /// /// 1. FormatFile is not rooted. /// @@ -96,7 +96,7 @@ internal TypeInfoDataBaseManager( this.isShared = isShared; // check to see if there are any errors loading the format files - if (errors.Count > 0) + if (!errors.IsEmpty) { throw new FormatTableLoadException(errors); } @@ -215,7 +215,7 @@ internal void AddFormatData(IEnumerable formatData, bool LoadFromFile(filesToLoad, expressionFactory, false, null, null, false, out logEntries); // check to see if there are any errors loading the format files - if (errors.Count > 0) + if (!errors.IsEmpty) { throw new FormatTableLoadException(errors); } @@ -559,4 +559,3 @@ private static void AddPostLoadIntrinsics(TypeInfoDataBase db) } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataQuery.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataQuery.cs index ec0c40736fb..60953d22c26 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataQuery.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataQuery.cs @@ -219,7 +219,7 @@ private int MatchTypeIndex(string typeName, PSObject currentObject, PSPropertyEx return BestMatchIndexUndefined; } - private bool MatchCondition(PSObject currentObject, PSPropertyExpression ex) + private static bool MatchCondition(PSObject currentObject, PSPropertyExpression ex) { if (ex == null) return true; @@ -230,10 +230,10 @@ private bool MatchCondition(PSObject currentObject, PSPropertyExpression ex) return retVal; } - private PSPropertyExpressionFactory _expressionFactory; - private TypeInfoDataBase _db; - private Collection _typeNameHierarchy; - private bool _useInheritance; + private readonly PSPropertyExpressionFactory _expressionFactory; + private readonly TypeInfoDataBase _db; + private readonly Collection _typeNameHierarchy; + private readonly bool _useInheritance; private int _bestMatchIndex = BestMatchIndexUndefined; private TypeMatchItem _bestMatchItem; @@ -602,9 +602,7 @@ internal static AppliesTo GetAllApplicableTypes(TypeInfoDataBase db, AppliesTo a else { // check if we have a type group reference - TypeGroupReference tgr = r as TypeGroupReference; - - if (tgr == null) + if (!(r is TypeGroupReference tgr)) continue; // find the type group definition the reference points to diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs index 79bcbd61dca..8c1c251f149 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs @@ -43,7 +43,7 @@ internal sealed partial class TypeInfoDataBaseLoader : XmlLoaderBase #region tracer [TraceSource("TypeInfoDataBaseLoader", "TypeInfoDataBaseLoader")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("TypeInfoDataBaseLoader", "TypeInfoDataBaseLoader"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("TypeInfoDataBaseLoader", "TypeInfoDataBaseLoader"); #endregion tracer /// @@ -586,7 +586,7 @@ private ControlBase LoadTableControlFromObjectModel(TableControl table, int view /// /// /// - private void LoadHeadersSectionFromObjectModel(TableControlBody tableBody, List headers) + private static void LoadHeadersSectionFromObjectModel(TableControlBody tableBody, List headers) { foreach (TableControlColumnHeader header in headers) { @@ -746,7 +746,7 @@ private ExpressionToken LoadExpressionFromObjectModel(DisplayEntry displayEntry, /// Load EntrySelectedBy (TypeName) into AppliesTo. /// /// - private AppliesTo LoadAppliesToSectionFromObjectModel(List selectedBy, List condition) + private static AppliesTo LoadAppliesToSectionFromObjectModel(List selectedBy, List condition) { AppliesTo appliesTo = new AppliesTo(); @@ -1122,9 +1122,9 @@ private FormatToken LoadFormatTokenFromObjectModel(CustomItemBase item, int view { frameInfoDefinition = { - leftIndentation = (int) frame.LeftIndent, - rightIndentation = (int) frame.RightIndent, - firstLine = frame.FirstLineHanging != 0 ? -(int) frame.FirstLineHanging : (int) frame.FirstLineIndent + leftIndentation = (int)frame.LeftIndent, + rightIndentation = (int)frame.RightIndent, + firstLine = frame.FirstLineHanging != 0 ? -(int)frame.FirstLineHanging : (int)frame.FirstLineIndent } }; @@ -2035,7 +2035,7 @@ internal ExpressionToken GenerateExpressionToken() return _token; } - private TypeInfoDataBaseLoader _loader; + private readonly TypeInfoDataBaseLoader _loader; private ExpressionToken _token; private bool _fatalError = false; } @@ -2175,7 +2175,7 @@ internal bool ProcessExpressionDirectives(XmlNode containerNode, List u private TextToken _textToken; private ExpressionToken _expression; - private TypeInfoDataBaseLoader _loader; + private readonly TypeInfoDataBaseLoader _loader; } #endregion @@ -2228,10 +2228,9 @@ internal ControlBase Control } private ControlBase _control; - private TypeInfoDataBaseLoader _loader; + private readonly TypeInfoDataBaseLoader _loader; } #endregion } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader_Views.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader_Views.cs index 8b960e32297..505c766b9d1 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader_Views.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader_Views.cs @@ -170,7 +170,7 @@ private bool LoadMainControlDependentData(List unprocessedNodes, ViewDe return false; } - if (!(view.mainControl is ComplexControlBody) && !(view.mainControl is ListControlBody)) + if (view.mainControl is not ComplexControlBody && view.mainControl is not ListControlBody) { // Error at XPath {0} in file {1}: Out Of Band views can only have CustomControl or ListControl. ReportError(StringUtil.Format(FormatAndOutXmlLoadingStrings.InvalidControlForOutOfBandView, ComputeCurrentXPath(), FilePath)); diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatGroupManager.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatGroupManager.cs index c3d733a7f2d..a4e2a74f622 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatGroupManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatGroupManager.cs @@ -121,4 +121,3 @@ private static bool IsEqual(object first, object second) private object _currentGroupingKeyPropertyValue = AutomationNull.Value; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatMsgCtxManager.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatMsgCtxManager.cs index 0aaf16a9a28..3eabcc975a0 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatMsgCtxManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatMsgCtxManager.cs @@ -19,10 +19,15 @@ internal class FormatMessagesContextManager { // callbacks declarations internal delegate OutputContext FormatContextCreationCallback(OutputContext parentContext, FormatInfoData formatData); + internal delegate void FormatStartCallback(OutputContext c); + internal delegate void FormatEndCallback(FormatEndData fe, OutputContext c); + internal delegate void GroupStartCallback(OutputContext c); + internal delegate void GroupEndCallback(GroupEndData fe, OutputContext c); + internal delegate void PayloadCallback(FormatEntryData formatEntryData, OutputContext c); // callback instances @@ -135,6 +140,6 @@ internal OutputContext ActiveOutputContext /// /// Internal stack to manage context. /// - private Stack _stack = new Stack(); + private readonly Stack _stack = new Stack(); } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator.cs index cf6a4d2eb88..f29033e3c8d 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator.cs @@ -307,7 +307,7 @@ internal bool IsObjectApplicable(Collection typeNames) // we were unable to find a best match so far..try // to get rid of Deserialization prefix and see if a // match can be found. - if (false == result) + if (!result) { Collection typesWithoutPrefix = Deserializer.MaskDeserializationPrefix(typeNames); if (typesWithoutPrefix != null) diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Complex.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Complex.cs index c9cd80bbee8..c1645b09ad5 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Complex.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Complex.cs @@ -383,13 +383,13 @@ private bool EvaluateDisplayCondition(PSObject so, ExpressionToken conditionToke return retVal; } - private TypeInfoDataBase _db; - private DatabaseLoadingInfo _loadingInfo; - private PSPropertyExpressionFactory _expressionFactory; - private List _controlDefinitionList; - private FormatErrorManager _errorManager; - private TerminatingErrorContext _errorContext; - private int _enumerationLimit; + private readonly TypeInfoDataBase _db; + private readonly DatabaseLoadingInfo _loadingInfo; + private readonly PSPropertyExpressionFactory _expressionFactory; + private readonly List _controlDefinitionList; + private readonly FormatErrorManager _errorManager; + private readonly TerminatingErrorContext _errorContext; + private readonly int _enumerationLimit; } internal class TraversalInfo @@ -412,8 +412,8 @@ internal TraversalInfo NextLevel } } - private int _level; - private int _maxDepth; + private readonly int _level; + private readonly int _maxDepth; } /// @@ -771,13 +771,12 @@ private List AddIndentationLevel(List formatValueList) /// /// Indentation added to each level in the recursion. /// - private int _indentationStep = 2; + private readonly int _indentationStep = 2; - private FormatErrorManager _errorManager; + private readonly FormatErrorManager _errorManager; - private PSPropertyExpressionFactory _expressionFactory; + private readonly PSPropertyExpressionFactory _expressionFactory; - private int _enumerationLimit; + private readonly int _enumerationLimit; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_List.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_List.cs index 2ded68cd510..1cee3067011 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_List.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_List.cs @@ -237,4 +237,3 @@ private void SetUpActiveProperties(PSObject so) } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs index ab4912c8838..bfd3291dd46 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Table.cs @@ -137,7 +137,7 @@ private void FilterActiveAssociationList() // make sure we do not have too many properties // NOTE: this is an arbitrary number, chosen to be a sensitive default - int nMax = 10; + const int nMax = 10; if (activeAssociationList.Count > nMax) { @@ -491,4 +491,3 @@ private TableRowEntry GenerateTableRowEntryFromFromProperties(PSObject so, int e } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Wide.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Wide.cs index 9d378eaf9cc..26c0af670c7 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Wide.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Wide.cs @@ -195,4 +195,3 @@ private void SetUpActiveProperty(PSObject so) } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatViewManager.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatViewManager.cs index aca38f8994b..0737e43476e 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatViewManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatViewManager.cs @@ -70,7 +70,7 @@ internal sealed class FormatViewManager { #region tracer [TraceSource("FormatViewBinding", "Format view binding")] - private static PSTraceSource s_formatViewBindingTracer = PSTraceSource.GetTracer("FormatViewBinding", "Format view binding", false); + private static readonly PSTraceSource s_formatViewBindingTracer = PSTraceSource.GetTracer("FormatViewBinding", "Format view binding", false); #endregion tracer private static string PSObjectTypeName(PSObject so) @@ -234,7 +234,7 @@ private static void ProcessUnknownViewName(TerminatingErrorContext errorContext, string msg = null; bool foundValidViews = false; string formatTypeName = null; - string separator = ", "; + const string separator = ", "; StringBuilder validViewFormats = new StringBuilder(); if (so != null && so.BaseObject != null && @@ -336,7 +336,7 @@ private static void ProcessUnknownViewName(TerminatingErrorContext errorContext, { // unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.UnknownViewNameError, viewName)); unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.UnknownViewNameErrorSuffix, viewName, formatTypeName)); - unKnowViewFormatStringBuilder.Append(validViewFormats.ToString()); + unKnowViewFormatStringBuilder.Append(validViewFormats); } else { @@ -677,12 +677,11 @@ private static ErrorRecord GenerateErrorRecord(FormattingError error) return errorRecord; } - private FormatErrorPolicy _formatErrorPolicy; + private readonly FormatErrorPolicy _formatErrorPolicy; /// /// Current list of failed PSPropertyExpression evaluations. /// - private List _formattingErrorList = new List(); + private readonly List _formattingErrorList = new List(); } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormatXMLWriter.cs b/src/System.Management.Automation/FormatAndOutput/common/FormatXMLWriter.cs index bb2c8ff93e7..c18297c620e 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormatXMLWriter.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormatXMLWriter.cs @@ -13,7 +13,7 @@ namespace Microsoft.PowerShell.Commands /// /// Helper class for writing formatting directives to XML. /// - internal class FormatXmlWriter + internal sealed class FormatXmlWriter { private XmlWriter _writer; private bool _exportScriptBlock; diff --git a/src/System.Management.Automation/FormatAndOutput/common/FormattingObjectsDeserializer.cs b/src/System.Management.Automation/FormatAndOutput/common/FormattingObjectsDeserializer.cs index 8609d35c9a9..962cf6f5ff1 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/FormattingObjectsDeserializer.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/FormattingObjectsDeserializer.cs @@ -55,9 +55,7 @@ fid is GroupEndData || return false; } - string classId = GetProperty(so, FormatInfoData.classidProperty) as string; - - if (classId == null) + if (!(GetProperty(so, FormatInfoData.classidProperty) is string classId)) { // it's not one of the objects derived from FormatInfoData return false; @@ -113,9 +111,7 @@ fid is GroupEndData || return so; } - string classId = GetProperty(so, FormatInfoData.classidProperty) as string; - - if (classId == null) + if (!(GetProperty(so, FormatInfoData.classidProperty) is string classId)) { // it's not one of the objects derived from FormatInfoData, // just return it as is @@ -294,7 +290,7 @@ internal int DeserializeIntMemberVariable(PSObject so, string property) internal bool DeserializeBoolMemberVariable(PSObject so, string property, bool cannotBeNull = true) { var val = DeserializeMemberVariable(so, property, typeof(bool), cannotBeNull); - return (val == null) ? false : (bool)val; + return val != null && (bool)val; } internal WriteStreamType DeserializeWriteStreamTypeMemberVariable(PSObject so) @@ -359,31 +355,31 @@ static FormatInfoDataClassFactory() { s_constructors = new Dictionary> { - {FormatStartData.CLSID, () => new FormatStartData()}, - {FormatEndData.CLSID, () => new FormatEndData()}, - {GroupStartData.CLSID, () => new GroupStartData()}, - {GroupEndData.CLSID, () => new GroupEndData()}, - {FormatEntryData.CLSID, () => new FormatEntryData()}, - {WideViewHeaderInfo.CLSID, () => new WideViewHeaderInfo()}, - {TableHeaderInfo.CLSID, () => new TableHeaderInfo()}, - {TableColumnInfo.CLSID, () => new TableColumnInfo()}, - {ListViewHeaderInfo.CLSID, () => new ListViewHeaderInfo()}, - {ListViewEntry.CLSID, () => new ListViewEntry()}, - {ListViewField.CLSID, () => new ListViewField()}, - {TableRowEntry.CLSID, () => new TableRowEntry()}, - {WideViewEntry.CLSID, () => new WideViewEntry()}, - {ComplexViewHeaderInfo.CLSID, () => new ComplexViewHeaderInfo()}, - {ComplexViewEntry.CLSID, () => new ComplexViewEntry()}, - {GroupingEntry.CLSID, () => new GroupingEntry()}, - {PageHeaderEntry.CLSID, () => new PageHeaderEntry()}, - {PageFooterEntry.CLSID, () => new PageFooterEntry()}, - {AutosizeInfo.CLSID, () => new AutosizeInfo()}, - {FormatNewLine.CLSID, () => new FormatNewLine()}, - {FrameInfo.CLSID, () => new FrameInfo()}, - {FormatTextField.CLSID, () => new FormatTextField()}, - {FormatPropertyField.CLSID, () => new FormatPropertyField()}, - {FormatEntry.CLSID, () => new FormatEntry()}, - {RawTextFormatEntry.CLSID, () => new RawTextFormatEntry()} + {FormatStartData.CLSID, static () => new FormatStartData()}, + {FormatEndData.CLSID, static () => new FormatEndData()}, + {GroupStartData.CLSID, static () => new GroupStartData()}, + {GroupEndData.CLSID, static () => new GroupEndData()}, + {FormatEntryData.CLSID, static () => new FormatEntryData()}, + {WideViewHeaderInfo.CLSID, static () => new WideViewHeaderInfo()}, + {TableHeaderInfo.CLSID, static () => new TableHeaderInfo()}, + {TableColumnInfo.CLSID, static () => new TableColumnInfo()}, + {ListViewHeaderInfo.CLSID, static () => new ListViewHeaderInfo()}, + {ListViewEntry.CLSID, static () => new ListViewEntry()}, + {ListViewField.CLSID, static () => new ListViewField()}, + {TableRowEntry.CLSID, static () => new TableRowEntry()}, + {WideViewEntry.CLSID, static () => new WideViewEntry()}, + {ComplexViewHeaderInfo.CLSID, static () => new ComplexViewHeaderInfo()}, + {ComplexViewEntry.CLSID, static () => new ComplexViewEntry()}, + {GroupingEntry.CLSID, static () => new GroupingEntry()}, + {PageHeaderEntry.CLSID, static () => new PageHeaderEntry()}, + {PageFooterEntry.CLSID, static () => new PageFooterEntry()}, + {AutosizeInfo.CLSID, static () => new AutosizeInfo()}, + {FormatNewLine.CLSID, static () => new FormatNewLine()}, + {FrameInfo.CLSID, static () => new FrameInfo()}, + {FormatTextField.CLSID, static () => new FormatTextField()}, + {FormatPropertyField.CLSID, static () => new FormatPropertyField()}, + {FormatEntry.CLSID, static () => new FormatEntry()}, + {RawTextFormatEntry.CLSID, static () => new RawTextFormatEntry()} }; } @@ -706,4 +702,3 @@ internal override void Deserialize(PSObject so, FormatObjectDeserializer deseria } #endregion } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/ILineOutput.cs b/src/System.Management.Automation/FormatAndOutput/common/ILineOutput.cs index 09432253e33..8c672b62063 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/ILineOutput.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/ILineOutput.cs @@ -4,6 +4,8 @@ using System.Globalization; using System.IO; using System.Management.Automation; +using System.Management.Automation.Host; +using System.Management.Automation.Internal; using System.Text; // interfaces for host interaction @@ -258,17 +260,17 @@ internal class WriteLineHelper /// Instance of the delegate previously defined /// for line that has EXACTLY this.ncols characters. /// - private WriteCallback _writeCall = null; + private readonly WriteCallback _writeCall = null; /// /// Instance of the delegate previously defined /// for generic line, less that this.ncols characters. /// - private WriteCallback _writeLineCall = null; + private readonly WriteCallback _writeLineCall = null; #endregion - private bool _lineWrap; + private readonly bool _lineWrap; /// /// Construct an instance, given the two callbacks @@ -367,7 +369,7 @@ private void WriteLineInternal(string val, int cols) } } - private DisplayCells _displayCells; + private readonly DisplayCells _displayCells; } /// @@ -411,6 +413,9 @@ internal override int RowNumber internal override void WriteLine(string s) { CheckStopProcessing(); + + s = PSHostUserInterface.GetOutputString(s, isHost: false); + if (_suppressNewline) { _writer.Write(s); @@ -447,11 +452,11 @@ internal TextWriterLineOutput(TextWriter writer, int columns, bool suppressNewli _suppressNewline = suppressNewline; } - private int _columns = 0; + private readonly int _columns = 0; - private TextWriter _writer = null; + private readonly TextWriter _writer = null; - private bool _suppressNewline = false; + private readonly bool _suppressNewline = false; } /// @@ -462,7 +467,7 @@ internal class StreamingTextWriter : TextWriter { #region tracer [TraceSource("StreamingTextWriter", "StreamingTextWriter")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("StreamingTextWriter", "StreamingTextWriter"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("StreamingTextWriter", "StreamingTextWriter"); #endregion tracer /// @@ -499,6 +504,6 @@ public override void WriteLine(string s) /// /// Instance of the delegate previously defined. /// - private WriteLineCallback _writeCall = null; + private readonly WriteLineCallback _writeCall = null; } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/ListWriter.cs b/src/System.Management.Automation/FormatAndOutput/common/ListWriter.cs index 91a7b8698a6..b5c97c3d85d 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/ListWriter.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/ListWriter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Specialized; using System.Diagnostics; +using System.Management.Automation; using System.Management.Automation.Internal; namespace Microsoft.PowerShell.Commands.Internal.Format @@ -59,6 +60,10 @@ internal void Initialize(string[] propertyNames, int screenColumnWidth, DisplayC // check if we have to truncate the labels int maxAllowableLabelLength = screenColumnWidth - Separator.Length - MinFieldWidth; + if (InternalTestHooks.ForceFormatListFixedLabelWidth) + { + maxAllowableLabelLength = 10; + } // find out the max display length (cell count) of the property names _propertyLabelsDisplayLength = 0; // reset max @@ -217,11 +222,11 @@ private void WriteSingleLineHelper(string prependString, string line, LineOutput { if (k == 0) { - lo.WriteLine(prependString + sc[k]); + lo.WriteLine(PSStyle.Instance.Formatting.FormatAccent + prependString + PSStyle.Instance.Reset + sc[k]); } else { - lo.WriteLine(padding + sc[k]); + lo.WriteLine(padding + PSStyle.Instance.Formatting.FormatAccent + PSStyle.Instance.Reset + sc[k]); } } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/OutputManager.cs b/src/System.Management.Automation/FormatAndOutput/common/OutputManager.cs index b07731c3e04..41ea611f198 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/OutputManager.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/OutputManager.cs @@ -135,7 +135,7 @@ protected override void InternalDispose() /// /// Lock object. /// - private object _syncRoot = new object(); + private readonly object _syncRoot = new object(); } /// @@ -185,7 +185,7 @@ public void Dispose() /// /// Ordered list of ETS type names this object is handling. /// - private StringCollection _applicableTypes = new StringCollection(); + private readonly StringCollection _applicableTypes = new StringCollection(); } /// @@ -322,7 +322,7 @@ private CommandEntry GetActiveCommandEntry(PSObject so) /// /// List of command entries, each with a set of applicable types. /// - private List _commandEntryList = new List(); + private readonly List _commandEntryList = new List(); /// /// Default command entry to be executed when all type matches fail. diff --git a/src/System.Management.Automation/FormatAndOutput/common/OutputQueue.cs b/src/System.Management.Automation/FormatAndOutput/common/OutputQueue.cs index 1545f456e12..1909b03939c 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/OutputQueue.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/OutputQueue.cs @@ -164,28 +164,28 @@ internal PacketInfoData Dequeue() /// /// Queue to store the currently cached objects. /// - private Queue _queue = new Queue(); + private readonly Queue _queue = new Queue(); /// /// Number of objects to compute the best fit. /// Zero: all the objects /// a positive number N: use the first N. /// - private int _objectCount = 0; + private readonly int _objectCount = 0; /// /// Maximum amount of time for record processing to compute the best fit. /// MaxValue: all the objects. /// A positive timespan: use all objects that have been processed within the timeframe. /// - private TimeSpan _groupingDuration = TimeSpan.MinValue; + private readonly TimeSpan _groupingDuration = TimeSpan.MinValue; private Stopwatch _groupingTimer = null; /// /// Notification callback to be called when we have accumulated enough /// data to compute a hint. /// - private FormattedObjectsCache.ProcessCachedGroupNotification _notificationCallBack = null; + private readonly FormattedObjectsCache.ProcessCachedGroupNotification _notificationCallBack = null; /// /// Reference kept to be used during notification. @@ -327,7 +327,7 @@ internal List Drain() /// /// Front end queue (if present, cache ALL, if not, bypass) /// - private Queue _frontEndQueue; + private readonly Queue _frontEndQueue; /// /// Back end grouping queue. @@ -335,4 +335,3 @@ internal List Drain() private OutputGroupQueue _groupQueue = null; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs new file mode 100644 index 00000000000..52ca35dff4b --- /dev/null +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -0,0 +1,712 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections; +using System.Collections.Generic; +using System.Management.Automation.Internal; + +namespace System.Management.Automation +{ + #region OutputRendering + /// + /// Defines the options for output rendering. + /// + public enum OutputRendering + { + /// Render ANSI only to host. + Host = 0, + + /// Render as plaintext. + PlainText = 1, + + /// Render as ANSI. + Ansi = 2, + } + #endregion OutputRendering + + /// + /// Defines the options for views of progress rendering. + /// + public enum ProgressView + { + /// Render progress using minimal space. + Minimal = 0, + + /// Classic rendering of progress. + Classic = 1, + } + + #region PSStyle + /// + /// Contains configuration for how PowerShell renders text. + /// + public sealed class PSStyle + { + /// + /// Contains foreground colors. + /// + public sealed class ForegroundColor + { + /// + /// Gets the color black. + /// + public string Black { get; } = "\x1b[30m"; + + /// + /// Gets the color red. + /// + public string Red { get; } = "\x1b[31m"; + + /// + /// Gets the color green. + /// + public string Green { get; } = "\x1b[32m"; + + /// + /// Gets the color yellow. + /// + public string Yellow { get; } = "\x1b[33m"; + + /// + /// Gets the color blue. + /// + public string Blue { get; } = "\x1b[34m"; + + /// + /// Gets the color magenta. + /// + public string Magenta { get; } = "\x1b[35m"; + + /// + /// Gets the color cyan. + /// + public string Cyan { get; } = "\x1b[36m"; + + /// + /// Gets the color white. + /// + public string White { get; } = "\x1b[37m"; + + /// + /// Gets the color bright black. + /// + public string BrightBlack { get; } = "\x1b[90m"; + + /// + /// Gets the color bright red. + /// + public string BrightRed { get; } = "\x1b[91m"; + + /// + /// Gets the color bright green. + /// + public string BrightGreen { get; } = "\x1b[92m"; + + /// + /// Gets the color bright yellow. + /// + public string BrightYellow { get; } = "\x1b[93m"; + + /// + /// Gets the color bright blue. + /// + public string BrightBlue { get; } = "\x1b[94m"; + + /// + /// Gets the color bright magenta. + /// + public string BrightMagenta { get; } = "\x1b[95m"; + + /// + /// Gets the color bright cyan. + /// + public string BrightCyan { get; } = "\x1b[96m"; + + /// + /// Gets the color bright white. + /// + public string BrightWhite { get; } = "\x1b[97m"; + + /// + /// Set as RGB (Red, Green, Blue). + /// + /// Byte value representing red. + /// Byte value representing green. + /// Byte value representing blue. + /// String representing ANSI code for RGB value. + public string FromRgb(byte red, byte green, byte blue) + { + return $"\x1b[38;2;{red};{green};{blue}m"; + } + + /// + /// The color set as RGB as a single number. + /// + /// RGB value specified as an integer. + /// String representing ANSI code for RGB value. + public string FromRgb(int rgb) + { + byte red, green, blue; + blue = (byte)(rgb & 0xFF); + rgb >>= 8; + green = (byte)(rgb & 0xFF); + rgb >>= 8; + red = (byte)(rgb & 0xFF); + + return FromRgb(red, green, blue); + } + } + + /// + /// Contains background colors. + /// + public sealed class BackgroundColor + { + /// + /// Gets the color black. + /// + public string Black { get; } = "\x1b[40m"; + + /// + /// Gets the color red. + /// + public string Red { get; } = "\x1b[41m"; + + /// + /// Gets the color green. + /// + public string Green { get; } = "\x1b[42m"; + + /// + /// Gets the color yellow. + /// + public string Yellow { get; } = "\x1b[43m"; + + /// + /// Gets the color blue. + /// + public string Blue { get; } = "\x1b[44m"; + + /// + /// Gets the color magenta. + /// + public string Magenta { get; } = "\x1b[45m"; + + /// + /// Gets the color cyan. + /// + public string Cyan { get; } = "\x1b[46m"; + + /// + /// Gets the color white. + /// + public string White { get; } = "\x1b[47m"; + + /// + /// Gets the color bright black. + /// + public string BrightBlack { get; } = "\x1b[100m"; + + /// + /// Gets the color bright red. + /// + public string BrightRed { get; } = "\x1b[101m"; + + /// + /// Gets the color bright green. + /// + public string BrightGreen { get; } = "\x1b[102m"; + + /// + /// Gets the color bright yellow. + /// + public string BrightYellow { get; } = "\x1b[103m"; + + /// + /// Gets the color bright blue. + /// + public string BrightBlue { get; } = "\x1b[104m"; + + /// + /// Gets the color bright magenta. + /// + public string BrightMagenta { get; } = "\x1b[105m"; + + /// + /// Gets the color bright cyan. + /// + public string BrightCyan { get; } = "\x1b[106m"; + + /// + /// Gets the color bright white. + /// + public string BrightWhite { get; } = "\x1b[107m"; + + /// + /// The color set as RGB (Red, Green, Blue). + /// + /// Byte value representing red. + /// Byte value representing green. + /// Byte value representing blue. + /// String representing ANSI code for RGB value. + public string FromRgb(byte red, byte green, byte blue) + { + return $"\x1b[48;2;{red};{green};{blue}m"; + } + + /// + /// The color set as RGB as a single number. + /// + /// RGB value specified as an integer. + /// String representing ANSI code for RGB value. + public string FromRgb(int rgb) + { + byte red, green, blue; + blue = (byte)(rgb & 0xFF); + rgb >>= 8; + green = (byte)(rgb & 0xFF); + rgb >>= 8; + red = (byte)(rgb & 0xFF); + + return FromRgb(red, green, blue); + } + } + + /// + /// Contains configuration for the progress bar visualization. + /// + public sealed class ProgressConfiguration + { + /// + /// Gets or sets the style for progress bar. + /// + public string Style + { + get => _style; + set => _style = ValidateNoContent(value); + } + + private string _style = "\x1b[33;1m"; + + /// + /// Gets or sets the max width of the progress bar. + /// + public int MaxWidth + { + get => _maxWidth; + set + { + // Width less than 18 does not render correctly due to the different parts of the progress bar. + if (value < 18) + { + throw new ArgumentOutOfRangeException(nameof(MaxWidth), PSStyleStrings.ProgressWidthTooSmall); + } + + _maxWidth = value; + } + } + + private int _maxWidth = 120; + + /// + /// Gets or sets the view for progress bar. + /// + public ProgressView View { get; set; } = ProgressView.Minimal; + + /// + /// Gets or sets a value indicating whether to use Operating System Command (OSC) control sequences 'ESC ]9;4;' to show indicator in terminal. + /// + public bool UseOSCIndicator { get; set; } = false; + } + + /// + /// Contains formatting styles for steams and objects. + /// + public sealed class FormattingData + { + /// + /// Gets or sets the accent style for formatting. + /// + public string FormatAccent + { + get => _formatAccent; + set => _formatAccent = ValidateNoContent(value); + } + + private string _formatAccent = "\x1b[32;1m"; + + /// + /// Gets or sets the style for table headers. + /// + public string TableHeader + { + get => _tableHeader; + set => _tableHeader = ValidateNoContent(value); + } + + private string _tableHeader = "\x1b[32;1m"; + + /// + /// Gets or sets the accent style for errors. + /// + public string ErrorAccent + { + get => _errorAccent; + set => _errorAccent = ValidateNoContent(value); + } + + private string _errorAccent = "\x1b[36;1m"; + + /// + /// Gets or sets the style for error messages. + /// + public string Error + { + get => _error; + set => _error = ValidateNoContent(value); + } + + private string _error = "\x1b[31;1m"; + + /// + /// Gets or sets the style for warning messages. + /// + public string Warning + { + get => _warning; + set => _warning = ValidateNoContent(value); + } + + private string _warning = "\x1b[33;1m"; + + /// + /// Gets or sets the style for verbose messages. + /// + public string Verbose + { + get => _verbose; + set => _verbose = ValidateNoContent(value); + } + + private string _verbose = "\x1b[33;1m"; + + /// + /// Gets or sets the style for debug messages. + /// + public string Debug + { + get => _debug; + set => _debug = ValidateNoContent(value); + } + + private string _debug = "\x1b[33;1m"; + } + + /// + /// Contains formatting styles for FileInfo objects. + /// + public sealed class FileInfoFormatting + { + /// + /// Gets or sets the style for directories. + /// + public string Directory + { + get => _directory; + set => _directory = ValidateNoContent(value); + } + + private string _directory = "\x1b[44;1m"; + + /// + /// Gets or sets the style for symbolic links. + /// + public string SymbolicLink + { + get => _symbolicLink; + set => _symbolicLink = ValidateNoContent(value); + } + + private string _symbolicLink = "\x1b[36;1m"; + + /// + /// Gets or sets the style for executables. + /// + public string Executable + { + get => _executable; + set => _executable = ValidateNoContent(value); + } + + private string _executable = "\x1b[32;1m"; + + /// + /// Custom dictionary handling validation of extension and content. + /// + public sealed class FileExtensionDictionary + { + private static string ValidateExtension(string extension) + { + if (!extension.StartsWith('.')) + { + throw new ArgumentException(PSStyleStrings.ExtensionNotStartingWithPeriod); + } + + return extension; + } + + private readonly Dictionary _extensionDictionary = new(StringComparer.OrdinalIgnoreCase); + + /// + /// Add new extension and decoration to dictionary. + /// + /// Extension to add. + /// ANSI string value to add. + public void Add(string extension, string decoration) + { + _extensionDictionary.Add(ValidateExtension(extension), ValidateNoContent(decoration)); + } + + /// + /// Remove an extension from dictionary. + /// + /// Extension to remove. + public void Remove(string extension) + { + _extensionDictionary.Remove(ValidateExtension(extension)); + } + + /// + /// Clear the dictionary. + /// + public void Clear() + { + _extensionDictionary.Clear(); + } + + /// + /// Gets or sets the decoration by specified extension. + /// + /// Extension to get decoration for. + /// The decoration for specified extension. + public string this[string extension] + { + get + { + return _extensionDictionary[ValidateExtension(extension)]; + } + + set + { + _extensionDictionary[ValidateExtension(extension)] = ValidateNoContent(value); + } + } + + /// + /// Gets whether the dictionary contains the specified extension. + /// + /// Extension to check for. + /// True if the dictionary contains the specified extension, otherwise false. + public bool ContainsKey(string extension) + { + if (string.IsNullOrEmpty(extension)) + { + return false; + } + + return _extensionDictionary.ContainsKey(ValidateExtension(extension)); + } + + /// + /// Gets the extensions for the dictionary. + /// + /// The extensions for the dictionary. + public IEnumerable Keys + { + get + { + return _extensionDictionary.Keys; + } + } + } + + /// + /// Gets the style for archive. + /// + public FileExtensionDictionary Extension { get; } + + /// + /// Initializes a new instance of the class. + /// + public FileInfoFormatting() + { + Extension = new FileExtensionDictionary(); + + // archives + Extension.Add(".zip", "\x1b[31;1m"); + Extension.Add(".tgz", "\x1b[31;1m"); + Extension.Add(".gz", "\x1b[31;1m"); + Extension.Add(".tar", "\x1b[31;1m"); + Extension.Add(".nupkg", "\x1b[31;1m"); + Extension.Add(".cab", "\x1b[31;1m"); + Extension.Add(".7z", "\x1b[31;1m"); + + // powershell + Extension.Add(".ps1", "\x1b[33;1m"); + Extension.Add(".psd1", "\x1b[33;1m"); + Extension.Add(".psm1", "\x1b[33;1m"); + Extension.Add(".ps1xml", "\x1b[33;1m"); + } + } + + /// + /// Gets or sets the rendering mode for output. + /// + public OutputRendering OutputRendering { get; set; } = OutputRendering.Host; + + /// + /// Gets value to turn off all attributes. + /// + public string Reset { get; } = "\x1b[0m"; + + /// + /// Gets value to turn off blink. + /// + public string BlinkOff { get; } = "\x1b[25m"; + + /// + /// Gets value to turn on blink. + /// + public string Blink { get; } = "\x1b[5m"; + + /// + /// Gets value to turn off bold. + /// + public string BoldOff { get; } = "\x1b[22m"; + + /// + /// Gets value to turn on blink. + /// + public string Bold { get; } = "\x1b[1m"; + + /// + /// Gets value to turn on hidden. + /// + public string Hidden { get; } = "\x1b[8m"; + + /// + /// Gets value to turn off hidden. + /// + public string HiddenOff { get; } = "\x1b[28m"; + + /// + /// Gets value to turn on reverse. + /// + public string Reverse { get; } = "\x1b[7m"; + + /// + /// Gets value to turn off reverse. + /// + public string ReverseOff { get; } = "\x1b[27m"; + + /// + /// Gets value to turn off standout. + /// + public string ItalicOff { get; } = "\x1b[23m"; + + /// + /// Gets value to turn on standout. + /// + public string Italic { get; } = "\x1b[3m"; + + /// + /// Gets value to turn off underlined. + /// + public string UnderlineOff { get; } = "\x1b[24m"; + + /// + /// Gets value to turn on underlined. + /// + public string Underline { get; } = "\x1b[4m"; + + /// + /// Gets value to turn off strikethrough. + /// + public string StrikethroughOff { get; } = "\x1b[29m"; + + /// + /// Gets value to turn on strikethrough. + /// + public string Strikethrough { get; } = "\x1b[9m"; + + /// + /// Gets ANSI representation of a hyperlink. + /// + /// Text describing the link. + /// A valid hyperlink. + /// String representing ANSI code for the hyperlink. + public string FormatHyperlink(string text, Uri link) + { + return $"\x1b]8;;{link}\x1b\\{text}\x1b]8;;\x1b\\"; + } + + /// + /// Gets the formatting rendering settings. + /// + public FormattingData Formatting { get; } + + /// + /// Gets the configuration for progress rendering. + /// + public ProgressConfiguration Progress { get; } + + /// + /// Gets foreground colors. + /// + public ForegroundColor Foreground { get; } + + /// + /// Gets background colors. + /// + public BackgroundColor Background { get; } + + /// + /// Gets FileInfo colors. + /// + public FileInfoFormatting FileInfo { get; } + + private static readonly PSStyle s_psstyle = new PSStyle(); + + private PSStyle() + { + Formatting = new FormattingData(); + Progress = new ProgressConfiguration(); + Foreground = new ForegroundColor(); + Background = new BackgroundColor(); + FileInfo = new FileInfoFormatting(); + } + + private static string ValidateNoContent(string text) + { + var decorartedString = new StringDecorated(text); + if (decorartedString.ContentLength > 0) + { + throw new ArgumentException(string.Format(PSStyleStrings.TextContainsContent, decorartedString.ToString(OutputRendering.PlainText))); + } + + return text; + } + + /// + /// Gets singleton instance. + /// + public static PSStyle Instance + { + get + { + return s_psstyle; + } + } + } + #endregion PSStyle +} diff --git a/src/System.Management.Automation/FormatAndOutput/common/StringDecorated.cs b/src/System.Management.Automation/FormatAndOutput/common/StringDecorated.cs new file mode 100644 index 00000000000..03a360ff5c1 --- /dev/null +++ b/src/System.Management.Automation/FormatAndOutput/common/StringDecorated.cs @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Text.RegularExpressions; + +namespace System.Management.Automation.Internal +{ + /// + /// Extensions to String type to calculate and render decorated content. + /// + public class StringDecorated + { + private readonly bool _isDecorated; + private readonly string _text; + private string? _plaintextcontent; + + private string PlainText + { + get + { + if (_plaintextcontent == null) + { + _plaintextcontent = ValueStringDecorated.AnsiRegex.Replace(_text, string.Empty); + } + + return _plaintextcontent; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The input string. + public StringDecorated(string text) + { + _text = text; + _isDecorated = text.Contains(ValueStringDecorated.ESC); + } + + /// + /// Gets a value indicating whether the string contains decoration. + /// + /// Boolean if the string contains decoration. + public bool IsDecorated => _isDecorated; + + /// + /// Gets the length of content sans escape sequences. + /// + /// Length of content sans escape sequences. + public int ContentLength => PlainText.Length; + + /// + /// Render the decorarted string using automatic output rendering. + /// + /// Rendered string based on automatic output rendering. + public override string ToString() => ToString( + PSStyle.Instance.OutputRendering == OutputRendering.PlainText + ? OutputRendering.PlainText + : OutputRendering.Ansi); + + /// + /// Return string representation of content depending on output rendering mode. + /// + /// Specify how to render the text content. + /// Rendered string based on outputRendering. + public string ToString(OutputRendering outputRendering) + { + if (outputRendering == OutputRendering.Host) + { + throw new ArgumentException(StringDecoratedStrings.RequireExplicitRendering); + } + + if (!_isDecorated) + { + return _text; + } + + return outputRendering == OutputRendering.PlainText ? PlainText : _text; + } + } + + internal struct ValueStringDecorated + { + internal const char ESC = '\x1b'; + private readonly bool _isDecorated; + private readonly string _text; + private string? _plaintextcontent; + + private string PlainText + { + get + { + if (_plaintextcontent == null) + { + _plaintextcontent = AnsiRegex.Replace(_text, string.Empty); + } + + return _plaintextcontent; + } + } + + // replace regex with .NET 6 API once available + internal static readonly Regex AnsiRegex = new Regex(@"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the struct. + /// + /// The input string. + public ValueStringDecorated(string text) + { + _text = text; + _isDecorated = text.Contains(ESC); + _plaintextcontent = null; + } + + /// + /// Gets a value indicating whether the string contains decoration. + /// + /// Boolean if the string contains decoration. + public bool IsDecorated => _isDecorated; + + /// + /// Gets the length of content sans escape sequences. + /// + /// Length of content sans escape sequences. + public int ContentLength => PlainText.Length; + + /// + /// Render the decorarted string using automatic output rendering. + /// + /// Rendered string based on automatic output rendering. + public override string ToString() => ToString( + PSStyle.Instance.OutputRendering == OutputRendering.PlainText + ? OutputRendering.PlainText + : OutputRendering.Ansi); + + /// + /// Return string representation of content depending on output rendering mode. + /// + /// Specify how to render the text content. + /// Rendered string based on outputRendering. + public string ToString(OutputRendering outputRendering) + { + if (outputRendering == OutputRendering.Host) + { + throw new ArgumentException(StringDecoratedStrings.RequireExplicitRendering); + } + + if (!_isDecorated) + { + return _text; + } + + return outputRendering == OutputRendering.PlainText ? PlainText : _text; + } + } +} diff --git a/src/System.Management.Automation/FormatAndOutput/common/TableWriter.cs b/src/System.Management.Automation/FormatAndOutput/common/TableWriter.cs index 54aaa9438c5..fb5ef0bf930 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/TableWriter.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/TableWriter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Management.Automation; using System.Management.Automation.Internal; using System.Text; @@ -16,7 +17,7 @@ internal class TableWriter /// /// Information about each column boundaries. /// - private class ColumnInfo + private sealed class ColumnInfo { internal int startCol = 0; internal int width = 0; @@ -25,7 +26,7 @@ private class ColumnInfo /// /// Class containing information about the tabular layout. /// - private class ScreenInfo + private sealed class ScreenInfo { internal int screenColumns = 0; internal int screenRows = 0; @@ -42,7 +43,6 @@ private class ScreenInfo private ScreenInfo _si; private const char ESC = '\u001b'; - private const string ResetConsoleVt100Code = "\u001b[m"; private List _header; @@ -155,7 +155,7 @@ internal int GenerateHeader(string[] values, LineOutput lo) { foreach (string line in _header) { - lo.WriteLine(line); + lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset); } return _header.Count; @@ -164,7 +164,7 @@ internal int GenerateHeader(string[] values, LineOutput lo) _header = new List(); // generate the row with the header labels - GenerateRow(values, lo, true, null, lo.DisplayCells, _header); + GenerateRow(values, lo, true, null, lo.DisplayCells, _header, isHeader: true); // generate an array of "--" as header markers below // the column header labels @@ -191,14 +191,16 @@ internal int GenerateHeader(string[] values, LineOutput lo) breakLine[k] = StringUtil.DashPadding(count); } - GenerateRow(breakLine, lo, false, null, lo.DisplayCells, _header); + GenerateRow(breakLine, lo, false, null, lo.DisplayCells, _header, isHeader: true); return _header.Count; } - internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOnlySpan alignment, DisplayCells dc, List generatedRows) + internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOnlySpan alignment, DisplayCells dc, List generatedRows, bool isHeader = false) { if (_disabled) + { return; + } // build the current row alignment settings int cols = _si.columnInfo.Length; @@ -216,9 +218,13 @@ internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOn for (int i = 0; i < currentAlignment.Length; i++) { if (alignment[i] == TextAlignment.Undefined) + { currentAlignment[i] = _si.columnInfo[i].alignment; + } else + { currentAlignment[i] = alignment[i]; + } } } @@ -227,14 +233,28 @@ internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOn foreach (string line in GenerateTableRow(values, currentAlignment, lo.DisplayCells)) { generatedRows?.Add(line); - lo.WriteLine(line); + if (isHeader) + { + lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset); + } + else + { + lo.WriteLine(line); + } } } else { string line = GenerateRow(values, currentAlignment, dc); generatedRows?.Add(line); - lo.WriteLine(line); + if (isHeader) + { + lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset); + } + else + { + lo.WriteLine(line); + } } } @@ -438,10 +458,10 @@ private string GenerateRow(string[] values, ReadOnlySpan alignment, Display } sb.Append(GenerateRowField(values[k], _si.columnInfo[k].width, alignment[k], dc, addPadding)); - if (values[k].Contains(ESC)) + if (values[k] is not null && values[k].Contains(ESC)) { // Reset the console output if the content of this column contains ESC - sb.Append(ResetConsoleVt100Code); + sb.Append(PSStyle.Instance.Reset); } } diff --git a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs index c890599cb1e..7760e86b13d 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs @@ -7,6 +7,7 @@ using System.Collections.ObjectModel; using System.Globalization; using System.Management.Automation; +using System.Management.Automation.Internal; using System.Management.Automation.Runspaces; using System.Reflection; using System.Text; @@ -19,6 +20,11 @@ namespace Microsoft.PowerShell.Commands.Internal.Format /// internal static class PSObjectHelper { + #region tracer + [TraceSource("PSObjectHelper", "PSObjectHelper")] + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("PSObjectHelper", "PSObjectHelper"); + #endregion tracer + internal const char Ellipsis = '\u2026'; internal static string PSObjectIsOfExactType(Collection typeNames) @@ -213,7 +219,7 @@ internal static string SmartToString(PSObject so, PSPropertyExpressionFactory ex if (e != null) { StringBuilder sb = new StringBuilder(); - sb.Append("{"); + sb.Append('{'); bool first = true; int enumCount = 0; @@ -283,17 +289,19 @@ internal static string SmartToString(PSObject so, PSPropertyExpressionFactory ex } } - sb.Append("}"); + sb.Append('}'); return sb.ToString(); } // take care of the case there is no base object return so.ToString(); } - catch (ExtendedTypeSystemException e) + catch (Exception e) when (e is ExtendedTypeSystemException || e is InvalidOperationException) { - // NOTE: we catch all the exceptions, since we do not know - // what the underlying object access would throw + // These exceptions are being caught and handled by returning an empty string when + // the object cannot be stringified due to ETS or an instance in the collection has been modified + s_tracer.TraceWarning($"SmartToString method: Exception during conversion to string, emitting empty string: {e.Message}"); + if (formatErrorObject != null) { formatErrorObject.sourceObject = so; @@ -333,7 +341,7 @@ internal static string FormatField(FieldFormattingDirective directive, object va { // use some heuristics to determine if we have "composite formatting" // 2004/11/16-JonN This is heuristic but should be safe enough - if (directive.formatString.Contains("{0") || directive.formatString.Contains("}")) + if (directive.formatString.Contains("{0") || directive.formatString.Contains('}')) { // we do have it, just use it return string.Format(CultureInfo.CurrentCulture, directive.formatString, so); @@ -626,4 +634,3 @@ internal PSPropertyExpression CreateFromExpressionToken(ExpressionToken et, Data private Dictionary _expressionCache; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameter.cs b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameter.cs index d04008a1f9a..e7d7b9e75ed 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameter.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameter.cs @@ -507,7 +507,7 @@ private static string CatenateTypeArray(Type[] arr) internal static string CatenateStringArray(string[] arr) { StringBuilder sb = new StringBuilder(); - sb.Append("{"); + sb.Append('{'); for (int k = 0; k < arr.Length; k++) { if (k > 0) @@ -518,13 +518,12 @@ internal static string CatenateStringArray(string[] arr) sb.Append(arr[k]); } - sb.Append("}"); + sb.Append('}'); return sb.ToString(); } #endregion - private CommandParameterDefinition _paramDef = null; + private readonly CommandParameterDefinition _paramDef = null; } } - diff --git a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameterAssociation.cs b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameterAssociation.cs index 22b4c47ee40..a373f18ee81 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameterAssociation.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshParameterAssociation.cs @@ -225,4 +225,3 @@ internal static void HandleComputerNameProperties(PSObject so, List /// Property name pattern to match. - /// true if no further attempts should be made to resolve wildcards. + /// if no further attempts should be made to resolve wildcards. /// public PSPropertyExpression(string s, bool isResolved) { @@ -354,7 +354,7 @@ private PSPropertyExpressionResult GetValue(PSObject target, bool eatExceptions) } } - private PSObject IfHashtableWrapAsPSCustomObject(PSObject target, out bool wrapped) + private static PSObject IfHashtableWrapAsPSCustomObject(PSObject target, out bool wrapped) { wrapped = false; @@ -375,7 +375,7 @@ private PSObject IfHashtableWrapAsPSCustomObject(PSObject target, out bool wrapp } // private members - private string _stringValue; + private readonly string _stringValue; private bool _isResolved = false; #endregion Private Members diff --git a/src/System.Management.Automation/FormatAndOutput/format-default/format-default.cs b/src/System.Management.Automation/FormatAndOutput/format-default/format-default.cs index 4a6540afb4d..7d7a993d539 100644 --- a/src/System.Management.Automation/FormatAndOutput/format-default/format-default.cs +++ b/src/System.Management.Automation/FormatAndOutput/format-default/format-default.cs @@ -22,4 +22,3 @@ public FormatDefaultCommand() } } } - diff --git a/src/System.Management.Automation/FormatAndOutput/out-console/ConsoleLineOutput.cs b/src/System.Management.Automation/FormatAndOutput/out-console/ConsoleLineOutput.cs index b6cde18fb65..f3ed3ba6189 100644 --- a/src/System.Management.Automation/FormatAndOutput/out-console/ConsoleLineOutput.cs +++ b/src/System.Management.Automation/FormatAndOutput/out-console/ConsoleLineOutput.cs @@ -87,8 +87,15 @@ internal DisplayCellsPSHost(PSHostRawUserInterface rawUserInterface) internal override int Length(string str, int offset) { - Dbg.Assert(offset >= 0, "offset >= 0"); - Dbg.Assert(string.IsNullOrEmpty(str) || (offset < str.Length), "offset < str.Length"); + if (string.IsNullOrEmpty(str)) + { + return 0; + } + + if (offset < 0 || offset >= str.Length) + { + throw PSTraceSource.NewArgumentException(nameof(offset)); + } try { @@ -100,7 +107,7 @@ internal override int Length(string str, int offset) // we will fallback to the default value. } - return string.IsNullOrEmpty(str) ? 0 : str.Length - offset; + return str.Length - offset; } internal override int Length(string str) @@ -143,7 +150,7 @@ internal override int GetTailSplitLength(string str, int offset, int displayCell return GetSplitLengthInternalHelper(str, offset, displayCells, false); } - private PSHostRawUserInterface _rawUserInterface; + private readonly PSHostRawUserInterface _rawUserInterface; } /// @@ -222,6 +229,7 @@ internal override int RowNumber internal override void WriteLine(string s) { CheckStopProcessing(); + // delegate the action to the helper, // that will properly break the string into // screen lines @@ -351,6 +359,7 @@ private void OnWrite(string s) #if TEST_MULTICELL_ON_SINGLE_CELL_LOCALE s = ((DisplayCellsTest)this._displayCellsPSHost).GenerateTestString(s); #endif + switch (this.WriteStream) { case WriteStreamType.Error: @@ -464,7 +473,7 @@ private bool NeedToPrompt /// /// Object to manage prompting. /// - private class PromptHandler + private sealed class PromptHandler { /// /// Prompt handler with the given prompt. @@ -555,12 +564,12 @@ internal PromptResponse PromptUser(PSHostUserInterface console) /// /// Prompt string as passed at initialization. /// - private string _promptString; + private readonly string _promptString; /// /// The cmdlet that uses this prompt helper. /// - private ConsoleLineOutput _callingCmdlet = null; + private readonly ConsoleLineOutput _callingCmdlet = null; } /// @@ -568,25 +577,25 @@ internal PromptResponse PromptUser(PSHostUserInterface console) /// usable width to N-1 (e.g. 80-1) and forcing a call /// to WriteLine() /// - private bool _forceNewLine = true; + private readonly bool _forceNewLine = true; /// /// Use this if IRawConsole is null; /// - private int _fallbackRawConsoleColumnNumber = 80; + private readonly int _fallbackRawConsoleColumnNumber = 80; /// /// Use this if IRawConsole is null; /// - private int _fallbackRawConsoleRowNumber = 40; + private readonly int _fallbackRawConsoleRowNumber = 40; - private WriteLineHelper _writeLineHelper; + private readonly WriteLineHelper _writeLineHelper; /// /// Handler to prompt the user for page breaks /// if this handler is not null, we have prompting. /// - private PromptHandler _prompt = null; + private readonly PromptHandler _prompt = null; /// /// Conter for the # of lines written when prompting is on. @@ -601,17 +610,17 @@ internal PromptResponse PromptUser(PSHostUserInterface console) /// /// Refecence to the PSHostUserInterface interface we use. /// - private PSHostUserInterface _console = null; + private readonly PSHostUserInterface _console = null; /// /// Msh host specific string manipulation helper. /// - private DisplayCells _displayCellsPSHost; + private readonly DisplayCells _displayCellsPSHost; /// /// Reference to error context to throw Msh exceptions. /// - private TerminatingErrorContext _errorContext = null; + private readonly TerminatingErrorContext _errorContext = null; #endregion } diff --git a/src/System.Management.Automation/FormatAndOutput/out-console/OutConsole.cs b/src/System.Management.Automation/FormatAndOutput/out-console/OutConsole.cs index edf9e5ef8f1..2582a1e68db 100644 --- a/src/System.Management.Automation/FormatAndOutput/out-console/OutConsole.cs +++ b/src/System.Management.Automation/FormatAndOutput/out-console/OutConsole.cs @@ -22,7 +22,7 @@ public class OutNullCommand : PSCmdlet /// This parameter specifies the current pipeline object. /// [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { set; get; } = AutomationNull.Value; + public PSObject InputObject { get; set; } = AutomationNull.Value; /// /// Do nothing. diff --git a/src/System.Management.Automation/FormatAndOutput/out-textInterface/OutTextInterface.cs b/src/System.Management.Automation/FormatAndOutput/out-textInterface/OutTextInterface.cs index 5a6f2bd0683..f520df5787b 100644 --- a/src/System.Management.Automation/FormatAndOutput/out-textInterface/OutTextInterface.cs +++ b/src/System.Management.Automation/FormatAndOutput/out-textInterface/OutTextInterface.cs @@ -90,4 +90,3 @@ private void ProcessWrongTypeLineOutput(object obj) } } } - diff --git a/src/System.Management.Automation/GlobalSuppressions.cs b/src/System.Management.Automation/GlobalSuppressions.cs new file mode 100644 index 00000000000..99e9a7c98ac --- /dev/null +++ b/src/System.Management.Automation/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage( + "Style", + "IDE0044:Add readonly modifier", + Justification = "see src/System.Management.Automation/engine/ComInterop/README.md", + Scope = "NamespaceAndDescendants", + Target = "~N:System.Management.Automation.ComInterop")] diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 767d2877a9d..c7ba6db749d 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -12,23 +12,23 @@ - + - + - - - - - - - - - - + + + + + + + + + + - + diff --git a/src/System.Management.Automation/cimSupport/cmdletization/EnumWriter.cs b/src/System.Management.Automation/cimSupport/cmdletization/EnumWriter.cs index 23c7a09c4f2..77328bf0257 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/EnumWriter.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/EnumWriter.cs @@ -17,14 +17,14 @@ internal static class EnumWriter private static ModuleBuilder CreateModuleBuilder() { - AssemblyName aName = new AssemblyName(namespacePrefix); + AssemblyName aName = new(namespacePrefix); AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run); ModuleBuilder mb = ab.DefineDynamicModule(aName.Name); return mb; } - private static Lazy s_moduleBuilder = new Lazy(CreateModuleBuilder, isThreadSafe: true); - private static object s_moduleBuilderUsageLock = new object(); + private static readonly Lazy s_moduleBuilder = new(CreateModuleBuilder, isThreadSafe: true); + private static readonly object s_moduleBuilderUsageLock = new(); internal static string GetEnumFullName(EnumMetadataEnum enumMetadata) { diff --git a/src/System.Management.Automation/cimSupport/cmdletization/MethodInvocationInfo.cs b/src/System.Management.Automation/cimSupport/cmdletization/MethodInvocationInfo.cs index 81a4c33062f..1640dec33b9 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/MethodInvocationInfo.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/MethodInvocationInfo.cs @@ -18,7 +18,7 @@ public sealed class MethodInvocationInfo /// /// Name of the method to invoke. /// Method parameters. - /// Return value of the method (ok to pass null if the method doesn't return anything). + /// Return value of the method (ok to pass if the method doesn't return anything). public MethodInvocationInfo(string name, IEnumerable parameters, MethodParameter returnValue) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -48,16 +48,16 @@ public MethodInvocationInfo(string name, IEnumerable parameters public KeyedCollection Parameters { get; } /// - /// Return value of the method. Can be null if the method doesn't return anything. + /// Return value of the method. Can be if the method doesn't return anything. /// public MethodParameter ReturnValue { get; } internal IEnumerable GetArgumentsOfType() where T : class { - List result = new List(); + List result = new(); foreach (var methodParameter in this.Parameters) { - if (MethodParameterBindings.In != (methodParameter.Bindings & MethodParameterBindings.In)) + if ((methodParameter.Bindings & MethodParameterBindings.In) != MethodParameterBindings.In) { continue; } diff --git a/src/System.Management.Automation/cimSupport/cmdletization/MethodParameter.cs b/src/System.Management.Automation/cimSupport/cmdletization/MethodParameter.cs index d9b08b27179..f044d4d422f 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/MethodParameter.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/MethodParameter.cs @@ -43,7 +43,7 @@ public sealed class MethodParameter public Type ParameterType { get; set; } /// - /// Contents of the ETS type attribute in the CDXML file (or null if that attribute was not specified). + /// Contents of the ETS type attribute in the CDXML file (or if that attribute was not specified). /// The expectation is that the CmdletAdapter will stamp this value onto PSTypeNames of emitted objects. /// public string ParameterTypeName { get; set; } diff --git a/src/System.Management.Automation/cimSupport/cmdletization/ObjectModelWrapper.cs b/src/System.Management.Automation/cimSupport/cmdletization/ObjectModelWrapper.cs index 289ad0c3a76..a840ca527fd 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/ObjectModelWrapper.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/ObjectModelWrapper.cs @@ -127,7 +127,7 @@ public virtual void StopProcessing() /// /// The object on which to invoke the method. /// Method invocation details. - /// true if successful method invocations should emit downstream the being operated on. + /// if successful method invocations should emit downstream the being operated on. public virtual void ProcessRecord(TObjectInstance objectInstance, MethodInvocationInfo methodInvocationInfo, bool passThru) { throw new NotImplementedException(); @@ -138,7 +138,7 @@ public virtual void ProcessRecord(TObjectInstance objectInstance, MethodInvocati /// /// Query parameters. /// Method invocation details. - /// true if successful method invocations should emit downstream the object instance being operated on. + /// if successful method invocations should emit downstream the object instance being operated on. public virtual void ProcessRecord(QueryBuilder query, MethodInvocationInfo methodInvocationInfo, bool passThru) { throw new NotImplementedException(); @@ -182,7 +182,7 @@ public string ClassName /// /// Name of the class (from the object model handled by this ObjectModelWrapper) that is wrapped by the currently executing cmdlet. - /// This value can be null (i.e. when ClassVersion attribute is omitted in the ps1xml) + /// This value can be (i.e. when ClassVersion attribute is omitted in the ps1xml) /// public string ClassVersion { diff --git a/src/System.Management.Automation/cimSupport/cmdletization/QueryBuilder.cs b/src/System.Management.Automation/cimSupport/cmdletization/QueryBuilder.cs index a1ce1d726ec..36f781d98a0 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/QueryBuilder.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/QueryBuilder.cs @@ -52,8 +52,8 @@ public abstract class QueryBuilder /// Property name to query on. /// Property values to accept in the query. /// - /// true if should be treated as a containing a wildcard pattern; - /// false otherwise + /// if should be treated as a containing a wildcard pattern; + /// otherwise. /// /// /// Describes how to handle filters that didn't match any objects @@ -69,8 +69,8 @@ public virtual void FilterByProperty(string propertyName, IEnumerable allowedPro /// Property name to query on. /// Property values to reject in the query. /// - /// true if should be treated as a containing a wildcard pattern; - /// false otherwise + /// if should be treated as a containing a wildcard pattern; + /// otherwise. /// /// /// Describes how to handle filters that didn't match any objects diff --git a/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs b/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs index 3757319c9ab..5aa1b201fc9 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs @@ -234,13 +234,13 @@ private string GetCmdletName(CommonCmdletMetadata cmdletMetadata) return verb + "-" + noun; } - private string GetCmdletAttributes(CommonCmdletMetadata cmdletMetadata) + private static string GetCmdletAttributes(CommonCmdletMetadata cmdletMetadata) { // Generate the script for the Alias and Obsolete Attribute if any is declared in CDXML - StringBuilder attributes = new StringBuilder(150); + StringBuilder attributes = new(150); if (cmdletMetadata.Aliases != null) { - attributes.Append("[Alias('" + string.Join("','", cmdletMetadata.Aliases.Select(alias => CodeGeneration.EscapeSingleQuotedStringContent(alias))) + "')]"); + attributes.Append("[Alias('" + string.Join("','", cmdletMetadata.Aliases.Select(static alias => CodeGeneration.EscapeSingleQuotedStringContent(alias))) + "')]"); } if (cmdletMetadata.Obsolete != null) @@ -257,12 +257,12 @@ private string GetCmdletAttributes(CommonCmdletMetadata cmdletMetadata) private Dictionary GetCommonParameters() { - Dictionary commonParameters = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary commonParameters = new(StringComparer.OrdinalIgnoreCase); - InternalParameterMetadata internalParameterMetadata = new InternalParameterMetadata(_objectModelWrapper, false); + InternalParameterMetadata internalParameterMetadata = new(_objectModelWrapper, false); foreach (CompiledCommandParameter compiledCommandParameter in internalParameterMetadata.BindableParameters.Values) { - ParameterMetadata parameterMetadata = new ParameterMetadata(compiledCommandParameter); + ParameterMetadata parameterMetadata = new(compiledCommandParameter); foreach (ParameterSetMetadata psetMetadata in parameterMetadata.ParameterSets.Values) { if (psetMetadata.ValueFromPipeline) @@ -335,7 +335,7 @@ private Dictionary GetCommonParameters() private static List GetCommonParameterSets(Dictionary commonParameters) { - Dictionary parameterSetNames = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary parameterSetNames = new(StringComparer.OrdinalIgnoreCase); foreach (ParameterMetadata parameter in commonParameters.Values) { foreach (string parameterSetName in parameter.ParameterSets.Keys) @@ -352,7 +352,7 @@ private static List GetCommonParameterSets(Dictionary result = new List(parameterSetNames.Keys); + List result = new(parameterSetNames.Keys); result.Sort(StringComparer.Ordinal); // to have a deterministic order of parameter sets (also means that Ordinal instead of OrdinalIgnoreCase is ok) return result; } @@ -365,7 +365,7 @@ private string GetMethodParameterSet(StaticMethodMetadata staticMethod) private List GetMethodParameterSets(StaticCmdletMetadata staticCmdlet) { - Dictionary parameterSetNames = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary parameterSetNames = new(StringComparer.OrdinalIgnoreCase); foreach (StaticMethodMetadata method in staticCmdlet.Method) { @@ -386,7 +386,7 @@ private List GetMethodParameterSets(StaticCmdletMetadata staticCmdlet) return new List(parameterSetNames.Keys); } - private Dictionary _staticMethodMetadataToUniqueId = new Dictionary(); + private readonly Dictionary _staticMethodMetadataToUniqueId = new(); private string GetMethodParameterSet(CommonMethodMetadata methodMetadata) { @@ -404,7 +404,7 @@ private string GetMethodParameterSet(CommonMethodMetadata methodMetadata) private List GetMethodParameterSets(InstanceCmdletMetadata instanceCmdlet) { - Dictionary parameterSetNames = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary parameterSetNames = new(StringComparer.OrdinalIgnoreCase); InstanceMethodMetadata method = instanceCmdlet.Method; string parameterSetName = GetMethodParameterSet(method); @@ -436,7 +436,7 @@ private GetCmdletParameters GetGetCmdletParameters(InstanceCmdletMetadata instan private List GetQueryParameterSets(InstanceCmdletMetadata instanceCmdlet) { - Dictionary parameterSetNames = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary parameterSetNames = new(StringComparer.OrdinalIgnoreCase); var parameters = new List(); bool anyQueryParameters = false; @@ -555,7 +555,7 @@ private ParameterMetadata GetParameter( parameterName = objectModelParameterName; } - ParameterMetadata parameterMetadata = new ParameterMetadata(parameterName); + ParameterMetadata parameterMetadata = new(parameterName); parameterMetadata.ParameterType = GetDotNetType(parameterTypeMetadata); if (typeof(PSCredential).Equals(parameterMetadata.ParameterType)) { @@ -645,7 +645,7 @@ private ParameterMetadata GetParameter( if (parameterCmdletization.ValidateSet != null) { - List allowedValues = new List(); + List allowedValues = new(); foreach (string allowedValue in parameterCmdletization.ValidateSet) { allowedValues.Add(allowedValue); @@ -803,9 +803,9 @@ private CommandMetadata GetCommandMetadata(CommonCmdletMetadata cmdletMetadata) confirmImpact = (System.Management.Automation.ConfirmImpact)(int)cmdletMetadata.ConfirmImpact; } - Dictionary parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary parameters = new(StringComparer.OrdinalIgnoreCase); - CommandMetadata commandMetadata = new CommandMetadata( + CommandMetadata commandMetadata = new( name: this.GetCmdletName(cmdletMetadata), commandType: CommandTypes.Cmdlet, isProxyForCmdlet: true, @@ -829,12 +829,12 @@ private static string EscapeModuleNameForHelpComment(string name) { Dbg.Assert(name != null, "Caller should verify name != null"); - StringBuilder result = new StringBuilder(name.Length); + StringBuilder result = new(name.Length); foreach (char c in name) { - if (("\"'`$#".IndexOf(c) == (-1)) && - (!char.IsControl(c)) && - (!char.IsWhiteSpace(c))) + if (!"\"'`$#".Contains(c) + && !char.IsControl(c) + && !char.IsWhiteSpace(c)) { result.Append(c); } @@ -850,10 +850,10 @@ private static List> GetCombinations(params IEnumerable[] x if (x.Length == 1) { - List> result = new List>(); + List> result = new(); foreach (string s in x[0]) { - List subresult = new List(); + List subresult = new(); subresult.Add(s); result.Add(subresult); } @@ -866,12 +866,12 @@ private static List> GetCombinations(params IEnumerable[] x Array.Copy(x, 0, smallX, 0, smallX.Length); List> smallResult = GetCombinations(smallX); - List> result = new List>(); + List> result = new(); foreach (List smallSubresult in smallResult) { foreach (string s in x[x.Length - 1]) { - List newsubresult = new List(smallSubresult); + List newsubresult = new(smallSubresult); newsubresult.Add(s); result.Add(newsubresult); } @@ -941,7 +941,7 @@ private static void MultiplyParameterSets( foreach (ParameterMetadata parameter in parameters.Values) { - List> oldParameterSets = new List>(parameter.ParameterSets); + List> oldParameterSets = new(parameter.ParameterSets); parameter.ParameterSets.Clear(); foreach (KeyValuePair oldParameterSet in oldParameterSets) @@ -964,7 +964,7 @@ private static IEnumerable MultiplyParameterSets( string parameterSetNameTemplate, // {0} is the original parameter set, other ones are taken from the otherParameterSets array params IEnumerable[] otherParameterSets) { - List result = new List(); + List result = new(); List> combinations = GetCombinations(otherParameterSets); foreach (List combination in combinations) @@ -1086,7 +1086,7 @@ private static void GenerateSingleMethodParameterProcessing( prefix); } - if (MethodParameterBindings.In == (methodParameterBindings & MethodParameterBindings.In)) + if ((methodParameterBindings & MethodParameterBindings.In) == MethodParameterBindings.In) { Dbg.Assert(cmdletParameterName != null, "Called should verify cmdletParameterName!=null for 'in' parameters"); @@ -1114,7 +1114,7 @@ private static void GenerateSingleMethodParameterProcessing( CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterTypeName), CodeGeneration.EscapeSingleQuotedStringContent(methodParameterBindings.ToString())); - if (MethodParameterBindings.In == (methodParameterBindings & MethodParameterBindings.In)) + if ((methodParameterBindings & MethodParameterBindings.In) == MethodParameterBindings.In) { output.WriteLine("{0}}}", prefix); } @@ -1139,8 +1139,8 @@ private void GenerateMethodParametersProcessing( out string outputTypeAttributeDeclaration) { methodParameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - StringBuilder outputTypeAttributeDeclarationBuilder = new StringBuilder(); - StringWriter output = new StringWriter(CultureInfo.InvariantCulture); + StringBuilder outputTypeAttributeDeclarationBuilder = new(); + StringWriter output = new(CultureInfo.InvariantCulture); output.WriteLine(" $__cmdletization_methodParameters = [System.Collections.Generic.List[Microsoft.PowerShell.Cmdletization.MethodParameter]]::new()"); output.WriteLine(); @@ -1170,8 +1170,8 @@ string parameterSetName in output.WriteLine(") -contains $_ } {"); } - List typesOfOutParameters = new List(); - List etsTypesOfOutParameters = new List(); + List typesOfOutParameters = new(); + List etsTypesOfOutParameters = new(); if (method.Parameters != null) { foreach (StaticMethodParameterMetadata methodParameter in method.Parameters) @@ -1222,7 +1222,7 @@ string parameterSetName in methodParameter.ParameterName, methodParameterBindings); - if (MethodParameterBindings.Out == (methodParameterBindings & MethodParameterBindings.Out)) + if ((methodParameterBindings & MethodParameterBindings.Out) == MethodParameterBindings.Out) { typesOfOutParameters.Add(dotNetTypeOfParameter); etsTypesOfOutParameters.Add(methodParameter.Type.ETSType); @@ -1246,7 +1246,7 @@ string parameterSetName in CodeGeneration.EscapeSingleQuotedStringContent(method.ReturnValue.Type.ETSType)); } - if (MethodParameterBindings.Out == (methodParameterBindings & MethodParameterBindings.Out)) + if ((methodParameterBindings & MethodParameterBindings.Out) == MethodParameterBindings.Out) { typesOfOutParameters.Add(dotNetTypeOfParameter); etsTypesOfOutParameters.Add(method.ReturnValue.Type.ETSType); @@ -1303,7 +1303,7 @@ private void GenerateMethodParametersProcessing( { methodParameters = new Dictionary(StringComparer.OrdinalIgnoreCase); outputTypeAttributeDeclaration = string.Empty; - StringWriter output = new StringWriter(CultureInfo.InvariantCulture); + StringWriter output = new(CultureInfo.InvariantCulture); output.WriteLine(" $__cmdletization_methodParameters = [System.Collections.Generic.List[Microsoft.PowerShell.Cmdletization.MethodParameter]]::new()"); output.WriteLine(" switch -exact ($PSCmdlet.ParameterSetName) { "); @@ -1320,8 +1320,8 @@ private void GenerateMethodParametersProcessing( output.WriteLine(") -contains $_ } {"); - List typesOfOutParameters = new List(); - List etsTypesOfOutParameters = new List(); + List typesOfOutParameters = new(); + List etsTypesOfOutParameters = new(); if (method.Parameters != null) { foreach (InstanceMethodParameterMetadata methodParameter in method.Parameters) @@ -1363,7 +1363,7 @@ private void GenerateMethodParametersProcessing( methodParameter.ParameterName, methodParameterBindings); - if (MethodParameterBindings.Out == (methodParameterBindings & MethodParameterBindings.Out)) + if ((methodParameterBindings & MethodParameterBindings.Out) == MethodParameterBindings.Out) { typesOfOutParameters.Add(dotNetTypeOfParameter); etsTypesOfOutParameters.Add(methodParameter.Type.ETSType); @@ -1387,7 +1387,7 @@ private void GenerateMethodParametersProcessing( CodeGeneration.EscapeSingleQuotedStringContent(method.ReturnValue.Type.ETSType)); } - if (MethodParameterBindings.Out == (methodParameterBindings & MethodParameterBindings.Out)) + if ((methodParameterBindings & MethodParameterBindings.Out) == MethodParameterBindings.Out) { typesOfOutParameters.Add(dotNetTypeOfParameter); etsTypesOfOutParameters.Add(method.ReturnValue.Type.ETSType); @@ -1444,7 +1444,7 @@ private void GenerateMethodParametersProcessing( } } - private void GenerateIfBoundParameter( + private static void GenerateIfBoundParameter( IEnumerable commonParameterSets, IEnumerable methodParameterSets, ParameterMetadata cmdletParameterMetadata, @@ -1615,14 +1615,14 @@ private void GenerateQueryParametersProcessing( out Dictionary queryParameters) { queryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - StringWriter output = new StringWriter(CultureInfo.InvariantCulture); + StringWriter output = new(CultureInfo.InvariantCulture); output.WriteLine(" $__cmdletization_queryBuilder = $__cmdletization_objectModelWrapper.GetQueryBuilder()"); GetCmdletParameters getCmdletParameters = GetGetCmdletParameters(instanceCmdlet); if (getCmdletParameters.QueryableProperties != null) { - foreach (PropertyMetadata property in getCmdletParameters.QueryableProperties.Where(p => p.Items != null)) + foreach (PropertyMetadata property in getCmdletParameters.QueryableProperties.Where(static p => p.Items != null)) { for (int i = 0; i < property.Items.Length; i++) { @@ -1681,7 +1681,7 @@ private void GenerateQueryParametersProcessing( if (getCmdletParameters.QueryableAssociations != null) { - foreach (Association association in getCmdletParameters.QueryableAssociations.Where(a => a.AssociatedInstance != null)) + foreach (Association association in getCmdletParameters.QueryableAssociations.Where(static a => a.AssociatedInstance != null)) { ParameterMetadata parameterMetadata = GenerateAssociationClause( commonParameterSets, queryParameterSets, methodParameterSets, association, association.AssociatedInstance, output); @@ -1725,7 +1725,7 @@ private void GenerateQueryParametersProcessing( if (instanceCmdlet != null) { - ParameterMetadata inputObjectParameter = new ParameterMetadata("InputObject", _objectInstanceType.MakeArrayType()); + ParameterMetadata inputObjectParameter = new("InputObject", _objectInstanceType.MakeArrayType()); ParameterSetMetadata.ParameterFlags inputObjectFlags = ParameterSetMetadata.ParameterFlags.ValueFromPipeline; if (queryParameters.Count > 0) @@ -1761,10 +1761,10 @@ private void GenerateQueryParametersProcessing( inputObjectParameter.Attributes.Add(new ValidateNotNullAttribute()); inputObjectParameter.ParameterSets.Clear(); - ParameterSetMetadata inputObjectPSet = new ParameterSetMetadata( + ParameterSetMetadata inputObjectPSet = new( int.MinValue, // non-positional inputObjectFlags, - null); // no help message + helpMessage: null); inputObjectParameter.ParameterSets.Add(ScriptWriter.InputObjectQueryParameterSetName, inputObjectPSet); queryParameters.Add(inputObjectParameter.Name, inputObjectParameter); } @@ -1859,9 +1859,9 @@ private void GenerateQueryParametersProcessing( private string GetHelpDirectiveForExternalHelp() { - StringBuilder output = new StringBuilder(); + StringBuilder output = new(); - if (GenerationOptions.HelpXml == (_generationOptions & GenerationOptions.HelpXml)) + if ((_generationOptions & GenerationOptions.HelpXml) == GenerationOptions.HelpXml) { output.AppendFormat( CultureInfo.InvariantCulture, @@ -1874,7 +1874,7 @@ private string GetHelpDirectiveForExternalHelp() private void WriteCmdlet(TextWriter output, StaticCmdletMetadata staticCmdlet) { - string attributeString = this.GetCmdletAttributes(staticCmdlet.CmdletMetadata); + string attributeString = GetCmdletAttributes(staticCmdlet.CmdletMetadata); Dictionary commonParameters = this.GetCommonParameters(); List commonParameterSets = GetCommonParameterSets(commonParameters); @@ -1948,9 +1948,9 @@ private static void AddPassThruParameter(IDictionary if (!outParametersArePresent) { - ParameterMetadata passThruParameter = new ParameterMetadata("PassThru", typeof(SwitchParameter)); + ParameterMetadata passThruParameter = new("PassThru", typeof(SwitchParameter)); passThruParameter.ParameterSets.Clear(); - ParameterSetMetadata passThruPSet = new ParameterSetMetadata(int.MinValue, 0, null); + ParameterSetMetadata passThruPSet = new(int.MinValue, 0, null); passThruParameter.ParameterSets.Add(ParameterAttribute.AllParameterSets, passThruPSet); commonParameters.Add(passThruParameter.Name, passThruParameter); @@ -1959,7 +1959,7 @@ private static void AddPassThruParameter(IDictionary private void WriteCmdlet(TextWriter output, InstanceCmdletMetadata instanceCmdlet) { - string attributeString = this.GetCmdletAttributes(instanceCmdlet.CmdletMetadata); + string attributeString = GetCmdletAttributes(instanceCmdlet.CmdletMetadata); Dictionary commonParameters = this.GetCommonParameters(); List commonParameterSets = GetCommonParameterSets(commonParameters); @@ -1983,7 +1983,7 @@ private void WriteCmdlet(TextWriter output, InstanceCmdletMetadata instanceCmdle } else if (queryParameterSets.Count == 1) { - commandMetadata.DefaultParameterSetName = queryParameterSets.Single(); + commandMetadata.DefaultParameterSetName = queryParameterSets[0]; } AddPassThruParameter(commonParameters, instanceCmdlet); @@ -2017,7 +2017,7 @@ private void WriteCmdlet(TextWriter output, InstanceCmdletMetadata instanceCmdle private string GetOutputAttributeForGetCmdlet() { - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); result.AppendFormat( CultureInfo.InvariantCulture, "[OutputType([{0}])]", @@ -2055,7 +2055,7 @@ private void WriteGetCmdlet(TextWriter output) { Dictionary commonParameters = this.GetCommonParameters(); List commonParameterSets = GetCommonParameterSets(commonParameters); - List methodParameterSets = new List(); + List methodParameterSets = new(); methodParameterSets.Add(string.Empty); List queryParameterSets = GetQueryParameterSets(null); @@ -2066,7 +2066,7 @@ private void WriteGetCmdlet(TextWriter output) CommonCmdletMetadata cmdletMetadata = this.GetGetCmdletMetadata(); Dbg.Assert(cmdletMetadata != null, "xsd should ensure that cmdlet metadata element is always present"); CommandMetadata commandMetadata = this.GetCommandMetadata(cmdletMetadata); - string attributeString = this.GetCmdletAttributes(cmdletMetadata); + string attributeString = GetCmdletAttributes(cmdletMetadata); GetCmdletParameters getCmdletParameters = this.GetGetCmdletParameters(null); if (!string.IsNullOrEmpty(getCmdletParameters.DefaultCmdletParameterSet)) @@ -2100,7 +2100,7 @@ private void WriteGetCmdlet(TextWriter output) /* 1 */ CodeGeneration.EscapeSingleQuotedStringContent(commandMetadata.Name)); } - private static object s_enumCompilationLock = new object(); + private static readonly object s_enumCompilationLock = new(); private static void CompileEnum(EnumMetadataEnum enumMetadata) { @@ -2176,11 +2176,11 @@ internal void PopulatePSModuleInfo(PSModuleInfo moduleInfo) moduleInfo.SetModuleType(ModuleType.Cim); moduleInfo.SetVersion(new Version(_cmdletizationMetadata.Class.Version)); - Hashtable cmdletizationData = new Hashtable(StringComparer.OrdinalIgnoreCase); + Hashtable cmdletizationData = new(StringComparer.OrdinalIgnoreCase); cmdletizationData.Add(PrivateDataKey_ClassName, _cmdletizationMetadata.Class.ClassName); cmdletizationData.Add(PrivateDataKey_ObjectModelWrapper, _objectModelWrapper); - Hashtable privateData = new Hashtable(StringComparer.OrdinalIgnoreCase); + Hashtable privateData = new(StringComparer.OrdinalIgnoreCase); privateData.Add(PrivateDataKey_CmdletsOverObjects, cmdletizationData); moduleInfo.PrivateData = privateData; } @@ -2203,7 +2203,7 @@ internal void ReportExportedCommands(PSModuleInfo moduleInfo, string prefix) { cmdletMetadatas = cmdletMetadatas.Concat( - _cmdletizationMetadata.Class.InstanceCmdlets.Cmdlet.Select(c => c.CmdletMetadata)); + _cmdletizationMetadata.Class.InstanceCmdlets.Cmdlet.Select(static c => c.CmdletMetadata)); } } @@ -2211,7 +2211,7 @@ internal void ReportExportedCommands(PSModuleInfo moduleInfo, string prefix) { cmdletMetadatas = cmdletMetadatas.Concat( - _cmdletizationMetadata.Class.StaticCmdlets.Select(c => c.CmdletMetadata)); + _cmdletizationMetadata.Class.StaticCmdlets.Select(static c => c.CmdletMetadata)); } foreach (CommonCmdletMetadata cmdletMetadata in cmdletMetadatas) diff --git a/src/System.Management.Automation/cimSupport/cmdletization/cim/WildcardPatternToCimQueryParser.cs b/src/System.Management.Automation/cimSupport/cmdletization/cim/WildcardPatternToCimQueryParser.cs index 4ce8a854487..48a47da7289 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/cim/WildcardPatternToCimQueryParser.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/cim/WildcardPatternToCimQueryParser.cs @@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.Cmdletization.Cim /// internal class WildcardPatternToCimQueryParser : WildcardPatternParser { - private readonly StringBuilder _result = new StringBuilder(); + private readonly StringBuilder _result = new(); private bool _needClientSideFiltering; protected override void AppendLiteralCharacter(char c) @@ -79,13 +79,13 @@ protected override void AppendCharacterRangeToBracketExpression(char startOfChar // 93 = ] // 94 = ^ // 95 = _ - if ((91 <= startOfCharacterRange) && (startOfCharacterRange <= 94)) + if ((startOfCharacterRange >= 91) && (startOfCharacterRange <= 94)) { startOfCharacterRange = (char)90; _needClientSideFiltering = true; } - if ((91 <= endOfCharacterRange) && (endOfCharacterRange <= 94)) + if ((endOfCharacterRange >= 91) && (endOfCharacterRange <= 94)) { endOfCharacterRange = (char)95; _needClientSideFiltering = true; diff --git a/src/System.Management.Automation/cimSupport/cmdletization/xml/CoreCLR/cmdlets-over-objects.xmlSerializer.autogen.cs b/src/System.Management.Automation/cimSupport/cmdletization/xml/CoreCLR/cmdlets-over-objects.xmlSerializer.autogen.cs index 9c53032284e..ece48f33d0b 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/xml/CoreCLR/cmdlets-over-objects.xmlSerializer.autogen.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/xml/CoreCLR/cmdlets-over-objects.xmlSerializer.autogen.cs @@ -6680,7 +6680,7 @@ internal object Deserialize(XmlReader reader) { if (reader == null) { - throw new ArgumentNullException("reader"); + throw new ArgumentNullException(nameof(reader)); } XmlSerializationReader1 cdxmlSerializationReader = new XmlSerializationReader1(reader); diff --git a/src/System.Management.Automation/cimSupport/cmdletization/xml/cmdlets-over-objects.xmlSerializer.autogen.cs b/src/System.Management.Automation/cimSupport/cmdletization/xml/cmdlets-over-objects.xmlSerializer.autogen.cs index f4892b51bc1..a05d597999a 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/xml/cmdlets-over-objects.xmlSerializer.autogen.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/xml/cmdlets-over-objects.xmlSerializer.autogen.cs @@ -2071,22 +2071,22 @@ private void Write15_PropertyMetadata(string n, string ns, global::Microsoft.Pow { if (ci == Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@RegularQuery && ((object)(ai) != null)) { - if (((object)ai) != null && !(ai is global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery)) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@RegularQuery"); + if (((object)ai) != null && ai is not global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@RegularQuery"); Write13_WildcardablePropertyQuery(@"RegularQuery", @"http://schemas.microsoft.com/cmdlets-over-objects/2009/11", ((global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery)ai), false, false); } else if (ci == Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@ExcludeQuery && ((object)(ai) != null)) { - if (((object)ai) != null && !(ai is global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery)) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@ExcludeQuery"); + if (((object)ai) != null && ai is not global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@ExcludeQuery"); Write13_WildcardablePropertyQuery(@"ExcludeQuery", @"http://schemas.microsoft.com/cmdlets-over-objects/2009/11", ((global::Microsoft.PowerShell.Cmdletization.Xml.WildcardablePropertyQuery)ai), false, false); } else if (ci == Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MaxValueQuery && ((object)(ai) != null)) { - if (((object)ai) != null && !(ai is global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery)) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MaxValueQuery"); + if (((object)ai) != null && ai is not global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MaxValueQuery"); Write14_PropertyQuery(@"MaxValueQuery", @"http://schemas.microsoft.com/cmdlets-over-objects/2009/11", ((global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery)ai), false, false); } else if (ci == Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MinValueQuery && ((object)(ai) != null)) { - if (((object)ai) != null && !(ai is global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery)) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MinValueQuery"); + if (((object)ai) != null && ai is not global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery) throw CreateMismatchChoiceException(@"Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery", @"ItemsElementName", @"Microsoft.PowerShell.Cmdletization.Xml.ItemsChoiceType.@MinValueQuery"); Write14_PropertyQuery(@"MinValueQuery", @"http://schemas.microsoft.com/cmdlets-over-objects/2009/11", ((global::Microsoft.PowerShell.Cmdletization.Xml.PropertyQuery)ai), false, false); } else if ((object)(ai) != null) diff --git a/src/System.Management.Automation/cimSupport/other/ciminstancetypeadapter.cs b/src/System.Management.Automation/cimSupport/other/ciminstancetypeadapter.cs index 3a7e29a4c14..f9aa9f9b73c 100644 --- a/src/System.Management.Automation/cimSupport/other/ciminstancetypeadapter.cs +++ b/src/System.Management.Automation/cimSupport/other/ciminstancetypeadapter.cs @@ -28,7 +28,7 @@ public sealed class CimInstanceAdapter : PSPropertyAdapter { private static PSAdaptedProperty GetCimPropertyAdapter(CimProperty property, object baseObject, string propertyName) { - PSAdaptedProperty propertyToAdd = new PSAdaptedProperty(propertyName, property); + PSAdaptedProperty propertyToAdd = new(propertyName, property); propertyToAdd.baseObject = baseObject; // propertyToAdd.adapter = this; return propertyToAdd; @@ -50,7 +50,7 @@ private static PSAdaptedProperty GetCimPropertyAdapter(CimProperty property, obj private static PSAdaptedProperty GetPSComputerNameAdapter(CimInstance cimInstance) { - PSAdaptedProperty psComputerNameProperty = new PSAdaptedProperty(RemotingConstants.ComputerNameNoteProperty, cimInstance); + PSAdaptedProperty psComputerNameProperty = new(RemotingConstants.ComputerNameNoteProperty, cimInstance); psComputerNameProperty.baseObject = cimInstance; // psComputerNameProperty.adapter = this; return psComputerNameProperty; @@ -73,7 +73,7 @@ public override System.Collections.ObjectModel.Collection Get throw new PSInvalidOperationException(msg); } - Collection result = new Collection(); + Collection result = new(); if (cimInstance.CimInstanceProperties != null) { @@ -135,7 +135,7 @@ public override PSAdaptedProperty GetProperty(object baseObject, string property return null; } - /// + /// public override PSAdaptedProperty GetFirstPropertyOrDefault(object baseObject, MemberNamePredicate predicate) { if (predicate == null) @@ -242,7 +242,7 @@ public override object GetPropertyValue(PSAdaptedProperty adaptedProperty) throw new ArgumentNullException(nameof(adaptedProperty)); } - private void AddTypeNameHierarchy(IList typeNamesWithNamespace, IList typeNamesWithoutNamespace, string namespaceName, string className) + private static void AddTypeNameHierarchy(IList typeNamesWithNamespace, IList typeNamesWithoutNamespace, string namespaceName, string className) { if (!string.IsNullOrEmpty(namespaceName)) { @@ -258,9 +258,9 @@ private void AddTypeNameHierarchy(IList typeNamesWithNamespace, IList GetInheritanceChain(CimInstance cimInstance) + private static List GetInheritanceChain(CimInstance cimInstance) { - List inheritanceChain = new List(); + List inheritanceChain = new(); CimClass cimClass = cimInstance.CimClass; Dbg.Assert(cimClass != null, "CimInstance should always have ClassDecl"); while (cimClass != null) @@ -285,8 +285,7 @@ private List GetInheritanceChain(CimInstance cimInstance) /// public override Collection GetTypeNameHierarchy(object baseObject) { - var cimInstance = baseObject as CimInstance; - if (cimInstance == null) + if (!(baseObject is CimInstance cimInstance)) { throw new ArgumentNullException(nameof(baseObject)); } @@ -362,13 +361,12 @@ public override bool IsSettable(PSAdaptedProperty adaptedProperty) return false; } - CimProperty cimProperty = adaptedProperty.Tag as CimProperty; - if (cimProperty == null) + if (!(adaptedProperty.Tag is CimProperty cimProperty)) { return false; } - bool isReadOnly = (CimFlags.ReadOnly == (cimProperty.Flags & CimFlags.ReadOnly)); + bool isReadOnly = ((cimProperty.Flags & CimFlags.ReadOnly) == CimFlags.ReadOnly); bool isSettable = !isReadOnly; return isSettable; } diff --git a/src/System.Management.Automation/engine/ApplicationInfo.cs b/src/System.Management.Automation/engine/ApplicationInfo.cs index 9e785aee935..5fe76424f5a 100644 --- a/src/System.Management.Automation/engine/ApplicationInfo.cs +++ b/src/System.Management.Automation/engine/ApplicationInfo.cs @@ -52,7 +52,7 @@ internal ApplicationInfo(string name, string path, ExecutionContext context) : b _context = context; } - private ExecutionContext _context; + private readonly ExecutionContext _context; #endregion ctor /// @@ -113,7 +113,10 @@ public override SessionStateEntryVisibility Visibility return _context.EngineSessionState.CheckApplicationVisibility(Path); } - set { throw PSTraceSource.NewNotImplementedException(); } + set + { + throw PSTraceSource.NewNotImplementedException(); + } } /// diff --git a/src/System.Management.Automation/engine/ArgumentTypeConverterAttribute.cs b/src/System.Management.Automation/engine/ArgumentTypeConverterAttribute.cs index e9b6be3caff..a2c2cd8321e 100644 --- a/src/System.Management.Automation/engine/ArgumentTypeConverterAttribute.cs +++ b/src/System.Management.Automation/engine/ArgumentTypeConverterAttribute.cs @@ -25,15 +25,13 @@ internal ArgumentTypeConverterAttribute(params Type[] types) _convertTypes = types; } - private Type[] _convertTypes; + private readonly Type[] _convertTypes; internal Type TargetType { get { - return _convertTypes == null - ? null - : _convertTypes.LastOrDefault(); + return _convertTypes?.LastOrDefault(); } } @@ -67,9 +65,7 @@ internal object Transform(EngineIntrinsics engineIntrinsics, object inputData, b else temp = result; - PSReference reference = temp as PSReference; - - if (reference == null) + if (!(temp is PSReference reference)) { throw new PSInvalidCastException("InvalidCastExceptionReferenceTypeExpected", null, ExtendedTypeSystem.ReferenceTypeExpected); @@ -210,4 +206,3 @@ internal static void ThrowPSInvalidBooleanArgumentCastException(Type resultType, } } } - diff --git a/src/System.Management.Automation/engine/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index 16445703030..a0411c78df7 100644 --- a/src/System.Management.Automation/engine/Attributes.cs +++ b/src/System.Management.Automation/engine/Attributes.cs @@ -326,7 +326,10 @@ public abstract class CmdletCommonMetadataAttribute : CmdletMetadataAttribute /// public bool SupportsTransactions { - get { return _supportsTransactions; } + get + { + return _supportsTransactions; + } set { @@ -507,7 +510,7 @@ public OutputTypeAttribute(params string[] type) [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ParameterSetName { - get => _parameterSetName ?? (_parameterSetName = new[] { ParameterAttribute.AllParameterSets }); + get => _parameterSetName ??= new[] { ParameterAttribute.AllParameterSets }; set => _parameterSetName = value; } @@ -607,6 +610,7 @@ public ParameterAttribute(string experimentName, ExperimentAction experimentActi public ExperimentAction ExperimentAction { get; } internal bool ToHide => EffectiveAction == ExperimentAction.Hide; + internal bool ToShow => EffectiveAction == ExperimentAction.Show; /// @@ -839,8 +843,7 @@ public sealed class ValidateLengthAttribute : ValidateEnumeratedArgumentsAttribu /// For invalid arguments. protected override void ValidateElement(object element) { - string objectString = element as string; - if (objectString == null) + if (!(element is string objectString)) { throw new ValidationMetadataException( "ValidateLengthNotString", @@ -938,27 +941,27 @@ public sealed class ValidateRangeAttribute : ValidateEnumeratedArgumentsAttribut /// public object MinRange { get; } - private IComparable _minComparable; + private readonly IComparable _minComparable; /// /// Gets the attribute's maximum range. /// public object MaxRange { get; } - private IComparable _maxComparable; + private readonly IComparable _maxComparable; /// /// The range values and the value to validate will all be converted to the promoted type. /// If minRange and maxRange are the same type, /// - private Type _promotedType; + private readonly Type _promotedType; /// /// Gets the name of the predefined range. /// internal ValidateRangeKind? RangeKind { get => _rangeKind; } - private ValidateRangeKind? _rangeKind; + private readonly ValidateRangeKind? _rangeKind; /// /// Validates that each parameter argument falls in the range specified by @@ -1083,7 +1086,7 @@ public ValidateRangeAttribute(ValidateRangeKind kind) : base() _rangeKind = kind; } - private void ValidateRange(object element, ValidateRangeKind rangeKind) + private static void ValidateRange(object element, ValidateRangeKind rangeKind) { Type commonType = GetCommonType(typeof(int), element.GetType()); if (commonType == null) @@ -1093,7 +1096,7 @@ private void ValidateRange(object element, ValidateRangeKind rangeKind) innerException: null, Metadata.ValidateRangeElementType, element.GetType().Name, - typeof(int).Name); + nameof(Int32)); } object resultValue; @@ -1265,7 +1268,7 @@ public sealed class ValidatePatternAttribute : ValidateEnumeratedArgumentsAttrib /// /// Gets or sets the Regex options to be used in the validation. /// - public RegexOptions Options { set; get; } = RegexOptions.IgnoreCase; + public RegexOptions Options { get; set; } = RegexOptions.IgnoreCase; /// /// Gets or sets the custom error message pattern that is displayed to the user. @@ -1532,7 +1535,7 @@ public abstract class CachedValidValuesGeneratorBase : IValidateSetValuesGenerat { // Cached valid values. private string[] _validValues; - private int _validValuesCacheExpiration; + private readonly int _validValuesCacheExpiration; /// /// Initializes a new instance of the class. @@ -1591,11 +1594,11 @@ public sealed class ValidateSetAttribute : ValidateEnumeratedArgumentsAttribute { // We can use either static '_validValues' or dynamic valid values list generated by instance // of 'validValuesGenerator'. - private string[] _validValues; - private IValidateSetValuesGenerator validValuesGenerator = null; + private readonly string[] _validValues; + private readonly IValidateSetValuesGenerator validValuesGenerator = null; // The valid values generator cache works across 'ValidateSetAttribute' instances. - private static ConcurrentDictionary s_ValidValuesGeneratorCache = + private static readonly ConcurrentDictionary s_ValidValuesGeneratorCache = new ConcurrentDictionary(); /// @@ -1619,6 +1622,7 @@ public sealed class ValidateSetAttribute : ValidateEnumeratedArgumentsAttribute /// /// Gets the valid values in the set. /// + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "")] public IList ValidValues { get @@ -1725,20 +1729,23 @@ public ValidateSetAttribute(Type valuesGeneratorType) // Add a valid values generator to the cache. // We don't cache valid values; we expect that valid values will be cached in the generator. validValuesGenerator = s_ValidValuesGeneratorCache.GetOrAdd( - valuesGeneratorType, (key) => (IValidateSetValuesGenerator)Activator.CreateInstance(key)); + valuesGeneratorType, static (key) => (IValidateSetValuesGenerator)Activator.CreateInstance(key)); } } /// /// Allows dynamically generate set of values for /// +#nullable enable public interface IValidateSetValuesGenerator { /// /// Gets valid values. /// + /// A non-null array of non-null strings. string[] GetValidValues(); } +#nullable restore /// /// Validates that each parameter argument is Trusted data. @@ -1821,7 +1828,7 @@ public AllowEmptyCollectionAttribute() { } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class ValidateDriveAttribute : ValidateArgumentsAttribute { - private string[] _validRootDrives; + private readonly string[] _validRootDrives; /// /// Gets the values in the set. @@ -1857,8 +1864,7 @@ protected override void Validate(object arguments, EngineIntrinsics engineIntrin Metadata.ValidateNotNullFailure); } - var path = arguments as string; - if (path == null) + if (!(arguments is string path)) { throw new ValidationMetadataException( "PathArgumentIsNotValid", diff --git a/src/System.Management.Automation/engine/AutomationEngine.cs b/src/System.Management.Automation/engine/AutomationEngine.cs index 38d985c7634..7da8f4200e5 100644 --- a/src/System.Management.Automation/engine/AutomationEngine.cs +++ b/src/System.Management.Automation/engine/AutomationEngine.cs @@ -110,4 +110,3 @@ internal ScriptBlock ParseScriptBlock(string script, string fileName, bool addTo } } } - diff --git a/src/System.Management.Automation/engine/AutomationNull.cs b/src/System.Management.Automation/engine/AutomationNull.cs index 6dec6aeabb7..38016c3c513 100644 --- a/src/System.Management.Automation/engine/AutomationNull.cs +++ b/src/System.Management.Automation/engine/AutomationNull.cs @@ -31,4 +31,3 @@ public static class AutomationNull #endregion public_property } } - diff --git a/src/System.Management.Automation/engine/COM/ComAdapter.cs b/src/System.Management.Automation/engine/COM/ComAdapter.cs index 75e95b6082a..18a87cc71fa 100644 --- a/src/System.Management.Automation/engine/COM/ComAdapter.cs +++ b/src/System.Management.Automation/engine/COM/ComAdapter.cs @@ -32,7 +32,7 @@ internal static string GetComTypeName(string clsid) StringBuilder firstType = new StringBuilder("System.__ComObject"); firstType.Append("#{"); firstType.Append(clsid); - firstType.Append("}"); + firstType.Append('}'); return firstType.ToString(); } diff --git a/src/System.Management.Automation/engine/COM/ComDispatch.cs b/src/System.Management.Automation/engine/COM/ComDispatch.cs index 9199ef9f48f..8e0417e17cc 100644 --- a/src/System.Management.Automation/engine/COM/ComDispatch.cs +++ b/src/System.Management.Automation/engine/COM/ComDispatch.cs @@ -5,6 +5,7 @@ using COM = System.Runtime.InteropServices.ComTypes; +#nullable enable namespace System.Management.Automation { /// @@ -19,7 +20,7 @@ internal interface IDispatch int GetTypeInfoCount(out int info); [PreserveSig] - int GetTypeInfo(int iTInfo, int lcid, out COM.ITypeInfo ppTInfo); + int GetTypeInfo(int iTInfo, int lcid, out COM.ITypeInfo? ppTInfo); void GetIDsOfNames( [MarshalAs(UnmanagedType.LPStruct)] Guid iid, @@ -33,8 +34,8 @@ void Invoke( [MarshalAs(UnmanagedType.LPStruct)] Guid iid, int lcid, COM.INVOKEKIND wFlags, - [In, Out] [MarshalAs(UnmanagedType.LPArray)] COM.DISPPARAMS[] paramArray, - out object pVarResult, + [In, Out][MarshalAs(UnmanagedType.LPArray)] COM.DISPPARAMS[] paramArray, + out object? pVarResult, out ComInvoker.EXCEPINFO pExcepInfo, out uint puArgErr); } diff --git a/src/System.Management.Automation/engine/COM/ComMethod.cs b/src/System.Management.Automation/engine/COM/ComMethod.cs index 32552c6bd14..7f6f3ca8816 100644 --- a/src/System.Management.Automation/engine/COM/ComMethod.cs +++ b/src/System.Management.Automation/engine/COM/ComMethod.cs @@ -30,8 +30,8 @@ internal ComMethodInformation(bool hasvarargs, bool hasoptional, ParameterInform /// internal class ComMethod { - private Collection _methods = new Collection(); - private COM.ITypeInfo _typeInfo; + private readonly Collection _methods = new Collection(); + private readonly COM.ITypeInfo _typeInfo; /// /// Initializes new instance of ComMethod class. @@ -133,4 +133,3 @@ internal object InvokeMethod(PSMethod method, object[] arguments) } } } - diff --git a/src/System.Management.Automation/engine/COM/ComProperty.cs b/src/System.Management.Automation/engine/COM/ComProperty.cs index b36d2717534..9ac1a28656b 100644 --- a/src/System.Management.Automation/engine/COM/ComProperty.cs +++ b/src/System.Management.Automation/engine/COM/ComProperty.cs @@ -22,7 +22,7 @@ internal class ComProperty private int _setterIndex; private int _setterByRefIndex; private int _getterIndex; - private COM.ITypeInfo _typeInfo; + private readonly COM.ITypeInfo _typeInfo; /// /// Initializes a new instance of ComProperty. @@ -366,7 +366,7 @@ public override string ToString() { StringBuilder builder = new StringBuilder(); builder.Append(this.GetDefinition()); - builder.Append(" "); + builder.Append(' '); if (IsGettable) { builder.Append("{get} "); diff --git a/src/System.Management.Automation/engine/COM/ComTypeInfo.cs b/src/System.Management.Automation/engine/COM/ComTypeInfo.cs index 6a03f31c9ac..851325e82ec 100644 --- a/src/System.Management.Automation/engine/COM/ComTypeInfo.cs +++ b/src/System.Management.Automation/engine/COM/ComTypeInfo.cs @@ -30,9 +30,9 @@ internal class ComTypeInfo /// /// Member variables. /// - private Dictionary _properties = null; - private Dictionary _methods = null; - private COM.ITypeInfo _typeinfo = null; + private readonly Dictionary _properties = null; + private readonly Dictionary _methods = null; + private readonly COM.ITypeInfo _typeinfo = null; private Guid _guid = Guid.Empty; /// @@ -307,4 +307,3 @@ internal static COM.ITypeInfo GetDispatchTypeInfoFromCoClassTypeInfo(COM.ITypeIn } } } - diff --git a/src/System.Management.Automation/engine/COM/ComUtil.cs b/src/System.Management.Automation/engine/COM/ComUtil.cs index 1ba9d9099b2..e244e4cdf3f 100644 --- a/src/System.Management.Automation/engine/COM/ComUtil.cs +++ b/src/System.Management.Automation/engine/COM/ComUtil.cs @@ -16,7 +16,7 @@ namespace System.Management.Automation /// /// Defines a utility class that is used by COM adapter. /// - internal class ComUtil + internal static class ComUtil { // HResult error code '-2147352573' - Member not found. internal const int DISP_E_MEMBERNOTFOUND = unchecked((int)0x80020003); @@ -97,7 +97,7 @@ internal static string GetMethodSignatureFromFuncDesc(COM.ITypeInfo typeinfo, CO } } - builder.Append(")"); + builder.Append(')'); return builder.ToString(); } diff --git a/src/System.Management.Automation/engine/ChildrenCmdletProviderInterfaces.cs b/src/System.Management.Automation/engine/ChildrenCmdletProviderInterfaces.cs index 85cff4c8efb..57c871b2f76 100644 --- a/src/System.Management.Automation/engine/ChildrenCmdletProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/ChildrenCmdletProviderInterfaces.cs @@ -761,8 +761,8 @@ internal bool HasChild( #region private data - private Cmdlet _cmdlet; - private SessionStateInternal _sessionState; + private readonly Cmdlet _cmdlet; + private readonly SessionStateInternal _sessionState; #endregion private data } @@ -784,4 +784,3 @@ public enum ReturnContainers ReturnAllContainers } } - diff --git a/src/System.Management.Automation/engine/CmdletFamilyProviderInterfaces.cs b/src/System.Management.Automation/engine/CmdletFamilyProviderInterfaces.cs index 27537b21601..061b630d353 100644 --- a/src/System.Management.Automation/engine/CmdletFamilyProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/CmdletFamilyProviderInterfaces.cs @@ -102,9 +102,8 @@ internal ProviderIntrinsics(SessionStateInternal sessionState) #region private data - private InternalCommand _cmdlet; + private readonly InternalCommand _cmdlet; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/CmdletInfo.cs b/src/System.Management.Automation/engine/CmdletInfo.cs index 2861fa3a8b6..05b7548f9fc 100644 --- a/src/System.Management.Automation/engine/CmdletInfo.cs +++ b/src/System.Management.Automation/engine/CmdletInfo.cs @@ -149,7 +149,7 @@ public string Verb } } - private string _verb = string.Empty; + private readonly string _verb = string.Empty; /// /// Gets the noun of the cmdlet. @@ -162,7 +162,7 @@ public string Noun } } - private string _noun = string.Empty; + private readonly string _noun = string.Empty; internal static bool SplitCmdletName(string name, out string verb, out string noun) { @@ -224,7 +224,7 @@ public PSSnapInInfo PSSnapIn } } - private PSSnapInInfo _PSSnapin; + private readonly PSSnapInInfo _PSSnapin; /// /// Gets the name of the PSSnapin the cmdlet is implemented in. @@ -279,7 +279,7 @@ public Type ImplementingType } } - private Type _implementingType = null; + private readonly Type _implementingType = null; /// /// Gets the synopsis of the cmdlet. @@ -535,8 +535,7 @@ internal override CommandMetadata CommandMetadata { get { - return _cmdletMetadata ?? - (_cmdletMetadata = CommandMetadata.Get(this.Name, this.ImplementingType, Context)); + return _cmdletMetadata ??= CommandMetadata.Get(this.Name, this.ImplementingType, Context); } } @@ -548,7 +547,7 @@ internal override bool ImplementsDynamicParameters { if (ImplementingType != null) { - return (ImplementingType.GetInterface(typeof(IDynamicParameters).Name, true) != null); + return (ImplementingType.GetInterface(nameof(IDynamicParameters), true) != null); } else { diff --git a/src/System.Management.Automation/engine/CmdletParameterBinderController.cs b/src/System.Management.Automation/engine/CmdletParameterBinderController.cs index eeccc290883..8f853610447 100644 --- a/src/System.Management.Automation/engine/CmdletParameterBinderController.cs +++ b/src/System.Management.Automation/engine/CmdletParameterBinderController.cs @@ -626,8 +626,7 @@ private Dictionary GetDefaultParameterVa foreach (DictionaryEntry entry in DefaultParameterValues) { - string key = entry.Key as string; - if (key == null) + if (!(entry.Key is string key)) { continue; } @@ -2451,7 +2450,7 @@ private void IgnoreOtherMandatoryParameterSets(uint otherMandatorySetsToBeIgnore } } - private uint NewParameterSetPromptingData( + private static uint NewParameterSetPromptingData( Dictionary promptingData, MergedCompiledCommandParameter parameter, ParameterSetSpecificMetadata parameterSetMetadata, @@ -2662,7 +2661,7 @@ Cmdlet command IEnumerable allParameterSetMetadatas = boundParameters.Values .Concat(unboundParameters) - .SelectMany(p => p.Parameter.ParameterSetData.Values); + .SelectMany(static p => p.Parameter.ParameterSetData.Values); uint allParameterSetFlags = 0; foreach (ParameterSetSpecificMetadata parameterSetMetadata in allParameterSetMetadatas) { @@ -2676,8 +2675,8 @@ Cmdlet command "This method should only be called when there is an ambiguity wrt parameter sets"); IEnumerable parameterSetMetadatasForUnboundMandatoryParameters = unboundParameters - .SelectMany(p => p.Parameter.ParameterSetData.Values) - .Where(p => p.IsMandatory); + .SelectMany(static p => p.Parameter.ParameterSetData.Values) + .Where(static p => p.IsMandatory); foreach (ParameterSetSpecificMetadata parameterSetMetadata in parameterSetMetadatasForUnboundMandatoryParameters) { remainingParameterSetsWithNoMandatoryUnboundParameters &= (~parameterSetMetadata.ParameterSetFlag); @@ -3928,8 +3927,7 @@ private HashSet BoundObsoleteParameterNames { get { - return _boundObsoleteParameterNames ?? - (_boundObsoleteParameterNames = new HashSet(StringComparer.OrdinalIgnoreCase)); + return _boundObsoleteParameterNames ??= new HashSet(StringComparer.OrdinalIgnoreCase); } } @@ -4049,7 +4047,7 @@ internal ReflectionParameterBinder CommonParametersBinder private ReflectionParameterBinder _commonParametersBinder; - private class DelayedScriptBlockArgument + private sealed class DelayedScriptBlockArgument { // Remember the parameter binder so we know when to invoke the script block // and when to use the evaluated argument. @@ -4119,7 +4117,7 @@ private bool BindPipelineParameter( /*argumentAst*/null, parameterValue, false); - flags = flags & ~ParameterBindingFlags.DelayBindScriptBlock; + flags &= ~ParameterBindingFlags.DelayBindScriptBlock; result = BindParameter(_currentParameterSetFlag, param, parameter, flags); if (result) @@ -4224,7 +4222,7 @@ private void RestoreDefaultParameterValues(IEnumerable) - (*(*(void***)dispatchPointer + 6 /* IDispatch.Invoke slot */)); + var pfnIDispatchInvoke = (delegate* unmanaged)(*(*(void***)dispatchPointer + 6 /* IDispatch.Invoke slot */)); int hresult = pfnIDispatchInvoke(dispatchPointer, memberDispId, &IID_NULL, 0, (ushort)flags, pDispParams, pResult, pExcepInfo, pArgErr); diff --git a/src/System.Management.Automation/engine/ComInterop/ComTypeClassDesc.cs b/src/System.Management.Automation/engine/ComInterop/ComTypeClassDesc.cs index 1ff4fac18cf..fdf0751d85c 100644 --- a/src/System.Management.Automation/engine/ComInterop/ComTypeClassDesc.cs +++ b/src/System.Management.Automation/engine/ComInterop/ComTypeClassDesc.cs @@ -24,8 +24,7 @@ public object CreateInstance() return Activator.CreateInstance(Type.GetTypeFromCLSID(Guid)); } - internal ComTypeClassDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) : - base(typeInfo, typeLibDesc) + internal ComTypeClassDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) : base(typeInfo, typeLibDesc) { ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); Guid = typeAttr.guid; diff --git a/src/System.Management.Automation/engine/ComInterop/ComTypeDesc.cs b/src/System.Management.Automation/engine/ComInterop/ComTypeDesc.cs index 92e9ea8ed6f..a4b90913e9b 100644 --- a/src/System.Management.Automation/engine/ComInterop/ComTypeDesc.cs +++ b/src/System.Management.Automation/engine/ComInterop/ComTypeDesc.cs @@ -118,6 +118,7 @@ internal bool TryGetPutRef(string name, out ComMethodDesc method) method = null; return false; } + internal void AddPutRef(string name, ComMethodDesc method) { name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); diff --git a/src/System.Management.Automation/engine/ComInterop/ComTypeEnumDesc.cs b/src/System.Management.Automation/engine/ComInterop/ComTypeEnumDesc.cs index 5752fac1e5f..1f59dc475e5 100644 --- a/src/System.Management.Automation/engine/ComInterop/ComTypeEnumDesc.cs +++ b/src/System.Management.Automation/engine/ComInterop/ComTypeEnumDesc.cs @@ -20,8 +20,7 @@ public override string ToString() return string.Format(CultureInfo.CurrentCulture, "", TypeName); } - internal ComTypeEnumDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) : - base(typeInfo, typeLibDesc) + internal ComTypeEnumDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) : base(typeInfo, typeLibDesc) { ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); string[] memberNames = new string[typeAttr.cVars]; diff --git a/src/System.Management.Automation/engine/ComInterop/IDispatchComObject.cs b/src/System.Management.Automation/engine/ComInterop/IDispatchComObject.cs index bf4c3f021f0..c3a16639b62 100644 --- a/src/System.Management.Automation/engine/ComInterop/IDispatchComObject.cs +++ b/src/System.Management.Automation/engine/ComInterop/IDispatchComObject.cs @@ -449,7 +449,7 @@ private static void ScanSourceInterface(ComTypes.ITypeInfo sourceTypeInfo, ref D // adding new events and putting them on new interfaces while keeping the // old interfaces around. This may cause name collisions which we are // resolving by keeping only the first event with the same name. - if (events.ContainsKey(name) == false) + if (!events.ContainsKey(name)) { ComEventDesc eventDesc = new ComEventDesc { diff --git a/src/System.Management.Automation/engine/ComInterop/InteropServices/Variant.cs b/src/System.Management.Automation/engine/ComInterop/InteropServices/Variant.cs index 24405957f72..84a31b26426 100644 --- a/src/System.Management.Automation/engine/ComInterop/InteropServices/Variant.cs +++ b/src/System.Management.Automation/engine/ComInterop/InteropServices/Variant.cs @@ -343,6 +343,7 @@ public sbyte AsI1 Debug.Assert(VariantType == VarEnum.VT_I1); return _typeUnion._unionTypes._i1; } + set { Debug.Assert(IsEmpty); @@ -360,6 +361,7 @@ public short AsI2 Debug.Assert(VariantType == VarEnum.VT_I2); return _typeUnion._unionTypes._i2; } + set { Debug.Assert(IsEmpty); @@ -377,6 +379,7 @@ public int AsI4 Debug.Assert(VariantType == VarEnum.VT_I4); return _typeUnion._unionTypes._i4; } + set { Debug.Assert(IsEmpty); @@ -394,6 +397,7 @@ public long AsI8 Debug.Assert(VariantType == VarEnum.VT_I8); return _typeUnion._unionTypes._i8; } + set { Debug.Assert(IsEmpty); @@ -411,6 +415,7 @@ public byte AsUi1 Debug.Assert(VariantType == VarEnum.VT_UI1); return _typeUnion._unionTypes._ui1; } + set { Debug.Assert(IsEmpty); @@ -428,6 +433,7 @@ public ushort AsUi2 Debug.Assert(VariantType == VarEnum.VT_UI2); return _typeUnion._unionTypes._ui2; } + set { Debug.Assert(IsEmpty); @@ -445,6 +451,7 @@ public uint AsUi4 Debug.Assert(VariantType == VarEnum.VT_UI4); return _typeUnion._unionTypes._ui4; } + set { Debug.Assert(IsEmpty); @@ -462,6 +469,7 @@ public ulong AsUi8 Debug.Assert(VariantType == VarEnum.VT_UI8); return _typeUnion._unionTypes._ui8; } + set { Debug.Assert(IsEmpty); @@ -479,6 +487,7 @@ public int AsInt Debug.Assert(VariantType == VarEnum.VT_INT); return _typeUnion._unionTypes._int; } + set { Debug.Assert(IsEmpty); @@ -496,6 +505,7 @@ public uint AsUint Debug.Assert(VariantType == VarEnum.VT_UINT); return _typeUnion._unionTypes._uint; } + set { Debug.Assert(IsEmpty); @@ -513,6 +523,7 @@ public bool AsBool Debug.Assert(VariantType == VarEnum.VT_BOOL); return _typeUnion._unionTypes._bool != 0; } + set { Debug.Assert(IsEmpty); @@ -532,6 +543,7 @@ public int AsError Debug.Assert(VariantType == VarEnum.VT_ERROR); return _typeUnion._unionTypes._error; } + set { Debug.Assert(IsEmpty); @@ -549,6 +561,7 @@ public float AsR4 Debug.Assert(VariantType == VarEnum.VT_R4); return _typeUnion._unionTypes._r4; } + set { Debug.Assert(IsEmpty); @@ -566,6 +579,7 @@ public double AsR8 Debug.Assert(VariantType == VarEnum.VT_R8); return _typeUnion._unionTypes._r8; } + set { Debug.Assert(IsEmpty); @@ -586,6 +600,7 @@ public decimal AsDecimal v._typeUnion._vt = 0; return v._decimal; } + set { Debug.Assert(IsEmpty); @@ -605,6 +620,7 @@ public decimal AsCy Debug.Assert(VariantType == VarEnum.VT_CY); return decimal.FromOACurrency(_typeUnion._unionTypes._cy); } + set { Debug.Assert(IsEmpty); @@ -622,6 +638,7 @@ public DateTime AsDate Debug.Assert(VariantType == VarEnum.VT_DATE); return DateTime.FromOADate(_typeUnion._unionTypes._date); } + set { Debug.Assert(IsEmpty); @@ -639,6 +656,7 @@ public string AsBstr Debug.Assert(VariantType == VarEnum.VT_BSTR); return (string)Marshal.PtrToStringBSTR(this._typeUnion._unionTypes._bstr); } + set { Debug.Assert(IsEmpty); @@ -660,6 +678,7 @@ public object? AsUnknown } return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._unknown); } + set { Debug.Assert(IsEmpty); @@ -688,6 +707,7 @@ public object? AsDispatch } return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._dispatch); } + set { Debug.Assert(IsEmpty); diff --git a/src/System.Management.Automation/engine/ComInterop/SplatCallSite.cs b/src/System.Management.Automation/engine/ComInterop/SplatCallSite.cs index 68c394033fc..ecbff91a36c 100644 --- a/src/System.Management.Automation/engine/ComInterop/SplatCallSite.cs +++ b/src/System.Management.Automation/engine/ComInterop/SplatCallSite.cs @@ -24,6 +24,7 @@ internal SplatCallSite(object callable) } public delegate object InvokeDelegate(object[] args); + internal object Invoke(object[] args) { Debug.Assert(args != null); diff --git a/src/System.Management.Automation/engine/ComInterop/TypeUtils.cs b/src/System.Management.Automation/engine/ComInterop/TypeUtils.cs index 0d4ee61dcf7..041d7ccfd07 100644 --- a/src/System.Management.Automation/engine/ComInterop/TypeUtils.cs +++ b/src/System.Management.Automation/engine/ComInterop/TypeUtils.cs @@ -38,6 +38,7 @@ internal static bool AreReferenceAssignable(Type dest, Type src) } return false; } + //CONFORMING internal static bool AreAssignable(Type dest, Type src) { diff --git a/src/System.Management.Automation/engine/ComInterop/VariantArray.cs b/src/System.Management.Automation/engine/ComInterop/VariantArray.cs index 83ea62e51f4..a196eb96079 100644 --- a/src/System.Management.Automation/engine/ComInterop/VariantArray.cs +++ b/src/System.Management.Automation/engine/ComInterop/VariantArray.cs @@ -74,7 +74,7 @@ internal static Type GetStructType(int args) // See if we can find an existing type foreach (Type t in s_generatedTypes) { - int arity = int.Parse(t.Name.AsSpan("VariantArray".Length), NumberStyles.Integer, CultureInfo.InvariantCulture); + int arity = int.Parse(t.Name.AsSpan("VariantArray".Length), NumberStyles.Integer, CultureInfo.InvariantCulture); if (size == arity) { return t; diff --git a/src/System.Management.Automation/engine/ComInterop/VariantBuilder.cs b/src/System.Management.Automation/engine/ComInterop/VariantBuilder.cs index edcb0eb0f10..baabb25cd75 100644 --- a/src/System.Management.Automation/engine/ComInterop/VariantBuilder.cs +++ b/src/System.Management.Automation/engine/ComInterop/VariantBuilder.cs @@ -16,6 +16,7 @@ internal class VariantBuilder private MemberExpression _variant; private readonly ArgBuilder _argBuilder; private readonly VarEnum _targetComType; + internal ParameterExpression TempVariable { get; private set; } internal VariantBuilder(VarEnum targetComType, ArgBuilder builder) diff --git a/src/System.Management.Automation/engine/CommandBase.cs b/src/System.Management.Automation/engine/CommandBase.cs index b2019ec90dd..048eafd56c8 100644 --- a/src/System.Management.Automation/engine/CommandBase.cs +++ b/src/System.Management.Automation/engine/CommandBase.cs @@ -76,7 +76,7 @@ internal InternalCommand() /// The invocation object for this command. internal InvocationInfo MyInvocation { - get { return _myInvocation ?? (_myInvocation = new InvocationInfo(this)); } + get { return _myInvocation ??= new InvocationInfo(this); } } /// @@ -89,7 +89,10 @@ internal InvocationInfo MyInvocation /// internal PSObject CurrentPipelineObject { - get { return currentObjectInPipeline; } + get + { + return currentObjectInPipeline; + } set { @@ -155,7 +158,10 @@ internal CommandInfo CommandInfo /// internal ExecutionContext Context { - get { return _context; } + get + { + return _context; + } set { @@ -266,6 +272,26 @@ internal void InternalDispose(bool isDisposing) namespace System.Management.Automation { + #region NativeArgumentPassingStyle + /// + /// Defines the different native command argument parsing options. + /// + public enum NativeArgumentPassingStyle + { + /// Use legacy argument parsing via ProcessStartInfo.Arguments. + Legacy = 0, + + /// Use new style argument passing via ProcessStartInfo.ArgumentList. + Standard = 1, + + /// + /// Use specific to Windows passing style which is Legacy for selected files on Windows, but + /// Standard for everything else. This is the default behavior for Windows. + /// + Windows = 2 + } + #endregion NativeArgumentPassingStyle + #region ErrorView /// /// Defines the potential ErrorView options. @@ -280,6 +306,9 @@ public enum ErrorView /// Concise shows more information on the context of the error or just the message if not a script or parser error. ConciseView = 2, + + /// Detailed will leverage Get-Error to get much more detailed information for the error. + DetailedView = 3, } #endregion ErrorView @@ -470,7 +499,7 @@ public ProviderIntrinsics InvokeProvider { using (PSTransactionManager.GetEngineProtectionScope()) { - return _invokeProvider ?? (_invokeProvider = new ProviderIntrinsics(this)); + return _invokeProvider ??= new ProviderIntrinsics(this); } } } @@ -560,4 +589,3 @@ public object GetVariableValue(string name, object defaultValue) #endregion public_methods } } - diff --git a/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs b/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs index e00e0d737fc..0549f93e266 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs @@ -157,7 +157,7 @@ public static CommandCompletion CompleteInput(string input, int cursorIndex, Has } // If we are in a debugger stop, let the debugger do the command completion. - var debugger = (powershell.Runspace != null) ? powershell.Runspace.Debugger : null; + var debugger = powershell.Runspace?.Debugger; if ((debugger != null) && debugger.InBreakpoint) { return CompleteInputInDebugger(input, cursorIndex, options, debugger); @@ -236,7 +236,7 @@ public static CommandCompletion CompleteInput(Ast ast, Token[] tokens, IScriptPo } // If we are in a debugger stop, let the debugger do the command completion. - var debugger = (powershell.Runspace != null) ? powershell.Runspace.Debugger : null; + var debugger = powershell.Runspace?.Debugger; if ((debugger != null) && debugger.InBreakpoint) { return CompleteInputInDebugger(ast, tokens, cursorPosition, options, debugger); @@ -526,74 +526,70 @@ private static CommandCompletion CompleteInputImpl(Ast ast, Token[] tokens, IScr { var context = LocalPipeline.GetExecutionContextFromTLS(); - bool cleanupModuleAnalysisAppDomain = context.TakeResponsibilityForModuleAnalysisAppDomain(); + // First, check if a V1/V2 implementation of TabExpansion exists. If so, the user had overridden + // the built-in version, so we should continue to use theirs. + int replacementIndex = -1; + int replacementLength = -1; + List results = null; - try + if (NeedToInvokeLegacyTabExpansion(powershell)) { - // First, check if a V1/V2 implementation of TabExpansion exists. If so, the user had overridden - // the built-in version, so we should continue to use theirs. - int replacementIndex = -1; - int replacementLength = -1; - List results = null; + var inputAndCursor = GetInputAndCursorFromAst(positionOfCursor); + results = InvokeLegacyTabExpansion(powershell, inputAndCursor.Item1, inputAndCursor.Item2, false, out replacementIndex, out replacementLength); + replacementIndex += inputAndCursor.Item3; + } - if (NeedToInvokeLegacyTabExpansion(powershell)) + if (results == null || results.Count == 0) + { + /* BROKEN code commented out, fix sometime + // If we were invoked from TabExpansion2, we want to "remove" TabExpansion2 and anything it calls + // from our results. We do this by faking out the session so that TabExpansion2 isn't anywhere to be found. + MutableTuple tupleForFrameToSkipPast = null; + foreach (var stackEntry in context.Debugger.GetCallStack()) { - var inputAndCursor = GetInputAndCursorFromAst(positionOfCursor); - results = InvokeLegacyTabExpansion(powershell, inputAndCursor.Item1, inputAndCursor.Item2, false, out replacementIndex, out replacementLength); - replacementIndex += inputAndCursor.Item3; + dynamic stackEntryAsPSObj = PSObject.AsPSObject(stackEntry); + if (stackEntryAsPSObj.Command.Equals("TabExpansion2", StringComparison.OrdinalIgnoreCase)) + { + tupleForFrameToSkipPast = stackEntry.FunctionContext._localsTuple; + break; + } } - if (results == null || results.Count == 0) + SessionStateScope scopeToRestore = null; + if (tupleForFrameToSkipPast != null) { - /* BROKEN code commented out, fix sometime - // If we were invoked from TabExpansion2, we want to "remove" TabExpansion2 and anything it calls - // from our results. We do this by faking out the session so that TabExpansion2 isn't anywhere to be found. - MutableTuple tupleForFrameToSkipPast = null; - foreach (var stackEntry in context.Debugger.GetCallStack()) + // Find this tuple in the scope stack. + scopeToRestore = context.EngineSessionState.CurrentScope; + var scope = context.EngineSessionState.CurrentScope; + while (scope != null && scope.LocalsTuple != tupleForFrameToSkipPast) { - dynamic stackEntryAsPSObj = PSObject.AsPSObject(stackEntry); - if (stackEntryAsPSObj.Command.Equals("TabExpansion2", StringComparison.OrdinalIgnoreCase)) - { - tupleForFrameToSkipPast = stackEntry.FunctionContext._localsTuple; - break; - } + scope = scope.Parent; } - SessionStateScope scopeToRestore = null; - if (tupleForFrameToSkipPast != null) + if (scope != null) { - // Find this tuple in the scope stack. - scopeToRestore = context.EngineSessionState.CurrentScope; - var scope = context.EngineSessionState.CurrentScope; - while (scope != null && scope.LocalsTuple != tupleForFrameToSkipPast) - { - scope = scope.Parent; - } - - if (scope != null) - { - context.EngineSessionState.CurrentScope = scope.Parent; - } + context.EngineSessionState.CurrentScope = scope.Parent; } + } - try - { - */ - var completionAnalysis = new CompletionAnalysis(ast, tokens, positionOfCursor, options); - results = completionAnalysis.GetResults(powershell, out replacementIndex, out replacementLength); - /* - } - finally + try + { + */ + var completionAnalysis = new CompletionAnalysis(ast, tokens, positionOfCursor, options); + results = completionAnalysis.GetResults(powershell, out replacementIndex, out replacementLength); + /* + } + finally + { + if (scopeToRestore != null) { - if (scopeToRestore != null) - { - context.EngineSessionState.CurrentScope = scopeToRestore; - } + context.EngineSessionState.CurrentScope = scopeToRestore; } - */ } + */ + } - var completionResults = results ?? EmptyCompletionResult; + var completionResults = results ?? EmptyCompletionResult; #if LEGACYTELEMETRY // no telemetry here. We don't capture tab completion performance. @@ -601,19 +597,11 @@ private static CommandCompletion CompleteInputImpl(Ast ast, Token[] tokens, IScr TelemetryAPI.ReportTabCompletionTelemetry(sw.ElapsedMilliseconds, completionResults.Count, completionResults.Count > 0 ? completionResults[0].ResultType : CompletionResultType.Text); #endif - return new CommandCompletion( - new Collection(completionResults), - -1, - replacementIndex, - replacementLength); - } - finally - { - if (cleanupModuleAnalysisAppDomain) - { - context.ReleaseResponsibilityForModuleAnalysisAppDomain(); - } - } + return new CommandCompletion( + new Collection(completionResults), + -1, + replacementIndex, + replacementLength); } } @@ -740,7 +728,7 @@ private static bool PSv2IsCommandLikeCmdlet(string lastWord, out bool isSnapinSp return false; } - private struct CommandAndName + private readonly struct CommandAndName { internal readonly PSObject Command; internal readonly PSSnapinQualifiedName CommandName; @@ -891,7 +879,7 @@ internal static List PSv2GenerateMatchSetOfFiles(PowerShellExe // Determine if we need to quote the paths we parse - lastWord = lastWord ?? string.Empty; + lastWord ??= string.Empty; bool isLastWordEmpty = string.IsNullOrEmpty(lastWord); bool lastCharIsStar = !isLastWordEmpty && lastWord.EndsWith('*'); bool containsGlobChars = WildcardPattern.ContainsWildcardCharacters(lastWord); @@ -1067,7 +1055,7 @@ private static bool PSv2ShouldFullyQualifyPathsPath(PowerShellExecutionHelper he return isAbsolute; } - private struct PathItemAndConvertedPath + private readonly struct PathItemAndConvertedPath { internal readonly string Path; internal readonly PSObject Item; @@ -1137,11 +1125,11 @@ private static List PSv2FindMatches(PowerShellExecutio return null; } - result.Sort(delegate (PathItemAndConvertedPath x, PathItemAndConvertedPath y) - { - Diagnostics.Assert(x.Path != null && y.Path != null, "SafeToString always returns a non-null string"); - return string.Compare(x.Path, y.Path, StringComparison.CurrentCultureIgnoreCase); - }); + result.Sort((PathItemAndConvertedPath x, PathItemAndConvertedPath y) => + { + Diagnostics.Assert(x.Path != null && y.Path != null, "SafeToString always returns a non-null string"); + return string.Compare(x.Path, y.Path, StringComparison.CurrentCultureIgnoreCase); + }); return result; } @@ -1153,7 +1141,7 @@ private static List PSv2FindMatches(PowerShellExecutio /// LastWordFinder implements the algorithm we use to search for the last word in a line of input taken from the console. /// This class exists for legacy purposes only - V3 and forward uses a slightly different interface. /// - private class LastWordFinder + private sealed class LastWordFinder { internal static string FindLastWord(string sentence, out int replacementIndexOut, out char closingQuote) { @@ -1301,7 +1289,10 @@ private void Consume(char c) private int ReplacementIndex { - get { return _replacementIndex; } + get + { + return _replacementIndex; + } set { diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs index db32f5de184..76be6418805 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs @@ -9,6 +9,8 @@ using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.DSC; namespace System.Management.Automation { @@ -20,18 +22,29 @@ internal class CompletionContext // This is how we can tell if we're trying to complete part of something (like a member) // or complete an argument, where TokenBeforeCursor could be a parameter name. internal Token TokenAtCursor { get; set; } + internal Token TokenBeforeCursor { get; set; } + internal IScriptPosition CursorPosition { get; set; } internal PowerShellExecutionHelper Helper { get; set; } + internal Hashtable Options { get; set; } + internal Dictionary CustomArgumentCompleters { get; set; } + internal Dictionary NativeArgumentCompleters { get; set; } + internal string WordToComplete { get; set; } + internal int ReplacementIndex { get; set; } + internal int ReplacementLength { get; set; } + internal ExecutionContext ExecutionContext { get; set; } + internal PseudoBindingInfo PseudoBindingInfo { get; set; } + internal TypeInferenceContext TypeInferenceContext { get; set; } internal bool GetOption(string option, bool @default) @@ -239,8 +252,7 @@ private static bool CompleteAgainstSwitchFile(Ast lastAst, Token tokenBeforeCurs if (lastAst.Parent is CommandExpressionAst) { // Handle "switch -file m" or "switch -file *.ps1" - var pipeline = lastAst.Parent.Parent as PipelineAst; - if (pipeline == null) + if (!(lastAst.Parent.Parent is PipelineAst pipeline)) { return false; } @@ -463,7 +475,7 @@ internal List GetResultHelper(CompletionContext completionCont break; completionContext.WordToComplete = tokenAtCursor.Text; - result = CompletionCompleters.CompleteComment(completionContext); + result = CompletionCompleters.CompleteComment(completionContext, ref replacementIndex, ref replacementLength); break; case TokenKind.StringExpandable: @@ -516,6 +528,12 @@ internal List GetResultHelper(CompletionContext completionCont result = CompletionCompleters.CompleteCommandArgument(completionContext); } + else if (lastAst is AttributeAst) + { + completionContext.ReplacementIndex = replacementIndex += tokenAtCursor.Text.Length; + completionContext.ReplacementLength = replacementLength = 0; + result = GetResultForAttributeArgument(completionContext, ref replacementIndex, ref replacementLength); + } else { // @@ -627,7 +645,7 @@ internal List GetResultHelper(CompletionContext completionCont completionContext.ReplacementLength = replacementLength = 0; result = GetResultForAttributeArgument(completionContext, ref replacementIndex, ref replacementLength); } - else if (lastAst is HashtableAst hashTableAst && !(lastAst.Parent is DynamicKeywordStatementAst) && CheckForPendingAssignment(hashTableAst)) + else if (lastAst is HashtableAst hashTableAst && lastAst.Parent is not DynamicKeywordStatementAst && CheckForPendingAssignment(hashTableAst)) { // Handle scenarios such as 'gci | Format-Table @{Label=' if incomplete parsing of the assignment. return null; @@ -810,6 +828,7 @@ internal List GetResultHelper(CompletionContext completionCont case TokenKind.Equals: case TokenKind.Comma: case TokenKind.AtParen: + case TokenKind.LParen: { if (lastAst is AssignmentStatementAst assignmentAst) { @@ -820,24 +839,17 @@ internal List GetResultHelper(CompletionContext completionCont } } + if (lastAst is AttributeAst) + { + completionContext.ReplacementLength = replacementLength = 0; + result = GetResultForAttributeArgument(completionContext, ref replacementIndex, ref replacementLength); + break; + } + bool unused; result = GetResultForEnumPropertyValueOfDSCResource(completionContext, string.Empty, ref replacementIndex, ref replacementLength, out unused); break; } - case TokenKind.LParen: - if (lastAst is AttributeAst) - { - completionContext.ReplacementLength = replacementLength = 0; - result = GetResultForAttributeArgument(completionContext, ref replacementIndex, ref replacementLength); - } - else - { - bool unused; - result = GetResultForEnumPropertyValueOfDSCResource(completionContext, string.Empty, - ref replacementIndex, ref replacementLength, out unused); - } - - break; default: break; } @@ -926,7 +938,7 @@ internal List GetResultHelper(CompletionContext completionCont } // Helper method to auto complete hashtable key - private List GetResultForHashtable(CompletionContext completionContext) + private static List GetResultForHashtable(CompletionContext completionContext) { var lastAst = completionContext.RelatedAsts.Last(); HashtableAst tempHashtableAst = null; @@ -987,7 +999,7 @@ private List GetResultForHashtable(CompletionContext completio } // Helper method to look for an incomplete assignment pair in hash table. - private bool CheckForPendingAssignment(HashtableAst hashTableAst) + private static bool CheckForPendingAssignment(HashtableAst hashTableAst) { foreach (var keyValue in hashTableAst.KeyValuePairs) { @@ -1055,7 +1067,7 @@ private static string GetFirstLineSubString(string stringToComplete, out bool ha return stringToComplete; } - private Tuple GetHashEntryContainsCursor( + private static Tuple GetHashEntryContainsCursor( IScriptPosition cursor, HashtableAst hashTableAst, bool isCursorInString) @@ -1346,7 +1358,7 @@ private static List GetResultForEnum( return GetMatchedResults(allNames, completionContext); } - private List GetResultForEnumPropertyValueOfDSCResource( + private static List GetResultForEnumPropertyValueOfDSCResource( CompletionContext completionContext, string stringToComplete, ref int replacementIndex, @@ -1431,7 +1443,7 @@ private List GetResultForEnumPropertyValueOfDSCResource( Diagnostics.Assert(isCursorInString || (!hasNewLine), "hasNoQuote and hasNewLine cannot be true at the same time"); if (property.ValueMap != null && property.ValueMap.Count > 0) { - IEnumerable orderedValues = property.ValueMap.Keys.OrderBy(x => x).Where(v => !existingValues.Contains(v, StringComparer.OrdinalIgnoreCase)); + IEnumerable orderedValues = property.ValueMap.Keys.OrderBy(static x => x).Where(v => !existingValues.Contains(v, StringComparer.OrdinalIgnoreCase)); var matchedResults = orderedValues.Where(v => wildcardPattern.IsMatch(v)); if (matchedResults == null || !matchedResults.Any()) { @@ -1443,7 +1455,7 @@ private List GetResultForEnumPropertyValueOfDSCResource( { string completionText = isCursorInString ? value : stringQuote + value + stringQuote; if (hasNewLine) - completionText = completionText + stringQuote; + completionText += stringQuote; result.Add(new CompletionResult( completionText, value, @@ -1471,7 +1483,7 @@ private List GetResultForEnumPropertyValueOfDSCResource( { StringBuilder sb = new StringBuilder("[", 50); sb.Append(dynamicKeywordAst.Keyword.Keyword); - sb.Append("]"); + sb.Append(']'); sb.Append(dynamicKeywordAst.ElementName); var resource = sb.ToString(); if (!existingValues.Contains(resource, StringComparer.OrdinalIgnoreCase) && @@ -1494,7 +1506,7 @@ private List GetResultForEnumPropertyValueOfDSCResource( { string completionText = isCursorInString ? resource : stringQuote + resource + stringQuote; if (hasNewLine) - completionText = completionText + stringQuote; + completionText += stringQuote; result.Add(new CompletionResult( completionText, resource, @@ -1633,7 +1645,7 @@ private List GetResultForString(CompletionContext completionCo /// /// /// - private ConfigurationDefinitionAst GetAncestorConfigurationAstAndKeywordAst( + private static ConfigurationDefinitionAst GetAncestorConfigurationAstAndKeywordAst( IScriptPosition cursorPosition, Ast ast, out DynamicKeywordStatementAst keywordAst) @@ -1669,7 +1681,7 @@ private ConfigurationDefinitionAst GetAncestorConfigurationAstAndKeywordAst( /// /// /// - private List GetResultForIdentifierInConfiguration( + private static List GetResultForIdentifierInConfiguration( CompletionContext completionContext, ConfigurationDefinitionAst configureAst, DynamicKeywordStatementAst keywordAst, @@ -1711,7 +1723,17 @@ private List GetResultForIdentifierInConfiguration( foreach (var keyword in matchedResults) { - string usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword); + string usageString = string.Empty; + ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem(); + if (dscSubsystem != null) + { + usageString = dscSubsystem.GetDSCResourceUsageString(keyword); + } + else + { + usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword); + } + if (results == null) { results = new List(); @@ -2083,12 +2105,12 @@ private List GetResultForIdentifier(CompletionContext completi return result; } - private List GetResultForAttributeArgument(CompletionContext completionContext, ref int replacementIndex, ref int replacementLength) + private static List GetResultForAttributeArgument(CompletionContext completionContext, ref int replacementIndex, ref int replacementLength) { // Attribute member arguments Type attributeType = null; string argName = string.Empty; - Ast argAst = completionContext.RelatedAsts.Find(ast => ast is NamedAttributeArgumentAst); + Ast argAst = completionContext.RelatedAsts.Find(static ast => ast is NamedAttributeArgumentAst); NamedAttributeArgumentAst namedArgAst = argAst as NamedAttributeArgumentAst; if (argAst != null && namedArgAst != null) { @@ -2099,7 +2121,7 @@ private List GetResultForAttributeArgument(CompletionContext c } else { - Ast astAtt = completionContext.RelatedAsts.Find(ast => ast is AttributeAst); + Ast astAtt = completionContext.RelatedAsts.Find(static ast => ast is AttributeAst); AttributeAst attAst = astAtt as AttributeAst; if (astAtt != null && attAst != null) { diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index a3c5b2053ef..d8360e714d8 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -24,6 +24,7 @@ using Microsoft.PowerShell; using Microsoft.PowerShell.Cim; using Microsoft.PowerShell.Commands; +using Microsoft.PowerShell.Commands.Internal.Format; namespace System.Management.Automation { @@ -194,7 +195,7 @@ List ExecuteGetCommandCommand(bool useModulePrefix) if (commandInfos != null && commandInfos.Count > 1) { // OrderBy is using stable sorting - var sortedCommandInfos = commandInfos.OrderBy(a => a, new CommandNameComparer()); + var sortedCommandInfos = commandInfos.OrderBy(static a => a, new CommandNameComparer()); completionResults = MakeCommandsUnique(sortedCommandInfos, useModulePrefix, addAmpersandIfNecessary, quote); } else @@ -407,7 +408,7 @@ internal static List MakeCommandsUnique(IEnumerable return results; } - private class FindFunctionsVisitor : AstVisitor + private sealed class FindFunctionsVisitor : AstVisitor { internal readonly List FunctionDefinitions = new List(); @@ -480,7 +481,7 @@ internal static List CompleteModuleName(CompletionContext cont #endregion Module Names #region Command Parameters - private static string[] s_parameterNamesOfImportDSCResource = { "Name", "ModuleName", "ModuleVersion" }; + private static readonly string[] s_parameterNamesOfImportDSCResource = { "Name", "ModuleName", "ModuleVersion" }; internal static List CompleteCommandParameter(CompletionContext context) { @@ -511,9 +512,9 @@ internal static List CompleteCommandParameter(CompletionContex && !string.IsNullOrWhiteSpace(context.WordToComplete) && context.WordToComplete.StartsWith('-')) { var lastAst = context.RelatedAsts.Last(); - var wordToMatch = context.WordToComplete.Substring(1) + "*"; + var wordToMatch = string.Concat(context.WordToComplete.AsSpan(1), "*"); var pattern = WildcardPattern.Get(wordToMatch, WildcardOptions.IgnoreCase); - var parameterNames = keywordAst.CommandElements.Where(ast => ast is CommandParameterAst).Select(ast => (ast as CommandParameterAst).ParameterName); + var parameterNames = keywordAst.CommandElements.Where(static ast => ast is CommandParameterAst).Select(static ast => (ast as CommandParameterAst).ParameterName); foreach (var parameterName in s_parameterNamesOfImportDSCResource) { if (pattern.IsMatch(parameterName) && !parameterNames.Contains(parameterName, StringComparer.OrdinalIgnoreCase)) @@ -542,8 +543,7 @@ internal static List CompleteCommandParameter(CompletionContex else { // No CommandParameterAst is found. It could be a StringConstantExpressionAst "-" - var dashAst = (context.RelatedAsts[context.RelatedAsts.Count - 1] as StringConstantExpressionAst); - if (dashAst == null) + if (!(context.RelatedAsts[context.RelatedAsts.Count - 1] is StringConstantExpressionAst dashAst)) return result; if (!dashAst.Value.Trim().Equals("-", StringComparison.OrdinalIgnoreCase)) return result; @@ -1210,7 +1210,7 @@ internal static List CompleteCommandArgument(CompletionContext if (ret != null && ret.Count > 0) { - var prefix = TokenKind.LParen.Text() + input.Substring(0, fakeReplacementIndex); + string prefix = string.Concat(TokenKind.LParen.Text(), input.AsSpan(0, fakeReplacementIndex)); foreach (CompletionResult entry in ret) { string completionText = prefix + entry.CompletionText; @@ -2031,19 +2031,17 @@ private static void NativeCommandArgumentCompletion( { try { - if (argumentCompleterAttribute.Type != null) + var completer = argumentCompleterAttribute.CreateArgumentCompleter(); + + if (completer != null) { - var completer = Activator.CreateInstance(argumentCompleterAttribute.Type) as IArgumentCompleter; - if (completer != null) + var customResults = completer.CompleteArgument(commandName, parameterName, + context.WordToComplete, commandAst, GetBoundArgumentsAsHashtable(context)); + if (customResults != null) { - var customResults = completer.CompleteArgument(commandName, parameterName, - context.WordToComplete, commandAst, GetBoundArgumentsAsHashtable(context)); - if (customResults != null) - { - result.AddRange(customResults); - result.Add(CompletionResult.Null); - return; - } + result.AddRange(customResults); + result.Add(CompletionResult.Null); + return; } } else @@ -2285,6 +2283,14 @@ private static void NativeCommandArgumentCompletion( case "Measure-Object": case "Sort-Object": case "Where-Object": + { + if (parameterName.Equals("Property", StringComparison.OrdinalIgnoreCase)) + { + NativeCompletionMemberName(context, result, commandAst); + } + + break; + } case "Format-Custom": case "Format-List": case "Format-Table": @@ -2294,6 +2300,10 @@ private static void NativeCommandArgumentCompletion( { NativeCompletionMemberName(context, result, commandAst); } + else if (parameterName.Equals("View", StringComparison.OrdinalIgnoreCase)) + { + NativeCompletionFormatViewName(context, boundArguments, result, commandAst, commandName); + } break; } @@ -2570,7 +2580,7 @@ private static void NativeCompletionCimCommands( } } - private static ConcurrentDictionary> s_cimNamespaceAndClassNameToAssociationResultClassNames = + private static readonly ConcurrentDictionary> s_cimNamespaceAndClassNameToAssociationResultClassNames = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); private static IEnumerable NativeCompletionCimAssociationResultClassName_GetResultClassNames( @@ -2599,7 +2609,7 @@ private static IEnumerable NativeCompletionCimAssociationResultClassName resultClassNames.AddRange( cimSession.QueryInstances(cimNamespaceOfSource ?? "root/cimv2", "WQL", query) - .Select(associationInstance => associationInstance.CimSystemProperties.ClassName)); + .Select(static associationInstance => associationInstance.CimSystemProperties.ClassName)); cimClass = cimClass.CimSuperClass; } @@ -2659,7 +2669,7 @@ private static void NativeCompletionCimMethodName( continue; } - bool currentMethodIsStatic = methodDeclaration.Qualifiers.Any(q => q.Name.Equals("Static", StringComparison.OrdinalIgnoreCase)); + bool currentMethodIsStatic = methodDeclaration.Qualifiers.Any(static q => q.Name.Equals("Static", StringComparison.OrdinalIgnoreCase)); if ((currentMethodIsStatic && !staticMethod) || (!currentMethodIsStatic && staticMethod)) { continue; @@ -2667,11 +2677,11 @@ private static void NativeCompletionCimMethodName( StringBuilder tooltipText = new StringBuilder(); tooltipText.Append(methodName); - tooltipText.Append("("); + tooltipText.Append('('); bool gotFirstParameter = false; foreach (var methodParameter in methodDeclaration.Parameters) { - bool outParameter = methodParameter.Qualifiers.Any(q => q.Name.Equals("Out", StringComparison.OrdinalIgnoreCase)); + bool outParameter = methodParameter.Qualifiers.Any(static q => q.Name.Equals("Out", StringComparison.OrdinalIgnoreCase)); if (!gotFirstParameter) { @@ -2688,7 +2698,7 @@ private static void NativeCompletionCimMethodName( } tooltipText.Append(CimInstanceAdapter.CimTypeToTypeNameDisplayString(methodParameter.CimType)); - tooltipText.Append(" "); + tooltipText.Append(' '); tooltipText.Append(methodParameter.Name); if (outParameter) @@ -2697,15 +2707,15 @@ private static void NativeCompletionCimMethodName( } } - tooltipText.Append(")"); + tooltipText.Append(')'); localResults.Add(new CompletionResult(methodName, methodName, CompletionResultType.Method, tooltipText.ToString())); } - result.AddRange(localResults.OrderBy(x => x.ListItemText, StringComparer.OrdinalIgnoreCase)); + result.AddRange(localResults.OrderBy(static x => x.ListItemText, StringComparer.OrdinalIgnoreCase)); } - private static ConcurrentDictionary> s_cimNamespaceToClassNames = + private static readonly ConcurrentDictionary> s_cimNamespaceToClassNames = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); private static IEnumerable NativeCompletionCimClassName_GetClassNames(string targetNamespace) @@ -2803,8 +2813,7 @@ private static void NativeCompletionCimNamespace( continue; } - string childNamespace = namespaceNameProperty.Value as string; - if (childNamespace == null) + if (!(namespaceNameProperty.Value is string childNamespace)) { continue; } @@ -2822,7 +2831,7 @@ private static void NativeCompletionCimNamespace( } } - result.AddRange(namespaceResults.OrderBy(x => x.ListItemText, StringComparer.OrdinalIgnoreCase)); + result.AddRange(namespaceResults.OrderBy(static x => x.ListItemText, StringComparer.OrdinalIgnoreCase)); } private static void NativeCompletionGetCommand(CompletionContext context, string moduleName, string paramName, List result) @@ -3630,7 +3639,7 @@ private static void NativeCompletionSetLocationCommand(CompletionContext context RemoveLastNullCompletionResult(result); - context.WordToComplete = context.WordToComplete ?? string.Empty; + context.WordToComplete ??= string.Empty; var clearLiteralPath = false; if (paramName.Equals("LiteralPath", StringComparison.OrdinalIgnoreCase)) { @@ -3736,7 +3745,7 @@ private static void NativeCompletionCopyMoveItemCommand(CompletionContext contex // The parameter Destination for Move-Item and Copy-Item takes literal path RemoveLastNullCompletionResult(result); - context.WordToComplete = context.WordToComplete ?? string.Empty; + context.WordToComplete ??= string.Empty; var clearLiteralPath = TurnOnLiteralPathOption(context); try @@ -3767,7 +3776,7 @@ private static void NativeCompletionPathArgument(CompletionContext context, stri RemoveLastNullCompletionResult(result); - context.WordToComplete = context.WordToComplete ?? string.Empty; + context.WordToComplete ??= string.Empty; var clearLiteralPath = false; if (paramName.Equals("LiteralPath", StringComparison.OrdinalIgnoreCase)) { @@ -3789,45 +3798,78 @@ private static void NativeCompletionPathArgument(CompletionContext context, stri result.Add(CompletionResult.Null); } - private static void NativeCompletionMemberName(CompletionContext context, List result, CommandAst commandAst) + private static IEnumerable GetInferenceTypes(CompletionContext context, CommandAst commandAst) { // Command is something like where-object/foreach-object/format-list/etc. where there is a parameter that is a property name // and we want member names based on the input object, which is either the parameter InputObject, or comes from the pipeline. - var pipelineAst = commandAst.Parent as PipelineAst; - if (pipelineAst == null) - return; + if (commandAst.Parent is not PipelineAst pipelineAst) + { + return null; + } int i; for (i = 0; i < pipelineAst.PipelineElements.Count; i++) { if (pipelineAst.PipelineElements[i] == commandAst) + { break; + } } IEnumerable prevType = null; if (i == 0) { + // based on a type of the argument which is binded to 'InputObject' parameter. AstParameterArgumentPair pair; if (!context.PseudoBindingInfo.BoundArguments.TryGetValue("InputObject", out pair) || !pair.ArgumentSpecified) { - return; + return null; } var astPair = pair as AstPair; if (astPair == null || astPair.Argument == null) { - return; + return null; } prevType = AstTypeInference.InferTypeOf(astPair.Argument, context.TypeInferenceContext, TypeInferenceRuntimePermissions.AllowSafeEval); } else { + // based on OutputTypeAttribute() of the first cmdlet in pipeline. prevType = AstTypeInference.InferTypeOf(pipelineAst.PipelineElements[i - 1], context.TypeInferenceContext, TypeInferenceRuntimePermissions.AllowSafeEval); } - CompleteMemberByInferredType(context.TypeInferenceContext, prevType, result, context.WordToComplete + "*", filter: IsPropertyMember, isStatic: false); + return prevType; + } + + private static void NativeCompletionMemberName(CompletionContext context, List result, CommandAst commandAst) + { + IEnumerable prevType = GetInferenceTypes(context, commandAst); + if (prevType is not null) + { + CompleteMemberByInferredType(context.TypeInferenceContext, prevType, result, context.WordToComplete + "*", filter: IsPropertyMember, isStatic: false); + } + + result.Add(CompletionResult.Null); + } + + private static void NativeCompletionFormatViewName( + CompletionContext context, + Dictionary boundArguments, + List result, + CommandAst commandAst, + string commandName) + { + IEnumerable prevType = NativeCommandArgumentCompletion_InferTypesOfArgument(boundArguments, commandAst, context, "InputObject"); + + if (prevType is not null) + { + string[] inferTypeNames = prevType.Select(t => t.Name).ToArray(); + CompleteFormatViewByInferredType(context, inferTypeNames, result, commandName); + } + result.Add(CompletionResult.Null); } @@ -4089,7 +4131,9 @@ private static ArgumentLocation FindTargetArgumentLocation(Collection CompleteFilename(CompletionContext if (leaf != null) { - leaf = leaf + "*"; + leaf += "*"; var parentPath = Path.GetDirectoryName(providerPath); // ProviderPath should be absolute path for FileSystem entries @@ -4325,7 +4369,7 @@ internal static IEnumerable CompleteFilename(CompletionContext } // Sorting the results by the path - var sortedPsobjs = psobjs.OrderBy(a => a, new ItemPathComparer()); + var sortedPsobjs = psobjs.OrderBy(static a => a, new ItemPathComparer()); foreach (PSObject psobj in sortedPsobjs) { @@ -4507,7 +4551,7 @@ private struct SHARE_INFO_1 private const int STYPE_DISKTREE = 0; private const int STYPE_MASK = 0x000000FF; - private static System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions + private static readonly System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, AttributesToSkip = 0 // Default is to skip Hidden and System files, so we clear this to retain existing behavior @@ -4708,7 +4752,7 @@ internal static List CompleteVariable(CompletionContext contex provider = wordToComplete.Substring(0, colon + 1); if (s_variableScopes.Contains(provider, StringComparer.OrdinalIgnoreCase)) { - pattern = "variable:" + wordToComplete.Substring(colon + 1) + "*"; + pattern = string.Concat("variable:", wordToComplete.AsSpan(colon + 1), "*"); } else { @@ -4843,7 +4887,7 @@ private static void AddUniqueVariable(HashSet hashedResults, List BuildSpecialVariablesCache() #region Comments - // Complete the history entries - internal static List CompleteComment(CompletionContext context) + internal static List CompleteComment(CompletionContext context, ref int replacementIndex, ref int replacementLength) { - List results = new List(); + if (context.WordToComplete.StartsWith("<#", StringComparison.Ordinal)) + { + return CompleteCommentHelp(context, ref replacementIndex, ref replacementLength); + } + // Complete #requires statements + if (context.WordToComplete.StartsWith("#requires ", StringComparison.OrdinalIgnoreCase)) + { + return CompleteRequires(context, ref replacementIndex, ref replacementLength); + } + + var results = new List(); + + // Complete the history entries Match matchResult = Regex.Match(context.WordToComplete, @"^#([\w\-]*)$"); - if (!matchResult.Success) { return results; } + if (!matchResult.Success) + { + return results; + } string wordToComplete = matchResult.Groups[1].Value; Collection psobjs; @@ -4973,8 +5031,7 @@ internal static List CompleteComment(CompletionContext context for (int index = psobjs.Count - 1; index >= 0; index--) { var psobj = psobjs[index]; - var historyInfo = PSObject.Base(psobj) as HistoryInfo; - if (historyInfo == null) continue; + if (!(PSObject.Base(psobj) is HistoryInfo historyInfo)) continue; var commandLine = historyInfo.CommandLine; if (!string.IsNullOrEmpty(commandLine) && pattern.IsMatch(commandLine)) @@ -4992,6 +5049,447 @@ internal static List CompleteComment(CompletionContext context return results; } + private static List CompleteRequires(CompletionContext context, ref int replacementIndex, ref int replacementLength) + { + var results = new List(); + + int cursorIndex = context.CursorPosition.ColumnNumber - 1; + string lineToCursor = context.CursorPosition.Line.Substring(0, cursorIndex); + + // RunAsAdministrator must be the last parameter in a Requires statement so no completion if the cursor is after the parameter. + if (lineToCursor.Contains(" -RunAsAdministrator", StringComparison.OrdinalIgnoreCase)) + { + return results; + } + + // Regex to find parameter like " -Parameter1" or " -" + MatchCollection hashtableKeyMatches = Regex.Matches(lineToCursor, @"\s+-([A-Za-z]+|$)"); + if (hashtableKeyMatches.Count == 0) + { + return results; + } + + Group currentParameterMatch = hashtableKeyMatches[^1].Groups[1]; + + // Complete the parameter if the cursor is at a parameter + if (currentParameterMatch.Index + currentParameterMatch.Length == cursorIndex) + { + string currentParameterPrefix = currentParameterMatch.Value; + + replacementIndex = context.CursorPosition.Offset - currentParameterPrefix.Length; + replacementLength = currentParameterPrefix.Length; + + // Produce completions for all parameters that begin with the prefix we've found, + // but which haven't already been specified in the line we need to complete + foreach (KeyValuePair parameter in s_requiresParameters) + { + if (parameter.Key.StartsWith(currentParameterPrefix, StringComparison.OrdinalIgnoreCase) + && !context.CursorPosition.Line.Contains($" -{parameter.Key}", StringComparison.OrdinalIgnoreCase)) + { + results.Add(new CompletionResult(parameter.Key, parameter.Key, CompletionResultType.ParameterName, parameter.Value)); + } + } + + return results; + } + + // Regex to find parameter values (any text that appears after various delimiters) + hashtableKeyMatches = Regex.Matches(lineToCursor, @"(\s+|,|;|{|\""|'|=)(\w+|$)"); + string currentValue; + if (hashtableKeyMatches.Count == 0) + { + currentValue = string.Empty; + } + else + { + currentValue = hashtableKeyMatches[^1].Groups[2].Value; + } + + replacementIndex = context.CursorPosition.Offset - currentValue.Length; + replacementLength = currentValue.Length; + + // Complete PSEdition parameter values + if (currentParameterMatch.Value.Equals("PSEdition", StringComparison.OrdinalIgnoreCase)) + { + foreach (KeyValuePair psEditionEntry in s_requiresPSEditions) + { + if (psEditionEntry.Key.StartsWith(currentValue, StringComparison.OrdinalIgnoreCase)) + { + results.Add(new CompletionResult(psEditionEntry.Key, psEditionEntry.Key, CompletionResultType.ParameterValue, psEditionEntry.Value)); + } + } + + return results; + } + + // Complete Modules module specification values + if (currentParameterMatch.Value.Equals("Modules", StringComparison.OrdinalIgnoreCase)) + { + int hashtableStart = lineToCursor.LastIndexOf("@{"); + int hashtableEnd = lineToCursor.LastIndexOf('}'); + + bool insideHashtable = hashtableStart != -1 && (hashtableEnd == -1 || hashtableEnd < hashtableStart); + + // If not inside a hashtable, try to complete a module simple name + if (!insideHashtable) + { + context.WordToComplete = currentValue; + return CompleteModuleName(context, true); + } + + string hashtableString = lineToCursor.Substring(hashtableStart); + + // Regex to find hashtable keys with or without quotes + hashtableKeyMatches = Regex.Matches(hashtableString, @"(@{|;)\s*(?:'|\""|\w*)\w*"); + + // Build the list of keys we might want to complete, based on what's already been provided + var moduleSpecKeysToComplete = new HashSet(s_requiresModuleSpecKeys.Keys); + bool sawModuleNameLast = false; + foreach (Match existingHashtableKeyMatch in hashtableKeyMatches) + { + string existingHashtableKey = existingHashtableKeyMatch.Value.TrimStart(s_hashtableKeyPrefixes); + + if (string.IsNullOrEmpty(existingHashtableKey)) + { + continue; + } + + // Remove the existing key we just saw + moduleSpecKeysToComplete.Remove(existingHashtableKey); + + // We need to remember later if we saw "ModuleName" as the last hashtable key, for completions + if (sawModuleNameLast = existingHashtableKey.Equals("ModuleName", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + // "RequiredVersion" is mutually exclusive with "ModuleVersion" and "MaximumVersion" + if (existingHashtableKey.Equals("ModuleVersion", StringComparison.OrdinalIgnoreCase) + || existingHashtableKey.Equals("MaximumVersion", StringComparison.OrdinalIgnoreCase)) + { + moduleSpecKeysToComplete.Remove("RequiredVersion"); + continue; + } + + if (existingHashtableKey.Equals("RequiredVersion", StringComparison.OrdinalIgnoreCase)) + { + moduleSpecKeysToComplete.Remove("ModuleVersion"); + moduleSpecKeysToComplete.Remove("MaximumVersion"); + continue; + } + } + + Group lastHashtableKeyPrefixGroup = hashtableKeyMatches[^1].Groups[0]; + + // If we're not completing a key for the hashtable, try to complete module names, but nothing else + bool completingHashtableKey = lastHashtableKeyPrefixGroup.Index + lastHashtableKeyPrefixGroup.Length == hashtableString.Length; + if (!completingHashtableKey) + { + if (sawModuleNameLast) + { + context.WordToComplete = currentValue; + return CompleteModuleName(context, true); + } + + return results; + } + + // Now try to complete hashtable keys + foreach (string moduleSpecKey in moduleSpecKeysToComplete) + { + if (moduleSpecKey.StartsWith(currentValue, StringComparison.OrdinalIgnoreCase)) + { + results.Add(new CompletionResult(moduleSpecKey, moduleSpecKey, CompletionResultType.ParameterValue, s_requiresModuleSpecKeys[moduleSpecKey])); + } + } + } + + return results; + } + + private static readonly IReadOnlyDictionary s_requiresParameters = new SortedList(StringComparer.OrdinalIgnoreCase) + { + { "Modules", "Specifies PowerShell modules that the script requires." }, + { "PSEdition", "Specifies a PowerShell edition that the script requires." }, + { "RunAsAdministrator", "Specifies that PowerShell must be running as administrator on Windows." }, + { "Version", "Specifies the minimum version of PowerShell that the script requires." }, + }; + + private static readonly IReadOnlyDictionary s_requiresPSEditions = new SortedList(StringComparer.OrdinalIgnoreCase) + { + { "Core", "Specifies that the script requires PowerShell Core to run." }, + { "Desktop", "Specifies that the script requires Windows PowerShell to run." }, + }; + + private static readonly IReadOnlyDictionary s_requiresModuleSpecKeys = new SortedList(StringComparer.OrdinalIgnoreCase) + { + { "ModuleName", "Required. Specifies the module name." }, + { "GUID", "Optional. Specifies the GUID of the module." }, + { "ModuleVersion", "Specifies a minimum acceptable version of the module." }, + { "RequiredVersion", "Specifies an exact, required version of the module." }, + { "MaximumVersion", "Specifies the maximum acceptable version of the module." }, + }; + + private static readonly char[] s_hashtableKeyPrefixes = new[] + { + '@', + '{', + ';', + '"', + '\'', + ' ', + }; + + private static List CompleteCommentHelp(CompletionContext context, ref int replacementIndex, ref int replacementLength) + { + // Finds comment keywords like ".DESCRIPTION" + MatchCollection usedKeywords = Regex.Matches(context.TokenAtCursor.Text, @"(?<=^\s*\.)\w*", RegexOptions.Multiline); + if (usedKeywords.Count == 0) + { + return null; + } + + // Last keyword at or before the cursor + Match lineKeyword = null; + for (int i = usedKeywords.Count - 1; i >= 0; i--) + { + Match keyword = usedKeywords[i]; + if (context.CursorPosition.Offset >= keyword.Index + context.TokenAtCursor.Extent.StartOffset) + { + lineKeyword = keyword; + break; + } + } + + if (lineKeyword is null) + { + return null; + } + + // Cursor is within or at the start/end of the keyword + if (context.CursorPosition.Offset <= lineKeyword.Index + lineKeyword.Length + context.TokenAtCursor.Extent.StartOffset) + { + replacementIndex = context.TokenAtCursor.Extent.StartOffset + lineKeyword.Index; + replacementLength = lineKeyword.Value.Length; + + var validKeywords = new HashSet(s_commentHelpKeywords.Keys, StringComparer.OrdinalIgnoreCase); + foreach (Match keyword in usedKeywords) + { + if (keyword == lineKeyword || s_commentHelpAllowedDuplicateKeywords.Contains(keyword.Value)) + { + continue; + } + + validKeywords.Remove(keyword.Value); + } + + var result = new List(); + foreach (string keyword in validKeywords) + { + if (keyword.StartsWith(lineKeyword.Value, StringComparison.OrdinalIgnoreCase)) + { + result.Add(new CompletionResult(keyword, keyword, CompletionResultType.Keyword, s_commentHelpKeywords[keyword])); + } + } + + return result.Count > 0 ? result : null; + } + + // Finds the argument for the keyword (any characters following the keyword, ignoring leading/trailing whitespace). For example "C:\New folder" + Match keywordArgument = Regex.Match(context.CursorPosition.Line, @"(?<=^\s*\.\w+\s+)\S.*(?<=\S)"); + int lineStartIndex = lineKeyword.Index - context.CursorPosition.Line.IndexOf(lineKeyword.Value) + context.TokenAtCursor.Extent.StartOffset; + int argumentIndex = keywordArgument.Success ? keywordArgument.Index : context.CursorPosition.ColumnNumber - 1; + + replacementIndex = lineStartIndex + argumentIndex; + replacementLength = keywordArgument.Value.Length; + + if (lineKeyword.Value.Equals("PARAMETER", StringComparison.OrdinalIgnoreCase)) + { + return CompleteCommentParameterValue(context, keywordArgument.Value); + } + + if (lineKeyword.Value.Equals("FORWARDHELPTARGETNAME", StringComparison.OrdinalIgnoreCase)) + { + var result = new List(CompleteCommand(keywordArgument.Value, "*", CommandTypes.All)); + return result.Count > 0 ? result : null; + } + + if (lineKeyword.Value.Equals("FORWARDHELPCATEGORY", StringComparison.OrdinalIgnoreCase)) + { + var result = new List(); + foreach (string category in s_commentHelpForwardCategories) + { + if (category.StartsWith(keywordArgument.Value, StringComparison.OrdinalIgnoreCase)) + { + result.Add(new CompletionResult(category)); + } + } + return result.Count > 0 ? result : null; + } + + if (lineKeyword.Value.Equals("REMOTEHELPRUNSPACE", StringComparison.OrdinalIgnoreCase)) + { + var result = new List(); + foreach (CompletionResult variable in CompleteVariable(keywordArgument.Value)) + { + // ListItemText is used because it excludes the "$" as expected by REMOTEHELPRUNSPACE. + result.Add(new CompletionResult(variable.ListItemText, variable.ListItemText, variable.ResultType, variable.ToolTip)); + } + return result.Count > 0 ? result : null; + } + + if (lineKeyword.Value.Equals("EXTERNALHELP", StringComparison.OrdinalIgnoreCase)) + { + context.WordToComplete = keywordArgument.Value; + var result = new List(CompleteFilename(context, containerOnly: false, (new HashSet() { ".xml" }))); + return result.Count > 0 ? result : null; + } + + return null; + } + + private static readonly IReadOnlyDictionary s_commentHelpKeywords = new SortedList(StringComparer.OrdinalIgnoreCase) + { + { "SYNOPSIS", "A brief description of the function or script. This keyword can be used only once in each topic." }, + { "DESCRIPTION", "A detailed description of the function or script. This keyword can be used only once in each topic." }, + { "PARAMETER", ".PARAMETER \nThe description of a parameter. Add a .PARAMETER keyword for each parameter in the function or script syntax." }, + { "EXAMPLE", "A sample command that uses the function or script, optionally followed by sample output and a description. Repeat this keyword for each example." }, + { "INPUTS", "The .NET types of objects that can be piped to the function or script. You can also include a description of the input objects." }, + { "OUTPUTS", "The .NET type of the objects that the cmdlet returns. You can also include a description of the returned objects." }, + { "NOTES", "Additional information about the function or script." }, + { "LINK", "The name of a related topic. Repeat the .LINK keyword for each related topic. The .Link keyword content can also include a URI to an online version of the same help topic." }, + { "COMPONENT", "The name of the technology or feature that the function or script uses, or to which it is related." }, + { "ROLE", "The name of the user role for the help topic." }, + { "FUNCTIONALITY", "The keywords that describe the intended use of the function." }, + { "FORWARDHELPTARGETNAME", ".FORWARDHELPTARGETNAME \nRedirects to the help topic for the specified command." }, + { "FORWARDHELPCATEGORY", ".FORWARDHELPCATEGORY \nSpecifies the help category of the item in .ForwardHelpTargetName" }, + { "REMOTEHELPRUNSPACE", ".REMOTEHELPRUNSPACE \nSpecifies a session that contains the help topic. Enter a variable that contains a PSSession object." }, + { "EXTERNALHELP", ".EXTERNALHELP \nThe .ExternalHelp keyword is required when a function or script is documented in XML files." } + }; + + private static readonly HashSet s_commentHelpAllowedDuplicateKeywords = new(StringComparer.OrdinalIgnoreCase) + { + "PARAMETER", + "EXAMPLE", + "LINK" + }; + + private static readonly string[] s_commentHelpForwardCategories = new string[] + { + "Alias", + "Cmdlet", + "HelpFile", + "Function", + "Provider", + "General", + "FAQ", + "Glossary", + "ScriptCommand", + "ExternalScript", + "Filter", + "All" + }; + + private static FunctionDefinitionAst GetCommentHelpFunctionTarget(CompletionContext context) + { + if (context.TokenAtCursor.Kind != TokenKind.Comment) + { + return null; + } + + Ast lastAst = context.RelatedAsts[^1]; + Ast firstAstAfterComment = lastAst.Find(ast => ast.Extent.StartOffset >= context.TokenAtCursor.Extent.EndOffset, searchNestedScriptBlocks: false); + + // Comment-based help can apply to a following function definition if it starts within 2 lines + int commentEndLine = context.TokenAtCursor.Extent.EndLineNumber + 2; + + if (lastAst is NamedBlockAst) + { + // Helpblock before function inside advanced function + if (firstAstAfterComment is not null + && firstAstAfterComment.Extent.StartLineNumber <= commentEndLine + && firstAstAfterComment is FunctionDefinitionAst outerHelpFunctionDefAst) + { + return outerHelpFunctionDefAst; + } + + // Helpblock inside function + if (lastAst.Parent.Parent is FunctionDefinitionAst innerHelpFunctionDefAst) + { + return innerHelpFunctionDefAst; + } + } + + if (lastAst is ScriptBlockAst) + { + // Helpblock before function + if (firstAstAfterComment is not null + && firstAstAfterComment.Extent.StartLineNumber <= commentEndLine + && firstAstAfterComment is NamedBlockAst block + && block.Statements.Count > 0 + && block.Statements[0] is FunctionDefinitionAst statement) + { + return statement; + } + + // Advanced function with help inside + if (lastAst.Parent is FunctionDefinitionAst advFuncDefAst) + { + return advFuncDefAst; + } + } + + return null; + } + + private static List CompleteCommentParameterValue(CompletionContext context, string wordToComplete) + { + FunctionDefinitionAst foundFunction = GetCommentHelpFunctionTarget(context); + + ReadOnlyCollection foundParameters = null; + if (foundFunction is not null) + { + foundParameters = foundFunction.Parameters ?? foundFunction.Body.ParamBlock?.Parameters; + } + else if (context.RelatedAsts[^1] is ScriptBlockAst scriptAst) + { + // The helpblock is for a script file + foundParameters = scriptAst.ParamBlock?.Parameters; + } + + if (foundParameters is null || foundParameters.Count == 0) + { + return null; + } + + var parametersToShow = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (ParameterAst parameter in foundParameters) + { + if (parameter.Name.VariablePath.UserPath.StartsWith(wordToComplete, StringComparison.OrdinalIgnoreCase)) + { + parametersToShow.Add(parameter.Name.VariablePath.UserPath); + } + } + + MatchCollection usedParameters = Regex.Matches(context.TokenAtCursor.Text, @"(?<=^\s*\.parameter\s+)\w.*(?<=\S)", RegexOptions.Multiline | RegexOptions.IgnoreCase); + foreach (Match parameter in usedParameters) + { + if (wordToComplete.Equals(parameter.Value, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + parametersToShow.Remove(parameter.Value); + } + + var result = new List(); + foreach (string parameter in parametersToShow) + { + result.Add(new CompletionResult(parameter)); + } + + return result.Count > 0 ? result : null; + } + #endregion Comments #region Members @@ -5003,6 +5501,7 @@ internal static List CompleteComment(CompletionContext context new Tuple("Where", "Where({ expression } [, mode [, numberToReturn]])"), new Tuple("ForEach", "ForEach(expression [, arguments...])") }; + // List of DSC collection-value variables private static readonly HashSet s_dscCollectionVariables = new HashSet(StringComparer.OrdinalIgnoreCase) { "SelectedNodes", "AllNodes" }; @@ -5050,7 +5549,7 @@ internal static List CompleteMember(CompletionContext context, memberName = memberNameAst.Value + "*"; } } - else if (!(lastAst is ErrorExpressionAst) && targetExpr == null) + else if (lastAst is not ErrorExpressionAst && targetExpr == null) { // I don't think we can complete anything interesting return results; @@ -5245,6 +5744,59 @@ private static bool IsInDscContext(ExpressionAst expression) return Ast.GetAncestorAst(expression) != null; } + private static void CompleteFormatViewByInferredType(CompletionContext context, string[] inferredTypeNames, List results, string commandName) + { + var typeInfoDB = context.TypeInferenceContext.ExecutionContext.FormatDBManager.GetTypeInfoDataBase(); + + if (typeInfoDB is null) + { + return; + } + + Type controlBodyType = commandName switch + { + "Format-Table" => typeof(TableControlBody), + "Format-List" => typeof(ListControlBody), + "Format-Wide" => typeof(WideControlBody), + "Format-Custom" => typeof(ComplexControlBody), + _ => null + }; + + Diagnostics.Assert(controlBodyType is not null, "This should never happen unless a new Format-* cmdlet is added"); + + var wordToComplete = context.WordToComplete; + var quote = HandleDoubleAndSingleQuote(ref wordToComplete); + WildcardPattern viewPattern = WildcardPattern.Get(wordToComplete + "*", WildcardOptions.IgnoreCase); + + var uniqueNames = new HashSet(); + foreach (ViewDefinition viewDefinition in typeInfoDB.viewDefinitionsSection.viewDefinitionList) + { + if (viewDefinition?.appliesTo is not null && controlBodyType == viewDefinition.mainControl.GetType()) + { + foreach (TypeOrGroupReference applyTo in viewDefinition.appliesTo.referenceList) + { + foreach (string inferredTypeName in inferredTypeNames) + { + // We use 'StartsWith()' because 'applyTo.Name' can look like "System.Diagnostics.Process#IncludeUserName". + if (applyTo.name.StartsWith(inferredTypeName, StringComparison.OrdinalIgnoreCase) + && uniqueNames.Add(viewDefinition.name) + && viewPattern.IsMatch(viewDefinition.name)) + { + string completionText = viewDefinition.name; + // If the string is quoted or if it contains characters that need quoting, quote it in single quotes + if (quote != string.Empty || viewDefinition.name.IndexOfAny(s_charactersRequiringQuotes) != -1) + { + completionText = "'" + completionText.Replace("'", "''") + "'"; + } + + results.Add(new CompletionResult(completionText, viewDefinition.name, CompletionResultType.Text, viewDefinition.name)); + } + } + } + } + } + } + internal static void CompleteMemberByInferredType(TypeInferenceContext context, IEnumerable inferredTypes, List results, string memberName, Func filter, bool isStatic) { bool extensionMethodsAdded = false; @@ -5284,7 +5836,7 @@ internal static void CompleteMemberByInferredType(TypeInferenceContext context, Exception unused; var sortedResults = powerShellExecutionHelper.ExecuteCurrentPowerShell(out unused, results); results.Clear(); - results.AddRange(sortedResults.Select(psobj => PSObject.Base(psobj) as CompletionResult)); + results.AddRange(sortedResults.Select(static psobj => PSObject.Base(psobj) as CompletionResult)); } } @@ -5314,7 +5866,7 @@ private static void AddInferredMember(object member, WildcardPattern memberNameP { memberName = methodCacheEntry[0].method.Name; isMethod = true; - getToolTip = () => string.Join("\n", methodCacheEntry.methodInformationStructures.Select(m => m.methodDefinition)); + getToolTip = () => string.Join("\n", methodCacheEntry.methodInformationStructures.Select(static m => m.methodDefinition)); } var psMemberInfo = member as PSMemberInfo; @@ -5371,7 +5923,7 @@ private static string GetCimPropertyToString(CimPropertyDeclaration cimProperty) break; } - bool isReadOnly = (CimFlags.ReadOnly == (cimProperty.Flags & CimFlags.ReadOnly)); + bool isReadOnly = ((cimProperty.Flags & CimFlags.ReadOnly) == CimFlags.ReadOnly); return type + " " + cimProperty.Name + " { get; " + (isReadOnly ? "}" : "set; }"); } @@ -5444,6 +5996,7 @@ private static bool IsConstructor(object member) private abstract class TypeCompletionBase { internal abstract CompletionResult GetCompletionResult(string keyMatched, string prefix, string suffix); + internal abstract CompletionResult GetCompletionResult(string keyMatched, string prefix, string suffix, string namespaceToRemove); internal static string RemoveBackTick(string typeName) @@ -5539,7 +6092,7 @@ internal override CompletionResult GetCompletionResult(string keyMatched, string /// This type represents a generic type for type name completion. It only contains information that can be /// inferred from the full type name. /// - private class GenericTypeCompletionInStringFormat : TypeCompletionInStringFormat + private sealed class GenericTypeCompletionInStringFormat : TypeCompletionInStringFormat { /// /// Get the number of generic type arguments required by the type represented by this instance. @@ -5656,7 +6209,7 @@ internal override CompletionResult GetCompletionResult(string keyMatched, string /// /// This type represents a generic type for type name completion. It contains the actual type instance. /// - private class GenericTypeCompletion : TypeCompletion + private sealed class GenericTypeCompletion : TypeCompletion { internal override CompletionResult GetCompletionResult(string keyMatched, string prefix, string suffix) { @@ -5693,7 +6246,7 @@ internal override CompletionResult GetCompletionResult(string keyMatched, string /// /// This type represents a namespace for namespace completion. /// - private class NamespaceCompletion : TypeCompletionBase + private sealed class NamespaceCompletion : TypeCompletionBase { internal string Namespace; @@ -5715,7 +6268,7 @@ internal override CompletionResult GetCompletionResult(string keyMatched, string } } - private class TypeCompletionMapping + private sealed class TypeCompletionMapping { // The Key is the string we'll be searching on. It could complete to various things. internal string Key; @@ -5824,7 +6377,7 @@ private static TypeCompletionMapping[][] InitializeTypeCache() #endregion Process_LoadedAssemblies - var grouping = entries.Values.GroupBy(t => t.Key.Count(c => c == '.')).OrderBy(g => g.Key).ToArray(); + var grouping = entries.Values.GroupBy(static t => t.Key.Count(c => c == '.')).OrderBy(static g => g.Key).ToArray(); var localTypeCache = new TypeCompletionMapping[grouping.Last().Key + 1][]; foreach (var group in grouping) { @@ -5941,7 +6494,7 @@ internal static List CompleteNamespace(CompletionContext conte var localTypeCache = s_typeCache ?? InitializeTypeCache(); var results = new List(); var wordToComplete = context.WordToComplete; - var dots = wordToComplete.Count(c => c == '.'); + var dots = wordToComplete.Count(static c => c == '.'); if (dots >= localTypeCache.Length || localTypeCache[dots] == null) { return results; @@ -5957,7 +6510,7 @@ internal static List CompleteNamespace(CompletionContext conte } } - results.Sort((c1, c2) => string.Compare(c1.ListItemText, c2.ListItemText, StringComparison.OrdinalIgnoreCase)); + results.Sort(static (c1, c2) => string.Compare(c1.ListItemText, c2.ListItemText, StringComparison.OrdinalIgnoreCase)); return results; } @@ -5985,7 +6538,7 @@ internal static List CompleteType(CompletionContext context, s var results = new List(); var completionTextSet = new HashSet(StringComparer.OrdinalIgnoreCase); var wordToComplete = context.WordToComplete; - var dots = wordToComplete.Count(c => c == '.'); + var dots = wordToComplete.Count(static c => c == '.'); if (dots >= localTypeCache.Length || localTypeCache[dots] == null) { return results; @@ -6016,7 +6569,7 @@ internal static List CompleteType(CompletionContext context, s if (context.RelatedAsts != null && context.RelatedAsts.Count > 0) { var scriptBlockAst = (ScriptBlockAst)context.RelatedAsts[0]; - var typeAsts = scriptBlockAst.FindAll(ast => ast is TypeDefinitionAst, false).Cast(); + var typeAsts = scriptBlockAst.FindAll(static ast => ast is TypeDefinitionAst, false).Cast(); foreach (var typeAst in typeAsts.Where(ast => pattern.IsMatch(ast.Name))) { string toolTipPrefix = string.Empty; @@ -6031,7 +6584,7 @@ internal static List CompleteType(CompletionContext context, s } } - results.Sort((c1, c2) => string.Compare(c1.ListItemText, c2.ListItemText, StringComparison.OrdinalIgnoreCase)); + results.Sort(static (c1, c2) => string.Compare(c1.ListItemText, c2.ListItemText, StringComparison.OrdinalIgnoreCase)); return results; } @@ -6072,35 +6625,36 @@ private static string GetNamespaceToRemove(CompletionContext context, TypeComple internal static List CompleteHelpTopics(CompletionContext context) { var results = new List(); - var searchPaths = new List(); - var currentCulture = CultureInfo.CurrentCulture.Name; - - // Add the user scope path first, since it is searched in order. - var userHelpRoot = Path.Combine(HelpUtils.GetUserHomeHelpSearchPath(), currentCulture); + string userHelpDir = HelpUtils.GetUserHomeHelpSearchPath(); + string appHelpDir = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID); + string currentCulture = CultureInfo.CurrentCulture.Name; - if (Directory.Exists(userHelpRoot)) + //search for help files for the current culture + en-US as fallback + var searchPaths = new string[] { - searchPaths.Add(userHelpRoot); - } - - var dirPath = Path.Combine(Utils.GetApplicationBase(Utils.DefaultPowerShellShellID), currentCulture); - searchPaths.Add(dirPath); - - var wordToComplete = context.WordToComplete + "*"; - var topicPattern = WildcardPattern.Get("about_*.help.txt", WildcardOptions.IgnoreCase); - List files = new List(); + Path.Combine(userHelpDir, currentCulture), + Path.Combine(appHelpDir, currentCulture), + Path.Combine(userHelpDir, "en-US"), + Path.Combine(appHelpDir, "en-US") + }.Distinct(); + string wordToComplete = context.WordToComplete + "*"; try { var wildcardPattern = WildcardPattern.Get(wordToComplete, WildcardOptions.IgnoreCase); foreach (var dir in searchPaths) { - foreach (var file in Directory.GetFiles(dir)) + var currentDir = new DirectoryInfo(dir); + if (currentDir.Exists) { - if (wildcardPattern.IsMatch(Path.GetFileName(file))) + foreach (var file in currentDir.EnumerateFiles("about_*.help.txt")) { - files.Add(file); + if (wildcardPattern.IsMatch(file.Name)) + { + string topicName = file.Name.Substring(0, file.Name.LastIndexOf(".help.txt")); + results.Add(new CompletionResult(topicName)); + } } } } @@ -6108,33 +6662,6 @@ internal static List CompleteHelpTopics(CompletionContext cont catch (Exception) { } - - if (files != null) - { - foreach (string file in files) - { - if (file == null) - { - continue; - } - - try - { - var fileName = Path.GetFileName(file); - if (fileName == null || !topicPattern.IsMatch(fileName)) - continue; - - // All topic files are ending with ".help.txt" - var completionText = fileName.Substring(0, fileName.Length - 9); - results.Add(new CompletionResult(completionText)); - } - catch (Exception) - { - continue; - } - } - } - return results; } @@ -6438,7 +6965,7 @@ private static List GetSpecialHashTableKeyMembers(params strin // return keys.Select(key => new CompletionResult(key, key, CompletionResultType.Property, // ResourceManagerCache.GetResourceString(typeof(CompletionCompleters).Assembly, // "TabCompletionStrings", key + "HashKeyDescription"))).ToList(); - return keys.Select(key => new CompletionResult(key, key, CompletionResultType.Property, key)).ToList(); + return keys.Select(static key => new CompletionResult(key, key, CompletionResultType.Property, key)).ToList(); } #endregion Hashtable Keys @@ -6460,8 +6987,7 @@ internal static bool IsPathSafelyExpandable(ExpandableStringExpressionAst expand var varValues = new List(); foreach (ExpressionAst nestedAst in expandableStringAst.NestedExpressions) { - var variableAst = nestedAst as VariableExpressionAst; - if (variableAst == null) { return false; } + if (!(nestedAst is VariableExpressionAst variableAst)) { return false; } string strValue = CombineVariableWithPartialPath(variableAst, null, executionContext); if (strValue != null) @@ -6567,7 +7093,7 @@ internal static void CompleteMemberHelper( object value; if (SafeExprEvaluator.TrySafeEval(targetExpr, context.ExecutionContext, out value) && value != null) { - if (targetExpr is ArrayExpressionAst && !(value is object[])) + if (targetExpr is ArrayExpressionAst && value is not object[]) { // When the array contains only one element, the evaluation result would be that element. We wrap it into an array value = new[] { value }; @@ -6586,8 +7112,7 @@ internal static void CompleteMemberHelper( IEnumerable members; if (@static) { - var type = PSObject.Base(value) as Type; - if (type == null) + if (!(PSObject.Base(value) is Type type)) { return; } @@ -6653,8 +7178,7 @@ internal static void CompleteMemberHelper( var pattern = WildcardPattern.Get(memberName, WildcardOptions.IgnoreCase); foreach (DictionaryEntry entry in dictionary) { - var key = entry.Key as string; - if (key == null) + if (!(entry.Key is string key)) continue; if (pattern.IsMatch(key)) @@ -6810,7 +7334,7 @@ internal static bool IsAmpersandNeeded(CompletionContext context, bool defaultCh return defaultChoice; } - private class ItemPathComparer : IComparer + private sealed class ItemPathComparer : IComparer { public int Compare(PSObject x, PSObject y) { @@ -6845,7 +7369,7 @@ public int Compare(PSObject x, PSObject y) } } - private class CommandNameComparer : IComparer + private sealed class CommandNameComparer : IComparer { public int Compare(PSObject x, PSObject y) { @@ -6872,7 +7396,7 @@ public int Compare(PSObject x, PSObject y) } /// - /// This class is very similar to the restricted langauge checker, but it is meant to allow more things, yet still + /// This class is very similar to the restricted language checker, but it is meant to allow more things, yet still /// be considered "safe", at least in the sense that tab completion can rely on it to not do bad things. The primary /// use is for intellisense where you don't want to run arbitrary code, but you do want to know the values /// of various expressions so you can get the members. @@ -6963,6 +7487,7 @@ internal static bool TrySafeEval(ExpressionAst ast, ExecutionContext executionCo public object VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst) { return false; } public object VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { return false; } + // REVIEW: we could relax this to allow specific commands public object VisitCommand(CommandAst commandAst) { return false; } @@ -7127,7 +7652,7 @@ public PropertyNameCompleter() /// /// Initializes a new instance of the class. /// - /// The name of the property of the input object for witch to complete with property names. + /// The name of the property of the input object for which to complete with property names. public PropertyNameCompleter(string parameterNameOfInput) { _parameterNameOfInput = parameterNameOfInput; diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionResult.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionResult.cs index 3fe4a54e023..ffb09e2a50d 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionResult.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionResult.cs @@ -65,22 +65,22 @@ public class CompletionResult /// /// Text to be used as the auto completion result. /// - private string _completionText; + private readonly string _completionText; /// /// Text to be displayed in a list. /// - private string _listItemText; + private readonly string _listItemText; /// /// The text for the tooltip with details to be displayed about the object. /// - private string _toolTip; + private readonly string _toolTip; /// /// Type of completion result. /// - private CompletionResultType _resultType; + private readonly CompletionResultType _resultType; /// /// Private member for null instance. diff --git a/src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs b/src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs index f26b9881c19..2b5281a8f26 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs @@ -32,7 +32,7 @@ public class ArgumentCompleterAttribute : Attribute /// The type must implement and have a default constructor. public ArgumentCompleterAttribute(Type type) { - if (type == null || (type.GetInterfaces().All(t => t != typeof(IArgumentCompleter)))) + if (type == null || (type.GetInterfaces().All(static t => t != typeof(IArgumentCompleter)))) { throw PSTraceSource.NewArgumentException(nameof(type)); } @@ -40,24 +40,46 @@ public ArgumentCompleterAttribute(Type type) Type = type; } + /// + /// Initializes a new instance of the class. + /// This constructor is used by derived attributes implementing . + /// + protected ArgumentCompleterAttribute() + { + if (this is not IArgumentCompleterFactory) + { + throw PSTraceSource.NewInvalidOperationException(); + } + } + /// /// This constructor is used primarily via PowerShell scripts. /// /// public ArgumentCompleterAttribute(ScriptBlock scriptBlock) { - if (scriptBlock == null) + if (scriptBlock is null) { throw PSTraceSource.NewArgumentNullException(nameof(scriptBlock)); } ScriptBlock = scriptBlock; } + + internal IArgumentCompleter CreateArgumentCompleter() + { + return Type != null + ? Activator.CreateInstance(Type) as IArgumentCompleter + : this is IArgumentCompleterFactory factory + ? factory.Create() + : null; + } } /// /// A type specified by the must implement this interface. /// +#nullable enable public interface IArgumentCompleter { /// @@ -82,6 +104,68 @@ IEnumerable CompleteArgument( CommandAst commandAst, IDictionary fakeBoundParameters); } +#nullable restore + + /// + /// Creates a new argument completer. + /// + /// + /// If an attribute that derives from implements this interface, + /// it will be used to create the , thus giving a way to parameterize a completer. + /// The derived attribute can have properties or constructor arguments that are used when creating the completer. + /// + /// + /// This example shows the intended usage of to pass arguments to an argument completer. + /// + /// public class NumberCompleterAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory { + /// private readonly int _from; + /// private readonly int _to; + /// + /// public NumberCompleterAttribute(int from, int to){ + /// _from = from; + /// _to = to; + /// } + /// + /// // use the attribute parameters to create a parameterized completer + /// IArgumentCompleter Create() => new NumberCompleter(_from, _to); + /// } + /// + /// class NumberCompleter : IArgumentCompleter { + /// private readonly int _from; + /// private readonly int _to; + /// + /// public NumberCompleter(int from, int to){ + /// _from = from; + /// _to = to; + /// } + /// + /// IEnumerable{CompletionResult} CompleteArgument(string commandName, string parameterName, string wordToComplete, + /// CommandAst commandAst, IDictionary fakeBoundParameters) { + /// for(int i = _from; i < _to; i++) { + /// yield return new CompletionResult(i.ToString()); + /// } + /// } + /// } + /// + /// + public interface IArgumentCompleterFactory + { + /// + /// Creates an instance of a class implementing the interface. + /// + /// An IArgumentCompleter instance. + IArgumentCompleter Create(); + } + + /// + /// Base class for parameterized argument completer attributes. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + public abstract class ArgumentCompleterFactoryAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory + { + /// + public abstract IArgumentCompleter Create(); + } /// /// @@ -129,7 +213,7 @@ protected override void EndProcessing() if (CommandName == null || CommandName.Length == 0) { - CommandName = new[] { "" }; + CommandName = new[] { string.Empty }; } for (int i = 0; i < CommandName.Length; i++) @@ -164,7 +248,7 @@ protected override void EndProcessing() [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class ArgumentCompletionsAttribute : Attribute { - private string[] _completions; + private readonly string[] _completions; /// /// Initializes a new instance of the ArgumentCompletionsAttribute class. diff --git a/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs b/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs index b98999cae65..c98be4ccac8 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs @@ -201,9 +201,9 @@ internal AstPair(CommandParameterAst parameterAst, ExpressionAst argumentAst) ParameterArgumentType = AstParameterArgumentType.AstPair; ParameterSpecified = parameterAst != null; ArgumentSpecified = argumentAst != null; - ParameterName = parameterAst != null ? parameterAst.ParameterName : null; - ParameterText = parameterAst != null ? parameterAst.ParameterName : null; - ArgumentType = argumentAst != null ? argumentAst.StaticType : null; + ParameterName = parameterAst?.ParameterName; + ParameterText = parameterAst?.ParameterName; + ArgumentType = argumentAst?.StaticType; ParameterContainsArgument = false; Argument = argumentAst; @@ -261,8 +261,7 @@ public static class StaticParameterBinder /// The StaticBindingResult that represents the binding. public static StaticBindingResult BindCommand(CommandAst commandAst) { - bool resolve = true; - return BindCommand(commandAst, resolve); + return BindCommand(commandAst, resolve: true); } /// @@ -729,7 +728,10 @@ internal ParameterBindingResult() /// public object ConstantValue { - get { return _constantValue; } + get + { + return _constantValue; + } internal set { @@ -746,7 +748,10 @@ internal set /// public CommandElementAst Value { - get { return _value; } + get + { + return _value; + } internal set { @@ -1151,12 +1156,12 @@ private void InitializeMembers() _bindableParameters = null; // reuse the collections/dictionaries - _arguments = _arguments ?? new Collection(); - _boundParameters = _boundParameters ?? new Dictionary(StringComparer.OrdinalIgnoreCase); - _boundArguments = _boundArguments ?? new Dictionary(StringComparer.OrdinalIgnoreCase); - _unboundParameters = _unboundParameters ?? new List(); - _boundPositionalParameter = _boundPositionalParameter ?? new Collection(); - _bindingExceptions = _bindingExceptions ?? new Dictionary(); + _arguments ??= new Collection(); + _boundParameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase); + _boundArguments ??= new Dictionary(StringComparer.OrdinalIgnoreCase); + _unboundParameters ??= new List(); + _boundPositionalParameter ??= new Collection(); + _bindingExceptions ??= new Dictionary(); _arguments.Clear(); _boundParameters.Clear(); @@ -1171,9 +1176,9 @@ private void InitializeMembers() _isPipelineInputExpected = false; // reuse the collections - _parametersNotFound = _parametersNotFound ?? new Collection(); - _ambiguousParameters = _ambiguousParameters ?? new Collection(); - _duplicateParameters = _duplicateParameters ?? new Collection(); + _parametersNotFound ??= new Collection(); + _ambiguousParameters ??= new Collection(); + _duplicateParameters ??= new Collection(); _parametersNotFound.Clear(); _ambiguousParameters.Clear(); @@ -1857,6 +1862,13 @@ private static AstParameterArgumentPair GetNextPositionalArgument( while (unboundArgumentsIndex < unboundArgumentsCollection.Count) { AstParameterArgumentPair argument = unboundArgumentsCollection[unboundArgumentsIndex++]; + if (argument is AstPair astPair + && astPair.Argument is VariableExpressionAst argumentVariable + && argumentVariable.Splatted) + { + continue; + } + if (!argument.ParameterSpecified) { result = argument; diff --git a/src/System.Management.Automation/engine/CommandDiscovery.cs b/src/System.Management.Automation/engine/CommandDiscovery.cs index f5f2a0501f0..6d7fb77eba8 100644 --- a/src/System.Management.Automation/engine/CommandDiscovery.cs +++ b/src/System.Management.Automation/engine/CommandDiscovery.cs @@ -37,7 +37,7 @@ internal CommandLookupEventArgs(string commandName, CommandOrigin commandOrigin, _context = context; } - private ExecutionContext _context; + private readonly ExecutionContext _context; /// /// The name of the command we're looking for. @@ -65,7 +65,10 @@ internal CommandLookupEventArgs(string commandName, CommandOrigin commandOrigin, /// public ScriptBlock CommandScriptBlock { - get { return _scriptBlock; } + get + { + return _scriptBlock; + } set { @@ -149,7 +152,7 @@ internal CommandDiscovery(ExecutionContext context) /// /// True if the cmdlet is a special cmdlet that shouldn't be part of the discovery list. Or false otherwise. /// - private bool IsSpecialCmdlet(Type implementingType) + private static bool IsSpecialCmdlet(Type implementingType) { // These commands should never be put in the discovery list. They are an internal implementation // detail of the formatting and output component. That component uses these cmdlets by creating @@ -652,7 +655,7 @@ internal static void ShouldRun(ExecutionContext context, PSHost host, CommandInf private static CommandProcessorBase CreateCommandProcessorForScript(ScriptInfo scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState) { - sessionState = sessionState ?? scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; + sessionState ??= scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(scriptInfo, context, useNewScope, true, sessionState); if (scriptAsCmdletProcessor != null) { @@ -664,7 +667,7 @@ private static CommandProcessorBase CreateCommandProcessorForScript(ScriptInfo s private static CommandProcessorBase CreateCommandProcessorForScript(ExternalScriptInfo scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState) { - sessionState = sessionState ?? scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; + sessionState ??= scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(scriptInfo, context, useNewScope, true, sessionState); if (scriptAsCmdletProcessor != null) { @@ -676,7 +679,7 @@ private static CommandProcessorBase CreateCommandProcessorForScript(ExternalScri internal static CommandProcessorBase CreateCommandProcessorForScript(FunctionInfo functionInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState) { - sessionState = sessionState ?? functionInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; + sessionState ??= functionInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(functionInfo, context, useNewScope, false, sessionState); if (scriptAsCmdletProcessor != null) { @@ -688,7 +691,7 @@ internal static CommandProcessorBase CreateCommandProcessorForScript(FunctionInf internal static CommandProcessorBase CreateCommandProcessorForScript(ScriptBlock scriptblock, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState) { - sessionState = sessionState ?? scriptblock.SessionStateInternal ?? context.EngineSessionState; + sessionState ??= scriptblock.SessionStateInternal ?? context.EngineSessionState; if (scriptblock.UsesCmdletBinding) { @@ -706,7 +709,7 @@ private static CommandProcessorBase GetScriptAsCmdletProcessor(IScriptCommandInf return null; } - sessionState = sessionState ?? scriptCommandInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; + sessionState ??= scriptCommandInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState; return new CommandProcessor(scriptCommandInfo, context, useNewScope, fromScriptFile, sessionState); } @@ -784,7 +787,7 @@ internal static CommandInfo LookupCommandInfo( // Check the module auto-loading preference PSModuleAutoLoadingPreference moduleAutoLoadingPreference = GetCommandDiscoveryPreference(context, SpecialVariables.PSModuleAutoLoadingPreferenceVarPath, "PSModuleAutoLoadingPreference"); - if (eventArgs == null || eventArgs.StopSearch != true) + if (eventArgs == null || !eventArgs.StopSearch) { do { @@ -994,7 +997,7 @@ private static CommandInfo TryNormalSearch(string commandName, { if (!searcher.MoveNext()) { - if (!commandName.Contains("-") && !commandName.Contains("\\")) + if (!commandName.Contains('-') && !commandName.Contains('\\')) { discoveryTracer.WriteLine( "The command [{0}] was not found, trying again with get- prepended", @@ -1050,7 +1053,6 @@ private static CommandInfo TryModuleAutoDiscovery(string commandName, if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoDiscoveryStart(commandName); CommandInfo result = null; - bool cleanupModuleAnalysisAppDomain = false; try { // If commandName had a slash, it was module-qualified or path-qualified. @@ -1073,8 +1075,6 @@ private static CommandInfo TryModuleAutoDiscovery(string commandName, discoveryTracer.WriteLine("Executing non module-qualified search: {0}", commandName); context.CommandDiscovery.RegisterLookupCommandInfoAction("ActiveModuleSearch", commandName); - cleanupModuleAnalysisAppDomain = context.TakeResponsibilityForModuleAnalysisAppDomain(); - // Get the available module files, preferring modules from $PSHOME so that user modules don't // override system modules during auto-loading if (etwEnabled) CommandDiscoveryEventSource.Log.SearchingForModuleFilesStart(); @@ -1139,10 +1139,6 @@ private static CommandInfo TryModuleAutoDiscovery(string commandName, finally { context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActiveModuleSearch", commandName); - if (cleanupModuleAnalysisAppDomain) - { - context.ReleaseResponsibilityForModuleAnalysisAppDomain(); - } } if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoDiscoveryStop(commandName); @@ -1281,10 +1277,10 @@ internal void UnregisterLookupCommandInfoAction(string currentAction, string com currentActionSet.Remove(command); } - private HashSet _activePreLookup = new HashSet(StringComparer.OrdinalIgnoreCase); - private HashSet _activeModuleSearch = new HashSet(StringComparer.OrdinalIgnoreCase); - private HashSet _activeCommandNotFound = new HashSet(StringComparer.OrdinalIgnoreCase); - private HashSet _activePostCommand = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly HashSet _activePreLookup = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly HashSet _activeModuleSearch = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly HashSet _activeCommandNotFound = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly HashSet _activePostCommand = new HashSet(StringComparer.OrdinalIgnoreCase); /// /// Gets the resolved paths contained in the PATH environment @@ -1348,7 +1344,7 @@ internal LookupPathCollection GetLookupDirectoryPaths() } // Cache the new lookup paths - return _cachedLookupPaths ?? (_cachedLookupPaths = result); + return _cachedLookupPaths ??= result; } /// @@ -1414,7 +1410,7 @@ private static void InitPathExtCache(string pathExt) lock (s_lockObject) { s_cachedPathExtCollection = pathExt != null - ? pathExt.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries) + ? pathExt.ToLower().Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries) : Array.Empty(); s_cachedPathExtCollectionWithPs1 = new string[s_cachedPathExtCollection.Length + 1]; s_cachedPathExtCollectionWithPs1[0] = StringLiterals.PowerShellScriptFileExtension; @@ -1428,7 +1424,7 @@ private static void InitPathExtCache(string pathExt) #region private members - private static object s_lockObject = new object(); + private static readonly object s_lockObject = new object(); private static string s_pathExtCacheKey; private static string[] s_cachedPathExtCollection; private static string[] s_cachedPathExtCollectionWithPs1; @@ -1737,4 +1733,3 @@ internal class CommandDiscoveryEventSource : EventSource public void ModuleManifestAnalysisException(string ModulePath, string Exception) { WriteEvent(12, ModulePath, Exception); } } } - diff --git a/src/System.Management.Automation/engine/CommandInfo.cs b/src/System.Management.Automation/engine/CommandInfo.cs index fd98949eff0..7e28fece99d 100644 --- a/src/System.Management.Automation/engine/CommandInfo.cs +++ b/src/System.Management.Automation/engine/CommandInfo.cs @@ -230,7 +230,10 @@ public virtual Version Version /// internal ExecutionContext Context { - get { return _context; } + get + { + return _context; + } set { @@ -478,7 +481,7 @@ private MergedCommandParameterMetadata GetMergedCommandParameterMetadataSafely() return result; } - private class GetMergedCommandParameterMetadataSafelyEventArgs : EventArgs + private sealed class GetMergedCommandParameterMetadataSafelyEventArgs : EventArgs { public MergedCommandParameterMetadata Result; public ExceptionDispatchInfo Exception; @@ -583,7 +586,7 @@ public virtual Dictionary Parameters internal CommandMetadata ExternalCommandMetadata { - get { return _externalCommandMetadata ?? (_externalCommandMetadata = new CommandMetadata(this, true)); } + get { return _externalCommandMetadata ??= new CommandMetadata(this, true); } set { _externalCommandMetadata = value; } } @@ -904,7 +907,7 @@ public override string ToString() } [DebuggerDisplay("{PSTypeName} {Name}")] - internal struct PSMemberNameAndType + internal readonly struct PSMemberNameAndType { public readonly string Name; @@ -925,7 +928,7 @@ public PSMemberNameAndType(string name, PSTypeName typeName, object value = null /// but can be used where a real type might not be available, in which case the name of the type can be used. /// The type encodes the members of dynamic objects in the type name. /// - internal class PSSyntheticTypeName : PSTypeName + internal sealed class PSSyntheticTypeName : PSTypeName { internal static PSSyntheticTypeName Create(string typename, IList membersTypes) => Create(new PSTypeName(typename), membersTypes); @@ -936,7 +939,7 @@ internal static PSSyntheticTypeName Create(PSTypeName typename, IList(); members.AddRange(membersTypes); - members.Sort((c1, c2) => string.Compare(c1.Name, c2.Name, StringComparison.OrdinalIgnoreCase)); + members.Sort(static (c1, c2) => string.Compare(c1.Name, c2.Name, StringComparison.OrdinalIgnoreCase)); return new PSSyntheticTypeName(typeName, typename.Type, members); } @@ -960,7 +963,7 @@ private PSSyntheticTypeName(string typeName, Type type, IList member.Name.Equals(nameof(PSTypeName), StringComparison.OrdinalIgnoreCase); + private static bool IsPSTypeName(in PSMemberNameAndType member) => member.Name.Equals(nameof(PSTypeName), StringComparison.OrdinalIgnoreCase); private static string GetMemberTypeProjection(string typename, IList members) { @@ -977,11 +980,11 @@ private static string GetMemberTypeProjection(string typename, IList m.Name)) + foreach (var m in members.OrderBy(static m => m.Name)) { if (!IsPSTypeName(m)) { - builder.Append(m.Name).Append(":"); + builder.Append(m.Name).Append(':'); } } @@ -992,6 +995,7 @@ private static string GetMemberTypeProjection(string typename, IList Members { get; } } +#nullable enable internal interface IScriptCommandInfo { ScriptBlock ScriptBlock { get; } diff --git a/src/System.Management.Automation/engine/CommandMetadata.cs b/src/System.Management.Automation/engine/CommandMetadata.cs index edcd9a9cd66..eb59f9140a2 100644 --- a/src/System.Management.Automation/engine/CommandMetadata.cs +++ b/src/System.Management.Automation/engine/CommandMetadata.cs @@ -464,7 +464,10 @@ internal CommandMetadata(ScriptBlock scriptblock, string commandName, ExecutionC /// public string DefaultParameterSetName { - get { return _defaultParameterSetName; } + get + { + return _defaultParameterSetName; + } set { @@ -528,7 +531,10 @@ public RemotingCapability RemotingCapability return _remotingCapability; } - set { _remotingCapability = value; } + set + { + _remotingCapability = value; + } } private RemotingCapability _remotingCapability = RemotingCapability.PowerShell; @@ -680,7 +686,7 @@ private void ConstructCmdletMetadataUsingReflection() // Determine if the cmdlet implements dynamic parameters by looking for the interface - Type dynamicParametersType = CommandType.GetInterface(typeof(IDynamicParameters).Name, true); + Type dynamicParametersType = CommandType.GetInterface(nameof(IDynamicParameters), true); if (dynamicParametersType != null) { @@ -897,7 +903,7 @@ internal string GetDecl() decl.Append(separator); decl.Append("DefaultParameterSetName='"); decl.Append(CodeGeneration.EscapeSingleQuotedStringContent(_defaultParameterSetName)); - decl.Append("'"); + decl.Append('\''); separator = ", "; } @@ -909,7 +915,7 @@ internal string GetDecl() decl.Append(separator); decl.Append("ConfirmImpact='"); decl.Append(ConfirmImpact); - decl.Append("'"); + decl.Append('\''); } if (SupportsPaging) @@ -926,7 +932,7 @@ internal string GetDecl() separator = ", "; } - if (PositionalBinding == false) + if (!PositionalBinding) { decl.Append(separator); decl.Append("PositionalBinding=$false"); @@ -938,7 +944,7 @@ internal string GetDecl() decl.Append(separator); decl.Append("HelpUri='"); decl.Append(CodeGeneration.EscapeSingleQuotedStringContent(HelpUri)); - decl.Append("'"); + decl.Append('\''); separator = ", "; } @@ -947,7 +953,7 @@ internal string GetDecl() decl.Append(separator); decl.Append("RemotingCapability='"); decl.Append(_remotingCapability); - decl.Append("'"); + decl.Append('\''); separator = ", "; } @@ -1316,7 +1322,7 @@ public static Dictionary GetRestrictedCommands(SessionC List restrictedCommands = new List(); // all remoting cmdlets need to be included for workflow scenarios as wel - if (SessionCapabilities.RemoteServer == (sessionCapabilities & SessionCapabilities.RemoteServer)) + if ((sessionCapabilities & SessionCapabilities.RemoteServer) == SessionCapabilities.RemoteServer) { restrictedCommands.AddRange(GetRestrictedRemotingCommands()); } @@ -1533,7 +1539,7 @@ private static Collection GetRestrictedJobCommands() /// The command metadata cache. This is separate from the parameterMetadata cache /// because it is specific to cmdlets. /// - private static System.Collections.Concurrent.ConcurrentDictionary s_commandMetadataCache = + private static readonly System.Collections.Concurrent.ConcurrentDictionary s_commandMetadataCache = new System.Collections.Concurrent.ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); #endregion diff --git a/src/System.Management.Automation/engine/CommandParameter.cs b/src/System.Management.Automation/engine/CommandParameter.cs index b13cc94ad40..227795cf1d6 100644 --- a/src/System.Management.Automation/engine/CommandParameter.cs +++ b/src/System.Management.Automation/engine/CommandParameter.cs @@ -12,14 +12,14 @@ namespace System.Management.Automation [DebuggerDisplay("{ParameterName}")] internal sealed class CommandParameterInternal { - private class Parameter + private sealed class Parameter { internal Ast ast; internal string parameterName; internal string parameterText; } - private class Argument + private sealed class Argument { internal Ast ast; internal object value; @@ -116,7 +116,7 @@ internal object ArgumentValue /// internal bool ArgumentToBeSplatted { - get { return _argument != null ? _argument.splatted : false; } + get { return _argument != null && _argument.splatted; } } /// diff --git a/src/System.Management.Automation/engine/CommandPathSearch.cs b/src/System.Management.Automation/engine/CommandPathSearch.cs index 1929000d7d3..a761aa638cb 100644 --- a/src/System.Management.Automation/engine/CommandPathSearch.cs +++ b/src/System.Management.Automation/engine/CommandPathSearch.cs @@ -346,9 +346,12 @@ public bool MoveNext() /// public void Reset() { + _lookupPathsEnumerator.Dispose(); _lookupPathsEnumerator = _lookupPaths.GetEnumerator(); + _patternEnumerator.Dispose(); _patternEnumerator = _patterns.GetEnumerator(); _currentDirectoryResults = Array.Empty(); + _currentDirectoryResultsEnumerator.Dispose(); _currentDirectoryResultsEnumerator = _currentDirectoryResults.GetEnumerator(); _justReset = true; } @@ -531,7 +534,7 @@ private void GetNewDirectoryResults(string pattern, string directory) /// The directory paths in which to look for commands. /// This is derived from the PATH environment variable. /// - private LookupPathCollection _lookupPaths; + private readonly LookupPathCollection _lookupPaths; /// /// The enumerator for the lookup paths. @@ -552,7 +555,7 @@ private void GetNewDirectoryResults(string pattern, string directory) /// /// The command name to search for. /// - private IEnumerable _patterns; + private readonly IEnumerable _patterns; /// /// The enumerator for the patterns. @@ -562,7 +565,7 @@ private void GetNewDirectoryResults(string pattern, string directory) /// /// A reference to the execution context for this runspace. /// - private ExecutionContext _context; + private readonly ExecutionContext _context; /// /// When reset is called, this gets set to true. Once MoveNext @@ -573,14 +576,13 @@ private void GetNewDirectoryResults(string pattern, string directory) /// /// If not null, called with the enumerated files for further processing. /// - private Func?> _postProcessEnumeratedFiles; + private readonly Func?> _postProcessEnumeratedFiles; - private string[] _orderedPathExt; - private Collection? _acceptableCommandNames; + private readonly string[] _orderedPathExt; + private readonly Collection? _acceptableCommandNames; - private bool _useFuzzyMatch = false; + private readonly bool _useFuzzyMatch = false; #endregion private members } } - diff --git a/src/System.Management.Automation/engine/CommandProcessor.cs b/src/System.Management.Automation/engine/CommandProcessor.cs index 4433d75ca99..fb1fe81fc54 100644 --- a/src/System.Management.Automation/engine/CommandProcessor.cs +++ b/src/System.Management.Automation/engine/CommandProcessor.cs @@ -101,8 +101,7 @@ internal CommandProcessor(IScriptCommandInfo scriptCommandInfo, ExecutionContext /// internal ParameterBinderController NewParameterBinderController(InternalCommand command) { - Cmdlet cmdlet = command as Cmdlet; - if (cmdlet == null) + if (!(command is Cmdlet cmdlet)) { throw PSTraceSource.NewArgumentException(nameof(command)); } @@ -319,7 +318,7 @@ internal override void ProcessRecord() // NOTICE-2004/06/08-JonN 959638 using (commandRuntime.AllowThisCommandToWrite(true)) { - if (Context._debuggingMode > 0 && !(Command is PSScriptCmdlet)) + if (Context._debuggingMode > 0 && Command is not PSScriptCmdlet) { Context.Debugger.CheckCommand(this.Command.MyInvocation); } @@ -528,7 +527,7 @@ internal sealed override bool Read() try { // Process the input pipeline object - if (false == ProcessInputPipelineObject(inputObject)) + if (!ProcessInputPipelineObject(inputObject)) { // The input object was not bound to any parameters of the cmdlet. // Write a non-terminating error and continue with the next input @@ -608,7 +607,7 @@ private void WriteInputObjectError( string errorId, params object[] args) { - Type inputObjectType = (inputObject == null) ? null : inputObject.GetType(); + Type inputObjectType = inputObject?.GetType(); ParameterBindingException bindingException = new ParameterBindingException( ErrorCategory.InvalidArgument, @@ -825,7 +824,7 @@ private void InitCommon() /// /// Help target to request. /// Help category to request. - /// true if user requested help; false otherwise. + /// if user requested help; otherwise. internal override bool IsHelpRequested(out string helpTarget, out HelpCategory helpCategory) { if (this.arguments != null) @@ -870,4 +869,3 @@ internal override bool IsHelpRequested(out string helpTarget, out HelpCategory h #endregion helper_methods } } - diff --git a/src/System.Management.Automation/engine/CommandProcessorBase.cs b/src/System.Management.Automation/engine/CommandProcessorBase.cs index 87fd4606c9f..c6825cc6925 100644 --- a/src/System.Management.Automation/engine/CommandProcessorBase.cs +++ b/src/System.Management.Automation/engine/CommandProcessorBase.cs @@ -121,7 +121,10 @@ internal bool AddedToPipelineAlready /// internal InternalCommand Command { - get { return _command; } + get + { + return _command; + } set { @@ -149,6 +152,7 @@ internal virtual ObsoleteAttribute ObsoleteAttribute { get { return null; } } + // Full Qualified ID for the obsolete command warning private const string FQIDCommandObsolete = "CommandObsolete"; @@ -256,7 +260,7 @@ internal ExecutionContext Context /// /// Help target to request. /// Help category to request. - /// true if user requested help; false otherwise. + /// if user requested help; otherwise. internal virtual bool IsHelpRequested(out string helpTarget, out HelpCategory helpCategory) { // by default we don't handle "-?" parameter at all @@ -517,7 +521,7 @@ internal virtual void DoBegin() { SetCurrentScopeToExecutionScope(); - if (Context._debuggingMode > 0 && !(Command is PSScriptCmdlet)) + if (Context._debuggingMode > 0 && Command is not PSScriptCmdlet) { Context.Debugger.CheckCommand(this.Command.MyInvocation); } @@ -896,7 +900,7 @@ internal void ManageScriptException(RuntimeException e) // An explicit throw is written to $error as an ErrorRecord, so we // skip adding what is more or less a duplicate. - if (!(e is PipelineStoppedException) && !e.WasThrownFromThrowStatement) + if (e is not PipelineStoppedException && !e.WasThrownFromThrowStatement) commandRuntime.AppendErrorToVariables(e); } // Upstream cmdlets see only that execution stopped @@ -956,14 +960,6 @@ private void Dispose(bool disposing) _disposed = true; } - /// - /// Finalizer for class CommandProcessorBase. - /// - ~CommandProcessorBase() - { - Dispose(false); - } - #endregion IDispose } } diff --git a/src/System.Management.Automation/engine/CommandSearcher.cs b/src/System.Management.Automation/engine/CommandSearcher.cs index d3a1033c932..9745d2aa9ad 100644 --- a/src/System.Management.Automation/engine/CommandSearcher.cs +++ b/src/System.Management.Automation/engine/CommandSearcher.cs @@ -842,7 +842,7 @@ private static bool checkPath(string path, string commandName) // Don't return commands to the user if that might result in: // - Trusted commands calling untrusted functions that the user has overridden // - Debug prompts calling internal functions that are likely to have code injection - private bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInfo? result, ExecutionContext executionContext) + private static bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInfo? result, ExecutionContext executionContext) { if (result == null) { @@ -1087,7 +1087,7 @@ private bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInfo? resu string? result = null; if (_context.EngineSessionState != null && - _context.EngineSessionState.ProviderCount > 0) + _context.EngineSessionState.ProviderCount > 0 && _commandName.Length != 0) { // NTRAID#Windows OS Bugs-1009294-2004/02/04-JeffJon // This is really slow. Maybe since we are only allowing FS paths right @@ -1099,7 +1099,9 @@ private bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInfo? resu // Relative Path: ".\command.exe" // Home Path: "~\command.exe" // Drive Relative Path: "\Users\User\AppData\Local\Temp\command.exe" - if (_commandName[0] == '.' || _commandName[0] == '~' || _commandName[0] == '\\') + + char firstChar = _commandName[0]; + if (firstChar == '.' || firstChar == '~' || firstChar == '\\') { using (CommandDiscovery.discoveryTracer.TraceScope( "{0} appears to be a relative path. Trying to resolve relative path", @@ -1334,10 +1336,6 @@ private bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInfo? resu /// internal LookupPathCollection ConstructSearchPatternsFromName(string name, bool commandDiscovery = false) { - Dbg.Assert( - !string.IsNullOrEmpty(name), - "Caller should verify name"); - var result = new LookupPathCollection(); // First check to see if the commandName has an extension, if so diff --git a/src/System.Management.Automation/engine/CommonCommandParameters.cs b/src/System.Management.Automation/engine/CommonCommandParameters.cs index 9cc0b2ad899..376b9d0adbf 100644 --- a/src/System.Management.Automation/engine/CommonCommandParameters.cs +++ b/src/System.Management.Automation/engine/CommonCommandParameters.cs @@ -234,7 +234,7 @@ public string PipelineVariable #endregion parameters - private MshCommandRuntime _commandRuntime; + private readonly MshCommandRuntime _commandRuntime; internal class ValidateVariableName : ValidateArgumentsAttribute { @@ -261,4 +261,3 @@ protected override void Validate(object arguments, EngineIntrinsics engineIntrin } } } - diff --git a/src/System.Management.Automation/engine/CompiledCommandParameter.cs b/src/System.Management.Automation/engine/CompiledCommandParameter.cs index 90011fbde74..2f17fca8fcd 100644 --- a/src/System.Management.Automation/engine/CompiledCommandParameter.cs +++ b/src/System.Management.Automation/engine/CompiledCommandParameter.cs @@ -625,7 +625,7 @@ internal ParameterCollectionTypeInformation(Type type) return; } - bool implementsIList = (type.GetInterface(typeof(IList).Name) != null); + bool implementsIList = (type.GetInterface(nameof(IList)) != null); // Look for class Collection. Collection implements IList, and also IList // is more efficient to bind than ICollection. This optimization @@ -649,7 +649,7 @@ internal ParameterCollectionTypeInformation(Type type) // to an ICollection is via reflected calls to Add(T), // but the advantage over plain IList is that we can typecast the elements. Type interfaceICollection = - Array.Find(interfaces, i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)); + Array.Find(interfaces, static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)); if (interfaceICollection != null) { // We only deal with the first type for which ICollection is implemented diff --git a/src/System.Management.Automation/engine/ContentCmdletProviderInterfaces.cs b/src/System.Management.Automation/engine/ContentCmdletProviderInterfaces.cs index 382f6b7e46a..a5ede5c7c97 100644 --- a/src/System.Management.Automation/engine/ContentCmdletProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/ContentCmdletProviderInterfaces.cs @@ -586,10 +586,9 @@ internal object ClearContentDynamicParameters(string path, CmdletProviderContext #region private data - private Cmdlet _cmdlet; - private SessionStateInternal _sessionState; + private readonly Cmdlet _cmdlet; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/CoreAdapter.cs b/src/System.Management.Automation/engine/CoreAdapter.cs index b6752387d58..1a623e92f1e 100644 --- a/src/System.Management.Automation/engine/CoreAdapter.cs +++ b/src/System.Management.Automation/engine/CoreAdapter.cs @@ -1157,8 +1157,8 @@ private static int CompareTypeSpecificity(OverloadCandidate candidate1, Overload return 0; } - Type[] params1 = GetGenericMethodDefinitionIfPossible(candidate1.method.method).GetParameters().Select(p => p.ParameterType).ToArray(); - Type[] params2 = GetGenericMethodDefinitionIfPossible(candidate2.method.method).GetParameters().Select(p => p.ParameterType).ToArray(); + Type[] params1 = GetGenericMethodDefinitionIfPossible(candidate1.method.method).GetParameters().Select(static p => p.ParameterType).ToArray(); + Type[] params2 = GetGenericMethodDefinitionIfPossible(candidate2.method.method).GetParameters().Select(static p => p.ParameterType).ToArray(); return CompareTypeSpecificity(params1, params2); } @@ -1177,7 +1177,7 @@ private static MethodBase GetGenericMethodDefinitionIfPossible(MethodBase method } [DebuggerDisplay("OverloadCandidate: {method.methodDefinition}")] - private class OverloadCandidate + private sealed class OverloadCandidate { internal MethodInformation method; internal ParameterInformation[] parameters; @@ -1363,7 +1363,7 @@ internal static MethodInformation FindBestMethod( Type targetType = methodInfo.method.DeclaringType; if (targetType != invocationConstraints.MethodTargetType && targetType.IsSubclassOf(invocationConstraints.MethodTargetType)) { - var parameterTypes = methodInfo.method.GetParameters().Select(parameter => parameter.ParameterType).ToArray(); + var parameterTypes = methodInfo.method.GetParameters().Select(static parameter => parameter.ParameterType).ToArray(); var targetTypeMethod = invocationConstraints.MethodTargetType.GetMethod(methodInfo.method.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null); if (targetTypeMethod != null && (targetTypeMethod.IsPublic || targetTypeMethod.IsFamily || targetTypeMethod.IsFamilyOrAssembly)) @@ -1395,8 +1395,8 @@ private static MethodInformation FindBestMethodImpl( // We also skip the optimization if the number of arguments and parameters is different // so we let the loop deal with possible optional parameters. if ((methods.Length == 1) && - (methods[0].hasVarArgs == false) && - (methods[0].isGeneric == false) && + (!methods[0].hasVarArgs) && + (!methods[0].isGeneric) && (methods[0].method == null || !(methods[0].method.DeclaringType.IsGenericTypeDefinition)) && // generic methods need to be double checked in a loop below - generic methods can be rejected if type inference fails (methods[0].parameters.Length == arguments.Length)) @@ -1581,7 +1581,7 @@ private static MethodInformation FindBestMethodImpl( if (candidates.Count == 0) { - if ((methods.Length > 0) && (methods.All(m => m.method != null && m.method.DeclaringType.IsGenericTypeDefinition && m.method.IsStatic))) + if ((methods.Length > 0) && (methods.All(static m => m.method != null && m.method.DeclaringType.IsGenericTypeDefinition && m.method.IsStatic))) { errorId = "CannotInvokeStaticMethodOnUninstantiatedGenericType"; errorMsg = string.Format( @@ -1658,8 +1658,7 @@ internal static void SetReferences(object[] arguments, MethodInformation methodI // It still might be an PSObject wrapping an PSReference if (originalArgumentReference == null) { - PSObject originalArgumentObj = originalArgument as PSObject; - if (originalArgumentObj == null) + if (!(originalArgument is PSObject originalArgumentObj)) { continue; } @@ -2014,7 +2013,7 @@ internal class CacheTable /// . /// internal Collection memberCollection; - private Dictionary _indexes; + private readonly Dictionary _indexes; internal CacheTable() { @@ -2217,7 +2216,7 @@ internal object Invoke(object target, object[] arguments) return method.Invoke(target, arguments); } - private static OpCode[] s_ldc = new OpCode[] { + private static readonly OpCode[] s_ldc = new OpCode[] { OpCodes.Ldc_I4_0, OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_3, OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_5, OpCodes.Ldc_I4_6, OpCodes.Ldc_I4_7, OpCodes.Ldc_I4_8 }; @@ -2562,7 +2561,7 @@ internal class DotNetAdapter : Adapter private const BindingFlags staticBindingFlags = (BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Static); - private bool _isStatic; + private readonly bool _isStatic; internal DotNetAdapter() { } @@ -2575,25 +2574,25 @@ internal DotNetAdapter(bool isStatic) /// /// CLR reflection property cache for instance properties. /// - private static Dictionary s_instancePropertyCacheTable = new Dictionary(); + private static readonly Dictionary s_instancePropertyCacheTable = new Dictionary(); // This static is thread safe based on the lock in GetStaticPropertyReflectionTable /// /// CLR reflection property cache for static properties. /// - private static Dictionary s_staticPropertyCacheTable = new Dictionary(); + private static readonly Dictionary s_staticPropertyCacheTable = new Dictionary(); // This static is thread safe based on the lock in GetInstanceMethodReflectionTable /// /// CLR reflection method cache for instance methods. /// - private static Dictionary s_instanceMethodCacheTable = new Dictionary(); + private static readonly Dictionary s_instanceMethodCacheTable = new Dictionary(); // This static is thread safe based on the lock in GetStaticMethodReflectionTable /// /// CLR reflection method cache for static methods. /// - private static Dictionary s_staticMethodCacheTable = new Dictionary(); + private static readonly Dictionary s_staticMethodCacheTable = new Dictionary(); // This static is thread safe based on the lock in GetInstanceMethodReflectionTable /// @@ -2617,7 +2616,7 @@ internal class MethodCacheEntry : CacheEntry /// internal Func PSMethodCtor; - internal MethodCacheEntry(MethodBase[] methods) + internal MethodCacheEntry(IList methods) { methodInformationStructures = DotNetAdapter.GetMethodInformationArray(methods); } @@ -2722,7 +2721,7 @@ internal ParameterizedPropertyCacheEntry(List properties) definition.Append(" {"); definition.Append(extraDefinition); - definition.Append("}"); + definition.Append('}'); definitionArray.Add(definition.ToString()); } @@ -2748,6 +2747,7 @@ internal ParameterizedPropertyCacheEntry(List properties) internal class PropertyCacheEntry : CacheEntry { internal delegate object GetterDelegate(object instance); + internal delegate void SetterDelegate(object instance, object setValue); internal PropertyCacheEntry(PropertyInfo property) @@ -3075,9 +3075,8 @@ private static void AddOverload(List previousMethodEntry, MethodInfo private static void PopulateMethodReflectionTable(Type type, MethodInfo[] methods, CacheTable typeMethods) { - for (int i = 0; i < methods.Length; i++) + foreach (MethodInfo method in methods) { - MethodInfo method = methods[i]; if (method.DeclaringType == type) { string methodName = method.Name; @@ -3102,7 +3101,7 @@ private static void PopulateMethodReflectionTable(Type type, MethodInfo[] method private static void PopulateMethodReflectionTable(ConstructorInfo[] ctors, CacheTable typeMethods) { - foreach (var ctor in ctors) + foreach (ConstructorInfo ctor in ctors) { var previousMethodEntry = (List)typeMethods["new"]; if (previousMethodEntry == null) @@ -3127,26 +3126,14 @@ private static void PopulateMethodReflectionTable(ConstructorInfo[] ctors, Cache /// BindingFlags to use. private static void PopulateMethodReflectionTable(Type type, CacheTable typeMethods, BindingFlags bindingFlags) { - Type typeToGetMethod = type; - - // Assemblies in CoreCLR might not allow reflection execution on their internal types. In such case, we walk up - // the derivation chain to find the first public parent, and use reflection methods on the public parent. - if (!TypeResolver.IsPublic(type) && DisallowPrivateReflection(type)) - { - typeToGetMethod = GetFirstPublicParentType(type); - } + bool isStatic = bindingFlags.HasFlag(BindingFlags.Static); - // In CoreCLR, "GetFirstPublicParentType" may return null if 'type' is an interface - if (typeToGetMethod != null) - { - MethodInfo[] methods = typeToGetMethod.GetMethods(bindingFlags); - PopulateMethodReflectionTable(typeToGetMethod, methods, typeMethods); - } + MethodInfo[] methods = type.GetMethods(bindingFlags); + PopulateMethodReflectionTable(type, methods, typeMethods); Type[] interfaces = type.GetInterfaces(); - for (int interfaceIndex = 0; interfaceIndex < interfaces.Length; interfaceIndex++) + foreach (Type interfaceType in interfaces) { - var interfaceType = interfaces[interfaceIndex]; if (!TypeResolver.IsPublic(interfaceType)) { continue; @@ -3154,41 +3141,50 @@ private static void PopulateMethodReflectionTable(Type type, CacheTable typeMeth if (interfaceType.IsGenericType && type.IsArray) { - continue; // GetInterfaceMap is not supported in this scenario... not sure if we need to do something special here... + // A bit of background: Array doesn't directly support any generic interface at all. Instead, a stub class + // named 'SZArrayHelper' provides these generic interfaces at runtime for zero-based one-dimension arrays. + // This is why '[object[]].GetInterfaceMap([ICollection[object]])' throws 'ArgumentException'. + // (see https://stackoverflow.com/a/31883327) + // + // We had always been skipping generic interfaces for array types because 'GetInterfaceMap' doesn't work + // for it. Today, even though we don't use 'GetInterfaceMap' anymore, the same code is kept here because + // methods from generic interfaces of an array type could cause ambiguity in method overloads resolution. + // For example, "$objs = @(1,2,3,4); $objs.Contains(1)" would fail because there would be 2 overloads of + // the 'Contains' methods which are equally good matches for the call. + // bool IList.Contains(System.Object value) + // bool ICollection[Object].Contains(System.Object item) + continue; } - MethodInfo[] methods; - if (type.IsInterface) - { - methods = interfaceType.GetMethods(bindingFlags); - } - else - { - InterfaceMapping interfaceMapping = type.GetInterfaceMap(interfaceType); - methods = interfaceMapping.InterfaceMethods; - } + methods = interfaceType.GetMethods(bindingFlags); - for (int methodIndex = 0; methodIndex < methods.Length; methodIndex++) + foreach (MethodInfo interfaceMethod in methods) { - MethodInfo interfaceMethodDefinition = methods[methodIndex]; - - if ((!interfaceMethodDefinition.IsPublic) || - (interfaceMethodDefinition.IsStatic != ((BindingFlags.Static & bindingFlags) != 0))) + if (isStatic && interfaceMethod.IsVirtual) { + // Ignore static virtual/abstract methods on an interface because: + // 1. if it's implicitly implemented, which will be mostly the case, then the corresponding + // methods were already retrieved from the 'type.GetMethods' step above; + // 2. if it's explicitly implemented, we cannot call 'Invoke(null, args)' on the static method, + // but have to use 'type.GetInterfaceMap(interfaceType)' to get the corresponding target + // methods, and call 'Invoke(null, args)' on them. The target methods will be non-public + // in this case, which we always ignore. + // 3. The recommendation from .NET team is to ignore the static virtuals on interfaces, + // especially given that the APIs may change in .NET 7. continue; } - var previousMethodEntry = (List)typeMethods[interfaceMethodDefinition.Name]; + var previousMethodEntry = (List)typeMethods[interfaceMethod.Name]; if (previousMethodEntry == null) { - var methodEntry = new List { interfaceMethodDefinition }; - typeMethods.Add(interfaceMethodDefinition.Name, methodEntry); + var methodEntry = new List { interfaceMethod }; + typeMethods.Add(interfaceMethod.Name, methodEntry); } else { - if (!previousMethodEntry.Contains(interfaceMethodDefinition)) + if (!previousMethodEntry.Contains(interfaceMethod)) { - previousMethodEntry.Add(interfaceMethodDefinition); + previousMethodEntry.Add(interfaceMethod); } } } @@ -3211,7 +3207,7 @@ private static void PopulateMethodReflectionTable(Type type, CacheTable typeMeth for (int i = 0; i < typeMethods.memberCollection.Count; i++) { typeMethods.memberCollection[i] = - new MethodCacheEntry(((List)typeMethods.memberCollection[i]).ToArray()); + new MethodCacheEntry((List)typeMethods.memberCollection[i]); } } @@ -3224,38 +3220,24 @@ private static void PopulateMethodReflectionTable(Type type, CacheTable typeMeth /// BindingFlags to use. private static void PopulateEventReflectionTable(Type type, Dictionary typeEvents, BindingFlags bindingFlags) { - // Assemblies in CoreCLR might not allow reflection execution on their internal types. In such case, we walk up - // the derivation chain to find the first public parent, and use reflection events on the public parent. - if (!TypeResolver.IsPublic(type) && DisallowPrivateReflection(type)) - { - type = GetFirstPublicParentType(type); - } + EventInfo[] events = type.GetEvents(bindingFlags); + var tempTable = new Dictionary>(StringComparer.OrdinalIgnoreCase); - // In CoreCLR, "GetFirstPublicParentType" may return null if 'type' is an interface - if (type != null) + foreach (EventInfo typeEvent in events) { - EventInfo[] events = type.GetEvents(bindingFlags); - var tempTable = new Dictionary>(StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < events.Length; i++) + string eventName = typeEvent.Name; + if (!tempTable.TryGetValue(eventName, out List entryList)) { - var typeEvent = events[i]; - string eventName = typeEvent.Name; - List previousEntry; - if (!tempTable.TryGetValue(eventName, out previousEntry)) - { - var eventEntry = new List { typeEvent }; - tempTable.Add(eventName, eventEntry); - } - else - { - previousEntry.Add(typeEvent); - } + entryList = new List(); + tempTable.Add(eventName, entryList); } - foreach (var entry in tempTable) - { - typeEvents.Add(entry.Key, new EventCacheEntry(entry.Value.ToArray())); - } + entryList.Add(typeEvent); + } + + foreach (KeyValuePair> entry in tempTable) + { + typeEvents.Add(entry.Key, new EventCacheEntry(entry.Value.ToArray())); } } @@ -3270,9 +3252,8 @@ private static bool PropertyAlreadyPresent(List previousProperties ParameterInfo[] propertyParameters = property.GetIndexParameters(); int propertyIndexLength = propertyParameters.Length; - for (int propertyIndex = 0; propertyIndex < previousProperties.Count; propertyIndex++) + foreach (PropertyInfo previousProperty in previousProperties) { - var previousProperty = previousProperties[propertyIndex]; ParameterInfo[] previousParameters = previousProperty.GetIndexParameters(); if (previousParameters.Length == propertyIndexLength) { @@ -3308,79 +3289,81 @@ private static bool PropertyAlreadyPresent(List previousProperties /// BindingFlags to use. private static void PopulatePropertyReflectionTable(Type type, CacheTable typeProperties, BindingFlags bindingFlags) { + bool isStatic = bindingFlags.HasFlag(BindingFlags.Static); var tempTable = new Dictionary>(StringComparer.OrdinalIgnoreCase); - Type typeToGetPropertyAndField = type; - // Assemblies in CoreCLR might not allow reflection execution on their internal types. In such case, we walk up the - // derivation chain to find the first public parent, and use reflection properties/fields on the public parent. - if (!TypeResolver.IsPublic(type) && DisallowPrivateReflection(type)) + PropertyInfo[] properties = type.GetProperties(bindingFlags); + foreach (PropertyInfo property in properties) { - typeToGetPropertyAndField = GetFirstPublicParentType(type); - } - - // In CoreCLR, "GetFirstPublicParentType" may return null if 'type' is an interface - PropertyInfo[] properties; - if (typeToGetPropertyAndField != null) - { - properties = typeToGetPropertyAndField.GetProperties(bindingFlags); - for (int i = 0; i < properties.Length; i++) - { - PopulateSingleProperty(type, properties[i], tempTable, properties[i].Name); - } + PopulateSingleProperty(type, property, tempTable, property.Name); } Type[] interfaces = type.GetInterfaces(); - for (int interfaceIndex = 0; interfaceIndex < interfaces.Length; interfaceIndex++) + foreach (Type interfaceType in interfaces) { - Type interfaceType = interfaces[interfaceIndex]; if (!TypeResolver.IsPublic(interfaceType)) { continue; } properties = interfaceType.GetProperties(bindingFlags); - for (int propertyIndex = 0; propertyIndex < properties.Length; propertyIndex++) + foreach (PropertyInfo property in properties) { - PopulateSingleProperty(type, properties[propertyIndex], tempTable, properties[propertyIndex].Name); + if (isStatic && + (property.GetMethod?.IsVirtual == true || property.SetMethod?.IsVirtual == true)) + { + // Ignore static virtual/abstract properties on an interface because: + // 1. if it's implicitly implemented, which will be mostly the case, then the corresponding + // properties were already retrieved from the 'type.GetProperties' step above; + // 2. if it's explicitly implemented, we cannot call 'GetValue(null)' on the static property, + // but have to use 'type.GetInterfaceMap(interfaceType)' to get the corresponding target + // get/set accessor methods, and call 'Invoke(null, args)' on them. The target methods will + // be non-public in this case, which we always ignore. + // 3. The recommendation from .NET team is to ignore the static virtuals on interfaces, + // especially given that the APIs may change in .NET 7. + continue; + } + + PopulateSingleProperty(type, property, tempTable, property.Name); } } - foreach (var pairs in tempTable) + foreach (KeyValuePair> entry in tempTable) { - var propertiesList = pairs.Value; + List propertiesList = entry.Value; PropertyInfo firstProperty = propertiesList[0]; if ((propertiesList.Count > 1) || (firstProperty.GetIndexParameters().Length != 0)) { - typeProperties.Add(pairs.Key, new ParameterizedPropertyCacheEntry(propertiesList)); + typeProperties.Add(entry.Key, new ParameterizedPropertyCacheEntry(propertiesList)); } else { - typeProperties.Add(pairs.Key, new PropertyCacheEntry(firstProperty)); + typeProperties.Add(entry.Key, new PropertyCacheEntry(firstProperty)); } } - // In CoreCLR, "GetFirstPublicParentType" may return null if 'type' is an interface - if (typeToGetPropertyAndField != null) + FieldInfo[] fields = type.GetFields(bindingFlags); + foreach (FieldInfo field in fields) { - FieldInfo[] fields = typeToGetPropertyAndField.GetFields(bindingFlags); - for (int i = 0; i < fields.Length; i++) + string fieldName = field.Name; + var previousMember = (PropertyCacheEntry)typeProperties[fieldName]; + if (previousMember == null) { - FieldInfo field = fields[i]; - string fieldName = field.Name; - var previousMember = (PropertyCacheEntry)typeProperties[fieldName]; - if (previousMember == null) - { - typeProperties.Add(fieldName, new PropertyCacheEntry(field)); - } - else - { - // A property/field declared with new in a derived class might appear twice - if (!string.Equals(previousMember.member.Name, fieldName)) - { - throw new ExtendedTypeSystemException("NotACLSComplaintField", null, - ExtendedTypeSystem.NotAClsCompliantFieldProperty, fieldName, type.FullName, previousMember.member.Name); - } - } + typeProperties.Add(fieldName, new PropertyCacheEntry(field)); + } + else if (!string.Equals(previousMember.member.Name, fieldName)) + { + // A property/field declared with 'new' in a derived class might appear twice, and it's OK to ignore + // the second property/field in that case. + // However, if the names of two properties/fields are different only in letter casing, then it's not + // CLS complaint and we throw an exception. + throw new ExtendedTypeSystemException( + "NotACLSComplaintField", + innerException: null, + ExtendedTypeSystem.NotAClsCompliantFieldProperty, + fieldName, + type.FullName, + previousMember.member.Name); } } } @@ -3411,66 +3394,6 @@ private static void PopulateSingleProperty(Type type, PropertyInfo property, Dic } } - #region Handle_Internal_Type_Reflection_In_CoreCLR - - /// - /// The dictionary cache about if an assembly supports reflection execution on its internal types. - /// - private static readonly ConcurrentDictionary s_disallowReflectionCache = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Check if the type is defined in an assembly that disallows reflection execution on internal types. - /// - .NET Framework assemblies don't support reflection execution on their internal types. - /// - internal static bool DisallowPrivateReflection(Type type) - { - bool disallowReflection = false; - Assembly assembly = type.Assembly; - if (s_disallowReflectionCache.TryGetValue(assembly.FullName, out disallowReflection)) - { - return disallowReflection; - } - - var productAttribute = assembly.GetCustomAttribute(); - if (productAttribute != null && string.Equals(productAttribute.Product, "Microsoft® .NET Framework", StringComparison.OrdinalIgnoreCase)) - { - disallowReflection = true; - } - else - { - // Check for 'DisablePrivateReflectionAttribute'. It's applied at the assembly level, and allow an assembly to opt-out of private/internal reflection. - var disablePrivateReflectionAttribute = assembly.GetCustomAttribute(); - disallowReflection = disablePrivateReflectionAttribute != null; - } - - s_disallowReflectionCache.TryAdd(assembly.FullName, disallowReflection); - return disallowReflection; - } - - /// - /// Walk up the derivation chain to find the first public parent type. - /// - internal static Type GetFirstPublicParentType(Type type) - { - Dbg.Assert(!TypeResolver.IsPublic(type), "type should not be public."); - Type parent = type.BaseType; - while (parent != null) - { - if (parent.IsPublic) - { - return parent; - } - - parent = parent.BaseType; - } - - // Return null when type is an interface - return null; - } - - #endregion Handle_Internal_Type_Reflection_In_CoreCLR - /// /// Called from GetProperty and GetProperties to populate the /// typeTable with all public properties and fields @@ -3878,8 +3801,7 @@ internal void AddAllDynamicMembers(object obj, PSMemberInfoInternalCollection private static bool PropertyIsStatic(PSProperty property) { - PropertyCacheEntry entry = property.adapterData as PropertyCacheEntry; - if (entry == null) + if (!(property.adapterData is PropertyCacheEntry entry)) { return false; } @@ -3895,7 +3817,7 @@ private static bool PropertyIsStatic(PSProperty property) internal override bool CanSiteBinderOptimize(MemberTypes typeToOperateOn) { return true; } - private static ConcurrentDictionary s_typeToTypeNameDictionary = + private static readonly ConcurrentDictionary s_typeToTypeNameDictionary = new ConcurrentDictionary(); internal static ConsolidatedString GetInternedTypeNameHierarchy(Type type) @@ -3995,7 +3917,7 @@ protected override string PropertyToString(PSProperty property) } returnValue.Append(PropertyType(property, forDisplay: true)); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(property.Name); returnValue.Append(" {"); if (PropertyIsGettable(property)) @@ -4008,7 +3930,7 @@ protected override string PropertyToString(PSProperty property) returnValue.Append("set;"); } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -4285,11 +4207,10 @@ internal static object AuxiliaryMethodInvoke(object target, object[] arguments, /// /// The methods to be converted. /// The MethodInformation[] corresponding to methods. - internal static MethodInformation[] GetMethodInformationArray(MethodBase[] methods) + internal static MethodInformation[] GetMethodInformationArray(IList methods) { - int methodCount = methods.Length; - MethodInformation[] returnValue = new MethodInformation[methodCount]; - for (int i = 0; i < methods.Length; i++) + var returnValue = new MethodInformation[methods.Count]; + for (int i = 0; i < methods.Count; i++) { returnValue[i] = new MethodInformation(methods[i], 0); } @@ -4415,7 +4336,7 @@ internal static string GetMethodInfoOverloadDefinition(string memberName, Method if (method != null) { builder.Append(ToStringCodeMethods.Type(method.ReturnType)); - builder.Append(" "); + builder.Append(' '); } else { @@ -4423,20 +4344,20 @@ internal static string GetMethodInfoOverloadDefinition(string memberName, Method if (ctorInfo != null) { builder.Append(ToStringCodeMethods.Type(ctorInfo.DeclaringType)); - builder.Append(" "); + builder.Append(' '); } } if (methodEntry.DeclaringType.IsInterface) { builder.Append(ToStringCodeMethods.Type(methodEntry.DeclaringType, dropNamespaces: true)); - builder.Append("."); + builder.Append('.'); } builder.Append(memberName ?? methodEntry.Name); if (methodEntry.IsGenericMethodDefinition) { - builder.Append("["); + builder.Append('['); Type[] genericArgs = methodEntry.GetGenericArguments(); for (int i = 0; i < genericArgs.Length; i++) @@ -4446,10 +4367,10 @@ internal static string GetMethodInfoOverloadDefinition(string memberName, Method builder.Append(ToStringCodeMethods.Type(genericArgs[i])); } - builder.Append("]"); + builder.Append(']'); } - builder.Append("("); + builder.Append('('); System.Reflection.ParameterInfo[] parameters = methodEntry.GetParameters(); int parametersLength = parameters.Length - parametersToIgnore; if (parametersLength > 0) @@ -4478,7 +4399,7 @@ internal static string GetMethodInfoOverloadDefinition(string memberName, Method } builder.Append(ToStringCodeMethods.Type(parameterType)); - builder.Append(" "); + builder.Append(' '); builder.Append(parameter.Name); builder.Append(", "); } @@ -4486,7 +4407,7 @@ internal static string GetMethodInfoOverloadDefinition(string memberName, Method builder.Remove(builder.Length - 2, 2); } - builder.Append(")"); + builder.Append(')'); return builder.ToString(); } @@ -4534,7 +4455,7 @@ protected override Collection MethodDefinitions(PSMethod method) MethodCacheEntry methodEntry = (MethodCacheEntry)method.adapterData; IList uniqueValues = methodEntry .methodInformationStructures - .Select(m => m.methodDefinition) + .Select(static m => m.methodDefinition) .Distinct(StringComparer.Ordinal) .ToList(); return new Collection(uniqueValues); @@ -4756,7 +4677,7 @@ protected override T GetFirstMemberOrDefault(object obj, MemberNamePredicate /// internal class DotNetAdapterWithComTypeName : DotNetAdapter { - private ComTypeInfo _comTypeInfo; + private readonly ComTypeInfo _comTypeInfo; internal DotNetAdapterWithComTypeName(ComTypeInfo comTypeInfo) { @@ -5256,9 +5177,9 @@ protected override IEnumerable GetTypeNameHierarchy(object obj) if (firstType == null) { firstType = new StringBuilder(baseType); - firstType.Append("#"); + firstType.Append('#'); firstType.Append(node.NamespaceURI); - firstType.Append("#"); + firstType.Append('#'); firstType.Append(node.LocalName); yield return firstType.ToString(); } @@ -5904,7 +5825,7 @@ private static MethodInfo Infer(MethodInfo genericMethod, Type[] typesOfMethodAr } Type[] typeParameters = genericMethod.GetGenericArguments(); - Type[] typesOfMethodParameters = genericMethod.GetParameters().Select(p => p.ParameterType).ToArray(); + Type[] typesOfMethodParameters = genericMethod.GetParameters().Select(static p => p.ParameterType).ToArray(); MethodInfo inferredMethod = Infer(genericMethod, typeParameters, typesOfMethodParameters, typesOfMethodArguments); @@ -5941,11 +5862,11 @@ private static MethodInfo Infer(MethodInfo genericMethod, ICollection type using (s_tracer.TraceScope("Inferring type parameters for the following method: {0}", genericMethod)) { - if (PSTraceSourceOptions.WriteLine == (s_tracer.Options & PSTraceSourceOptions.WriteLine)) + if ((s_tracer.Options & PSTraceSourceOptions.WriteLine) == PSTraceSourceOptions.WriteLine) { s_tracer.WriteLine( "Types of method arguments: {0}", - string.Join(", ", typesOfMethodArguments.Select(t => t.ToString()).ToArray())); + string.Join(", ", typesOfMethodArguments.Select(static t => t.ToString()).ToArray())); } var typeInference = new TypeInference(typeParameters); @@ -5955,7 +5876,7 @@ private static MethodInfo Infer(MethodInfo genericMethod, ICollection type } IEnumerable inferredTypeParameters = typeParameters.Select(typeInference.GetInferredType); - if (inferredTypeParameters.Any(inferredType => inferredType == null)) + if (inferredTypeParameters.Any(static inferredType => inferredType == null)) { return null; } @@ -5991,7 +5912,7 @@ internal TypeInference(ICollection typeParameters) #endif _typeParameterIndexToSetOfInferenceCandidates = new HashSet[typeParameters.Count]; #if DEBUG - List listOfTypeParameterPositions = typeParameters.Select(t => t.GenericParameterPosition).ToList(); + List listOfTypeParameterPositions = typeParameters.Select(static t => t.GenericParameterPosition).ToList(); listOfTypeParameterPositions.Sort(); Dbg.Assert( listOfTypeParameterPositions.Count == listOfTypeParameterPositions.Distinct().Count(), @@ -6023,9 +5944,9 @@ internal Type GetInferredType(Type typeParameter) ICollection inferenceCandidates = _typeParameterIndexToSetOfInferenceCandidates[typeParameter.GenericParameterPosition]; - if ((inferenceCandidates != null) && (inferenceCandidates.Any(t => t == typeof(LanguagePrimitives.Null)))) + if ((inferenceCandidates != null) && (inferenceCandidates.Any(static t => t == typeof(LanguagePrimitives.Null)))) { - Type firstValueType = inferenceCandidates.FirstOrDefault(t => t.IsValueType); + Type firstValueType = inferenceCandidates.FirstOrDefault(static t => t.IsValueType); if (firstValueType != null) { s_tracer.WriteLine("Cannot reconcile null and {0} (a value type)", firstValueType); @@ -6034,7 +5955,7 @@ internal Type GetInferredType(Type typeParameter) } else { - inferenceCandidates = inferenceCandidates.Where(t => t != typeof(LanguagePrimitives.Null)).ToList(); + inferenceCandidates = inferenceCandidates.Where(static t => t != typeof(LanguagePrimitives.Null)).ToList(); if (inferenceCandidates.Count == 0) { inferenceCandidates = null; diff --git a/src/System.Management.Automation/engine/Credential.cs b/src/System.Management.Automation/engine/Credential.cs index 6b9c4be8d4d..86557c922c6 100644 --- a/src/System.Management.Automation/engine/Credential.cs +++ b/src/System.Management.Automation/engine/Credential.cs @@ -177,8 +177,8 @@ private PSCredential(SerializationInfo info, StreamingContext context) } } - private string _userName; - private SecureString _password; + private readonly string _userName; + private readonly SecureString _password; /// /// User's name. @@ -405,4 +405,3 @@ private static void SplitUserDomain(string input, } } } - diff --git a/src/System.Management.Automation/engine/DataStoreAdapter.cs b/src/System.Management.Automation/engine/DataStoreAdapter.cs index e44a2a3c0b3..9bf7611d7ff 100644 --- a/src/System.Management.Automation/engine/DataStoreAdapter.cs +++ b/src/System.Management.Automation/engine/DataStoreAdapter.cs @@ -29,7 +29,7 @@ public class PSDriveInfo : IComparable [Dbg.TraceSourceAttribute( "PSDriveInfo", "The namespace navigation tracer")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("PSDriveInfo", "The namespace navigation tracer"); @@ -830,4 +830,3 @@ internal PSNoteProperty GetNotePropertyForProviderCmdlets(string name) } } } - diff --git a/src/System.Management.Automation/engine/DataStoreAdapterProvider.cs b/src/System.Management.Automation/engine/DataStoreAdapterProvider.cs index f1e798c0edf..69202e6d20e 100644 --- a/src/System.Management.Automation/engine/DataStoreAdapterProvider.cs +++ b/src/System.Management.Automation/engine/DataStoreAdapterProvider.cs @@ -34,7 +34,7 @@ public class ProviderInfo /// /// The instance of session state the provider belongs to. /// - private SessionState _sessionState; + private readonly SessionState _sessionState; private string _fullName; private string _cachedModuleName; @@ -51,7 +51,7 @@ internal string FullName { get { - string GetFullName(string name, string psSnapInName, string moduleName) + static string GetFullName(string name, string psSnapInName, string moduleName) { string result = name; if (!string.IsNullOrEmpty(psSnapInName)) @@ -221,7 +221,7 @@ public Collection Drives /// A hidden drive for the provider that is used for setting /// the location to a provider-qualified path. /// - private PSDriveInfo _hiddenDrive; + private readonly PSDriveInfo _hiddenDrive; /// /// Gets the hidden drive for the provider that is used @@ -686,4 +686,3 @@ internal PSNoteProperty GetNotePropertyForProviderCmdlets(string name) } } } - diff --git a/src/System.Management.Automation/engine/DefaultCommandRuntime.cs b/src/System.Management.Automation/engine/DefaultCommandRuntime.cs index 09a933eaad2..48d74667dae 100644 --- a/src/System.Management.Automation/engine/DefaultCommandRuntime.cs +++ b/src/System.Management.Automation/engine/DefaultCommandRuntime.cs @@ -14,7 +14,7 @@ namespace System.Management.Automation /// internal class DefaultCommandRuntime : ICommandRuntime2 { - private List _output; + private readonly List _output; /// /// Constructs an instance of the default ICommandRuntime object /// that will write objects into the list that was passed. @@ -30,7 +30,7 @@ public DefaultCommandRuntime(List outputList) /// /// Return the instance of PSHost - null by default. /// - public PSHost Host { set; get; } + public PSHost Host { get; set; } #region Write /// @@ -230,6 +230,7 @@ public PSTransactionContext CurrentPSTransaction /// if it exists, otherwise throw an invalid operation exception. /// /// The error record to throw. + [System.Diagnostics.CodeAnalysis.DoesNotReturn] public void ThrowTerminatingError(ErrorRecord errorRecord) { if (errorRecord.Exception != null) diff --git a/src/System.Management.Automation/engine/DriveInterfaces.cs b/src/System.Management.Automation/engine/DriveInterfaces.cs index 36bfc73c573..299faa8b76e 100644 --- a/src/System.Management.Automation/engine/DriveInterfaces.cs +++ b/src/System.Management.Automation/engine/DriveInterfaces.cs @@ -387,9 +387,8 @@ public Collection GetAllForProvider(string providerName) #region private data // A private reference to the internal session state of the engine. - private SessionStateInternal _sessionState; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/DscResourceSearcher.cs b/src/System.Management.Automation/engine/DscResourceSearcher.cs index 8bb4f5bd267..bfd406f56ff 100644 --- a/src/System.Management.Automation/engine/DscResourceSearcher.cs +++ b/src/System.Management.Automation/engine/DscResourceSearcher.cs @@ -27,8 +27,8 @@ internal DscResourceSearcher( #region private properties - private string _resourceName = null; - private ExecutionContext _context = null; + private readonly string _resourceName = null; + private readonly ExecutionContext _context = null; private DscResourceInfo _currentMatch = null; private IEnumerator _matchingResource = null; private Collection _matchingResourceList = null; diff --git a/src/System.Management.Automation/engine/EngineIntrinsics.cs b/src/System.Management.Automation/engine/EngineIntrinsics.cs index d0bc7a2f100..a492a5215fc 100644 --- a/src/System.Management.Automation/engine/EngineIntrinsics.cs +++ b/src/System.Management.Automation/engine/EngineIntrinsics.cs @@ -101,17 +101,16 @@ public SessionState SessionState /// public CommandInvocationIntrinsics InvokeCommand { - get { return _invokeCommand ?? (_invokeCommand = new CommandInvocationIntrinsics(_context)); } + get { return _invokeCommand ??= new CommandInvocationIntrinsics(_context); } } #endregion Public methods #region private data - private ExecutionContext _context; - private PSHost _host; + private readonly ExecutionContext _context; + private readonly PSHost _host; private CommandInvocationIntrinsics _invokeCommand; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/EnumExpressionEvaluator.cs b/src/System.Management.Automation/engine/EnumExpressionEvaluator.cs index 88aa49e98d2..056372ac63e 100644 --- a/src/System.Management.Automation/engine/EnumExpressionEvaluator.cs +++ b/src/System.Management.Automation/engine/EnumExpressionEvaluator.cs @@ -157,6 +157,7 @@ internal abstract class Node public Node Operand1 { get; set; } internal abstract bool Eval(object val); + internal abstract bool ExistEnum(object enumVal); } @@ -308,7 +309,7 @@ internal override bool ExistEnum(object enumVal) return exist; } - private bool isUnsigned(Type type) + private static bool isUnsigned(Type type) { return (type == typeof(ulong) || type == typeof(uint) || type == typeof(ushort) || type == typeof(byte)); } @@ -318,7 +319,7 @@ private bool isUnsigned(Type type) #region private members - private Type _underType = null; + private readonly Type _underType = null; #endregion @@ -385,7 +386,7 @@ internal bool ExistsInExpression(T flagName) /// /// A generic list of tokenized input. /// - private List TokenizeInput(string input) + private static List TokenizeInput(string input) { List tokenList = new List(); int _offset = 0; @@ -411,7 +412,7 @@ private List TokenizeInput(string input) /// /// Current offset position for the string parser. /// - private void FindNextToken(string input, ref int _offset) + private static void FindNextToken(string input, ref int _offset) { while (_offset < input.Length) { @@ -438,7 +439,7 @@ private void FindNextToken(string input, ref int _offset) /// /// The next token on the input string /// - private Token GetNextToken(string input, ref int _offset) + private static Token GetNextToken(string input, ref int _offset) { StringBuilder sb = new StringBuilder(); // bool singleQuoted = false; @@ -521,7 +522,7 @@ private Token GetNextToken(string input, ref int _offset) /// /// A list of tokenized input. /// - private void CheckSyntaxError(List tokenList) + private static void CheckSyntaxError(List tokenList) { // Initialize, assuming preceded by OR TokenKind previous = TokenKind.Or; @@ -576,7 +577,7 @@ private void CheckSyntaxError(List tokenList) /// /// Tokenized list of the input string. /// - private Node ConstructExpressionTree(List tokenList) + private static Node ConstructExpressionTree(List tokenList) { bool notFlag = false; Queue andQueue = new Queue(); diff --git a/src/System.Management.Automation/engine/EnumMinimumDisambiguation.cs b/src/System.Management.Automation/engine/EnumMinimumDisambiguation.cs index 543d920418f..5c166c69a63 100644 --- a/src/System.Management.Automation/engine/EnumMinimumDisambiguation.cs +++ b/src/System.Management.Automation/engine/EnumMinimumDisambiguation.cs @@ -85,7 +85,7 @@ internal static string EnumDisambiguate(string text, Type enumType) } // No special cases match, throw error for multiple matches. StringBuilder matchListSB = new StringBuilder(namesWithMatchingPrefix[0]); - string separator = ", "; + const string separator = ", "; for (int i = 1; i < namesWithMatchingPrefix.Count; i++) { matchListSB.Append(separator); @@ -106,7 +106,7 @@ internal static string EnumDisambiguate(string text, Type enumType) internal static string EnumAllValues(Type enumType) { string[] names = Enum.GetNames(enumType); - string separator = ", "; + const string separator = ", "; StringBuilder returnValue = new StringBuilder(); if (names.Length != 0) { @@ -122,6 +122,6 @@ internal static string EnumAllValues(Type enumType) return returnValue.ToString(); } - private static Dictionary s_specialDisambiguateCases = new Dictionary(); + private static readonly Dictionary s_specialDisambiguateCases = new Dictionary(); } } diff --git a/src/System.Management.Automation/engine/ErrorPackage.cs b/src/System.Management.Automation/engine/ErrorPackage.cs index e95bb060bdd..1f17a501736 100644 --- a/src/System.Management.Automation/engine/ErrorPackage.cs +++ b/src/System.Management.Automation/engine/ErrorPackage.cs @@ -477,7 +477,7 @@ public override string ToString() #region Private // back-reference for facade class - private ErrorRecord _errorRecord; + private readonly ErrorRecord _errorRecord; /// /// The Activity, Reason, TargetName and TargetType strings in @@ -495,7 +495,7 @@ public override string ToString() /// internal static string Ellipsize(CultureInfo uiCultureInfo, string original) { - if (40 >= original.Length) + if (original.Length <= 40) { return original; } @@ -756,7 +756,7 @@ public string Message get { return ErrorRecord.NotNull(_message); } } - private string _message = string.Empty; + private readonly string _message = string.Empty; /// /// Text describing the recommended action in the event that this error @@ -769,7 +769,10 @@ public string Message /// public string RecommendedAction { - get { return ErrorRecord.NotNull(_recommendedAction); } + get + { + return ErrorRecord.NotNull(_recommendedAction); + } set { @@ -1204,21 +1207,21 @@ internal void ToPSObjectForRemoting(PSObject dest) private void ToPSObjectForRemoting(PSObject dest, bool serializeExtInfo) { - RemotingEncoder.AddNoteProperty(dest, "Exception", delegate () { return Exception; }); - RemotingEncoder.AddNoteProperty(dest, "TargetObject", delegate () { return TargetObject; }); - RemotingEncoder.AddNoteProperty(dest, "FullyQualifiedErrorId", delegate () { return FullyQualifiedErrorId; }); - RemotingEncoder.AddNoteProperty(dest, "InvocationInfo", delegate () { return InvocationInfo; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Category", delegate () { return (int)CategoryInfo.Category; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Activity", delegate () { return CategoryInfo.Activity; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Reason", delegate () { return CategoryInfo.Reason; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_TargetName", delegate () { return CategoryInfo.TargetName; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_TargetType", delegate () { return CategoryInfo.TargetType; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Message", delegate () { return CategoryInfo.GetMessage(CultureInfo.CurrentCulture); }); + RemotingEncoder.AddNoteProperty(dest, "Exception", () => Exception); + RemotingEncoder.AddNoteProperty(dest, "TargetObject", () => TargetObject); + RemotingEncoder.AddNoteProperty(dest, "FullyQualifiedErrorId", () => FullyQualifiedErrorId); + RemotingEncoder.AddNoteProperty(dest, "InvocationInfo", () => InvocationInfo); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Category", () => (int)CategoryInfo.Category); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Activity", () => CategoryInfo.Activity); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Reason", () => CategoryInfo.Reason); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_TargetName", () => CategoryInfo.TargetName); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_TargetType", () => CategoryInfo.TargetType); + RemotingEncoder.AddNoteProperty(dest, "ErrorCategory_Message", () => CategoryInfo.GetMessage(CultureInfo.CurrentCulture)); if (ErrorDetails != null) { - RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_Message", delegate () { return ErrorDetails.Message; }); - RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_RecommendedAction", delegate () { return ErrorDetails.RecommendedAction; }); + RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_Message", () => ErrorDetails.Message); + RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_RecommendedAction", () => ErrorDetails.RecommendedAction); } if (!serializeExtInfo || this.InvocationInfo == null) @@ -1229,12 +1232,12 @@ private void ToPSObjectForRemoting(PSObject dest, bool serializeExtInfo) { RemotingEncoder.AddNoteProperty(dest, "SerializeExtendedInfo", () => true); this.InvocationInfo.ToPSObjectForRemoting(dest); - RemotingEncoder.AddNoteProperty(dest, "PipelineIterationInfo", delegate () { return PipelineIterationInfo; }); + RemotingEncoder.AddNoteProperty(dest, "PipelineIterationInfo", () => PipelineIterationInfo); } if (!string.IsNullOrEmpty(this.ScriptStackTrace)) { - RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_ScriptStackTrace", delegate () { return this.ScriptStackTrace; }); + RemotingEncoder.AddNoteProperty(dest, "ErrorDetails_ScriptStackTrace", () => this.ScriptStackTrace); } } @@ -1336,7 +1339,7 @@ private void ConstructFromPSObjectForRemoting(PSObject serializedErrorRecord) string errorDetails_ScriptStackTrace = GetNoteValue(serializedErrorRecord, "ErrorDetails_ScriptStackTrace") as string; - RemoteException re = new RemoteException((string.IsNullOrWhiteSpace(exceptionMessage) == false) ? exceptionMessage : errorCategory_Message, serializedException, invocationInfo); + RemoteException re = new RemoteException((!string.IsNullOrWhiteSpace(exceptionMessage)) ? exceptionMessage : errorCategory_Message, serializedException, invocationInfo); // Create ErrorRecord PopulateProperties( @@ -1480,7 +1483,7 @@ internal void SetTargetObject(object target) /// for that ErrorCategory. /// /// never null - public ErrorCategoryInfo CategoryInfo { get => _categoryInfo ?? (_categoryInfo = new ErrorCategoryInfo(this)); } + public ErrorCategoryInfo CategoryInfo { get => _categoryInfo ??= new ErrorCategoryInfo(this); } private ErrorCategoryInfo _categoryInfo; @@ -1634,7 +1637,7 @@ internal bool SerializeExtendedInfo #endregion Public Properties #region Private - private string _errorId; + private readonly string _errorId; #region Exposed by ErrorCategoryInfo internal ErrorCategory _category; @@ -1666,8 +1669,7 @@ private string GetInvocationTypeName() return commandInfo.Name; } - CmdletInfo cmdletInfo = commandInfo as CmdletInfo; - if (cmdletInfo == null) + if (!(commandInfo is CmdletInfo cmdletInfo)) { return string.Empty; } @@ -1762,6 +1764,7 @@ public ErrorRecord(Exception exception, string errorId, ErrorCategory errorCateg /// /// is no longer available. /// +#nullable enable public interface IContainsErrorRecord { /// @@ -1790,6 +1793,7 @@ public interface IContainsErrorRecord /// ErrorRecord ErrorRecord { get; } } +#nullable restore /// /// Objects implementing this interface can be used by @@ -1811,6 +1815,7 @@ public interface IContainsErrorRecord /// since the improved /// information about the error may help enable future scenarios. /// +#nullable enable public interface IResourceSupplier { /// diff --git a/src/System.Management.Automation/engine/EventManager.cs b/src/System.Management.Automation/engine/EventManager.cs index 7dd39180885..3df9153f4e7 100644 --- a/src/System.Management.Automation/engine/EventManager.cs +++ b/src/System.Management.Automation/engine/EventManager.cs @@ -331,12 +331,12 @@ internal PSLocalEventManager(ExecutionContext context) _context = context; } - private Dictionary _eventSubscribers; - private Dictionary> _engineEventSubscribers; - private Queue _actionQueue; - private ExecutionContext _context; + private readonly Dictionary _eventSubscribers; + private readonly Dictionary> _engineEventSubscribers; + private readonly Queue _actionQueue; + private readonly ExecutionContext _context; private int _nextSubscriptionId = 1; - private double _throttleLimit = 1; + private readonly double _throttleLimit = 1; private int _throttleChecks = 0; // The assembly and module to hold our event registrations @@ -599,7 +599,7 @@ private void OnElapsedEvent(object source) if (_engineEventSubscribers.TryGetValue(PSEngineEvent.OnIdle, out subscribers) && subscribers.Count > 0) { // We send out on-idle event and keep enabling the timer only if there still are subscribers to the on-idle event - GenerateEvent(PSEngineEvent.OnIdle, null, new object[] { }, null, false, false); + GenerateEvent(PSEngineEvent.OnIdle, null, Array.Empty(), null, false, false); EnableTimer(); } else @@ -640,7 +640,7 @@ private void EnableTimer() #endregion OnIdleProcessing - private static Dictionary s_generatedEventHandlers = new Dictionary(); + private static readonly Dictionary s_generatedEventHandlers = new Dictionary(); private void ProcessNewSubscriber(PSEventSubscriber subscriber, object source, string eventName, string sourceIdentifier, PSObject data, bool supportEvent, bool forwardEvent) { @@ -680,7 +680,7 @@ private void ProcessNewSubscriber(PSEventSubscriber subscriber, object source, s } // Retrieve the event from the object - BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase; + const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase; eventInfo = sourceType.GetEvent(eventName, bindingFlags); // If we can't find the event, throw an exception @@ -844,7 +844,7 @@ private void UnsubscribeEvent(PSEventSubscriber subscriber, bool skipDraining) Type sourceType = subscriber.SourceObject as Type ?? subscriber.SourceObject.GetType(); - BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase; + const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase; eventInfo = sourceType.GetEvent(subscriber.EventName, bindingFlags); if ((eventInfo != null) && (existingSubscriber != null)) @@ -953,11 +953,7 @@ protected internal override void ProcessNewEvent(PSEventArgs newEvent, } else { - ThreadPool.QueueUserWorkItem(new WaitCallback( - delegate (object unused) - { - ProcessNewEventImplementation(newEvent, false); - })); + ThreadPool.QueueUserWorkItem(new WaitCallback((_) => ProcessNewEventImplementation(newEvent, false))); } } @@ -1137,7 +1133,7 @@ private void ProcessPendingActionsImpl() // teardown event. That can result in starvation of // foreground threads that also want to use the runspace. ThreadPool.QueueUserWorkItem(new WaitCallback( - delegate (object unused) + (_) => { System.Threading.Thread.Sleep(100); this.PulseEngine(); @@ -1168,7 +1164,7 @@ private void AutoUnregisterEventIfNecessary(PSEventSubscriber subscriber) } } - private object _actionProcessingLock = new object(); + private readonly object _actionProcessingLock = new object(); private EventAction _processingAction = null; /// @@ -1511,20 +1507,7 @@ private Type GenerateEventHandler(MethodInfo invokeSignature) /// protected virtual void OnForwardEvent(PSEventArgs e) { - EventHandler eh = ForwardEvent; - - if (eh != null) - { - eh(this, e); - } - } - - /// - /// Destructor for the EventManager class. - /// - ~PSLocalEventManager() - { - Dispose(false); + ForwardEvent?.Invoke(this, e); } /// @@ -1561,6 +1544,14 @@ public void Dispose(bool disposing) } } } + + /// + /// Finalizes an instance of the class. + /// + ~PSLocalEventManager() + { + Dispose(false); + } } /// @@ -1569,10 +1560,10 @@ public void Dispose(bool disposing) internal class PSRemoteEventManager : PSEventManager { /// Computer on which the event was generated - private string _computerName; + private readonly string _computerName; /// Runspace on which the event was generated - private Guid _runspaceId; + private readonly Guid _runspaceId; /// /// Creates an event manager for the given runspace. @@ -1824,12 +1815,7 @@ public override void UnsubscribeEvent(PSEventSubscriber subscriber) /// protected virtual void OnForwardEvent(PSEventArgs e) { - EventHandler eh = ForwardEvent; - - if (eh != null) - { - eh(this, e); - } + ForwardEvent?.Invoke(this, e); } } @@ -1909,9 +1895,17 @@ internal PSEventSubscriber(ExecutionContext context, int id, object source, /// Creates an instance of the PSEventSubscriber /// class. Additionally supports an Action scriptblock. /// - internal PSEventSubscriber(ExecutionContext context, int id, object source, - string eventName, string sourceIdentifier, ScriptBlock action, bool supportEvent, bool forwardEvent, int maxTriggerCount) : - this(context, id, source, eventName, sourceIdentifier, supportEvent, forwardEvent, maxTriggerCount) + internal PSEventSubscriber( + ExecutionContext context, + int id, + object source, + string eventName, + string sourceIdentifier, + ScriptBlock action, + bool supportEvent, + bool forwardEvent, + int maxTriggerCount) + : this(context, id, source, eventName, sourceIdentifier, supportEvent, forwardEvent, maxTriggerCount) { // Create the bound scriptblock, and job. if (action != null) @@ -1938,14 +1932,22 @@ internal void RegisterJob() /// Creates an instance of the PSEventSubscriber /// class. Additionally supports an Action scriptblock. /// - internal PSEventSubscriber(ExecutionContext context, int id, object source, - string eventName, string sourceIdentifier, PSEventReceivedEventHandler handlerDelegate, bool supportEvent, bool forwardEvent, int maxTriggerCount) : - this(context, id, source, eventName, sourceIdentifier, supportEvent, forwardEvent, maxTriggerCount) + internal PSEventSubscriber( + ExecutionContext context, + int id, + object source, + string eventName, + string sourceIdentifier, + PSEventReceivedEventHandler handlerDelegate, + bool supportEvent, + bool forwardEvent, + int maxTriggerCount) + : this(context, id, source, eventName, sourceIdentifier, supportEvent, forwardEvent, maxTriggerCount) { HandlerDelegate = handlerDelegate; } - private ExecutionContext _context; + private readonly ExecutionContext _context; /// /// Create a bound script block. @@ -2040,6 +2042,19 @@ private ScriptBlock CreateBoundScriptBlock(ScriptBlock scriptAction) #region IComparable Members + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// + /// if the specified object is equal to the current object; + /// otherwise, . + /// + public override bool Equals(object obj) + { + return obj is PSEventSubscriber es && Equals(es); + } + /// /// Determines if two PSEventSubscriber instances are equal /// @@ -2067,10 +2082,7 @@ public override int GetHashCode() internal void OnPSEventUnsubscribed(object sender, PSEventUnsubscribedEventArgs e) { - if (Unsubscribed != null) - { - Unsubscribed(sender, e); - } + Unsubscribed?.Invoke(sender, e); } } @@ -2351,7 +2363,7 @@ public class PSEventArgsCollection : IEnumerable /// public event PSEventReceivedEventHandler PSEventReceived; - private List _eventCollection = new List(); + private readonly List _eventCollection = new List(); /// /// Add add an event to the collection. @@ -2404,11 +2416,7 @@ public PSEventArgs this[int index] private void OnPSEventReceived(object sender, PSEventArgs e) { - PSEventReceivedEventHandler eventHandler = PSEventReceived; - if (eventHandler != null) - { - eventHandler(sender, e); - } + PSEventReceived?.Invoke(sender, e); } /// @@ -2477,8 +2485,12 @@ public class PSEventJob : Job /// The name of the job /// /// - public PSEventJob(PSEventManager eventManager, PSEventSubscriber subscriber, ScriptBlock action, string name) : - base(action == null ? null : action.ToString(), name) + public PSEventJob( + PSEventManager eventManager, + PSEventSubscriber subscriber, + ScriptBlock action, + string name) + : base(action?.ToString(), name) { if (eventManager == null) throw new ArgumentNullException(nameof(eventManager)); @@ -2491,8 +2503,8 @@ public PSEventJob(PSEventManager eventManager, PSEventSubscriber subscriber, Scr _subscriber = subscriber; } - private PSEventManager _eventManager = null; - private PSEventSubscriber _subscriber = null; + private readonly PSEventManager _eventManager = null; + private readonly PSEventSubscriber _subscriber = null; private int _highestErrorIndex = 0; /// diff --git a/src/System.Management.Automation/engine/ExecutionContext.cs b/src/System.Management.Automation/engine/ExecutionContext.cs index 98f0b3deb5a..cfcc417de4a 100644 --- a/src/System.Management.Automation/engine/ExecutionContext.cs +++ b/src/System.Management.Automation/engine/ExecutionContext.cs @@ -83,7 +83,10 @@ internal int PSDebugTraceLevel return IgnoreScriptDebug ? 0 : _debugTraceLevel; } - set { _debugTraceLevel = value; } + set + { + _debugTraceLevel = value; + } } private int _debugTraceLevel; @@ -100,7 +103,10 @@ internal bool PSDebugTraceStep return !IgnoreScriptDebug && _debugTraceStep; } - set { _debugTraceStep = value; } + set + { + _debugTraceStep = value; + } } private bool _debugTraceStep; @@ -113,9 +119,7 @@ internal static bool IsStrictVersion(ExecutionContext context, int majorVersion) context = LocalPipeline.GetExecutionContextFromTLS(); } - return (context != null) - ? context.IsStrictVersion(majorVersion) - : false; + return (context != null) && context.IsStrictVersion(majorVersion); } /// /// Check to see a specific version of strict mode is enabled. The check is always scoped, @@ -172,7 +176,7 @@ internal bool ShouldTraceStatement /// trace flag. /// /// The current state of the IgnoreScriptDebug flag. - internal bool IgnoreScriptDebug { set; get; } = true; + internal bool IgnoreScriptDebug { get; set; } = true; /// /// Gets the automation engine instance. @@ -201,40 +205,6 @@ internal bool ShouldTraceStatement /// internal string ModuleBeingProcessed { get; set; } - private bool _responsibilityForModuleAnalysisAppDomainOwned; - - internal bool TakeResponsibilityForModuleAnalysisAppDomain() - { - if (_responsibilityForModuleAnalysisAppDomainOwned) - { - return false; - } - - Diagnostics.Assert(AppDomainForModuleAnalysis == null, "Invalid module analysis app domain state"); - _responsibilityForModuleAnalysisAppDomainOwned = true; - return true; - } - - internal void ReleaseResponsibilityForModuleAnalysisAppDomain() - { - Diagnostics.Assert(_responsibilityForModuleAnalysisAppDomainOwned, "Invalid module analysis app domain state"); - - if (AppDomainForModuleAnalysis != null) - { - AppDomain.Unload(AppDomainForModuleAnalysis); - AppDomainForModuleAnalysis = null; - } - - _responsibilityForModuleAnalysisAppDomainOwned = false; - } - - /// - /// The AppDomain currently being used for module analysis. It should only be created if needed, - /// but various callers need to take responsibility for unloading the domain via - /// the TakeResponsibilityForModuleAnalysisAppDomain. - /// - internal AppDomain AppDomainForModuleAnalysis { get; set; } - /// /// Authorization manager for this runspace. /// @@ -426,7 +396,7 @@ internal static void MarkObjectAsUntrusted(object value) if (baseValue != null && baseValue != NullString.Value) { // It's actually setting a key value pair when the key doesn't exist - UntrustedObjects.GetValue(baseValue, key => null); + UntrustedObjects.GetValue(baseValue, static key => null); try { @@ -488,7 +458,7 @@ internal bool UseFullLanguageModeInDebugger { get { - return InitialSessionState != null ? InitialSessionState.UseFullLanguageModeInDebugger : false; + return InitialSessionState != null && InitialSessionState.UseFullLanguageModeInDebugger; } } @@ -666,7 +636,7 @@ internal bool GetBooleanPreference(VariablePath preferenceVariablePath, bool def /// internal HelpSystem HelpSystem { - get { return _helpSystem ?? (_helpSystem = new HelpSystem(this)); } + get { return _helpSystem ??= new HelpSystem(this); } } private HelpSystem _helpSystem; @@ -679,6 +649,7 @@ internal HelpSystem HelpSystem #endregion internal Dictionary CustomArgumentCompleters { get; set; } + internal Dictionary NativeArgumentCompleters { get; set; } /// @@ -744,7 +715,7 @@ internal InternalHost InternalHost /// internal EngineIntrinsics EngineIntrinsics { - get { return _engineIntrinsics ?? (_engineIntrinsics = new EngineIntrinsics(this)); } + get { return _engineIntrinsics ??= new EngineIntrinsics(this); } } private EngineIntrinsics _engineIntrinsics; @@ -772,11 +743,11 @@ internal EngineIntrinsics EngineIntrinsics internal class SavedContextData { - private bool _stepScript; - private bool _ignoreScriptDebug; - private int _PSDebug; + private readonly bool _stepScript; + private readonly bool _ignoreScriptDebug; + private readonly int _PSDebug; - private Pipe _shellFunctionErrorOutputPipe; + private readonly Pipe _shellFunctionErrorOutputPipe; public SavedContextData(ExecutionContext context) { @@ -875,7 +846,7 @@ internal void ResetRedirection() internal void AppendDollarError(object obj) { ErrorRecord objAsErrorRecord = obj as ErrorRecord; - if (objAsErrorRecord == null && !(obj is Exception)) + if (objAsErrorRecord == null && obj is not Exception) { Diagnostics.Assert(false, "Object to append was neither an ErrorRecord nor an Exception in ExecutionContext.AppendDollarError"); return; @@ -906,7 +877,7 @@ internal void AppendDollarError(object obj) const int maxErrorCount = 256; int numToErase = arraylist.Count - (maxErrorCount - 1); - if (0 < numToErase) + if (numToErase > 0) { arraylist.RemoveRange( maxErrorCount - 1, @@ -1637,7 +1608,7 @@ private void InitializeCommon(AutomationEngine engine, PSHost hostInterface) Modules = new ModuleIntrinsics(this); } - private static object lockObject = new object(); + private static readonly object lockObject = new object(); #if !CORECLR // System.AppDomain is not in CoreCLR private static bool _assemblyEventHandlerSet = false; @@ -1698,5 +1669,5 @@ internal enum EngineState /// Engine is stopped. /// Stopped = 4 - }; + } } diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs b/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs index c15d8628cb9..f68a45cd0f2 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs @@ -70,7 +70,7 @@ protected override void ProcessRecord() } } - internal class ExperimentalFeatureConfigHelper + internal static class ExperimentalFeatureConfigHelper { internal static void UpdateConfig(PSCmdlet cmdlet, string[] name, ConfigScope scope, bool enable) { @@ -131,7 +131,7 @@ public IEnumerable CompleteArgument(string commandName, string names.Add(result.Name); } - return names.OrderBy(name => name).Select(name => new CompletionResult(name, name, CompletionResultType.Text, name)); + return names.OrderBy(static name => name).Select(static name => new CompletionResult(name, name, CompletionResultType.Text, name)); } } } diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs index ebb47e9be72..9268003ee87 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs @@ -21,6 +21,7 @@ public class ExperimentalFeature #region Const Members internal const string EngineSource = "PSEngine"; + internal const string PSNativeCommandArgumentPassingFeatureName = "PSNativeCommandArgumentPassing"; #endregion @@ -103,31 +104,30 @@ static ExperimentalFeature() name: "PSFileSystemProviderV2", description: "Replace the old FileSystemProvider with cleaner design and faster code"), */ - new ExperimentalFeature( - name: "PSImplicitRemotingBatching", - description: "Batch implicit remoting proxy commands to improve performance"), new ExperimentalFeature( name: "PSCommandNotFoundSuggestion", description: "Recommend potential commands based on fuzzy search on a CommandNotFoundException"), -#if UNIX - new ExperimentalFeature( - name: "PSUnixFileStat", - description: "Provide unix permission information for files and directories"), -#endif new ExperimentalFeature( - name: "PSCultureInvariantReplaceOperator", - description: "Use culture invariant to-string convertor for lval in replace operator"), - new ExperimentalFeature( - name: "PSNotApplyErrorActionToStderr", - description: "Don't have $ErrorActionPreference affect stderr output"), + name: "PSNativePSPathResolution", + description: "Convert PSPath to filesystem path, if possible, for native commands"), new ExperimentalFeature( name: "PSSubsystemPluginModel", description: "A plugin model for registering and un-registering PowerShell subsystems"), + new ExperimentalFeature( + name: PSNativeCommandArgumentPassingFeatureName, + description: "Use ArgumentList when invoking a native command"), + new ExperimentalFeature( + name: "PSLoadAssemblyFromNativeCode", + description: "Expose an API to allow assembly loading from native code"), + new ExperimentalFeature( + name: "PSAnsiRenderingFileInfo", + description: "Enable coloring for FileInfo objects"), }; + EngineExperimentalFeatures = new ReadOnlyCollection(engineFeatures); // Initialize the readonly dictionary 'EngineExperimentalFeatureMap'. - var engineExpFeatureMap = engineFeatures.ToDictionary(f => f.Name, StringComparer.OrdinalIgnoreCase); + var engineExpFeatureMap = engineFeatures.ToDictionary(static f => f.Name, StringComparer.OrdinalIgnoreCase); EngineExperimentalFeatureMap = new ReadOnlyDictionary(engineExpFeatureMap); // Initialize the readonly hashset 'EnabledExperimentalFeatureNames'. @@ -342,20 +342,21 @@ internal static void ValidateArguments(string experimentName, ExperimentAction e { if (string.IsNullOrEmpty(experimentName)) { - string paramName = nameof(experimentName); + const string paramName = nameof(experimentName); throw PSTraceSource.NewArgumentNullException(paramName, Metadata.ArgumentNullOrEmpty, paramName); } if (experimentAction == ExperimentAction.None) { - string paramName = nameof(experimentAction); - string invalidMember = nameof(ExperimentAction.None); + const string paramName = nameof(experimentAction); + const string invalidMember = nameof(ExperimentAction.None); string validMembers = StringUtil.Format("{0}, {1}", ExperimentAction.Hide, ExperimentAction.Show); throw PSTraceSource.NewArgumentException(paramName, Metadata.InvalidEnumArgument, invalidMember, paramName, validMembers); } } internal bool ToHide => EffectiveAction == ExperimentAction.Hide; + internal bool ToShow => EffectiveAction == ExperimentAction.Show; /// diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/GetExperimentalFeatureCommand.cs b/src/System.Management.Automation/engine/ExperimentalFeature/GetExperimentalFeatureCommand.cs index ff1c964fc4c..d87669000de 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/GetExperimentalFeatureCommand.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/GetExperimentalFeatureCommand.cs @@ -14,6 +14,7 @@ namespace Microsoft.PowerShell.Commands /// Implements Get-ExperimentalFeature cmdlet. /// [Cmdlet(VerbsCommon.Get, "ExperimentalFeature", HelpUri = "https://go.microsoft.com/fwlink/?linkid=2096786")] + [OutputType(typeof(ExperimentalFeature))] public class GetExperimentalFeatureCommand : PSCmdlet { /// diff --git a/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs b/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs index 436d2fc3886..ac99127ab29 100644 --- a/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs +++ b/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs @@ -18,7 +18,8 @@ public class ExtendedTypeSystemException : RuntimeException /// Initializes a new instance of ExtendedTypeSystemException with the message set /// to typeof(ExtendedTypeSystemException).FullName. /// - public ExtendedTypeSystemException() : base(typeof(ExtendedTypeSystemException).FullName) + public ExtendedTypeSystemException() + : base(typeof(ExtendedTypeSystemException).FullName) { } @@ -26,7 +27,8 @@ public ExtendedTypeSystemException() : base(typeof(ExtendedTypeSystemException). /// Initializes a new instance of ExtendedTypeSystemException setting the message. /// /// The exception's message. - public ExtendedTypeSystemException(string message) : base(message) + public ExtendedTypeSystemException(string message) + : base(message) { } @@ -35,7 +37,8 @@ public ExtendedTypeSystemException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public ExtendedTypeSystemException(string message, Exception innerException) : base(message, innerException) + public ExtendedTypeSystemException(string message, Exception innerException) + : base(message, innerException) { } @@ -46,9 +49,14 @@ public ExtendedTypeSystemException(string message, Exception innerException) : b /// The inner exception, null for none. /// Resource string. /// Arguments to the resource string. - internal ExtendedTypeSystemException(string errorId, Exception innerException, string resourceString, - params object[] arguments) : - base(StringUtil.Format(resourceString, arguments), innerException) + internal ExtendedTypeSystemException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base( + StringUtil.Format(resourceString, arguments), + innerException) { SetErrorId(errorId); } @@ -86,7 +94,8 @@ public class MethodException : ExtendedTypeSystemException /// Initializes a new instance of MethodException with the message set /// to typeof(MethodException).FullName. /// - public MethodException() : base(typeof(MethodException).FullName) + public MethodException() + : base(typeof(MethodException).FullName) { } @@ -94,7 +103,8 @@ public MethodException() : base(typeof(MethodException).FullName) /// Initializes a new instance of MethodException setting the message. /// /// The exception's message. - public MethodException(string message) : base(message) + public MethodException(string message) + : base(message) { } @@ -103,7 +113,8 @@ public MethodException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public MethodException(string message, Exception innerException) : base(message, innerException) + public MethodException(string message, Exception innerException) + : base(message, innerException) { } @@ -114,9 +125,12 @@ public MethodException(string message, Exception innerException) : base(message, /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal MethodException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal MethodException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -151,7 +165,8 @@ public class MethodInvocationException : MethodException /// Initializes a new instance of MethodInvocationException with the message set /// to typeof(MethodInvocationException).FullName. /// - public MethodInvocationException() : base(typeof(MethodInvocationException).FullName) + public MethodInvocationException() + : base(typeof(MethodInvocationException).FullName) { } @@ -159,7 +174,8 @@ public MethodInvocationException() : base(typeof(MethodInvocationException).Full /// Initializes a new instance of MethodInvocationException setting the message. /// /// The exception's message. - public MethodInvocationException(string message) : base(message) + public MethodInvocationException(string message) + : base(message) { } @@ -168,7 +184,8 @@ public MethodInvocationException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public MethodInvocationException(string message, Exception innerException) : base(message, innerException) + public MethodInvocationException(string message, Exception innerException) + : base(message, innerException) { } @@ -179,9 +196,12 @@ public MethodInvocationException(string message, Exception innerException) : bas /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal MethodInvocationException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal MethodInvocationException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -192,7 +212,7 @@ internal MethodInvocationException(string errorId, Exception innerException, /// Serialization information. /// Streaming context. protected MethodInvocationException(SerializationInfo info, StreamingContext context) - : base(info, context) + : base(info, context) { } #endregion Serialization @@ -214,7 +234,8 @@ public class GetValueException : ExtendedTypeSystemException /// Initializes a new instance of GetValueException with the message set /// to typeof(GetValueException).FullName. /// - public GetValueException() : base(typeof(GetValueException).FullName) + public GetValueException() + : base(typeof(GetValueException).FullName) { } @@ -222,7 +243,8 @@ public GetValueException() : base(typeof(GetValueException).FullName) /// Initializes a new instance of GetValueException setting the message. /// /// The exception's message. - public GetValueException(string message) : base(message) + public GetValueException(string message) + : base(message) { } @@ -231,7 +253,8 @@ public GetValueException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public GetValueException(string message, Exception innerException) : base(message, innerException) + public GetValueException(string message, Exception innerException) + : base(message, innerException) { } @@ -242,9 +265,12 @@ public GetValueException(string message, Exception innerException) : base(messag /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal GetValueException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal GetValueException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -255,7 +281,7 @@ internal GetValueException(string errorId, Exception innerException, /// Serialization information. /// Streaming context. protected GetValueException(SerializationInfo info, StreamingContext context) - : base(info, context) + : base(info, context) { } #endregion Serialization @@ -306,9 +332,12 @@ public PropertyNotFoundException(string message, Exception innerException) /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal PropertyNotFoundException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal PropertyNotFoundException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -341,7 +370,8 @@ public class GetValueInvocationException : GetValueException /// Initializes a new instance of GetValueInvocationException with the message set /// to typeof(GetValueInvocationException).FullName. /// - public GetValueInvocationException() : base(typeof(GetValueInvocationException).FullName) + public GetValueInvocationException() + : base(typeof(GetValueInvocationException).FullName) { } @@ -349,7 +379,8 @@ public GetValueInvocationException() : base(typeof(GetValueInvocationException). /// Initializes a new instance of GetValueInvocationException setting the message. /// /// The exception's message. - public GetValueInvocationException(string message) : base(message) + public GetValueInvocationException(string message) + : base(message) { } @@ -358,7 +389,8 @@ public GetValueInvocationException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public GetValueInvocationException(string message, Exception innerException) : base(message, innerException) + public GetValueInvocationException(string message, Exception innerException) + : base(message, innerException) { } @@ -369,9 +401,12 @@ public GetValueInvocationException(string message, Exception innerException) : b /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal GetValueInvocationException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal GetValueInvocationException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -382,7 +417,7 @@ internal GetValueInvocationException(string errorId, Exception innerException, /// Serialization information. /// Streaming context. protected GetValueInvocationException(SerializationInfo info, StreamingContext context) - : base(info, context) + : base(info, context) { } #endregion Serialization @@ -402,7 +437,8 @@ public class SetValueException : ExtendedTypeSystemException /// Initializes a new instance of SetValueException with the message set /// to typeof(SetValueException).FullName. /// - public SetValueException() : base(typeof(SetValueException).FullName) + public SetValueException() + : base(typeof(SetValueException).FullName) { } @@ -410,7 +446,8 @@ public SetValueException() : base(typeof(SetValueException).FullName) /// Initializes a new instance of SetValueException setting the message. /// /// The exception's message. - public SetValueException(string message) : base(message) + public SetValueException(string message) + : base(message) { } @@ -419,7 +456,8 @@ public SetValueException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public SetValueException(string message, Exception innerException) : base(message, innerException) + public SetValueException(string message, Exception innerException) + : base(message, innerException) { } @@ -430,9 +468,12 @@ public SetValueException(string message, Exception innerException) : base(messag /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal SetValueException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal SetValueException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -443,7 +484,7 @@ internal SetValueException(string errorId, Exception innerException, /// Serialization information. /// Streaming context. protected SetValueException(SerializationInfo info, StreamingContext context) - : base(info, context) + : base(info, context) { } #endregion Serialization @@ -463,7 +504,8 @@ public class SetValueInvocationException : SetValueException /// Initializes a new instance of SetValueInvocationException with the message set /// to typeof(SetValueInvocationException).FullName. /// - public SetValueInvocationException() : base(typeof(SetValueInvocationException).FullName) + public SetValueInvocationException() + : base(typeof(SetValueInvocationException).FullName) { } @@ -471,7 +513,8 @@ public SetValueInvocationException() : base(typeof(SetValueInvocationException). /// Initializes a new instance of SetValueInvocationException setting the message. /// /// The exception's message. - public SetValueInvocationException(string message) : base(message) + public SetValueInvocationException(string message) + : base(message) { } @@ -480,7 +523,8 @@ public SetValueInvocationException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public SetValueInvocationException(string message, Exception innerException) : base(message, innerException) + public SetValueInvocationException(string message, Exception innerException) + : base(message, innerException) { } @@ -491,9 +535,12 @@ public SetValueInvocationException(string message, Exception innerException) : b /// The inner exception. /// Resource string. /// Arguments to the resource string. - internal SetValueInvocationException(string errorId, Exception innerException, - string resourceString, params object[] arguments) : - base(errorId, innerException, resourceString, arguments) + internal SetValueInvocationException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : base(errorId, innerException, resourceString, arguments) { } @@ -504,7 +551,7 @@ internal SetValueInvocationException(string errorId, Exception innerException, /// Serialization information. /// Streaming context. protected SetValueInvocationException(SerializationInfo info, StreamingContext context) - : base(info, context) + : base(info, context) { } #endregion Serialization @@ -542,7 +589,8 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont /// /// Serialization information. /// Streaming context. - protected PSInvalidCastException(SerializationInfo info, StreamingContext context) : base(info, context) + protected PSInvalidCastException(SerializationInfo info, StreamingContext context) + : base(info, context) { _errorId = info.GetString("ErrorId"); } @@ -553,14 +601,16 @@ protected PSInvalidCastException(SerializationInfo info, StreamingContext contex /// Initializes a new instance of PSInvalidCastException with the message set /// to typeof(PSInvalidCastException).FullName. /// - public PSInvalidCastException() : base(typeof(PSInvalidCastException).FullName) + public PSInvalidCastException() + : base(typeof(PSInvalidCastException).FullName) { } /// /// Initializes a new instance of PSInvalidCastException setting the message. /// /// The exception's message. - public PSInvalidCastException(string message) : base(message) + public PSInvalidCastException(string message) + : base(message) { } /// @@ -568,7 +618,8 @@ public PSInvalidCastException(string message) : base(message) /// /// The exception's message. /// The exceptions's inner exception. - public PSInvalidCastException(string message, Exception innerException) : base(message, innerException) + public PSInvalidCastException(string message, Exception innerException) + : base(message, innerException) { } @@ -578,8 +629,14 @@ internal PSInvalidCastException(string errorId, string message, Exception innerE _errorId = errorId; } - internal PSInvalidCastException(string errorId, Exception innerException, string resourceString, params object[] arguments) - : this(errorId, StringUtil.Format(resourceString, arguments), innerException) + internal PSInvalidCastException( + string errorId, + Exception innerException, + string resourceString, + params object[] arguments) + : this( + errorId, StringUtil.Format(resourceString, arguments), + innerException) { } @@ -604,7 +661,6 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "PSInvalidCastException"; + private readonly string _errorId = "PSInvalidCastException"; } } - diff --git a/src/System.Management.Automation/engine/ExternalScriptInfo.cs b/src/System.Management.Automation/engine/ExternalScriptInfo.cs index d87e3027f2e..bbd49c76d36 100644 --- a/src/System.Management.Automation/engine/ExternalScriptInfo.cs +++ b/src/System.Management.Automation/engine/ExternalScriptInfo.cs @@ -193,7 +193,10 @@ public override SessionStateEntryVisibility Visibility return Context.EngineSessionState.CheckScriptVisibility(_path); } - set { throw PSTraceSource.NewNotImplementedException(); } + set + { + throw PSTraceSource.NewNotImplementedException(); + } } /// @@ -358,9 +361,8 @@ internal override CommandMetadata CommandMetadata { get { - return _commandMetadata ?? - (_commandMetadata = - new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS())); + return _commandMetadata ??= + new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS()); } } @@ -403,7 +405,7 @@ internal string RequiresApplicationID get { var data = GetRequiresData(); - return data == null ? null : data.RequiredApplicationId; + return data?.RequiredApplicationId; } } @@ -417,7 +419,7 @@ internal Version RequiresPSVersion get { var data = GetRequiresData(); - return data == null ? null : data.RequiredPSVersion; + return data?.RequiredPSVersion; } } @@ -426,7 +428,7 @@ internal IEnumerable RequiresPSEditions get { var data = GetRequiresData(); - return data == null ? null : data.RequiredPSEditions; + return data?.RequiredPSEditions; } } @@ -435,7 +437,7 @@ internal IEnumerable RequiresModules get { var data = GetRequiresData(); - return data == null ? null : data.RequiredModules; + return data?.RequiredModules; } } @@ -444,7 +446,7 @@ internal bool RequiresElevation get { var data = GetRequiresData(); - return data == null ? false : data.IsElevationRequired; + return data != null && data.IsElevationRequired; } } @@ -458,7 +460,7 @@ internal IEnumerable RequiresPSSnapIns get { var data = GetRequiresData(); - return data == null ? null : data.RequiresPSSnapIns; + return data?.RequiresPSSnapIns; } } @@ -608,4 +610,3 @@ internal PSSnapInSpecification(string psSnapinName) public Version Version { get; internal set; } } } - diff --git a/src/System.Management.Automation/engine/FunctionInfo.cs b/src/System.Management.Automation/engine/FunctionInfo.cs index 8afe41ece15..70ab80e8ca4 100644 --- a/src/System.Management.Automation/engine/FunctionInfo.cs +++ b/src/System.Management.Automation/engine/FunctionInfo.cs @@ -265,7 +265,7 @@ internal void Update(ScriptBlock newFunction, bool force, ScopedItemOptions opti } /// - /// Returns true if this function uses cmdlet binding mode for its parameters; otherwise returns false. + /// Returns if this function uses cmdlet binding mode for its parameters; otherwise returns . /// public bool CmdletBinding { @@ -277,7 +277,7 @@ public bool CmdletBinding /// /// Gets the name of the default parameter set. - /// Returns null if this function doesn't use cmdlet parameter binding or if the default parameter set wasn't specified. + /// Returns if this function doesn't use cmdlet parameter binding or if the default parameter set wasn't specified. /// public string DefaultParameterSet { @@ -479,9 +479,8 @@ internal override CommandMetadata CommandMetadata { get { - return _commandMetadata ?? - (_commandMetadata = - new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS())); + return _commandMetadata ??= + new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS()); } } diff --git a/src/System.Management.Automation/engine/GetCommandCommand.cs b/src/System.Management.Automation/engine/GetCommandCommand.cs index b3ab36ae19c..a1e5fa768ba 100644 --- a/src/System.Management.Automation/engine/GetCommandCommand.cs +++ b/src/System.Management.Automation/engine/GetCommandCommand.cs @@ -280,16 +280,14 @@ public SwitchParameter ListImported [ValidateNotNullOrEmpty] public string[] ParameterName { - get { return _parameterNames; } + get + { + return _parameterNames; + } set { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - _parameterNames = value; + _parameterNames = value ?? throw new ArgumentNullException(nameof(value)); _parameterNameWildcards = SessionStateUtilities.CreateWildcardsFromStrings( _parameterNames, WildcardOptions.CultureInvariant | WildcardOptions.IgnoreCase); @@ -316,7 +314,7 @@ public PSTypeName[] ParameterType { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } // if '...CimInstance#Win32_Process' is specified, then exclude '...CimInstance' @@ -350,7 +348,7 @@ public PSTypeName[] ParameterType [Parameter(ParameterSetName = "AllCommandSet")] public SwitchParameter UseFuzzyMatching { get; set; } - private List _commandScores = new List(); + private readonly List _commandScores = new List(); /// /// Gets or sets the parameter that determines if return cmdlets based on abbreviation expansion. @@ -484,7 +482,7 @@ protected override void EndProcessing() if ((_names == null) || (_nameContainsWildcard)) { // Use the stable sorting to sort the result list - _accumulatedResults = _accumulatedResults.OrderBy(a => a, new CommandInfoComparer()).ToList(); + _accumulatedResults = _accumulatedResults.OrderBy(static a => a, new CommandInfoComparer()).ToList(); } OutputResultsHelper(_accumulatedResults); @@ -515,7 +513,7 @@ private void OutputResultsHelper(IEnumerable results) if (UseFuzzyMatching) { - results = _commandScores.OrderBy(x => x.Score).Select(x => x.Command).ToList(); + results = _commandScores.OrderBy(static x => x.Score).Select(static x => x.Command).ToList(); } int count = 0; @@ -647,7 +645,7 @@ private PSObject GetSyntaxObject(CommandInfo command) /// /// The comparer to sort CommandInfo objects in the result list. /// - private class CommandInfoComparer : IComparer + private sealed class CommandInfoComparer : IComparer { /// /// Compare two CommandInfo objects first by their command types, and if they @@ -872,7 +870,7 @@ private void AccumulateMatchingCommands(IEnumerable commandNames) _commandScores.Add(commandScore); } - commands = _commandScores.Select(x => x.Command).ToList(); + commands = _commandScores.Select(static x => x.Command).ToList(); } else { @@ -1320,7 +1318,9 @@ private bool IsCommandMatch(ref CommandInfo current, out bool isDuplicate) } } - if (ArgumentList != null && !(current is CmdletInfo || current is IScriptCommandInfo)) + if (ArgumentList != null + && current is not CmdletInfo + && current is not IScriptCommandInfo) { // If current is not a cmdlet or script, we need to throw a terminating error. ThrowTerminatingError( @@ -1421,7 +1421,7 @@ private IEnumerable GetMatchingCommandsFromModules(string commandNa { PSModuleInfo module = null; - if (Context.EngineSessionState.ModuleTable.TryGetValue(Context.EngineSessionState.ModuleTableKeys[i], out module) == false) + if (!Context.EngineSessionState.ModuleTable.TryGetValue(Context.EngineSessionState.ModuleTableKeys[i], out module)) { Dbg.Assert(false, "ModuleTableKeys should be in sync with ModuleTable"); } @@ -1487,22 +1487,31 @@ private IEnumerable GetMatchingCommandsFromModules(string commandNa private bool IsCommandInResult(CommandInfo command) { bool isPresent = false; - bool commandHasModule = command.Module != null; - foreach (CommandInfo commandInfo in _accumulatedResults) - { - if ((command.CommandType == commandInfo.CommandType && - (string.Equals(command.Name, commandInfo.Name, StringComparison.OrdinalIgnoreCase) || - // If the command has been imported with a prefix, then just checking the names for duplication will not be enough. - // Hence, an additional check is done with the prefix information - string.Equals(ModuleCmdletBase.RemovePrefixFromCommandName(commandInfo.Name, commandInfo.Prefix), command.Name, StringComparison.OrdinalIgnoreCase)) - ) && commandInfo.Module != null && commandHasModule && - ( // We do reference equal comparison if both command are imported. If either one is not imported, we compare the module path - (commandInfo.IsImported && command.IsImported && commandInfo.Module.Equals(command.Module)) || - ((!commandInfo.IsImported || !command.IsImported) && commandInfo.Module.Path.Equals(command.Module.Path, StringComparison.OrdinalIgnoreCase)) - )) + + if (command.Module is not null) + { + foreach (CommandInfo commandInfo in _accumulatedResults) { - isPresent = true; - break; + if (commandInfo.Module is null || commandInfo.CommandType != command.CommandType) + { + continue; + } + + // We do reference equal comparison if both command are imported. If either one is not imported, we compare the module path + if ((!commandInfo.IsImported || !command.IsImported || !commandInfo.Module.Equals(command.Module)) + && ((commandInfo.IsImported && command.IsImported) || !commandInfo.Module.Path.Equals(command.Module.Path, StringComparison.OrdinalIgnoreCase))) + { + continue; + } + + // If the command has been imported with a prefix, then just checking the names for duplication will not be enough. + // Hence, an additional check is done with the prefix information + if (commandInfo.Name.Equals(command.Name, StringComparison.OrdinalIgnoreCase) + || ModuleCmdletBase.RemovePrefixFromCommandName(commandInfo.Name, commandInfo.Prefix).Equals(command.Name, StringComparison.OrdinalIgnoreCase)) + { + isPresent = true; + break; + } } } @@ -1513,7 +1522,7 @@ private bool IsCommandInResult(CommandInfo command) #region Members - private Dictionary _commandsWritten = + private readonly Dictionary _commandsWritten = new Dictionary(StringComparer.OrdinalIgnoreCase); private List _accumulatedResults = new List(); @@ -1630,8 +1639,7 @@ private static PSObject GetParameterType(Type parameterType) new ArrayList(Enum.GetValues(parameterType)) : new ArrayList(); returnParameterType.Properties.Add(new PSNoteProperty("EnumValues", enumValues)); - bool hasFlagAttribute = (isArray) ? - ((parameterType.GetCustomAttributes(typeof(FlagsAttribute), true)).Length > 0) : false; + bool hasFlagAttribute = (isArray) && ((parameterType.GetCustomAttributes(typeof(FlagsAttribute), true)).Length > 0); returnParameterType.Properties.Add(new PSNoteProperty("HasFlagAttribute", hasFlagAttribute)); // Recurse into array elements. @@ -1682,7 +1690,7 @@ public IEnumerable CompleteArgument(string commandName, string } } - return nouns.OrderBy(noun => noun).Select(noun => new CompletionResult(noun, noun, CompletionResultType.Text, noun)); + return nouns.OrderBy(static noun => noun).Select(static noun => new CompletionResult(noun, noun, CompletionResultType.Text, noun)); } } } diff --git a/src/System.Management.Automation/engine/ICommandRuntime.cs b/src/System.Management.Automation/engine/ICommandRuntime.cs index cf5de2b20ab..5ad67039d2e 100644 --- a/src/System.Management.Automation/engine/ICommandRuntime.cs +++ b/src/System.Management.Automation/engine/ICommandRuntime.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + using System.Management.Automation.Host; namespace System.Management.Automation @@ -26,7 +28,7 @@ public interface ICommandRuntime /// /// Returns an instance of the PSHost implementation for this environment. /// - PSHost Host { get; } + PSHost? Host { get; } #region Write /// /// Display debug information. @@ -65,7 +67,7 @@ public interface ICommandRuntime /// When the cmdlet wants to write a single object out, it will call this /// API. It is up to the implementation to decide what to do with these objects. /// - void WriteObject(object sendToPipeline); + void WriteObject(object? sendToPipeline); /// /// Called to write one or more objects to the output pipe. @@ -83,7 +85,7 @@ public interface ICommandRuntime /// When the cmdlet wants to write multiple objects out, it will call this /// API. It is up to the implementation to decide what to do with these objects. /// - void WriteObject(object sendToPipeline, bool enumerateCollection); + void WriteObject(object? sendToPipeline, bool enumerateCollection); /// /// Called by the cmdlet to display progress information. @@ -219,7 +221,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldProcess(string target); + bool ShouldProcess(string? target); /// /// Called by a cmdlet to confirm the operation with the user. Cmdlets which make changes @@ -265,7 +267,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldProcess(string target, string action); + bool ShouldProcess(string? target, string? action); /// /// Called by a cmdlet to confirm the operation with the user. Cmdlets which make changes @@ -319,7 +321,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldProcess(string verboseDescription, string verboseWarning, string caption); + bool ShouldProcess(string? verboseDescription, string? verboseWarning, string? caption); /// /// Called by a cmdlet to confirm the operation with the user. Cmdlets which make changes @@ -379,7 +381,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldProcess(string verboseDescription, string verboseWarning, string caption, out ShouldProcessReason shouldProcessReason); + bool ShouldProcess(string? verboseDescription, string? verboseWarning, string? caption, out ShouldProcessReason shouldProcessReason); /// /// Called by a cmdlet to confirm an operation or grouping of operations with the user. @@ -436,7 +438,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldContinue(string query, string caption); + bool ShouldContinue(string? query, string? caption); /// /// Called to confirm an operation or grouping of operations with the user. @@ -501,7 +503,7 @@ public interface ICommandRuntime /// /// /// - bool ShouldContinue(string query, string caption, ref bool yesToAll, ref bool noToAll); + bool ShouldContinue(string? query, string? caption, ref bool yesToAll, ref bool noToAll); #endregion Should @@ -515,7 +517,7 @@ public interface ICommandRuntime /// Gets an object that surfaces the current PowerShell transaction. /// When this object is disposed, PowerShell resets the active transaction. /// - PSTransactionContext CurrentPSTransaction { get; } + PSTransactionContext? CurrentPSTransaction { get; } #endregion Transaction Support #region Misc @@ -549,6 +551,7 @@ public interface ICommandRuntime /// if any information is to be added. It should encapsulate the /// error record into an exception and then throw that exception. /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] void ThrowTerminatingError(ErrorRecord errorRecord); #endregion ThrowTerminatingError #endregion misc @@ -614,6 +617,6 @@ public interface ICommandRuntime2 : ICommandRuntime /// performed, and the Cmdlet should move on to the next target resource. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - bool ShouldContinue(string query, string caption, bool hasSecurityImpact, ref bool yesToAll, ref bool noToAll); + bool ShouldContinue(string? query, string? caption, bool hasSecurityImpact, ref bool yesToAll, ref bool noToAll); } } diff --git a/src/System.Management.Automation/engine/InformationRecord.cs b/src/System.Management.Automation/engine/InformationRecord.cs index b9513e30d87..310c34a8809 100644 --- a/src/System.Management.Automation/engine/InformationRecord.cs +++ b/src/System.Management.Automation/engine/InformationRecord.cs @@ -29,7 +29,7 @@ public InformationRecord(object messageData, string source) this.TimeGenerated = DateTime.Now; this.NativeThreadId = PsUtils.GetNativeThreadId(); - this.ManagedThreadId = (uint)System.Threading.Thread.CurrentThread.ManagedThreadId; + this.ManagedThreadId = (uint)Environment.CurrentManagedThreadId; } private InformationRecord() { } @@ -81,7 +81,7 @@ internal InformationRecord(InformationRecord baseRecord) [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public List Tags { - get { return _tags ?? (_tags = new List()); } + get { return _tags ??= new List(); } internal set { _tags = value; } } @@ -109,7 +109,10 @@ public string User return _user; } - set { _user = value; } + set + { + _user = value; + } } private string _user; @@ -120,7 +123,7 @@ public string User [DataMember] public string Computer { - get { return this._computerName ?? (this._computerName = PsUtils.GetHostName()); } + get { return this._computerName ??= PsUtils.GetHostName(); } set { this._computerName = value; } } @@ -137,13 +140,16 @@ public uint ProcessId { if (!this._processId.HasValue) { - this._processId = (uint)System.Diagnostics.Process.GetCurrentProcess().Id; + this._processId = (uint)Environment.ProcessId; } return this._processId.Value; } - set { _processId = value; } + set + { + _processId = value; + } } private uint? _processId; diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index c284c66e2e0..99aa639d09c 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -26,7 +26,7 @@ namespace System.Management.Automation.Runspaces { - internal class EarlyStartup + internal static class EarlyStartup { internal static void Init() { @@ -45,10 +45,7 @@ internal static void Init() // We shouldn't create too many tasks. #if !UNIX // Amsi initialize can be a little slow - Task.Run(() => - { - AmsiUtils.WinScanContent(content: string.Empty, sourceMetadata: string.Empty, warmUp: true); - }); + Task.Run(() => AmsiUtils.WinScanContent(content: string.Empty, sourceMetadata: string.Empty, warmUp: true)); #endif // One other task for other stuff that's faster, but still a little slow. @@ -952,7 +949,7 @@ public override InitialSessionStateEntry Clone() /// public Collection Attributes { - get { return _attributes ?? (_attributes = new Collection()); } + get { return _attributes ??= new Collection(); } } private Collection _attributes; @@ -1250,10 +1247,10 @@ IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() return _internalCollection.GetEnumerator(); } - private Collection _internalCollection; + private readonly Collection _internalCollection; // object to use for locking - private object _syncObject = new object(); + private readonly object _syncObject = new object(); } /// @@ -1311,6 +1308,37 @@ private static void MakeDisallowedEntriesPrivate(InitialSessionStateEntryColl } } + #region VariableHelper + /// + /// A helper for adding variables to session state. + /// Experimental features can be handled here. + /// + /// The variables to add to session state. + private void AddVariables(IEnumerable variables) + { + Variables.Add(variables); + + // If the PSNativeCommandArgumentPassing feature is enabled, create the variable which controls the behavior + // Since the BuiltInVariables list is static, and this should be done dynamically + // we need to do this here. Also, since the defaults are different based on platform we need a + // bit more logic. + if (ExperimentalFeature.IsEnabled("PSNativeCommandArgumentPassing")) + { + NativeArgumentPassingStyle style = NativeArgumentPassingStyle.Standard; + if (Platform.IsWindows) { + style = NativeArgumentPassingStyle.Windows; + } + Variables.Add( + new SessionStateVariableEntry( + SpecialVariables.NativeArgumentPassing, + style, + RunspaceInit.NativeCommandArgumentPassingDescription, + ScopedItemOptions.None, + new ArgumentTypeConverterAttribute(typeof(NativeArgumentPassingStyle)))); + } + } + #endregion + /// /// Creates an initial session state from a PSSC configuration file. /// @@ -1349,7 +1377,7 @@ public static InitialSessionState CreateFromSessionConfigurationFile(string path public static InitialSessionState CreateRestricted(SessionCapabilities sessionCapabilities) { // only remote server has been requested - if (SessionCapabilities.RemoteServer == sessionCapabilities) + if (sessionCapabilities == SessionCapabilities.RemoteServer) { return CreateRestrictedForRemoteServer(); } @@ -1416,7 +1444,7 @@ private static InitialSessionState CreateRestrictedForRemoteServer() } // Add built-in variables. - iss.Variables.Add(BuiltInVariables); + iss.AddVariables(BuiltInVariables); // wrap some commands in a proxy function to restrict their parameters foreach (KeyValuePair proxyFunction in CommandMetadata.GetRestrictedCommands(SessionCapabilities.RemoteServer)) @@ -1438,7 +1466,7 @@ private static InitialSessionState CreateRestrictedForRemoteServer() } // Porting note: moved to Platform so we have one list to maintain - private static string[] s_PSCoreFormatFileNames = Platform.FormatFileNames.ToArray(); + private static readonly string[] s_PSCoreFormatFileNames = Platform.FormatFileNames.ToArray(); private static void IncludePowerShellCoreFormats(InitialSessionState iss) { @@ -1480,7 +1508,7 @@ public static InitialSessionState Create() // be causing test failures - i suspect due to lack test isolation - brucepay Mar 06/2008 #if false // Add the default variables and make them private... - iss.Variables.Add(BuiltInVariables); + iss.AddVariables(BuiltInVariables); foreach (SessionStateVariableEntry v in iss.Variables) { v.Visibility = SessionStateEntryVisibility.Private; @@ -1503,7 +1531,7 @@ public static InitialSessionState CreateDefault() InitialSessionState ss = new InitialSessionState(); - ss.Variables.Add(BuiltInVariables); + ss.AddVariables(BuiltInVariables); ss.Commands.Add(new SessionStateApplicationEntry("*")); ss.Commands.Add(new SessionStateScriptEntry("*")); ss.Commands.Add(BuiltInFunctions); @@ -1570,7 +1598,7 @@ public static InitialSessionState CreateDefault2() { InitialSessionState ss = new InitialSessionState(); - ss.Variables.Add(BuiltInVariables); + ss.AddVariables(BuiltInVariables); ss.Commands.Add(new SessionStateApplicationEntry("*")); ss.Commands.Add(new SessionStateScriptEntry("*")); ss.Commands.Add(BuiltInFunctions); @@ -1611,7 +1639,7 @@ public InitialSessionState Clone() { InitialSessionState ss = new InitialSessionState(); - ss.Variables.Add(this.Variables.Clone()); + ss.AddVariables(this.Variables.Clone()); ss.EnvironmentVariables.Add(this.EnvironmentVariables.Clone()); ss.Commands.Add(this.Commands.Clone()); ss.Assemblies.Add(this.Assemblies.Clone()); @@ -2118,7 +2146,7 @@ public virtual HashSet StartupScripts private HashSet _startupScripts = new HashSet(); - private object _syncObject = new object(); + private readonly object _syncObject = new object(); internal void Bind(ExecutionContext context, bool updateOnly, PSModuleInfo module, bool noClobber, bool local, bool setLocation) { @@ -2587,7 +2615,7 @@ HashSet GetPublicCommands() return null; } - private string[] GetModulesForUnResolvedCommands(IEnumerable unresolvedCommands, ExecutionContext context) + private static string[] GetModulesForUnResolvedCommands(IEnumerable unresolvedCommands, ExecutionContext context) { Collection modulesToImport = new Collection(); HashSet commandsToResolve = new HashSet(StringComparer.OrdinalIgnoreCase); @@ -3075,7 +3103,7 @@ private RunspaceOpenModuleLoadException ProcessModulesToImport( /// /// /// - private IEnumerable LookupCommands( + private static IEnumerable LookupCommands( string commandPattern, string moduleName, ExecutionContext context) @@ -3368,8 +3396,7 @@ internal static void SetSessionStateDrive(ExecutionContext context, bool setLoca { // If we can't access the Environment.CurrentDirectory, we may be in an AppContainer. Set the // default drive to $pshome - System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess(); - string defaultPath = System.IO.Path.GetDirectoryName(PsUtils.GetMainModule(currentProcess).FileName); + string defaultPath = System.IO.Path.GetDirectoryName(Environment.ProcessPath); context.EngineSessionState.SetLocation(defaultPath, providerContext); } } @@ -3472,13 +3499,13 @@ internal void Unbind(ExecutionContext context) List formatFilesToRemove = new List(); if (this.Formats != null) { - formatFilesToRemove.AddRange(this.Formats.Select(f => f.FileName)); + formatFilesToRemove.AddRange(this.Formats.Select(static f => f.FileName)); } List typeFilesToRemove = new List(); if (this.Types != null) { - typeFilesToRemove.AddRange(this.Types.Select(t => t.FileName)); + typeFilesToRemove.AddRange(this.Types.Select(static t => t.FileName)); } RemoveTypesAndFormats(context, formatFilesToRemove, typeFilesToRemove); @@ -3630,7 +3657,7 @@ internal void UpdateTypes(ExecutionContext context, bool updateOnly) } } - if (errors.Count > 0) + if (!errors.IsEmpty) { var allErrors = new StringBuilder(); allErrors.Append('\n'); @@ -3739,7 +3766,7 @@ internal void UpdateFormats(ExecutionContext context, bool update) // if this is the case... foreach (PSSnapInTypeAndFormatErrors entry in entries) { - if (entry.Errors != null && entry.Errors.Count > 0) + if (entry.Errors != null && !entry.Errors.IsEmpty) { foreach (string error in entry.Errors) { @@ -4100,7 +4127,7 @@ internal void ImportCmdletsFromAssembly(Assembly assembly, PSModuleInfo module) /// /// This is the default function to use for tab expansion. /// - private static string s_tabExpansionFunctionText = @" + private static readonly string s_tabExpansionFunctionText = @" <# Options include: RelativeFilePaths - [bool] Always resolve file paths using Resolve-Path -Relative. @@ -4275,7 +4302,13 @@ .FORWARDHELPCATEGORY Cmdlet } else { $pagerCommand = 'less' - $pagerArgs = '-Ps""Page %db?B of %D:.\. Press h for help or q to quit\.$""' + # PSNativeCommandArgumentPassing arguments should be constructed differently. + if ($EnabledExperimentalFeatures -contains 'PSNativeCommandArgumentPassing') { + $pagerArgs = '-s','-P','Page %db?B of %D:.\. Press h for help or q to quit\.' + } + else { + $pagerArgs = '-Ps""Page %db?B of %D:.\. Press h for help or q to quit\.$""' + } } # Respect PAGER environment variable which allows user to specify a custom pager. @@ -4315,10 +4348,16 @@ .FORWARDHELPCATEGORY Cmdlet $consoleWidth = [System.Math]::Max([System.Console]::WindowWidth, 20) if ($pagerArgs) { - # Supply pager arguments to an application without any PowerShell parsing of the arguments. + # Start the pager arguments directly if the PSNativeCommandArgumentPassing feature is enabled. + # Otherwise, supply pager arguments to an application without any PowerShell parsing of the arguments. # Leave environment variable to help user debug arguments supplied in $env:PAGER. - $env:__PSPAGER_ARGS = $pagerArgs - $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand --% %__PSPAGER_ARGS% + if ($EnabledExperimentalFeatures -contains 'PSNativeCommandArgumentPassing') { + $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand $pagerArgs + } + else { + $env:__PSPAGER_ARGS = $pagerArgs + $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand --% %__PSPAGER_ARGS% + } } else { $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand @@ -4445,6 +4484,13 @@ .ForwardHelpCategory Cmdlet new SessionStateVariableEntry(SpecialVariables.FirstToken, null, string.Empty), new SessionStateVariableEntry(SpecialVariables.StackTrace, null, string.Empty), + // Variable which controls the output rendering + new SessionStateVariableEntry( + SpecialVariables.PSStyle, + PSStyle.Instance, + RunspaceInit.PSStyleDescription, + ScopedItemOptions.None), + // Variable which controls the encoding for piping data to a NativeCommand new SessionStateVariableEntry( SpecialVariables.OutputEncoding, @@ -4624,7 +4670,7 @@ internal static SessionStateAliasEntry[] BuiltInAliases new SessionStateAliasEntry("gm", "Get-Member", string.Empty, ReadOnly), new SessionStateAliasEntry("gmo", "Get-Module", string.Empty, ReadOnly), new SessionStateAliasEntry("gp", "Get-ItemProperty", string.Empty, ReadOnly), - new SessionStateAliasEntry("gpv", "Get-ItemPropertyValue", string.Empty,ReadOnly), + new SessionStateAliasEntry("gpv", "Get-ItemPropertyValue", string.Empty, ReadOnly), new SessionStateAliasEntry("gps", "Get-Process", string.Empty, ReadOnly), new SessionStateAliasEntry("group", "Group-Object", string.Empty, ReadOnly), new SessionStateAliasEntry("gu", "Get-Unique", string.Empty, ReadOnly), @@ -4774,7 +4820,7 @@ internal static SessionStateAliasEntry[] BuiltInAliases internal static readonly ScriptBlock SetDriveScriptBlock = ScriptBlock.CreateDelayParsedScriptBlock(DefaultSetDriveFunctionText, isProductCode: true); - private static PSLanguageMode systemLanguageMode = (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ? PSLanguageMode.ConstrainedLanguage : PSLanguageMode.FullLanguage; + private static readonly PSLanguageMode systemLanguageMode = (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ? PSLanguageMode.ConstrainedLanguage : PSLanguageMode.FullLanguage; internal static readonly SessionStateFunctionEntry[] BuiltInFunctions = new SessionStateFunctionEntry[] { @@ -4783,7 +4829,7 @@ internal static SessionStateAliasEntry[] BuiltInAliases SessionStateFunctionEntry.GetDelayParsedFunctionEntry("cd\\", "Set-Location \\", isProductCode: true, languageMode: systemLanguageMode), // Win8: 320909. Retaining the original definition to ensure backward compatability. SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Pause", - string.Concat("$null = Read-Host '", CodeGeneration.EscapeSingleQuotedStringContent(RunspaceInit.PauseDefinitionString),"'"), isProductCode: true, languageMode: systemLanguageMode), + string.Concat("$null = Read-Host '", CodeGeneration.EscapeSingleQuotedStringContent(RunspaceInit.PauseDefinitionString), "'"), isProductCode: true, languageMode: systemLanguageMode), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("help", GetHelpPagingFunctionText(), isProductCode: true, languageMode: systemLanguageMode), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("prompt", DefaultPromptFunctionText, isProductCode: true, languageMode: systemLanguageMode), @@ -4841,7 +4887,7 @@ internal static void RemoveAllDrivesForProvider(ProviderInfo pi, SessionStateInt } } - private static PSTraceSource s_PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); + private static readonly PSTraceSource s_PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); internal static readonly string CoreSnapin = "Microsoft.PowerShell.Core"; internal static readonly string CoreModule = "Microsoft.PowerShell.Core"; @@ -5244,12 +5290,12 @@ private static void AnalyzeModuleAssemblyWithReflection( cmdlet.SetModule(moduleInfo); } - cmdlets = cmdlets ?? new Dictionary(StringComparer.OrdinalIgnoreCase); + cmdlets ??= new Dictionary(StringComparer.OrdinalIgnoreCase); cmdlets.Add(cmdletName, cmdlet); if (TryGetCustomAttribute(type, out AliasAttribute aliasAttribute)) { - aliases = aliases ?? new Dictionary>(StringComparer.OrdinalIgnoreCase); + aliases ??= new Dictionary>(StringComparer.OrdinalIgnoreCase); var aliasList = new List(); foreach (var alias in aliasAttribute.AliasNames) @@ -5302,7 +5348,7 @@ private static void AnalyzeModuleAssemblyWithReflection( provider.SetModule(moduleInfo); } - providers = providers ?? new Dictionary(StringComparer.OrdinalIgnoreCase); + providers ??= new Dictionary(StringComparer.OrdinalIgnoreCase); providers.Add(providerName, provider); s_PSSnapInTracer.WriteLine("{0} from type {1} is added as a provider. ", providerName, type.FullName); @@ -5395,7 +5441,7 @@ private static void InitializeCoreCmdletsAndProviders( if (ExperimentalFeature.IsEnabled("PSSubsystemPluginModel")) { - cmdlets.Add("Get-Subsystem", new SessionStateCmdletEntry("Get-Subsystem", typeof(Subsystem.GetSubsystemCommand), helpFile)); + cmdlets.Add("Get-PSSubsystem", new SessionStateCmdletEntry("Get-PSSubsystem", typeof(Subsystem.GetPSSubsystemCommand), helpFile)); } foreach (var val in cmdlets.Values) @@ -5439,7 +5485,7 @@ internal static IEnumerable GetAssemblyTypes(Assembly assembly, string nam try { // Return types that are public, non-abstract, non-interface and non-valueType. - return assembly.ExportedTypes.Where(t => !t.IsAbstract && !t.IsInterface && !t.IsValueType); + return assembly.ExportedTypes.Where(static t => !t.IsAbstract && !t.IsInterface && !t.IsValueType); } catch (ReflectionTypeLoadException e) { @@ -5492,7 +5538,7 @@ private static string GetHelpFile(string assemblyPath) return Path.GetFileName(assemblyPath).Replace(".ni.dll", ".dll") + StringLiterals.HelpFileExtension; } - private static PSTraceSource s_PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); + private static readonly PSTraceSource s_PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); } // Guid is {15d4c170-2f29-5689-a0e2-d95b0c7b4ea0} diff --git a/src/System.Management.Automation/engine/InternalCommands.cs b/src/System.Management.Automation/engine/InternalCommands.cs index 7c37cc4f0eb..8d628aea660 100644 --- a/src/System.Management.Automation/engine/InternalCommands.cs +++ b/src/System.Management.Automation/engine/InternalCommands.cs @@ -80,9 +80,9 @@ public sealed class ForEachObjectCommand : PSCmdlet, IDisposable [Parameter(ValueFromPipeline = true, ParameterSetName = ForEachObjectCommand.ParallelParameterSet)] public PSObject InputObject { - set { _inputObject = value; } - get { return _inputObject; } + + set { _inputObject = value; } } private PSObject _inputObject = AutomationNull.Value; @@ -91,7 +91,7 @@ public PSObject InputObject #region ScriptBlockSet - private List _scripts = new List(); + private readonly List _scripts = new List(); /// /// Gets or sets the script block to apply in begin processing. @@ -220,9 +220,9 @@ public string MemberName [Alias("Args")] public object[] ArgumentList { - set { _arguments = value; } - get { return _arguments; } + + set { _arguments = value; } } private object[] _arguments; @@ -381,6 +381,17 @@ public void Dispose() private Exception _taskCollectionException; private string _currentLocationPath; + // List of Foreach-Object command names and aliases. + // TODO: Look into using SessionState.Internal.GetAliasTable() to find all user created aliases. + // But update Alias command logic to maintain reverse table that lists all aliases mapping + // to a single command definition, for performance. + private static readonly string[] forEachNames = new string[] + { + "ForEach-Object", + "foreach", + "%" + }; + private void InitParallelParameterSet() { // The following common parameters are not (yet) supported in this parameter set. @@ -407,12 +418,12 @@ private void InitParallelParameterSet() { } - bool allowUsingExpression = this.Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage; - _usingValuesMap = ScriptBlockToPowerShellConverter.GetUsingValuesAsDictionary( - Parallel, - allowUsingExpression, - this.Context, - null); + var allowUsingExpression = this.Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage; + _usingValuesMap = ScriptBlockToPowerShellConverter.GetUsingValuesForEachParallel( + scriptBlock: Parallel, + isTrustedInput: allowUsingExpression, + context: this.Context, + foreachNames: forEachNames); // Validate using values map, which is a map of '$using:' variables referenced in the script. // Script block variables are not allowed since their behavior is undefined outside the runspace @@ -455,10 +466,7 @@ private void InitParallelParameterSet() _taskCollection = new PSDataCollection(); _taskDataStreamWriter = new PSTaskDataStreamWriter(this); _taskPool = new PSTaskPool(ThrottleLimit, UseNewRunspace); - _taskPool.PoolComplete += (sender, args) => - { - _taskDataStreamWriter.Close(); - }; + _taskPool.PoolComplete += (sender, args) => _taskDataStreamWriter.Close(); // Create timeout timer if requested. if (TimeoutSeconds != 0) @@ -1035,7 +1043,7 @@ private void MethodCallWithArguments() _propertyOrMethodName, possibleMatches)); } - else if (methods.Count == 0 || !(methods[0] is PSMethodInfo)) + else if (methods.Count == 0 || methods[0] is not PSMethodInfo) { // write error record: method no found WriteError(GenerateNameParameterError( @@ -1235,7 +1243,7 @@ private bool BlockMethodInLanguageMode(object inputObject) internal static ErrorRecord GenerateNameParameterError(string paraName, string resourceString, string errorId, object target, params object[] args) { string message; - if (args == null || 0 == args.Length) + if (args == null || args.Length == 0) { // Don't format in case the string contains literal curly braces message = resourceString; @@ -2008,8 +2016,7 @@ private void CheckLanguageMode() private object GetLikeRHSOperand(object operand) { - var val = operand as string; - if (val == null) + if (!(operand is string val)) { return operand; } @@ -2659,7 +2666,7 @@ public override object Transform(EngineIntrinsics engineIntrinsics, object input return PSVersionInfo.PSVersion; } - if (versionStr.Contains(".")) + if (versionStr.Contains('.')) { // If the string contains a '.', let the Version constructor handle the conversion. return inputData; diff --git a/src/System.Management.Automation/engine/InvocationInfo.cs b/src/System.Management.Automation/engine/InvocationInfo.cs index 1871ae3c9cd..d0ba2c15c41 100644 --- a/src/System.Management.Automation/engine/InvocationInfo.cs +++ b/src/System.Management.Automation/engine/InvocationInfo.cs @@ -201,11 +201,13 @@ public Dictionary BoundParameters { get { - return _boundParameters ?? - (_boundParameters = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return _boundParameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } - internal set { _boundParameters = value; } + internal set + { + _boundParameters = value; + } } /// @@ -213,7 +215,7 @@ public Dictionary BoundParameters /// public List UnboundArguments { - get { return _unboundArguments ?? (_unboundArguments = new List()); } + get { return _unboundArguments ??= new List(); } internal set { _unboundArguments = value; } } @@ -382,7 +384,10 @@ internal IScriptExtent ScriptPosition } } - set { _scriptPosition = value; } + set + { + _scriptPosition = value; + } } /// @@ -435,11 +440,11 @@ internal void ToPSObjectForRemoting(PSObject psObject) if (extent != null) { extent.ToPSObjectForRemoting(psObject); - RemotingEncoder.AddNoteProperty(psObject, "SerializeExtent", () => true); + RemotingEncoder.AddNoteProperty(psObject, "SerializeExtent", static () => true); } else { - RemotingEncoder.AddNoteProperty(psObject, "SerializeExtent", () => false); + RemotingEncoder.AddNoteProperty(psObject, "SerializeExtent", static () => false); } RemoteCommandInfo.ToPSObjectForRemoting(this.MyCommand, psObject); @@ -518,4 +523,3 @@ public override ReadOnlyCollection OutputType private string _definition; } } - diff --git a/src/System.Management.Automation/engine/ItemCmdletProviderInterfaces.cs b/src/System.Management.Automation/engine/ItemCmdletProviderInterfaces.cs index 699d60dafa0..1809ebd1c18 100644 --- a/src/System.Management.Automation/engine/ItemCmdletProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/ItemCmdletProviderInterfaces.cs @@ -2082,8 +2082,8 @@ internal bool IsContainer( #region private data - private Cmdlet _cmdlet; - private SessionStateInternal _sessionState; + private readonly Cmdlet _cmdlet; + private readonly SessionStateInternal _sessionState; #endregion private data } @@ -2105,4 +2105,3 @@ public enum CopyContainers CopyChildrenOfTargetContainer } } - diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 5929a5637e9..3176fbbead1 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -9,7 +9,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; -using System.Linq; using System.Linq.Expressions; using System.Management.Automation.Internal; using System.Management.Automation.Language; @@ -299,7 +298,7 @@ internal enum ConversionRank public static class LanguagePrimitives { [TraceSource("ETS", "Extended Type System")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("ETS", "Extended Type System"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("ETS", "Extended Type System"); internal delegate void MemberNotFoundError(PSObject pso, DictionaryEntry property, Type resultType); @@ -339,12 +338,13 @@ internal static void UpdateTypeConvertFromTypeTable(string typeName) { lock (s_converterCache) { - var toRemove = s_converterCache.Keys.Where( - conv => string.Equals(conv.to.FullName, typeName, StringComparison.OrdinalIgnoreCase) || - string.Equals(conv.from.FullName, typeName, StringComparison.OrdinalIgnoreCase)).ToArray(); - foreach (var k in toRemove) + foreach (var key in s_converterCache.Keys) { - s_converterCache.Remove(k); + if (string.Equals(key.to.FullName, typeName, StringComparison.OrdinalIgnoreCase) + || string.Equals(key.from.FullName, typeName, StringComparison.OrdinalIgnoreCase)) + { + s_converterCache.Remove(key); + } } // Note we do not clear possibleTypeConverter even when removing. @@ -362,10 +362,10 @@ internal static void UpdateTypeConvertFromTypeTable(string typeName) /// implementation of an object when we can't use it's non-generic /// implementation. /// - private class EnumerableTWrapper : IEnumerable + private sealed class EnumerableTWrapper : IEnumerable { - private object _enumerable; - private Type _enumerableType; + private readonly object _enumerable; + private readonly Type _enumerableType; private DynamicMethod _getEnumerator; internal EnumerableTWrapper(object enumerable, Type enumerableType) @@ -384,7 +384,7 @@ private void CreateGetEnumerator() emitter.Emit(OpCodes.Ldarg_0); emitter.Emit(OpCodes.Castclass, _enumerableType); - MethodInfo methodInfo = _enumerableType.GetMethod("GetEnumerator", new Type[] { }); + MethodInfo methodInfo = _enumerableType.GetMethod("GetEnumerator", Array.Empty()); emitter.Emit(OpCodes.Callvirt, methodInfo); emitter.Emit(OpCodes.Ret); } @@ -414,7 +414,7 @@ private static IEnumerable GetEnumerableFromIEnumerableT(object obj) private delegate IEnumerable GetEnumerableDelegate(object obj); - private static Dictionary s_getEnumerableCache = new Dictionary(32); + private static readonly Dictionary s_getEnumerableCache = new Dictionary(32); private static GetEnumerableDelegate GetOrCalculateEnumerable(Type type) { @@ -637,8 +637,7 @@ public static bool Equals(object first, object second, bool ignoreCase, IFormatP formatProvider = CultureInfo.InvariantCulture; } - var culture = formatProvider as CultureInfo; - if (culture == null) + if (!(formatProvider is CultureInfo culture)) { throw PSTraceSource.NewArgumentException(nameof(formatProvider)); } @@ -785,8 +784,7 @@ public static int Compare(object first, object second, bool ignoreCase, IFormatP formatProvider = CultureInfo.InvariantCulture; } - var culture = formatProvider as CultureInfo; - if (culture == null) + if (!(formatProvider is CultureInfo culture)) { throw PSTraceSource.NewArgumentException(nameof(formatProvider)); } @@ -1045,9 +1043,7 @@ internal static bool IsTrue(IList objectArray) // but since we don't want this to recurse indefinitely // we explicitly check the case where it would recurse // and deal with it. - IList firstElement = PSObject.Base(objectArray[0]) as IList; - - if (firstElement == null) + if (!(PSObject.Base(objectArray[0]) is IList firstElement)) { return IsTrue(objectArray[0]); } @@ -1506,7 +1502,7 @@ internal static object GetConverter(Type type, TypeTable backupTypeTable) private static object NewConverterInstance(string assemblyQualifiedTypeName) { - if (assemblyQualifiedTypeName.IndexOf(',') == -1) + if (!assemblyQualifiedTypeName.Contains(',')) { typeConversion.WriteLine("Type name \"{0}\" should be assembly qualified.", assemblyQualifiedTypeName); return null; @@ -1579,7 +1575,7 @@ public static string ConvertTypeNameToPSTypeName(string typeName) // CIM name string to .NET namestring mapping table // (Considered using the MI routines but they didn't do quite the right thing. // - private static Dictionary s_nameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { + private static readonly Dictionary s_nameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "SInt8", "SByte" }, { "UInt8", "Byte" }, { "SInt16", "Int16" }, @@ -1599,8 +1595,8 @@ public static string ConvertTypeNameToPSTypeName(string typeName) { "BooleanArray", "bool[]" }, { "UInt8Array", "byte[]" }, { "SInt8Array", "Sbyte[]" }, - { "UInt16Array", "uint16[]" }, - { "SInt16Array", "int64[]" }, + { "UInt16Array", "UInt16[]" }, + { "SInt16Array", "Int16[]" }, { "UInt32Array", "UInt32[]" }, { "SInt32Array", "Int32[]" }, { "UInt64Array", "UInt64[]" }, @@ -1893,7 +1889,7 @@ public override object ConvertFrom(object sourceValue, Type destinationType, IFo internal class EnumSingleTypeConverter : PSTypeConverter { - private class EnumHashEntry + private sealed class EnumHashEntry { internal EnumHashEntry(string[] names, Array values, UInt64 allValues, bool hasNegativeValue, bool hasFlagsAttribute) { @@ -2095,8 +2091,7 @@ public override object ConvertFrom(object sourceValue, Type destinationType, IFo protected static object BaseConvertFrom(object sourceValue, Type destinationType, IFormatProvider formatProvider, bool ignoreCase, bool multipleValues) { Diagnostics.Assert(sourceValue != null, "the type converter has a special case for null source values"); - string sourceValueString = sourceValue as string; - if (sourceValueString == null) + if (!(sourceValue is string sourceValueString)) { throw new PSInvalidCastException("InvalidCastEnumFromTypeNotAString", null, ExtendedTypeSystem.InvalidCastException, @@ -2138,7 +2133,7 @@ protected static object BaseConvertFrom(object sourceValue, Type destinationType WildcardPattern[] fromValuePatterns; if (!multipleValues) { - if (sourceValueString.Contains(",")) + if (sourceValueString.Contains(',')) { throw new PSInvalidCastException("InvalidCastEnumCommaAndNoFlags", null, ExtendedTypeSystem.InvalidCastExceptionEnumerationNoFlagAndComma, @@ -3689,7 +3684,7 @@ private static object ConvertEnumerableToEnum(object valueToConvert, return ConvertStringToEnum(sbResult.ToString(), resultType, recursion, originalValueToConvert, formatProvider, backupTable); } - private class PSMethodToDelegateConverter + private sealed class PSMethodToDelegateConverter { // Index of the matching overload method. private readonly int _matchIndex; @@ -3749,7 +3744,7 @@ internal Delegate Convert(object valueToConvert, } } - private class ConvertViaParseMethod + private sealed class ConvertViaParseMethod { // TODO - use an ETS wrapper that generates a dynamic method internal MethodInfo parse; @@ -3815,7 +3810,7 @@ internal object ConvertWithoutCulture(object valueToConvert, } } - private class ConvertViaConstructor + private sealed class ConvertViaConstructor { internal Func TargetCtorLambda; @@ -3859,7 +3854,7 @@ internal object Convert(object valueToConvert, /// 1. toType is a closed generic type and it has a constructor that takes IEnumerable[T], ICollection[T] or IList[T] /// 2. fromType is System.Array, System.Object[] or it's the same as the element type of toType /// - private class ConvertViaIEnumerableConstructor + private sealed class ConvertViaIEnumerableConstructor { internal Func ListCtorLambda; internal Func TargetCtorLambda; @@ -3952,7 +3947,7 @@ internal object Convert(object valueToConvert, } } - private class ConvertViaNoArgumentConstructor + private sealed class ConvertViaNoArgumentConstructor { private readonly Func _constructor; @@ -4055,7 +4050,7 @@ internal object Convert(object valueToConvert, } } - private class ConvertViaCast + private sealed class ConvertViaCast { internal MethodInfo cast; @@ -4135,7 +4130,7 @@ private static object ConvertNumericIConvertible(object valueToConvert, } } - private class ConvertCheckingForCustomConverter + private sealed class ConvertCheckingForCustomConverter { internal PSConverter tryfirstConverter; internal PSConverter fallbackConverter; @@ -4354,19 +4349,21 @@ internal delegate T PSConverter(object valueToConvert, internal delegate object PSNullConverter(object nullOrAutomationNull); +#nullable enable internal interface IConversionData { object Converter { get; } ConversionRank Rank { get; } - object Invoke(object valueToConvert, + object? Invoke(object? valueToConvert, Type resultType, bool recurse, - PSObject originalValueToConvert, - IFormatProvider formatProvider, - TypeTable backupTable); + PSObject? originalValueToConvert, + IFormatProvider? formatProvider, + TypeTable? backupTable); } +#nullable restore [System.Diagnostics.DebuggerDisplay("{_converter.Method.Name}")] internal class ConversionData : IConversionData @@ -4392,7 +4389,7 @@ public object Invoke(object valueToConvert, Type resultType, bool recurse, PSObj } } - private static Dictionary s_converterCache = new Dictionary(256); + private static readonly Dictionary s_converterCache = new Dictionary(256); private static IConversionData CacheConversion(Type fromType, Type toType, PSConverter converter, ConversionRank rank) { @@ -4430,7 +4427,7 @@ internal static ConversionRank GetConversionRank(Type fromType, Type toType) return FigureConversion(fromType, toType).Rank; } - private static Type[] s_numericTypes = new Type[] { + private static readonly Type[] s_numericTypes = new Type[] { typeof(Int16), typeof(Int32), typeof(Int64), typeof(UInt16), typeof(UInt32), typeof(UInt64), typeof(sbyte), typeof(byte), @@ -4438,17 +4435,17 @@ internal static ConversionRank GetConversionRank(Type fromType, Type toType) typeof(BigInteger) }; - private static Type[] s_integerTypes = new Type[] { + private static readonly Type[] s_integerTypes = new Type[] { typeof(Int16), typeof(Int32), typeof(Int64), typeof(UInt16), typeof(UInt32), typeof(UInt64), typeof(sbyte), typeof(byte) }; // Do not reorder the elements of these arrays, we depend on them being ordered by increasing size. - private static Type[] s_signedIntegerTypes = new Type[] { typeof(sbyte), typeof(Int16), typeof(Int32), typeof(Int64) }; - private static Type[] s_unsignedIntegerTypes = new Type[] { typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64) }; + private static readonly Type[] s_signedIntegerTypes = new Type[] { typeof(sbyte), typeof(Int16), typeof(Int32), typeof(Int64) }; + private static readonly Type[] s_unsignedIntegerTypes = new Type[] { typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64) }; - private static Type[] s_realTypes = new Type[] { typeof(Single), typeof(double), typeof(decimal) }; + private static readonly Type[] s_realTypes = new Type[] { typeof(Single), typeof(double), typeof(decimal) }; internal static void RebuildConversionCache() { @@ -4747,7 +4744,7 @@ private static string GetAvailableProperties(PSObject pso) { foreach (PSPropertyInfo p in pso.Properties) { - if (first == false) + if (!first) { availableProperties.Append(" , "); } @@ -5109,7 +5106,7 @@ private static IConversionData FigureLanguageConversion(Type fromType, Type toTy return null; } - private struct SignatureComparator + private readonly struct SignatureComparator { private enum TypeMatchingContext { @@ -5580,7 +5577,7 @@ private static bool TypeConverterPossiblyExists(Type type) return false; } - private static Dictionary s_possibleTypeConverter = new Dictionary(16); + private static readonly Dictionary s_possibleTypeConverter = new Dictionary(16); // This is the internal dummy type used when an IDictionary is converted to a pscustomobject // PS C:\> $ps = [pscustomobject]@{a=10;b=5} @@ -5654,15 +5651,6 @@ internal static IConversionData FigureConversion(Type fromType, Type toType) } } - // Assemblies in CoreCLR might not allow reflection execution on their internal types. - if (!TypeResolver.IsPublic(toType) && DotNetAdapter.DisallowPrivateReflection(toType)) - { - // If the type is non-public and reflection execution is not allowed on it, then we return - // 'ConvertNoConversion', because we won't be able to invoke constructor, methods or set - // properties on an instance of this type through reflection. - return CacheConversion(fromType, toType, ConvertNoConversion, ConversionRank.None); - } - PSConverter valueDependentConversion = null; ConversionRank valueDependentRank = ConversionRank.None; IConversionData conversionData = FigureLanguageConversion(fromType, toType, out valueDependentConversion, out valueDependentRank); @@ -5784,7 +5772,7 @@ internal static IConversionData FigureConversion(Type fromType, Type toType) return CacheConversion(fromType, toType, converter, rank); } - internal class Null { }; + internal class Null { } private static IConversionData FigureConversionFromNull(Type toType) { diff --git a/src/System.Management.Automation/engine/ManagementObjectAdapter.cs b/src/System.Management.Automation/engine/ManagementObjectAdapter.cs index 94e07d3af0e..c591a6963ec 100644 --- a/src/System.Management.Automation/engine/ManagementObjectAdapter.cs +++ b/src/System.Management.Automation/engine/ManagementObjectAdapter.cs @@ -77,17 +77,17 @@ public WMIParameterInformation(string name, Type ty) : base(ty, true, null, fals /// /// /// - private IEnumerable GetTypeNameHierarchyFromDerivation(ManagementBaseObject managementObj, + private static IEnumerable GetTypeNameHierarchyFromDerivation(ManagementBaseObject managementObj, string dotnetBaseType, bool shouldIncludeNamespace) { StringBuilder type = new StringBuilder(200); // give the typename based on NameSpace and Class type.Append(dotnetBaseType); - type.Append("#"); + type.Append('#'); if (shouldIncludeNamespace) { type.Append(managementObj.SystemProperties["__NAMESPACE"].Value); - type.Append("\\"); + type.Append('\\'); } type.Append(managementObj.SystemProperties["__CLASS"].Value); @@ -112,11 +112,11 @@ private IEnumerable GetTypeNameHierarchyFromDerivation(ManagementBaseObj { type.Clear(); type.Append(dotnetBaseType); - type.Append("#"); + type.Append('#'); if (shouldIncludeNamespace) { type.Append(managementObj.SystemProperties["__NAMESPACE"].Value); - type.Append("\\"); + type.Append('\\'); } type.Append(t); @@ -172,9 +172,7 @@ protected override T GetMember(object obj, string memberName) { tracer.WriteLine("Getting member with name {0}", memberName); - ManagementBaseObject mgmtObject = obj as ManagementBaseObject; - - if (mgmtObject == null) + if (!(obj is ManagementBaseObject mgmtObject)) { return null; } @@ -366,8 +364,7 @@ protected override object PropertyGet(PSProperty property) /// Instructs the adapter to convert before setting, if the adapter supports conversion. protected override void PropertySet(PSProperty property, object setValue, bool convertIfPossible) { - ManagementBaseObject mObj = property.baseObject as ManagementBaseObject; - if (mObj == null) + if (!(property.baseObject is ManagementBaseObject mObj)) { throw new SetValueInvocationException("CannotSetNonManagementObjectMsg", null, @@ -412,7 +409,7 @@ protected override string PropertyToString(PSProperty property) // } returnValue.Append(PropertyType(property, forDisplay: true)); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(property.Name); returnValue.Append(" {"); if (PropertyIsGettable(property)) @@ -425,7 +422,7 @@ protected override string PropertyToString(PSProperty property) returnValue.Append("set;"); } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -856,7 +853,7 @@ internal static string GetMethodDefinition(MethodData mData) } inParameterString.Append(typeName); - inParameterString.Append(" "); + inParameterString.Append(' '); inParameterString.Append(parameter.Name); inParameterString.Append(", "); } @@ -872,9 +869,9 @@ internal static string GetMethodDefinition(MethodData mData) builder.Append("System.Management.ManagementBaseObject "); builder.Append(mData.Name); - builder.Append("("); - builder.Append(inParameterString.ToString()); - builder.Append(")"); + builder.Append('('); + builder.Append(inParameterString); + builder.Append(')'); string returnValue = builder.ToString(); tracer.WriteLine("Definition constructed: {0}", returnValue); @@ -946,7 +943,7 @@ protected abstract PSProperty DoGetProperty(ManagementBaseObject wmiObject, #region Private Data - private static HybridDictionary s_instanceMethodCacheTable = new HybridDictionary(); + private static readonly HybridDictionary s_instanceMethodCacheTable = new HybridDictionary(); #endregion } diff --git a/src/System.Management.Automation/engine/MergedCommandParameterMetadata.cs b/src/System.Management.Automation/engine/MergedCommandParameterMetadata.cs index 440fe17396f..f2d20c68ec9 100644 --- a/src/System.Management.Automation/engine/MergedCommandParameterMetadata.cs +++ b/src/System.Management.Automation/engine/MergedCommandParameterMetadata.cs @@ -708,4 +708,3 @@ internal enum ParameterBinderAssociation PagingParameters, } } - diff --git a/src/System.Management.Automation/engine/MinishellParameterBinderController.cs b/src/System.Management.Automation/engine/MinishellParameterBinderController.cs index 4bf375e7c99..e19defd57a7 100644 --- a/src/System.Management.Automation/engine/MinishellParameterBinderController.cs +++ b/src/System.Management.Automation/engine/MinishellParameterBinderController.cs @@ -99,7 +99,7 @@ internal Collection BindParameters(Collection /// Handles error handling if some parameter is specified more than once. @@ -271,7 +271,7 @@ private void HandleSeenParameter(ref MinishellParameters seen, MinishellParamete } else { - seen = seen | parameter; + seen |= parameter; } } diff --git a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs index dd188b3ff99..bb2cf74495e 100644 --- a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs +++ b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs @@ -27,13 +27,13 @@ namespace System.Management.Automation /// Changes to these type of modules will not be re-analyzed, unless the user re-imports the module, /// or runs Get-Module -List. /// - internal class AnalysisCache + internal static class AnalysisCache { - private static AnalysisCacheData s_cacheData = AnalysisCacheData.Get(); + private static readonly AnalysisCacheData s_cacheData = AnalysisCacheData.Get(); // This dictionary shouldn't see much use, so low concurrency and capacity - private static ConcurrentDictionary s_modulesBeingAnalyzed = - new ConcurrentDictionary( /*concurrency*/1, /*capacity*/2, StringComparer.OrdinalIgnoreCase); + private static readonly ConcurrentDictionary s_modulesBeingAnalyzed = + new(concurrencyLevel: 1, capacity: 2, StringComparer.OrdinalIgnoreCase); internal static readonly char[] InvalidCommandNameCharacters = new[] { @@ -194,8 +194,7 @@ internal static bool ModuleIsEditionIncompatible(string modulePath, Hashtable mo internal static bool ModuleAnalysisViaGetModuleRequired(object modulePathObj, bool hadCmdlets, bool hadFunctions, bool hadAliases) { - var modulePath = modulePathObj as string; - if (modulePath == null) + if (!(modulePathObj is string modulePath)) return true; if (modulePath.EndsWith(StringLiterals.PowerShellModuleFileExtension, StringComparison.OrdinalIgnoreCase)) @@ -257,8 +256,7 @@ private static bool CheckModulesTypesInManifestAgainstExportedCommands(Hashtable return ModuleAnalysisViaGetModuleRequired(nestedModule, hadCmdlets, hadFunctions, hadAliases); } - var nestedModuleArray = nestedModules as object[]; - if (nestedModuleArray == null) + if (!(nestedModules is object[] nestedModuleArray)) return true; foreach (var element in nestedModuleArray) @@ -362,7 +360,7 @@ private static ConcurrentDictionary AnalyzeScriptModule(st if (commandName.IndexOfAny(InvalidCommandNameCharacters) < 0) { result.AddOrUpdate(commandName, CommandTypes.Alias, - (_, existingCommandType) => existingCommandType | CommandTypes.Alias); + static (_, existingCommandType) => existingCommandType | CommandTypes.Alias); } } @@ -373,11 +371,11 @@ private static ConcurrentDictionary AnalyzeScriptModule(st try { - foreach (string item in Directory.GetFiles(baseDirectory, "*.ps1")) + foreach (string item in Directory.EnumerateFiles(baseDirectory, "*.ps1")) { var command = Path.GetFileNameWithoutExtension(item); result.AddOrUpdate(command, CommandTypes.ExternalScript, - (_, existingCommandType) => existingCommandType | CommandTypes.ExternalScript); + static (_, existingCommandType) => existingCommandType | CommandTypes.ExternalScript); } } catch (UnauthorizedAccessException) @@ -386,8 +384,10 @@ private static ConcurrentDictionary AnalyzeScriptModule(st } } - var exportedClasses = new ConcurrentDictionary( /*concurrency*/ - 1, scriptAnalysis.DiscoveredClasses.Count, StringComparer.OrdinalIgnoreCase); + ConcurrentDictionary exportedClasses = new( + concurrencyLevel: 1, + capacity: scriptAnalysis.DiscoveredClasses.Count, + StringComparer.OrdinalIgnoreCase); foreach (var exportedClass in scriptAnalysis.DiscoveredClasses) { exportedClasses[exportedClass.Name] = exportedClass.TypeAttributes; @@ -642,7 +642,7 @@ private static bool GetModuleEntryFromCache(string modulePath, out DateTime last } } - internal class AnalysisCacheData + internal sealed class AnalysisCacheData { private static byte[] GetHeader() { diff --git a/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs b/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs index 7dc91d76776..8520e39258b 100644 --- a/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs @@ -28,6 +28,11 @@ public sealed class ExportModuleMemberCommand : PSCmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { + get + { + return _functionList; + } + set { _functionList = value; @@ -42,8 +47,6 @@ public string[] Function } } } - - get { return _functionList; } } private string[] _functionList; @@ -57,6 +60,11 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { + get + { + return _cmdletList; + } + set { _cmdletList = value; @@ -71,8 +79,6 @@ public string[] Cmdlet } } } - - get { return _cmdletList; } } private string[] _cmdletList; @@ -86,6 +92,11 @@ public string[] Cmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Variable { + get + { + return _variableExportList; + } + set { _variableExportList = value; @@ -100,8 +111,6 @@ public string[] Variable } } } - - get { return _variableExportList; } } private string[] _variableExportList; @@ -115,6 +124,11 @@ public string[] Variable [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Alias { + get + { + return _aliasExportList; + } + set { _aliasExportList = value; @@ -129,8 +143,6 @@ public string[] Alias } } } - - get { return _aliasExportList; } } private string[] _aliasExportList; diff --git a/src/System.Management.Automation/engine/Modules/GetModuleCommand.cs b/src/System.Management.Automation/engine/Modules/GetModuleCommand.cs index bfecce83e4e..743b64a1b0e 100644 --- a/src/System.Management.Automation/engine/Modules/GetModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/GetModuleCommand.cs @@ -165,8 +165,8 @@ private IEnumerable GetAvailableViaPsrpSessionCore(string[] module "Get-Module"); foreach ( PSObject outputObject in - RemoteDiscoveryHelper.InvokePowerShell(powerShell, this.CancellationToken, this, - errorMessageTemplate)) + RemoteDiscoveryHelper.InvokePowerShell(powerShell, this, errorMessageTemplate, + this.CancellationToken)) { PSModuleInfo moduleInfo = RemoteDiscoveryHelper.RehydratePSModuleInfo(outputObject); yield return moduleInfo; @@ -174,7 +174,7 @@ PSObject outputObject in } } - private PSModuleInfo GetModuleInfoForRemoteModuleWithoutManifest(RemoteDiscoveryHelper.CimModule cimModule) + private static PSModuleInfo GetModuleInfoForRemoteModuleWithoutManifest(RemoteDiscoveryHelper.CimModule cimModule) { return new PSModuleInfo(cimModule.ModuleName, null, null); } @@ -265,7 +265,7 @@ private IEnumerable GetAvailableViaCimSessionCore(IEnumerable remoteModuleInfos = remoteModules .Select(cimModule => this.ConvertCimModuleInfoToPSModuleInfo(cimModule, cimSession.ComputerName)) - .Where(moduleInfo => moduleInfo != null); + .Where(static moduleInfo => moduleInfo != null); return remoteModuleInfos; } @@ -382,8 +382,8 @@ protected override void ProcessRecord() FullyQualifiedName[modSpecIndex] = FullyQualifiedName[modSpecIndex].WithNormalizedName(Context, SessionState.Path.CurrentLocation.Path); } - moduleSpecTable = FullyQualifiedName.ToDictionary(moduleSpecification => moduleSpecification.Name, StringComparer.OrdinalIgnoreCase); - strNames.AddRange(FullyQualifiedName.Select(spec => spec.Name)); + moduleSpecTable = FullyQualifiedName.ToDictionary(static moduleSpecification => moduleSpecification.Name, StringComparer.OrdinalIgnoreCase); + strNames.AddRange(FullyQualifiedName.Select(static spec => spec.Name)); } string[] names = strNames.Count > 0 ? strNames.ToArray() : null; @@ -515,7 +515,7 @@ private IEnumerable FilterModulesForEditionAndSpecification( // Edition check only applies to Windows System32 module path if (!SkipEditionCheck && ListAvailable && !All) { - modules = modules.Where(module => module.IsConsideredEditionCompatible); + modules = modules.Where(static module => module.IsConsideredEditionCompatible); } #endif diff --git a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs index f6641930bf7..2cbb30bcb00 100644 --- a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs @@ -63,9 +63,9 @@ public sealed class ImportModuleCommand : ModuleCmdletBase, IDisposable [Parameter] public SwitchParameter Global { - set { base.BaseGlobal = value; } - get { return base.BaseGlobal; } + + set { base.BaseGlobal = value; } } /// @@ -75,9 +75,9 @@ public SwitchParameter Global [ValidateNotNull] public string Prefix { - set { BasePrefix = value; } - get { return BasePrefix; } + + set { BasePrefix = value; } } /// @@ -89,7 +89,7 @@ public string Prefix [Parameter(ParameterSetName = ParameterSet_ViaWinCompat, Mandatory = true, ValueFromPipeline = true, Position = 0)] [ValidateTrustedData] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] - public string[] Name { set; get; } = Array.Empty(); + public string[] Name { get; set; } = Array.Empty(); /// /// This parameter specifies the current pipeline object. @@ -117,6 +117,11 @@ public string Prefix [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { + get + { + return _functionImportList; + } + set { if (value == null) @@ -130,8 +135,6 @@ public string[] Function BaseFunctionPatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _functionImportList; } } private string[] _functionImportList = Array.Empty(); @@ -144,6 +147,11 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { + get + { + return _cmdletImportList; + } + set { if (value == null) @@ -158,8 +166,6 @@ public string[] Cmdlet BaseCmdletPatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _cmdletImportList; } } private string[] _cmdletImportList = Array.Empty(); @@ -172,6 +178,11 @@ public string[] Cmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Variable { + get + { + return _variableExportList; + } + set { if (value == null) @@ -185,8 +196,6 @@ public string[] Variable BaseVariablePatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _variableExportList; } } private string[] _variableExportList; @@ -199,6 +208,11 @@ public string[] Variable [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Alias { + get + { + return _aliasExportList; + } + set { if (value == null) @@ -213,8 +227,6 @@ public string[] Alias BaseAliasPatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _aliasExportList; } } private string[] _aliasExportList; @@ -335,7 +347,7 @@ public Version RequiredVersion [Parameter(ParameterSetName = ParameterSet_ModuleInfo, Mandatory = true, ValueFromPipeline = true, Position = 0)] [ValidateTrustedData] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] - public PSModuleInfo[] ModuleInfo { set; get; } = Array.Empty(); + public PSModuleInfo[] ModuleInfo { get; set; } = Array.Empty(); /// /// The arguments to pass to the module script. @@ -375,7 +387,10 @@ public SwitchParameter DisableNameChecking [ValidateSet("Local", "Global")] public string Scope { - get { return _scope; } + get + { + return _scope; + } set { @@ -573,11 +588,18 @@ private void ImportModule_ViaAssembly(ImportModuleOptions importModuleOptions, A if (!moduleLoaded) { - bool found; - PSModuleInfo module = LoadBinaryModule(false, null, null, suppliedAssembly, null, null, + PSModuleInfo module = LoadBinaryModule( + moduleName: null, + fileName: null, + suppliedAssembly, + moduleBase: null, + ss: null, importModuleOptions, ManifestProcessingFlags.LoadElements | ManifestProcessingFlags.WriteErrors | ManifestProcessingFlags.NullOnFirstError, - this.BasePrefix, false /* loadTypes */ , false /* loadFormats */, out found); + this.BasePrefix, + loadTypes: false, + loadFormats: false, + out bool found); if (found && module != null) { @@ -957,9 +979,9 @@ private IList ImportModule_RemotelyViaPsrpSession( string.Format(CultureInfo.InvariantCulture, "Import-Module -Name '{0}'", moduleName)); remotelyImportedModules = RemoteDiscoveryHelper.InvokePowerShell( powerShell, - this.CancellationToken, this, - errorMessageTemplate).ToList(); + errorMessageTemplate, + this.CancellationToken).ToList(); } List result = new List(); @@ -1076,8 +1098,7 @@ private PSModuleInfo ImportModule_RemotelyViaPsrpSession_SinglePreimportedModule CultureInfo.InvariantCulture, Modules.RemoteDiscoveryFailedToGenerateProxyForRemoteModule, remoteModuleName); - int numberOfLocallyCreatedFiles = RemoteDiscoveryHelper.InvokePowerShell(powerShell, this.CancellationToken, this, errorMessageTemplate).Count(); - if (numberOfLocallyCreatedFiles == 0) + if (!RemoteDiscoveryHelper.InvokePowerShell(powerShell, this, errorMessageTemplate, this.CancellationToken).Any()) { return null; } @@ -1286,8 +1307,8 @@ private void ImportModule_RemotelyViaCimSession( this, this.CancellationToken).ToList(); - IEnumerable remotePsCimModules = remoteModules.Where(cimModule => cimModule.IsPsCimModule); - IEnumerable remotePsrpModuleNames = remoteModules.Where(cimModule => !cimModule.IsPsCimModule).Select(cimModule => cimModule.ModuleName); + IEnumerable remotePsCimModules = remoteModules.Where(static cimModule => cimModule.IsPsCimModule); + IEnumerable remotePsrpModuleNames = remoteModules.Where(static cimModule => !cimModule.IsPsCimModule).Select(static cimModule => cimModule.ModuleName); foreach (string psrpModuleName in remotePsrpModuleNames) { string errorMessage = string.Format( @@ -1305,7 +1326,7 @@ private void ImportModule_RemotelyViaCimSession( // // report an error if some modules were not found // - IEnumerable allFoundModuleNames = remoteModules.Select(cimModule => cimModule.ModuleName).ToList(); + IEnumerable allFoundModuleNames = remoteModules.Select(static cimModule => cimModule.ModuleName).ToList(); foreach (string requestedModuleName in moduleNames) { var wildcardPattern = WildcardPattern.Get(requestedModuleName, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); @@ -1394,7 +1415,7 @@ private static bool IsCmdletizationFile(RemoteDiscoveryHelper.CimModuleFile cimM return cimModuleFile.FileCode == RemoteDiscoveryHelper.CimFileCode.CmdletizationV1; } - private IEnumerable CreateCimModuleFiles( + private static IEnumerable CreateCimModuleFiles( RemoteDiscoveryHelper.CimModule remoteCimModule, RemoteDiscoveryHelper.CimFileCode fileCode, Func filesFilter, @@ -1823,11 +1844,11 @@ protected override void ProcessRecord() ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, module.Name); RemoteDiscoveryHelper.DispatchModuleInfoProcessing( module, - localAction: delegate () - { - ImportModule_ViaLocalModuleInfo(importModuleOptions, module); - SetModuleBaseForEngineModules(module.Name, this.Context); - }, + localAction: () => + { + ImportModule_ViaLocalModuleInfo(importModuleOptions, module); + SetModuleBaseForEngineModules(module.Name, this.Context); + }, cimSessionAction: (cimSession, resourceUri, cimNamespace) => ImportModule_RemotelyViaCimSession( importModuleOptions, @@ -2024,7 +2045,7 @@ internal override IList ImportModulesUsingWinCompat(IEnumerable ImportModulesUsingWinCompat(IEnumerable ImportModulesUsingWinCompat(IEnumerable /// This parameter specified a prefix used to modify names of imported commands. /// - internal string BasePrefix { set; get; } = string.Empty; + internal string BasePrefix { get; set; } = string.Empty; /// /// Flags -force operations. @@ -274,7 +274,7 @@ internal List MatchAll "DefaultCommandPrefix" }; - private static string[] s_moduleVersionMembers = new string[] { + private static readonly string[] s_moduleVersionMembers = new string[] { "ModuleName", "GUID", "ModuleVersion" @@ -305,7 +305,7 @@ internal List MatchAll /// internal static readonly object s_WindowsPowerShellCompatSyncObject = new object(); - private Dictionary _currentlyProcessingModules = new Dictionary(); + private readonly Dictionary _currentlyProcessingModules = new Dictionary(); internal bool LoadUsingModulePath(bool found, IEnumerable modulePath, string name, SessionState ss, ImportModuleOptions options, ManifestProcessingFlags manifestProcessingFlags, out PSModuleInfo module) @@ -334,7 +334,7 @@ internal bool LoadUsingModulePath(PSModuleInfo parentModule, bool found, IEnumer foreach (string folder in Directory.EnumerateDirectories(path)) { string moduleName = Path.GetFileName(folder); - if (string.Compare(moduleName, fileBaseName, StringComparison.OrdinalIgnoreCase) == 0) + if (string.Equals(moduleName, fileBaseName, StringComparison.OrdinalIgnoreCase)) { fileBaseName = moduleName; #endif @@ -452,7 +452,7 @@ private Hashtable LoadModuleManifestData( } catch (RuntimeException pe) { - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors)) + if ((manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0) { string message = StringUtil.Format(Modules.InvalidModuleManifest, scriptInfo.Path, pe.Message); MissingMemberException mm = new MissingMemberException(message); @@ -483,8 +483,8 @@ internal Hashtable LoadModuleManifestData( { string message; - var importingModule = 0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements); - var writingErrors = 0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors); + var importingModule = (manifestProcessingFlags & ManifestProcessingFlags.LoadElements) != 0; + var writingErrors = (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0; // Load the data file(s) to get the module info... try @@ -556,7 +556,7 @@ internal Hashtable LoadModuleManifestData( if (validMembers != null && !ValidateManifestHash(data, validMembers, moduleManifestPath, manifestProcessingFlags)) { containedErrors = true; - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.NullOnFirstError)) + if ((manifestProcessingFlags & ManifestProcessingFlags.NullOnFirstError) != 0) return null; } @@ -591,9 +591,9 @@ private bool ValidateManifestHash( { if (badKeys.Length > 0) badKeys.Append(", "); - badKeys.Append("'"); + badKeys.Append('\''); badKeys.Append(s); - badKeys.Append("'"); + badKeys.Append('\''); } } @@ -602,7 +602,7 @@ private bool ValidateManifestHash( result = false; string message = null; - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors)) + if ((manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0) { // Check for PowerShell Version before checking other keys // If a PowerShellVersion exists and does not match the requirements, then the error is InsufficientPowerShellVersion @@ -630,7 +630,7 @@ private bool ValidateManifestHash( validMembersString.Append(validMembers[i]); } - validMembersString.Append("'"); + validMembersString.Append('\''); message = StringUtil.Format(Modules.InvalidModuleManifestMember, moduleManifestPath, validMembersString, badKeys); InvalidOperationException ioe = new InvalidOperationException(message); ErrorRecord er = new ErrorRecord(ioe, "Modules_InvalidManifestMember", @@ -644,8 +644,8 @@ private bool ValidateManifestHash( } private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, ModuleSpecification moduleSpecification, string moduleBase, bool searchModulePath, - string prefix, SessionState ss, ImportModuleOptions options, ManifestProcessingFlags manifestProcessingFlags, bool loadTypesFiles, - bool loadFormatFiles, object privateData, out bool found, string shortModuleName, PSLanguageMode? manifestLanguageMode) + string prefix, SessionState ss, ImportModuleOptions options, ManifestProcessingFlags manifestProcessingFlags, bool loadTypes, + bool loadFormats, object privateData, out bool found, string shortModuleName, PSLanguageMode? manifestLanguageMode) { PSModuleInfo module = null; PSModuleInfo tempModuleInfoFromVerification = null; @@ -723,7 +723,7 @@ private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, Module // NestedModules = 'test2' ---> test2 is a directory under current module directory (e.g - Test1) // We also need to look for Test1\Test2\Test2.(psd1/psm1/dll) // With the call above, we are only looking at Test1\Test2.(psd1/psm1/dll) - if (found == false && moduleFileFound == false) + if (!found && !moduleFileFound) { string newRootedPath = Path.Combine(rootedPath, moduleSpecification.Name); string newModuleBase = Path.Combine(moduleBase, moduleSpecification.Name); @@ -764,7 +764,7 @@ private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, Module // Win8: 262157 - Import-Module is giving errors while loading Nested Modules. (This is a V2 bug) // Only look for the file if the file was not found with the previous search - if (found == false && moduleFileFound == false) + if (!found && !moduleFileFound) { string newRootedPath = Path.Combine(rootedPath, moduleSpecification.Name); string newModuleBase = Path.Combine(moduleBase, moduleSpecification.Name); @@ -786,10 +786,10 @@ private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, Module } // The rooted files wasn't found, so don't search anymore... - if (found == false && wasRooted) + if (!found && wasRooted) return null; - if (searchModulePath && found == false && moduleFileFound == false) + if (searchModulePath && !found && !moduleFileFound) { if (VerifyIfNestedModuleIsAvailable(moduleSpecification, null, null, out tempModuleInfoFromVerification)) { @@ -846,7 +846,7 @@ private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, Module // At this point, we haven't found an actual module, so try loading it as a // PSSnapIn and then finally as an assembly in the GAC... - if ((found == false) && (moduleSpecification.Guid == null) && (moduleSpecification.Version == null) && (moduleSpecification.RequiredVersion == null) && (moduleSpecification.MaximumVersion == null)) + if (!found && (moduleSpecification.Guid == null) && (moduleSpecification.Version == null) && (moduleSpecification.RequiredVersion == null) && (moduleSpecification.MaximumVersion == null)) { // If we are in module analysis and the parent module declares non-wildcarded ExportedCmdlets, then we don't need to // actually process the binary module. @@ -878,19 +878,19 @@ private PSModuleInfo LoadModuleNamedInManifest(PSModuleInfo parentModule, Module // At this point, we are already exhaust all possible ways to load the nested module. The last option is to load it as a binary module/snapin. module = LoadBinaryModule( parentModule, - true, // trySnapInName moduleSpecification.Name, - null, // fileName - null, // assemblyToLoad + fileName: null, + assemblyToLoad: null, moduleBase, ss, options, manifestProcessingFlags, prefix, - loadTypesFiles, - loadFormatFiles, + loadTypes, + loadFormats, out found, - shortModuleName, false); + shortModuleName, + disableFormatUpdates: false); } catch (FileNotFoundException) { @@ -1043,7 +1043,7 @@ private IEnumerable GetModuleForRootedPaths(List modulePat } } - private ErrorRecord CreateModuleNotFoundError(string modulePath) + private static ErrorRecord CreateModuleNotFoundError(string modulePath) { string errorMessage = StringUtil.Format(Modules.ModuleNotFoundForGetModule, modulePath); FileNotFoundException fnf = new FileNotFoundException(errorMessage); @@ -1055,35 +1055,27 @@ private IEnumerable GetModuleForNames(List names, bool all { IEnumerable allModules = null; HashSet modulePathSet = new HashSet(StringComparer.OrdinalIgnoreCase); - bool cleanupModuleAnalysisAppDomain = Context.TakeResponsibilityForModuleAnalysisAppDomain(); - try + foreach (string path in ModuleIntrinsics.GetModulePath(false, Context)) { - foreach (string path in ModuleIntrinsics.GetModulePath(false, Context)) - { - string uniquePath = path.TrimEnd(Utils.Separators.Directory); + string uniquePath = path.TrimEnd(Utils.Separators.Directory); - // Ignore repeated module path. - if (!modulePathSet.Add(uniquePath)) { continue; } + // Ignore repeated module path. + if (!modulePathSet.Add(uniquePath)) + { + continue; + } - try - { - IEnumerable modulesFound = GetModulesFromOneModulePath( - names, uniquePath, all, refresh).OrderBy(m => m.Name); - allModules = allModules == null ? modulesFound : allModules.Concat(modulesFound); - } - catch (Exception e) when (e is IOException || e is UnauthorizedAccessException) - { - // ignore directories that can't be accessed - continue; - } + try + { + IEnumerable modulesFound = GetModulesFromOneModulePath( + names, uniquePath, all, refresh).OrderBy(static m => m.Name); + allModules = allModules == null ? modulesFound : allModules.Concat(modulesFound); } - } - finally - { - if (cleanupModuleAnalysisAppDomain) + catch (Exception e) when (e is IOException || e is UnauthorizedAccessException) { - Context.ReleaseResponsibilityForModuleAnalysisAppDomain(); + // ignore directories that can't be accessed + continue; } } @@ -1140,12 +1132,12 @@ internal static Version GetMaximumVersion(string stringVersion) else { // If first conversion fails, try to convert * to maximum version - string maxRange = "999999999"; + const string maxRange = "999999999"; if (stringVersion[stringVersion.Length - 1] == '*') { stringVersion = stringVersion.Substring(0, stringVersion.Length - 1); - stringVersion = stringVersion + maxRange; - int starNum = stringVersion.Count(x => x == '.'); + stringVersion += maxRange; + int starNum = stringVersion.Count(static x => x == '.'); for (int i = 0; i < (3 - starNum); i++) { stringVersion = stringVersion + '.' + maxRange; @@ -1421,7 +1413,7 @@ private IEnumerable CreateFakeModuleObject(IEnumerable exportedTypeFiles; - if ( - !GetListOfFilesFromData(data, moduleManifestPath, "TypesToProcess", manifestProcessingFlags, moduleBase, - ".ps1xml", true, out exportedTypeFiles)) + if (!GetListOfFilesFromData( + data, + moduleManifestPath, + key: "TypesToProcess", + manifestProcessingFlags, + moduleBase, + extension: ".ps1xml", + verifyFilesExist: true, + out List exportedTypeFiles)) { containedErrors = true; if (bailOnFirstError) return null; @@ -2234,10 +2231,15 @@ internal PSModuleInfo LoadModuleManifest( } // Set up to load any format files that have been specified... - List exportedFormatFiles; - if ( - !GetListOfFilesFromData(data, moduleManifestPath, "FormatsToProcess", manifestProcessingFlags, - moduleBase, ".ps1xml", true, out exportedFormatFiles)) + if (!GetListOfFilesFromData( + data, + moduleManifestPath, + key: "FormatsToProcess", + manifestProcessingFlags, + moduleBase, + extension: ".ps1xml", + verifyFilesExist: true, + out List exportedFormatFiles)) { containedErrors = true; if (bailOnFirstError) return null; @@ -2276,10 +2278,15 @@ internal PSModuleInfo LoadModuleManifest( } // scripts to process - List scriptsToProcess; - if ( - !GetListOfFilesFromData(data, moduleManifestPath, "ScriptsToProcess", manifestProcessingFlags, - moduleBase, ".ps1", true, out scriptsToProcess)) + if (!GetListOfFilesFromData( + data, + moduleManifestPath, + key: "ScriptsToProcess", + manifestProcessingFlags, + moduleBase, + extension: ".ps1", + verifyFilesExist: true, + out List scriptsToProcess)) { containedErrors = true; if (bailOnFirstError) return null; @@ -2323,13 +2330,16 @@ internal PSModuleInfo LoadModuleManifest( } // Process "FileList" - List fileList; - if ( - !GetListOfFilesFromData(data, moduleManifestPath, "FileList", manifestProcessingFlags, moduleBase, "" - /*extension*/, - false - /* don't check file existence - don't want to change current behavior without feature team discussion */, - out fileList)) + if (!GetListOfFilesFromData( + data, + moduleManifestPath, + key: "FileList", + manifestProcessingFlags, + moduleBase, + extension: string.Empty, + // Don't check file existence - don't want to change current behavior without feature team discussion. + verifyFilesExist: false, + out List fileList)) { containedErrors = true; if (bailOnFirstError) return null; @@ -2927,8 +2937,8 @@ internal PSModuleInfo LoadModuleManifest( ss: null, options: nestedModuleOptions, manifestProcessingFlags: manifestProcessingFlags, - loadTypesFiles: true, - loadFormatFiles: true, + loadTypes: true, + loadFormats: true, privateData: privateData, found: out found, shortModuleName: null, @@ -3030,8 +3040,8 @@ internal PSModuleInfo LoadModuleManifest( ss: ss, options: options, manifestProcessingFlags: manifestProcessingFlags, - loadTypesFiles: (exportedTypeFiles == null || 0 == exportedTypeFiles.Count), // If types files already loaded, don't load snapin files - loadFormatFiles: (exportedFormatFiles == null || 0 == exportedFormatFiles.Count), // if format files already loaded, don't load snapin files + loadTypes: (exportedTypeFiles == null || exportedTypeFiles.Count == 0), // If types files already loaded, don't load snapin files + loadFormats: (exportedFormatFiles == null || exportedFormatFiles.Count == 0), // if format files already loaded, don't load snapin files privateData: privateData, found: out found, shortModuleName: null, @@ -3213,7 +3223,7 @@ internal PSModuleInfo LoadModuleManifest( newManifestInfo.Prefix = resolvedCommandPrefix; } - if (newManifestInfo.FileList == null || newManifestInfo.FileList.LongCount() == 0) + if (newManifestInfo.FileList == null || !newManifestInfo.FileList.Any()) { if (fileList != null) { @@ -3224,7 +3234,7 @@ internal PSModuleInfo LoadModuleManifest( } } - if (newManifestInfo.ModuleList == null || newManifestInfo.ModuleList.LongCount() == 0) + if (newManifestInfo.ModuleList == null || !newManifestInfo.ModuleList.Any()) { if (moduleList != null) { @@ -3235,7 +3245,7 @@ internal PSModuleInfo LoadModuleManifest( } } - if (newManifestInfo.CompatiblePSEditions == null || newManifestInfo.CompatiblePSEditions.LongCount() == 0) + if (newManifestInfo.CompatiblePSEditions == null || !newManifestInfo.CompatiblePSEditions.Any()) { if (compatiblePSEditions != null) { @@ -3248,7 +3258,7 @@ internal PSModuleInfo LoadModuleManifest( newManifestInfo.ProcessorArchitecture = requiredProcessorArchitecture; } - if (newManifestInfo.RequiredAssemblies == null || newManifestInfo.RequiredAssemblies.LongCount() == 0) + if (newManifestInfo.RequiredAssemblies == null || !newManifestInfo.RequiredAssemblies.Any()) { if (assemblyList != null) { @@ -3259,7 +3269,7 @@ internal PSModuleInfo LoadModuleManifest( } } - if (newManifestInfo.Scripts == null || newManifestInfo.Scripts.LongCount() == 0) + if (newManifestInfo.Scripts == null || !newManifestInfo.Scripts.Any()) { if (scriptsToProcess != null) { @@ -3531,7 +3541,7 @@ private static void PropagateExportedTypesFromNestedModulesToRootModuleScope(Imp if (nestedModule != null) { var exportedTypes = nestedModule.GetExportedTypeDefinitions(); - if (exportedTypes != null && exportedTypes.Count != 0) + if (exportedTypes != null && exportedTypes.Count > 0) { foreach (var t in exportedTypes) { @@ -3646,7 +3656,7 @@ private static void WriteInvalidManifestMemberError( Exception e, ManifestProcessingFlags manifestProcessingFlags) { - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors)) + if ((manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0) { ErrorRecord er = GenerateInvalidModuleMemberErrorRecord(manifestElement, moduleManifestPath, e); cmdlet.WriteError(er); @@ -3750,7 +3760,7 @@ internal static PSModuleInfo LoadRequiredModule(ExecutionContext context, ManifestProcessingFlags manifestProcessingFlags, out ErrorRecord error) { - Dbg.Assert(0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements), "LoadRequiredModule / RequiredModules checks should only be done when actually loading a module"); + Dbg.Assert((manifestProcessingFlags & ManifestProcessingFlags.LoadElements) != 0, "LoadRequiredModule / RequiredModules checks should only be done when actually loading a module"); error = null; @@ -3817,7 +3827,7 @@ internal static PSModuleInfo LoadRequiredModule(ExecutionContext context, string message; if (moduleManifestPath != null) { - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors)) + if ((manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0) { switch (loadFailureReason) { @@ -4203,7 +4213,7 @@ private static bool HasRequiredModulesCyclicReference(ModuleSpecification curren /// Search for a localized psd1 manifest file, using the same algorithm /// as Import-LocalizedData. /// - private ExternalScriptInfo FindLocalizedModuleManifest(string path) + private static ExternalScriptInfo FindLocalizedModuleManifest(string path) { string dir = Path.GetDirectoryName(path); string file = Path.GetFileName(path); @@ -4214,9 +4224,9 @@ private ExternalScriptInfo FindLocalizedModuleManifest(string path) while (currentCulture != null && !string.IsNullOrEmpty(currentCulture.Name)) { StringBuilder stringBuilder = new StringBuilder(dir); - stringBuilder.Append("\\"); + stringBuilder.Append('\\'); stringBuilder.Append(currentCulture.Name); - stringBuilder.Append("\\"); + stringBuilder.Append('\\'); stringBuilder.Append(file); string filePath = stringBuilder.ToString(); @@ -4242,7 +4252,7 @@ private ExternalScriptInfo FindLocalizedModuleManifest(string path) /// /// Checks to see if the module manifest contains the specified key. /// If it does and it's valid, it returns true otherwise it returns false. - /// If the key wasn't there or wasn't valid, then is set to null + /// If the key wasn't there or wasn't valid, then is set to /// /// The hashtable to look for the key in. /// The manifest that generated the hashtable. @@ -4281,7 +4291,7 @@ internal bool GetListOfStringsFromData( /// /// Checks to see if the module manifest contains the specified key. /// If it does and it's valid, it returns true otherwise it returns false. - /// If the key wasn't there or wasn't valid, then is set to null. + /// If the key wasn't there or wasn't valid, then is set to . /// /// The hashtable to look for the key in. /// The manifest that generated the hashtable. @@ -4334,7 +4344,7 @@ private bool GetListOfWildcardsFromData( /// /// Checks to see if the module manifest contains the specified key. /// If it does and it's valid, it returns true otherwise it returns false. - /// If the key wasn't there or wasn't valid, then is set to null + /// If the key wasn't there or wasn't valid, then is set to /// /// The hashtable to look for the key in. /// The manifest that generated the hashtable. @@ -4342,7 +4352,7 @@ private bool GetListOfWildcardsFromData( /// Specifies how to treat errors and whether to load elements. /// Base directory of a module. /// Expected file extension (added to strings that didn't have an extension). - /// If true then we want to error out if the specified files don't exist. + /// If then we want to error out if the specified files don't exist. /// Returns the extracted version. /// private bool GetListOfFilesFromData( @@ -4435,7 +4445,7 @@ internal void SetModuleLoggingInformation(PSModuleInfo m) } } - private void SetModuleLoggingInformation(ModuleLoggingGroupPolicyStatus status, PSModuleInfo m, IEnumerable moduleNames) + private static void SetModuleLoggingInformation(ModuleLoggingGroupPolicyStatus status, PSModuleInfo m, IEnumerable moduleNames) { // TODO, insivara : What happens when Enabled but none of the other options (DefaultSystemModules, NonDefaultSystemModule, NonSystemModule, SpecificModules) are set? // After input from GP team for this behavior, need to revisit the commented out part @@ -4489,16 +4499,16 @@ internal static ModuleLoggingGroupPolicyStatus GetModuleLoggingInformation(out I /// /// Checks to see if the module manifest contains the specified key. - /// If it does and it can be converted to the expected type, then it returns true and sets to the value. - /// If the key is missing it returns true and sets to default(). - /// If the key is invalid then it returns false. + /// If it does and it can be converted to the expected type, then it returns and sets to the value. + /// If the key is missing it returns and sets to default(). + /// If the key is invalid then it returns . /// /// The hashtable to look for the key in. /// The manifest that generated the hashtable. /// The table key to use. /// Specifies how to treat errors and whether to load elements. /// Value from the manifest converted to the right type. - /// true if success; false if there were errors. + /// if success; if there were errors. internal bool GetScalarFromData( Hashtable data, string moduleManifestPath, @@ -4521,7 +4531,7 @@ internal bool GetScalarFromData( catch (PSInvalidCastException e) { result = default(T); - if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors)) + if ((manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0) { string message = StringUtil.Format(Modules.ModuleManifestInvalidValue, key, e.Message, moduleManifestPath); ArgumentException newAe = new ArgumentException(message); @@ -4956,7 +4966,7 @@ internal void RemoveModule(PSModuleInfo module, string moduleNameInRemoveModuleC args: new object[] { module }); } - if (module.ImplementingAssembly != null && module.ImplementingAssembly.IsDynamic == false) + if (module.ImplementingAssembly != null && !module.ImplementingAssembly.IsDynamic) { var exportedTypes = PSSnapInHelpers.GetAssemblyTypes(module.ImplementingAssembly, module.Name); foreach (var type in exportedTypes) @@ -5167,21 +5177,6 @@ internal void RemoveModule(PSModuleInfo module, string moduleNameInRemoveModuleC // And the appdomain level module path cache. PSModuleInfo.RemoveFromAppDomainLevelCache(module.Name); - - // Update implicit module loaded property - if (Context.Modules.IsImplicitRemotingModuleLoaded) - { - Context.Modules.IsImplicitRemotingModuleLoaded = false; - foreach (var modInfo in Context.Modules.ModuleTable.Values) - { - var privateData = modInfo.PrivateData as Hashtable; - if ((privateData != null) && privateData.ContainsKey("ImplicitRemoting")) - { - Context.Modules.IsImplicitRemotingModuleLoaded = true; - break; - } - } - } } } } @@ -5230,7 +5225,7 @@ internal bool DoesAlreadyLoadedModuleSatisfyConstraints(PSModuleInfo alreadyLoad /// /// /// Returns PSModuleInfo of an already loaded module if that module can be simply reimported and there is no need to proceed with a regular import. - /// Returns null if the caller should proceed with a regular import (either because there is no previously loaded module, or because the -Force flag was specified and the previously loaded module has been removed by this method). + /// Returns if the caller should proceed with a regular import (either because there is no previously loaded module, or because the -Force flag was specified and the previously loaded module has been removed by this method). /// internal PSModuleInfo IsModuleImportUnnecessaryBecauseModuleIsAlreadyLoaded(string modulePath, string prefix, ImportModuleOptions options) { @@ -5349,7 +5344,7 @@ internal PSModuleInfo LoadUsingExtensions(PSModuleInfo parentModule, else extensions = ModuleIntrinsics.PSModuleExtensions; - var importingModule = 0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements); + var importingModule = (manifestProcessingFlags & ManifestProcessingFlags.LoadElements) != 0; // "ni.dll" has a higher priority then ".dll" to be loaded. for (int i = 0; i < extensions.Length; i++) @@ -5556,8 +5551,8 @@ internal PSModuleInfo LoadModule(PSModuleInfo parentModule, string fileName, str return null; } - var importingModule = 0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements); - var writingErrors = 0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors); + var importingModule = (manifestProcessingFlags & ManifestProcessingFlags.LoadElements) != 0; + var writingErrors = (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors) != 0; // In case the file is a Ngen Assembly. string ext; @@ -5872,8 +5867,19 @@ internal PSModuleInfo LoadModule(PSModuleInfo parentModule, string fileName, str ext.Equals(StringLiterals.PowerShellNgenAssemblyExtension, StringComparison.OrdinalIgnoreCase) || ext.Equals(StringLiterals.PowerShellILExecutableExtension, StringComparison.OrdinalIgnoreCase)) { - module = LoadBinaryModule(false, ModuleIntrinsics.GetModuleName(fileName), fileName, null, - moduleBase, ss, options, manifestProcessingFlags, prefix, true, true, out found); + module = LoadBinaryModule( + ModuleIntrinsics.GetModuleName(fileName), + fileName, + assemblyToLoad: null, + moduleBase, + ss, + options, + manifestProcessingFlags, + prefix, + loadTypes: true, + loadFormats: true, + out found); + if (found && module != null) { // LanguageMode does not apply to binary modules @@ -6071,9 +6077,9 @@ private static bool ShouldProcessScriptModule(PSModuleInfo parentModule, ref boo return shouldProcessModule; } - private static object s_lockObject = new object(); + private static readonly object s_lockObject = new object(); - private void ClearAnalysisCaches() + private static void ClearAnalysisCaches() { lock (s_lockObject) { @@ -6083,10 +6089,9 @@ private void ClearAnalysisCaches() } // Analyzes a binary module implementation for its cmdlets. - private static Dictionary> s_binaryAnalysisCache = + private static readonly Dictionary> s_binaryAnalysisCache = new Dictionary>(); -#if CORECLR /// /// Analyze the module assembly to find out all cmdlets and aliases defined in that assembly. /// @@ -6126,158 +6131,9 @@ private static BinaryAnalysisResult GetCmdletsFromBinaryModuleImplementation(str return resultToReturn; } -#else - /// - /// Analyze the module assembly to find out all cmdlets and aliases defined in that assembly. - /// - private BinaryAnalysisResult GetCmdletsFromBinaryModuleImplementation(string path, ManifestProcessingFlags manifestProcessingFlags, out Version assemblyVersion) - { - Tuple tuple = null; - - lock (s_lockObject) - { - s_binaryAnalysisCache.TryGetValue(path, out tuple); - } - - if (tuple != null) - { - assemblyVersion = tuple.Item2; - return tuple.Item1; - } - - assemblyVersion = new Version("0.0.0.0"); - - bool cleanupModuleAnalysisAppDomain = false; - AppDomain tempDomain = Context.AppDomainForModuleAnalysis; - if (tempDomain == null) - { - cleanupModuleAnalysisAppDomain = Context.TakeResponsibilityForModuleAnalysisAppDomain(); - tempDomain = Context.AppDomainForModuleAnalysis = AppDomain.CreateDomain("ReflectionDomain"); - } - - try - { - // create temp appdomain if one is not passed in - tempDomain.SetData("PathToProcess", path); - tempDomain.SetData("IsModuleLoad", 0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements)); - - // reset DetectedCmdlets and AssemblyVersion from previous invocation - tempDomain.SetData("DetectedCmdlets", null); - tempDomain.SetData("DetectedAliases", null); - tempDomain.SetData("AssemblyVersion", assemblyVersion); - - tempDomain.DoCallBack(AnalyzeSnapinDomainHelper); - List detectedCmdlets = (List)tempDomain.GetData("DetectedCmdlets"); - List> detectedAliases = (List>)tempDomain.GetData("DetectedAliases"); - assemblyVersion = (Version)tempDomain.GetData("AssemblyVersion"); - - if ((detectedCmdlets.Count == 0) && (System.IO.Path.IsPathRooted(path))) - { - // If we couldn't load it from a file, try loading from the GAC - string assemblyname = Path.GetFileName(path); - BinaryAnalysisResult gacResult = GetCmdletsFromBinaryModuleImplementation(assemblyname, manifestProcessingFlags, out assemblyVersion); - detectedCmdlets = gacResult.DetectedCmdlets; - detectedAliases = gacResult.DetectedAliases; - } - - BinaryAnalysisResult result = new BinaryAnalysisResult(); - result.DetectedCmdlets = detectedCmdlets; - result.DetectedAliases = detectedAliases; - - lock (s_lockObject) - { - s_binaryAnalysisCache[path] = Tuple.Create(result, assemblyVersion); - } - - return result; - } - finally - { - if (cleanupModuleAnalysisAppDomain) - { - Context.ReleaseResponsibilityForModuleAnalysisAppDomain(); - } - } - } - - private static void AnalyzeSnapinDomainHelper() - { - string path = (string)AppDomain.CurrentDomain.GetData("PathToProcess"); - bool isModuleLoad = (bool)AppDomain.CurrentDomain.GetData("IsModuleLoad"); - Dictionary cmdlets = null; - Dictionary> aliases = null; - Dictionary providers = null; - string throwAwayHelpFile = null; - Version assemblyVersion = new Version("0.0.0.0"); - - try - { - Assembly assembly = null; - - try - { - // If this is a fully-qualified search, load it from the file - if (Path.IsPathRooted(path)) - { - assembly = InitialSessionState.LoadAssemblyFromFile(path); - } - else - { - // Otherwise, load it from the GAC - Exception ignored = null; - assembly = ExecutionContext.LoadAssembly(path, null, out ignored); - } - - if (assembly != null) - { - assemblyVersion = GetAssemblyVersionNumber(assembly); - } - } - // Catch-all OK, analyzing user code. - catch (Exception) - { - } - - if (assembly != null) - { - PSSnapInHelpers.AnalyzePSSnapInAssembly(assembly, assembly.Location, null, null, isModuleLoad, out cmdlets, out aliases, out providers, out throwAwayHelpFile); - } - } - // Catch-all OK, analyzing user code. - catch (Exception) - { - } - - List detectedCmdlets = new List(); - List> detectedAliases = new List>(); - - if (cmdlets != null) - { - foreach (SessionStateCmdletEntry cmdlet in cmdlets.Values) - { - detectedCmdlets.Add(cmdlet.Name); - } - } - - if (aliases != null) - { - foreach (List aliasList in aliases.Values) - { - foreach (SessionStateAliasEntry alias in aliasList) - { - detectedAliases.Add(new Tuple(alias.Name, alias.Definition)); - } - } - } - - AppDomain.CurrentDomain.SetData("DetectedCmdlets", detectedCmdlets); - AppDomain.CurrentDomain.SetData("DetectedAliases", detectedAliases); - AppDomain.CurrentDomain.SetData("AssemblyVersion", assemblyVersion); - } -#endif // Analyzes a script module implementation for its exports. - private static Dictionary s_scriptAnalysisCache = new Dictionary(); + private static readonly Dictionary s_scriptAnalysisCache = new Dictionary(); private PSModuleInfo AnalyzeScriptFile(string filename, bool force, ExecutionContext context) { @@ -6385,7 +6241,7 @@ private PSModuleInfo AnalyzeScriptFile(string filename, bool force, ExecutionCon try { - foreach (string item in System.IO.Directory.GetFiles(baseDirectory, "*.ps1")) + foreach (string item in System.IO.Directory.EnumerateFiles(baseDirectory, "*.ps1")) { module.AddDetectedFunctionExport(Path.GetFileNameWithoutExtension(item)); } @@ -6493,7 +6349,6 @@ private PSModuleInfo AnalyzeScriptFile(string filename, bool force, ExecutionCon /// /// Load a binary module. A binary module is an assembly that should contain cmdlets. /// - /// If true, then the registered snapins will also be searched when loading. /// The name of the snapin or assembly to load. /// The path to the assembly to load. /// The assembly to load so no lookup need be done. @@ -6510,20 +6365,40 @@ private PSModuleInfo AnalyzeScriptFile(string filename, bool force, ExecutionCon /// Command name prefix. /// Sets this to true if an assembly was found. /// THe module info object that was created... - internal PSModuleInfo LoadBinaryModule(bool trySnapInName, string moduleName, string fileName, - Assembly assemblyToLoad, string moduleBase, SessionState ss, ImportModuleOptions options, - ManifestProcessingFlags manifestProcessingFlags, string prefix, - bool loadTypes, bool loadFormats, out bool found) + internal PSModuleInfo LoadBinaryModule( + string moduleName, + string fileName, + Assembly assemblyToLoad, + string moduleBase, + SessionState ss, + ImportModuleOptions options, + ManifestProcessingFlags manifestProcessingFlags, + string prefix, + bool loadTypes, + bool loadFormats, + out bool found) { - return LoadBinaryModule(null, trySnapInName, moduleName, fileName, assemblyToLoad, moduleBase, ss, options, - manifestProcessingFlags, prefix, loadTypes, loadFormats, out found, null, false); + return LoadBinaryModule( + parentModule: null, + moduleName, + fileName, + assemblyToLoad, + moduleBase, + ss, + options, + manifestProcessingFlags, + prefix, + loadTypes, + loadFormats, + out found, + shortModuleName: null, + disableFormatUpdates: false); } /// /// Load a binary module. A binary module is an assembly that should contain cmdlets. /// /// The parent module for which this module is a nested module. - /// If true, then the registered snapins will also be searched when loading. /// The name of the snapin or assembly to load. /// The path to the assembly to load. /// The assembly to load so no lookup need be done. @@ -6542,7 +6417,21 @@ internal PSModuleInfo LoadBinaryModule(bool trySnapInName, string moduleName, st /// Short name for module. /// /// THe module info object that was created... - internal PSModuleInfo LoadBinaryModule(PSModuleInfo parentModule, bool trySnapInName, string moduleName, string fileName, Assembly assemblyToLoad, string moduleBase, SessionState ss, ImportModuleOptions options, ManifestProcessingFlags manifestProcessingFlags, string prefix, bool loadTypes, bool loadFormats, out bool found, string shortModuleName, bool disableFormatUpdates) + internal PSModuleInfo LoadBinaryModule( + PSModuleInfo parentModule, + string moduleName, + string fileName, + Assembly assemblyToLoad, + string moduleBase, + SessionState ss, + ImportModuleOptions options, + ManifestProcessingFlags manifestProcessingFlags, + string prefix, + bool loadTypes, + bool loadFormats, + out bool found, + string shortModuleName, + bool disableFormatUpdates) { PSModuleInfo module = null; @@ -6555,10 +6444,9 @@ internal PSModuleInfo LoadBinaryModule(PSModuleInfo parentModule, bool trySnapIn List> detectedAliases = null; Assembly assembly = null; Exception error = null; - bool importSuccessful = false; string modulePath = string.Empty; Version assemblyVersion = new Version(0, 0, 0, 0); - var importingModule = 0 != (manifestProcessingFlags & ManifestProcessingFlags.LoadElements); + var importingModule = (manifestProcessingFlags & ManifestProcessingFlags.LoadElements) != 0; // See if we're loading a straight assembly... if (assemblyToLoad != null) @@ -6606,114 +6494,50 @@ internal PSModuleInfo LoadBinaryModule(PSModuleInfo parentModule, bool trySnapIn } } } - else + else if (importingModule) { - // Avoid trying to import a PowerShell assembly as Snapin as it results in PSArgumentException - if ((moduleName != null) && Utils.IsPowerShellAssembly(moduleName)) - { - trySnapInName = false; - } + assembly = Context.AddAssembly(moduleName, fileName, out error); - if (trySnapInName && PSSnapInInfo.IsPSSnapinIdValid(moduleName)) + if (assembly == null) { - PSSnapInInfo snapin = null; - -#if !CORECLR - // Avoid trying to load SnapIns with Import-Module - PSSnapInException warning; - try - { - if (importingModule) - { - snapin = iss.ImportPSSnapIn(moduleName, out warning); - } - } - catch (PSArgumentException) - { - // BUGBUG - brucepay - probably want to have a verbose message here... - } -#endif - - if (snapin != null) - { - importSuccessful = true; - if (string.IsNullOrEmpty(fileName)) - modulePath = snapin.AbsoluteModulePath; - else - modulePath = fileName; - assemblyVersion = snapin.Version; - // If we're not supposed to load the types files from the snapin - // clear the iss member - if (!loadTypes) - { - iss.Types.Reset(); - } - // If we're not supposed to load the format files from the snapin, - // clear the iss member - if (!loadFormats) - { - iss.Formats.Reset(); - } + if (error != null) + throw error; - foreach (var a in ClrFacade.GetAssemblies()) - { - if (a.GetName().FullName.Equals(snapin.AssemblyName, StringComparison.Ordinal)) - { - assembly = a; - break; - } - } - } + found = false; + return null; } - if (importSuccessful == false) - { - if (importingModule) - { - assembly = Context.AddAssembly(moduleName, fileName, out error); + assemblyVersion = GetAssemblyVersionNumber(assembly); - if (assembly == null) - { - if (error != null) - throw error; - - found = false; - return null; - } - - assemblyVersion = GetAssemblyVersionNumber(assembly); - - if (string.IsNullOrEmpty(fileName)) - modulePath = assembly.Location; - else - modulePath = fileName; - - // Passing module as a parameter here so that the providers can have the module property populated. - // For engine providers, the module should point to top-level module name - // For FileSystem, the module is Microsoft.PowerShell.Core and not System.Management.Automation - if (parentModule != null && InitialSessionState.IsEngineModule(parentModule.Name)) - { - iss.ImportCmdletsFromAssembly(assembly, parentModule); - } - else - { - iss.ImportCmdletsFromAssembly(assembly, null); - } - } - else - { - string binaryPath = fileName; - modulePath = fileName; - if (binaryPath == null) - { - binaryPath = System.IO.Path.Combine(moduleBase, moduleName); - } + if (string.IsNullOrEmpty(fileName)) + modulePath = assembly.Location; + else + modulePath = fileName; - BinaryAnalysisResult analysisResult = GetCmdletsFromBinaryModuleImplementation(binaryPath, manifestProcessingFlags, out assemblyVersion); - detectedCmdlets = analysisResult.DetectedCmdlets; - detectedAliases = analysisResult.DetectedAliases; - } + // Passing module as a parameter here so that the providers can have the module property populated. + // For engine providers, the module should point to top-level module name + // For FileSystem, the module is Microsoft.PowerShell.Core and not System.Management.Automation + if (parentModule != null && InitialSessionState.IsEngineModule(parentModule.Name)) + { + iss.ImportCmdletsFromAssembly(assembly, parentModule); } + else + { + iss.ImportCmdletsFromAssembly(assembly, null); + } + } + else + { + string binaryPath = fileName; + modulePath = fileName; + if (binaryPath == null) + { + binaryPath = System.IO.Path.Combine(moduleBase, moduleName); + } + + BinaryAnalysisResult analysisResult = GetCmdletsFromBinaryModuleImplementation(binaryPath, manifestProcessingFlags, out assemblyVersion); + detectedCmdlets = analysisResult.DetectedCmdlets; + detectedAliases = analysisResult.DetectedAliases; } found = true; @@ -6882,7 +6706,7 @@ internal PSModuleInfo LoadBinaryModule(PSModuleInfo parentModule, bool trySnapIn iss.Bind(Context, updateOnly: true, module, options.NoClobber, options.Local, setLocation: false); // Scan all of the types in the assembly to register JobSourceAdapters. - IEnumerable allTypes = new Type[] { }; + IEnumerable allTypes = Array.Empty(); if (assembly != null) { allTypes = assembly.ExportedTypes; @@ -7085,13 +6909,6 @@ internal static void AddModuleToModuleTables(ExecutionContext context, SessionSt { targetSessionState.Module.AddNestedModule(module); } - - var privateDataHashTable = module.PrivateData as Hashtable; - if (context.Modules.IsImplicitRemotingModuleLoaded == false && - privateDataHashTable != null && privateDataHashTable.ContainsKey("ImplicitRemoting")) - { - context.Modules.IsImplicitRemotingModuleLoaded = true; - } } /// diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index b20e11e4745..1d8fe6bc8b5 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -54,15 +54,6 @@ internal ModuleIntrinsics(ExecutionContext context) private const int MaxModuleNestingDepth = 10; - /// - /// Gets and sets boolean that indicates when an implicit remoting module is loaded. - /// - internal bool IsImplicitRemotingModuleLoaded - { - get; - set; - } - internal void IncrementModuleNestingDepth(PSCmdlet cmdlet, string path) { if (++ModuleNestingDepth > MaxModuleNestingDepth) @@ -358,7 +349,7 @@ private List GetModuleCore(string[] patterns, bool all, bool exact } } - return modulesMatched.OrderBy(m => m.Name).ToList(); + return modulesMatched.OrderBy(static m => m.Name).ToList(); } internal List GetModules(ModuleSpecification[] fullyQualifiedName, bool all) @@ -417,7 +408,7 @@ internal List GetModules(ModuleSpecification[] fullyQualifiedName, } } - return modulesMatched.OrderBy(m => m.Name).ToList(); + return modulesMatched.OrderBy(static m => m.Name).ToList(); } /// @@ -703,9 +694,9 @@ internal static bool MatchesModulePath(string modulePath, string requiredPath) } #if UNIX - StringComparison strcmp = StringComparison.Ordinal; + const StringComparison strcmp = StringComparison.Ordinal; #else - StringComparison strcmp = StringComparison.OrdinalIgnoreCase; + const StringComparison strcmp = StringComparison.OrdinalIgnoreCase; #endif // We must check modulePath (e.g. /path/to/module/module.psd1) against several possibilities: @@ -1014,7 +1005,7 @@ internal static string GetPSHomeModulePath() /// It's known as "Program Files" module path in windows powershell. /// /// - private static string GetSharedModulePath() + internal static string GetSharedModulePath() { #if UNIX return Platform.SelectProductNameForDirectory(Platform.XDG_Type.SHARED_MODULES); @@ -1432,25 +1423,16 @@ internal static void RemoveNestedModuleFunctions(PSModuleInfo module) if ((input == null) || (input.Count == 0)) { return; } - List output = new List(input.Count); - foreach (var fnInfo in input) - { - if (module.Name.Equals(fnInfo.ModuleName, StringComparison.OrdinalIgnoreCase)) - { - output.Add(fnInfo); - } - } - - input.Clear(); - input.AddRange(output); + input.RemoveAll(fnInfo => !module.Name.Equals(fnInfo.ModuleName, StringComparison.OrdinalIgnoreCase)); } +#nullable enable private static void SortAndRemoveDuplicates(List input, Func keyGetter) { - Dbg.Assert(input != null, "Caller should verify that input != null"); + Dbg.Assert(input is not null, "Caller should verify that input != null"); input.Sort( - delegate (T x, T y) + (T x, T y) => { string kx = keyGetter(x); string ky = keyGetter(y); @@ -1458,24 +1440,19 @@ private static void SortAndRemoveDuplicates(List input, Func ke } ); - bool firstItem = true; - string previousKey = null; - List output = new List(input.Count); - foreach (T item in input) + string? previousKey = null; + input.RemoveAll(ShouldRemove); + + bool ShouldRemove(T item) { string currentKey = keyGetter(item); - if ((firstItem) || !currentKey.Equals(previousKey, StringComparison.OrdinalIgnoreCase)) - { - output.Add(item); - } - + bool match = previousKey is not null + && currentKey.Equals(previousKey, StringComparison.OrdinalIgnoreCase); previousKey = currentKey; - firstItem = false; + return match; } - - input.Clear(); - input.AddRange(output); } +#nullable restore /// /// Mark stuff to be exported from the current environment using the various patterns. @@ -1527,7 +1504,7 @@ internal static void ExportModuleMembers( } } - SortAndRemoveDuplicates(sessionState.ExportedFunctions, delegate (FunctionInfo ci) { return ci.Name; }); + SortAndRemoveDuplicates(sessionState.ExportedFunctions, static (FunctionInfo ci) => ci.Name); } if (cmdletPatterns != null) @@ -1582,7 +1559,7 @@ internal static void ExportModuleMembers( } } - SortAndRemoveDuplicates(sessionState.Module.CompiledExports, delegate (CmdletInfo ci) { return ci.Name; }); + SortAndRemoveDuplicates(sessionState.Module.CompiledExports, static (CmdletInfo ci) => ci.Name); } if (variablePatterns != null) @@ -1605,7 +1582,7 @@ internal static void ExportModuleMembers( } } - SortAndRemoveDuplicates(sessionState.ExportedVariables, delegate (PSVariable v) { return v.Name; }); + SortAndRemoveDuplicates(sessionState.ExportedVariables, static (PSVariable v) => v.Name); } if (aliasPatterns != null) @@ -1645,7 +1622,7 @@ internal static void ExportModuleMembers( } } - SortAndRemoveDuplicates(sessionState.ExportedAliases, delegate (AliasInfo ci) { return ci.Name; }); + SortAndRemoveDuplicates(sessionState.ExportedAliases, static (AliasInfo ci) => ci.Name); } } @@ -1715,10 +1692,12 @@ internal enum ModuleMatchFailure NullModuleSpecification, } +#nullable enable /// /// Used by Modules/Snapins to provide a hook to the engine for startup initialization /// w.r.t compiled assembly loading. /// +#nullable enable public interface IModuleAssemblyInitializer { /// diff --git a/src/System.Management.Automation/engine/Modules/ModuleSpecification.cs b/src/System.Management.Automation/engine/Modules/ModuleSpecification.cs index 5333e364502..315cf3aaf64 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleSpecification.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleSpecification.cs @@ -123,9 +123,9 @@ internal static Exception ModuleSpecificationInitHelper(ModuleSpecification modu badKeys.Append(", "); } - badKeys.Append("'"); + badKeys.Append('\''); badKeys.Append(entry.Key.ToString()); - badKeys.Append("'"); + badKeys.Append('\''); } } } @@ -197,7 +197,7 @@ public override string ToString() var moduleSpecBuilder = new StringBuilder(); - moduleSpecBuilder.Append("@{ ModuleName = '").Append(Name).Append("'"); + moduleSpecBuilder.Append("@{ ModuleName = '").Append(Name).Append('\''); if (Guid != null) { @@ -206,18 +206,18 @@ public override string ToString() if (RequiredVersion != null) { - moduleSpecBuilder.Append("; RequiredVersion = '").Append(RequiredVersion).Append("'"); + moduleSpecBuilder.Append("; RequiredVersion = '").Append(RequiredVersion).Append('\''); } else { if (Version != null) { - moduleSpecBuilder.Append("; ModuleVersion = '").Append(Version).Append("'"); + moduleSpecBuilder.Append("; ModuleVersion = '").Append(Version).Append('\''); } if (MaximumVersion != null) { - moduleSpecBuilder.Append("; MaximumVersion = '").Append(MaximumVersion).Append("'"); + moduleSpecBuilder.Append("; MaximumVersion = '").Append(MaximumVersion).Append('\''); } } diff --git a/src/System.Management.Automation/engine/Modules/ModuleUtils.cs b/src/System.Management.Automation/engine/Modules/ModuleUtils.cs index b825a54fbab..26d3174ca3b 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleUtils.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleUtils.cs @@ -81,8 +81,7 @@ internal static IEnumerable GetAllAvailableModuleFiles(string topDirecto string directoryToCheck = directoriesToCheck.Dequeue(); try { - string[] subDirectories = Directory.GetDirectories(directoryToCheck, "*", options); - foreach (string toAdd in subDirectories) + foreach (string toAdd in Directory.EnumerateDirectories(directoryToCheck, "*", options)) { if (firstSubDirs || !IsPossibleResourceDirectory(toAdd)) { @@ -94,8 +93,7 @@ internal static IEnumerable GetAllAvailableModuleFiles(string topDirecto catch (UnauthorizedAccessException) { } firstSubDirs = false; - string[] files = Directory.GetFiles(directoryToCheck, "*", options); - foreach (string moduleFile in files) + foreach (string moduleFile in Directory.EnumerateFiles(directoryToCheck, "*", options)) { foreach (string ext in ModuleIntrinsics.PSModuleExtensions) { @@ -332,14 +330,14 @@ internal static List GetModuleVersionSubfolders(string moduleBase) if (!string.IsNullOrWhiteSpace(moduleBase) && Directory.Exists(moduleBase)) { var options = Utils.PathIsUnc(moduleBase) ? s_uncPathEnumerationOptions : s_defaultEnumerationOptions; - string[] subdirectories = Directory.GetDirectories(moduleBase, "*", options); + IEnumerable subdirectories = Directory.EnumerateDirectories(moduleBase, "*", options); ProcessPossibleVersionSubdirectories(subdirectories, versionFolders); } return versionFolders; } - private static void ProcessPossibleVersionSubdirectories(string[] subdirectories, List versionFolders) + private static void ProcessPossibleVersionSubdirectories(IEnumerable subdirectories, List versionFolders) { foreach (string subdir in subdirectories) { @@ -352,7 +350,7 @@ private static void ProcessPossibleVersionSubdirectories(string[] subdirectories if (versionFolders.Count > 1) { - versionFolders.Sort((x, y) => y.CompareTo(x)); + versionFolders.Sort(static (x, y) => y.CompareTo(x)); } } @@ -437,7 +435,7 @@ internal static IEnumerable GetMatchingCommands(string pattern, Exe // 1. We continue to the next module path if we don't want to re-discover those imported modules // 2. If we want to re-discover the imported modules, but one or more commands from the module were made private, // then we don't do re-discovery - if (!rediscoverImportedModules || modules.Exists(module => module.ModuleHasPrivateMembers)) + if (!rediscoverImportedModules || modules.Exists(static module => module.ModuleHasPrivateMembers)) { continue; } @@ -615,4 +613,3 @@ public CommandScore(CommandInfo command, int score) public int Score; } } - diff --git a/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs b/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs index f61d3bb39bb..d47681166a0 100644 --- a/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs @@ -27,9 +27,9 @@ public sealed class NewModuleCommand : ModuleCmdletBase [Parameter(ParameterSetName = "Name", Mandatory = true, ValueFromPipeline = true, Position = 0)] public string Name { - set { _name = value; } - get { return _name; } + + set { _name = value; } } private string _name; @@ -42,7 +42,10 @@ public string Name [ValidateNotNull] public ScriptBlock ScriptBlock { - get { return _scriptBlock; } + get + { + return _scriptBlock; + } set { @@ -60,6 +63,11 @@ public ScriptBlock ScriptBlock [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { + get + { + return _functionImportList; + } + set { if (value == null) @@ -74,8 +82,6 @@ public string[] Function BaseFunctionPatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _functionImportList; } } private string[] _functionImportList = Array.Empty(); @@ -88,6 +94,11 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { + get + { + return _cmdletImportList; + } + set { if (value == null) @@ -102,8 +113,6 @@ public string[] Cmdlet BaseCmdletPatterns.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase)); } } - - get { return _cmdletImportList; } } private string[] _cmdletImportList = Array.Empty(); diff --git a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs index 77dab2bd551..e7cb2f846b3 100644 --- a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs +++ b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs @@ -160,7 +160,7 @@ public string Description [Parameter] public ProcessorArchitecture ProcessorArchitecture { - get { return _processorArchitecture.HasValue ? _processorArchitecture.Value : ProcessorArchitecture.None; } + get { return _processorArchitecture ?? ProcessorArchitecture.None; } set { _processorArchitecture = value; } } @@ -534,7 +534,7 @@ public string DefaultCommandPrefix /// /// The string to quote. /// The quoted string. - private string QuoteName(string name) + private static string QuoteName(string name) { if (name == null) return "''"; @@ -546,7 +546,7 @@ private string QuoteName(string name) /// /// The Uri to quote. /// The quoted AbsoluteUri. - private string QuoteName(Uri name) + private static string QuoteName(Uri name) { if (name == null) return "''"; @@ -558,7 +558,7 @@ private string QuoteName(Uri name) /// /// The Version object to quote. /// The quoted Version string. - private string QuoteName(Version name) + private static string QuoteName(Version name) { if (name == null) return "''"; @@ -572,7 +572,7 @@ private string QuoteName(Version name) /// The list to quote. /// Streamwriter to get end of line character from. /// The quoted list. - private string QuoteNames(IEnumerable names, StreamWriter streamWriter) + private static string QuoteNames(IEnumerable names, StreamWriter streamWriter) { if (names == null) return "@()"; @@ -622,7 +622,7 @@ private string QuoteNames(IEnumerable names, StreamWriter streamWriter) /// /// /// - private IEnumerable PreProcessModuleSpec(IEnumerable moduleSpecs) + private static IEnumerable PreProcessModuleSpec(IEnumerable moduleSpecs) { if (moduleSpecs != null) { @@ -647,7 +647,7 @@ private IEnumerable PreProcessModuleSpec(IEnumerable moduleSpecs) /// The list to quote. /// Streamwriter to get end of line character from. /// The quoted list. - private string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter) + private static string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter) { StringBuilder result = new StringBuilder(); result.Append("@("); @@ -662,8 +662,7 @@ private string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter) continue; } - ModuleSpecification moduleSpecification = (ModuleSpecification) - LanguagePrimitives.ConvertTo( + ModuleSpecification moduleSpecification = (ModuleSpecification)LanguagePrimitives.ConvertTo( spec, typeof(ModuleSpecification), CultureInfo.InvariantCulture); @@ -717,12 +716,12 @@ private string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter) result.Append("; "); } - result.Append("}"); + result.Append('}'); } } } - result.Append(")"); + result.Append(')'); return result.ToString(); } @@ -897,7 +896,7 @@ private string ManifestFragmentForNonSpecifiedManifestMember(string key, string _indent, resourceString, streamWriter.NewLine, key, value); } - private string ManifestComment(string insert, StreamWriter streamWriter) + private static string ManifestComment(string insert, StreamWriter streamWriter) { // Prefix a non-empty string with a space for formatting reasons... if (!string.IsNullOrEmpty(insert)) @@ -1094,7 +1093,7 @@ protected override void EndProcessing() BuildModuleManifest(result, nameof(DefaultCommandPrefix), Modules.DefaultCommandPrefix, !string.IsNullOrEmpty(_defaultCommandPrefix), () => QuoteName(_defaultCommandPrefix), streamWriter); - result.Append("}"); + result.Append('}'); result.Append(streamWriter.NewLine); result.Append(streamWriter.NewLine); string strResult = result.ToString(); @@ -1188,7 +1187,7 @@ private void BuildPrivateDataInModuleManifest(StringBuilder result, StreamWriter BuildModuleManifest(result, nameof(IconUri), Modules.IconUri, IconUri != null, () => QuoteName(IconUri), streamWriter); BuildModuleManifest(result, nameof(ReleaseNotes), Modules.ReleaseNotes, !string.IsNullOrEmpty(ReleaseNotes), () => QuoteName(ReleaseNotes), streamWriter); BuildModuleManifest(result, nameof(Prerelease), Modules.Prerelease, !string.IsNullOrEmpty(Prerelease), () => QuoteName(Prerelease), streamWriter); - BuildModuleManifest(result, nameof(RequireLicenseAcceptance), Modules.RequireLicenseAcceptance, RequireLicenseAcceptance.IsPresent, () => { return RequireLicenseAcceptance.IsPresent ? "$true" : "$false"; }, streamWriter); + BuildModuleManifest(result, nameof(RequireLicenseAcceptance), Modules.RequireLicenseAcceptance, RequireLicenseAcceptance.IsPresent, () => RequireLicenseAcceptance.IsPresent ? "$true" : "$false", streamWriter); BuildModuleManifest(result, nameof(ExternalModuleDependencies), Modules.ExternalModuleDependencies, ExternalModuleDependencies != null && ExternalModuleDependencies.Length > 0, () => QuoteNames(ExternalModuleDependencies, streamWriter), streamWriter); result.Append(" } "); diff --git a/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs b/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs index 033382a565b..1c56e8f920b 100644 --- a/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs +++ b/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs @@ -28,7 +28,7 @@ public sealed class PSModuleInfo new ReadOnlyDictionary(new Dictionary(StringComparer.OrdinalIgnoreCase)); // This dictionary doesn't include ExportedTypes from nested modules. - private ReadOnlyDictionary _exportedTypeDefinitionsNoNested { set; get; } + private ReadOnlyDictionary _exportedTypeDefinitionsNoNested { get; set; } private static readonly HashSet s_scriptModuleExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) { @@ -299,8 +299,7 @@ public string ModuleBase { get { - return _moduleBase ?? - (_moduleBase = !string.IsNullOrEmpty(Path) ? IO.Path.GetDirectoryName(Path) : string.Empty); + return _moduleBase ??= !string.IsNullOrEmpty(Path) ? IO.Path.GetDirectoryName(Path) : string.Empty; } } @@ -471,7 +470,10 @@ public string Author /// public ModuleAccessMode AccessMode { - get { return _accessMode; } + get + { + return _accessMode; + } set { @@ -582,7 +584,7 @@ public Dictionary ExportedFunctions } } - private bool IsScriptModuleFile(string path) + private static bool IsScriptModuleFile(string path) { var ext = System.IO.Path.GetExtension(path); return ext != null && s_scriptModuleExtensions.Contains(ext); @@ -659,16 +661,16 @@ internal void CreateExportedTypeDefinitions(ScriptBlockAst moduleContentScriptBl else { this._exportedTypeDefinitionsNoNested = new ReadOnlyDictionary( - moduleContentScriptBlockAsts.FindAll(a => (a is TypeDefinitionAst), false) + moduleContentScriptBlockAsts.FindAll(static a => (a is TypeDefinitionAst), false) .OfType() - .ToDictionary(a => a.Name, StringComparer.OrdinalIgnoreCase)); + .ToDictionary(static a => a.Name, StringComparer.OrdinalIgnoreCase)); } } internal void AddDetectedTypeExports(List typeDefinitions) { this._exportedTypeDefinitionsNoNested = new ReadOnlyDictionary( - typeDefinitions.ToDictionary(a => a.Name, StringComparer.OrdinalIgnoreCase)); + typeDefinitions.ToDictionary(static a => a.Name, StringComparer.OrdinalIgnoreCase)); } /// @@ -876,7 +878,7 @@ public IEnumerable CompatiblePSEditions get { return _compatiblePSEditions; } } - private List _compatiblePSEditions = new List(); + private readonly List _compatiblePSEditions = new List(); internal void AddToCompatiblePSEditions(string psEdition) { @@ -922,8 +924,7 @@ public ReadOnlyCollection NestedModules { get { - return _readonlyNestedModules ?? - (_readonlyNestedModules = new ReadOnlyCollection(_nestedModules)); + return _readonlyNestedModules ??= new ReadOnlyCollection(_nestedModules); } } @@ -1014,8 +1015,7 @@ public ReadOnlyCollection RequiredModules { get { - return _readonlyRequiredModules ?? - (_readonlyRequiredModules = new ReadOnlyCollection(_requiredModules)); + return _readonlyRequiredModules ??= new ReadOnlyCollection(_requiredModules); } } @@ -1040,8 +1040,7 @@ internal ReadOnlyCollection RequiredModulesSpecification { get { - return _readonlyRequiredModulesSpecification ?? - (_readonlyRequiredModulesSpecification = new ReadOnlyCollection(_requiredModulesSpecification)); + return _readonlyRequiredModulesSpecification ??= new ReadOnlyCollection(_requiredModulesSpecification); } } @@ -1360,7 +1359,7 @@ internal void CaptureLocals() try { // Only copy simple mutable variables... - if (v.Options == ScopedItemOptions.None && !(v is NullVariable)) + if (v.Options == ScopedItemOptions.None && v is not NullVariable) { PSVariable newVar = new PSVariable(v.Name, v.Value, v.Options, v.Description); // The variable is already defined/set in the scope, and that means the attributes diff --git a/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs b/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs index 015b2bb72d2..18e12541528 100644 --- a/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs +++ b/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs @@ -25,13 +25,13 @@ namespace System.Management.Automation { - internal class RemoteDiscoveryHelper + internal static class RemoteDiscoveryHelper { #region PSRP private static Collection RehydrateHashtableKeys(PSObject pso, string propertyName) { - var rehydrationFlags = DeserializingTypeConverter.RehydrationFlags.NullValueOk | + const DeserializingTypeConverter.RehydrationFlags rehydrationFlags = DeserializingTypeConverter.RehydrationFlags.NullValueOk | DeserializingTypeConverter.RehydrationFlags.MissingPropertyOk; Hashtable hashtable = DeserializingTypeConverter.GetPropertyValue(pso, propertyName, rehydrationFlags); if (hashtable == null) @@ -43,9 +43,9 @@ private static Collection RehydrateHashtableKeys(PSObject pso, string pr List list = hashtable .Keys .Cast() - .Where(k => k != null) - .Select(k => k.ToString()) - .Where(s => s != null) + .Where(static k => k != null) + .Select(static k => k.ToString()) + .Where(static s => s != null) .ToList(); return new Collection(list); } @@ -53,7 +53,7 @@ private static Collection RehydrateHashtableKeys(PSObject pso, string pr internal static PSModuleInfo RehydratePSModuleInfo(PSObject deserializedModuleInfo) { - var rehydrationFlags = DeserializingTypeConverter.RehydrationFlags.NullValueOk | + const DeserializingTypeConverter.RehydrationFlags rehydrationFlags = DeserializingTypeConverter.RehydrationFlags.NullValueOk | DeserializingTypeConverter.RehydrationFlags.MissingPropertyOk; string name = DeserializingTypeConverter.GetPropertyValue(deserializedModuleInfo, "Name", rehydrationFlags); string path = DeserializingTypeConverter.GetPropertyValue(deserializedModuleInfo, "Path", rehydrationFlags); @@ -112,24 +112,24 @@ internal static PSModuleInfo RehydratePSModuleInfo(PSObject deserializedModuleIn private static EventHandler GetStreamForwarder(Action forwardingAction, bool swallowInvalidOperationExceptions = false) { // TODO/FIXME: ETW event for extended semantics streams - return delegate (object sender, DataAddedEventArgs eventArgs) - { - var psDataCollection = (PSDataCollection)sender; - foreach (T t in psDataCollection.ReadAll()) - { - try - { - forwardingAction(t); - } - catch (InvalidOperationException) - { - if (!swallowInvalidOperationExceptions) - { - throw; - } - } - } - }; + return (object sender, DataAddedEventArgs eventArgs) => + { + var psDataCollection = (PSDataCollection)sender; + foreach (T t in psDataCollection.ReadAll()) + { + try + { + forwardingAction(t); + } + catch (InvalidOperationException) + { + if (!swallowInvalidOperationExceptions) + { + throw; + } + } + } + }; } // This is a static field (instead of a constant) to make it possible to set through tests (and/or by customers if needed for a workaround) @@ -137,10 +137,10 @@ private static EventHandler GetStreamForwarder(Action private static IEnumerable InvokeTopLevelPowerShell( PowerShell powerShell, - CancellationToken cancellationToken, PSCmdlet cmdlet, PSInvocationSettings invocationSettings, - string errorMessageTemplate) + string errorMessageTemplate, + CancellationToken cancellationToken) { using (var mergedOutput = new BlockingCollection>>(s_blockingCollectionCapacity)) { @@ -151,7 +151,7 @@ private static IEnumerable InvokeTopLevelPowerShell( EventHandler errorHandler = GetStreamForwarder( errorRecord => mergedOutput.Add( - delegate (PSCmdlet c) + (PSCmdlet c) => { errorRecord = GetErrorRecordForRemotePipelineInvocation(errorRecord, errorMessageTemplate); HandleErrorFromPipeline(c, errorRecord, powerShell); @@ -161,7 +161,7 @@ private static IEnumerable InvokeTopLevelPowerShell( EventHandler warningHandler = GetStreamForwarder( warningRecord => mergedOutput.Add( - delegate (PSCmdlet c) + (PSCmdlet c) => { c.WriteWarning(warningRecord.Message); return Enumerable.Empty(); @@ -170,7 +170,7 @@ private static IEnumerable InvokeTopLevelPowerShell( EventHandler verboseHandler = GetStreamForwarder( verboseRecord => mergedOutput.Add( - delegate (PSCmdlet c) + (PSCmdlet c) => { c.WriteVerbose(verboseRecord.Message); return Enumerable.Empty(); @@ -179,7 +179,7 @@ private static IEnumerable InvokeTopLevelPowerShell( EventHandler debugHandler = GetStreamForwarder( debugRecord => mergedOutput.Add( - delegate (PSCmdlet c) + (PSCmdlet c) => { c.WriteDebug(debugRecord.Message); return Enumerable.Empty(); @@ -188,7 +188,7 @@ private static IEnumerable InvokeTopLevelPowerShell( EventHandler informationHandler = GetStreamForwarder( informationRecord => mergedOutput.Add( - delegate (PSCmdlet c) + (PSCmdlet c) => { c.WriteInformation(informationRecord); return Enumerable.Empty(); @@ -256,13 +256,13 @@ private static IEnumerable InvokeTopLevelPowerShell( private static IEnumerable InvokeNestedPowerShell( PowerShell powerShell, - CancellationToken cancellationToken, PSCmdlet cmdlet, PSInvocationSettings invocationSettings, - string errorMessageTemplate) + string errorMessageTemplate, + CancellationToken cancellationToken) { EventHandler errorHandler = GetStreamForwarder( - delegate (ErrorRecord errorRecord) + (ErrorRecord errorRecord) => { errorRecord = GetErrorRecordForRemotePipelineInvocation(errorRecord, errorMessageTemplate); HandleErrorFromPipeline(cmdlet, errorRecord, powerShell); @@ -360,7 +360,7 @@ private static ErrorRecord GetErrorRecordForRemotePipelineInvocation(Exception i Exception outerException = new InvalidOperationException(errorMessage, innerException); RemoteException remoteException = innerException as RemoteException; - ErrorRecord remoteErrorRecord = remoteException != null ? remoteException.ErrorRecord : null; + ErrorRecord remoteErrorRecord = remoteException?.ErrorRecord; string errorId = remoteErrorRecord != null ? remoteErrorRecord.FullyQualifiedErrorId : innerException.GetType().Name; ErrorCategory errorCategory = remoteErrorRecord != null ? remoteErrorRecord.CategoryInfo.Category : ErrorCategory.NotSpecified; ErrorRecord errorRecord = new ErrorRecord(outerException, errorId, errorCategory, null); @@ -467,9 +467,9 @@ private static void HandleErrorFromPipeline(Cmdlet cmdlet, ErrorRecord errorReco internal static IEnumerable InvokePowerShell( PowerShell powerShell, - CancellationToken cancellationToken, PSCmdlet cmdlet, - string errorMessageTemplate) + string errorMessageTemplate, + CancellationToken cancellationToken) { CopyParameterFromCmdletToPowerShell(cmdlet, powerShell, "ErrorAction"); CopyParameterFromCmdletToPowerShell(cmdlet, powerShell, "WarningAction"); @@ -481,12 +481,12 @@ internal static IEnumerable InvokePowerShell( // TODO/FIXME: ETW events for the output stream IEnumerable outputStream = powerShell.IsNested - ? InvokeNestedPowerShell(powerShell, cancellationToken, cmdlet, invocationSettings, errorMessageTemplate) - : InvokeTopLevelPowerShell(powerShell, cancellationToken, cmdlet, invocationSettings, errorMessageTemplate); + ? InvokeNestedPowerShell(powerShell, cmdlet, invocationSettings, errorMessageTemplate, cancellationToken) + : InvokeTopLevelPowerShell(powerShell, cmdlet, invocationSettings, errorMessageTemplate, cancellationToken); return EnumerateWithCatch( outputStream, - delegate (Exception exception) + (Exception exception) => { ErrorRecord errorRecord = GetErrorRecordForRemotePipelineInvocation(exception, errorMessageTemplate); HandleErrorFromPipeline(cmdlet, errorRecord, powerShell); @@ -683,13 +683,13 @@ internal void FetchAllModuleFiles(CimSession cimSession, string cimNamespace, Ci "Dependent", operationOptions); - IEnumerable associatedFiles = associatedInstances.Select(i => new CimModuleImplementationFile(i)); + IEnumerable associatedFiles = associatedInstances.Select(static i => new CimModuleImplementationFile(i)); _moduleFiles = associatedFiles.ToList(); } private List _moduleFiles; - private class CimModuleManifestFile : CimModuleFile + private sealed class CimModuleManifestFile : CimModuleFile { internal CimModuleManifestFile(string fileName, byte[] rawFileData) { @@ -705,7 +705,7 @@ internal CimModuleManifestFile(string fileName, byte[] rawFileData) internal override byte[] RawFileDataCore { get; } } - private class CimModuleImplementationFile : CimModuleFile + private sealed class CimModuleImplementationFile : CimModuleFile { private readonly CimInstance _baseObject; @@ -744,7 +744,7 @@ internal static IEnumerable GetCimModules( Cmdlet cmdlet, CancellationToken cancellationToken) { - moduleNamePatterns = moduleNamePatterns ?? new[] { "*" }; + moduleNamePatterns ??= new[] { "*" }; HashSet alreadyEmittedNamesOfCimModules = new HashSet(StringComparer.OrdinalIgnoreCase); IEnumerable remoteModules = moduleNamePatterns @@ -795,13 +795,13 @@ private static IEnumerable GetCimModules( options); // TODO/FIXME: ETW for method results IEnumerable cimModules = syncResults - .Select(cimInstance => new CimModule(cimInstance)) + .Select(static cimInstance => new CimModule(cimInstance)) .Where(cimModule => wildcardPattern.IsMatch(cimModule.ModuleName)); if (!onlyManifests) { cimModules = cimModules.Select( - delegate (CimModule cimModule) + (CimModule cimModule) => { cimModule.FetchAllModuleFiles(cimSession, cimNamespace, options); return cimModule; @@ -810,14 +810,15 @@ private static IEnumerable GetCimModules( return EnumerateWithCatch( cimModules, - delegate (Exception exception) + (Exception exception) => { ErrorRecord errorRecord = GetErrorRecordForRemoteDiscoveryProvider(exception); if (!cmdlet.MyInvocation.ExpectingInput) { - if (((-1) != errorRecord.FullyQualifiedErrorId.IndexOf(DiscoveryProviderNotFoundErrorId, StringComparison.OrdinalIgnoreCase)) || - (cancellationToken.IsCancellationRequested || (exception is OperationCanceledException)) || - (!cimSession.TestConnection())) + if (errorRecord.FullyQualifiedErrorId.Contains(DiscoveryProviderNotFoundErrorId, StringComparison.OrdinalIgnoreCase) + || cancellationToken.IsCancellationRequested + || exception is OperationCanceledException + || !cimSession.TestConnection()) { cmdlet.ThrowTerminatingError(errorRecord); } @@ -855,9 +856,9 @@ internal static Hashtable RewriteManifest( IEnumerable typesToProcess, IEnumerable formatsToProcess) { - nestedModules = nestedModules ?? Array.Empty(); - typesToProcess = typesToProcess ?? Array.Empty(); - formatsToProcess = formatsToProcess ?? Array.Empty(); + nestedModules ??= Array.Empty(); + typesToProcess ??= Array.Empty(); + formatsToProcess ??= Array.Empty(); var newManifest = new Hashtable(StringComparer.OrdinalIgnoreCase); newManifest["NestedModules"] = nestedModules; @@ -980,8 +981,8 @@ internal static CimSession CreateCimSession( PSCredential credential, string authentication, bool isLocalHost, - CancellationToken cancellationToken, - PSCmdlet cmdlet) + PSCmdlet cmdlet, + CancellationToken cancellationToken) { if (isLocalHost) { @@ -1037,7 +1038,7 @@ internal static Hashtable ConvertCimModuleFileToManifestHashtable(RemoteDiscover internal static string GetModulePath(string remoteModuleName, Version remoteModuleVersion, string computerName, Runspace localRunspace) { - computerName = computerName ?? string.Empty; + computerName ??= string.Empty; string sanitizedRemoteModuleName = Regex.Replace(remoteModuleName, "[^a-zA-Z0-9]", string.Empty); string sanitizedComputerName = Regex.Replace(computerName, "[^a-zA-Z0-9]", string.Empty); diff --git a/src/System.Management.Automation/engine/Modules/RemoveModuleCommand.cs b/src/System.Management.Automation/engine/Modules/RemoveModuleCommand.cs index 64958c9fde6..7978e42a5b8 100644 --- a/src/System.Management.Automation/engine/Modules/RemoveModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/RemoveModuleCommand.cs @@ -32,9 +32,9 @@ public sealed class RemoveModuleCommand : ModuleCmdletBase [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Name { - set { _name = value; } - get { return _name; } + + set { _name = value; } } private string[] _name = Array.Empty(); @@ -53,9 +53,9 @@ public string[] Name [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public PSModuleInfo[] ModuleInfo { - set { _moduleInfo = value; } - get { return _moduleInfo; } + + set { _moduleInfo = value; } } private PSModuleInfo[] _moduleInfo = Array.Empty(); @@ -362,7 +362,7 @@ protected override void EndProcessing() hasWildcards = false; } - if (FullyQualifiedName != null && (FullyQualifiedName.Any(moduleSpec => !InitialSessionState.IsEngineModule(moduleSpec.Name)))) + if (FullyQualifiedName != null && (FullyQualifiedName.Any(static moduleSpec => !InitialSessionState.IsEngineModule(moduleSpec.Name)))) { isEngineModule = false; } diff --git a/src/System.Management.Automation/engine/Modules/ScriptAnalysis.cs b/src/System.Management.Automation/engine/Modules/ScriptAnalysis.cs index 6ec64a4cf0f..8720fc1f161 100644 --- a/src/System.Management.Automation/engine/Modules/ScriptAnalysis.cs +++ b/src/System.Management.Automation/engine/Modules/ScriptAnalysis.cs @@ -105,10 +105,15 @@ internal static string ReadScript(string path) } internal List DiscoveredExports { get; set; } + internal Dictionary DiscoveredAliases { get; set; } + internal List DiscoveredModules { get; set; } + internal List DiscoveredCommandFilters { get; set; } + internal bool AddsSelfToPath { get; set; } + internal List DiscoveredClasses { get; set; } } @@ -160,11 +165,17 @@ static ExportVisitor() private readonly bool _forCompletion; internal List DiscoveredExports { get; set; } + internal List DiscoveredModules { get; set; } + internal Dictionary DiscoveredFunctions { get; set; } + internal Dictionary DiscoveredAliases { get; set; } + internal List DiscoveredCommandFilters { get; set; } + internal bool AddsSelfToPath { get; set; } + internal List DiscoveredClasses { get; set; } public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) @@ -335,10 +346,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst) List commandsToPostFilter = new List(); - Action onEachCommand = importedCommandName => - { - commandsToPostFilter.Add(importedCommandName); - }; + Action onEachCommand = importedCommandName => commandsToPostFilter.Add(importedCommandName); // Process any exports from the module that we determine from // the -Function, -Cmdlet, or -Alias parameters @@ -454,7 +462,7 @@ private void ProcessCmdletArguments(object value, Action onEachArgument) // // It also only populates the bound parameters for a limited set of parameters needed // for module analysis. - private Hashtable DoPsuedoParameterBinding(CommandAst commandAst, string commandName) + private static Hashtable DoPsuedoParameterBinding(CommandAst commandAst, string commandName) { var result = new Hashtable(StringComparer.OrdinalIgnoreCase); @@ -547,9 +555,9 @@ private Hashtable DoPsuedoParameterBinding(CommandAst commandAst, string command return result; } - private static Dictionary s_parameterBindingInfoTable; + private static readonly Dictionary s_parameterBindingInfoTable; - private class ParameterBindingInfo + private sealed class ParameterBindingInfo { internal ParameterInfo[] parameterInfo; } @@ -567,6 +575,7 @@ private struct ParameterInfo internal class RequiredModuleInfo { internal string Name { get; set; } + internal List CommandsToPostFilter { get; set; } } } diff --git a/src/System.Management.Automation/engine/Modules/TestModuleManifestCommand.cs b/src/System.Management.Automation/engine/Modules/TestModuleManifestCommand.cs index 2f6c0fdd5cf..566262e3db9 100644 --- a/src/System.Management.Automation/engine/Modules/TestModuleManifestCommand.cs +++ b/src/System.Management.Automation/engine/Modules/TestModuleManifestCommand.cs @@ -172,7 +172,7 @@ protected override void ProcessRecord() && !IsValidGacAssembly(nestedModule.Name)) { Collection modules = GetModuleIfAvailable(nestedModule); - if (0 == modules.Count) + if (modules.Count == 0) { string errorMsg = StringUtil.Format(Modules.InvalidNestedModuleinModuleManifest, nestedModule.Name, filePath); var errorRecord = new ErrorRecord(new DirectoryNotFoundException(errorMsg), "Modules_InvalidNestedModuleinModuleManifest", @@ -294,7 +294,7 @@ protected override void ProcessRecord() // All module extensions except ".psd1" are valid RootModule extensions private static readonly IReadOnlyList s_validRootModuleExtensions = ModuleIntrinsics.PSModuleExtensions - .Where(ext => !string.Equals(ext, StringLiterals.PowerShellDataFileExtension, StringComparison.OrdinalIgnoreCase)) + .Where(static ext => !string.Equals(ext, StringLiterals.PowerShellDataFileExtension, StringComparison.OrdinalIgnoreCase)) .ToArray(); /// @@ -404,7 +404,7 @@ private bool IsValidFilePath(string path, PSModuleInfo module, bool verifyPathSc /// /// /// - private bool IsValidGacAssembly(string assemblyName) + private static bool IsValidGacAssembly(string assemblyName) { #if UNIX return false; @@ -420,23 +420,13 @@ private bool IsValidGacAssembly(string assemblyName) try { - var allFiles = Directory.GetFiles(gacPath, assemblyFile, SearchOption.AllDirectories); - - if (allFiles.Length == 0) - { - var allNgenFiles = Directory.GetFiles(gacPath, ngenAssemblyFile, SearchOption.AllDirectories); - if (allNgenFiles.Length == 0) - { - return false; - } - } + return Directory.EnumerateFiles(gacPath, assemblyFile, SearchOption.AllDirectories).Any() + || Directory.EnumerateFiles(gacPath, ngenAssemblyFile, SearchOption.AllDirectories).Any(); } catch { return false; } - - return true; #endif } } diff --git a/src/System.Management.Automation/engine/MshCmdlet.cs b/src/System.Management.Automation/engine/MshCmdlet.cs index 113c3d39dbd..c11e674660c 100644 --- a/src/System.Management.Automation/engine/MshCmdlet.cs +++ b/src/System.Management.Automation/engine/MshCmdlet.cs @@ -14,6 +14,7 @@ namespace System.Management.Automation { #region Auxiliary + /// /// An interface that a /// or @@ -31,6 +32,7 @@ namespace System.Management.Automation /// /// /// +#nullable enable public interface IDynamicParameters { /// @@ -62,15 +64,17 @@ public interface IDynamicParameters /// may not be set at the time this method is called, /// even if the parameters are mandatory. /// - object GetDynamicParameters(); + object? GetDynamicParameters(); } +#nullable restore + /// /// Type used to define a parameter on a cmdlet script of function that /// can only be used as a switch. /// - public struct SwitchParameter + public readonly struct SwitchParameter { - private bool _isPresent; + private readonly bool _isPresent; /// /// Returns true if the parameter was specified on the command line, false otherwise. /// @@ -233,9 +237,9 @@ public override string ToString() /// public class CommandInvocationIntrinsics { - private ExecutionContext _context; - private PSCmdlet _cmdlet; - private MshCommandRuntime _commandRuntime; + private readonly ExecutionContext _context; + private readonly PSCmdlet _cmdlet; + private readonly MshCommandRuntime _commandRuntime; internal CommandInvocationIntrinsics(ExecutionContext context, PSCmdlet cmdlet) { @@ -670,40 +674,46 @@ internal IEnumerable GetCommands(string name, CommandTypes commandT } /// - /// Executes a piece of text as a script synchronously. + /// Executes a piece of text as a script synchronously in the caller's session state. + /// The given text will be executed in a child scope rather than dot-sourced. /// /// The script text to evaluate. - /// A collection of MshCobjects generated by the script. + /// A collection of MshCobjects generated by the script. Never null, but may be empty. /// Thrown if there was a parsing error in the script. /// Represents a script-level exception. /// public Collection InvokeScript(string script) { - return InvokeScript(script, true, PipelineResultTypes.None, null); + return InvokeScript(script, useNewScope: true, PipelineResultTypes.None, input: null); } /// - /// Executes a piece of text as a script synchronously. + /// Executes a piece of text as a script synchronously in the caller's session state. + /// The given text will be executed in a child scope rather than dot-sourced. /// /// The script text to evaluate. - /// The arguments to the script. - /// A collection of MshCobjects generated by the script. + /// The arguments to the script, available as $args. + /// A collection of MshCobjects generated by the script. Never null, but may be empty. /// Thrown if there was a parsing error in the script. /// Represents a script-level exception. /// public Collection InvokeScript(string script, params object[] args) { - return InvokeScript(script, true, PipelineResultTypes.None, null, args); + return InvokeScript(script, useNewScope: true, PipelineResultTypes.None, input: null, args); } /// + /// Executes a given scriptblock synchonously in the given session state. + /// The scriptblock will be executed in the calling scope (dot-sourced) rather than in a new child scope. /// - /// - /// - /// - /// + /// The session state in which to execute the scriptblock. + /// The scriptblock to execute. + /// The arguments to the scriptblock, available as $args. + /// A collection of the PSObjects emitted by the executing scriptblock. Never null, but may be empty. public Collection InvokeScript( - SessionState sessionState, ScriptBlock scriptBlock, params object[] args) + SessionState sessionState, + ScriptBlock scriptBlock, + params object[] args) { if (scriptBlock == null) { @@ -735,13 +745,18 @@ public Collection InvokeScript( /// /// Invoke a scriptblock in the current runspace, controlling if it gets a new scope. /// - /// If true, a new scope will be created. + /// If true, executes the scriptblock in a new child scope, otherwise the scriptblock is dot-sourced into the calling scope. /// The scriptblock to execute. /// Optionall input to the command. /// Arguments to pass to the scriptblock. - /// The result of the evaluation. + /// + /// A collection of the PSObjects generated by executing the script. Never null, but may be empty. + /// public Collection InvokeScript( - bool useLocalScope, ScriptBlock scriptBlock, IList input, params object[] args) + bool useLocalScope, + ScriptBlock scriptBlock, + IList input, + params object[] args) { if (scriptBlock == null) { @@ -767,21 +782,25 @@ public Collection InvokeScript( /// /// The script to evaluate. /// If true, evaluate the script in its own scope. - /// If false, the script will be evaluated in the current scope i.e. it will be "dotted" + /// If false, the script will be evaluated in the current scope i.e. it will be dot-sourced. /// If set to Output, all output will be streamed /// to the output pipe of the calling cmdlet. If set to None, the result will be returned /// to the caller as a collection of PSObjects. No other flags are supported at this time and /// will result in an exception if used. /// The list of objects to use as input to the script. - /// The array of arguments to the command. - /// A collection of MshCobjects generated by the script. This will be - /// empty if output was redirected. + /// The array of arguments to the command, available as $args. + /// A collection of PSObjects generated by the script. This will be + /// empty if output was redirected. Never null. /// Thrown if there was a parsing error in the script. /// Represents a script-level exception. /// Thrown if any redirect other than output is attempted. /// - public Collection InvokeScript(string script, bool useNewScope, - PipelineResultTypes writeToPipeline, IList input, params object[] args) + public Collection InvokeScript( + string script, + bool useNewScope, + PipelineResultTypes writeToPipeline, + IList input, + params object[] args) { if (script == null) throw new ArgumentNullException(nameof(script)); @@ -792,8 +811,12 @@ public Collection InvokeScript(string script, bool useNewScope, return InvokeScript(sb, useNewScope, writeToPipeline, input, args); } - private Collection InvokeScript(ScriptBlock sb, bool useNewScope, - PipelineResultTypes writeToPipeline, IList input, params object[] args) + private Collection InvokeScript( + ScriptBlock sb, + bool useNewScope, + PipelineResultTypes writeToPipeline, + IList input, + params object[] args) { if (_cmdlet != null) _cmdlet.ThrowIfStopping(); @@ -956,7 +979,7 @@ public string ParameterSetName /// /// If the cmdlet declares paging support (via ), /// then property contains arguments of the paging parameters. - /// Otherwise property is null. + /// Otherwise property is . /// public PagingParameters PagingParameters { @@ -999,7 +1022,7 @@ public CommandInvocationIntrinsics InvokeCommand { using (PSTransactionManager.GetEngineProtectionScope()) { - return _invokeCommand ?? (_invokeCommand = new CommandInvocationIntrinsics(Context, this)); + return _invokeCommand ??= new CommandInvocationIntrinsics(Context, this); } } } @@ -1009,4 +1032,3 @@ public CommandInvocationIntrinsics InvokeCommand } } - diff --git a/src/System.Management.Automation/engine/MshCommandRuntime.cs b/src/System.Management.Automation/engine/MshCommandRuntime.cs index 2816dd42f13..3a440478d1a 100644 --- a/src/System.Management.Automation/engine/MshCommandRuntime.cs +++ b/src/System.Management.Automation/engine/MshCommandRuntime.cs @@ -92,8 +92,8 @@ internal bool IsPipelineInputExpected internal PipelineProcessor PipelineProcessor { get; set; } - private CommandInfo _commandInfo; - private InternalCommand _thisCommand; + private readonly CommandInfo _commandInfo; + private readonly InternalCommand _thisCommand; #endregion private_members @@ -125,7 +125,7 @@ public override string ToString() /// The invocation object for this command. internal InvocationInfo MyInvocation { - get { return _myInvocation ?? (_myInvocation = _thisCommand.MyInvocation); } + get { return _myInvocation ??= _thisCommand.MyInvocation; } } /// @@ -353,7 +353,7 @@ internal void WriteProgress(ProgressRecord progressRecord, bool overrideInquire) // WriteProgress. The following logic ensures that // there is a unique id for each Cmdlet instance. - if (0 == _sourceId) + if (_sourceId == 0) { _sourceId = Interlocked.Increment(ref s_lastUsedSourceId); } @@ -1735,8 +1735,13 @@ public bool ShouldContinue(string query, string caption) { bool yesToAll = false; bool noToAll = false; - bool hasSecurityImpact = false; - return DoShouldContinue(query, caption, hasSecurityImpact, false, ref yesToAll, ref noToAll); + return DoShouldContinue( + query, + caption, + hasSecurityImpact: false, + supportsToAllOptions: false, + ref yesToAll, + ref noToAll); } /// @@ -2050,6 +2055,7 @@ public PSTransactionContext CurrentPSTransaction /// . /// etc. /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] public void ThrowTerminatingError(ErrorRecord errorRecord) { ThrowIfStopping(); @@ -2206,7 +2212,7 @@ internal void SetMergeFromRuntime(MshCommandRuntime fromRuntime) /// internal Pipe InputPipe { - get { return _inputPipe ?? (_inputPipe = new Pipe()); } + get { return _inputPipe ??= new Pipe(); } set { _inputPipe = value; } } @@ -2216,7 +2222,7 @@ internal Pipe InputPipe /// internal Pipe OutputPipe { - get { return _outputPipe ?? (_outputPipe = new Pipe()); } + get { return _outputPipe ??= new Pipe(); } set { _outputPipe = value; } } @@ -2239,7 +2245,7 @@ internal object[] GetResultsAsArray() /// internal Pipe ErrorOutputPipe { - get { return _errorOutputPipe ?? (_errorOutputPipe = new Pipe()); } + get { return _errorOutputPipe ??= new Pipe(); } set { _errorOutputPipe = value; } } @@ -2312,7 +2318,7 @@ internal IDisposable AllowThisCommandToWrite(bool permittedToWriteToPipeline) return new AllowWrite(_thisCommand, permittedToWriteToPipeline); } - private class AllowWrite : IDisposable + private sealed class AllowWrite : IDisposable { /// /// Begin the scope where WriteObject/WriteError is permitted. @@ -2321,8 +2327,7 @@ internal AllowWrite(InternalCommand permittedToWrite, bool permittedToWriteToPip { if (permittedToWrite == null) throw PSTraceSource.NewArgumentNullException(nameof(permittedToWrite)); - MshCommandRuntime mcr = permittedToWrite.commandRuntime as MshCommandRuntime; - if (mcr == null) + if (!(permittedToWrite.commandRuntime is MshCommandRuntime mcr)) throw PSTraceSource.NewArgumentNullException("permittedToWrite.CommandRuntime"); _pp = mcr.PipelineProcessor; if (_pp == null) @@ -2352,10 +2357,10 @@ public void Dispose() // There is no finalizer, by design. This class relies on always // being disposed and always following stack semantics. - private PipelineProcessor _pp = null; - private InternalCommand _wasPermittedToWrite = null; - private bool _wasPermittedToWriteToPipeline = false; - private Thread _wasPermittedToWriteThread = null; + private readonly PipelineProcessor _pp = null; + private readonly InternalCommand _wasPermittedToWrite = null; + private readonly bool _wasPermittedToWriteToPipeline = false; + private readonly Thread _wasPermittedToWriteThread = null; } /// @@ -2384,7 +2389,10 @@ public Exception ManageException(Exception e) // PipelineStoppedException should not get added to $Error // 2008/06/25 - narrieta: ExistNestedPromptException should not be added to $error either // 2019/10/18 - StopUpstreamCommandsException should not be added either - if (!(e is HaltCommandException) && !(e is PipelineStoppedException) && !(e is ExitNestedPromptException) && !(e is StopUpstreamCommandsException)) + if (e is not HaltCommandException + && e is not PipelineStoppedException + && e is not ExitNestedPromptException + && e is not StopUpstreamCommandsException) { try { @@ -2831,7 +2839,7 @@ internal void _WriteErrorSkipAllowCheck(ErrorRecord errorRecord, ActionPreferenc this.PipelineProcessor.LogExecutionError(_thisCommand.MyInvocation, errorRecord); } - if (!(ExperimentalFeature.IsEnabled("PSNotApplyErrorActionToStderr") && isNativeError)) + if (!isNativeError) { this.PipelineProcessor.ExecutionFailed = true; @@ -2842,20 +2850,20 @@ internal void _WriteErrorSkipAllowCheck(ErrorRecord errorRecord, ActionPreferenc } // No trace of the error in the 'Ignore' case - if (ActionPreference.Ignore == preference) + if (preference == ActionPreference.Ignore) { return; // do not write or record to output pipe } // 2004/05/26-JonN // The object is not written in the SilentlyContinue case - if (ActionPreference.SilentlyContinue == preference) + if (preference == ActionPreference.SilentlyContinue) { AppendErrorToVariables(errorRecord); return; // do not write to output pipe } - if (ContinueStatus.YesToAll == lastErrorContinueStatus) + if (lastErrorContinueStatus == ContinueStatus.YesToAll) { preference = ActionPreference.Continue; } @@ -3024,7 +3032,7 @@ internal ActionPreference DebugPreference } } - private bool _isVerbosePreferenceCached = false; + private readonly bool _isVerbosePreferenceCached = false; private ActionPreference _verbosePreference = InitialSessionState.DefaultVerbosePreference; /// /// Preference setting. @@ -3073,7 +3081,7 @@ internal ActionPreference VerbosePreference internal bool IsWarningActionSet { get; private set; } = false; - private bool _isWarningPreferenceCached = false; + private readonly bool _isWarningPreferenceCached = false; private ActionPreference _warningPreference = InitialSessionState.DefaultWarningPreference; /// /// Preference setting. @@ -3129,7 +3137,10 @@ internal ActionPreference WarningPreference /// internal bool Verbose { - get { return _verboseFlag; } + get + { + return _verboseFlag; + } set { @@ -3202,7 +3213,10 @@ internal SwitchParameter UseTransaction /// internal bool Debug { - get { return _debugFlag; } + get + { + return _debugFlag; + } set { @@ -3382,7 +3396,7 @@ internal enum ContinueStatus No, YesToAll, NoToAll - }; + } internal ContinueStatus lastShouldProcessContinueStatus = ContinueStatus.Yes; internal ContinueStatus lastErrorContinueStatus = ContinueStatus.Yes; @@ -3682,7 +3696,7 @@ bool hasSecurityImpact CBhost.EnterNestedPrompt(_thisCommand); // continue loop } - else if (-1 == response) + else if (response == -1) { ActionPreferenceStopException e = new ActionPreferenceStopException( @@ -3744,6 +3758,17 @@ internal void SetVariableListsInPipe() if (this.PipelineVariable != null) { + // _state can be null if the current script block is dynamicparam, etc. + if (_state != null) + { + // Create the pipeline variable + _state.PSVariable.Set(_pipelineVarReference); + + // Get the reference again in case we re-used one from the + // same scope. + _pipelineVarReference = _state.PSVariable.Get(this.PipelineVariable); + } + this.OutputPipe.SetPipelineVariable(_pipelineVarReference); } } diff --git a/src/System.Management.Automation/engine/MshMemberInfo.cs b/src/System.Management.Automation/engine/MshMemberInfo.cs index ab1369822ea..73ee243f6e8 100644 --- a/src/System.Management.Automation/engine/MshMemberInfo.cs +++ b/src/System.Management.Automation/engine/MshMemberInfo.cs @@ -6,6 +6,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Management.Automation.Internal; @@ -161,7 +162,7 @@ internal enum MshMemberMatchOptions IncludeHidden = 1, /// - /// Only include members with property set to true + /// Only include members with property set to /// OnlySerializable = 2 } @@ -283,12 +284,12 @@ protected void SetMemberName(string name) internal bool MatchesOptions(MshMemberMatchOptions options) { - if (this.IsHidden && (0 == (options & MshMemberMatchOptions.IncludeHidden))) + if (this.IsHidden && ((options & MshMemberMatchOptions.IncludeHidden) == 0)) { return false; } - if (!this.ShouldSerialize && (0 != (options & MshMemberMatchOptions.OnlySerializable))) + if (!this.ShouldSerialize && ((options & MshMemberMatchOptions.OnlySerializable) != 0)) { return false; } @@ -356,9 +357,9 @@ public override string ToString() returnValue.Append(" = "); if (ConversionType != null) { - returnValue.Append("("); + returnValue.Append('('); returnValue.Append(ConversionType); - returnValue.Append(")"); + returnValue.Append(')'); } returnValue.Append(ReferencedMemberName); @@ -616,24 +617,24 @@ public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(this.Name); - returnValue.Append("{"); + returnValue.Append('{'); if (this.IsGettable) { returnValue.Append("get="); returnValue.Append(GetterCodeReference.Name); - returnValue.Append(";"); + returnValue.Append(';'); } if (this.IsSettable) { returnValue.Append("set="); returnValue.Append(SetterCodeReference.Name); - returnValue.Append(";"); + returnValue.Append(';'); } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -875,6 +876,7 @@ public override PSMemberInfo Copy() /// /// When getting and there is no getter or when the getter throws an exception. /// When setting and there is no setter or when the setter throws an exception. + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "")] public override object Value { get @@ -964,6 +966,7 @@ public override object Value /// Gets the type of the value for this member. /// /// If there is no property getter. + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "")] public override string TypeNameOfValue { get @@ -1274,9 +1277,9 @@ public override string ToString() StringBuilder returnValue = new StringBuilder(); returnValue.Append(GetDisplayTypeNameOfValue(this.Value)); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(this.Name); - returnValue.Append("="); + returnValue.Append('='); returnValue.Append(this.noteValue == null ? "null" : this.noteValue.ToString()); return returnValue.ToString(); } @@ -1421,9 +1424,9 @@ public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(GetDisplayTypeNameOfValue(_variable.Value)); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(_variable.Name); - returnValue.Append("="); + returnValue.Append('='); returnValue.Append(_variable.Value ?? "null"); return returnValue.ToString(); } @@ -1541,24 +1544,24 @@ public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(this.Name); returnValue.Append(" {"); if (this.IsGettable) { returnValue.Append("get="); returnValue.Append(this.GetterScript.ToString()); - returnValue.Append(";"); + returnValue.Append(';'); } if (this.IsSettable) { returnValue.Append("set="); returnValue.Append(this.SetterScript.ToString()); - returnValue.Append(";"); + returnValue.Append(';'); } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -1786,6 +1789,7 @@ public override PSMemberInfo Copy() /// /// When setting and there is no setter, /// when the setter throws an exception or when there is no Runspace to run the script. + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "")] public override object Value { get @@ -1911,12 +1915,12 @@ internal PSMethodInvocationConstraints( } /// - /// If null then there are no constraints + /// If then there are no constraints /// public Type MethodTargetType { get; } /// - /// If null then there are no constraints + /// If then there are no constraints /// public IEnumerable ParameterTypes => _parameterTypes; @@ -1971,7 +1975,7 @@ public bool Equals(PSMethodInvocationConstraints other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) + if (obj is null) { return false; } @@ -2283,7 +2287,7 @@ public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); - returnValue.Append(" "); + returnValue.Append(' '); returnValue.Append(this.Name); returnValue.Append("();"); return returnValue.ToString(); @@ -3038,7 +3042,7 @@ public override string ToString() } returnValue.Insert(0, this.Name); - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -3441,7 +3445,7 @@ public override string ToString() returnValue.Remove(returnValue.Length - 2, 2); } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -3554,7 +3558,7 @@ public override string ToString() StringBuilder eventDefinition = new StringBuilder(); eventDefinition.Append(this.baseEvent.ToString()); - eventDefinition.Append("("); + eventDefinition.Append('('); int loopCounter = 0; foreach (ParameterInfo parameter in baseEvent.EventHandlerType.GetMethod("Invoke").GetParameters()) @@ -3567,7 +3571,7 @@ public override string ToString() loopCounter++; } - eventDefinition.Append(")"); + eventDefinition.Append(')'); return eventDefinition.ToString(); } @@ -3666,7 +3670,7 @@ public override PSMemberInfo Copy() /// /// /// This class is used in PSMemberInfoInternalCollection and ReadOnlyPSMemberInfoCollection. /// - internal class MemberMatch + internal static class MemberMatch { internal static WildcardPattern GetNamePattern(string name) { @@ -3728,7 +3732,7 @@ internal static PSMemberInfoInternalCollection Match(PSMemberInfoInternalC /// A Predicate that determine if a member name matches a criterion. /// /// - /// true if the matches the predicate, otherwise false. + /// if the matches the predicate, otherwise . public delegate bool MemberNamePredicate(string memberName); /// @@ -4970,7 +4974,7 @@ internal override ReadOnlyPSMemberInfoCollection Match(string name, PSMemberT /// The enumerator for this collection. public override IEnumerator GetEnumerator() { - return new Enumerator(this); + return new Enumerator(this); } internal override T FirstOrDefault(MemberNamePredicate predicate) @@ -5024,17 +5028,17 @@ internal override T FirstOrDefault(MemberNamePredicate predicate) /// /// Enumerable for this class. /// - internal struct Enumerator : IEnumerator where S : PSMemberInfo + internal struct Enumerator : IEnumerator { - private S _current; + private T _current; private int _currentIndex; - private readonly PSMemberInfoInternalCollection _allMembers; + private readonly PSMemberInfoInternalCollection _allMembers; /// /// Constructs this instance to enumerate over members. /// /// Members we are enumerating. - internal Enumerator(PSMemberInfoIntegratingCollection integratingCollection) + internal Enumerator(PSMemberInfoIntegratingCollection integratingCollection) { using (PSObject.MemberResolution.TraceScope("Enumeration Start")) { @@ -5066,7 +5070,7 @@ public bool MoveNext() { _currentIndex++; - S member = null; + T member = null; while (_currentIndex < _allMembers.Count) { member = _allMembers[_currentIndex]; @@ -5092,7 +5096,7 @@ public bool MoveNext() /// Current PSMemberInfo in the enumeration. /// /// For invalid arguments. - S IEnumerator.Current + T IEnumerator.Current { get { @@ -5105,7 +5109,7 @@ S IEnumerator.Current } } - object IEnumerator.Current => ((IEnumerator)this).Current; + object IEnumerator.Current => ((IEnumerator)this).Current; void IEnumerator.Reset() { diff --git a/src/System.Management.Automation/engine/MshObject.cs b/src/System.Management.Automation/engine/MshObject.cs index cd7a8cf0a14..7ea7ef1bd72 100644 --- a/src/System.Management.Automation/engine/MshObject.cs +++ b/src/System.Management.Automation/engine/MshObject.cs @@ -164,20 +164,21 @@ private static T AdapterGetFirstMemberOrDefaultDelegate(PSObject msjObj, Memb return retValue; } - internal static PSMemberInfoInternalCollection TransformMemberInfoCollection(PSMemberInfoCollection source) where T : PSMemberInfo where U : PSMemberInfo + internal static PSMemberInfoInternalCollection TransformMemberInfoCollection(PSMemberInfoCollection source) + where TSource : PSMemberInfo where TResult : PSMemberInfo { - if (typeof(T) == typeof(U)) + if (typeof(TSource) == typeof(TResult)) { // If the types are the same, don't make a copy, return the cached collection. - return source as PSMemberInfoInternalCollection; + return source as PSMemberInfoInternalCollection; } - PSMemberInfoInternalCollection returnValue = new PSMemberInfoInternalCollection(); - foreach (T member in source) + PSMemberInfoInternalCollection returnValue = new PSMemberInfoInternalCollection(); + foreach (TSource member in source) { - if (member is U tAsU) + if (member is TResult result) { - returnValue.Add(tAsU); + returnValue.Add(result); } } @@ -588,9 +589,7 @@ protected PSObject(SerializationInfo info, StreamingContext context) throw PSTraceSource.NewArgumentNullException(nameof(info)); } - string serializedData = info.GetValue("CliXml", typeof(string)) as string; - - if (serializedData == null) + if (!(info.GetValue("CliXml", typeof(string)) is string serializedData)) { throw PSTraceSource.NewArgumentNullException(nameof(info)); } @@ -653,6 +652,7 @@ internal static PSObject ConstructPSObjectFromSerializationInfo(SerializationInf new PSObject.AdapterSet(new ThirdPartyAdapter(typeof(Microsoft.Management.Infrastructure.CimInstance), new Microsoft.PowerShell.Cim.CimInstanceAdapter()), PSObject.DotNetInstanceAdapter); + #if !UNIX private static readonly AdapterSet s_managementObjectAdapter = new AdapterSet(new ManagementObjectAdapter(), DotNetInstanceAdapter); private static readonly AdapterSet s_managementClassAdapter = new AdapterSet(new ManagementClassApdapter(), DotNetInstanceAdapter); @@ -948,6 +948,7 @@ public static implicit operator PSObject(int valueToConvert) { return PSObject.AsPSObject(valueToConvert); } + /// /// /// @@ -956,6 +957,7 @@ public static implicit operator PSObject(string valueToConvert) { return PSObject.AsPSObject(valueToConvert); } + /// /// /// @@ -964,6 +966,7 @@ public static implicit operator PSObject(Hashtable valueToConvert) { return PSObject.AsPSObject(valueToConvert); } + /// /// /// @@ -972,6 +975,7 @@ public static implicit operator PSObject(double valueToConvert) { return PSObject.AsPSObject(valueToConvert); } + /// /// /// @@ -988,8 +992,7 @@ public static implicit operator PSObject(bool valueToConvert) /// internal static object Base(object obj) { - PSObject mshObj = obj as PSObject; - if (mshObj == null) + if (!(obj is PSObject mshObj)) { return obj; } @@ -1073,8 +1076,7 @@ internal static PSObject AsPSObject(object obj, bool storeTypeNameAndInstanceMem /// internal static object GetKeyForResurrectionTables(object obj) { - var pso = obj as PSObject; - if (pso == null) + if (!(obj is PSObject pso)) { return obj; } @@ -1175,7 +1177,7 @@ private static string ToStringEmptyBaseObject(ExecutionContext context, PSObject isFirst = false; returnValue.Append(property.Name); - returnValue.Append("="); + returnValue.Append('='); // Don't evaluate script properties during a ToString() operation. var propertyValue = property is PSScriptProperty ? property.GetType().FullName : property.Value; @@ -1188,7 +1190,7 @@ private static string ToStringEmptyBaseObject(ExecutionContext context, PSObject return string.Empty; } - returnValue.Append("}"); + returnValue.Append('}'); return returnValue.ToString(); } @@ -1861,8 +1863,7 @@ internal static object GetNoteSettingValue(PSMemberSet settings, string noteName settings.ReplicateInstance(ownerObject); } - PSNoteProperty note = settings.Members[noteName] as PSNoteProperty; - if (note == null) + if (!(settings.Members[noteName] is PSNoteProperty note)) { return defaultValue; } @@ -2150,7 +2151,7 @@ public override IEnumerable GetDynamicMemberNames() private bool MustDeferIDMOP() { var baseObject = PSObject.Base(Value); - return baseObject is IDynamicMetaObjectProvider && !(baseObject is PSObject); + return baseObject is IDynamicMetaObjectProvider && baseObject is not PSObject; } private DynamicMetaObject DeferForIDMOP(DynamicMetaObjectBinder binder, params DynamicMetaObject[] args) @@ -2538,13 +2539,13 @@ internal static string Type(Type type, bool dropNamespaces = false, string key = { string elementDefinition = Type(type.GetElementType(), dropNamespaces); var sb = new StringBuilder(elementDefinition, elementDefinition.Length + 10); - sb.Append("["); + sb.Append('['); for (int i = 0; i < type.GetArrayRank() - 1; ++i) { - sb.Append(","); + sb.Append(','); } - sb.Append("]"); + sb.Append(']'); result = sb.ToString(); } else diff --git a/src/System.Management.Automation/engine/MshObjectTypeDescriptor.cs b/src/System.Management.Automation/engine/MshObjectTypeDescriptor.cs index 8fe26b1437c..6e941b4c5f1 100644 --- a/src/System.Management.Automation/engine/MshObjectTypeDescriptor.cs +++ b/src/System.Management.Automation/engine/MshObjectTypeDescriptor.cs @@ -92,6 +92,7 @@ internal GettingValueExceptionEventArgs(Exception exception) public class PSObjectPropertyDescriptor : PropertyDescriptor { internal event EventHandler SettingValueException; + internal event EventHandler GettingValueException; internal PSObjectPropertyDescriptor(string propertyName, Type propertyType, bool isReadOnly, AttributeCollection propertyAttributes) @@ -218,13 +219,12 @@ private static PSObject GetComponentPSObject(object component) PSObject mshObj = component as PSObject; if (mshObj == null) { - PSObjectTypeDescriptor descriptor = component as PSObjectTypeDescriptor; - if (descriptor == null) + if (!(component is PSObjectTypeDescriptor descriptor)) { throw PSTraceSource.NewArgumentException(nameof(component), ExtendedTypeSystem.InvalidComponent, "component", - typeof(PSObject).Name, - typeof(PSObjectTypeDescriptor).Name); + nameof(PSObject), + nameof(PSObjectTypeDescriptor)); } mshObj = descriptor.Instance; @@ -467,8 +467,7 @@ public override PropertyDescriptorCollection GetProperties(Attribute[] attribute /// True if the Instance property of is equal to the current Instance; otherwise, false. public override bool Equals(object obj) { - PSObjectTypeDescriptor other = obj as PSObjectTypeDescriptor; - if (other == null) + if (!(obj is PSObjectTypeDescriptor other)) { return false; } @@ -771,4 +770,3 @@ public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object } } } - diff --git a/src/System.Management.Automation/engine/MshReference.cs b/src/System.Management.Automation/engine/MshReference.cs index 05077708608..a021e09f794 100644 --- a/src/System.Management.Automation/engine/MshReference.cs +++ b/src/System.Management.Automation/engine/MshReference.cs @@ -88,4 +88,3 @@ public PSReference(object value) : base(value) } } } - diff --git a/src/System.Management.Automation/engine/MshSecurityException.cs b/src/System.Management.Automation/engine/MshSecurityException.cs index 878de10e2b4..6ba04e4af7c 100644 --- a/src/System.Management.Automation/engine/MshSecurityException.cs +++ b/src/System.Management.Automation/engine/MshSecurityException.cs @@ -118,7 +118,6 @@ public override string Message get { return _message; } } - private string _message; + private readonly string _message; } } - diff --git a/src/System.Management.Automation/engine/MshSnapinQualifiedName.cs b/src/System.Management.Automation/engine/MshSnapinQualifiedName.cs index b23df2202eb..08115648527 100644 --- a/src/System.Management.Automation/engine/MshSnapinQualifiedName.cs +++ b/src/System.Management.Automation/engine/MshSnapinQualifiedName.cs @@ -10,7 +10,7 @@ namespace System.Management.Automation /// /// A class representing a name that is qualified by the PSSnapin name. /// - internal class PSSnapinQualifiedName + internal sealed class PSSnapinQualifiedName { private PSSnapinQualifiedName(string[] splitName) { @@ -132,4 +132,3 @@ public override string ToString() } } } - diff --git a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs index 6d987334922..511449bc7e5 100644 --- a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs +++ b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.Collections; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; @@ -19,6 +20,8 @@ namespace System.Management.Automation /// internal class NativeCommandParameterBinder : ParameterBinderBase { + private readonly VariablePath s_nativeArgumentPassingVarPath = new VariablePath(SpecialVariables.NativeArgumentPassing); + #region ctor /// @@ -82,7 +85,7 @@ internal void BindParameters(Collection parameters) if (parameter.ParameterNameSpecified) { Diagnostics.Assert(!parameter.ParameterText.Contains(' '), "Parameters cannot have whitespace"); - PossiblyGlobArg(parameter.ParameterText, StringConstantType.BareWord); + PossiblyGlobArg(parameter.ParameterText, parameter, StringConstantType.BareWord); if (parameter.SpaceAfterParameter) { @@ -122,7 +125,15 @@ internal void BindParameters(Collection parameters) break; } - AppendOneNativeArgument(Context, argValue, arrayLiteralAst, sawVerbatimArgumentMarker, stringConstantType); + // Prior to PSNativePSPathResolution experimental feature, a single quote worked the same as a double quote + // so if the feature is not enabled, we treat any quotes as double quotes. When this feature is no longer + // experimental, this code here needs to be removed. + if (!ExperimentalFeature.IsEnabled("PSNativePSPathResolution") && stringConstantType == StringConstantType.SingleQuoted) + { + stringConstantType = StringConstantType.DoubleQuoted; + } + + AppendOneNativeArgument(Context, parameter, argValue, arrayLiteralAst, sawVerbatimArgumentMarker, stringConstantType); } } } @@ -143,6 +154,65 @@ internal string Arguments private readonly StringBuilder _arguments = new StringBuilder(); + internal string[] ArgumentList + { + get + { + return _argumentList.ToArray(); + } + } + + /// + /// Add an argument to the ArgumentList. + /// We may need to construct the argument out of the parameter text and the argument + /// in the case that we have a parameter that appears as "-switch:value". + /// + /// The parameter associated with the operation. + /// The value used with parameter. + internal void AddToArgumentList(CommandParameterInternal parameter, string argument) + { + if (parameter.ParameterNameSpecified && parameter.ParameterText.EndsWith(":")) + { + if (argument != parameter.ParameterText) + { + _argumentList.Add(parameter.ParameterText + argument); + } + } + else + { + _argumentList.Add(argument); + } + } + + private readonly List _argumentList = new List(); + + /// + /// Gets a value indicating whether to use an ArgumentList or string for arguments when invoking a native executable. + /// + internal NativeArgumentPassingStyle ArgumentPassingStyle + { + get + { + if (ExperimentalFeature.IsEnabled("PSNativeCommandArgumentPassing")) + { + try + { + // This will default to the new behavior if it is set to anything other than Legacy + var preference = LanguagePrimitives.ConvertTo( + Context.GetVariableValue(s_nativeArgumentPassingVarPath, NativeArgumentPassingStyle.Standard)); + return preference; + } + catch + { + // The value is not convertable send back Legacy + return NativeArgumentPassingStyle.Legacy; + } + } + + return NativeArgumentPassingStyle.Legacy; + } + } + #endregion internal members #region private members @@ -153,24 +223,27 @@ internal string Arguments /// each of which will be stringized. /// /// Execution context instance. + /// The parameter associated with the operation. /// The object to append. /// If the argument was an array literal, the Ast, otherwise null. /// True if the argument occurs after --%. /// Bare, SingleQuoted, or DoubleQuoted. - private void AppendOneNativeArgument(ExecutionContext context, object obj, ArrayLiteralAst argArrayAst, bool sawVerbatimArgumentMarker, StringConstantType stringConstantType) + private void AppendOneNativeArgument(ExecutionContext context, CommandParameterInternal parameter, object obj, ArrayLiteralAst argArrayAst, bool sawVerbatimArgumentMarker, StringConstantType stringConstantType) { IEnumerator list = LanguagePrimitives.GetEnumerator(obj); - Diagnostics.Assert((argArrayAst == null) || obj is object[] && ((object[])obj).Length == argArrayAst.Elements.Count, "array argument and ArrayLiteralAst differ in number of elements"); + Diagnostics.Assert((argArrayAst == null) || (obj is object[] && ((object[])obj).Length == argArrayAst.Elements.Count), "array argument and ArrayLiteralAst differ in number of elements"); int currentElement = -1; string separator = string.Empty; do { string arg; + object currentObj; if (list == null) { arg = PSObject.ToStringParser(context, obj); + currentObj = obj; } else { @@ -179,7 +252,8 @@ private void AppendOneNativeArgument(ExecutionContext context, object obj, Array break; } - arg = PSObject.ToStringParser(context, ParserOps.Current(null, list)); + currentObj = ParserOps.Current(null, list); + arg = PSObject.ToStringParser(context, currentObj); currentElement += 1; if (currentElement != 0) @@ -190,12 +264,16 @@ private void AppendOneNativeArgument(ExecutionContext context, object obj, Array if (!string.IsNullOrEmpty(arg)) { + // Only add the separator to the argument string rather than adding a separator to the ArgumentList. _arguments.Append(separator); if (sawVerbatimArgumentMarker) { arg = Environment.ExpandEnvironmentVariables(arg); _arguments.Append(arg); + + // we need to split the argument on spaces + _argumentList.AddRange(arg.Split(' ', StringSplitOptions.RemoveEmptyEntries)); } else { @@ -219,10 +297,12 @@ private void AppendOneNativeArgument(ExecutionContext context, object obj, Array if (stringConstantType == StringConstantType.DoubleQuoted) { _arguments.Append(ResolvePath(arg, Context)); + AddToArgumentList(parameter, ResolvePath(arg, Context)); } else { _arguments.Append(arg); + AddToArgumentList(parameter, arg); } // need to escape all trailing backslashes so the native command receives it correctly @@ -236,10 +316,28 @@ private void AppendOneNativeArgument(ExecutionContext context, object obj, Array } else { - PossiblyGlobArg(arg, stringConstantType); + if (argArrayAst != null && ArgumentPassingStyle == NativeArgumentPassingStyle.Standard) + { + // We have a literal array, so take the extent, break it on spaces and add them to the argument list. + foreach (string element in argArrayAst.Extent.Text.Split(' ', StringSplitOptions.RemoveEmptyEntries)) + { + PossiblyGlobArg(element, parameter, stringConstantType); + } + + break; + } + else + { + PossiblyGlobArg(arg, parameter, stringConstantType); + } } } } + else if (ArgumentPassingStyle == NativeArgumentPassingStyle.Standard && currentObj != null) + { + // add empty strings to arglist, but not nulls + AddToArgumentList(parameter, arg); + } } while (list != null); } @@ -249,8 +347,9 @@ private void AppendOneNativeArgument(ExecutionContext context, object obj, Array /// On Unix, do globbing as appropriate, otherwise just append . /// /// The argument that possibly needs expansion. + /// The parameter associated with the operation. /// Bare, SingleQuoted, or DoubleQuoted. - private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) + private void PossiblyGlobArg(string arg, CommandParameterInternal parameter, StringConstantType stringConstantType) { var argExpanded = false; @@ -284,7 +383,7 @@ private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) } // Expand paths, but only from the file system. - if (paths?.Count > 0 && paths.All(p => p.BaseObject is FileSystemInfo)) + if (paths?.Count > 0 && paths.All(static p => p.BaseObject is FileSystemInfo)) { var sep = string.Empty; foreach (var path in paths) @@ -300,13 +399,15 @@ private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) // If the path contains spaces, then add quotes around it. if (NeedQuotes(expandedPath)) { - _arguments.Append("\""); + _arguments.Append('"'); _arguments.Append(expandedPath); - _arguments.Append("\""); + _arguments.Append('"'); + AddToArgumentList(parameter, expandedPath); } else { _arguments.Append(expandedPath); + AddToArgumentList(parameter, expandedPath); } argExpanded = true; @@ -323,12 +424,14 @@ private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) if (string.Equals(arg, "~")) { _arguments.Append(home); + AddToArgumentList(parameter, home); argExpanded = true; } else if (arg.StartsWith("~/", StringComparison.OrdinalIgnoreCase)) { - var replacementString = home + arg.Substring(1); + string replacementString = string.Concat(home, arg.AsSpan(1)); _arguments.Append(replacementString); + AddToArgumentList(parameter, replacementString); argExpanded = true; } } @@ -343,6 +446,7 @@ private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) if (!argExpanded) { _arguments.Append(arg); + AddToArgumentList(parameter, arg); } } @@ -354,55 +458,58 @@ private void PossiblyGlobArg(string arg, StringConstantType stringConstantType) /// Resolved PSPath if applicable otherwise the original path internal static string ResolvePath(string path, ExecutionContext context) { -#if !UNIX - // on Windows, we need to expand ~ to point to user's home path - if (string.Equals(path, "~", StringComparison.Ordinal) || path.StartsWith(TildeDirectorySeparator, StringComparison.Ordinal) || path.StartsWith(TildeAltDirectorySeparator, StringComparison.Ordinal)) + if (ExperimentalFeature.IsEnabled("PSNativePSPathResolution")) { - try - { - ProviderInfo fileSystemProvider = context.EngineSessionState.GetSingleProvider(FileSystemProvider.ProviderName); - return new StringBuilder(fileSystemProvider.Home) - .Append(path.Substring(1)) - .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) - .ToString(); - } - catch +#if !UNIX + // on Windows, we need to expand ~ to point to user's home path + if (string.Equals(path, "~", StringComparison.Ordinal) || path.StartsWith(TildeDirectorySeparator, StringComparison.Ordinal) || path.StartsWith(TildeAltDirectorySeparator, StringComparison.Ordinal)) { - return path; + try + { + ProviderInfo fileSystemProvider = context.EngineSessionState.GetSingleProvider(FileSystemProvider.ProviderName); + return new StringBuilder(fileSystemProvider.Home) + .Append(path.AsSpan(1)) + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) + .ToString(); + } + catch + { + return path; + } } - } - // check if the driveName is an actual disk drive on Windows, if so, no expansion - if (path.Length >= 2 && path[1] == ':') - { - foreach (var drive in DriveInfo.GetDrives()) + // check if the driveName is an actual disk drive on Windows, if so, no expansion + if (path.Length >= 2 && path[1] == ':') { - if (drive.Name.StartsWith(new string(path[0], 1), StringComparison.OrdinalIgnoreCase)) + foreach (var drive in DriveInfo.GetDrives()) { - return path; + if (drive.Name.StartsWith(new string(path[0], 1), StringComparison.OrdinalIgnoreCase)) + { + return path; + } } } - } #endif - if (path.Contains(':')) - { - LocationGlobber globber = new LocationGlobber(context.SessionState); - try + if (path.Contains(':')) { - ProviderInfo providerInfo; + LocationGlobber globber = new LocationGlobber(context.SessionState); + try + { + ProviderInfo providerInfo; - // replace the argument with resolved path if it's a filesystem path - string pspath = globber.GetProviderPath(path, out providerInfo); - if (string.Equals(providerInfo.Name, FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase)) + // replace the argument with resolved path if it's a filesystem path + string pspath = globber.GetProviderPath(path, out providerInfo); + if (string.Equals(providerInfo.Name, FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase)) + { + path = pspath; + } + } + catch { - path = pspath; + // if it's not a provider path, do nothing } } - catch - { - // if it's not a provider path, do nothing - } } return path; @@ -461,7 +568,7 @@ private static string GetEnumerableArgSeparator(ArrayLiteralAst arrayLiteralAst, /// /// The native command to bind to. /// - private NativeCommand _nativeCommand; + private readonly NativeCommand _nativeCommand; private static readonly string TildeDirectorySeparator = $"~{Path.DirectorySeparatorChar}"; private static readonly string TildeAltDirectorySeparator = $"~{Path.AltDirectorySeparatorChar}"; diff --git a/src/System.Management.Automation/engine/NativeCommandParameterBinderController.cs b/src/System.Management.Automation/engine/NativeCommandParameterBinderController.cs index 5acdf199637..9a1dab71beb 100644 --- a/src/System.Management.Automation/engine/NativeCommandParameterBinderController.cs +++ b/src/System.Management.Automation/engine/NativeCommandParameterBinderController.cs @@ -38,6 +38,28 @@ internal string Arguments } } + /// + /// Gets the value of the command arguments as an array of strings. + /// + internal string[] ArgumentList + { + get + { + return ((NativeCommandParameterBinder)DefaultParameterBinder).ArgumentList; + } + } + + /// + /// Gets the value indicating what type of native argument binding to use. + /// + internal NativeArgumentPassingStyle ArgumentPassingStyle + { + get + { + return ((NativeCommandParameterBinder)DefaultParameterBinder).ArgumentPassingStyle; + } + } + /// /// Passes the binding directly through to the parameter binder. /// It does no verification against metadata. @@ -49,8 +71,7 @@ internal string Arguments /// Ignored. /// /// - /// True if the parameter was successfully bound. Any error condition - /// produces an exception. + /// True if the parameter was successfully bound. Any error condition produces an exception. /// internal override bool BindParameter( CommandParameterInternal argument, @@ -83,4 +104,3 @@ internal override Collection BindParameters(Collection private static readonly Collection s_emptyReturnCollection = new Collection(); } } - diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs index b9c101edcd4..83d76df5d4f 100644 --- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs +++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs @@ -32,7 +32,7 @@ internal enum NativeCommandIOFormat { Text, Xml - }; + } /// /// Different streams produced by minishell output. @@ -135,13 +135,33 @@ internal ProcessOutputObject(object data, MinishellStream stream) /// internal class NativeCommandProcessor : CommandProcessorBase { + // This is the list of files which will trigger Legacy behavior if + // PSNativeCommandArgumentPassing is set to "Windows". + private static readonly IReadOnlySet s_legacyFileExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) + { + ".js", + ".wsf", + ".cmd", + ".bat", + ".vbs", + }; + + // The following native commands have non-standard behavior with regard to argument passing, + // so we use Legacy argument parsing for them when PSNativeCommandArgumentPassing is set to Windows. + private static readonly IReadOnlySet s_legacyCommands = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "cmd", + "cscript", + "wscript", + }; + #region ctor/native command properties /// /// Information about application which is invoked by this instance of /// NativeCommandProcessor. /// - private ApplicationInfo _applicationInfo; + private readonly ApplicationInfo _applicationInfo; /// /// Initializes the new instance of NativeCommandProcessor class. @@ -221,29 +241,6 @@ private string Path } } - /// - /// Gets true if Path is Console Application. - /// - private bool IsConsoleApplication => !IsWindowsApplication; - - /// - /// Gets true if Path is Windows Application. - /// - private bool IsWindowsApplication - { - get - { - if (!_isWindowsApplication.HasValue) - { - _isWindowsApplication = CheckIfWindowsApplication(Path); - } - - return _isWindowsApplication.Value; - } - } - - private bool? _isWindowsApplication; - #endregion ctor/native command properties #region parameter binder @@ -364,7 +361,7 @@ internal override void ProcessRecord() /// /// This is used for writing input to the process. /// - private ProcessInputWriter _inputWriter = null; + private readonly ProcessInputWriter _inputWriter = null; /// /// Is true if this command is to be run "standalone" - that is, with @@ -380,7 +377,7 @@ internal override void ProcessRecord() /// /// Indicate if we have called 'NotifyBeginApplication()' on the host, so that - /// we can call the counterpart 'NotifyEndApplication' as approriate. + /// we can call the counterpart 'NotifyEndApplication' as appropriate. /// private bool _hasNotifiedBeginApplication; @@ -392,14 +389,14 @@ internal override void ProcessRecord() private BlockingCollection _nativeProcessOutputQueue; private static bool? s_supportScreenScrape = null; - private bool _isTranscribing; + private readonly bool _isTranscribing; private Host.Coordinates _startPosition; /// /// Object used for synchronization between StopProcessing thread and /// Pipeline thread. /// - private object _sync = new object(); + private readonly object _sync = new object(); /// /// Executes the native command once all of the input has been gathered. @@ -423,7 +420,8 @@ private void InitNativeProcess() _startPosition = new Host.Coordinates(); - CalculateIORedirection(out redirectOutput, out redirectError, out redirectInput); + bool isWindowsApplication = IsWindowsApplication(this.Path); + CalculateIORedirection(isWindowsApplication, out redirectOutput, out redirectError, out redirectInput); // Find out if it's the only command in the pipeline. bool soloCommand = this.Command.MyInvocation.PipelineLength == 1; @@ -462,7 +460,7 @@ private void InitNativeProcess() // Also, store the Raw UI coordinates so that we can scrape the screen after // if we are transcribing. - if (_isTranscribing && (true == s_supportScreenScrape)) + if (_isTranscribing && (s_supportScreenScrape == true)) { _startPosition = this.Command.Context.EngineHostInterface.UI.RawUI.CursorPosition; _startPosition.X = 0; @@ -496,9 +494,11 @@ private void InitNativeProcess() // on Windows desktops, see if there is a file association for this command. If so then we'll use that. string executable = FindExecutable(startInfo.FileName); bool notDone = true; + // check to see what mode we should be in for argument passing if (!string.IsNullOrEmpty(executable)) { - if (CheckIfConsoleApplication(executable)) + isWindowsApplication = IsWindowsApplication(executable); + if (!isWindowsApplication) { // Allocate a console if there isn't one attached already... ConsoleVisibility.AllocateHiddenConsole(); @@ -506,7 +506,16 @@ private void InitNativeProcess() string oldArguments = startInfo.Arguments; string oldFileName = startInfo.FileName; - startInfo.Arguments = "\"" + startInfo.FileName + "\" " + startInfo.Arguments; + // Check to see whether this executable should be using Legacy mode argument parsing + bool useSpecialArgumentPassing = UseSpecialArgumentPassing(oldFileName); + if (useSpecialArgumentPassing) + { + startInfo.Arguments = "\"" + oldFileName + "\" " + startInfo.Arguments; + } + else + { + startInfo.ArgumentList.Insert(0, oldFileName); + } startInfo.FileName = executable; try { @@ -516,7 +525,14 @@ private void InitNativeProcess() catch (Win32Exception) { // Restore the old filename and arguments to try shell execute last... - startInfo.Arguments = oldArguments; + if (useSpecialArgumentPassing) + { + startInfo.Arguments = oldArguments; + } + else + { + startInfo.ArgumentList.RemoveAt(0); + } startInfo.FileName = oldFileName; } } @@ -525,7 +541,7 @@ private void InitNativeProcess() // we will try launching one last time using ShellExecute... if (notDone) { - if (soloCommand && startInfo.UseShellExecute == false) + if (soloCommand && !startInfo.UseShellExecute) { startInfo.UseShellExecute = true; startInfo.RedirectStandardInput = false; @@ -552,9 +568,9 @@ private void InitNativeProcess() else { _isRunningInBackground = true; - if (startInfo.UseShellExecute == false) + if (!startInfo.UseShellExecute) { - _isRunningInBackground = IsWindowsApplication; + _isRunningInBackground = isWindowsApplication; } } @@ -584,7 +600,7 @@ private void InitNativeProcess() throw; } - if (_isRunningInBackground == false) + if (!_isRunningInBackground) { InitOutputQueue(); } @@ -675,7 +691,7 @@ private ProcessOutputObject DequeueProcessOutput(bool blocking) /// private void ConsumeAvailableNativeProcessOutput(bool blocking) { - if (_isRunningInBackground == false) + if (!_isRunningInBackground) { if (_nativeProcess.StartInfo.RedirectStandardOutput || _nativeProcess.StartInfo.RedirectStandardError) { @@ -699,7 +715,7 @@ internal override void Complete() Exception exceptionToRethrow = null; try { - if (_isRunningInBackground == false) + if (!_isRunningInBackground) { // Wait for input writer to finish. _inputWriter.Done(); @@ -709,7 +725,7 @@ internal override void Complete() _nativeProcess.WaitForExit(); // Capture screen output if we are transcribing and running stand alone - if (_isTranscribing && (true == s_supportScreenScrape) && _runStandAlone) + if (_isTranscribing && (s_supportScreenScrape == true) && _runStandAlone) { Host.Coordinates endPosition = this.Command.Context.EngineHostInterface.UI.RawUI.CursorPosition; endPosition.X = this.Command.Context.EngineHostInterface.UI.RawUI.BufferSize.Width - 1; @@ -845,7 +861,7 @@ public int ParentId get { // Construct parent id only once. - if (int.MinValue == _parentId) + if (_parentId == int.MinValue) { ConstructParentId(); } @@ -952,36 +968,41 @@ private static void KillChildProcesses(int parentId, ProcessWithParentId[] curre #region checkForConsoleApplication - /// - /// Return true if the passed in process is a console process. - /// - /// - /// - private static bool CheckIfConsoleApplication(string fileName) - { - return !CheckIfWindowsApplication(fileName); - } - /// /// Check if the passed in process is a windows application. /// /// /// [ArchitectureSensitive] - private static bool CheckIfWindowsApplication(string fileName) + private static bool IsWindowsApplication(string fileName) { #if UNIX return false; #else - if (!Platform.IsWindowsDesktop) { return false; } + if (!Platform.IsWindowsDesktop) + { + return false; + } - // SHGetFileInfo() does not understand reparse points and returns 0 ("non exe or error") - // so we are trying to get a real path before. - // It is a workaround for Microsoft Store applications. - string realPath = Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods.WinInternalGetTarget(fileName); - if (realPath is not null) + // The function 'SHGetFileInfo()' does not understand reparse points and returns 0 ("non exe or error") + // for a symbolic link file, so we try to get the immediate link target in that case. + // Why not get the final target (use 'returnFinalTarget: true')? Because: + // 1. When starting a process on Windows, if the 'FileName' is a symbolic link, the immediate link target will automatically be used, + // but the OS does not do recursive resolution when the immediate link target is also a symbolic link. + // 2. Keep the same behavior as before adopting the 'LinkTarget' and 'ResolveLinkTarget' APIs in .NET 6. + try + { + string linkTarget = File.ResolveLinkTarget(fileName, returnFinalTarget: false)?.FullName; + if (linkTarget is not null) + { + fileName = linkTarget; + } + } + catch { - fileName = realPath; + // An exception may be thrown from 'File.ResolveLinkTarget' when it fails to resolve a link path, + // for example, when the underlying file system doesn't support reparse points. + // Just use the original file name in this case. } SHFILEINFO shinfo = new SHFILEINFO(); @@ -1049,9 +1070,21 @@ private void CleanUp() try { - // Dispose the process if it's already created if (_nativeProcess != null) { + // on Unix, we need to kill the process to ensure it terminates as Dispose() merely + // closes the redirected streams and the processs does not exit on macOS. However, + // on Windows, a winexe like notepad should continue running so we don't want to kill it. +#if UNIX + try + { + _nativeProcess.Kill(); + } + catch + { + // Ignore all exception since it is cleanup. + } +#endif _nativeProcess.Dispose(); } } @@ -1127,56 +1160,81 @@ private void ProcessOutputRecord(ProcessOutputObject outputValue) } /// - /// Gets the start info for process. + /// Get whether we should treat this executable with special handling and use the legacy passing style. /// - /// - /// - /// - /// - /// - private ProcessStartInfo GetProcessStartInfo(bool redirectOutput, bool redirectError, bool redirectInput, bool soloCommand) + /// + private bool UseSpecialArgumentPassing(string filePath) => + NativeParameterBinderController.ArgumentPassingStyle switch + { + NativeArgumentPassingStyle.Legacy => true, + NativeArgumentPassingStyle.Windows => ShouldUseLegacyPassingStyle(filePath), + _ => false + }; + + /// + /// Gets the ProcessStartInfo for process. + /// + /// A boolean that indicates that, when true, output from the process is redirected to a stream, and otherwise is sent to stdout. + /// A boolean that indicates that, when true, error output from the process is redirected to a stream, and otherwise is sent to stderr. + /// A boolean that indicates that, when true, input to the process is taken from a stream, and otherwise is taken from stdin. + /// A boolean that indicates, when true, that the command to be executed is not part of a pipeline, and otherwise indicates that is is. + /// A ProcessStartInfo object which is the base of the native invocation. + private ProcessStartInfo GetProcessStartInfo( + bool redirectOutput, + bool redirectError, + bool redirectInput, + bool soloCommand) { - ProcessStartInfo startInfo = new ProcessStartInfo(); - startInfo.FileName = this.Path; + var startInfo = new ProcessStartInfo + { + FileName = this.Path + }; - if (IsExecutable(this.Path)) + if (!IsExecutable(this.Path)) { - startInfo.UseShellExecute = false; - if (redirectInput) + if (Platform.IsNanoServer || Platform.IsIoT) { - startInfo.RedirectStandardInput = true; + // Shell doesn't exist on headless SKUs, so documents cannot be associated with an application. + // Therefore, we cannot run document in this case. + throw InterpreterError.NewInterpreterException( + this.Path, + typeof(RuntimeException), + this.Command.InvocationExtent, + "CantActivateDocumentInPowerShellCore", + ParserStrings.CantActivateDocumentInPowerShellCore, + this.Path); } - if (redirectOutput) + // We only want to ShellExecute something that is standalone... + if (!soloCommand) { - startInfo.RedirectStandardOutput = true; - startInfo.StandardOutputEncoding = Console.OutputEncoding; + throw InterpreterError.NewInterpreterException( + this.Path, + typeof(RuntimeException), + this.Command.InvocationExtent, + "CantActivateDocumentInPipeline", + ParserStrings.CantActivateDocumentInPipeline, + this.Path); } - if (redirectError) - { - startInfo.RedirectStandardError = true; - startInfo.StandardErrorEncoding = Console.OutputEncoding; - } + startInfo.UseShellExecute = true; } else { - if (Platform.IsNanoServer || Platform.IsIoT) + startInfo.UseShellExecute = false; + startInfo.RedirectStandardInput = redirectInput; + + if (redirectOutput) { - // Shell doesn't exist on headless SKUs, so documents cannot be associated with an application. - // Therefore, we cannot run document in this case. - throw InterpreterError.NewInterpreterException(this.Path, typeof(RuntimeException), - this.Command.InvocationExtent, "CantActivateDocumentInPowerShellCore", ParserStrings.CantActivateDocumentInPowerShellCore, this.Path); + startInfo.RedirectStandardOutput = true; + startInfo.StandardOutputEncoding = Console.OutputEncoding; } - // We only want to ShellExecute something that is standalone... - if (!soloCommand) + if (redirectError) { - throw InterpreterError.NewInterpreterException(this.Path, typeof(RuntimeException), - this.Command.InvocationExtent, "CantActivateDocumentInPipeline", ParserStrings.CantActivateDocumentInPipeline, this.Path); + startInfo.RedirectStandardError = true; + startInfo.StandardErrorEncoding = Console.OutputEncoding; } - - startInfo.UseShellExecute = true; } // For minishell value of -outoutFormat parameter depends on value of redirectOutput. @@ -1184,23 +1242,67 @@ private ProcessStartInfo GetProcessStartInfo(bool redirectOutput, bool redirectE if (_isMiniShell) { MinishellParameterBinderController mpc = (MinishellParameterBinderController)NativeParameterBinderController; - mpc.BindParameters(arguments, redirectOutput, this.Command.Context.EngineHostInterface.Name); + mpc.BindParameters(arguments, startInfo.RedirectStandardOutput, this.Command.Context.EngineHostInterface.Name); startInfo.CreateNoWindow = mpc.NonInteractive; } - startInfo.Arguments = NativeParameterBinderController.Arguments; - ExecutionContext context = this.Command.Context; + // We provide the user a way to select the new behavior via a new preference variable + using (ParameterBinderBase.bindingTracer.TraceScope("BIND NAMED native application line args [{0}]", this.Path)) + { + // We need to check if we're using legacy argument passing or it's a special case. + if (UseSpecialArgumentPassing(startInfo.FileName)) + { + using (ParameterBinderBase.bindingTracer.TraceScope("BIND argument [{0}]", NativeParameterBinderController.Arguments)) + { + startInfo.Arguments = NativeParameterBinderController.Arguments; + } + } + else + { + // Use new API for running native application + int position = 0; + foreach (string nativeArgument in NativeParameterBinderController.ArgumentList) + { + if (nativeArgument != null) + { + using (ParameterBinderBase.bindingTracer.TraceScope("BIND cmd line arg [{0}] to position [{1}]", nativeArgument, position++)) + { + startInfo.ArgumentList.Add(nativeArgument); + } + } + } + } + } + // Start command in the current filesystem directory string rawPath = context.EngineSessionState.GetNamespaceCurrentLocation( context.ProviderNames.FileSystem).ProviderPath; startInfo.WorkingDirectory = WildcardPattern.Unescape(rawPath); + return startInfo; } - private bool IsDownstreamOutDefault(Pipe downstreamPipe) + /// + /// Determine if we have a special file which will change the way native argument passing + /// is done on Windows. We use legacy behavior for cmd.exe, .bat, .cmd files. + /// + /// The file to use when checking how to pass arguments. + /// A boolean indicating what passing style should be used. + private static bool ShouldUseLegacyPassingStyle(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + return false; + } + + return s_legacyFileExtensions.Contains(IO.Path.GetExtension(filePath)) + || s_legacyCommands.Contains(IO.Path.GetFileNameWithoutExtension(filePath)); + } + + private static bool IsDownstreamOutDefault(Pipe downstreamPipe) { Diagnostics.Assert(downstreamPipe != null, "Caller makes sure the passed-in parameter is not null."); @@ -1227,10 +1329,11 @@ private bool IsDownstreamOutDefault(Pipe downstreamPipe) /// /// This method calculates if input and output of the process are redirected. /// + /// /// /// /// - private void CalculateIORedirection(out bool redirectOutput, out bool redirectError, out bool redirectInput) + private void CalculateIORedirection(bool isWindowsApplication, out bool redirectOutput, out bool redirectError, out bool redirectInput) { redirectInput = this.Command.MyInvocation.ExpectingInput; redirectOutput = true; @@ -1281,7 +1384,7 @@ private void CalculateIORedirection(out bool redirectOutput, out bool redirectEr // In minishell scenario, if output is redirected // then error should also be redirected. - if (redirectError == false && redirectOutput && _isMiniShell) + if (!redirectError && redirectOutput && _isMiniShell) { redirectError = true; } @@ -1301,7 +1404,7 @@ private void CalculateIORedirection(out bool redirectOutput, out bool redirectEr redirectOutput = true; redirectError = true; } - else if (Platform.IsWindowsDesktop && IsConsoleApplication) + else if (Platform.IsWindowsDesktop && !isWindowsApplication) { // On Windows desktops, if the command to run is a console application, // then allocate a console if there isn't one attached already... @@ -1335,7 +1438,7 @@ private void CalculateIORedirection(out bool redirectOutput, out bool redirectEr // if screen scraping isn't supported, we enable redirection so that the output is still transcribed // as redirected output is always transcribed - if (_isTranscribing && (false == s_supportScreenScrape)) + if (_isTranscribing && (s_supportScreenScrape == false)) { redirectOutput = true; redirectError = true; @@ -1346,6 +1449,10 @@ private void CalculateIORedirection(out bool redirectOutput, out bool redirectEr // On Windows, check the extension list and see if we should try to execute this directly. // Otherwise, use the platform library to check executability + [SuppressMessage( + "Performance", + "CA1822:Mark members as static", + Justification = "Accesses instance members in preprocessor branch.")] private bool IsExecutable(string path) { #if UNIX @@ -1449,7 +1556,7 @@ private struct SHFILEINFO [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; - }; + } private const uint SHGFI_EXETYPE = 0x000002000; // flag used to ask to return exe type @@ -1497,12 +1604,12 @@ internal class ProcessOutputHandler internal const string XmlCliTag = "#< CLIXML"; private int _refCount; - private BlockingCollection _queue; + private readonly BlockingCollection _queue; private bool _isFirstOutput; private bool _isFirstError; private bool _isXmlCliOutput; private bool _isXmlCliError; - private string _processFileName; + private readonly string _processFileName; public ProcessOutputHandler(Process process, BlockingCollection queue) { @@ -1743,7 +1850,7 @@ internal class ProcessInputWriter { #region constructor - private InternalCommand _command; + private readonly InternalCommand _command; /// /// Creates an instance of ProcessInputWriter. /// @@ -2176,10 +2283,10 @@ protected RemoteException(SerializationInfo info, StreamingContext context) #endregion [NonSerialized] - private PSObject _serializedRemoteException; + private readonly PSObject _serializedRemoteException; [NonSerialized] - private PSObject _serializedRemoteInvocationInfo; + private readonly PSObject _serializedRemoteInvocationInfo; /// /// Original Serialized Exception from remote msh. diff --git a/src/System.Management.Automation/engine/PSClassSearcher.cs b/src/System.Management.Automation/engine/PSClassSearcher.cs index 613035820d0..ce47ae93e16 100644 --- a/src/System.Management.Automation/engine/PSClassSearcher.cs +++ b/src/System.Management.Automation/engine/PSClassSearcher.cs @@ -33,14 +33,14 @@ internal PSClassSearcher( #region private properties - private string _className = null; - private ExecutionContext _context = null; + private readonly string _className = null; + private readonly ExecutionContext _context = null; private PSClassInfo _currentMatch = null; private IEnumerator _matchingClass = null; private Collection _matchingClassList = null; - private bool _useWildCards = false; - private Dictionary _moduleInfoCache = null; - private object _lockObject = new object(); + private readonly bool _useWildCards = false; + private readonly Dictionary _moduleInfoCache = null; + private readonly object _lockObject = new object(); #endregion @@ -288,7 +288,7 @@ private Collection GetPSModuleInfo(string modulePath) return modules; } - private PSClassInfo ConvertToClassInfo(PSModuleInfo module, ScriptBlockAst ast, TypeDefinitionAst statement) + private static PSClassInfo ConvertToClassInfo(PSModuleInfo module, ScriptBlockAst ast, TypeDefinitionAst statement) { PSClassInfo classInfo = new PSClassInfo(statement.Name); Dbg.Assert(statement.Name != null, "statement should have a name."); diff --git a/src/System.Management.Automation/engine/PSConfiguration.cs b/src/System.Management.Automation/engine/PSConfiguration.cs index aacf5c50e32..16273979a69 100644 --- a/src/System.Management.Automation/engine/PSConfiguration.cs +++ b/src/System.Management.Automation/engine/PSConfiguration.cs @@ -174,7 +174,7 @@ internal void SetExecutionPolicy(ConfigScope scope, string shellId, string execu WriteValueToFile(scope, key, executionPolicy); } - private string GetExecutionPolicySettingKey(string shellId) + private static string GetExecutionPolicySettingKey(string shellId) { return string.Equals(shellId, Utils.DefaultPowerShellShellID, StringComparison.Ordinal) ? ExecutionPolicyDefaultShellKey @@ -290,12 +290,12 @@ internal PSLevel GetLogLevel() /// /// The supported separator characters for listing channels and keywords in configuration. /// - static readonly char[] s_valueSeparators = new char[] {' ', ',', '|'}; + private static readonly char[] s_valueSeparators = new char[] {' ', ',', '|'}; /// /// Provides a string name to indicate the default for a configuration setting. /// - const string LogDefaultValue = "default"; + private const string LogDefaultValue = "default"; /// /// Gets the bitmask of the PSChannel values to log. @@ -402,6 +402,10 @@ private T ReadValueFromFile(ConfigScope scope, string key, T defaultValue = d configData = serializer.Deserialize(jsonReader) ?? emptyConfig; } + catch (Exception exc) + { + throw PSTraceSource.NewInvalidOperationException(exc, PSConfigurationStrings.CanNotConfigurationFile, args: fileName); + } finally { fileLock.ExitReadLock(); @@ -562,7 +566,7 @@ private void UpdateValueInFile(ConfigScope scope, string key, T value, bool a /// The value to write. private void WriteValueToFile(ConfigScope scope, string key, T value) { - if (ConfigScope.CurrentUser == scope && !Directory.Exists(perUserConfigDirectory)) + if (scope == ConfigScope.CurrentUser && !Directory.Exists(perUserConfigDirectory)) { Directory.CreateDirectory(perUserConfigDirectory); } @@ -636,11 +640,17 @@ private void RemoveValueFromFile(ConfigScope scope, string key) internal sealed class PowerShellPolicies { public ScriptExecution ScriptExecution { get; set; } + public ScriptBlockLogging ScriptBlockLogging { get; set; } + public ModuleLogging ModuleLogging { get; set; } + public ProtectedEventLogging ProtectedEventLogging { get; set; } + public Transcription Transcription { get; set; } + public UpdatableHelp UpdatableHelp { get; set; } + public ConsoleSessionConfiguration ConsoleSessionConfiguration { get; set; } } @@ -652,6 +662,7 @@ internal abstract class PolicyBase { } internal sealed class ScriptExecution : PolicyBase { public string ExecutionPolicy { get; set; } + public bool? EnableScripts { get; set; } } @@ -661,6 +672,7 @@ internal sealed class ScriptExecution : PolicyBase internal sealed class ScriptBlockLogging : PolicyBase { public bool? EnableScriptBlockInvocationLogging { get; set; } + public bool? EnableScriptBlockLogging { get; set; } } @@ -670,6 +682,7 @@ internal sealed class ScriptBlockLogging : PolicyBase internal sealed class ModuleLogging : PolicyBase { public bool? EnableModuleLogging { get; set; } + public string[] ModuleNames { get; set; } } @@ -679,7 +692,9 @@ internal sealed class ModuleLogging : PolicyBase internal sealed class Transcription : PolicyBase { public bool? EnableTranscripting { get; set; } + public bool? EnableInvocationHeader { get; set; } + public string OutputDirectory { get; set; } } @@ -689,6 +704,7 @@ internal sealed class Transcription : PolicyBase internal sealed class UpdatableHelp : PolicyBase { public bool? EnableUpdateHelpDefaultSourcePath { get; set; } + public string DefaultSourcePath { get; set; } } @@ -698,6 +714,7 @@ internal sealed class UpdatableHelp : PolicyBase internal sealed class ConsoleSessionConfiguration : PolicyBase { public bool? EnableConsoleSessionConfiguration { get; set; } + public string ConsoleSessionConfigurationName { get; set; } } @@ -707,6 +724,7 @@ internal sealed class ConsoleSessionConfiguration : PolicyBase internal sealed class ProtectedEventLogging : PolicyBase { public bool? EnableProtectedEventLogging { get; set; } + public string[] EncryptionCertificate { get; set; } } diff --git a/src/System.Management.Automation/engine/PSVersionInfo.cs b/src/System.Management.Automation/engine/PSVersionInfo.cs index 09f9829c289..39fa635e733 100644 --- a/src/System.Management.Automation/engine/PSVersionInfo.cs +++ b/src/System.Management.Automation/engine/PSVersionInfo.cs @@ -2,8 +2,8 @@ // Licensed under the MIT License. using System.Collections; -using System.Diagnostics; using System.Globalization; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; @@ -27,7 +27,7 @@ namespace System.Management.Automation /// The above statement retrieves the PowerShell edition. /// /// - public class PSVersionInfo + public static class PSVersionInfo { internal const string PSVersionTableName = "PSVersionTable"; internal const string PSRemotingProtocolVersionName = "PSRemotingProtocolVersion"; @@ -63,6 +63,7 @@ public class PSVersionInfo private static readonly SemanticVersion s_psV61Version = new SemanticVersion(6, 1, 0, preReleaseLabel: null, buildLabel: null); private static readonly SemanticVersion s_psV62Version = new SemanticVersion(6, 2, 0, preReleaseLabel: null, buildLabel: null); private static readonly SemanticVersion s_psV7Version = new SemanticVersion(7, 0, 0, preReleaseLabel: null, buildLabel: null); + private static readonly SemanticVersion s_psV71Version = new SemanticVersion(7, 1, 0, preReleaseLabel: null, buildLabel: null); private static readonly SemanticVersion s_psSemVersion; private static readonly Version s_psVersion; @@ -76,8 +77,8 @@ static PSVersionInfo() { s_psVersionTable = new PSVersionHashTable(StringComparer.OrdinalIgnoreCase); - string assemblyPath = typeof(PSVersionInfo).Assembly.Location; - string productVersion = FileVersionInfo.GetVersionInfo(assemblyPath).ProductVersion; + Assembly currentAssembly = typeof(PSVersionInfo).Assembly; + ProductVersion = currentAssembly.GetCustomAttribute().InformationalVersion; // Get 'GitCommitId' and 'PSVersion' from the 'productVersion' assembly attribute. // @@ -92,11 +93,11 @@ static PSVersionInfo() // productVersion = '6.0.0 SHA: f1ec9...' convert to GitCommitId = 'v6.0.0' // PSVersion = '6.0.0' string rawGitCommitId; - string mainVersion = productVersion.Substring(0, productVersion.IndexOf(' ')); + string mainVersion = ProductVersion.Substring(0, ProductVersion.IndexOf(' ')); - if (productVersion.Contains(" Commits: ")) + if (ProductVersion.Contains(" Commits: ")) { - rawGitCommitId = productVersion.Replace(" Commits: ", "-").Replace(" SHA: ", "-g"); + rawGitCommitId = ProductVersion.Replace(" Commits: ", "-").Replace(" SHA: ", "-g"); } else { @@ -109,7 +110,7 @@ static PSVersionInfo() s_psVersionTable[PSVersionInfo.PSVersionName] = s_psSemVersion; s_psVersionTable[PSVersionInfo.PSEditionName] = PSEditionValue; s_psVersionTable[PSGitCommitIdName] = rawGitCommitId; - s_psVersionTable[PSCompatibleVersionsName] = new Version[] { s_psV1Version, s_psV2Version, s_psV3Version, s_psV4Version, s_psV5Version, s_psV51Version, s_psV6Version, s_psV61Version, s_psV62Version, s_psV7Version, s_psVersion }; + s_psVersionTable[PSCompatibleVersionsName] = new Version[] { s_psV1Version, s_psV2Version, s_psV3Version, s_psV4Version, s_psV5Version, s_psV51Version, s_psV6Version, s_psV61Version, s_psV62Version, s_psV7Version, s_psV71Version, s_psVersion }; s_psVersionTable[PSVersionInfo.SerializationVersionName] = new Version(InternalSerializer.DefaultVersion); s_psVersionTable[PSVersionInfo.PSRemotingProtocolVersionName] = RemotingConstants.ProtocolVersion; s_psVersionTable[PSVersionInfo.WSManStackVersionName] = GetWSManStackVersion(); @@ -181,6 +182,8 @@ public static Version PSVersion } } + internal static string ProductVersion { get; } + internal static string GitCommitId { get @@ -373,7 +376,7 @@ public override ICollection Keys } } - private class PSVersionTableComparer : IComparer + private sealed class PSVersionTableComparer : IComparer { public int Compare(object x, object y) { @@ -802,12 +805,12 @@ public override string ToString() if (!string.IsNullOrEmpty(PreReleaseLabel)) { - result.Append("-").Append(PreReleaseLabel); + result.Append('-').Append(PreReleaseLabel); } if (!string.IsNullOrEmpty(BuildLabel)) { - result.Append("+").Append(BuildLabel); + result.Append('+').Append(BuildLabel); } versionString = result.ToString(); @@ -844,8 +847,7 @@ public int CompareTo(object version) return 1; } - var v = version as SemanticVersion; - if (v == null) + if (!(version is SemanticVersion v)) { throw PSTraceSource.NewArgumentException(nameof(version)); } @@ -859,7 +861,7 @@ public int CompareTo(object version) /// public int CompareTo(SemanticVersion value) { - if ((object)value == null) + if (value is null) return 1; if (Major != value.Major) diff --git a/src/System.Management.Automation/engine/ParameterBinderBase.cs b/src/System.Management.Automation/engine/ParameterBinderBase.cs index ddf8072b941..ee7028c3865 100644 --- a/src/System.Management.Automation/engine/ParameterBinderBase.cs +++ b/src/System.Management.Automation/engine/ParameterBinderBase.cs @@ -58,7 +58,7 @@ internal abstract class ParameterBinderBase { #region tracer [TraceSource("ParameterBinderBase", "A abstract helper class for the CommandProcessor that binds parameters to the specified object.")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("ParameterBinderBase", "A abstract helper class for the CommandProcessor that binds parameters to the specified object."); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("ParameterBinderBase", "A abstract helper class for the CommandProcessor that binds parameters to the specified object."); [TraceSource("ParameterBinding", "Traces the process of binding the arguments to the parameters of cmdlets, scripts, and applications.")] internal static readonly PSTraceSource bindingTracer = @@ -172,10 +172,10 @@ internal object Target /// internal CommandLineParameters CommandLineParameters { + get { return _commandLineParameters ??= new CommandLineParameters(); } + // Setter is needed to pass into RuntimeParameterBinder instances set { _commandLineParameters = value; } - - get { return _commandLineParameters ?? (_commandLineParameters = new CommandLineParameters()); } } private CommandLineParameters _commandLineParameters; @@ -439,7 +439,7 @@ internal virtual bool BindParameter( GetErrorExtent(parameter), parameterMetadata.Name, parameterMetadata.Type, - (parameterValue == null) ? null : parameterValue.GetType(), + parameterValue?.GetType(), ParameterBinderStrings.ParameterArgumentTransformationError, "ParameterArgumentTransformationError", e.Message); @@ -522,7 +522,7 @@ internal virtual bool BindParameter( GetErrorExtent(parameter), parameterMetadata.Name, parameterMetadata.Type, - (parameterValue == null) ? null : parameterValue.GetType(), + parameterValue?.GetType(), ParameterBinderStrings.ParameterArgumentValidationError, "ParameterArgumentValidationError", e.Message); @@ -586,7 +586,7 @@ internal virtual bool BindParameter( if (bindError != null) { - Type specifiedType = (parameterValue == null) ? null : parameterValue.GetType(); + Type specifiedType = parameterValue?.GetType(); ParameterBindingException bindingException = new ParameterBindingException( bindError, @@ -736,7 +736,7 @@ private void ValidateNullOrEmptyArgument( GetErrorExtent(parameter), parameterMetadata.Name, parameterMetadata.Type, - (parameterValue == null) ? null : parameterValue.GetType(), + parameterValue?.GetType(), ParameterBinderStrings.ParameterArgumentValidationErrorEmptyStringNotAllowed, "ParameterArgumentValidationErrorEmptyStringNotAllowed"); throw bindingException; @@ -813,7 +813,7 @@ private void ValidateNullOrEmptyArgument( GetErrorExtent(parameter), parameterMetadata.Name, parameterMetadata.Type, - (parameterValue == null) ? null : parameterValue.GetType(), + parameterValue?.GetType(), resourceString, errorId); throw bindingException; @@ -903,7 +903,7 @@ private bool ShouldContinueUncoercedBind( /// /// The invocation information for the code that is being bound. /// - private InvocationInfo _invocationInfo; + private readonly InvocationInfo _invocationInfo; internal InvocationInfo InvocationInfo { @@ -916,7 +916,7 @@ internal InvocationInfo InvocationInfo /// /// The context of the currently running engine. /// - private ExecutionContext _context; + private readonly ExecutionContext _context; internal ExecutionContext Context { @@ -929,7 +929,7 @@ internal ExecutionContext Context /// /// An instance of InternalCommand that the binder is binding to. /// - private InternalCommand _command; + private readonly InternalCommand _command; internal InternalCommand Command { @@ -942,9 +942,9 @@ internal InternalCommand Command /// /// The engine APIs that need to be passed the attributes when evaluated. /// - private EngineIntrinsics _engine; + private readonly EngineIntrinsics _engine; - private bool _isTranscribing; + private readonly bool _isTranscribing; #endregion internal members @@ -1559,7 +1559,7 @@ private object EncodeCollection( toType, 0, null, - new object[] { }, + Array.Empty(), System.Globalization.CultureInfo.InvariantCulture); if (collectionTypeInformation.ParameterCollectionType == ParameterCollectionType.IList) resultAsIList = (IList)resultCollection; @@ -1781,7 +1781,7 @@ private object EncodeCollection( GetErrorExtent(argument), parameterName, toType, - (currentValueElement == null) ? null : currentValueElement.GetType(), + currentValueElement?.GetType(), ParameterBinderStrings.CannotConvertArgument, "CannotConvertArgument", currentValueElement ?? "null", @@ -1878,7 +1878,7 @@ private object EncodeCollection( GetErrorExtent(argument), parameterName, toType, - (currentValue == null) ? null : currentValue.GetType(), + currentValue?.GetType(), ParameterBinderStrings.CannotConvertArgument, "CannotConvertArgument", currentValue ?? "null", @@ -2066,4 +2066,3 @@ internal HashSet CopyBoundPositionalParameters() } } } - diff --git a/src/System.Management.Automation/engine/ParameterBinderController.cs b/src/System.Management.Automation/engine/ParameterBinderController.cs index e62454622ed..e6a7153a879 100644 --- a/src/System.Management.Automation/engine/ParameterBinderController.cs +++ b/src/System.Management.Automation/engine/ParameterBinderController.cs @@ -459,7 +459,7 @@ internal virtual bool BindParameter( throw bindingException; } - flags = flags & ~ParameterBindingFlags.DelayBindScriptBlock; + flags &= ~ParameterBindingFlags.DelayBindScriptBlock; result = BindParameter(_currentParameterSetFlag, argument, matchingParameter, flags); } @@ -1324,4 +1324,3 @@ protected IScriptExtent GetParameterErrorExtent(CommandParameterInternal cpi) #endregion internal_members } } - diff --git a/src/System.Management.Automation/engine/ParameterInfo.cs b/src/System.Management.Automation/engine/ParameterInfo.cs index cf1784a7b62..d1def1c468f 100644 --- a/src/System.Management.Automation/engine/ParameterInfo.cs +++ b/src/System.Management.Automation/engine/ParameterInfo.cs @@ -144,4 +144,3 @@ private void SetParameterSetData(ParameterSetSpecificMetadata parameterMetadata) #endregion private members } } - diff --git a/src/System.Management.Automation/engine/ParameterSetInfo.cs b/src/System.Management.Automation/engine/ParameterSetInfo.cs index a5f83063f4b..74745fca6da 100644 --- a/src/System.Management.Automation/engine/ParameterSetInfo.cs +++ b/src/System.Management.Automation/engine/ParameterSetInfo.cs @@ -92,18 +92,18 @@ public override string ToString() Text.StringBuilder result = new Text.StringBuilder(); GenerateParametersInDisplayOrder( - parameter => AppendFormatCommandParameterInfo(parameter, result), - delegate (string str) - { - if (result.Length > 0) - { - result.Append(" "); - } - - result.Append("["); - result.Append(str); - result.Append("]"); - }); + parameter => AppendFormatCommandParameterInfo(parameter, result), + (string str) => + { + if (result.Length > 0) + { + result.Append(' '); + } + + result.Append('['); + result.Append(str); + result.Append(']'); + }); return result.ToString(); } @@ -233,7 +233,7 @@ private static void AppendFormatCommandParameterInfo(CommandParameterInfo parame if (result.Length > 0) { // Add a space between parameters - result.Append(" "); + result.Append(' '); } if (parameter.ParameterType == typeof(SwitchParameter)) @@ -339,4 +339,3 @@ private void Initialize(MergedCommandParameterMetadata parameterMetadata, uint p #endregion private members } } - diff --git a/src/System.Management.Automation/engine/ParameterSetPromptingData.cs b/src/System.Management.Automation/engine/ParameterSetPromptingData.cs index 0f7889f8d0b..36e735e675a 100644 --- a/src/System.Management.Automation/engine/ParameterSetPromptingData.cs +++ b/src/System.Management.Automation/engine/ParameterSetPromptingData.cs @@ -60,4 +60,3 @@ internal Dictionary(); } } - diff --git a/src/System.Management.Automation/engine/ParameterSetSpecificMetadata.cs b/src/System.Management.Automation/engine/ParameterSetSpecificMetadata.cs index 4cc4ca7540e..a20b2af2061 100644 --- a/src/System.Management.Automation/engine/ParameterSetSpecificMetadata.cs +++ b/src/System.Management.Automation/engine/ParameterSetSpecificMetadata.cs @@ -209,7 +209,6 @@ internal string GetHelpMessage(Cmdlet cmdlet) return helpInfo; } - private ParameterAttribute _attribute; + private readonly ParameterAttribute _attribute; } } - diff --git a/src/System.Management.Automation/engine/PathInterfaces.cs b/src/System.Management.Automation/engine/PathInterfaces.cs index d11a225797e..9a604829295 100644 --- a/src/System.Management.Automation/engine/PathInterfaces.cs +++ b/src/System.Management.Automation/engine/PathInterfaces.cs @@ -1402,14 +1402,13 @@ private LocationGlobber PathResolver _sessionState != null, "The only constructor for this class should always set the sessionState field"); - return _pathResolver ?? (_pathResolver = _sessionState.ExecutionContext.LocationGlobber); + return _pathResolver ??= _sessionState.ExecutionContext.LocationGlobber; } } private LocationGlobber _pathResolver; - private SessionStateInternal _sessionState; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/Pipe.cs b/src/System.Management.Automation/engine/Pipe.cs index ac9350487a0..8ee000a4faf 100644 --- a/src/System.Management.Automation/engine/Pipe.cs +++ b/src/System.Management.Automation/engine/Pipe.cs @@ -16,7 +16,7 @@ internal enum VariableStreamKind Error, Warning, Information - }; + } /// /// Pipe provides a way to stitch two commands. @@ -28,7 +28,7 @@ internal enum VariableStreamKind /// internal class Pipe { - private ExecutionContext _context; + private readonly ExecutionContext _context; // If a pipeline object has been added, then // write objects to it, stepping one at a time... @@ -40,7 +40,10 @@ internal class Pipe /// internal CommandProcessorBase DownstreamCmdlet { - get { return _downstreamCmdlet; } + get + { + return _downstreamCmdlet; + } set { @@ -76,7 +79,10 @@ internal CommandProcessorBase DownstreamCmdlet /// internal PipelineWriter ExternalWriter { - get { return _externalWriter; } + get + { + return _externalWriter; + } set { @@ -108,7 +114,10 @@ public override string ToString() /// internal bool NullPipe { - get { return _nullPipe; } + get + { + return _nullPipe; + } set { @@ -299,7 +308,7 @@ internal void SetVariableListForTemporaryPipe(Pipe tempPipe) CopyVariableToTempPipe(VariableStreamKind.Information, _informationVariableList, tempPipe); } - private void CopyVariableToTempPipe(VariableStreamKind streamKind, List variableList, Pipe tempPipe) + private static void CopyVariableToTempPipe(VariableStreamKind streamKind, List variableList, Pipe tempPipe) { if (variableList != null && variableList.Count > 0) { @@ -349,7 +358,7 @@ internal Pipe(System.Collections.ObjectModel.Collection resultCollecti _resultCollection = resultCollection; } - private System.Collections.ObjectModel.Collection _resultCollection; + private readonly System.Collections.ObjectModel.Collection _resultCollection; /// /// This pipe writes into another pipeline processor allowing @@ -380,7 +389,7 @@ internal Pipe(IEnumerator enumeratorToProcess) _enumeratorToProcessIsEmpty = false; } - private IEnumerator _enumeratorToProcess; + private readonly IEnumerator _enumeratorToProcess; private bool _enumeratorToProcessIsEmpty; #endregion ctor @@ -510,7 +519,7 @@ internal void AddItems(object objects) // If our object came from GetEnumerator (and hence is not IEnumerator), then we need to dispose // Otherwise, we don't own the object, so don't dispose. var disposable = ie as IDisposable; - if (disposable != null && !(objects is IEnumerator)) + if (disposable != null && objects is not IEnumerator) { disposable.Dispose(); } diff --git a/src/System.Management.Automation/engine/PositionalCommandParameter.cs b/src/System.Management.Automation/engine/PositionalCommandParameter.cs index 1370d8c9a2f..3a2b4688ab4 100644 --- a/src/System.Management.Automation/engine/PositionalCommandParameter.cs +++ b/src/System.Management.Automation/engine/PositionalCommandParameter.cs @@ -25,4 +25,3 @@ internal PositionalCommandParameter(MergedCompiledCommandParameter parameter) internal Collection ParameterSetData { get; } = new Collection(); } } - diff --git a/src/System.Management.Automation/engine/ProgressRecord.cs b/src/System.Management.Automation/engine/ProgressRecord.cs index 346290f189f..b721b4003d9 100644 --- a/src/System.Management.Automation/engine/ProgressRecord.cs +++ b/src/System.Management.Automation/engine/ProgressRecord.cs @@ -418,7 +418,7 @@ internal static int GetPercentageComplete(DateTime startTime, TimeSpan expectedD #region DO NOT REMOVE OR RENAME THESE FIELDS - it will break remoting compatibility with Windows PowerShell [DataMemberAttribute()] - private int id; + private readonly int id; [DataMemberAttribute()] private int parentId = -1; @@ -540,4 +540,3 @@ enum ProgressRecordType Completed } } - diff --git a/src/System.Management.Automation/engine/PropertyCmdletProviderInterfaces.cs b/src/System.Management.Automation/engine/PropertyCmdletProviderInterfaces.cs index 9c1f9379190..4b6e8d818f1 100644 --- a/src/System.Management.Automation/engine/PropertyCmdletProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/PropertyCmdletProviderInterfaces.cs @@ -1824,10 +1824,9 @@ internal object MovePropertyDynamicParameters( #region private data - private Cmdlet _cmdlet; - private SessionStateInternal _sessionState; + private readonly Cmdlet _cmdlet; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/ProviderInterfaces.cs b/src/System.Management.Automation/engine/ProviderInterfaces.cs index 27e2680af5c..e9edcb48415 100644 --- a/src/System.Management.Automation/engine/ProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/ProviderInterfaces.cs @@ -160,9 +160,8 @@ internal int Count #region private data - private SessionStateInternal _sessionState; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/ProviderNames.cs b/src/System.Management.Automation/engine/ProviderNames.cs index 0ae3e63edec..6d9e3d2d598 100644 --- a/src/System.Management.Automation/engine/ProviderNames.cs +++ b/src/System.Management.Automation/engine/ProviderNames.cs @@ -130,4 +130,3 @@ internal override string Registry } } } - diff --git a/src/System.Management.Automation/engine/ProxyCommand.cs b/src/System.Management.Automation/engine/ProxyCommand.cs index 1bb3d15baf3..5703adec664 100644 --- a/src/System.Management.Automation/engine/ProxyCommand.cs +++ b/src/System.Management.Automation/engine/ProxyCommand.cs @@ -278,11 +278,11 @@ private static void AppendContent(StringBuilder sb, string section, object obj) string text = GetObjText(obj); if (!string.IsNullOrEmpty(text)) { - sb.Append("\n"); + sb.Append('\n'); sb.Append(section); sb.Append("\n\n"); sb.Append(text); - sb.Append("\n"); + sb.Append('\n'); } } } @@ -306,13 +306,13 @@ private static void AppendContent(StringBuilder sb, string section, PSObject[] a } sb.Append(text); - sb.Append("\n"); + sb.Append('\n'); } } if (!first) { - sb.Append("\n"); + sb.Append('\n'); } } } @@ -327,7 +327,7 @@ private static void AppendType(StringBuilder sb, string section, PSObject parent sb.Append(section); sb.Append("\n\n"); sb.Append(GetObjText(name)); - sb.Append("\n"); + sb.Append('\n'); } else { @@ -338,7 +338,7 @@ private static void AppendType(StringBuilder sb, string section, PSObject parent sb.Append(section); sb.Append("\n\n"); sb.Append(GetObjText(uri)); - sb.Append("\n"); + sb.Append('\n'); } } } @@ -395,7 +395,7 @@ public static string GetHelpComments(PSObject help) if (!string.IsNullOrEmpty(text)) { sb.Append(text); - sb.Append("\n"); + sb.Append('\n'); } } } @@ -430,7 +430,7 @@ public static string GetHelpComments(PSObject help) PSObject[] remarks = GetProperty(ex, "remarks"); if (remarks != null) { - exsb.Append("\n"); + exsb.Append('\n'); foreach (PSObject remark in remarks) { string remarkText = GetProperty(remark, "text"); @@ -441,7 +441,7 @@ public static string GetHelpComments(PSObject help) if (exsb.Length > 0) { sb.Append("\n\n.EXAMPLE\n\n"); - sb.Append(exsb.ToString()); + sb.Append(exsb); } } } diff --git a/src/System.Management.Automation/engine/PseudoParameterBinder.cs b/src/System.Management.Automation/engine/PseudoParameterBinder.cs index bddbe643f59..9bebe01b2e7 100644 --- a/src/System.Management.Automation/engine/PseudoParameterBinder.cs +++ b/src/System.Management.Automation/engine/PseudoParameterBinder.cs @@ -36,7 +36,7 @@ internal RuntimeDefinedParameterBinder( { string key = pair.Key; RuntimeDefinedParameter pp = pair.Value; - string ppName = (pp == null) ? null : pp.Name; + string ppName = pp?.Name; if (pp == null || key != ppName) { ParameterBindingException bindingException = diff --git a/src/System.Management.Automation/engine/PseudoParameters.cs b/src/System.Management.Automation/engine/PseudoParameters.cs index 78ef034cf5b..97b1d60e8ad 100644 --- a/src/System.Management.Automation/engine/PseudoParameters.cs +++ b/src/System.Management.Automation/engine/PseudoParameters.cs @@ -236,6 +236,6 @@ public string HelpFile /// public object Data { get; set; } - internal static readonly RuntimeDefinedParameter[] EmptyParameterArray = new RuntimeDefinedParameter[0]; + internal static readonly RuntimeDefinedParameter[] EmptyParameterArray = Array.Empty(); } } diff --git a/src/System.Management.Automation/engine/QuestionMarkVariable.cs b/src/System.Management.Automation/engine/QuestionMarkVariable.cs index af2436c2f2a..b25cb5107ba 100644 --- a/src/System.Management.Automation/engine/QuestionMarkVariable.cs +++ b/src/System.Management.Automation/engine/QuestionMarkVariable.cs @@ -41,4 +41,3 @@ public override object Value } } } - diff --git a/src/System.Management.Automation/engine/ReflectionParameterBinder.cs b/src/System.Management.Automation/engine/ReflectionParameterBinder.cs index 3e5dcab2502..0fd8bf8b339 100644 --- a/src/System.Management.Automation/engine/ReflectionParameterBinder.cs +++ b/src/System.Management.Automation/engine/ReflectionParameterBinder.cs @@ -124,7 +124,7 @@ internal override void BindParameter(string name, object value, CompiledCommandP try { var setter = parameterMetadata != null - ? (parameterMetadata.Setter ?? (parameterMetadata.Setter = GetSetter(Target.GetType(), name))) + ? (parameterMetadata.Setter ??= GetSetter(Target.GetType(), name)) : GetSetter(Target.GetType(), name); setter(Target, value); } @@ -155,63 +155,66 @@ internal override void BindParameter(string name, object value, CompiledCommandP static ReflectionParameterBinder() { // Statically add delegates that we typically need on startup or every time we run PowerShell - this avoids the JIT - s_getterMethods.TryAdd(Tuple.Create(typeof(OutDefaultCommand), "InputObject"), o => ((OutDefaultCommand)o).InputObject); - s_setterMethods.TryAdd(Tuple.Create(typeof(OutDefaultCommand), "InputObject"), (o, v) => ((OutDefaultCommand)o).InputObject = (PSObject)v); + s_getterMethods.TryAdd(Tuple.Create(typeof(OutDefaultCommand), "InputObject"), static o => ((OutDefaultCommand)o).InputObject); + s_setterMethods.TryAdd(Tuple.Create(typeof(OutDefaultCommand), "InputObject"), static (o, v) => ((OutDefaultCommand)o).InputObject = (PSObject)v); - s_getterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "InputObject"), o => ((OutLineOutputCommand)o).InputObject); - s_getterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "LineOutput"), o => ((OutLineOutputCommand)o).LineOutput); - s_setterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "InputObject"), (o, v) => ((OutLineOutputCommand)o).InputObject = (PSObject)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "LineOutput"), (o, v) => ((OutLineOutputCommand)o).LineOutput = v); + s_getterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "InputObject"), static o => ((OutLineOutputCommand)o).InputObject); + s_getterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "LineOutput"), static o => ((OutLineOutputCommand)o).LineOutput); + s_setterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "InputObject"), static (o, v) => ((OutLineOutputCommand)o).InputObject = (PSObject)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(OutLineOutputCommand), "LineOutput"), static (o, v) => ((OutLineOutputCommand)o).LineOutput = v); - s_getterMethods.TryAdd(Tuple.Create(typeof(FormatDefaultCommand), "InputObject"), o => ((FormatDefaultCommand)o).InputObject); - s_setterMethods.TryAdd(Tuple.Create(typeof(FormatDefaultCommand), "InputObject"), (o, v) => ((FormatDefaultCommand)o).InputObject = (PSObject)v); + s_getterMethods.TryAdd(Tuple.Create(typeof(FormatDefaultCommand), "InputObject"), static o => ((FormatDefaultCommand)o).InputObject); + s_setterMethods.TryAdd(Tuple.Create(typeof(FormatDefaultCommand), "InputObject"), static (o, v) => ((FormatDefaultCommand)o).InputObject = (PSObject)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(SetStrictModeCommand), "Off"), (o, v) => ((SetStrictModeCommand)o).Off = (SwitchParameter)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(SetStrictModeCommand), "Version"), (o, v) => ((SetStrictModeCommand)o).Version = (Version)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(SetStrictModeCommand), "Off"), static (o, v) => ((SetStrictModeCommand)o).Off = (SwitchParameter)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(SetStrictModeCommand), "Version"), static (o, v) => ((SetStrictModeCommand)o).Version = (Version)v); - s_getterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "InputObject"), o => ((ForEachObjectCommand)o).InputObject); - s_setterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "InputObject"), (o, v) => ((ForEachObjectCommand)o).InputObject = (PSObject)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "Process"), (o, v) => ((ForEachObjectCommand)o).Process = (ScriptBlock[])v); + s_getterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "InputObject"), static o => ((ForEachObjectCommand)o).InputObject); + s_setterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "InputObject"), static (o, v) => ((ForEachObjectCommand)o).InputObject = (PSObject)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(ForEachObjectCommand), "Process"), static (o, v) => ((ForEachObjectCommand)o).Process = (ScriptBlock[])v); - s_getterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "InputObject"), o => ((WhereObjectCommand)o).InputObject); - s_setterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "InputObject"), (o, v) => ((WhereObjectCommand)o).InputObject = (PSObject)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "FilterScript"), (o, v) => ((WhereObjectCommand)o).FilterScript = (ScriptBlock)v); + s_getterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "InputObject"), static o => ((WhereObjectCommand)o).InputObject); + s_setterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "InputObject"), static (o, v) => ((WhereObjectCommand)o).InputObject = (PSObject)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(WhereObjectCommand), "FilterScript"), static (o, v) => ((WhereObjectCommand)o).FilterScript = (ScriptBlock)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "Name"), (o, v) => ((ImportModuleCommand)o).Name = (string[])v); - s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "ModuleInfo"), (o, v) => ((ImportModuleCommand)o).ModuleInfo = (PSModuleInfo[])v); - s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "Scope"), (o, v) => ((ImportModuleCommand)o).Scope = (string)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "PassThru"), (o, v) => ((ImportModuleCommand)o).PassThru = (SwitchParameter)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "Name"), static (o, v) => ((ImportModuleCommand)o).Name = (string[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "ModuleInfo"), static (o, v) => ((ImportModuleCommand)o).ModuleInfo = (PSModuleInfo[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "Scope"), static (o, v) => ((ImportModuleCommand)o).Scope = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(ImportModuleCommand), "PassThru"), static (o, v) => ((ImportModuleCommand)o).PassThru = (SwitchParameter)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(GetCommandCommand), "Name"), (o, v) => ((GetCommandCommand)o).Name = (string[])v); - s_setterMethods.TryAdd(Tuple.Create(typeof(GetCommandCommand), "Module"), (o, v) => ((GetCommandCommand)o).Module = (string[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(GetCommandCommand), "Name"), static (o, v) => ((GetCommandCommand)o).Name = (string[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(GetCommandCommand), "Module"), static (o, v) => ((GetCommandCommand)o).Module = (string[])v); - s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "Name"), (o, v) => ((GetModuleCommand)o).Name = (string[])v); - s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "ListAvailable"), (o, v) => ((GetModuleCommand)o).ListAvailable = (SwitchParameter)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "FullyQualifiedName"), (o, v) => ((GetModuleCommand)o).FullyQualifiedName = (ModuleSpecification[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "Name"), static (o, v) => ((GetModuleCommand)o).Name = (string[])v); + s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "ListAvailable"), static (o, v) => ((GetModuleCommand)o).ListAvailable = (SwitchParameter)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(GetModuleCommand), "FullyQualifiedName"), static (o, v) => ((GetModuleCommand)o).FullyQualifiedName = (ModuleSpecification[])v); s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "ErrorAction"), - (o, v) => { + (o, v) => + { v ??= LanguagePrimitives.ThrowInvalidCastException(null, typeof(ActionPreference)); ((CommonParameters)o).ErrorAction = (ActionPreference)v; }); s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "WarningAction"), - (o, v) => { + (o, v) => + { v ??= LanguagePrimitives.ThrowInvalidCastException(null, typeof(ActionPreference)); ((CommonParameters)o).WarningAction = (ActionPreference)v; }); s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "InformationAction"), - (o, v) => { + (o, v) => + { v ??= LanguagePrimitives.ThrowInvalidCastException(null, typeof(ActionPreference)); ((CommonParameters)o).InformationAction = (ActionPreference)v; }); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "Verbose"), (o, v) => ((CommonParameters)o).Verbose = (SwitchParameter)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "Debug"), (o, v) => ((CommonParameters)o).Debug = (SwitchParameter)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "ErrorVariable"), (o, v) => ((CommonParameters)o).ErrorVariable = (string)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "WarningVariable"), (o, v) => ((CommonParameters)o).WarningVariable = (string)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "InformationVariable"), (o, v) => ((CommonParameters)o).InformationVariable = (string)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "OutVariable"), (o, v) => ((CommonParameters)o).OutVariable = (string)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "OutBuffer"), (o, v) => ((CommonParameters)o).OutBuffer = (int)v); - s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "PipelineVariable"), (o, v) => ((CommonParameters)o).PipelineVariable = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "Verbose"), static (o, v) => ((CommonParameters)o).Verbose = (SwitchParameter)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "Debug"), static (o, v) => ((CommonParameters)o).Debug = (SwitchParameter)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "ErrorVariable"), static (o, v) => ((CommonParameters)o).ErrorVariable = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "WarningVariable"), static (o, v) => ((CommonParameters)o).WarningVariable = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "InformationVariable"), static (o, v) => ((CommonParameters)o).InformationVariable = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "OutVariable"), static (o, v) => ((CommonParameters)o).OutVariable = (string)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "OutBuffer"), static (o, v) => ((CommonParameters)o).OutBuffer = (int)v); + s_setterMethods.TryAdd(Tuple.Create(typeof(CommonParameters), "PipelineVariable"), static (o, v) => ((CommonParameters)o).PipelineVariable = (string)v); } private static readonly ConcurrentDictionary, Func> s_getterMethods diff --git a/src/System.Management.Automation/engine/ScopedItemSearcher.cs b/src/System.Management.Automation/engine/ScopedItemSearcher.cs index a68b93694b9..fc67ee26374 100644 --- a/src/System.Management.Automation/engine/ScopedItemSearcher.cs +++ b/src/System.Management.Automation/engine/ScopedItemSearcher.cs @@ -230,7 +230,7 @@ private void InitializeScopeEnumerator() private T _current; protected SessionStateInternal sessionState; - private VariablePath _lookupPath; + private readonly VariablePath _lookupPath; private SessionStateScopeEnumerator _scopeEnumerable; private bool _isSingleScopeLookup; private bool _isInitialized; @@ -274,7 +274,7 @@ protected override bool GetScopeItem( VariablePath name, out PSVariable variable) { - Diagnostics.Assert(!(name is FunctionLookupPath), + Diagnostics.Assert(name is not FunctionLookupPath, "name was scanned incorrect if we get here and it is a FunctionLookupPath"); bool result = true; @@ -328,7 +328,7 @@ protected override bool GetScopeItem( VariablePath name, out AliasInfo alias) { - Diagnostics.Assert(!(name is FunctionLookupPath), + Diagnostics.Assert(name is not FunctionLookupPath, "name was scanned incorrect if we get here and it is a FunctionLookupPath"); bool result = true; @@ -470,7 +470,7 @@ protected override bool GetScopeItem( VariablePath name, out PSDriveInfo drive) { - Diagnostics.Assert(!(name is FunctionLookupPath), + Diagnostics.Assert(name is not FunctionLookupPath, "name was scanned incorrect if we get here and it is a FunctionLookupPath"); bool result = true; diff --git a/src/System.Management.Automation/engine/ScriptCommandProcessor.cs b/src/System.Management.Automation/engine/ScriptCommandProcessor.cs index 89e898a5532..99b685e07d2 100644 --- a/src/System.Management.Automation/engine/ScriptCommandProcessor.cs +++ b/src/System.Management.Automation/engine/ScriptCommandProcessor.cs @@ -131,7 +131,7 @@ protected void CommonInitialization(ScriptBlock scriptBlock, ExecutionContext co /// /// Help target to request. /// Help category to request. - /// true if user requested help; false otherwise. + /// if user requested help; otherwise. internal override bool IsHelpRequested(out string helpTarget, out HelpCategory helpCategory) { if (arguments != null && CommandInfo != null && !string.IsNullOrEmpty(CommandInfo.Name) && _scriptBlock != null) @@ -274,7 +274,7 @@ private void Init() { _scriptBlock = base._scriptBlock; _obsoleteAttribute = _scriptBlock.ObsoleteAttribute; - _runOptimizedCode = _scriptBlock.Compile(optimized: _context._debuggingMode > 0 ? false : UseLocalScope); + _runOptimizedCode = _scriptBlock.Compile(optimized: _context._debuggingMode <= 0 && UseLocalScope); _localsTuple = _scriptBlock.MakeLocalsTuple(_runOptimizedCode); if (UseLocalScope) diff --git a/src/System.Management.Automation/engine/ScriptInfo.cs b/src/System.Management.Automation/engine/ScriptInfo.cs index 9c6b097fc05..af91867c452 100644 --- a/src/System.Management.Automation/engine/ScriptInfo.cs +++ b/src/System.Management.Automation/engine/ScriptInfo.cs @@ -116,9 +116,8 @@ internal override CommandMetadata CommandMetadata { get { - return _commandMetadata ?? - (_commandMetadata = - new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS())); + return _commandMetadata ??= + new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS()); } } diff --git a/src/System.Management.Automation/engine/SecurityDescriptorCmdletProviderInterfaces.cs b/src/System.Management.Automation/engine/SecurityDescriptorCmdletProviderInterfaces.cs index 826fff642c3..0e034289254 100644 --- a/src/System.Management.Automation/engine/SecurityDescriptorCmdletProviderInterfaces.cs +++ b/src/System.Management.Automation/engine/SecurityDescriptorCmdletProviderInterfaces.cs @@ -239,10 +239,9 @@ public ObjectSecurity NewOfType(string providerId, string type, AccessControlSec #region private data - private Cmdlet _cmdlet; - private SessionStateInternal _sessionState; + private readonly Cmdlet _cmdlet; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/SecurityManagerBase.cs b/src/System.Management.Automation/engine/SecurityManagerBase.cs index 3cb4c9e7a70..31712949cf7 100644 --- a/src/System.Management.Automation/engine/SecurityManagerBase.cs +++ b/src/System.Management.Automation/engine/SecurityManagerBase.cs @@ -55,7 +55,7 @@ public AuthorizationManager(string shellId) #endregion constructor - private object _policyCheckLock = new object(); + private readonly object _policyCheckLock = new object(); #region methods to use internally @@ -181,4 +181,3 @@ protected internal virtual bool ShouldRun(CommandInfo commandInfo, #endregion methods for derived class to override } } - diff --git a/src/System.Management.Automation/engine/SerializationStrings.cs b/src/System.Management.Automation/engine/SerializationStrings.cs index c3a1c8a46dc..81b0f9cb741 100644 --- a/src/System.Management.Automation/engine/SerializationStrings.cs +++ b/src/System.Management.Automation/engine/SerializationStrings.cs @@ -308,6 +308,5 @@ internal static class SerializationStrings internal const string MonadNamespacePrefix = "ps"; #endregion namespace values - }; + } } - diff --git a/src/System.Management.Automation/engine/SessionState.cs b/src/System.Management.Automation/engine/SessionState.cs index 64e06a81744..e0bdbd23ee0 100644 --- a/src/System.Management.Automation/engine/SessionState.cs +++ b/src/System.Management.Automation/engine/SessionState.cs @@ -30,7 +30,7 @@ internal sealed partial class SessionStateInternal [Dbg.TraceSourceAttribute( "SessionState", "SessionState Class")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("SessionState", "SessionState Class"); @@ -143,7 +143,7 @@ internal void InitializeSessionStateInternalSpecialVariables(bool clearVariables /// internal LocationGlobber Globber { - get { return _globberPrivate ?? (_globberPrivate = ExecutionContext.LocationGlobber); } + get { return _globberPrivate ??= ExecutionContext.LocationGlobber; } } private LocationGlobber _globberPrivate; @@ -158,7 +158,7 @@ internal LocationGlobber Globber /// internal SessionState PublicSessionState { - get { return _publicSessionState ?? (_publicSessionState = new SessionState(this)); } + get { return _publicSessionState ??= new SessionState(this); } set { _publicSessionState = value; } } @@ -170,7 +170,7 @@ internal SessionState PublicSessionState /// internal ProviderIntrinsics InvokeProvider { - get { return _invokeProvider ?? (_invokeProvider = new ProviderIntrinsics(this)); } + get { return _invokeProvider ??= new ProviderIntrinsics(this); } } private ProviderIntrinsics _invokeProvider; @@ -389,7 +389,7 @@ internal SessionStateEntryVisibility CheckApplicationVisibility(string applicati return checkPathVisibility(Applications, applicationPath); } - private SessionStateEntryVisibility checkPathVisibility(List list, string path) + private static SessionStateEntryVisibility checkPathVisibility(List list, string path) { if (list == null || list.Count == 0) return SessionStateEntryVisibility.Private; if (string.IsNullOrEmpty(path)) return SessionStateEntryVisibility.Private; diff --git a/src/System.Management.Automation/engine/SessionStateAliasAPIs.cs b/src/System.Management.Automation/engine/SessionStateAliasAPIs.cs index 17ed891f862..fa2cf65e170 100644 --- a/src/System.Management.Automation/engine/SessionStateAliasAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateAliasAPIs.cs @@ -583,4 +583,3 @@ internal IEnumerable GetAliasesByCommandName(string command) #endregion aliases } } - diff --git a/src/System.Management.Automation/engine/SessionStateCmdletAPIs.cs b/src/System.Management.Automation/engine/SessionStateCmdletAPIs.cs index 9e50b4e0a6a..f14c25f7420 100644 --- a/src/System.Management.Automation/engine/SessionStateCmdletAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateCmdletAPIs.cs @@ -324,4 +324,3 @@ internal void RemoveCmdletEntry(string name, bool force) #endregion cmdlets } } - diff --git a/src/System.Management.Automation/engine/SessionStateContainer.cs b/src/System.Management.Automation/engine/SessionStateContainer.cs index f4f2a46d2a5..b2d2e3c6837 100644 --- a/src/System.Management.Automation/engine/SessionStateContainer.cs +++ b/src/System.Management.Automation/engine/SessionStateContainer.cs @@ -628,7 +628,7 @@ internal bool IsItemContainer( foreach (string providerPath in providerPaths) { result = IsItemContainer(providerInstance, providerPath, context); - if (result == false) + if (!result) { break; } @@ -1841,9 +1841,7 @@ private void ProcessPathItems( return; } - string childName = childNameObjects[index].BaseObject as string; - - if (childName == null) + if (!(childNameObjects[index].BaseObject is string childName)) { continue; } @@ -2063,7 +2061,7 @@ internal object GetChildItemsDynamicParameters( } // Detect if the GetChildItemDynamicParameters has been overridden. - private bool HasGetChildItemDynamicParameters(ProviderInfo providerInfo) + private static bool HasGetChildItemDynamicParameters(ProviderInfo providerInfo) { Type providerType = providerInfo.ImplementingType; @@ -2588,9 +2586,7 @@ private void DoGetChildNamesManually( return; } - string name = result.BaseObject as string; - - if (name == null) + if (!(result.BaseObject is string name)) { continue; } @@ -2638,9 +2634,7 @@ private void DoGetChildNamesManually( return; } - string name = result.BaseObject as string; - - if (name == null) + if (!(result.BaseObject is string name)) { continue; } @@ -4044,7 +4038,7 @@ private bool HasChildItems( #region CopyItem /// - /// Copies an item at the specified path to an item at the . + /// Copies an item at the specified path to an item at the . /// /// /// The path(s) of the item(s) to copy. @@ -4112,7 +4106,7 @@ internal Collection CopyItem(string[] paths, } /// - /// Copies an item at the specified path to an item at the . + /// Copies an item at the specified path to an item at the . /// /// /// The path(s) of the item(s) to copy. @@ -4687,7 +4681,7 @@ internal object CopyItemDynamicParameters( } } - if (providerPath != null) + if (providerInstance != null) { // Get the dynamic parameters for the first resolved path return CopyItemDynamicParameters(providerInstance, providerPath, destination, recurse, newContext); @@ -4739,10 +4733,6 @@ private object CopyItemDynamicParameters( providerInstance != null, "Caller should validate providerInstance before calling this method"); - Dbg.Diagnostics.Assert( - path != null, - "Caller should validate path before calling this method"); - Dbg.Diagnostics.Assert( context != null, "Caller should validate context before calling this method"); @@ -4782,7 +4772,7 @@ private object CopyItemDynamicParameters( // This function validates a remote path, and if it exists, it returns the root path. // - private string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession session, CmdletProviderContext context, PSLanguageMode? languageMode, bool sourceIsRemote) + private static string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession session, CmdletProviderContext context, PSLanguageMode? languageMode, bool sourceIsRemote) { Hashtable op = null; @@ -4796,9 +4786,8 @@ private string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession ses if (languageMode.HasValue && (languageMode.Value == PSLanguageMode.ConstrainedLanguage || languageMode.Value == PSLanguageMode.NoLanguage)) { - var psRemoteUtilsName = CopyFileRemoteUtils.PSCopyRemoteUtilsName; ps.Runspace = session.Runspace; - ps.AddCommand("Get-Command").AddArgument(psRemoteUtilsName); + ps.AddCommand("Get-Command").AddArgument(CopyFileRemoteUtils.PSCopyRemoteUtilsName); var result = ps.Invoke(); if (result.Count == 0) @@ -4822,12 +4811,11 @@ private string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession ses ps.Commands.Clear(); ps.Streams.ClearStreams(); - ps.AddCommand(psRemoteUtilsName); + ps.AddCommand(CopyFileRemoteUtils.PSCopyRemoteUtilsName); } else { - string remoteScript = CopyFileRemoteUtils.PSValidatePathDefinition; - ps.AddScript(remoteScript); + ps.AddScript(CopyFileRemoteUtils.PSValidatePathDefinition); } ps.AddParameter("pathToValidate", path); @@ -4900,7 +4888,7 @@ private string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession ses return root; } - private bool isValidSession(PSSession session, CmdletProviderContext context, out PSLanguageMode? languageMode) + private static bool isValidSession(PSSession session, CmdletProviderContext context, out PSLanguageMode? languageMode) { // session == null is validated by the parameter binding if (session.Availability != RunspaceAvailability.Available) diff --git a/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs b/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs index 23e9fdc0475..b8a89b9b31f 100644 --- a/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs @@ -251,7 +251,7 @@ private static bool IsValidDriveName(string name) return result; } - private static char[] s_charactersInvalidInDriveName = new char[] { ':', '/', '\\', '.', '~' }; + private static readonly char[] s_charactersInvalidInDriveName = new char[] { ':', '/', '\\', '.', '~' }; /// /// Tries to resolve the drive root as an MSH path. If it successfully resolves @@ -1204,8 +1204,7 @@ internal void RemoveDrive( else { PSInvalidOperationException e = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( SessionStateStrings.DriveRemovalPreventedByProvider, drive.Name, drive.Provider); diff --git a/src/System.Management.Automation/engine/SessionStateFunctionAPIs.cs b/src/System.Management.Automation/engine/SessionStateFunctionAPIs.cs index 42d3607cadb..f444f46d2c3 100644 --- a/src/System.Management.Automation/engine/SessionStateFunctionAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateFunctionAPIs.cs @@ -116,7 +116,10 @@ internal IDictionary GetFunctionTableAtScope(string scopeI /// internal bool FunctionsExportedWithWildcard { - get { return _functionsExportedWithWildcard; } + get + { + return _functionsExportedWithWildcard; + } set { @@ -220,7 +223,7 @@ internal FunctionInfo GetFunction(string name) return GetFunction(name, CommandOrigin.Internal); } - private IEnumerable GetFunctionAliases(IParameterMetadataProvider ipmp) + private static IEnumerable GetFunctionAliases(IParameterMetadataProvider ipmp) { if (ipmp == null || ipmp.Body.ParamBlock == null) yield break; diff --git a/src/System.Management.Automation/engine/SessionStateLocationAPIs.cs b/src/System.Management.Automation/engine/SessionStateLocationAPIs.cs index 4cd4718aca5..6869f5071fb 100644 --- a/src/System.Management.Automation/engine/SessionStateLocationAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateLocationAPIs.cs @@ -799,7 +799,7 @@ CmdletProviderContext normalizePathContext /// /// A stack of the most recently pushed locations. /// - private Dictionary> _workingLocationStack; + private readonly Dictionary> _workingLocationStack; private const string startingDefaultStackName = "default"; /// @@ -1115,4 +1115,3 @@ internal LocationChangedEventArgs(SessionState sessionState, PathInfo oldPath, P public SessionState SessionState { get; internal set; } } } - diff --git a/src/System.Management.Automation/engine/SessionStateNavigation.cs b/src/System.Management.Automation/engine/SessionStateNavigation.cs index 4afb9218dd7..f6d1a28eb1c 100644 --- a/src/System.Management.Automation/engine/SessionStateNavigation.cs +++ b/src/System.Management.Automation/engine/SessionStateNavigation.cs @@ -190,7 +190,7 @@ internal string GetParentPath( } } - private string AddQualifier(string path, ProviderInfo provider, string qualifier, bool isProviderQualified, bool isDriveQualified) + private static string AddQualifier(string path, ProviderInfo provider, string qualifier, bool isProviderQualified, bool isDriveQualified) { string result = path; @@ -640,7 +640,7 @@ internal string NormalizeRelativePath( /// /// The character to test. /// True if the character is a path separator. - private bool IsPathSeparator(char c) + private static bool IsPathSeparator(char c) { return c == StringLiterals.DefaultPathSeparator || c == StringLiterals.AlternatePathSeparator; } diff --git a/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs b/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs index f1b637a1d84..a6a7d2efc7f 100644 --- a/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs @@ -52,7 +52,7 @@ internal Dictionary ProvidersCurrentWorkingDrive } } - private Dictionary _providersCurrentWorkingDrive = new Dictionary(); + private readonly Dictionary _providersCurrentWorkingDrive = new Dictionary(); /// /// Entrypoint used by to add a provider to the current session state @@ -317,7 +317,7 @@ private static string GetPossibleMatches(Collection matchingProvid foreach (ProviderInfo matchingProvider in matchingProviders) { - possibleMatches.Append(" "); + possibleMatches.Append(' '); possibleMatches.Append(matchingProvider.FullName); } @@ -350,10 +350,7 @@ internal DriveCmdletProvider GetDriveProviderInstance(string providerId) throw PSTraceSource.NewArgumentNullException(nameof(providerId)); } - DriveCmdletProvider driveCmdletProvider = - GetProviderInstance(providerId) as DriveCmdletProvider; - - if (driveCmdletProvider == null) + if (!(GetProviderInstance(providerId) is DriveCmdletProvider driveCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported); @@ -385,10 +382,7 @@ internal DriveCmdletProvider GetDriveProviderInstance(ProviderInfo provider) throw PSTraceSource.NewArgumentNullException(nameof(provider)); } - DriveCmdletProvider driveCmdletProvider = - GetProviderInstance(provider) as DriveCmdletProvider; - - if (driveCmdletProvider == null) + if (!(GetProviderInstance(provider) is DriveCmdletProvider driveCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported); @@ -420,10 +414,7 @@ private static DriveCmdletProvider GetDriveProviderInstance(CmdletProvider provi throw PSTraceSource.NewArgumentNullException(nameof(providerInstance)); } - DriveCmdletProvider driveCmdletProvider = - providerInstance as DriveCmdletProvider; - - if (driveCmdletProvider == null) + if (!(providerInstance is DriveCmdletProvider driveCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported); @@ -458,10 +449,7 @@ internal ItemCmdletProvider GetItemProviderInstance(string providerId) throw PSTraceSource.NewArgumentNullException(nameof(providerId)); } - ItemCmdletProvider itemCmdletProvider = - GetProviderInstance(providerId) as ItemCmdletProvider; - - if (itemCmdletProvider == null) + if (!(GetProviderInstance(providerId) is ItemCmdletProvider itemCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported); @@ -493,10 +481,7 @@ internal ItemCmdletProvider GetItemProviderInstance(ProviderInfo provider) throw PSTraceSource.NewArgumentNullException(nameof(provider)); } - ItemCmdletProvider itemCmdletProvider = - GetProviderInstance(provider) as ItemCmdletProvider; - - if (itemCmdletProvider == null) + if (!(GetProviderInstance(provider) is ItemCmdletProvider itemCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported); @@ -528,10 +513,7 @@ private static ItemCmdletProvider GetItemProviderInstance(CmdletProvider provide throw PSTraceSource.NewArgumentNullException(nameof(providerInstance)); } - ItemCmdletProvider itemCmdletProvider = - providerInstance as ItemCmdletProvider; - - if (itemCmdletProvider == null) + if (!(providerInstance is ItemCmdletProvider itemCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported); @@ -566,10 +548,7 @@ internal ContainerCmdletProvider GetContainerProviderInstance(string providerId) throw PSTraceSource.NewArgumentNullException(nameof(providerId)); } - ContainerCmdletProvider containerCmdletProvider = - GetProviderInstance(providerId) as ContainerCmdletProvider; - - if (containerCmdletProvider == null) + if (!(GetProviderInstance(providerId) is ContainerCmdletProvider containerCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported); @@ -601,10 +580,7 @@ internal ContainerCmdletProvider GetContainerProviderInstance(ProviderInfo provi throw PSTraceSource.NewArgumentNullException(nameof(provider)); } - ContainerCmdletProvider containerCmdletProvider = - GetProviderInstance(provider) as ContainerCmdletProvider; - - if (containerCmdletProvider == null) + if (!(GetProviderInstance(provider) is ContainerCmdletProvider containerCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported); @@ -636,10 +612,7 @@ private static ContainerCmdletProvider GetContainerProviderInstance(CmdletProvid throw PSTraceSource.NewArgumentNullException(nameof(providerInstance)); } - ContainerCmdletProvider containerCmdletProvider = - providerInstance as ContainerCmdletProvider; - - if (containerCmdletProvider == null) + if (!(providerInstance is ContainerCmdletProvider containerCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported); @@ -671,10 +644,7 @@ internal NavigationCmdletProvider GetNavigationProviderInstance(ProviderInfo pro throw PSTraceSource.NewArgumentNullException(nameof(provider)); } - NavigationCmdletProvider navigationCmdletProvider = - GetProviderInstance(provider) as NavigationCmdletProvider; - - if (navigationCmdletProvider == null) + if (!(GetProviderInstance(provider) is NavigationCmdletProvider navigationCmdletProvider)) { throw PSTraceSource.NewNotSupportedException(SessionStateStrings.NavigationCmdletProvider_NotSupported); diff --git a/src/System.Management.Automation/engine/SessionStatePublic.cs b/src/System.Management.Automation/engine/SessionStatePublic.cs index 0dca57054db..ce14d4948dc 100644 --- a/src/System.Management.Automation/engine/SessionStatePublic.cs +++ b/src/System.Management.Automation/engine/SessionStatePublic.cs @@ -88,7 +88,7 @@ public SessionState() /// public DriveManagementIntrinsics Drive { - get { return _drive ?? (_drive = new DriveManagementIntrinsics(_sessionState)); } + get { return _drive ??= new DriveManagementIntrinsics(_sessionState); } } /// @@ -96,7 +96,7 @@ public DriveManagementIntrinsics Drive /// public CmdletProviderManagementIntrinsics Provider { - get { return _provider ?? (_provider = new CmdletProviderManagementIntrinsics(_sessionState)); } + get { return _provider ??= new CmdletProviderManagementIntrinsics(_sessionState); } } /// @@ -104,7 +104,7 @@ public CmdletProviderManagementIntrinsics Provider /// public PathIntrinsics Path { - get { return _path ?? (_path = new PathIntrinsics(_sessionState)); } + get { return _path ??= new PathIntrinsics(_sessionState); } } /// @@ -112,7 +112,7 @@ public PathIntrinsics Path /// public PSVariableIntrinsics PSVariable { - get { return _variable ?? (_variable = new PSVariableIntrinsics(_sessionState)); } + get { return _variable ??= new PSVariableIntrinsics(_sessionState); } } /// @@ -311,7 +311,7 @@ internal SessionStateInternal Internal #region private data - private SessionStateInternal _sessionState; + private readonly SessionStateInternal _sessionState; private DriveManagementIntrinsics _drive; private CmdletProviderManagementIntrinsics _provider; private PathIntrinsics _path; @@ -336,6 +336,7 @@ public enum SessionStateEntryVisibility Private = 1 } +#nullable enable internal interface IHasSessionStateEntryVisibility { SessionStateEntryVisibility Visibility { get; set; } @@ -371,4 +372,3 @@ public enum PSLanguageMode ConstrainedLanguage = 3 } } - diff --git a/src/System.Management.Automation/engine/SessionStateScope.cs b/src/System.Management.Automation/engine/SessionStateScope.cs index 6fd1749ba30..fc5dff00784 100644 --- a/src/System.Management.Automation/engine/SessionStateScope.cs +++ b/src/System.Management.Automation/engine/SessionStateScope.cs @@ -64,7 +64,10 @@ internal SessionStateScope(SessionStateScope parentScope) /// internal SessionStateScope ScriptScope { - get { return _scriptScope; } + get + { + return _scriptScope; + } set { @@ -111,7 +114,7 @@ internal SessionStateScope ScriptScope /// the provider has already been notified. /// /// - /// If is null. + /// If is null. /// /// /// If a drive of the same name already exists in this scope. @@ -165,7 +168,7 @@ internal void NewDrive(PSDriveInfo newDrive) /// by the provider. /// /// - /// If is null. + /// If is null. /// internal void RemoveDrive(PSDriveInfo drive) { @@ -216,7 +219,7 @@ internal void RemoveAllDrives() /// exists in this scope or null if one does not exist. /// /// - /// If is null. + /// If is null. /// internal PSDriveInfo GetDrive(string name) { @@ -489,7 +492,7 @@ internal PSVariable SetVariable(string name, object value, bool asValue, bool fo } else { - variable = (LocalsTuple != null ? LocalsTuple.TrySetVariable(name, value) : null) ?? new PSVariable(name, value); + variable = (LocalsTuple?.TrySetVariable(name, value)) ?? new PSVariable(name, value); } if (ExecutionContext.HasEverUsedConstrainedLanguage) @@ -1615,7 +1618,10 @@ internal Language.TypeResolutionState TypeResolutionState return Parent != null ? Parent.TypeResolutionState : Language.TypeResolutionState.UsingSystem; } - set { _typeResolutionState = value; } + set + { + _typeResolutionState = value; + } } internal IDictionary TypeTable { get; private set; } @@ -1692,7 +1698,7 @@ private static FunctionInfo CreateFunction(string name, ScriptBlock function, Fu // performance degradation, so we use lazy initialization for all of them. private Dictionary GetDrives() { - return _drives ?? (_drives = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return _drives ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } private Dictionary _drives; @@ -1704,8 +1710,7 @@ private Dictionary GetDrives() // performance degradation, so we use lazy initialization for all of them. private Dictionary GetAutomountedDrives() { - return _automountedDrives ?? - (_automountedDrives = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return _automountedDrives ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } private Dictionary _automountedDrives; @@ -1890,7 +1895,7 @@ private Dictionary GetAllScopeFunctions() #region Alias mapping - private Dictionary> _commandsToAliasesCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _commandsToAliasesCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); /// /// Gets the aliases by command name (used by metadata-driven help) @@ -1980,4 +1985,3 @@ private void CheckVariableChangeInConstrainedLanguage(PSVariable variable) #endregion } } - diff --git a/src/System.Management.Automation/engine/SessionStateScopeEnumerator.cs b/src/System.Management.Automation/engine/SessionStateScopeEnumerator.cs index c3b643e4f31..e64137cf396 100644 --- a/src/System.Management.Automation/engine/SessionStateScopeEnumerator.cs +++ b/src/System.Management.Automation/engine/SessionStateScopeEnumerator.cs @@ -101,4 +101,3 @@ public void Dispose() private SessionStateScope _currentEnumeratedScope; } } - diff --git a/src/System.Management.Automation/engine/SessionStateSecurityDescriptorInterface.cs b/src/System.Management.Automation/engine/SessionStateSecurityDescriptorInterface.cs index 73cf89cebdf..16ebe0fc3b5 100644 --- a/src/System.Management.Automation/engine/SessionStateSecurityDescriptorInterface.cs +++ b/src/System.Management.Automation/engine/SessionStateSecurityDescriptorInterface.cs @@ -35,10 +35,7 @@ internal static ISecurityDescriptorCmdletProvider GetPermissionProviderInstance( throw PSTraceSource.NewArgumentNullException(nameof(providerInstance)); } - ISecurityDescriptorCmdletProvider permissionCmdletProvider = - providerInstance as ISecurityDescriptorCmdletProvider; - - if (permissionCmdletProvider == null) + if (!(providerInstance is ISecurityDescriptorCmdletProvider permissionCmdletProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -579,4 +576,3 @@ internal ObjectSecurity NewSecurityDescriptorOfType( #endregion NewSecurityDescriptor } } - diff --git a/src/System.Management.Automation/engine/SessionStateUtils.cs b/src/System.Management.Automation/engine/SessionStateUtils.cs index 7c684abd1c3..754f228633a 100644 --- a/src/System.Management.Automation/engine/SessionStateUtils.cs +++ b/src/System.Management.Automation/engine/SessionStateUtils.cs @@ -325,4 +325,3 @@ public enum OpenMode Overwrite } } - diff --git a/src/System.Management.Automation/engine/SessionStateVariableAPIs.cs b/src/System.Management.Automation/engine/SessionStateVariableAPIs.cs index 9b4028314b8..8cc9e4bafa4 100644 --- a/src/System.Management.Automation/engine/SessionStateVariableAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateVariableAPIs.cs @@ -181,7 +181,7 @@ internal object GetVariableValue(string name, object defaultValue) /// The variable if it was found or null if it was not. /// /// - /// The is first parsed to see if it contains a drive + /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. If any other drive specifier /// is found the lookup goes in the following order. @@ -252,7 +252,7 @@ internal object GetVariableValue( /// The variable if it was found or null if it was not. /// /// - /// The is first parsed to see if it contains a drive + /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. If any other drive specifier /// is found the lookup goes in the following order. @@ -523,7 +523,7 @@ internal object GetVariableValueFromProvider( /// The variable if it was found or null if it was not. /// /// - /// The is first parsed to see if it contains a drive + /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. /// - current scope @@ -575,7 +575,7 @@ internal PSVariable GetVariableItem( /// The variable if it was found or null if it was not. /// /// - /// The is first parsed to see if it contains a drive + /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. /// - current scope @@ -1179,7 +1179,7 @@ internal object SetVariable( if (variablePath.IsPrivate && varResult != null) { - varResult.Options = varResult.Options | ScopedItemOptions.Private; + varResult.Options |= ScopedItemOptions.Private; } result = varResult; @@ -1816,7 +1816,7 @@ internal IDictionary GetVariableTable() return result; } - private void GetScopeVariableTable(SessionStateScope scope, Dictionary result, bool includePrivate) + private static void GetScopeVariableTable(SessionStateScope scope, Dictionary result, bool includePrivate) { foreach (KeyValuePair entry in scope.Variables) { diff --git a/src/System.Management.Automation/engine/ShellVariable.cs b/src/System.Management.Automation/engine/ShellVariable.cs index 4be5a96f52b..424be295346 100644 --- a/src/System.Management.Automation/engine/ShellVariable.cs +++ b/src/System.Management.Automation/engine/ShellVariable.cs @@ -387,7 +387,7 @@ internal void SetOptions(ScopedItemOptions newOptions, bool force) /// public Collection Attributes { - get { return _attributes ?? (_attributes = new PSVariableAttributeCollection(this)); } + get { return _attributes ??= new PSVariableAttributeCollection(this); } } private PSVariableAttributeCollection _attributes; @@ -759,7 +759,10 @@ public LocalVariable(string name, MutableTuple tuple, int tupleSlot) public override ScopedItemOptions Options { - get { return base.Options; } + get + { + return base.Options; + } set { @@ -840,7 +843,7 @@ public override object Value /// public override string Description { - get { return _description ?? (_description = SessionStateStrings.DollarNullDescription); } + get { return _description ??= SessionStateStrings.DollarNullDescription; } set { /* Do nothing */ } } @@ -898,4 +901,3 @@ public enum ScopedItemOptions Unspecified = 0x10 } } - diff --git a/src/System.Management.Automation/engine/SpecialVariables.cs b/src/System.Management.Automation/engine/SpecialVariables.cs index aa241b6c942..0f95349664f 100644 --- a/src/System.Management.Automation/engine/SpecialVariables.cs +++ b/src/System.Management.Automation/engine/SpecialVariables.cs @@ -32,6 +32,10 @@ internal static class SpecialVariables internal static readonly VariablePath OFSVarPath = new VariablePath(OFS); + internal const string PSStyle = "PSStyle"; + + internal static readonly VariablePath PSStyleVarPath = new VariablePath(PSStyle); + internal const string OutputEncoding = "OutputEncoding"; internal static readonly VariablePath OutputEncodingVarPath = new VariablePath(OutputEncoding); @@ -253,6 +257,11 @@ internal static class SpecialVariables #endregion Preference Variables + // Native command argument passing style + internal const string NativeArgumentPassing = "PSNativeCommandArgumentPassing"; + + internal static readonly VariablePath NativeArgumentPassingVarPath = new VariablePath(NativeArgumentPassing); + internal const string ErrorView = "ErrorView"; internal static readonly VariablePath ErrorViewVarPath = new VariablePath(ErrorView); diff --git a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs index f77072ea376..7a87b259314 100644 --- a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs +++ b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; -namespace System.Management.Automation.Subsystem +namespace System.Management.Automation.Subsystem.Prediction { /// /// The class represents the prediction result from a predictor. @@ -27,15 +27,22 @@ public sealed class PredictionResult /// public string Name { get; } + /// + /// Gets the mini-session id that represents a specific invocation to the API of the predictor. + /// When it's not specified, it's considered by a client that the predictor doesn't expect feedback. + /// + public uint? Session { get; } + /// /// Gets the suggestions. /// public IReadOnlyList Suggestions { get; } - internal PredictionResult(Guid id, string name, List suggestions) + internal PredictionResult(Guid id, string name, uint? session, List suggestions) { Id = id; Name = name; + Session = session; Suggestions = suggestions; } } @@ -48,22 +55,24 @@ public static class CommandPrediction /// /// Collect the predictive suggestions from registered predictors using the default timeout. /// + /// Represents the client that initiates the call. /// The object from parsing the current command line input. /// The objects from parsing the current command line input. /// A list of objects. - public static Task?> PredictInput(Ast ast, Token[] astTokens) + public static Task?> PredictInputAsync(PredictionClient client, Ast ast, Token[] astTokens) { - return PredictInput(ast, astTokens, millisecondsTimeout: 20); + return PredictInputAsync(client, ast, astTokens, millisecondsTimeout: 20); } /// /// Collect the predictive suggestions from registered predictors using the specified timeout. /// + /// Represents the client that initiates the call. /// The object from parsing the current command line input. /// The objects from parsing the current command line input. /// The milliseconds to timeout. /// A list of objects. - public static async Task?> PredictInput(Ast ast, Token[] astTokens, int millisecondsTimeout) + public static async Task?> PredictInputAsync(PredictionClient client, Ast ast, Token[] astTokens, int millisecondsTimeout) { Requires.Condition(millisecondsTimeout > 0, nameof(millisecondsTimeout)); @@ -77,16 +86,13 @@ public static class CommandPrediction var tasks = new Task[predictors.Count]; using var cancellationSource = new CancellationTokenSource(); + Func callBack = GetCallBack(client, context, cancellationSource); + for (int i = 0; i < predictors.Count; i++) { ICommandPredictor predictor = predictors[i]; - tasks[i] = Task.Factory.StartNew( - state => { - var predictor = (ICommandPredictor)state!; - List? texts = predictor.GetSuggestion(context, cancellationSource.Token); - return texts?.Count > 0 ? new PredictionResult(predictor.Id, predictor.Name, texts) : null; - }, + callBack, predictor, cancellationSource.Token, TaskCreationOptions.DenyChildAttach, @@ -98,7 +104,7 @@ await Task.WhenAny( Task.Delay(millisecondsTimeout, cancellationSource.Token)).ConfigureAwait(false); cancellationSource.Cancel(); - var results = new List(predictors.Count); + var resultList = new List(predictors.Count); foreach (Task task in tasks) { if (task.IsCompletedSuccessfully) @@ -106,19 +112,35 @@ await Task.WhenAny( PredictionResult? result = task.Result; if (result != null) { - results.Add(result); + resultList.Add(result); } } } - return results; + return resultList; + + // A local helper function to avoid creating an instance of the generated delegate helper class + // when no predictor is registered. + static Func GetCallBack( + PredictionClient client, + PredictionContext context, + CancellationTokenSource cancellationSource) + { + return state => + { + var predictor = (ICommandPredictor)state!; + SuggestionPackage pkg = predictor.GetSuggestion(client, context, cancellationSource.Token); + return pkg.SuggestionEntries?.Count > 0 ? new PredictionResult(predictor.Id, predictor.Name, pkg.Session, pkg.SuggestionEntries) : null; + }; + } } /// /// Allow registered predictors to do early processing when a command line is accepted. /// + /// Represents the client that initiates the call. /// History command lines provided as references for prediction. - public static void OnCommandLineAccepted(IReadOnlyList history) + public static void OnCommandLineAccepted(PredictionClient client, IReadOnlyList history) { Requires.NotNull(history, nameof(history)); @@ -128,24 +150,104 @@ public static void OnCommandLineAccepted(IReadOnlyList history) return; } + Action? callBack = null; + foreach (ICommandPredictor predictor in predictors) + { + if (predictor.CanAcceptFeedback(client, PredictorFeedbackKind.CommandLineAccepted)) + { + callBack ??= GetCallBack(client, history); + ThreadPool.QueueUserWorkItem(callBack, predictor, preferLocal: false); + } + } + + // A local helper function to avoid creating an instance of the generated delegate helper class + // when no predictor is registered, or no registered predictor accepts this feedback. + static Action GetCallBack(PredictionClient client, IReadOnlyList history) + { + return predictor => predictor.OnCommandLineAccepted(client, history); + } + } + + /// + /// Allow registered predictors to know the execution result (success/failure) of the last accepted command line. + /// + /// Represents the client that initiates the call. + /// The last accepted command line. + /// Whether the execution of the last command line was successful. + public static void OnCommandLineExecuted(PredictionClient client, string commandLine, bool success) + { + var predictors = SubsystemManager.GetSubsystems(); + if (predictors.Count == 0) + { + return; + } + + Action? callBack = null; + foreach (ICommandPredictor predictor in predictors) + { + if (predictor.CanAcceptFeedback(client, PredictorFeedbackKind.CommandLineExecuted)) + { + callBack ??= GetCallBack(client, commandLine, success); + ThreadPool.QueueUserWorkItem(callBack, predictor, preferLocal: false); + } + } + + // A local helper function to avoid creating an instance of the generated delegate helper class + // when no predictor is registered, or no registered predictor accepts this feedback. + static Action GetCallBack(PredictionClient client, string commandLine, bool success) + { + return predictor => predictor.OnCommandLineExecuted(client, commandLine, success); + } + } + + /// + /// Send feedback to a predictor when one or more suggestions from it were displayed to the user. + /// + /// Represents the client that initiates the call. + /// The identifier of the predictor whose prediction result was accepted. + /// The mini-session where the displayed suggestions came from. + /// + /// When the value is greater than 0, it's the number of displayed suggestions from the list returned in , starting from the index 0. + /// When the value is less than or equal to 0, it means a single suggestion from the list got displayed, and the index is the absolute value. + /// + public static void OnSuggestionDisplayed(PredictionClient client, Guid predictorId, uint session, int countOrIndex) + { + var predictors = SubsystemManager.GetSubsystems(); + if (predictors.Count == 0) + { + return; + } + foreach (ICommandPredictor predictor in predictors) { - if (predictor.SupportEarlyProcessing) + if (predictor.Id == predictorId) { - ThreadPool.QueueUserWorkItem( - state => state.StartEarlyProcessing(history), - predictor, - preferLocal: false); + if (predictor.CanAcceptFeedback(client, PredictorFeedbackKind.SuggestionDisplayed)) + { + Action callBack = GetCallBack(client, session, countOrIndex); + ThreadPool.QueueUserWorkItem(callBack, predictor, preferLocal: false); + } + + break; } } + + // A local helper function to avoid creating an instance of the generated delegate helper class + // when no predictor is registered, or no registered predictor accepts this feedback. + static Action GetCallBack(PredictionClient client, uint session, int countOrIndex) + { + return predictor => predictor.OnSuggestionDisplayed(client, session, countOrIndex); + } } /// - /// Send feedback to predictors about their last suggestions. + /// Send feedback to a predictor when a suggestion from it was accepted. /// + /// Represents the client that initiates the call. /// The identifier of the predictor whose prediction result was accepted. + /// The mini-session where the accepted suggestion came from. /// The accepted suggestion text. - public static void OnSuggestionAccepted(Guid predictorId, string suggestionText) + public static void OnSuggestionAccepted(PredictionClient client, Guid predictorId, uint session, string suggestionText) { Requires.NotNullOrEmpty(suggestionText, nameof(suggestionText)); @@ -157,14 +259,24 @@ public static void OnSuggestionAccepted(Guid predictorId, string suggestionText) foreach (ICommandPredictor predictor in predictors) { - if (predictor.AcceptFeedback && predictor.Id == predictorId) + if (predictor.Id == predictorId) { - ThreadPool.QueueUserWorkItem( - state => state.OnSuggestionAccepted(suggestionText), - predictor, - preferLocal: false); + if (predictor.CanAcceptFeedback(client, PredictorFeedbackKind.SuggestionAccepted)) + { + Action callBack = GetCallBack(client, session, suggestionText); + ThreadPool.QueueUserWorkItem(callBack, predictor, preferLocal: false); + } + + break; } } + + // A local helper function to avoid creating an instance of the generated delegate helper class + // when no predictor is registered, or no registered predictor accepts this feedback. + static Action GetCallBack(PredictionClient client, uint session, string suggestionText) + { + return predictor => predictor.OnSuggestionAccepted(client, session, suggestionText); + } } } } diff --git a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs index 0edd768cf89..bd8a48a85db 100644 --- a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs +++ b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs @@ -9,7 +9,7 @@ using System.Management.Automation.Language; using System.Threading; -namespace System.Management.Automation.Subsystem +namespace System.Management.Automation.Subsystem.Prediction { /// /// Interface for implementing a predictor plugin. @@ -27,41 +27,131 @@ public interface ICommandPredictor : ISubsystem SubsystemKind ISubsystem.Kind => SubsystemKind.CommandPredictor; /// - /// Gets a value indicating whether the predictor supports early processing. + /// Get the predictive suggestions. It indicates the start of a suggestion rendering session. /// - bool SupportEarlyProcessing { get; } + /// Represents the client that initiates the call. + /// The object to be used for prediction. + /// The cancellation token to cancel the prediction. + /// An instance of . + SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken); + + /// + /// Gets a value indicating whether the predictor accepts a specific kind of feedback. + /// + /// Represents the client that initiates the call. + /// A specific type of feedback. + /// True or false, to indicate whether the specific feedback is accepted. + bool CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback); /// - /// Gets a value indicating whether the predictor accepts feedback about the previous suggestion. + /// One or more suggestions provided by the predictor were displayed to the user. /// - bool AcceptFeedback { get; } + /// Represents the client that initiates the call. + /// The mini-session where the displayed suggestions came from. + /// + /// When the value is greater than 0, it's the number of displayed suggestions from the list returned in , starting from the index 0. + /// When the value is less than or equal to 0, it means a single suggestion from the list got displayed, and the index is the absolute value. + /// + void OnSuggestionDisplayed(PredictionClient client, uint session, int countOrIndex); + + /// + /// The suggestion provided by the predictor was accepted. + /// + /// Represents the client that initiates the call. + /// Represents the mini-session where the accepted suggestion came from. + /// The accepted suggestion text. + void OnSuggestionAccepted(PredictionClient client, uint session, string acceptedSuggestion); /// /// A command line was accepted to execute. /// The predictor can start processing early as needed with the latest history. /// + /// Represents the client that initiates the call. /// History command lines provided as references for prediction. - void StartEarlyProcessing(IReadOnlyList history); + void OnCommandLineAccepted(PredictionClient client, IReadOnlyList history); /// - /// The suggestion given by the predictor was accepted. + /// A command line was done execution. /// - /// The accepted suggestion text. - void OnSuggestionAccepted(string acceptedSuggestion); + /// Represents the client that initiates the call. + /// The last accepted command line. + /// Shows whether the execution was successful. + void OnCommandLineExecuted(PredictionClient client, string commandLine, bool success); + } + /// + /// Kinds of feedback a predictor can choose to accept. + /// + public enum PredictorFeedbackKind + { /// - /// Get the predictive suggestions. + /// Feedback when one or more suggestions are displayed to the user. /// - /// The object to be used for prediction. - /// The cancellation token to cancel the prediction. - /// A list of predictive suggestions. - List? GetSuggestion(PredictionContext context, CancellationToken cancellationToken); + SuggestionDisplayed, + + /// + /// Feedback when a suggestion is accepted by the user. + /// + SuggestionAccepted, + + /// + /// Feedback when a command line is accepted by the user. + /// + CommandLineAccepted, + + /// + /// Feedback when the accepted command line finishes its execution. + /// + CommandLineExecuted, + } + + /// + /// Kinds of prediction clients. + /// + public enum PredictionClientKind + { + /// + /// A terminal client, representing the command-line experience. + /// + Terminal, + + /// + /// An editor client, representing the editor experience. + /// + Editor, + } + + /// + /// The class represents a client that interacts with predictors. + /// + public sealed class PredictionClient + { + /// + /// Gets the client name. + /// + public string Name { get; } + + /// + /// Gets the client kind. + /// + public PredictionClientKind Kind { get; } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the interactive client. + /// Kind of the interactive client. + public PredictionClient(string name, PredictionClientKind kind) + { + Name = name; + Kind = kind; + } } /// /// Context information about the user input. /// - public class PredictionContext + public sealed class PredictionContext { /// /// Gets the abstract syntax tree (AST) generated from parsing the user input. @@ -160,4 +250,47 @@ public PredictiveSuggestion(string suggestion, string? toolTip) ToolTip = toolTip; } } + + /// + /// A package returned from . + /// + public struct SuggestionPackage + { + /// + /// Gets the mini-session that represents a specific invocation to . + /// When it's not specified, it's considered by a client that the predictor doesn't expect feedback. + /// + public uint? Session { get; } + + /// + /// Gets the suggestion entries returned from that mini-session. + /// + public List? SuggestionEntries { get; } + + /// + /// Initializes a new instance of the struct without providing a session id. + /// Note that, when a session id is not specified, it's considered by a client that the predictor doesn't expect feedback. + /// + /// The suggestions to return. + public SuggestionPackage(List suggestionEntries) + { + Requires.NotNullOrEmpty(suggestionEntries, nameof(suggestionEntries)); + + Session = null; + SuggestionEntries = suggestionEntries; + } + + /// + /// Initializes a new instance of the struct with the mini-session id and the suggestions. + /// + /// The mini-session where suggestions came from. + /// The suggestions to return. + public SuggestionPackage(uint session, List suggestionEntries) + { + Requires.NotNullOrEmpty(suggestionEntries, nameof(suggestionEntries)); + + Session = session; + SuggestionEntries = suggestionEntries; + } + } } diff --git a/src/System.Management.Automation/engine/Subsystem/Commands/GetSubsystemCommand.cs b/src/System.Management.Automation/engine/Subsystem/Commands/GetPSSubsystemCommand.cs similarity index 88% rename from src/System.Management.Automation/engine/Subsystem/Commands/GetSubsystemCommand.cs rename to src/System.Management.Automation/engine/Subsystem/Commands/GetPSSubsystemCommand.cs index 666cf9c5568..1ad79404f51 100644 --- a/src/System.Management.Automation/engine/Subsystem/Commands/GetSubsystemCommand.cs +++ b/src/System.Management.Automation/engine/Subsystem/Commands/GetPSSubsystemCommand.cs @@ -6,12 +6,12 @@ namespace System.Management.Automation.Subsystem { /// - /// Implementation of 'Get-Subsystem' cmdlet. + /// Implementation of 'Get-PSSubsystem' cmdlet. /// [Experimental("PSSubsystemPluginModel", ExperimentAction.Show)] - [Cmdlet(VerbsCommon.Get, "Subsystem", DefaultParameterSetName = AllSet)] + [Cmdlet(VerbsCommon.Get, "PSSubsystem", DefaultParameterSetName = AllSet)] [OutputType(typeof(SubsystemInfo))] - public sealed class GetSubsystemCommand : PSCmdlet + public sealed class GetPSSubsystemCommand : PSCmdlet { private const string AllSet = "GetAllSet"; private const string TypeSet = "GetByTypeSet"; @@ -37,7 +37,7 @@ protected override void ProcessRecord() switch (ParameterSetName) { case AllSet: - WriteObject(SubsystemManager.GetAllSubsystemInfo()); + WriteObject(SubsystemManager.GetAllSubsystemInfo(), enumerateCollection: true); break; case KindSet: WriteObject(SubsystemManager.GetSubsystemInfo(Kind)); diff --git a/src/System.Management.Automation/engine/Subsystem/DscSubsystem/ICrossPlatformDsc.cs b/src/System.Management.Automation/engine/Subsystem/DscSubsystem/ICrossPlatformDsc.cs new file mode 100644 index 00000000000..f16c6f245a3 --- /dev/null +++ b/src/System.Management.Automation/engine/Subsystem/DscSubsystem/ICrossPlatformDsc.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Management.Automation.Language; + +namespace System.Management.Automation.Subsystem.DSC +{ + /// + /// Interface for implementing a cross platform desired state configuration component. + /// + public interface ICrossPlatformDsc : ISubsystem + { + /// + /// Subsystem kind. + /// + SubsystemKind ISubsystem.Kind => SubsystemKind.CrossPlatformDsc; + + /// + /// Default implementation. No function is required for this subsystem. + /// + Dictionary? ISubsystem.FunctionsToDefine => null; + + /// + /// DSC initializer function. + /// + void LoadDefaultKeywords(Collection errors); + + /// + /// Clear internal class caches. + /// + void ClearCache(); + + /// + /// Returns resource usage string. + /// + string GetDSCResourceUsageString(DynamicKeyword keyword); + + /// + /// Checks if a string is one of dynamic keywords that can be used in both configuration and meta configuration. + /// + bool IsSystemResourceName(string name); + + /// + /// Checks if a string matches default module name used for meta configuration resources. + /// + bool IsDefaultModuleNameForMetaConfigResource(string name); + } +} diff --git a/src/System.Management.Automation/engine/Subsystem/ISubsystem.cs b/src/System.Management.Automation/engine/Subsystem/ISubsystem.cs index e19f37f06c7..db842f435bb 100644 --- a/src/System.Management.Automation/engine/Subsystem/ISubsystem.cs +++ b/src/System.Management.Automation/engine/Subsystem/ISubsystem.cs @@ -17,6 +17,11 @@ public enum SubsystemKind /// Component that provides predictive suggestions to commandline input. /// CommandPredictor = 1, + + /// + /// Cross platform desired state configuration component. + /// + CrossPlatformDsc = 2, } /// diff --git a/src/System.Management.Automation/engine/Subsystem/SubsystemInfo.cs b/src/System.Management.Automation/engine/Subsystem/SubsystemInfo.cs index b0b31504da4..ae555e8d187 100644 --- a/src/System.Management.Automation/engine/Subsystem/SubsystemInfo.cs +++ b/src/System.Management.Automation/engine/Subsystem/SubsystemInfo.cs @@ -90,6 +90,7 @@ private protected SubsystemInfo(SubsystemKind kind, Type subsystemType) } private protected abstract void AddImplementation(ISubsystem rawImpl); + private protected abstract ISubsystem RemoveImplementation(Guid id); internal void RegisterImplementation(ISubsystem impl) @@ -254,7 +255,7 @@ private protected override void AddImplementation(ISubsystem rawImpl) list.Add(impl); _registeredImpls = new ReadOnlyCollection(list); - _cachedImplInfos = new ReadOnlyCollection(list.ConvertAll(s => new ImplementationInfo(s))); + _cachedImplInfos = new ReadOnlyCollection(list.ConvertAll(static s => new ImplementationInfo(s))); } } @@ -325,7 +326,7 @@ private protected override ISubsystem RemoveImplementation(Guid id) } _registeredImpls = new ReadOnlyCollection(list); - _cachedImplInfos = new ReadOnlyCollection(list.ConvertAll(s => new ImplementationInfo(s))); + _cachedImplInfos = new ReadOnlyCollection(list.ConvertAll(static s => new ImplementationInfo(s))); } return target; diff --git a/src/System.Management.Automation/engine/Subsystem/SubsystemManager.cs b/src/System.Management.Automation/engine/Subsystem/SubsystemManager.cs index 1e32436e6da..d603436790c 100644 --- a/src/System.Management.Automation/engine/Subsystem/SubsystemManager.cs +++ b/src/System.Management.Automation/engine/Subsystem/SubsystemManager.cs @@ -8,6 +8,8 @@ using System.Collections.ObjectModel; using System.Linq; using System.Management.Automation.Internal; +using System.Management.Automation.Subsystem.DSC; +using System.Management.Automation.Subsystem.Prediction; namespace System.Management.Automation.Subsystem { @@ -28,6 +30,11 @@ static SubsystemManager() SubsystemKind.CommandPredictor, allowUnregistration: true, allowMultipleRegistration: true), + + SubsystemInfo.Create( + SubsystemKind.CrossPlatformDsc, + allowUnregistration: true, + allowMultipleRegistration: false), }; var subSystemTypeMap = new Dictionary(subsystems.Length); @@ -59,7 +66,7 @@ static SubsystemManager() /// directly interacting with the implementation proxy object of `IPrediction`. /// /// The concrete subsystem base type. - /// The most recently registered implmentation object of the concrete subsystem. + /// The most recently registered implementation object of the concrete subsystem. internal static TConcreteSubsystem? GetSubsystem() where TConcreteSubsystem : class, ISubsystem { @@ -80,7 +87,7 @@ static SubsystemManager() /// Return an empty collection when the given subsystem is not registered. /// /// The concrete subsystem base type. - /// A readonly collection of all implmentation objects registered for the concrete subsystem. + /// A readonly collection of all implementation objects registered for the concrete subsystem. internal static ReadOnlyCollection GetSubsystems() where TConcreteSubsystem : class, ISubsystem { @@ -217,7 +224,7 @@ private static void RegisterSubsystem(SubsystemInfo subsystemInfo, ISubsystem pr nameof(proxy)); } - if (subsystemInfo.RequiredCmdlets.Any() || subsystemInfo.RequiredFunctions.Any()) + if (subsystemInfo.RequiredCmdlets.Count > 0 || subsystemInfo.RequiredFunctions.Count > 0) { // Process 'proxy.CmdletImplementationAssembly' and 'proxy.FunctionsToDefine' // Functions are added to global scope. @@ -265,7 +272,7 @@ public static void UnregisterSubsystem(SubsystemKind kind, Guid id) private static void UnregisterSubsystem(SubsystemInfo subsystemInfo, Guid id) { - if (subsystemInfo.RequiredCmdlets.Any() || subsystemInfo.RequiredFunctions.Any()) + if (subsystemInfo.RequiredCmdlets.Count > 0 || subsystemInfo.RequiredFunctions.Count > 0) { throw new NotSupportedException("NotSupported yet: unregister subsystem that introduced new cmdlets/functions."); } @@ -273,7 +280,14 @@ private static void UnregisterSubsystem(SubsystemInfo subsystemInfo, Guid id) ISubsystem impl = subsystemInfo.UnregisterImplementation(id); if (impl is IDisposable disposable) { - disposable.Dispose(); + try + { + disposable.Dispose(); + } + catch + { + // It's OK to ignore all exceptions when disposing the object. + } } } diff --git a/src/System.Management.Automation/engine/ThirdPartyAdapter.cs b/src/System.Management.Automation/engine/ThirdPartyAdapter.cs index 9840aaa0555..bde0c0f3483 100644 --- a/src/System.Management.Automation/engine/ThirdPartyAdapter.cs +++ b/src/System.Management.Automation/engine/ThirdPartyAdapter.cs @@ -279,7 +279,7 @@ protected override string PropertyType(PSProperty property, bool forDisplay) return propertyTypeName ?? "System.Object"; } - private PSPropertyAdapter _externalAdapter; + private readonly PSPropertyAdapter _externalAdapter; } /// @@ -351,7 +351,7 @@ public virtual Collection GetTypeNameHierarchy(object baseObject) /// /// Returns a property if it's name matches the specified , otherwise null. /// - /// An adapted property if the predicate matches, or null. + /// An adapted property if the predicate matches, or . public virtual PSAdaptedProperty GetFirstPropertyOrDefault(object baseObject, MemberNamePredicate predicate) { foreach (var property in GetProperties(baseObject)) diff --git a/src/System.Management.Automation/engine/TypeMetadata.cs b/src/System.Management.Automation/engine/TypeMetadata.cs index 192042a3def..31a6adeab73 100644 --- a/src/System.Management.Automation/engine/TypeMetadata.cs +++ b/src/System.Management.Automation/engine/TypeMetadata.cs @@ -265,23 +265,23 @@ internal ParameterFlags Flags get { ParameterFlags flags = 0; - if (IsMandatory) { flags = flags | ParameterFlags.Mandatory; } + if (IsMandatory) { flags |= ParameterFlags.Mandatory; } - if (ValueFromPipeline) { flags = flags | ParameterFlags.ValueFromPipeline; } + if (ValueFromPipeline) { flags |= ParameterFlags.ValueFromPipeline; } - if (ValueFromPipelineByPropertyName) { flags = flags | ParameterFlags.ValueFromPipelineByPropertyName; } + if (ValueFromPipelineByPropertyName) { flags |= ParameterFlags.ValueFromPipelineByPropertyName; } - if (ValueFromRemainingArguments) { flags = flags | ParameterFlags.ValueFromRemainingArguments; } + if (ValueFromRemainingArguments) { flags |= ParameterFlags.ValueFromRemainingArguments; } return flags; } set { - this.IsMandatory = (ParameterFlags.Mandatory == (value & ParameterFlags.Mandatory)); - this.ValueFromPipeline = (ParameterFlags.ValueFromPipeline == (value & ParameterFlags.ValueFromPipeline)); - this.ValueFromPipelineByPropertyName = (ParameterFlags.ValueFromPipelineByPropertyName == (value & ParameterFlags.ValueFromPipelineByPropertyName)); - this.ValueFromRemainingArguments = (ParameterFlags.ValueFromRemainingArguments == (value & ParameterFlags.ValueFromRemainingArguments)); + this.IsMandatory = ((value & ParameterFlags.Mandatory) == ParameterFlags.Mandatory); + this.ValueFromPipeline = ((value & ParameterFlags.ValueFromPipeline) == ParameterFlags.ValueFromPipeline); + this.ValueFromPipelineByPropertyName = ((value & ParameterFlags.ValueFromPipelineByPropertyName) == ParameterFlags.ValueFromPipelineByPropertyName); + this.ValueFromRemainingArguments = ((value & ParameterFlags.ValueFromRemainingArguments) == ParameterFlags.ValueFromRemainingArguments); } } @@ -895,7 +895,7 @@ internal string GetProxyParameterData(string prefix, string paramNameOverride, b /// /// Attribute's proxy string. /// - private string GetProxyAttributeData(Attribute attrib, string prefix) + private static string GetProxyAttributeData(Attribute attrib, string prefix) { string result; @@ -978,7 +978,7 @@ private string GetProxyAttributeData(Attribute attrib, string prefix) string or = string.Empty; string[] regexOptionEnumValues = Enum.GetNames(typeof(System.Text.RegularExpressions.RegexOptions)); - foreach(string regexOption in regexOptionEnumValues) + foreach (string regexOption in regexOptionEnumValues) { System.Text.RegularExpressions.RegexOptions option = (System.Text.RegularExpressions.RegexOptions) Enum.Parse( typeof(System.Text.RegularExpressions.RegexOptions), @@ -1274,7 +1274,7 @@ internal InternalParameterMetadata(Type type, bool processingDynamicParameters) /// This member is null in all cases except when constructed with using reflection /// against the Type. /// - private Type _type; + private readonly Type _type; /// /// The flags used when reflecting against the object to create the metadata. @@ -1367,7 +1367,7 @@ private void ConstructCompiledParametersUsingReflection(bool processingDynamicPa } } - private void CheckForReservedParameter(string name) + private static void CheckForReservedParameter(string name) { if (name.Equals("SelectProperty", StringComparison.OrdinalIgnoreCase) || @@ -1544,10 +1544,9 @@ private static bool IsMemberAParameter(MemberInfo member) /// The cache of the type metadata. The key for the cache is the Type.FullName. /// Note, this is a case-sensitive dictionary because Type names are case sensitive. /// - private static System.Collections.Concurrent.ConcurrentDictionary s_parameterMetadataCache = + private static readonly System.Collections.Concurrent.ConcurrentDictionary s_parameterMetadataCache = new System.Collections.Concurrent.ConcurrentDictionary(StringComparer.Ordinal); #endregion Metadata cache } } - diff --git a/src/System.Management.Automation/engine/TypeTable.cs b/src/System.Management.Automation/engine/TypeTable.cs index a58bc094458..0bcd276a45b 100644 --- a/src/System.Management.Automation/engine/TypeTable.cs +++ b/src/System.Management.Automation/engine/TypeTable.cs @@ -277,7 +277,7 @@ private void CheckStandardNote(TypeMemberData member, TypeData typeData, Acti } } - private bool CheckStandardPropertySet(TypeMemberData member, TypeData typeData, Action setter) + private static bool CheckStandardPropertySet(TypeMemberData member, TypeData typeData, Action setter) { var propertySet = member as PropertySetData; if (propertySet != null) @@ -459,7 +459,7 @@ private TypeData Read_Type() { if (m.Name.Equals(TypeTable.DefaultDisplayProperty, StringComparison.OrdinalIgnoreCase)) { - CheckStandardNote(m, typeData, (t, v) => t.DefaultDisplayProperty = v, Converter); + CheckStandardNote(m, typeData, static (t, v) => t.DefaultDisplayProperty = v, Converter); } else if (m.Name.Equals(TypeTable.DefaultDisplayPropertySet, StringComparison.OrdinalIgnoreCase)) { @@ -477,11 +477,11 @@ private TypeData Read_Type() } else if (m.Name.Equals(TypeTable.SerializationMethodNode, StringComparison.OrdinalIgnoreCase)) { - CheckStandardNote(m, typeData, (t, v) => t.SerializationMethod = v, Converter); + CheckStandardNote(m, typeData, static (t, v) => t.SerializationMethod = v, Converter); } else if (m.Name.Equals(TypeTable.SerializationDepth, StringComparison.OrdinalIgnoreCase)) { - CheckStandardNote(m, typeData, (t, v) => t.SerializationDepth = v, Converter); + CheckStandardNote(m, typeData, static (t, v) => t.SerializationDepth = v, Converter); } else if (m.Name.Equals(TypeTable.StringSerializationSource, StringComparison.OrdinalIgnoreCase)) { @@ -504,11 +504,11 @@ private TypeData Read_Type() } else if (m.Name.Equals(TypeTable.InheritPropertySerializationSet, StringComparison.OrdinalIgnoreCase)) { - CheckStandardNote(m, typeData, (t, v) => t.InheritPropertySerializationSet = v, BoolConverter); + CheckStandardNote(m, typeData, static (t, v) => t.InheritPropertySerializationSet = v, BoolConverter); } else if (m.Name.Equals(TypeTable.TargetTypeForDeserialization, StringComparison.OrdinalIgnoreCase)) { - CheckStandardNote(m, typeData, (t, v) => t.TargetTypeForDeserialization = v, Converter); + CheckStandardNote(m, typeData, static (t, v) => t.TargetTypeForDeserialization = v, Converter); } else { @@ -1683,7 +1683,7 @@ public ConsolidatedString(IEnumerable strings) internal static readonly IEqualityComparer EqualityComparer = new ConsolidatedStringEqualityComparer(); - private class ConsolidatedStringEqualityComparer : IEqualityComparer + private sealed class ConsolidatedStringEqualityComparer : IEqualityComparer { bool IEqualityComparer.Equals(ConsolidatedString x, ConsolidatedString y) { @@ -1752,7 +1752,7 @@ internal void AddError(string typeName, int errorLineNumber, string resourceStri [Serializable] public class TypeTableLoadException : RuntimeException { - private Collection _errors; + private readonly Collection _errors; #region Constructors @@ -3191,7 +3191,7 @@ private static bool CheckStandardMembers(ConcurrentBag errors, string ty } while (false); - if (serializationSettingsOk == false) + if (!serializationSettingsOk) { AddError(errors, typeName, TypesXmlStrings.SerializationSettingsIgnored); members.Remove(InheritPropertySerializationSet); @@ -3290,9 +3290,14 @@ private static void AddError(ConcurrentBag errors, string typeName, stri #region add members from TypeData - private static void ProcessMembersData(ConcurrentBag errors, string typeName, IEnumerable membersData, PSMemberInfoInternalCollection membersCollection, bool isOverride) + private static void ProcessMembersData( + ConcurrentBag errors, + string typeName, + Dictionary membersData, + PSMemberInfoInternalCollection membersCollection, + bool isOverride) { - foreach (TypeMemberData typeMember in membersData) + foreach (TypeMemberData typeMember in membersData.Values) { typeMember.Process(errors, typeName, membersCollection, isOverride); } @@ -3448,12 +3453,12 @@ internal static void ProcessMemberSetData(ConcurrentBag errors, string t private static void ProcessStandardMembers( ConcurrentBag errors, string typeName, - IEnumerable standardMembers, - IEnumerable propertySets, + Dictionary standardMembers, + List propertySets, PSMemberInfoInternalCollection membersCollection, bool isOverride) { - int newMemberCount = standardMembers.Count() + propertySets.Count(); + int newMemberCount = standardMembers.Count + propertySets.Count; // If StandardMembers do not exists, we follow the original logic to create the StandardMembers if (membersCollection[PSStandardMembers] == null) @@ -3678,7 +3683,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat string typeName = typeData.TypeName; Dbg.Assert(!string.IsNullOrEmpty(typeName), "TypeData class guarantees the typeName is not null and not empty"); - var propertySets = new Collection(); + var propertySets = new List(); if (typeData.DefaultDisplayPropertySet != null) { propertySets.Add(typeData.DefaultDisplayPropertySet); @@ -3709,7 +3714,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat if (typeData.Members.Count > 0) { typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(collectionSize)); - ProcessMembersData(errors, typeName, typeData.Members.Values, typeMembers, typeData.IsOverride); + ProcessMembersData(errors, typeName, typeData.Members, typeMembers, typeData.IsOverride); foreach (var memberName in typeData.Members.Keys) { @@ -3724,7 +3729,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(capacity: 1)); } - ProcessStandardMembers(errors, typeName, typeData.StandardMembers.Values, propertySets, typeMembers, typeData.IsOverride); + ProcessStandardMembers(errors, typeName, typeData.StandardMembers, propertySets, typeMembers, typeData.IsOverride); } if (typeData.TypeConverter != null) @@ -3937,7 +3942,7 @@ internal TypeTable(IEnumerable typeFiles, AuthorizationManager authoriza _typeFileList.Add(typefile); } - if (errors.Count > 0) + if (!errors.IsEmpty) { throw new TypeTableLoadException(errors); } @@ -3970,8 +3975,7 @@ internal Collection GetSpecificProperties(ConsolidatedString types) } PSMemberSet settings = typeMembers[PSStandardMembers] as PSMemberSet; - PSPropertySet typeProperties = settings?.Members[PropertySerializationSet] as PSPropertySet; - if (typeProperties == null) + if (!(settings?.Members[PropertySerializationSet] is PSPropertySet typeProperties)) { continue; } @@ -4563,7 +4567,7 @@ internal void Initialize( /// /// Helper method to load content for a module. /// - private string GetModuleContents( + private static string GetModuleContents( string moduleName, string fileToLoad, ConcurrentBag errors, diff --git a/src/System.Management.Automation/engine/TypeTable_Types_Ps1Xml.cs b/src/System.Management.Automation/engine/TypeTable_Types_Ps1Xml.cs index aad2f70246e..648bafe152c 100644 --- a/src/System.Management.Automation/engine/TypeTable_Types_Ps1Xml.cs +++ b/src/System.Management.Automation/engine/TypeTable_Types_Ps1Xml.cs @@ -639,7 +639,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) #region System.IO.DirectoryInfo typeName = @"System.IO.DirectoryInfo"; - typeMembers = _extendedMembers.GetOrAdd(typeName, key => new PSMemberInfoInternalCollection(capacity: 9)); + typeMembers = _extendedMembers.GetOrAdd(typeName, static key => new PSMemberInfoInternalCollection(capacity: 9)); // Process regular members. newMembers.Add(@"Mode"); @@ -680,10 +680,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) AddMember( errors, typeName, - new PSCodeProperty( - @"Target", - GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), @"GetTarget"), - setterCodeReference: null), + new PSAliasProperty(@"Target", @"LinkTarget", conversionType: null), typeMembers, isOverride: false); @@ -755,7 +752,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) #region System.IO.FileInfo typeName = @"System.IO.FileInfo"; - typeMembers = _extendedMembers.GetOrAdd(typeName, key => new PSMemberInfoInternalCollection(capacity: 10)); + typeMembers = _extendedMembers.GetOrAdd(typeName, static key => new PSMemberInfoInternalCollection(capacity: 10)); // Process regular members. newMembers.Add(@"Mode"); @@ -808,10 +805,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) AddMember( errors, typeName, - new PSCodeProperty( - @"Target", - GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), @"GetTarget"), - setterCodeReference: null), + new PSAliasProperty(@"Target", @"LinkTarget", conversionType: null), typeMembers, isOverride: false); @@ -1047,7 +1041,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) #region System.Diagnostics.Process typeName = @"System.Diagnostics.Process"; - typeMembers = _extendedMembers.GetOrAdd(typeName, key => new PSMemberInfoInternalCollection(capacity: 19)); + typeMembers = _extendedMembers.GetOrAdd(typeName, static key => new PSMemberInfoInternalCollection(capacity: 19)); // Process regular members. newMembers.Add(@"PSConfiguration"); @@ -4068,7 +4062,7 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) #region System.Security.AccessControl.ObjectSecurity typeName = @"System.Security.AccessControl.ObjectSecurity"; - typeMembers = _extendedMembers.GetOrAdd(typeName, key => new PSMemberInfoInternalCollection(capacity: 7)); + typeMembers = _extendedMembers.GetOrAdd(typeName, static key => new PSMemberInfoInternalCollection(capacity: 7)); Type securityDescriptorCommandsBaseType = TypeResolver.ResolveType("Microsoft.PowerShell.Commands.SecurityDescriptorCommandsBase", exception: out _); // Process regular members. @@ -9227,46 +9221,42 @@ private void Process_Types_Ps1Xml(string filePath, ConcurrentBag errors) #if UNIX #region UnixStat + typeName = @"System.IO.FileSystemInfo"; + typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(capacity: 1)); - if (ExperimentalFeature.IsEnabled("PSUnixFileStat")) - { - typeName = @"System.IO.FileSystemInfo"; - typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(capacity: 1)); - - // Where we have a method to invoke below, first check to be sure that the object is present - // to avoid null reference issues - newMembers.Add(@"UnixMode"); - AddMember( - errors, - typeName, - new PSScriptProperty(@"UnixMode", GetScriptBlock(@"if ($this.UnixStat) { $this.UnixStat.GetModeString() }")), - typeMembers, - isOverride: false); - - newMembers.Add(@"User"); - AddMember( - errors, - typeName, - new PSScriptProperty(@"User", GetScriptBlock(@" if ($this.UnixStat) { $this.UnixStat.GetUserName() } ")), - typeMembers, - isOverride: false); - - newMembers.Add(@"Group"); - AddMember( - errors, - typeName, - new PSScriptProperty(@"Group", GetScriptBlock(@" if ($this.UnixStat) { $this.UnixStat.GetGroupName() } ")), - typeMembers, - isOverride: false); - - newMembers.Add(@"Size"); - AddMember( - errors, - typeName, - new PSScriptProperty(@"Size", GetScriptBlock(@"$this.UnixStat.Size")), - typeMembers, - isOverride: false); - } + // Where we have a method to invoke below, first check to be sure that the object is present + // to avoid null reference issues + newMembers.Add(@"UnixMode"); + AddMember( + errors, + typeName, + new PSScriptProperty(@"UnixMode", GetScriptBlock(@"if ($this.UnixStat) { $this.UnixStat.GetModeString() }")), + typeMembers, + isOverride: false); + + newMembers.Add(@"User"); + AddMember( + errors, + typeName, + new PSScriptProperty(@"User", GetScriptBlock(@" if ($this.UnixStat) { $this.UnixStat.GetUserName() } ")), + typeMembers, + isOverride: false); + + newMembers.Add(@"Group"); + AddMember( + errors, + typeName, + new PSScriptProperty(@"Group", GetScriptBlock(@" if ($this.UnixStat) { $this.UnixStat.GetGroupName() } ")), + typeMembers, + isOverride: false); + + newMembers.Add(@"Size"); + AddMember( + errors, + typeName, + new PSScriptProperty(@"Size", GetScriptBlock(@"$this.UnixStat.Size")), + typeMembers, + isOverride: false); #endregion #endif diff --git a/src/System.Management.Automation/engine/UserFeedbackParameters.cs b/src/System.Management.Automation/engine/UserFeedbackParameters.cs index feb1464d922..2fd26e5f32c 100644 --- a/src/System.Management.Automation/engine/UserFeedbackParameters.cs +++ b/src/System.Management.Automation/engine/UserFeedbackParameters.cs @@ -162,7 +162,7 @@ public SwitchParameter Confirm } #endregion parameters - private MshCommandRuntime _commandRuntime; + private readonly MshCommandRuntime _commandRuntime; } /// @@ -208,7 +208,6 @@ public SwitchParameter UseTransaction #endregion parameters - private MshCommandRuntime _commandRuntime; + private readonly MshCommandRuntime _commandRuntime; } } - diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 12f170937e0..f277dcb1e49 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -13,9 +13,7 @@ using System.Linq; using System.Management.Automation.Configuration; using System.Management.Automation.Internal; -using System.Management.Automation.Language; using System.Management.Automation.Remoting; -using System.Management.Automation.Runspaces; using System.Management.Automation.Security; using System.Numerics; using System.Reflection; @@ -49,7 +47,7 @@ internal static class Utils internal static bool TryCast(BigInteger value, out byte b) { - if (value < byte.MinValue || byte.MaxValue < value) + if (value < byte.MinValue || value > byte.MaxValue) { b = 0; return false; @@ -61,7 +59,7 @@ internal static bool TryCast(BigInteger value, out byte b) internal static bool TryCast(BigInteger value, out sbyte sb) { - if (value < sbyte.MinValue || sbyte.MaxValue < value) + if (value < sbyte.MinValue || value > sbyte.MaxValue) { sb = 0; return false; @@ -73,7 +71,7 @@ internal static bool TryCast(BigInteger value, out sbyte sb) internal static bool TryCast(BigInteger value, out short s) { - if (value < short.MinValue || short.MaxValue < value) + if (value < short.MinValue || value > short.MaxValue) { s = 0; return false; @@ -85,7 +83,7 @@ internal static bool TryCast(BigInteger value, out short s) internal static bool TryCast(BigInteger value, out ushort us) { - if (value < ushort.MinValue || ushort.MaxValue < value) + if (value < ushort.MinValue || value > ushort.MaxValue) { us = 0; return false; @@ -97,7 +95,7 @@ internal static bool TryCast(BigInteger value, out ushort us) internal static bool TryCast(BigInteger value, out int i) { - if (value < int.MinValue || int.MaxValue < value) + if (value < int.MinValue || value > int.MaxValue) { i = 0; return false; @@ -109,7 +107,7 @@ internal static bool TryCast(BigInteger value, out int i) internal static bool TryCast(BigInteger value, out uint u) { - if (value < uint.MinValue || uint.MaxValue < value) + if (value < uint.MinValue || value > uint.MaxValue) { u = 0; return false; @@ -121,7 +119,7 @@ internal static bool TryCast(BigInteger value, out uint u) internal static bool TryCast(BigInteger value, out long l) { - if (value < long.MinValue || long.MaxValue < value) + if (value < long.MinValue || value > long.MaxValue) { l = 0; return false; @@ -133,7 +131,7 @@ internal static bool TryCast(BigInteger value, out long l) internal static bool TryCast(BigInteger value, out ulong ul) { - if (value < ulong.MinValue || ulong.MaxValue < value) + if (value < ulong.MinValue || value > ulong.MaxValue) { ul = 0; return false; @@ -1391,96 +1389,11 @@ internal static bool Succeeded(int hresult) return hresult >= 0; } - // Attempt to determine the existing encoding - internal static Encoding GetEncoding(string path) - { - if (!File.Exists(path)) - { - return ClrFacade.GetDefaultEncoding(); - } - - byte[] initialBytes = new byte[100]; - int bytesRead = 0; - - try - { - using (FileStream stream = System.IO.File.OpenRead(path)) - { - using (BinaryReader reader = new BinaryReader(stream)) - { - bytesRead = reader.Read(initialBytes, 0, 100); - } - } - } - catch (IOException) - { - return ClrFacade.GetDefaultEncoding(); - } - - // Test for four-byte preambles - string preamble = null; - Encoding foundEncoding = ClrFacade.GetDefaultEncoding(); - - if (bytesRead > 3) - { - preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2], initialBytes[3]); - - if (encodingMap.TryGetValue(preamble, out foundEncoding)) - { - return foundEncoding; - } - } - - // Test for three-byte preambles - if (bytesRead > 2) - { - preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2]); - if (encodingMap.TryGetValue(preamble, out foundEncoding)) - { - return foundEncoding; - } - } - - // Test for two-byte preambles - if (bytesRead > 1) - { - preamble = string.Join("-", initialBytes[0], initialBytes[1]); - if (encodingMap.TryGetValue(preamble, out foundEncoding)) - { - return foundEncoding; - } - } - - // Check for binary - string initialBytesAsAscii = System.Text.Encoding.ASCII.GetString(initialBytes, 0, bytesRead); - if (initialBytesAsAscii.IndexOfAny(nonPrintableCharacters) >= 0) - { - return Encoding.Unicode; - } - - return Encoding.ASCII; - } - // BigEndianUTF32 encoding is possible, but requires creation internal static readonly Encoding BigEndianUTF32Encoding = new UTF32Encoding(bigEndian: true, byteOrderMark: true); // [System.Text.Encoding]::GetEncodings() | Where-Object { $_.GetEncoding().GetPreamble() } | // Add-Member ScriptProperty Preamble { $this.GetEncoding().GetPreamble() -join "-" } -PassThru | // Format-Table -Auto - internal static readonly Dictionary encodingMap = - new Dictionary() - { - { "255-254", Encoding.Unicode }, - { "254-255", Encoding.BigEndianUnicode }, - { "255-254-0-0", Encoding.UTF32 }, - { "0-0-254-255", BigEndianUTF32Encoding }, - { "239-187-191", Encoding.UTF8 }, - }; - - internal static readonly char[] nonPrintableCharacters = { - (char) 0, (char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7, (char) 8, - (char) 11, (char) 12, (char) 14, (char) 15, (char) 16, (char) 17, (char) 18, (char) 19, (char) 20, - (char) 21, (char) 22, (char) 23, (char) 24, (char) 25, (char) 26, (char) 28, (char) 29, (char) 30, - (char) 31, (char) 127, (char) 129, (char) 141, (char) 143, (char) 144, (char) 157 }; internal static readonly UTF8Encoding utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); @@ -1646,402 +1559,7 @@ internal static bool IsComObject(object obj) return oldMode; } - - #region Implicit Remoting Batching - - // Commands allowed to run on target remote session along with implicit remote commands - private static readonly HashSet AllowedCommands = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "ForEach-Object", - "Measure-Command", - "Measure-Object", - "Sort-Object", - "Where-Object" - }; - - // Determines if the typed command invokes implicit remoting module proxy functions in such - // a way as to allow simple batching, to reduce round trips between client and server sessions. - // Requirements: - // a. All commands must be implicit remoting module proxy commands targeted to the same remote session - // b. Except for *allowed* commands that can be safely run on remote session rather than client session - // c. Commands must be in a simple pipeline - internal static bool TryRunAsImplicitBatch(string command, Runspace runspace) - { - using (var ps = System.Management.Automation.PowerShell.Create()) - { - ps.Runspace = runspace; - - try - { - var scriptBlock = ScriptBlock.Create(command); - var scriptBlockAst = scriptBlock.Ast as ScriptBlockAst; - if (scriptBlockAst == null) - { - return false; - } - - // Make sure that this is a simple pipeline - string errorId; - string errorMsg; - scriptBlockAst.GetSimplePipeline(true, out errorId, out errorMsg); - if (errorId != null) - { - WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingNotASimplePipeline); - return false; - } - - // Run checker - var checker = new PipelineForBatchingChecker { ScriptBeingConverted = scriptBlockAst }; - scriptBlockAst.InternalVisit(checker); - - // If this is just a single command, there is no point in batching it - if (checker.Commands.Count < 2) - { - return false; - } - - // We have a valid batching candidate - - // Check commands - if (!TryGetCommandInfoList(ps, checker.Commands, out Collection cmdInfoList)) - { - return false; - } - - // All command modules must be implicit remoting modules from the same PSSession - var success = true; - var psSessionId = Guid.Empty; - foreach (var cmdInfo in cmdInfoList) - { - // Check for allowed command - string cmdName = (cmdInfo is AliasInfo aliasInfo) ? aliasInfo.ReferencedCommand.Name : cmdInfo.Name; - if (AllowedCommands.Contains(cmdName)) - { - continue; - } - - // Commands must be from implicit remoting module - if (cmdInfo.Module == null || string.IsNullOrEmpty(cmdInfo.ModuleName)) - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name)); - success = false; - break; - } - - // Commands must be from modules imported into the same remote session - if (cmdInfo.Module.PrivateData is System.Collections.Hashtable privateData) - { - var sessionIdString = privateData["ImplicitSessionId"] as string; - if (string.IsNullOrEmpty(sessionIdString)) - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name)); - success = false; - break; - } - - var sessionId = new Guid(sessionIdString); - if (psSessionId == Guid.Empty) - { - psSessionId = sessionId; - } - else if (psSessionId != sessionId) - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingWrongSession, cmdInfo.Name)); - success = false; - break; - } - } - else - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name)); - success = false; - break; - } - } - - if (success) - { - // - // Invoke command pipeline as entire pipeline on remote session - // - - // Update script to declare variables via Using keyword - if (checker.ValidVariables.Count > 0) - { - foreach (var variableName in checker.ValidVariables) - { - command = command.Replace(variableName, ("Using:" + variableName), StringComparison.OrdinalIgnoreCase); - } - - scriptBlock = ScriptBlock.Create(command); - } - - // Retrieve the PSSession runspace in which to run the batch script on - ps.Commands.Clear(); - ps.Commands.AddCommand("Get-PSSession").AddParameter("InstanceId", psSessionId); - var psSession = ps.Invoke().FirstOrDefault(); - if (psSession == null || (ps.Streams.Error.Count > 0) || (psSession.Availability != RunspaceAvailability.Available)) - { - WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingNoPSSession); - return false; - } - - WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingSuccess); - - // Create and invoke implicit remoting command pipeline - ps.Commands.Clear(); - ps.AddCommand("Invoke-Command").AddParameter("Session", psSession).AddParameter("ScriptBlock", scriptBlock).AddParameter("HideComputerName", true) - .AddCommand("Out-Default"); - foreach (var cmd in ps.Commands.Commands) - { - cmd.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); - } - - try - { - ps.Invoke(); - } - catch (Exception ex) - { - var errorRecord = new ErrorRecord(ex, "ImplicitRemotingBatchExecutionTerminatingError", ErrorCategory.InvalidOperation, null); - - ps.Commands.Clear(); - ps.AddCommand("Write-Error").AddParameter("InputObject", errorRecord).Invoke(); - } - - return true; - } - } - catch (ImplicitRemotingBatchingNotSupportedException ex) - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, "{0} : {1}", ex.Message, ex.ErrorId)); - } - catch (Exception ex) - { - WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingException, ex.Message)); - } - } - - return false; - } - - private static void WriteVerbose(PowerShell ps, string msg) - { - ps.Commands.Clear(); - ps.AddCommand("Write-Verbose").AddParameter("Message", msg).Invoke(); - } - - private const string WhereObjectCommandAlias = "?"; - - private static bool TryGetCommandInfoList(PowerShell ps, HashSet commandNames, out Collection cmdInfoList) - { - if (commandNames.Count == 0) - { - cmdInfoList = null; - return false; - } - - bool specialCaseWhereCommandAlias = commandNames.Contains(WhereObjectCommandAlias); - if (specialCaseWhereCommandAlias) - { - commandNames.Remove(WhereObjectCommandAlias); - } - - // Use Get-Command to collect CommandInfo from candidate commands, with correct precedence so - // that implicit remoting proxy commands will appear when available. - ps.Commands.Clear(); - ps.Commands.AddCommand("Get-Command").AddParameter("Name", commandNames.ToArray()); - cmdInfoList = ps.Invoke(); - if (ps.Streams.Error.Count > 0) - { - return false; - } - - // For special case '?' alias don't use Get-Command to retrieve command info, and instead - // use the GetCommand API. - if (specialCaseWhereCommandAlias) - { - var cmdInfo = ps.Runspace.ExecutionContext.SessionState.InvokeCommand.GetCommand(WhereObjectCommandAlias, CommandTypes.Alias); - if (cmdInfo == null) - { - return false; - } - - cmdInfoList.Add(cmdInfo); - } - - return true; - } - - #endregion - } - - #region ImplicitRemotingBatching - - // A visitor to walk an AST and validate that it is a candidate for implicit remoting batching. - // Based on ScriptBlockToPowerShellChecker. - internal class PipelineForBatchingChecker : AstVisitor - { - internal readonly HashSet ValidVariables = new HashSet(StringComparer.OrdinalIgnoreCase); - internal readonly HashSet Commands = new HashSet(StringComparer.OrdinalIgnoreCase); - - internal ScriptBlockAst ScriptBeingConverted { get; set; } - - public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst) - { - if (!variableExpressionAst.VariablePath.IsAnyLocal()) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "VariableTypeNotSupported"), - variableExpressionAst); - } - - if (variableExpressionAst.VariablePath.UnqualifiedPath != "_") - { - ValidVariables.Add(variableExpressionAst.VariablePath.UnqualifiedPath); - } - - return AstVisitAction.Continue; - } - - public override AstVisitAction VisitPipeline(PipelineAst pipelineAst) - { - if (pipelineAst.PipelineElements[0] is CommandExpressionAst) - { - // If the first element is a CommandExpression, this pipeline should be the value - // of a parameter. We want to avoid a scriptblock that contains only a pure expression. - // The check "pipelineAst.Parent.Parent == ScriptBeingConverted" guarantees we throw - // error on that kind of scriptblock. - - // Disallow pure expressions at the "top" level, but allow them otherwise. - // We want to catch: - // 1 | echo - // But we don't want to error out on: - // echo $(1) - // See the comment in VisitCommand on why it's safe to check Parent.Parent, we - // know that we have at least: - // * a NamedBlockAst (the end block) - // * a ScriptBlockAst (the ast we're comparing to) - if (pipelineAst.GetPureExpression() == null || pipelineAst.Parent.Parent == ScriptBeingConverted) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "PipelineStartingWithExpressionNotSupported"), - pipelineAst); - } - } - - return AstVisitAction.Continue; - } - - public override AstVisitAction VisitCommand(CommandAst commandAst) - { - if (commandAst.InvocationOperator == TokenKind.Dot) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "DotSourcingNotSupported"), - commandAst); - } - - /* - // Up front checking ensures that we have a simple script block, - // so we can safely assume that the parents are: - // * a PipelineAst - // * a NamedBlockAst (the end block) - // * a ScriptBlockAst (the ast we're comparing to) - // If that isn't the case, the conversion isn't allowed. It - // is also safe to assume that we have at least 3 parents, a script block can't be simpler. - if (commandAst.Parent.Parent.Parent != ScriptBeingConverted) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "CantConvertWithCommandInvocations not supported"), - commandAst); - } - */ - - if (commandAst.CommandElements[0] is ScriptBlockExpressionAst) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "ScriptBlockInvocationNotSupported"), - commandAst); - } - - var commandName = commandAst.GetCommandName(); - if (commandName != null) - { - Commands.Add(commandName); - } - - return AstVisitAction.Continue; - } - - public override AstVisitAction VisitMergingRedirection(MergingRedirectionAst redirectionAst) - { - if (redirectionAst.ToStream != RedirectionStream.Output) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "MergeRedirectionNotSupported"), - redirectionAst); - } - - return AstVisitAction.Continue; - } - - public override AstVisitAction VisitFileRedirection(FileRedirectionAst redirectionAst) - { - ThrowError( - new ImplicitRemotingBatchingNotSupportedException( - "FileRedirectionNotSupported"), - redirectionAst); - - return AstVisitAction.Continue; - } - - /* - public override AstVisitAction VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst) - { - ThrowError(new ImplicitRemotingBatchingNotSupportedException( - "ScriptBlocks not supported"), - scriptBlockExpressionAst); - - return AstVisitAction.SkipChildren; - } - */ - - public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst) - { - // Using expressions are not expected in Implicit remoting commands. - ThrowError(new ImplicitRemotingBatchingNotSupportedException( - "UsingExpressionNotSupported"), - usingExpressionAst); - - return AstVisitAction.SkipChildren; - } - - internal static void ThrowError(ImplicitRemotingBatchingNotSupportedException ex, Ast ast) - { - InterpreterError.UpdateExceptionErrorRecordPosition(ex, ast.Extent); - throw ex; - } - } - - internal class ImplicitRemotingBatchingNotSupportedException : Exception - { - internal string ErrorId { get; } - - internal ImplicitRemotingBatchingNotSupportedException(string errorId) : base( - ParserStrings.ImplicitRemotingPipelineBatchingNotSupported) - { - ErrorId = errorId; - } } - - #endregion } namespace System.Management.Automation.Internal @@ -2056,6 +1574,9 @@ public static class InternalTestHooks internal static bool BypassAppLockerPolicyCaching; internal static bool BypassOnlineHelpRetrieval; internal static bool ForcePromptForChoiceDefaultOption; + internal static bool BypassOutputRedirectionCheck; + internal static bool NoPromptForPassword; + internal static bool ForceFormatListFixedLabelWidth; // Stop/Restart/Rename Computer tests internal static bool TestStopComputer; @@ -2083,6 +1604,14 @@ public static class InternalTestHooks internal static bool ThrowExdevErrorOnMoveDirectory; + // To emulate OneDrive behavior we use the hard-coded symlink. + // If OneDriveTestRecurseOn is false then the symlink works as regular symlink. + // If OneDriveTestRecurseOn is true then we recurse into the symlink as OneDrive should work. + // OneDriveTestSymlinkName defines the symlink name used in tests. + internal static bool OneDriveTestOn; + internal static bool OneDriveTestRecurseOn; + internal static string OneDriveTestSymlinkName = "link-Beta"; + /// This member is used for internal test purposes. public static void SetTestHook(string property, object value) { @@ -2093,19 +1622,6 @@ public static void SetTestHook(string property, object value) } } - /// - /// Test hook used to test implicit remoting batching. A local runspace must be provided that has imported a - /// remote session, i.e., has run the Import-PSSession cmdlet. This hook will return true if the provided commandPipeline - /// is successfully batched and run in the remote session, and false if it is rejected for batching. - /// - /// Command pipeline to test. - /// Runspace with imported remote session. - /// True if commandPipeline is batched successfully. - public static bool TestImplicitRemotingBatching(string commandPipeline, System.Management.Automation.Runspaces.Runspace runspace) - { - return Utils.TryRunAsImplicitBatch(commandPipeline, runspace); - } - /// /// Constructs a custom PSSenderInfo instance that can be assigned to $PSSenderInfo /// in order to simulate a remoting session with respect to the $PSSenderInfo.ConnectionString (connection URL) @@ -2234,7 +1750,7 @@ internal T Pop() /// internal sealed class ReadOnlyBag : IEnumerable { - private HashSet _hashset; + private readonly HashSet _hashset; /// /// Constructor for the readonly Hashset. @@ -2296,6 +1812,14 @@ internal static void NotNullOrEmpty(string value, string paramName) } } + internal static void NotNullOrEmpty(ICollection value, string paramName) + { + if (value == null || value.Count == 0) + { + throw new ArgumentNullException(paramName); + } + } + internal static void Condition([DoesNotReturnIf(false)] bool precondition, string paramName) { if (!precondition) diff --git a/src/System.Management.Automation/engine/VariableAttributeCollection.cs b/src/System.Management.Automation/engine/VariableAttributeCollection.cs index f41bb3380ba..a1a81dbb01f 100644 --- a/src/System.Management.Automation/engine/VariableAttributeCollection.cs +++ b/src/System.Management.Automation/engine/VariableAttributeCollection.cs @@ -154,8 +154,7 @@ private object VerifyNewAttribute(Attribute item) /// The variable whose value needs to be verified anytime /// the attributes change. /// - private PSVariable _variable; + private readonly PSVariable _variable; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/VariableInterfaces.cs b/src/System.Management.Automation/engine/VariableInterfaces.cs index 90411860b6d..4ced936df57 100644 --- a/src/System.Management.Automation/engine/VariableInterfaces.cs +++ b/src/System.Management.Automation/engine/VariableInterfaces.cs @@ -441,9 +441,8 @@ internal void RemoveAtScope(PSVariable variable, string scope) #region private data - private SessionStateInternal _sessionState; + private readonly SessionStateInternal _sessionState; #endregion private data } } - diff --git a/src/System.Management.Automation/engine/VariablePath.cs b/src/System.Management.Automation/engine/VariablePath.cs index 0e33ae620c5..12bfc2d03a0 100644 --- a/src/System.Management.Automation/engine/VariablePath.cs +++ b/src/System.Management.Automation/engine/VariablePath.cs @@ -222,48 +222,48 @@ internal VariablePath CloneAndSetLocal() /// /// Returns true if the path explicitly specifies 'global:'. /// - public bool IsGlobal { get { return 0 != (_flags & VariablePathFlags.Global); } } + public bool IsGlobal { get { return (_flags & VariablePathFlags.Global) != 0; } } /// /// Returns true if the path explicitly specifies 'local:'. /// - public bool IsLocal { get { return 0 != (_flags & VariablePathFlags.Local); } } + public bool IsLocal { get { return (_flags & VariablePathFlags.Local) != 0; } } /// /// Returns true if the path explicitly specifies 'private:'. /// - public bool IsPrivate { get { return 0 != (_flags & VariablePathFlags.Private); } } + public bool IsPrivate { get { return (_flags & VariablePathFlags.Private) != 0; } } /// /// Returns true if the path explicitly specifies 'script:'. /// - public bool IsScript { get { return 0 != (_flags & VariablePathFlags.Script); } } + public bool IsScript { get { return (_flags & VariablePathFlags.Script) != 0; } } /// /// Returns true if the path specifies no drive or scope qualifiers. /// - public bool IsUnqualified { get { return 0 != (_flags & VariablePathFlags.Unqualified); } } + public bool IsUnqualified { get { return (_flags & VariablePathFlags.Unqualified) != 0; } } /// /// Returns true if the path specifies a variable path with no scope qualifiers. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unscoped")] - public bool IsUnscopedVariable { get { return (0 == (_flags & VariablePathFlags.UnscopedVariableMask)); } } + public bool IsUnscopedVariable { get { return ((_flags & VariablePathFlags.UnscopedVariableMask) == 0); } } /// /// Returns true if the path defines a variable. /// - public bool IsVariable { get { return 0 != (_flags & VariablePathFlags.Variable); } } + public bool IsVariable { get { return (_flags & VariablePathFlags.Variable) != 0; } } /// /// Returns true if the path defines a function. /// - internal bool IsFunction { get { return 0 != (_flags & VariablePathFlags.Function); } } + internal bool IsFunction { get { return (_flags & VariablePathFlags.Function) != 0; } } /// /// Returns true if the path specifies a drive other than the variable drive. /// - public bool IsDriveQualified { get { return 0 != (_flags & VariablePathFlags.DriveQualified); } } + public bool IsDriveQualified { get { return (_flags & VariablePathFlags.DriveQualified) != 0; } } /// /// The drive name, or null if the path is for a variable. diff --git a/src/System.Management.Automation/engine/WinRT/IInspectable.cs b/src/System.Management.Automation/engine/WinRT/IInspectable.cs index f6f4d9ee7d9..28544d42af4 100644 --- a/src/System.Management.Automation/engine/WinRT/IInspectable.cs +++ b/src/System.Management.Automation/engine/WinRT/IInspectable.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Runtime.InteropServices; +#nullable enable namespace System.Management.Automation { /// @@ -26,7 +27,7 @@ internal interface IInspectable { } /// /// Helper class for WinRT types. /// - internal class WinRTHelper + internal static class WinRTHelper { internal static bool IsWinRTType(Type type) { diff --git a/src/System.Management.Automation/engine/cmdlet.cs b/src/System.Management.Automation/engine/cmdlet.cs index b676337531e..ba7548f982d 100644 --- a/src/System.Management.Automation/engine/cmdlet.cs +++ b/src/System.Management.Automation/engine/cmdlet.cs @@ -46,7 +46,7 @@ public static HashSet CommonParameters } } - private static Lazy> s_commonParameters = new Lazy>( + private static readonly Lazy> s_commonParameters = new Lazy>( () => { return new HashSet(StringComparer.OrdinalIgnoreCase) { @@ -68,7 +68,7 @@ public static HashSet OptionalCommonParameters } } - private static Lazy> s_optionalCommonParameters = new Lazy>( + private static readonly Lazy> s_optionalCommonParameters = new Lazy>( () => { return new HashSet(StringComparer.OrdinalIgnoreCase) { @@ -1714,6 +1714,7 @@ public PSTransactionContext CurrentPSTransaction /// . /// etc. /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] public void ThrowTerminatingError(ErrorRecord errorRecord) { using (PSTransactionManager.GetEngineProtectionScope()) @@ -1831,4 +1832,3 @@ public enum ShouldProcessReason WhatIf = 0x1, } } - diff --git a/src/System.Management.Automation/engine/debugger/Breakpoint.cs b/src/System.Management.Automation/engine/debugger/Breakpoint.cs index b506ee8a246..5daf3bdc18b 100644 --- a/src/System.Management.Automation/engine/debugger/Breakpoint.cs +++ b/src/System.Management.Automation/engine/debugger/Breakpoint.cs @@ -434,10 +434,12 @@ public override string ToString() } internal int SequencePointIndex { get; set; } + internal IScriptExtent[] SequencePoints { get; set; } + internal BitArray BreakpointBitArray { get; set; } - private class CheckBreakpointInScript : AstVisitor + private sealed class CheckBreakpointInScript : AstVisitor { public static bool IsInNestedScriptBlock(Ast ast, LineBreakpoint breakpoint) { diff --git a/src/System.Management.Automation/engine/debugger/debugger.cs b/src/System.Management.Automation/engine/debugger/debugger.cs index 06e2ec78615..e8e8c849442 100644 --- a/src/System.Management.Automation/engine/debugger/debugger.cs +++ b/src/System.Management.Automation/engine/debugger/debugger.cs @@ -50,7 +50,7 @@ public enum DebuggerResumeAction /// Stop executing the script. /// Stop = 4, - }; + } /// /// Arguments for the DebuggerStop event. @@ -112,7 +112,7 @@ public DebuggerStopEventArgs( /// leave pending runspace debug sessions suspended until a debugger is attached. /// internal bool SuspendRemote { get; set; } - }; + } /// /// Kinds of breakpoint updates. @@ -135,7 +135,7 @@ public enum BreakpointUpdateType /// A breakpoint was disabled. /// Disabled = 3 - }; + } /// /// Arguments for the BreakpointUpdated event. @@ -166,7 +166,7 @@ internal BreakpointUpdatedEventArgs(Breakpoint breakpoint, BreakpointUpdateType /// Gets the current breakpoint count. /// public int BreakpointCount { get; } - }; + } #region PSJobStartEventArgs @@ -292,7 +292,7 @@ public enum DebugModes /// PowerShell remote script debugging. /// RemoteScript = 0x4 - }; + } /// /// Defines unhandled breakpoint processing behavior. @@ -1023,7 +1023,7 @@ public override bool InBreakpoint internal override bool IsPushed { - get { return (_activeDebuggers.Count > 0); } + get { return (!_activeDebuggers.IsEmpty); } } /// @@ -1447,7 +1447,7 @@ private List GetVariableBreakpointsToTrigger(string variable return null; var callStackInfo = _callStack.Last(); - var currentScriptFile = (callStackInfo != null) ? callStackInfo.File : null; + var currentScriptFile = callStackInfo?.File; return breakpoints.Values.Where(bp => bp.Trigger(currentScriptFile, read: read)).ToList(); } finally @@ -1575,11 +1575,14 @@ internal void OnSequencePointHit(FunctionContext functionContext) #region private members [DebuggerDisplay("{FunctionContext.CurrentPosition}")] - private class CallStackInfo + private sealed class CallStackInfo { internal InvocationInfo InvocationInfo { get; set; } + internal string File { get; set; } + internal bool DebuggerStepThrough { get; set; } + internal FunctionContext FunctionContext { get; set; } /// @@ -1589,7 +1592,7 @@ private class CallStackInfo internal bool IsFrameHidden { get; set; } internal bool TopFrameAtBreakpoint { get; set; } - }; + } private struct CallStackList { @@ -1633,7 +1636,7 @@ internal CallStackInfo Last() internal FunctionContext LastFunctionContext() { var last = Last(); - return last != null ? last.FunctionContext : null; + return last?.FunctionContext; } internal bool Any() @@ -1690,20 +1693,20 @@ internal void Clear() // Job debugger integration. private bool _nestedDebuggerStop; - private Dictionary _runningJobs; - private ConcurrentStack _activeDebuggers; - private ConcurrentStack _debuggerStopEventArgs; + private readonly Dictionary _runningJobs; + private readonly ConcurrentStack _activeDebuggers; + private readonly ConcurrentStack _debuggerStopEventArgs; private DebuggerResumeAction _lastActiveDebuggerAction; private DebuggerResumeAction _currentDebuggerAction; private DebuggerResumeAction _previousDebuggerAction; private CallStackInfo _nestedRunningFrame; - private object _syncObject; - private object _syncActiveDebuggerStopObject; + private readonly object _syncObject; + private readonly object _syncActiveDebuggerStopObject; private int _processingOutputCount; private ManualResetEventSlim _processingOutputCompleteEvent = new ManualResetEventSlim(true); // Runspace debugger integration. - private Dictionary _runningRunspaces; + private readonly Dictionary _runningRunspaces; private const int _jobCallStackOffset = 2; private const int _runspaceCallStackOffset = 1; @@ -1712,7 +1715,7 @@ internal void Clear() private ManualResetEventSlim _preserveDebugStopEvent; // Process runspace debugger - private Lazy> _runspaceDebugQueue = new Lazy>(); + private readonly Lazy> _runspaceDebugQueue = new Lazy>(); private volatile int _processingRunspaceDebugQueue; private ManualResetEventSlim _runspaceDebugCompleteEvent; @@ -1804,7 +1807,8 @@ private void OnDebuggerStop(InvocationInfo invocationInfo, List brea { // Fix up prompt. ++index; - string debugPrompt = "\"[DBG]: " + originalPromptString.Substring(index, originalPromptString.Length - index); + string debugPrompt = string.Concat("\"[DBG]: ", originalPromptString.AsSpan(index, originalPromptString.Length - index)); + defaultPromptInfo.Update( ScriptBlock.Create(debugPrompt), true, ScopedItemOptions.Unspecified); } @@ -2000,7 +2004,7 @@ private void UnbindBoundBreakpoints(List boundBreakpoints) private void SetPendingBreakpoints(FunctionContext functionContext) { - if (_pendingBreakpoints.Count == 0) + if (_pendingBreakpoints.IsEmpty) return; var newPendingBreakpoints = new Dictionary(); @@ -2133,7 +2137,7 @@ private bool CanDisableDebugger { // The debugger can be disbled if there are no breakpoints // left and if we are not currently stepping in the debugger. - return _idToBreakpoint.Count == 0 && + return _idToBreakpoint.IsEmpty && _currentDebuggerAction != DebuggerResumeAction.StepInto && _currentDebuggerAction != DebuggerResumeAction.StepOver && _currentDebuggerAction != DebuggerResumeAction.StepOut; @@ -2244,7 +2248,7 @@ private void DisableDebuggerStepping() private void RestoreInternalDebugMode() { - InternalDebugMode restoreMode = ((DebugMode != DebugModes.None) && (_idToBreakpoint.Count > 0)) ? InternalDebugMode.Enabled : InternalDebugMode.Disabled; + InternalDebugMode restoreMode = ((DebugMode != DebugModes.None) && (!_idToBreakpoint.IsEmpty)) ? InternalDebugMode.Enabled : InternalDebugMode.Disabled; SetInternalDebugMode(restoreMode); } @@ -2319,8 +2323,7 @@ public override DebuggerCommandResults ProcessCommand(PSCommand command, PSDataC // // Otherwise let root script debugger handle it. // - LocalRunspace localRunspace = _context.CurrentRunspace as LocalRunspace; - if (localRunspace == null) + if (!(_context.CurrentRunspace is LocalRunspace localRunspace)) { throw new PSInvalidOperationException( DebuggerStrings.CannotProcessDebuggerCommandNotStopped, @@ -2421,7 +2424,7 @@ public override void SetDebugMode(DebugModes mode) { SetInternalDebugMode(InternalDebugMode.Disabled); } - else if ((_idToBreakpoint.Count > 0) && (_context._debuggingMode == 0)) + else if ((!_idToBreakpoint.IsEmpty) && (_context._debuggingMode == 0)) { // Set internal debugger to active. SetInternalDebugMode(InternalDebugMode.Enabled); @@ -2866,7 +2869,7 @@ public override Breakpoint DisableBreakpoint(Breakpoint breakpoint, int? runspac return null; } - private Debugger GetRunspaceDebugger(int runspaceId) + private static Debugger GetRunspaceDebugger(int runspaceId) { if (!Runspace.RunspaceDictionary.TryGetValue(runspaceId, out WeakReference wr)) { @@ -3678,7 +3681,7 @@ private void RemoveFromRunningRunspaceList(Runspace runspace) } // Clean up nested debugger. - NestedRunspaceDebugger nestedDebugger = (runspaceInfo != null) ? runspaceInfo.NestedDebugger : null; + NestedRunspaceDebugger nestedDebugger = runspaceInfo?.NestedDebugger; if (nestedDebugger != null) { nestedDebugger.DebuggerStop -= HandleMonitorRunningRSDebuggerStop; @@ -3765,8 +3768,7 @@ private void HandleMonitorRunningRSDebuggerStop(object sender, DebuggerStopEvent } // Get nested debugger runspace info. - NestedRunspaceDebugger nestedDebugger = senderDebugger as NestedRunspaceDebugger; - if (nestedDebugger == null) { return; } + if (!(senderDebugger is NestedRunspaceDebugger nestedDebugger)) { return; } PSMonitorRunspaceType runspaceType = nestedDebugger.RunspaceType; @@ -3920,7 +3922,7 @@ private void DebuggerQueueThreadProc() Interlocked.CompareExchange(ref _processingRunspaceDebugQueue, 0, 1); - if (_runspaceDebugQueue.Value.Count > 0) + if (!_runspaceDebugQueue.Value.IsEmpty) { StartRunspaceForDebugQueueProcessing(); } @@ -4140,7 +4142,7 @@ internal void TraceVariableSet(string varName, object value) // because 'ToStringParser' would iterate through the enumerator to get the individual elements, which will // make irreversible changes to the enumerator. bool isValueAnIEnumerator = PSObject.Base(value) is IEnumerator; - string valAsString = isValueAnIEnumerator ? typeof(IEnumerator).Name : PSObject.ToStringParser(_context, value); + string valAsString = isValueAnIEnumerator ? nameof(IEnumerator) : PSObject.ToStringParser(_context, value); int msgLength = 60 - varName.Length; if (valAsString.Length > msgLength) @@ -4197,7 +4199,7 @@ public Guid ParentDebuggerId /// Runspace. /// Runspace type. /// Debugger Id of parent. - public NestedRunspaceDebugger( + protected NestedRunspaceDebugger( Runspace runspace, PSMonitorRunspaceType runspaceType, Guid parentDebuggerId) @@ -4449,14 +4451,14 @@ protected virtual DebuggerCommandResults HandlePromptCommand(PSDataCollection]: [RunspaceName]: PS C:\> - string computerName = (_runspace.ConnectionInfo != null) ? _runspace.ConnectionInfo.ComputerName : null; - string processPartPattern = "{0}[{1}:{2}]:{3}"; + string computerName = _runspace.ConnectionInfo?.ComputerName; + const string processPartPattern = "{0}[{1}:{2}]:{3}"; string processPart = StringUtil.Format(processPartPattern, @"""", DebuggerStrings.NestedRunspaceDebuggerPromptProcessName, @"$($PID)", @""""); - string locationPart = @"""PS $($executionContext.SessionState.Path.CurrentLocation)> """; + const string locationPart = @"""PS $($executionContext.SessionState.Path.CurrentLocation)> """; string promptScript = "'[DBG]: '" + " + " + processPart + " + " + "' [" + CodeGeneration.EscapeSingleQuotedStringContent(_runspace.Name) + "]: '" + " + " + locationPart; // Get the command prompt from the wrapped debugger. @@ -4626,8 +4628,7 @@ protected override void HandleDebuggerStop(object sender, DebuggerStopEventArgs private object DrainAndBlockRemoteOutput() { // We do this only for remote runspaces. - RemoteRunspace remoteRunspace = _runspace as RemoteRunspace; - if (remoteRunspace == null) { return null; } + if (!(_runspace is RemoteRunspace remoteRunspace)) { return null; } var runningPowerShell = remoteRunspace.GetCurrentBasePowerShell(); if (runningPowerShell != null) @@ -4650,7 +4651,7 @@ private object DrainAndBlockRemoteOutput() return null; } - private void RestoreRemoteOutput(object runningCmd) + private static void RestoreRemoteOutput(object runningCmd) { if (runningCmd == null) { return; } @@ -4864,19 +4865,18 @@ private InvocationInfo CreateInvocationInfoFromParent( StatementAst debugStatement = null; StatementAst callingStatement = _parentScriptBlockAst.Find( - ast => - { return ((ast is StatementAst) && (ast.Extent.StartLineNumber == callingLineNumber)); } - - , true) as StatementAst; + ast => ast is StatementAst && (ast.Extent.StartLineNumber == callingLineNumber), true) as StatementAst; if (callingStatement != null) { // Find first statement in calling statement. - StatementAst firstStatement = callingStatement.Find(ast => { return ((ast is StatementAst) && ast.Extent.StartLineNumber > callingLineNumber); }, true) as StatementAst; + StatementAst firstStatement = callingStatement.Find( + ast => ast is StatementAst && ast.Extent.StartLineNumber > callingLineNumber, true) as StatementAst; if (firstStatement != null) { int adjustedLineNumber = firstStatement.Extent.StartLineNumber + debugLineNumber - 1; - debugStatement = callingStatement.Find(ast => { return ((ast is StatementAst) && ast.Extent.StartLineNumber == adjustedLineNumber); }, true) as StatementAst; + debugStatement = callingStatement.Find( + ast => ast is StatementAst && ast.Extent.StartLineNumber == adjustedLineNumber, true) as StatementAst; } } @@ -4909,7 +4909,7 @@ private InvocationInfo CreateInvocationInfoFromParent( return null; } - private string FixUpStatementExtent(int startColNum, string stateExtentText) + private static string FixUpStatementExtent(int startColNum, string stateExtentText) { Text.StringBuilder sb = new Text.StringBuilder(); sb.Append(' ', startColNum); @@ -4948,7 +4948,7 @@ private object DrainAndBlockRemoteOutput() return null; } - private void RestoreRemoteOutput(object runningCmd) + private static void RestoreRemoteOutput(object runningCmd) { if (runningCmd == null) { return; } @@ -5052,13 +5052,13 @@ internal class DebuggerCommandProcessor private const int DefaultListLineCount = 16; // table of debugger commands - private Dictionary _commandTable; + private readonly Dictionary _commandTable; // the Help command - private DebuggerCommand _helpCommand; + private readonly DebuggerCommand _helpCommand; // the List command - private DebuggerCommand _listCommand; + private readonly DebuggerCommand _listCommand; // last command processed private DebuggerCommand _lastCommand; @@ -5208,7 +5208,7 @@ private DebuggerCommand DoProcessCommand(PSHost host, string command, Invocation /// /// Displays the help text for the debugger commands. /// - private void DisplayHelp(PSHost host, IList output) + private static void DisplayHelp(PSHost host, IList output) { WriteLine(string.Empty, host, output); WriteLine(StringUtil.Format(DebuggerStrings.StepHelp, StepShortcut, StepCommand), host, output); @@ -5336,7 +5336,7 @@ private void DisplayScript(PSHost host, IList output, InvocationInfo i WriteCR(host, output); } - private void WriteLine(string line, PSHost host, IList output) + private static void WriteLine(string line, PSHost host, IList output) { if (host != null) { @@ -5349,7 +5349,7 @@ private void WriteLine(string line, PSHost host, IList output) } } - private void WriteCR(PSHost host, IList output) + private static void WriteCR(PSHost host, IList output) { if (host != null) { @@ -5362,7 +5362,7 @@ private void WriteCR(PSHost host, IList output) } } - private void WriteErrorLine(string error, PSHost host, IList output) + private static void WriteErrorLine(string error, PSHost host, IList output) { if (host != null) { @@ -5638,7 +5638,7 @@ namespace System.Management.Automation.Internal [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes", Justification = "Needed Internal use only")] public static class DebuggerUtils { - private static SortedSet s_noHistoryCommandNames = new SortedSet(StringComparer.OrdinalIgnoreCase) + private static readonly SortedSet s_noHistoryCommandNames = new SortedSet(StringComparer.OrdinalIgnoreCase) { "prompt", "Set-PSDebuggerAction", diff --git a/src/System.Management.Automation/engine/hostifaces/AsyncResult.cs b/src/System.Management.Automation/engine/hostifaces/AsyncResult.cs index 8a0101ae802..f1e57e6fe39 100644 --- a/src/System.Management.Automation/engine/hostifaces/AsyncResult.cs +++ b/src/System.Management.Automation/engine/hostifaces/AsyncResult.cs @@ -42,7 +42,7 @@ internal class AsyncResult : IAsyncResult /// internal AsyncResult(Guid ownerId, AsyncCallback callback, object state) { - Dbg.Assert(Guid.Empty != ownerId, "ownerId cannot be empty"); + Dbg.Assert(ownerId != Guid.Empty, "ownerId cannot be empty"); OwnerId = ownerId; Callback = callback; AsyncState = state; @@ -152,10 +152,7 @@ internal void SetAsCompleted(Exception exception) } // call the user supplied callback - if (Callback != null) - { - Callback(this); - } + Callback?.Invoke(this); } /// diff --git a/src/System.Management.Automation/engine/hostifaces/ChoiceDescription.cs b/src/System.Management.Automation/engine/hostifaces/ChoiceDescription.cs index 94c47816c0d..1b55485afdc 100644 --- a/src/System.Management.Automation/engine/hostifaces/ChoiceDescription.cs +++ b/src/System.Management.Automation/engine/hostifaces/ChoiceDescription.cs @@ -134,4 +134,3 @@ class ChoiceDescription } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/Command.cs b/src/System.Management.Automation/engine/hostifaces/Command.cs index b98e447563b..6d8cd526486 100644 --- a/src/System.Management.Automation/engine/hostifaces/Command.cs +++ b/src/System.Management.Automation/engine/hostifaces/Command.cs @@ -422,7 +422,7 @@ public void MergeMyResults(PipelineResultTypes myResult, PipelineResultTypes toR } } - private Pipe GetRedirectionPipe( + private static Pipe GetRedirectionPipe( PipelineResultTypes toType, MshCommandRuntime mcr) { @@ -568,7 +568,7 @@ CommandOrigin origin /// property is bool, not bool? (from V1), so it should probably /// be deprecated, at least for internal use. /// - private bool? _useLocalScope; + private readonly bool? _useLocalScope; #endregion Private fields @@ -900,4 +900,3 @@ internal string GetCommandStringForHistory() } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/Connection.cs b/src/System.Management.Automation/engine/hostifaces/Connection.cs index acc54605b1a..5af011adb82 100644 --- a/src/System.Management.Automation/engine/hostifaces/Connection.cs +++ b/src/System.Management.Automation/engine/hostifaces/Connection.cs @@ -226,7 +226,7 @@ public enum PSThreadOptions /// This option is not valid for asynchronous calls /// UseCurrentThread = 3 - }; + } /// /// Defines type which has information about RunspaceState and @@ -450,9 +450,9 @@ public abstract class Runspace : IDisposable #region Private Data private static int s_globalId; - private Stack _runningPowerShells; + private readonly Stack _runningPowerShells; private PowerShell _baseRunningPowerShell; - private object _syncObject; + private readonly object _syncObject; #endregion @@ -574,7 +574,7 @@ public static bool CanUseDefaultRunspace { return (localPipeline.NestedPipelineExecutionThread.ManagedThreadId - == Threading.Thread.CurrentThread.ManagedThreadId); + == Environment.CurrentManagedThreadId); } } @@ -650,7 +650,7 @@ public bool RunspaceIsRemote { get { - return !(this is LocalRunspace || ConnectionInfo == null); + return this is not LocalRunspace && ConnectionInfo != null; } } @@ -801,8 +801,8 @@ internal static ReadOnlyDictionary> RunspaceDiction } } - private static SortedDictionary> s_runspaceDictionary; - private static object s_syncObject; + private static readonly SortedDictionary> s_runspaceDictionary; + private static readonly object s_syncObject; /// /// Returns a read only list of runspaces. @@ -943,7 +943,8 @@ internal void UpdateRunspaceAvailability(PipelineState pipelineState, bool raise case PipelineState.Completed: case PipelineState.Stopped: case PipelineState.Failed: - if (this.InNestedPrompt || !(this is RemoteRunspace) && this.Debugger.InBreakpoint) + if (this.InNestedPrompt + || (this is not RemoteRunspace && this.Debugger.InBreakpoint)) { this.RunspaceAvailability = RunspaceAvailability.AvailableForNestedCommand; } @@ -951,7 +952,7 @@ internal void UpdateRunspaceAvailability(PipelineState pipelineState, bool raise { RemoteRunspace remoteRunspace = this as RemoteRunspace; RemoteDebugger remoteDebugger = (remoteRunspace != null) ? remoteRunspace.Debugger as RemoteDebugger : null; - Internal.ConnectCommandInfo remoteCommand = (remoteRunspace != null) ? remoteRunspace.RemoteCommand : null; + Internal.ConnectCommandInfo remoteCommand = remoteRunspace?.RemoteCommand; if (((pipelineState == PipelineState.Completed) || (pipelineState == PipelineState.Failed) || ((pipelineState == PipelineState.Stopped) && (this.RunspaceStateInfo.State == RunspaceState.Opened))) && (remoteCommand != null) && (cmdInstanceId != null) && (remoteCommand.CommandId == cmdInstanceId)) @@ -1589,7 +1590,7 @@ public virtual Debugger Debugger get { var context = GetExecutionContext; - return (context != null) ? context.Debugger : null; + return context?.Debugger; } } @@ -1650,6 +1651,7 @@ public virtual void ResetRunspaceState() // Used for pipeline id generation. private long _pipelineIdSeed; + // Generate pipeline id unique to this runspace internal long GeneratePipelineId() { @@ -1667,7 +1669,7 @@ internal SessionStateProxy() { } - private RunspaceBase _runspace; + private readonly RunspaceBase _runspace; internal SessionStateProxy(RunspaceBase runspace) { diff --git a/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs b/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs index 4b933b590b9..b6b571e90e7 100644 --- a/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs +++ b/src/System.Management.Automation/engine/hostifaces/ConnectionBase.cs @@ -670,7 +670,7 @@ protected RunspaceState RunspaceState /// private Queue _runspaceEventQueue = new Queue(); - private class RunspaceEventQueueItem + private sealed class RunspaceEventQueueItem { public RunspaceEventQueueItem(RunspaceStateInfo runspaceStateInfo, RunspaceAvailability currentAvailability, RunspaceAvailability newAvailability) { @@ -829,7 +829,7 @@ internal void AddToRunningPipelineList(PipelineBase pipeline) lock (_pipelineListLock) { - if (ByPassRunspaceStateCheck == false && RunspaceState != RunspaceState.Opened) + if (!ByPassRunspaceStateCheck && RunspaceState != RunspaceState.Opened) { InvalidRunspaceStateException e = new InvalidRunspaceStateException @@ -924,12 +924,13 @@ internal bool WaitForFinishofPipelines() Tuple stateInfo = new Tuple(waitHandles, waitAllIsDone); ThreadPool.QueueUserWorkItem(new WaitCallback( - delegate (object state) - { - var tuple = (Tuple)state; - WaitHandle.WaitAll(tuple.Item1); - tuple.Item2.Set(); - }), stateInfo); + (object state) => + { + var tuple = (Tuple)state; + WaitHandle.WaitAll(tuple.Item1); + tuple.Item2.Set(); + }), + stateInfo); return waitAllIsDone.WaitOne(); } } @@ -1002,7 +1003,7 @@ internal void StopNestedPipelines(Pipeline pipeline) // first check if this pipeline is in the list of running // pipelines. It is possible that pipeline has already // completed. - if (RunningPipelines.Contains(pipeline) == false) + if (!RunningPipelines.Contains(pipeline)) { return; } @@ -1573,7 +1574,7 @@ internal ProviderIntrinsics InvokeProvider /// internal override SessionStateProxy GetSessionStateProxy() { - return _sessionStateProxy ?? (_sessionStateProxy = new SessionStateProxy(this)); + return _sessionStateProxy ??= new SessionStateProxy(this); } #endregion session state proxy diff --git a/src/System.Management.Automation/engine/hostifaces/DefaultHost.cs b/src/System.Management.Automation/engine/hostifaces/DefaultHost.cs index e49bafd28da..56d4225be56 100644 --- a/src/System.Management.Automation/engine/hostifaces/DefaultHost.cs +++ b/src/System.Management.Automation/engine/hostifaces/DefaultHost.cs @@ -133,4 +133,3 @@ public override #endregion private fields } } - diff --git a/src/System.Management.Automation/engine/hostifaces/FieldDescription.cs b/src/System.Management.Automation/engine/hostifaces/FieldDescription.cs index 0af791ed829..75987cc463a 100644 --- a/src/System.Management.Automation/engine/hostifaces/FieldDescription.cs +++ b/src/System.Management.Automation/engine/hostifaces/FieldDescription.cs @@ -291,7 +291,7 @@ public string Name Collection Attributes { - get { return metadata ?? (metadata = new Collection()); } + get { return metadata ??= new Collection(); } } /// @@ -414,4 +414,3 @@ internal bool IsFromRemoteHost #endregion } } - diff --git a/src/System.Management.Automation/engine/hostifaces/History.cs b/src/System.Management.Automation/engine/hostifaces/History.cs index 26496f74ef7..dc74a46213f 100644 --- a/src/System.Management.Automation/engine/hostifaces/History.cs +++ b/src/System.Management.Automation/engine/hostifaces/History.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Management.Automation; using System.Management.Automation.Host; @@ -138,7 +139,7 @@ public override string ToString() /// /// Id of the pipeline corresponding to this history entry. /// - private long _pipelineId; + private readonly long _pipelineId; /// /// Returns a clone of this object. @@ -262,7 +263,7 @@ internal HistoryInfo GetEntry(long id) HistoryInfo entry = CoreGetEntry(id); if (entry != null) - if (entry.Cleared == false) + if (!entry.Cleared) return entry.Clone(); return null; @@ -416,7 +417,7 @@ internal HistoryInfo[] GetEntries(long id, long count, SwitchParameter newest) } else { - index = _countEntriesAdded;//SmallestIDinBuffer + index = _countEntriesAdded; //SmallestIDinBuffer for (long i = count - 1; i >= 0;) { @@ -496,7 +497,7 @@ internal HistoryInfo[] GetEntries(WildcardPattern wildcardpattern, long count, S for (long i = 0; i <= count - 1;) { if (id > _countEntriesAdded) break; - if (_buffer[GetIndexFromId(id)].Cleared == false && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim())) + if (!_buffer[GetIndexFromId(id)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim())) { cmdlist.Add(_buffer[GetIndexFromId(id)].Clone()); i++; } @@ -520,7 +521,7 @@ internal HistoryInfo[] GetEntries(WildcardPattern wildcardpattern, long count, S } if (id < 1) break; - if (_buffer[GetIndexFromId(id)].Cleared == false && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim())) + if (!_buffer[GetIndexFromId(id)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim())) { cmdlist.Add(_buffer[GetIndexFromId(id)].Clone()); i++; } @@ -533,7 +534,7 @@ internal HistoryInfo[] GetEntries(WildcardPattern wildcardpattern, long count, S { for (long i = 1; i <= _countEntriesAdded; i++) { - if (_buffer[GetIndexFromId(i)].Cleared == false && wildcardpattern.IsMatch(_buffer[GetIndexFromId(i)].CommandLine.Trim())) + if (!_buffer[GetIndexFromId(i)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(i)].CommandLine.Trim())) { cmdlist.Add(_buffer[GetIndexFromId(i)].Clone()); } @@ -660,7 +661,7 @@ private long SmallestIDinBuffer() for (int i = 0; i < _buffer.Length; i++) { // assign the first entry in the buffer as min. - if (_buffer[i] != null && _buffer[i].Cleared == false) + if (_buffer[i] != null && !_buffer[i].Cleared) { minID = _buffer[i].Id; break; @@ -669,7 +670,7 @@ private long SmallestIDinBuffer() // check for the minimum id that is not cleared for (int i = 0; i < _buffer.Length; i++) { - if (_buffer[i] != null && _buffer[i].Cleared == false) + if (_buffer[i] != null && !_buffer[i].Cleared) if (minID > _buffer[i].Id) minID = _buffer[i].Id; } @@ -755,11 +756,11 @@ private void IncrementCountOfEntriesInBuffer() /// Get the current history size. /// /// - private int GetHistorySize() + private static int GetHistorySize() { int historySize = 0; var executionContext = LocalPipeline.GetExecutionContextFromTLS(); - object obj = (executionContext != null) ? executionContext.GetVariableValue(SpecialVariables.HistorySizeVarPath) : null; + object obj = executionContext?.GetVariableValue(SpecialVariables.HistorySizeVarPath); if (obj != null) { try @@ -803,7 +804,7 @@ private int GetHistorySize() /// /// Private object for synchronization. /// - private object _syncRoot = new object(); + private readonly object _syncRoot = new object(); #endregion private @@ -821,7 +822,7 @@ internal long GetNextHistoryId() /// This is a set of HistoryInfo ids which are currently being executed in the /// pipelines of the Runspace that is holding this 'History' instance. /// - private HashSet _invokeHistoryIds = new HashSet(); + private readonly HashSet _invokeHistoryIds = new HashSet(); internal bool PresentInInvokeHistoryEntrySet(HistoryInfo entry) { @@ -1098,12 +1099,12 @@ protected override void EndProcessing() { ps.AddScript(commandToInvoke); - EventHandler debugAdded = delegate (object sender, DataAddedEventArgs e) { DebugRecord record = (DebugRecord)((PSDataCollection)sender)[e.Index]; WriteDebug(record.Message); }; - EventHandler errorAdded = delegate (object sender, DataAddedEventArgs e) { ErrorRecord record = (ErrorRecord)((PSDataCollection)sender)[e.Index]; WriteError(record); }; - EventHandler informationAdded = delegate (object sender, DataAddedEventArgs e) { InformationRecord record = (InformationRecord)((PSDataCollection)sender)[e.Index]; WriteInformation(record); }; - EventHandler progressAdded = delegate (object sender, DataAddedEventArgs e) { ProgressRecord record = (ProgressRecord)((PSDataCollection)sender)[e.Index]; WriteProgress(record); }; - EventHandler verboseAdded = delegate (object sender, DataAddedEventArgs e) { VerboseRecord record = (VerboseRecord)((PSDataCollection)sender)[e.Index]; WriteVerbose(record.Message); }; - EventHandler warningAdded = delegate (object sender, DataAddedEventArgs e) { WarningRecord record = (WarningRecord)((PSDataCollection)sender)[e.Index]; WriteWarning(record.Message); }; + EventHandler debugAdded = (object sender, DataAddedEventArgs e) => { DebugRecord record = (DebugRecord)((PSDataCollection)sender)[e.Index]; WriteDebug(record.Message); }; + EventHandler errorAdded = (object sender, DataAddedEventArgs e) => { ErrorRecord record = (ErrorRecord)((PSDataCollection)sender)[e.Index]; WriteError(record); }; + EventHandler informationAdded = (object sender, DataAddedEventArgs e) => { InformationRecord record = (InformationRecord)((PSDataCollection)sender)[e.Index]; WriteInformation(record); }; + EventHandler progressAdded = (object sender, DataAddedEventArgs e) => { ProgressRecord record = (ProgressRecord)((PSDataCollection)sender)[e.Index]; WriteProgress(record); }; + EventHandler verboseAdded = (object sender, DataAddedEventArgs e) => { VerboseRecord record = (VerboseRecord)((PSDataCollection)sender)[e.Index]; WriteVerbose(record.Message); }; + EventHandler warningAdded = (object sender, DataAddedEventArgs e) => { WarningRecord record = (WarningRecord)((PSDataCollection)sender)[e.Index]; WriteWarning(record.Message); }; ps.Streams.Debug.DataAdded += debugAdded; ps.Streams.Error.DataAdded += errorAdded; @@ -1315,7 +1316,7 @@ private void PopulateIdAndCommandLine() /// in the pipeline. If there are more than one element in pipeline /// (ex A | Invoke-History 2 | B) then we cannot do this replacement. /// - private void ReplaceHistoryString(HistoryInfo entry, LocalRunspace localRunspace) + private static void ReplaceHistoryString(HistoryInfo entry, LocalRunspace localRunspace) { var pipeline = (LocalPipeline)localRunspace.GetCurrentlyRunningPipeline(); if (pipeline.AddToHistory) @@ -1338,7 +1339,7 @@ public class AddHistoryCommand : PSCmdlet /// This parameter specifies the current pipeline object. /// [Parameter(Position = 0, ValueFromPipeline = true)] - public PSObject[] InputObject { set; get; } + public PSObject[] InputObject { get; set; } private bool _passthru; /// @@ -1433,118 +1434,41 @@ void ProcessRecord() { break; } + // Read CommandLine property - string commandLine = GetPropertyValue(mshObject, "CommandLine") as string; - if (commandLine == null) + if (!(GetPropertyValue(mshObject, "CommandLine") is string commandLine)) { break; } // Read ExecutionStatus property object pipelineState = GetPropertyValue(mshObject, "ExecutionStatus"); - if (pipelineState == null) - { - break; - } - - PipelineState executionStatus; - if (pipelineState is PipelineState) - { - executionStatus = (PipelineState)pipelineState; - } - else if (pipelineState is PSObject) - { - PSObject serializedPipelineState = pipelineState as PSObject; - object baseObject = serializedPipelineState.BaseObject; - if (baseObject is not int) - { - break; - } - - executionStatus = (PipelineState)baseObject; - if (executionStatus < PipelineState.NotStarted || executionStatus > PipelineState.Failed) - { - break; - } - } - else if (pipelineState is string) - { - try - { - executionStatus = (PipelineState)Enum.Parse(typeof(PipelineState), (string)pipelineState); - } - catch (ArgumentException) - { - break; - } - } - else + if (pipelineState == null || !LanguagePrimitives.TryConvertTo(pipelineState, out PipelineState executionStatus)) { break; } // Read StartExecutionTime property - DateTime startExecutionTime; object temp = GetPropertyValue(mshObject, "StartExecutionTime"); - if (temp == null) - { - break; - } - else if (temp is DateTime) - { - startExecutionTime = (DateTime)temp; - } - else if (temp is string) - { - try - { - startExecutionTime = DateTime.Parse((string)temp, System.Globalization.CultureInfo.CurrentCulture); - } - catch (FormatException) - { - break; - } - } - else + if (temp == null || !LanguagePrimitives.TryConvertTo(temp, CultureInfo.CurrentCulture, out DateTime startExecutionTime)) { break; } // Read EndExecutionTime property - DateTime endExecutionTime; temp = GetPropertyValue(mshObject, "EndExecutionTime"); - if (temp == null) - { - break; - } - else if (temp is DateTime) - { - endExecutionTime = (DateTime)temp; - } - else if (temp is string) - { - try - { - endExecutionTime = DateTime.Parse((string)temp, System.Globalization.CultureInfo.CurrentCulture); - } - catch (FormatException) - { - break; - } - } - else + if (temp == null || !LanguagePrimitives.TryConvertTo(temp, CultureInfo.CurrentCulture, out DateTime endExecutionTime)) { break; } - return new HistoryInfo - ( - 0, - commandLine, - executionStatus, - startExecutionTime, - endExecutionTime - ); + return new HistoryInfo( + pipelineId: 0, + commandLine, + executionStatus, + startExecutionTime, + endExecutionTime + ); } while (false); // If we are here, an error has occured. @@ -1815,9 +1739,9 @@ private void ClearHistoryByID() else { // confirmation message if all the clearhistory cmdlet is used without any parameters - if (_countParameterSpecified == false) + if (!_countParameterSpecified) { - string message = StringUtil.Format(HistoryStrings.ClearHistoryWarning, "Warning");// "The command would clear all the entry(s) from the session history,Are you sure you want to continue ?"; + string message = StringUtil.Format(HistoryStrings.ClearHistoryWarning, "Warning"); // "The command would clear all the entry(s) from the session history,Are you sure you want to continue ?"; if (!ShouldProcess(message)) { return; @@ -1898,10 +1822,10 @@ private void ClearHistoryByCmdLine() /// /// Clears the session history based on the input parameter - /// Id of the entry to be cleared. - /// Count of entries to be cleared. - /// Cmdline string to be cleared. - /// Order of the entries. + /// Id of the entry to be cleared. + /// Count of entries to be cleared. + /// Cmdline string to be cleared. + /// Order of the entries. /// Nothing. /// private void ClearHistoryEntries(long id, int count, string cmdline, SwitchParameter newest) @@ -1956,7 +1880,7 @@ private void ClearHistoryEntries(long id, int count, string cmdline, SwitchParam // Clear the History value. foreach (HistoryInfo entry in _entries) { - if (entry != null && entry.Cleared == false) + if (entry != null && !entry.Cleared) _history.ClearEntry(entry.Id); } @@ -1976,4 +1900,3 @@ private void ClearHistoryEntries(long id, int count, string cmdline, SwitchParam #endregion Private } } - diff --git a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs index ecc4780c284..b3e29423a83 100644 --- a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs +++ b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs @@ -42,7 +42,7 @@ public static class HostUtilities { #region Internal Access - private static string s_checkForCommandInCurrentDirectoryScript = @" + private static readonly string s_checkForCommandInCurrentDirectoryScript = @" [System.Diagnostics.DebuggerHidden()] param() @@ -58,21 +58,21 @@ public static class HostUtilities $foundSuggestion "; - private static string s_createCommandExistsInCurrentDirectoryScript = @" + private static readonly string s_createCommandExistsInCurrentDirectoryScript = @" [System.Diagnostics.DebuggerHidden()] param([string] $formatString) $formatString -f $lastError.TargetObject,"".\$($lastError.TargetObject)"" "; - private static string s_getFuzzyMatchedCommands = @" + private static readonly string s_getFuzzyMatchedCommands = @" [System.Diagnostics.DebuggerHidden()] param([string] $formatString) $formatString -f [string]::Join(', ', (Get-Command $lastError.TargetObject -UseFuzzyMatch | Select-Object -First 10 -Unique -ExpandProperty Name)) "; - private static List s_suggestions = InitializeSuggestions(); + private static readonly List s_suggestions = InitializeSuggestions(); private static List InitializeSuggestions() { @@ -309,8 +309,7 @@ internal static string GetMaxLines(string source, int maxLines) internal static List GetSuggestion(Runspace runspace) { - LocalRunspace localRunspace = runspace as LocalRunspace; - if (localRunspace == null) { return new List(); } + if (!(runspace is LocalRunspace localRunspace)) { return new List(); } // Get the last value of $? bool questionMarkVariableValue = localRunspace.ExecutionContext.QuestionMarkVariableValue; diff --git a/src/System.Management.Automation/engine/hostifaces/InformationalRecord.cs b/src/System.Management.Automation/engine/hostifaces/InformationalRecord.cs index 9325f95ccad..3fdba5569c3 100644 --- a/src/System.Management.Automation/engine/hostifaces/InformationalRecord.cs +++ b/src/System.Management.Automation/engine/hostifaces/InformationalRecord.cs @@ -59,7 +59,10 @@ public string Message return _message; } - set { _message = value; } + set + { + _message = value; + } } /// @@ -217,7 +220,7 @@ public string FullyQualifiedWarningId } } - private string _fullyQualifiedWarningId; + private readonly string _fullyQualifiedWarningId; } /// diff --git a/src/System.Management.Automation/engine/hostifaces/InternalHost.cs b/src/System.Management.Automation/engine/hostifaces/InternalHost.cs index e170a3792e4..e9a4b0e86e3 100644 --- a/src/System.Management.Automation/engine/hostifaces/InternalHost.cs +++ b/src/System.Management.Automation/engine/hostifaces/InternalHost.cs @@ -39,7 +39,7 @@ internal class InternalHost : PSHost, IHostSupportsInteractiveSession internal InternalHost(PSHost externalHost, ExecutionContext executionContext) { Dbg.Assert(externalHost != null, "must supply an PSHost"); - Dbg.Assert(!(externalHost is InternalHost), "try to create an InternalHost from another InternalHost"); + Dbg.Assert(externalHost is not InternalHost, "try to create an InternalHost from another InternalHost"); Dbg.Assert(executionContext != null, "must supply an ExecutionContext"); @@ -448,8 +448,7 @@ public override void NotifyEndApplication() /// private IHostSupportsInteractiveSession GetIHostSupportsInteractiveSession() { - IHostSupportsInteractiveSession host = _externalHostRef.Value as IHostSupportsInteractiveSession; - if (host == null) + if (!(_externalHostRef.Value is IHostSupportsInteractiveSession host)) { throw new PSNotImplementedException(); } @@ -565,14 +564,14 @@ internal PSHost ExternalHost internal int NestedPromptCount { get; private set; } // Masked variables. - private ObjectRef _externalHostRef; - private ObjectRef _internalUIRef; + private readonly ObjectRef _externalHostRef; + private readonly ObjectRef _internalUIRef; // Private variables. private string _nameResult; private Version _versionResult; private Guid _idResult; - private Stack _contextStack = new Stack(); + private readonly Stack _contextStack = new Stack(); private readonly Guid _zeroGuid; } diff --git a/src/System.Management.Automation/engine/hostifaces/InternalHostRawUserInterface.cs b/src/System.Management.Automation/engine/hostifaces/InternalHostRawUserInterface.cs index 156d6d58dc8..69346ae303b 100644 --- a/src/System.Management.Automation/engine/hostifaces/InternalHostRawUserInterface.cs +++ b/src/System.Management.Automation/engine/hostifaces/InternalHostRawUserInterface.cs @@ -609,7 +609,7 @@ public override return _externalRawUI.LengthInBufferCells(character); } - private PSHostRawUserInterface _externalRawUI; - private InternalHost _parentHost; + private readonly PSHostRawUserInterface _externalRawUI; + private readonly InternalHost _parentHost; } } diff --git a/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs b/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs index 8aa5956e8a8..57f3f675ffc 100644 --- a/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs +++ b/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs @@ -49,8 +49,7 @@ class InternalHostUserInterface : PSHostUserInterface, IHostUISupportsMultipleCh _internalRawUI.ThrowNotInteractive(); } - private - void + private static void ThrowPromptNotInteractive(string promptMessage) { string message = StringUtil.Format(HostInterfaceExceptionsStrings.HostFunctionPromptNotImplemented, promptMessage); @@ -79,7 +78,7 @@ public override public override bool SupportsVirtualTerminal { - get { return (_externalUI != null) ? _externalUI.SupportsVirtualTerminal : false; } + get { return _externalUI != null && _externalUI.SupportsVirtualTerminal; } } /// @@ -517,7 +516,7 @@ internal PSInformationalBuffers GetInformationalMessageBuffers() endLoop = false; break; } - } while (endLoop != true); + } while (!endLoop); return shouldContinue; } @@ -680,12 +679,12 @@ internal static Type GetFieldType(FieldDescription field) internal static bool IsSecuritySensitiveType(string typeName) { - if (typeName.Equals(typeof(PSCredential).Name, StringComparison.OrdinalIgnoreCase)) + if (typeName.Equals(nameof(PSCredential), StringComparison.OrdinalIgnoreCase)) { return true; } - if (typeName.Equals(typeof(SecureString).Name, StringComparison.OrdinalIgnoreCase)) + if (typeName.Equals(nameof(SecureString), StringComparison.OrdinalIgnoreCase)) { return true; } @@ -912,7 +911,7 @@ private Collection EmulatePromptForMultipleChoice(string caption, // Construct the caption + message + list of choices + default choices Text.StringBuilder choicesMessage = new Text.StringBuilder(); - char newLine = '\n'; + const char newLine = '\n'; if (!string.IsNullOrEmpty(caption)) { choicesMessage.Append(caption); @@ -928,7 +927,7 @@ private Collection EmulatePromptForMultipleChoice(string caption, string[,] hotkeysAndPlainLabels = null; HostUIHelperMethods.BuildHotkeysAndPlainLabels(choices, out hotkeysAndPlainLabels); - string choiceTemplate = "[{0}] {1} "; + const string choiceTemplate = "[{0}] {1} "; for (int i = 0; i < hotkeysAndPlainLabels.GetLength(1); ++i) { string choice = @@ -994,7 +993,7 @@ private Collection EmulatePromptForMultipleChoice(string caption, // choices to be picked. // user did not pick up any choices..choose the default - if ((result.Count == 0) && (defaultChoiceKeys.Keys.Count >= 0)) + if (result.Count == 0) { // if there's a default, pick that one. foreach (int defaultChoice in defaultChoiceKeys.Keys) @@ -1020,10 +1019,9 @@ private Collection EmulatePromptForMultipleChoice(string caption, return result; } - private PSHostUserInterface _externalUI = null; - private InternalHostRawUserInterface _internalRawUI = null; - private InternalHost _parent = null; + private readonly PSHostUserInterface _externalUI = null; + private readonly InternalHostRawUserInterface _internalRawUI = null; + private readonly InternalHost _parent = null; private PSInformationalBuffers _informationalBuffers = null; } } - diff --git a/src/System.Management.Automation/engine/hostifaces/ListModifier.cs b/src/System.Management.Automation/engine/hostifaces/ListModifier.cs index 191a5309cc7..4723db9a1d7 100644 --- a/src/System.Management.Automation/engine/hostifaces/ListModifier.cs +++ b/src/System.Management.Automation/engine/hostifaces/ListModifier.cs @@ -151,7 +151,7 @@ public Collection Add get { return _itemsToAdd; } } - private Collection _itemsToAdd; + private readonly Collection _itemsToAdd; /// /// The list of items to remove when AppyTo is called. @@ -161,7 +161,7 @@ public Collection Remove get { return _itemsToRemove; } } - private Collection _itemsToRemove; + private readonly Collection _itemsToRemove; /// /// The list of items to replace an existing list with. @@ -171,7 +171,7 @@ public Collection Replace get { return _replacementItems; } } - private Collection _replacementItems; + private readonly Collection _replacementItems; /// /// Update the given collection with the items in Add and Remove. @@ -219,8 +219,7 @@ public void ApplyTo(object collectionToUpdate) collectionToUpdate = PSObject.Base(collectionToUpdate); - IList list = collectionToUpdate as IList; - if (list == null) + if (!(collectionToUpdate is IList list)) { throw PSTraceSource.NewInvalidOperationException(PSListModifierStrings.UpdateFailed); } diff --git a/src/System.Management.Automation/engine/hostifaces/LocalConnection.cs b/src/System.Management.Automation/engine/hostifaces/LocalConnection.cs index 92740acf8dd..7f10b75525c 100644 --- a/src/System.Management.Automation/engine/hostifaces/LocalConnection.cs +++ b/src/System.Management.Automation/engine/hostifaces/LocalConnection.cs @@ -363,8 +363,8 @@ public override Debugger Debugger } } - private static string s_debugPreferenceCachePath = Path.Combine(Path.Combine(Platform.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsPowerShell"), "DebugPreference.clixml"); - private static object s_debugPreferenceLockObject = new object(); + private static readonly string s_debugPreferenceCachePath = Path.Combine(Path.Combine(Platform.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsPowerShell"), "DebugPreference.clixml"); + private static readonly object s_debugPreferenceLockObject = new object(); /// /// DebugPreference serves as a property bag to keep @@ -851,7 +851,7 @@ private void DoCloseHelper() // Generate the shutdown event if (Events != null) - Events.GenerateEvent(PSEngineEvent.Exiting, null, new object[] { }, null, true, false); + Events.GenerateEvent(PSEngineEvent.Exiting, null, Array.Empty(), null, true, false); // Stop all running pipelines // Note:Do not perform the Cancel in lock. Reason is @@ -941,7 +941,7 @@ private void DoCloseHelper() /// function. If a remote runspace supports disconnect then it will be disconnected /// rather than closed. /// - private void CloseOrDisconnectAllRemoteRunspaces(Func> getRunspaces) + private static void CloseOrDisconnectAllRemoteRunspaces(Func> getRunspaces) { List runspaces = getRunspaces(); if (runspaces.Count == 0) { return; } @@ -950,10 +950,7 @@ private void CloseOrDisconnectAllRemoteRunspaces(Func> getR using (ManualResetEvent remoteRunspaceCloseCompleted = new ManualResetEvent(false)) { ThrottleManager throttleManager = new ThrottleManager(); - throttleManager.ThrottleComplete += delegate (object sender, EventArgs e) - { - remoteRunspaceCloseCompleted.Set(); - }; + throttleManager.ThrottleComplete += (object sender, EventArgs e) => remoteRunspaceCloseCompleted.Set(); foreach (RemoteRunspace remoteRunspace in runspaces) { @@ -979,15 +976,12 @@ private void StopOrDisconnectAllJobs() using (ManualResetEvent jobsStopCompleted = new ManualResetEvent(false)) { ThrottleManager throttleManager = new ThrottleManager(); - throttleManager.ThrottleComplete += delegate (object sender, EventArgs e) - { - jobsStopCompleted.Set(); - }; + throttleManager.ThrottleComplete += (object sender, EventArgs e) => jobsStopCompleted.Set(); foreach (Job job in this.JobRepository.Jobs) { // Only stop or disconnect PowerShell jobs. - if (job is PSRemotingJob == false) + if (job is not PSRemotingJob) { continue; } @@ -1016,10 +1010,7 @@ private void StopOrDisconnectAllJobs() } // Disconnect all disconnectable job runspaces found. - CloseOrDisconnectAllRemoteRunspaces(() => - { - return disconnectRunspaces; - }); + CloseOrDisconnectAllRemoteRunspaces(() => disconnectRunspaces); } internal void ReleaseDebugger() @@ -1312,14 +1303,13 @@ internal AutomationEngine Engine private History _history; [TraceSource("RunspaceInit", "Initialization code for Runspace")] - private static - PSTraceSource s_runspaceInitTracer = + private static readonly PSTraceSource s_runspaceInitTracer = PSTraceSource.GetTracer("RunspaceInit", "Initialization code for Runspace", false); /// /// This ensures all processes have a server/listener. /// - private static RemoteSessionNamedPipeServer s_IPCNamedPipeServer = RemoteSessionNamedPipeServer.IPCNamedPipeServer; + private static readonly RemoteSessionNamedPipeServer s_IPCNamedPipeServer = RemoteSessionNamedPipeServer.IPCNamedPipeServer; #endregion private fields } @@ -1331,7 +1321,7 @@ private static /// internal sealed class StopJobOperationHelper : IThrottleOperation { - private Job _job; + private readonly Job _job; /// /// Internal constructor. @@ -1408,7 +1398,7 @@ private void RaiseOperationCompleteEvent() /// internal sealed class CloseOrDisconnectRunspaceOperationHelper : IThrottleOperation { - private RemoteRunspace _remoteRunspace; + private readonly RemoteRunspace _remoteRunspace; /// /// Internal constructor. @@ -1569,7 +1559,7 @@ public PSDataCollection ErrorRecords get { return _errors; } } - private PSDataCollection _errors; + private readonly PSDataCollection _errors; #region Serialization /// @@ -1603,4 +1593,3 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont #endregion Helper Class } - diff --git a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs index fd34123937a..5392c1781e1 100644 --- a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs +++ b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs @@ -12,9 +12,6 @@ #endif using System.Threading; using Microsoft.PowerShell.Commands; -using Microsoft.Win32; - -using Dbg = System.Management.Automation.Diagnostics; namespace System.Management.Automation.Runspaces { @@ -192,7 +189,7 @@ protected override void StartPipelineExecution() } #if !UNIX - if (apartmentState != ApartmentState.Unknown && !Platform.IsNanoServer && !Platform.IsIoT) + if (apartmentState != ApartmentState.Unknown && Platform.IsStaSupported) { invokeThread.SetApartmentState(apartmentState); } @@ -249,7 +246,7 @@ protected override void StartPipelineExecution() } default: - Debug.Fail(""); + Debug.Fail(string.Empty); break; } } @@ -279,54 +276,53 @@ private void SetupInvokeThread(Thread invokeThread, bool changeName) private FlowControlException InvokeHelper() { FlowControlException flowControlException = null; - PipelineProcessor pipelineProcessor = null; + try { -#if TRANSACTIONS_SUPPORTED - // 2004/11/08-JeffJon - // Transactions will not be supported for the Exchange release - - // Add the transaction to this thread - System.Transactions.Transaction.Current = this.LocalRunspace.ExecutionContext.CurrentTransaction; -#endif // Raise the event for Pipeline.Running RaisePipelineStateEvents(); // Add this pipeline to history RecordPipelineStartTime(); - // Add automatic transcription, but don't transcribe nested commands - if (this.AddToHistory || !IsNested) + // Add automatic transcription when it's NOT a pulse pipeline, but don't transcribe nested commands. + if (!IsPulsePipeline && (AddToHistory || !IsNested)) { - bool needToAddOutDefault = true; - CommandInfo outDefaultCommandInfo = new CmdletInfo("Out-Default", typeof(Microsoft.PowerShell.Commands.OutDefaultCommand), null, null, null); - - foreach (Command command in this.Commands) + foreach (Command command in Commands) { - if (command.IsScript && (!this.IsPulsePipeline)) + if (command.IsScript) { // Transcribe scripts, unless they are the pulse pipeline. - this.Runspace.GetExecutionContext.EngineHostInterface.UI.TranscribeCommand(command.CommandText, null); + Runspace.GetExecutionContext.EngineHostInterface.UI.TranscribeCommand(command.CommandText, invocation: null); } + } + + if (Runspace.GetExecutionContext.EngineHostInterface.UI.IsTranscribing) + { + bool needToAddOutDefault = true; + Command lastCommand = Commands[Commands.Count - 1]; // Don't need to add Out-Default if the pipeline already has it, or we've got a pipeline evaluating - // the PSConsoleHostReadLine command. - if ( - string.Equals(outDefaultCommandInfo.Name, command.CommandText, StringComparison.OrdinalIgnoreCase) || - string.Equals("PSConsoleHostReadLine", command.CommandText, StringComparison.OrdinalIgnoreCase) || - string.Equals("TabExpansion2", command.CommandText, StringComparison.OrdinalIgnoreCase) || - this.IsPulsePipeline) + // the PSConsoleHostReadLine or the TabExpansion2 commands. + if (string.Equals("Out-Default", lastCommand.CommandText, StringComparison.OrdinalIgnoreCase) || + string.Equals("PSConsoleHostReadLine", lastCommand.CommandText, StringComparison.OrdinalIgnoreCase) || + string.Equals("TabExpansion2", lastCommand.CommandText, StringComparison.OrdinalIgnoreCase) || + (lastCommand.CommandInfo is CmdletInfo cmdlet && cmdlet.ImplementingType == typeof(OutDefaultCommand))) { needToAddOutDefault = false; } - } - if (this.Runspace.GetExecutionContext.EngineHostInterface.UI.IsTranscribing) - { if (needToAddOutDefault) { - Command outDefaultCommand = new Command(outDefaultCommandInfo); + var outDefaultCommand = new Command( + new CmdletInfo( + "Out-Default", + typeof(OutDefaultCommand), + helpFile: null, + PSSnapin: null, + context: null)); + outDefaultCommand.Parameters.Add(new CommandParameter("Transcript", true)); outDefaultCommand.Parameters.Add(new CommandParameter("OutVariable", null)); @@ -760,7 +756,7 @@ private void StopThreadProc() StopHelper(); } - private PipelineStopper _stopper; + private readonly PipelineStopper _stopper; /// /// Gets PipelineStopper object which maintains stack of PipelineProcessor @@ -1131,7 +1127,7 @@ protected override { try { - if (_disposed == false) + if (!_disposed) { _disposed = true; if (disposing) @@ -1165,7 +1161,7 @@ internal PipelineThread(ApartmentState apartmentState) _closed = false; #if !UNIX - if (apartmentState != ApartmentState.Unknown && !Platform.IsNanoServer && !Platform.IsIoT) + if (apartmentState != ApartmentState.Unknown && Platform.IsStaSupported) { _worker.SetApartmentState(apartmentState); } @@ -1251,16 +1247,16 @@ public void Dispose() } /// - /// Ensure we release the worker thread. + /// Finalizes an instance of the class. /// ~PipelineThread() { Dispose(); } - private Thread _worker; + private readonly Thread _worker; private ThreadStart _workItem; - private AutoResetEvent _workItemReady; + private readonly AutoResetEvent _workItemReady; private bool _closed; } @@ -1275,13 +1271,13 @@ internal class PipelineStopper /// /// Stack of current executing pipeline processor. /// - private Stack _stack = new Stack(); + private readonly Stack _stack = new Stack(); /// /// Object used for synchronization. /// - private object _syncRoot = new object(); - private LocalPipeline _localPipeline; + private readonly object _syncRoot = new object(); + private readonly LocalPipeline _localPipeline; /// /// Default constructor. @@ -1405,4 +1401,3 @@ internal void Stop() } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/MshHost.cs b/src/System.Management.Automation/engine/hostifaces/MshHost.cs index 64d8f1170f2..7ee89d14b12 100644 --- a/src/System.Management.Automation/engine/hostifaces/MshHost.cs +++ b/src/System.Management.Automation/engine/hostifaces/MshHost.cs @@ -290,6 +290,7 @@ public virtual bool DebuggerEnabled /// This interface needs to be implemented by PSHost objects that want to support the PushRunspace /// and PopRunspace functionality. /// +#nullable enable public interface IHostSupportsInteractiveSession { /// @@ -317,6 +318,6 @@ public interface IHostSupportsInteractiveSession /// Returns the current runspace associated with this host. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Runspace")] - Runspace Runspace { get; } + Runspace? Runspace { get; } } } diff --git a/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs b/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs index c4841cce94d..ea101ade659 100644 --- a/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs +++ b/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs @@ -232,6 +232,161 @@ public virtual void WriteLine(ConsoleColor foregroundColor, ConsoleColor backgro /// public virtual void WriteInformation(InformationRecord record) { } + private static bool ShouldOutputPlainText(bool isHost, bool? supportsVirtualTerminal) + { + var outputRendering = OutputRendering.PlainText; + + if (supportsVirtualTerminal != false) + { + switch (PSStyle.Instance.OutputRendering) + { + case OutputRendering.Host: + outputRendering = isHost ? OutputRendering.Ansi : OutputRendering.PlainText; + break; + default: + outputRendering = PSStyle.Instance.OutputRendering; + break; + } + } + + return outputRendering == OutputRendering.PlainText; + } + + /// + /// The format styles that are supported by the host. + /// + public enum FormatStyle + { + /// + /// Reset the formatting to the default. + /// + Reset, + + /// + /// Highlight text used in output formatting. + /// + FormatAccent, + + /// + /// Highlight for table headers. + /// + TableHeader, + + /// + /// Highlight for detailed error view. + /// + ErrorAccent, + + /// + /// Style for error messages. + /// + Error, + + /// + /// Style for warning messages. + /// + Warning, + + /// + /// Style for verbose messages. + /// + Verbose, + + /// + /// Style for debug messages. + /// + Debug, + } + + /// + /// Get the ANSI escape sequence for the given format style. + /// + /// + /// The format style to get the escape sequence for. + /// + /// + /// True if the output is redirected. + /// + /// + /// The ANSI escape sequence for the given format style. + /// + public static string GetFormatStyleString(FormatStyle formatStyle, bool isOutputRedirected) + { + // redirected console gets plaintext output to preserve existing behavior + if (!InternalTestHooks.BypassOutputRedirectionCheck && + (PSStyle.Instance.OutputRendering == OutputRendering.PlainText || + isOutputRedirected)) + { + return string.Empty; + } + + PSStyle psstyle = PSStyle.Instance; + switch (formatStyle) + { + case FormatStyle.Reset: + return psstyle.Reset; + case FormatStyle.FormatAccent: + return psstyle.Formatting.FormatAccent; + case FormatStyle.TableHeader: + return psstyle.Formatting.TableHeader; + case FormatStyle.ErrorAccent: + return psstyle.Formatting.ErrorAccent; + case FormatStyle.Error: + return psstyle.Formatting.Error; + case FormatStyle.Warning: + return psstyle.Formatting.Warning; + case FormatStyle.Verbose: + return psstyle.Formatting.Verbose; + case FormatStyle.Debug: + return psstyle.Formatting.Debug; + default: + return string.Empty; + } + } + + /// + /// Get the appropriate output string based on different criteria. + /// + /// + /// The text to format. + /// + /// + /// True if the host supports virtual terminal. + /// + /// + /// True if the output is redirected. + /// + /// + /// The formatted text. + /// + public static string GetOutputString(string text, bool supportsVirtualTerminal, bool isOutputRedirected) + { + return GetOutputString(text, isHost: true, supportsVirtualTerminal: supportsVirtualTerminal, isOutputRedirected: isOutputRedirected); + } + + internal static string GetOutputString(string text, bool isHost, bool? supportsVirtualTerminal = null, bool isOutputRedirected = false) + { + var sd = new ValueStringDecorated(text); + + if (sd.IsDecorated) + { + var outputRendering = OutputRendering.Ansi; + if (InternalTestHooks.BypassOutputRedirectionCheck) + { + isOutputRedirected = false; + } + + if (isOutputRedirected || ShouldOutputPlainText(isHost, supportsVirtualTerminal)) + { + outputRendering = OutputRendering.PlainText; + } + + text = sd.ToString(outputRendering); + } + + return text; + } + // Gets the state associated with PowerShell transcription. // // Ideally, this would be associated with the host instance, but remoting recycles host instances @@ -398,7 +553,7 @@ internal void IgnoreCommand(string commandText, InvocationInfo invocation) private sealed class TranscribeOnlyCookie : IDisposable { - private PSHostUserInterface _ui; + private readonly PSHostUserInterface _ui; private bool _disposed = false; public TranscribeOnlyCookie(PSHostUserInterface ui) @@ -438,7 +593,7 @@ private void CheckSystemTranscript() { if (TranscriptionData.SystemTranscript == null) { - TranscriptionData.SystemTranscript = PSHostUserInterface.GetSystemTranscriptOption(TranscriptionData.SystemTranscript); + TranscriptionData.SystemTranscript = GetSystemTranscriptOption(TranscriptionData.SystemTranscript); if (TranscriptionData.SystemTranscript != null) { LogTranscriptHeader(null, TranscriptionData.SystemTranscript); @@ -511,7 +666,7 @@ private void LogTranscriptHeader(System.Management.Automation.Remoting.PSSenderI Environment.MachineName, Environment.OSVersion.VersionString, string.Join(" ", Environment.GetCommandLineArgs()), - System.Diagnostics.Process.GetCurrentProcess().Id, + Environment.ProcessId, versionInfoFooter.ToString().TrimEnd()); } @@ -619,6 +774,13 @@ internal void TranscribeResult(Runspace sourceRunspace, string resultText) } resultText = resultText.TrimEnd(); + + var text = new ValueStringDecorated(resultText); + if (text.IsDecorated) + { + resultText = text.ToString(OutputRendering.PlainText); + } + foreach (TranscriptionOption transcript in TranscriptionData.Transcripts.Prepend(TranscriptionData.SystemTranscript)) { if (transcript != null) @@ -953,10 +1115,10 @@ internal static TranscriptionOption GetSystemTranscriptOption(TranscriptionOptio } internal static TranscriptionOption systemTranscript = null; - private static object s_systemTranscriptLock = new object(); + private static readonly object s_systemTranscriptLock = new object(); - private static Lazy s_transcriptionSettingCache = new Lazy( - () => Utils.GetPolicySetting(Utils.SystemWideThenCurrentUserConfig), + private static readonly Lazy s_transcriptionSettingCache = new Lazy( + static () => Utils.GetPolicySetting(Utils.SystemWideThenCurrentUserConfig), isThreadSafe: true); private static TranscriptionOption GetTranscriptOptionFromSettings(Transcription transcriptConfig, TranscriptionOption currentTranscript) @@ -1051,8 +1213,11 @@ internal TranscriptionData() internal List Transcripts { get; } internal TranscriptionOption SystemTranscript { get; set; } + internal string CommandBeingIgnored { get; set; } + internal bool IsHelperCommand { get; set; } + internal string PromptText { get; set; } } @@ -1068,22 +1233,7 @@ internal TranscriptionOption() /// /// The path that this transcript is being logged to. /// - internal string Path - { - get - { - return _path; - } - - set - { - _path = value; - // Get the encoding from the file, or default (UTF8-NoBom) - Encoding = Utils.GetEncoding(value); - } - } - - private string _path; + internal string Path { get; set; } /// /// Any output to log for this transcript. @@ -1101,12 +1251,6 @@ internal string Path /// internal bool IncludeInvocationHeader { get; set; } - /// - /// The encoding of this transcript, so that appending to it - /// can be done correctly. - /// - internal Encoding Encoding { get; private set; } - /// /// Logs buffered content to disk. We use this instead of File.AppendAllLines /// so that we don't need to pay seek penalties all the time, and so that we @@ -1114,6 +1258,13 @@ internal string Path /// internal void FlushContentToDisk() { + static Encoding GetPathEncoding(string path) + { + using StreamReader reader = new StreamReader(path, Utils.utf8NoBom, detectEncodingFromByteOrderMarks: true); + _ = reader.Read(); + return reader.CurrentEncoding; + } + lock (OutputBeingLogged) { if (!_disposed) @@ -1122,11 +1273,13 @@ internal void FlushContentToDisk() { try { + var currentEncoding = GetPathEncoding(this.Path); + // Try to first open the file with permissions that will allow us to read from it // later. _contentWriter = new StreamWriter( new FileStream(this.Path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read), - this.Encoding); + currentEncoding); _contentWriter.BaseStream.Seek(0, SeekOrigin.End); } catch (IOException) @@ -1135,7 +1288,7 @@ internal void FlushContentToDisk() // file permissions. _contentWriter = new StreamWriter( new FileStream(this.Path, FileMode.Append, FileAccess.Write, FileShare.Read), - this.Encoding); + Utils.utf8NoBom); } _contentWriter.AutoFlush = true; @@ -1173,8 +1326,20 @@ public void Dispose() if (_contentWriter != null) { - _contentWriter.Flush(); - _contentWriter.Dispose(); + try + { + _contentWriter.Flush(); + _contentWriter.Dispose(); + } + catch (ObjectDisposedException) + { + // Do nothing + } + catch (IOException) + { + // Do nothing + } + _contentWriter = null; } @@ -1189,6 +1354,7 @@ public void Dispose() /// by giving the user ability to select more than one choice. The PromptForChoice method available /// in PSHostUserInterface class supports only one choice selection. /// +#nullable enable public interface IHostUISupportsMultipleChoiceSelection { /// @@ -1213,9 +1379,10 @@ public interface IHostUISupportsMultipleChoiceSelection /// implementation. /// /// - Collection PromptForChoice(string caption, string message, - Collection choices, IEnumerable defaultChoices); + Collection PromptForChoice(string? caption, string? message, + Collection choices, IEnumerable? defaultChoices); } +#nullable restore /// /// Helper methods used by PowerShell's Hosts: ConsoleHost and InternalHost to process @@ -1247,7 +1414,7 @@ internal static void BuildHotkeysAndPlainLabels(Collection ch Text.StringBuilder splitLabel = new Text.StringBuilder(choices[i].Label.Substring(0, andPos), choices[i].Label.Length); if (andPos + 1 < choices[i].Label.Length) { - splitLabel.Append(choices[i].Label.Substring(andPos + 1)); + splitLabel.Append(choices[i].Label.AsSpan(andPos + 1)); hotkeysAndPlainLabels[0, i] = CultureInfo.CurrentCulture.TextInfo.ToUpper(choices[i].Label.AsSpan(andPos + 1, 1).Trim().ToString()); } @@ -1320,4 +1487,3 @@ internal static int DetermineChoicePicked(string response, Collection /// - /// A PSCommand instance with added. + /// A PSCommand instance with added. /// /// /// This method is not thread safe. @@ -89,7 +89,7 @@ public PSCommand AddCommand(string command) { if (command == null) { - throw PSTraceSource.NewArgumentNullException("cmdlet"); + throw PSTraceSource.NewArgumentNullException(nameof(command)); } if (_owner != null) @@ -151,15 +151,15 @@ public PSCommand AddCommand(string cmdlet, bool useLocalScope) /// Add a piece of script to construct a command pipeline. /// For example, to construct a command string "get-process | foreach { $_.Name }" /// - /// PSCommand command = new PSCommand("get-process"). - /// AddCommand("foreach { $_.Name }", true); + /// PSCommand command = new PSCommand("get-process") + /// .AddScript("foreach { $_.Name }", true); /// /// /// /// A string representing the script. /// /// - /// A PSCommand instance with added. + /// A PSCommand instance with added. /// /// /// This method is not thread-safe. @@ -193,8 +193,8 @@ public PSCommand AddScript(string script) /// Add a piece of script to construct a command pipeline. /// For example, to construct a command string "get-process | foreach { $_.Name }" /// - /// PSCommand command = new PSCommand("get-process"). - /// AddCommand("foreach { $_.Name }", true); + /// PSCommand command = new PSCommand("get-process") + /// .AddScript("foreach { $_.Name }", true); /// /// /// @@ -204,7 +204,7 @@ public PSCommand AddScript(string script) /// if true local scope is used to run the script command. /// /// - /// A PSCommand instance with added. + /// A PSCommand instance with added. /// /// /// This method is not thread-safe. @@ -276,8 +276,9 @@ public PSCommand AddCommand(Command command) /// Add a parameter to the last added command. /// For example, to construct a command string "get-process | select-object -property name" /// - /// PSCommand command = new PSCommand("get-process"). - /// AddCommand("select-object").AddParameter("property","name"); + /// PSCommand command = new PSCommand("get-process") + /// .AddCommand("select-object") + /// .AddParameter("property", "name"); /// /// /// @@ -321,8 +322,9 @@ public PSCommand AddParameter(string parameterName, object value) /// Adds a switch parameter to the last added command. /// For example, to construct a command string "get-process | sort-object -descending" /// - /// PSCommand command = new PSCommand("get-process"). - /// AddCommand("sort-object").AddParameter("descending"); + /// PSCommand command = new PSCommand("get-process") + /// .AddCommand("sort-object") + /// .AddParameter("descending"); /// /// /// @@ -383,8 +385,9 @@ internal PSCommand AddParameter(CommandParameter parameter) /// Adds an argument to the last added command. /// For example, to construct a command string "get-process | select-object name" /// - /// PSCommand command = new PSCommand("get-process"). - /// AddCommand("select-object").AddParameter("name"); + /// PSCommand command = new PSCommand("get-process") + /// .AddCommand("select-object") + /// .AddArgument("name"); /// /// This will add the value "name" to the positional parameter list of "select-object" /// cmdlet. When the command is invoked, this value will get bound to positional parameter 0 diff --git a/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs b/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs index dfd33cc2257..d51c96a33e0 100644 --- a/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs +++ b/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs @@ -121,7 +121,7 @@ public class PSDataCollection : IList, ICollection, IEnumerable, ILi { #region Private Data - private IList _data; + private readonly IList _data; private ManualResetEvent _readWaitHandle; private bool _isOpen = true; private bool _releaseOnEnumeration; @@ -336,9 +336,7 @@ protected PSDataCollection(SerializationInfo info, StreamingContext context) throw PSTraceSource.NewArgumentNullException(nameof(info)); } - IList listToUse = info.GetValue("Data", typeof(IList)) as IList; - - if (listToUse == null) + if (!(info.GetValue("Data", typeof(IList)) is IList listToUse)) { throw PSTraceSource.NewArgumentNullException(nameof(info)); } @@ -392,7 +390,10 @@ public bool IsOpen /// public int DataAddedCount { - get { return _dataAddedFrequency; } + get + { + return _dataAddedFrequency; + } set { @@ -560,11 +561,7 @@ public void Complete() // A temporary variable is used as the Completed may // reach null (because of -='s) after the null check - EventHandler tempCompleted = Completed; - if (tempCompleted != null) - { - tempCompleted(this, EventArgs.Empty); - } + Completed?.Invoke(this, EventArgs.Empty); } if (raiseDataAdded) @@ -1405,22 +1402,14 @@ private void RaiseDataAddingEvent(Guid psInstanceId, object itemAdded) { // A temporary variable is used as the DataAdding may // reach null (because of -='s) after the null check - EventHandler tempDataAdding = DataAdding; - if (tempDataAdding != null) - { - tempDataAdding(this, new DataAddingEventArgs(psInstanceId, itemAdded)); - } + DataAdding?.Invoke(this, new DataAddingEventArgs(psInstanceId, itemAdded)); } private void RaiseDataAddedEvent(Guid psInstanceId, int index) { // A temporary variable is used as the DataAdded may // reach null (because of -='s) after the null check - EventHandler tempDataAdded = DataAdded; - if (tempDataAdded != null) - { - tempDataAdded(this, new DataAddedEventArgs(psInstanceId, index)); - } + DataAdded?.Invoke(this, new DataAddedEventArgs(psInstanceId, index)); } /// @@ -1643,7 +1632,7 @@ private static void VerifyValueType(object value) } // Serializes an object, as long as it's not serialized. - private PSObject GetSerializedObject(object value) + private static PSObject GetSerializedObject(object value) { // This is a safe cast, as this method is only called with "SerializeInput" is set, // and that method throws if the collection type is not PSObject. @@ -1668,7 +1657,7 @@ private PSObject GetSerializedObject(object value) } } - private bool SerializationWouldHaveNoEffect(PSObject result) + private static bool SerializationWouldHaveNoEffect(PSObject result) { if (result == null) { @@ -1823,8 +1812,8 @@ protected void Dispose(bool disposing) /// Needed to provide a way to get to the non-blocking /// MoveNext implementation. /// - /// - internal interface IBlockingEnumerator : IEnumerator + /// + internal interface IBlockingEnumerator : IEnumerator { bool MoveNext(bool block); } @@ -1836,15 +1825,15 @@ internal interface IBlockingEnumerator : IEnumerator /// either all the PowerShell operations are completed or the /// PSDataCollection is closed. /// - /// - internal sealed class PSDataCollectionEnumerator : IBlockingEnumerator + /// + internal sealed class PSDataCollectionEnumerator : IBlockingEnumerator { #region Private Data - private W _currentElement; + private T _currentElement; private int _index; - private PSDataCollection _collToEnumerate; - private bool _neverBlock; + private readonly PSDataCollection _collToEnumerate; + private readonly bool _neverBlock; #endregion @@ -1859,7 +1848,7 @@ internal sealed class PSDataCollectionEnumerator : IBlockingEnumerator /// /// Controls if the enumerator is blocking by default or not. /// - internal PSDataCollectionEnumerator(PSDataCollection collection, bool neverBlock) + internal PSDataCollectionEnumerator(PSDataCollection collection, bool neverBlock) { Dbg.Assert(collection != null, "Collection cannot be null"); @@ -1868,7 +1857,7 @@ internal PSDataCollectionEnumerator(PSDataCollection collection, bool neverBl _collToEnumerate = collection; _index = 0; - _currentElement = default(W); + _currentElement = default(T); _collToEnumerate.IsEnumerated = true; _neverBlock = neverBlock; } @@ -1886,7 +1875,7 @@ internal PSDataCollectionEnumerator(PSDataCollection collection, bool neverBl /// if the enumerator is positioned before the first element or after /// the last element; the value of the property is undefined. /// - W IEnumerator.Current + T IEnumerator.Current { get { @@ -1925,7 +1914,7 @@ public object Current /// public bool MoveNext() { - return MoveNext(_neverBlock == false); + return MoveNext(!_neverBlock); } /// @@ -1947,7 +1936,7 @@ public bool MoveNext(bool block) _currentElement = _collToEnumerate[_index]; if (_collToEnumerate.ReleaseOnEnumeration) { - _collToEnumerate[_index] = default(W); + _collToEnumerate[_index] = default(T); } _index++; @@ -1956,7 +1945,7 @@ public bool MoveNext(bool block) // we have reached the end if either the collection is closed // or no powershell instance is bound to this collection. - if ((0 == _collToEnumerate.RefCount) || (!_collToEnumerate.IsOpen)) + if ((_collToEnumerate.RefCount == 0) || (!_collToEnumerate.IsOpen)) { return false; } @@ -1989,7 +1978,7 @@ public bool MoveNext(bool block) /// public void Reset() { - _currentElement = default(W); + _currentElement = default(T); _index = 0; } @@ -2010,7 +1999,7 @@ void IDisposable.Dispose() /// internal sealed class PSInformationalBuffers { - private Guid _psInstanceId; + private readonly Guid _psInstanceId; /// /// Default constructor. @@ -2042,7 +2031,10 @@ internal PSInformationalBuffers(Guid psInstanceId) /// internal PSDataCollection Progress { - get { return progress; } + get + { + return progress; + } set { @@ -2058,7 +2050,10 @@ internal PSDataCollection Progress /// internal PSDataCollection Verbose { - get { return verbose; } + get + { + return verbose; + } set { @@ -2074,7 +2069,10 @@ internal PSDataCollection Verbose /// internal PSDataCollection Debug { - get { return debug; } + get + { + return debug; + } set { diff --git a/src/System.Management.Automation/engine/hostifaces/PSTask.cs b/src/System.Management.Automation/engine/hostifaces/PSTask.cs index a25e4e2c840..6e08733cc2b 100644 --- a/src/System.Management.Automation/engine/hostifaces/PSTask.cs +++ b/src/System.Management.Automation/engine/hostifaces/PSTask.cs @@ -68,6 +68,7 @@ protected override void InitializePowershell() _powershell.Streams.Warning.DataAdded += (sender, args) => HandleWarningData(); _powershell.Streams.Verbose.DataAdded += (sender, args) => HandleVerboseData(); _powershell.Streams.Debug.DataAdded += (sender, args) => HandleDebugData(); + _powershell.Streams.Progress.DataAdded += (sender, args) => HandleProgressData(); _powershell.Streams.Information.DataAdded += (sender, args) => HandleInformationData(); // State change handler @@ -132,6 +133,15 @@ private void HandleInformationData() } } + private void HandleProgressData() + { + foreach (var item in _powershell.Streams.Progress.ReadAll()) + { + _dataStreamWriter.Add( + new PSStreamObject(PSStreamObjectType.Progress, item)); + } + } + #endregion #region Event handlers @@ -539,7 +549,7 @@ private PSTaskDataStreamWriter() { } public PSTaskDataStreamWriter(PSCmdlet psCmdlet) { _cmdlet = psCmdlet; - _cmdletThreadId = Thread.CurrentThread.ManagedThreadId; + _cmdletThreadId = Environment.CurrentManagedThreadId; _dataStream = new PSDataCollection(); } @@ -605,7 +615,7 @@ public void Close() private void CheckCmdletThread() { - if (Thread.CurrentThread.ManagedThreadId != _cmdletThreadId) + if (Environment.CurrentManagedThreadId != _cmdletThreadId) { throw new PSInvalidOperationException(InternalCommandStrings.PSTaskStreamWriterWrongThread); } diff --git a/src/System.Management.Automation/engine/hostifaces/Parameter.cs b/src/System.Management.Automation/engine/hostifaces/Parameter.cs index 725cc93e022..8511d13c050 100644 --- a/src/System.Management.Automation/engine/hostifaces/Parameter.cs +++ b/src/System.Management.Automation/engine/hostifaces/Parameter.cs @@ -101,7 +101,7 @@ internal static CommandParameter FromCommandParameterInternal(CommandParameterIn name = internalParameter.ParameterText; if (internalParameter.SpaceAfterParameter) { - name = name + " "; + name += " "; } Diagnostics.Assert(name != null, "'name' variable should be initialized at this point"); @@ -286,4 +286,3 @@ public void Add(string name, object value) } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/Pipeline.cs b/src/System.Management.Automation/engine/hostifaces/Pipeline.cs index 0a584c6fc36..874691852cb 100644 --- a/src/System.Management.Automation/engine/hostifaces/Pipeline.cs +++ b/src/System.Management.Automation/engine/hostifaces/Pipeline.cs @@ -113,13 +113,13 @@ public PipelineState ExpectedState /// State of pipeline when exception was thrown. /// [NonSerialized] - private PipelineState _currentState = 0; + private readonly PipelineState _currentState = 0; /// /// States of the pipeline expected in method which throws this exception. /// [NonSerialized] - private PipelineState _expectedState = 0; + private readonly PipelineState _expectedState = 0; } #endregion Exceptions @@ -738,4 +738,3 @@ protected virtual #endregion IDisposable Members } } - diff --git a/src/System.Management.Automation/engine/hostifaces/PowerShell.cs b/src/System.Management.Automation/engine/hostifaces/PowerShell.cs index 12a4ffce7ab..a2c3c8b4ebe 100644 --- a/src/System.Management.Automation/engine/hostifaces/PowerShell.cs +++ b/src/System.Management.Automation/engine/hostifaces/PowerShell.cs @@ -120,7 +120,7 @@ public PSInvocationState CurrentState /// State of powershell when exception was thrown. /// [NonSerialized] - private PSInvocationState _currState = 0; + private readonly PSInvocationState _currState = 0; } #endregion @@ -263,12 +263,12 @@ internal PSInvocationStateInfo Clone() /// /// The current execution state. /// - private PSInvocationState _executionState; + private readonly PSInvocationState _executionState; /// /// Non-null exception if the execution state change was due to an error. /// - private Exception _exceptionReason; + private readonly Exception _exceptionReason; #endregion } @@ -419,7 +419,7 @@ public bool ExposeFlowControlExceptions /// internal class BatchInvocationContext { - private AutoResetEvent _completionEvent; + private readonly AutoResetEvent _completionEvent; /// /// Class constructor. @@ -589,7 +589,7 @@ public sealed class PowerShell : IDisposable private PSDataCollection _errorBuffer; private bool _isDisposed; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); // client remote powershell if the powershell // is executed with a remote runspace pool @@ -1370,9 +1370,7 @@ public PowerShell AddParameters(IDictionary parameters) foreach (DictionaryEntry entry in parameters) { - string parameterName = entry.Key as string; - - if (parameterName == null) + if (!(entry.Key is string parameterName)) { throw PSTraceSource.NewArgumentException(nameof(parameters), PowerShellStrings.KeyMustBeString); } @@ -3081,6 +3079,10 @@ public IAsyncResult BeginInvoke(PSDataCollection input, /// /// Object is disposed. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// public Task> InvokeAsync() => Task>.Factory.FromAsync(BeginInvoke(), _endInvokeMethod); @@ -3122,6 +3124,10 @@ public Task> InvokeAsync() /// /// Object is disposed. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// public Task> InvokeAsync(PSDataCollection input) => Task>.Factory.FromAsync(BeginInvoke(input), _endInvokeMethod); @@ -3176,6 +3182,10 @@ public Task> InvokeAsync(PSDataCollection input /// /// Object is disposed. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// public Task> InvokeAsync(PSDataCollection input, PSInvocationSettings settings, AsyncCallback callback, object state) => Task>.Factory.FromAsync(BeginInvoke(input, settings, callback, state), _endInvokeMethod); @@ -3224,6 +3234,14 @@ public Task> InvokeAsync(PSDataCollection input /// /// Object is disposed. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// To collect partial output in this scenario, + /// supply a for the parameter, + /// and either add a handler for the event + /// or catch the exception and enumerate the object supplied for . + /// public Task> InvokeAsync(PSDataCollection input, PSDataCollection output) => Task>.Factory.FromAsync(BeginInvoke(input, output), _endInvokeMethod); @@ -3286,6 +3304,14 @@ public Task> InvokeAsync(PSDataColle /// /// Object is disposed. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// To collect partial output in this scenario, + /// supply a for the parameter, + /// and either add a handler for the event + /// or catch the exception and use object supplied for . + /// public Task> InvokeAsync(PSDataCollection input, PSDataCollection output, PSInvocationSettings settings, AsyncCallback callback, object state) => Task>.Factory.FromAsync(BeginInvoke(input, output, settings, callback, state), _endInvokeMethod); @@ -3325,9 +3351,7 @@ public Task> InvokeAsync(PSDataColle /// private IAsyncResult BeginBatchInvoke(PSDataCollection input, PSDataCollection output, PSInvocationSettings settings, AsyncCallback callback, object state) { - PSDataCollection asyncOutput = (object)output as PSDataCollection; - - if (asyncOutput == null) + if (!((object)output is PSDataCollection asyncOutput)) { throw PSTraceSource.NewInvalidOperationException(); } @@ -3497,9 +3521,7 @@ private void BatchInvocationCallback(IAsyncResult result) ActionPreference preference; if (_batchInvocationSettings != null) { - preference = (_batchInvocationSettings.ErrorActionPreference.HasValue) ? - _batchInvocationSettings.ErrorActionPreference.Value - : ActionPreference.Continue; + preference = _batchInvocationSettings.ErrorActionPreference ?? ActionPreference.Continue; } else { @@ -3659,6 +3681,14 @@ private void AppendExceptionToErrorStream(Exception e) /// asyncResult object was not created by calling BeginInvoke /// on this PowerShell instance. /// + /// + /// The running PowerShell pipeline was stopped. + /// This occurs when or is called. + /// To collect partial output in this scenario, + /// supply a to for the parameter + /// and either add a handler for the event + /// or catch the exception and enumerate the object supplied. + /// public PSDataCollection EndInvoke(IAsyncResult asyncResult) { try @@ -3674,7 +3704,7 @@ public PSDataCollection EndInvoke(IAsyncResult asyncResult) if ((psAsyncResult == null) || (psAsyncResult.OwnerId != InstanceId) || - (psAsyncResult.IsAssociatedWithAsyncInvoke != true)) + (!psAsyncResult.IsAssociatedWithAsyncInvoke)) { throw PSTraceSource.NewArgumentException(nameof(asyncResult), PowerShellStrings.AsyncResultNotOwned, "IAsyncResult", "BeginInvoke"); @@ -3710,6 +3740,10 @@ public PSDataCollection EndInvoke(IAsyncResult asyncResult) /// /// Object is disposed. /// + /// + /// When used with , that call will return a partial result. + /// When used with , that call will throw a . + /// public void Stop() { try @@ -3766,6 +3800,10 @@ public IAsyncResult BeginStop(AsyncCallback callback, object state) /// asyncResult object was not created by calling BeginStop /// on this PowerShell instance. /// + /// + /// When used with , that call will return a partial result. + /// When used with , that call will throw a . + /// public void EndStop(IAsyncResult asyncResult) { if (asyncResult == null) @@ -3816,6 +3854,10 @@ public void EndStop(IAsyncResult asyncResult) /// /// Object is disposed. /// + /// + /// When used with , that call will return a partial result. + /// When used with , that call will throw a . + /// public Task StopAsync(AsyncCallback callback, object state) => Task.Factory.FromAsync(BeginStop(callback, state), _endStopMethod); @@ -4606,7 +4648,7 @@ private void CoreInvokeRemoteHelper(PSDataCollection in psAsyncResult.EndInvoke(); EndInvokeAsyncResult = null; - if ((PSInvocationState.Failed == InvocationStateInfo.State) && + if ((InvocationStateInfo.State == PSInvocationState.Failed) && (InvocationStateInfo.Reason != null)) { throw InvocationStateInfo.Reason; @@ -4935,7 +4977,7 @@ private IAsyncResult CoreInvokeAsync(PSDataCollection i /// /// Verifies the settings for ThreadOptions and ApartmentState. /// - private void VerifyThreadSettings(PSInvocationSettings settings, ApartmentState runspaceApartmentState, PSThreadOptions runspaceThreadOptions, bool isRemote) + private static void VerifyThreadSettings(PSInvocationSettings settings, ApartmentState runspaceApartmentState, PSThreadOptions runspaceThreadOptions, bool isRemote) { ApartmentState apartmentState; @@ -4989,7 +5031,7 @@ private void Prepare(PSDataCollection input, PSDataColl lock (_syncObject) { - if ((_psCommand == null) || (_psCommand.Commands == null) || (0 == _psCommand.Commands.Count)) + if ((_psCommand == null) || (_psCommand.Commands == null) || (_psCommand.Commands.Count == 0)) { throw PSTraceSource.NewInvalidOperationException(PowerShellStrings.NoCommandToInvoke); } @@ -5320,7 +5362,7 @@ private void RemoveFromRemoteRunspaceRunningList() private RemoteRunspacePoolInternal GetRemoteRunspacePoolInternal() { RunspacePool runspacePool = _rsConnection as RunspacePool; - return (runspacePool != null) ? (runspacePool.RemoteRunspacePoolInternal) : null; + return runspacePool?.RemoteRunspacePoolInternal; } #endregion @@ -5333,13 +5375,13 @@ private RemoteRunspacePoolInternal GetRemoteRunspacePoolInternal() /// private sealed class Worker { - private ObjectStreamBase _inputStream; - private ObjectStreamBase _outputStream; - private ObjectStreamBase _errorStream; - private PSInvocationSettings _settings; + private readonly ObjectStreamBase _inputStream; + private readonly ObjectStreamBase _outputStream; + private readonly ObjectStreamBase _errorStream; + private readonly PSInvocationSettings _settings; private bool _isNotActive; - private PowerShell _shell; - private object _syncObject = new object(); + private readonly PowerShell _shell; + private readonly object _syncObject = new object(); /// /// @@ -5550,7 +5592,7 @@ internal bool ConstructPipelineAndDoWork(Runspace rs, bool performSyncInvoke) LocalPipeline localPipeline = new LocalPipeline( lrs, _shell.Commands.Commands, - ((_settings != null) && (_settings.AddToHistory)) ? true : false, + (_settings != null && _settings.AddToHistory), _shell.IsNested, _inputStream, _outputStream, @@ -5831,7 +5873,7 @@ internal PSObject ToPSObjectForRemoting() return powerShellAsPSObject; } - private List CommandsAsListOfPSObjects(CommandCollection commands, Version psRPVersion) + private static List CommandsAsListOfPSObjects(CommandCollection commands, Version psRPVersion) { List commandsAsListOfPSObjects = new List(commands.Count); foreach (Command command in commands) @@ -6144,7 +6186,7 @@ public void ClearStreams() this.Warning.Clear(); } - private PowerShell _powershell; + private readonly PowerShell _powershell; } /// @@ -6163,8 +6205,8 @@ public void ClearStreams() /// internal class PowerShellStopper : IDisposable { - private PipelineBase _pipeline; - private PowerShell _powerShell; + private readonly PipelineBase _pipeline; + private readonly PowerShell _powerShell; private EventHandler _eventHandler; internal PowerShellStopper(ExecutionContext context, PowerShell powerShell) diff --git a/src/System.Management.Automation/engine/hostifaces/PowerShellProcessInstance.cs b/src/System.Management.Automation/engine/hostifaces/PowerShellProcessInstance.cs index 35029df1e06..3f4dcf40744 100644 --- a/src/System.Management.Automation/engine/hostifaces/PowerShellProcessInstance.cs +++ b/src/System.Management.Automation/engine/hostifaces/PowerShellProcessInstance.cs @@ -185,6 +185,7 @@ public void Dispose() Dispose(true); GC.SuppressFinalize(this); } + /// /// /// diff --git a/src/System.Management.Automation/engine/hostifaces/RunspaceInit.cs b/src/System.Management.Automation/engine/hostifaces/RunspaceInit.cs index 34244c3db83..1d352448f29 100644 --- a/src/System.Management.Automation/engine/hostifaces/RunspaceInit.cs +++ b/src/System.Management.Automation/engine/hostifaces/RunspaceInit.cs @@ -26,4 +26,3 @@ private void InitializeDefaults() } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/RunspacePool.cs b/src/System.Management.Automation/engine/hostifaces/RunspacePool.cs index 9f281f2956a..5f814e0428b 100644 --- a/src/System.Management.Automation/engine/hostifaces/RunspacePool.cs +++ b/src/System.Management.Automation/engine/hostifaces/RunspacePool.cs @@ -182,13 +182,13 @@ private static RunspaceState RunspacePoolStateToRunspaceState(RunspacePoolState /// State of the runspace pool when exception was thrown. /// [NonSerialized] - private RunspacePoolState _currentState = 0; + private readonly RunspacePoolState _currentState = 0; /// /// State of the runspace pool expected in method which throws this exception. /// [NonSerialized] - private RunspacePoolState _expectedState = 0; + private readonly RunspacePoolState _expectedState = 0; } #endregion @@ -504,11 +504,13 @@ public sealed class RunspacePool : IDisposable { #region Private Data - private RunspacePoolInternal _internalPool; - private object _syncObject = new object(); + private readonly RunspacePoolInternal _internalPool; + private readonly object _syncObject = new object(); private event EventHandler InternalStateChanged = null; + private event EventHandler InternalForwardEvent = null; + private event EventHandler InternalRunspaceCreated = null; #endregion @@ -837,12 +839,7 @@ private void OnInternalPoolForwardEvent(object sender, PSEventArgs e) /// private void OnEventForwarded(PSEventArgs e) { - EventHandler eh = InternalForwardEvent; - - if (eh != null) - { - eh(this, e); - } + InternalForwardEvent?.Invoke(this, e); } /// diff --git a/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs index 37ab127658c..aac3acfbdf8 100644 --- a/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs +++ b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs @@ -40,7 +40,7 @@ internal class RunspacePoolInternal private static readonly TimeSpan s_defaultCleanupPeriod = new TimeSpan(0, 15, 0); // 15 minutes. private TimeSpan _cleanupInterval; - private Timer _cleanupTimer; + private readonly Timer _cleanupTimer; #endregion @@ -276,7 +276,10 @@ public virtual RunspaceConnectionInfo ConnectionInfo /// public TimeSpan CleanupInterval { - get { return _cleanupInterval; } + get + { + return _cleanupInterval; + } set { @@ -1640,12 +1643,7 @@ protected void AssertIfStateIsBeforeOpen() /// protected virtual void OnForwardEvent(PSEventArgs e) { - EventHandler eh = this.ForwardEvent; - - if (eh != null) - { - eh(this, e); - } + this.ForwardEvent?.Invoke(this, e); } /// diff --git a/src/System.Management.Automation/engine/hostifaces/internalHostuserInterfacesecurity.cs b/src/System.Management.Automation/engine/hostifaces/internalHostuserInterfacesecurity.cs index 0aeb89197f1..a7acbd0760b 100644 --- a/src/System.Management.Automation/engine/hostifaces/internalHostuserInterfacesecurity.cs +++ b/src/System.Management.Automation/engine/hostifaces/internalHostuserInterfacesecurity.cs @@ -72,4 +72,3 @@ PSCredentialUIOptions options } } } - diff --git a/src/System.Management.Automation/engine/hostifaces/pipelinebase.cs b/src/System.Management.Automation/engine/hostifaces/pipelinebase.cs index 64efdb12e4a..0eaa30daae0 100644 --- a/src/System.Management.Automation/engine/hostifaces/pipelinebase.cs +++ b/src/System.Management.Automation/engine/hostifaces/pipelinebase.cs @@ -491,7 +491,9 @@ private void CoreInvoke(IEnumerable input, bool syncCall) throw e; } - if (syncCall && !(InputStream is PSDataCollectionStream || InputStream is PSDataCollectionStream)) + if (syncCall + && InputStream is not PSDataCollectionStream + && InputStream is not PSDataCollectionStream) { // Method is called from synchronous invoke. if (input != null) @@ -616,7 +618,7 @@ internal void DoConcurrentCheck(bool syncCall, object syncObject, bool isInLock) { PipelineBase currentPipeline = (PipelineBase)RunspaceBase.GetCurrentlyRunningPipeline(); - if (IsNested == false) + if (!IsNested) { if (currentPipeline == null) { @@ -663,7 +665,7 @@ internal void DoConcurrentCheck(bool syncCall, object syncObject, bool isInLock) { if (_performNestedCheck) { - if (syncCall == false) + if (!syncCall) { throw PSTraceSource.NewInvalidOperationException( RunspaceStrings.NestedPipelineInvokeAsync); @@ -688,7 +690,7 @@ internal void DoConcurrentCheck(bool syncCall, object syncObject, bool isInLock) Dbg.Assert(currentPipeline.NestedPipelineExecutionThread != null, "Current pipeline should always have NestedPipelineExecutionThread set"); Thread th = Thread.CurrentThread; - if (currentPipeline.NestedPipelineExecutionThread.Equals(th) == false) + if (!currentPipeline.NestedPipelineExecutionThread.Equals(th)) { throw PSTraceSource.NewInvalidOperationException( RunspaceStrings.NestedPipelineNoParentPipeline); @@ -766,7 +768,7 @@ protected bool IsPipelineFinished() /// private Queue _executionEventQueue = new Queue(); - private class ExecutionEventQueueItem + private sealed class ExecutionEventQueueItem { public ExecutionEventQueueItem(PipelineStateInfo pipelineStateInfo, RunspaceAvailability currentAvailability, RunspaceAvailability newAvailability) { @@ -1044,7 +1046,7 @@ protected override { try { - if (_disposed == false) + if (!_disposed) { _disposed = true; if (disposing) diff --git a/src/System.Management.Automation/engine/interpreter/AddInstruction.cs b/src/System.Management.Automation/engine/interpreter/AddInstruction.cs index 9858167aa74..2f7ada9dcfd 100644 --- a/src/System.Management.Automation/engine/interpreter/AddInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/AddInstruction.cs @@ -130,14 +130,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new AddInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new AddInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new AddInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new AddUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new AddUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new AddUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new AddSingle()); - case TypeCode.Double: return s_double ?? (s_double = new AddDouble()); + case TypeCode.Int16: return s_int16 ??= new AddInt16(); + case TypeCode.Int32: return s_int32 ??= new AddInt32(); + case TypeCode.Int64: return s_int64 ??= new AddInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new AddUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new AddUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new AddUInt64(); + case TypeCode.Single: return s_single ??= new AddSingle(); + case TypeCode.Double: return s_double ??= new AddDouble(); default: throw Assert.Unreachable; @@ -263,14 +263,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new AddOvfInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new AddOvfInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new AddOvfInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new AddOvfUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new AddOvfUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new AddOvfUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new AddOvfSingle()); - case TypeCode.Double: return s_double ?? (s_double = new AddOvfDouble()); + case TypeCode.Int16: return s_int16 ??= new AddOvfInt16(); + case TypeCode.Int32: return s_int32 ??= new AddOvfInt32(); + case TypeCode.Int64: return s_int64 ??= new AddOvfInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new AddOvfUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new AddOvfUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new AddOvfUInt64(); + case TypeCode.Single: return s_single ??= new AddOvfSingle(); + case TypeCode.Double: return s_double ??= new AddOvfDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/BranchLabel.cs b/src/System.Management.Automation/engine/interpreter/BranchLabel.cs index 919a7b06106..08af974416c 100644 --- a/src/System.Management.Automation/engine/interpreter/BranchLabel.cs +++ b/src/System.Management.Automation/engine/interpreter/BranchLabel.cs @@ -19,7 +19,7 @@ namespace System.Management.Automation.Interpreter { - internal struct RuntimeLabel + internal readonly struct RuntimeLabel { public readonly int Index; public readonly int StackDepth; diff --git a/src/System.Management.Automation/engine/interpreter/CallInstruction.cs b/src/System.Management.Automation/engine/interpreter/CallInstruction.cs index bcf3acc8251..88ff4bc1357 100644 --- a/src/System.Management.Automation/engine/interpreter/CallInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/CallInstruction.cs @@ -178,7 +178,7 @@ public static void ArrayItemSetter3(Array array, int index0, int index1, int ind private static bool ShouldCache(MethodInfo info) { - return !(info is DynamicMethod); + return info is not DynamicMethod; } /// diff --git a/src/System.Management.Automation/engine/interpreter/ControlFlowInstructions.cs b/src/System.Management.Automation/engine/interpreter/ControlFlowInstructions.cs index 56aca65df37..0fddd203346 100644 --- a/src/System.Management.Automation/engine/interpreter/ControlFlowInstructions.cs +++ b/src/System.Management.Automation/engine/interpreter/ControlFlowInstructions.cs @@ -69,7 +69,7 @@ internal sealed class BranchFalseInstruction : OffsetInstruction public override Instruction[] Cache { - get { return s_cache ?? (s_cache = new Instruction[CacheSize]); } + get { return s_cache ??= new Instruction[CacheSize]; } } internal BranchFalseInstruction() @@ -97,7 +97,7 @@ internal sealed class BranchTrueInstruction : OffsetInstruction public override Instruction[] Cache { - get { return s_cache ?? (s_cache = new Instruction[CacheSize]); } + get { return s_cache ??= new Instruction[CacheSize]; } } internal BranchTrueInstruction() @@ -125,7 +125,7 @@ internal sealed class CoalescingBranchInstruction : OffsetInstruction public override Instruction[] Cache { - get { return s_cache ?? (s_cache = new Instruction[CacheSize]); } + get { return s_cache ??= new Instruction[CacheSize]; } } internal CoalescingBranchInstruction() @@ -204,7 +204,7 @@ internal abstract class IndexedBranchInstruction : Instruction internal readonly int _labelIndex; - public IndexedBranchInstruction(int labelIndex) + protected IndexedBranchInstruction(int labelIndex) { _labelIndex = labelIndex; } @@ -554,7 +554,7 @@ public override int Run(InterpretedFrame frame) /// internal sealed class LeaveExceptionHandlerInstruction : IndexedBranchInstruction { - private static LeaveExceptionHandlerInstruction[] s_cache = new LeaveExceptionHandlerInstruction[2 * CacheSize]; + private static readonly LeaveExceptionHandlerInstruction[] s_cache = new LeaveExceptionHandlerInstruction[2 * CacheSize]; private readonly bool _hasValue; diff --git a/src/System.Management.Automation/engine/interpreter/DivInstruction.cs b/src/System.Management.Automation/engine/interpreter/DivInstruction.cs index f6cfb5b265f..11edd140945 100644 --- a/src/System.Management.Automation/engine/interpreter/DivInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/DivInstruction.cs @@ -130,14 +130,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new DivInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new DivInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new DivInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new DivUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new DivUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new DivUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new DivSingle()); - case TypeCode.Double: return s_double ?? (s_double = new DivDouble()); + case TypeCode.Int16: return s_int16 ??= new DivInt16(); + case TypeCode.Int32: return s_int32 ??= new DivInt32(); + case TypeCode.Int64: return s_int64 ??= new DivInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new DivUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new DivUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new DivUInt64(); + case TypeCode.Single: return s_single ??= new DivSingle(); + case TypeCode.Double: return s_double ??= new DivDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/EqualInstruction.cs b/src/System.Management.Automation/engine/interpreter/EqualInstruction.cs index 639190e4d46..4db34761ce8 100644 --- a/src/System.Management.Automation/engine/interpreter/EqualInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/EqualInstruction.cs @@ -154,25 +154,25 @@ public static Instruction Create(Type type) var typeToUse = type.IsEnum ? Enum.GetUnderlyingType(type) : type; switch (typeToUse.GetTypeCode()) { - case TypeCode.Boolean: return s_boolean ?? (s_boolean = new EqualBoolean()); - case TypeCode.SByte: return s_SByte ?? (s_SByte = new EqualSByte()); - case TypeCode.Byte: return s_byte ?? (s_byte = new EqualByte()); - case TypeCode.Char: return s_char ?? (s_char = new EqualChar()); - case TypeCode.Int16: return s_int16 ?? (s_int16 = new EqualInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new EqualInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new EqualInt64()); + case TypeCode.Boolean: return s_boolean ??= new EqualBoolean(); + case TypeCode.SByte: return s_SByte ??= new EqualSByte(); + case TypeCode.Byte: return s_byte ??= new EqualByte(); + case TypeCode.Char: return s_char ??= new EqualChar(); + case TypeCode.Int16: return s_int16 ??= new EqualInt16(); + case TypeCode.Int32: return s_int32 ??= new EqualInt32(); + case TypeCode.Int64: return s_int64 ??= new EqualInt64(); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new EqualInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new EqualInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new EqualInt64()); + case TypeCode.UInt16: return s_UInt16 ??= new EqualInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new EqualInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new EqualInt64(); - case TypeCode.Single: return s_single ?? (s_single = new EqualSingle()); - case TypeCode.Double: return s_double ?? (s_double = new EqualDouble()); + case TypeCode.Single: return s_single ??= new EqualSingle(); + case TypeCode.Double: return s_double ??= new EqualDouble(); case TypeCode.Object: if (!type.IsValueType) { - return s_reference ?? (s_reference = new EqualReference()); + return s_reference ??= new EqualReference(); } // TODO: Nullable throw new NotImplementedException(); diff --git a/src/System.Management.Automation/engine/interpreter/GreaterThanInstruction.cs b/src/System.Management.Automation/engine/interpreter/GreaterThanInstruction.cs index 9f46323308f..ccd5c3780f7 100644 --- a/src/System.Management.Automation/engine/interpreter/GreaterThanInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/GreaterThanInstruction.cs @@ -144,17 +144,17 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.SByte: return s_SByte ?? (s_SByte = new GreaterThanSByte()); - case TypeCode.Byte: return s_byte ?? (s_byte = new GreaterThanByte()); - case TypeCode.Char: return s_char ?? (s_char = new GreaterThanChar()); - case TypeCode.Int16: return s_int16 ?? (s_int16 = new GreaterThanInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new GreaterThanInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new GreaterThanInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new GreaterThanUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new GreaterThanUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new GreaterThanUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new GreaterThanSingle()); - case TypeCode.Double: return s_double ?? (s_double = new GreaterThanDouble()); + case TypeCode.SByte: return s_SByte ??= new GreaterThanSByte(); + case TypeCode.Byte: return s_byte ??= new GreaterThanByte(); + case TypeCode.Char: return s_char ??= new GreaterThanChar(); + case TypeCode.Int16: return s_int16 ??= new GreaterThanInt16(); + case TypeCode.Int32: return s_int32 ??= new GreaterThanInt32(); + case TypeCode.Int64: return s_int64 ??= new GreaterThanInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new GreaterThanUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new GreaterThanUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new GreaterThanUInt64(); + case TypeCode.Single: return s_single ??= new GreaterThanSingle(); + case TypeCode.Double: return s_double ??= new GreaterThanDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/ILightCallSiteBinder.cs b/src/System.Management.Automation/engine/interpreter/ILightCallSiteBinder.cs index 49fbfdb0f8e..9f24d14fa14 100644 --- a/src/System.Management.Automation/engine/interpreter/ILightCallSiteBinder.cs +++ b/src/System.Management.Automation/engine/interpreter/ILightCallSiteBinder.cs @@ -13,6 +13,7 @@ * * ***************************************************************************/ +#nullable enable #if !CLR2 #else using Microsoft.Scripting.Ast; diff --git a/src/System.Management.Automation/engine/interpreter/Instruction.cs b/src/System.Management.Automation/engine/interpreter/Instruction.cs index 0a46fd88dfa..f1d8edaeb87 100644 --- a/src/System.Management.Automation/engine/interpreter/Instruction.cs +++ b/src/System.Management.Automation/engine/interpreter/Instruction.cs @@ -17,10 +17,12 @@ namespace System.Management.Automation.Interpreter { +#nullable enable internal interface IInstructionProvider { void AddInstructions(LightCompiler compiler); } +#nullable restore internal abstract class Instruction { diff --git a/src/System.Management.Automation/engine/interpreter/InstructionFactory.cs b/src/System.Management.Automation/engine/interpreter/InstructionFactory.cs index 286fce26f15..4a707201eb6 100644 --- a/src/System.Management.Automation/engine/interpreter/InstructionFactory.cs +++ b/src/System.Management.Automation/engine/interpreter/InstructionFactory.cs @@ -53,11 +53,17 @@ internal static InstructionFactory GetFactory(Type type) } protected internal abstract Instruction GetArrayItem(); + protected internal abstract Instruction SetArrayItem(); + protected internal abstract Instruction TypeIs(); + protected internal abstract Instruction TypeAs(); + protected internal abstract Instruction DefaultValue(); + protected internal abstract Instruction NewArray(); + protected internal abstract Instruction NewArrayInit(int elementCount); } @@ -81,32 +87,32 @@ private InstructionFactory() { } protected internal override Instruction GetArrayItem() { - return _getArrayItem ?? (_getArrayItem = new GetArrayItemInstruction()); + return _getArrayItem ??= new GetArrayItemInstruction(); } protected internal override Instruction SetArrayItem() { - return _setArrayItem ?? (_setArrayItem = new SetArrayItemInstruction()); + return _setArrayItem ??= new SetArrayItemInstruction(); } protected internal override Instruction TypeIs() { - return _typeIs ?? (_typeIs = new TypeIsInstruction()); + return _typeIs ??= new TypeIsInstruction(); } protected internal override Instruction TypeAs() { - return _typeAs ?? (_typeAs = new TypeAsInstruction()); + return _typeAs ??= new TypeAsInstruction(); } protected internal override Instruction DefaultValue() { - return _defaultValue ?? (_defaultValue = new DefaultValueInstruction()); + return _defaultValue ??= new DefaultValueInstruction(); } protected internal override Instruction NewArray() { - return _newArray ?? (_newArray = new NewArrayInstruction()); + return _newArray ??= new NewArrayInstruction(); } protected internal override Instruction NewArrayInit(int elementCount) diff --git a/src/System.Management.Automation/engine/interpreter/InstructionList.cs b/src/System.Management.Automation/engine/interpreter/InstructionList.cs index 9617c746359..cbf831f3377 100644 --- a/src/System.Management.Automation/engine/interpreter/InstructionList.cs +++ b/src/System.Management.Automation/engine/interpreter/InstructionList.cs @@ -24,7 +24,7 @@ namespace System.Management.Automation.Interpreter { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] [DebuggerTypeProxy(typeof(InstructionArray.DebugView))] - internal struct InstructionArray + internal readonly struct InstructionArray { internal readonly int MaxStackDepth; internal readonly int MaxContinuationDepth; @@ -95,7 +95,9 @@ internal sealed class InstructionList private List _labels; // list of (instruction index, cookie) sorted by instruction index: +#pragma warning disable IDE0044 // Add readonly modifier private List> _debugCookies = null; +#pragma warning restore IDE0044 // Variable is assigned when DEBUG is defined. #region Debug View @@ -156,7 +158,7 @@ internal static InstructionView[] GetInstructionViews(IList instruc } [DebuggerDisplay("{GetValue(),nq}", Name = "{GetName(),nq}", Type = "{GetDisplayType(), nq}")] - internal struct InstructionView + internal readonly struct InstructionView { private readonly int _index; private readonly int _stackDepth; @@ -273,7 +275,7 @@ internal Instruction GetInstruction(int index) static InstructionList() { AppDomain.CurrentDomain.ProcessExit += new EventHandler((_, __) => { PerfTrack.DumpHistogram(_executedInstructions); - Console.WriteLine("-- Total executed: {0}", _executedInstructions.Values.Aggregate(0, (sum, value) => sum + value)); + Console.WriteLine("-- Total executed: {0}", _executedInstructions.Values.Aggregate(0, static (sum, value) => sum + value)); Console.WriteLine("-----"); var referenced = new Dictionary(); @@ -312,7 +314,7 @@ public InstructionArray ToArray() _maxStackDepth, _maxContinuationDepth, _instructions.ToArray(), - (_objects != null) ? _objects.ToArray() : null, + _objects?.ToArray(), BuildRuntimeLabels(), _debugCookies ); @@ -341,11 +343,11 @@ public void EmitLoad(bool value) { if ((bool)value) { - Emit(s_true ?? (s_true = new LoadObjectInstruction(value))); + Emit(s_true ??= new LoadObjectInstruction(value)); } else { - Emit(s_false ?? (s_false = new LoadObjectInstruction(value))); + Emit(s_false ??= new LoadObjectInstruction(value)); } } @@ -353,7 +355,7 @@ public void EmitLoad(object value, Type type) { if (value == null) { - Emit(s_null ?? (s_null = new LoadObjectInstruction(null))); + Emit(s_null ??= new LoadObjectInstruction(null)); return; } @@ -925,7 +927,7 @@ public void EmitLoadField(FieldInfo field) Emit(GetLoadField(field)); } - private Instruction GetLoadField(FieldInfo field) + private static Instruction GetLoadField(FieldInfo field) { lock (s_loadFields) { @@ -1063,7 +1065,7 @@ public void EmitDynamic> s_factories = + private static readonly Dictionary> s_factories = new Dictionary>(); internal static Instruction CreateDynamicInstruction(Type delegateType, CallSiteBinder binder) @@ -1086,9 +1088,9 @@ internal static Instruction CreateDynamicInstruction(Type delegateType, CallSite return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder)); } - factory = - (Func) - instructionType.GetMethod("Factory").CreateDelegate(typeof(Func)); + factory = (Func)instructionType + .GetMethod("Factory") + .CreateDelegate(typeof(Func)); s_factories[delegateType] = factory; } diff --git a/src/System.Management.Automation/engine/interpreter/InterpretedFrame.cs b/src/System.Management.Automation/engine/interpreter/InterpretedFrame.cs index d4d6923da81..4b084ba72a8 100644 --- a/src/System.Management.Automation/engine/interpreter/InterpretedFrame.cs +++ b/src/System.Management.Automation/engine/interpreter/InterpretedFrame.cs @@ -34,7 +34,7 @@ internal sealed class InterpretedFrame internal InterpretedFrame _parent; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")] - private int[] _continuations; + private readonly int[] _continuations; private int _continuationIndex; private int _pendingContinuation; @@ -295,12 +295,12 @@ internal void PopPendingContinuation() internal static MethodInfo GotoMethod { - get { return s_goto ?? (s_goto = typeof(InterpretedFrame).GetMethod("Goto")); } + get { return s_goto ??= typeof(InterpretedFrame).GetMethod("Goto"); } } internal static MethodInfo VoidGotoMethod { - get { return s_voidGoto ?? (s_voidGoto = typeof(InterpretedFrame).GetMethod("VoidGoto")); } + get { return s_voidGoto ??= typeof(InterpretedFrame).GetMethod("VoidGoto"); } } public int VoidGoto(int labelIndex) diff --git a/src/System.Management.Automation/engine/interpreter/LabelInfo.cs b/src/System.Management.Automation/engine/interpreter/LabelInfo.cs index a8518099824..639be5204cc 100644 --- a/src/System.Management.Automation/engine/interpreter/LabelInfo.cs +++ b/src/System.Management.Automation/engine/interpreter/LabelInfo.cs @@ -137,7 +137,7 @@ private void ValidateJump(LabelScopeInfo reference) // We didn't find an outward jump. Look for a jump across blocks LabelScopeInfo def = FirstDefinition(); - LabelScopeInfo common = CommonNode(def, reference, b => b.Parent); + LabelScopeInfo common = CommonNode(def, reference, static b => b.Parent); // Validate that we aren't jumping across a finally for (LabelScopeInfo j = reference; j != common; j = j.Parent) diff --git a/src/System.Management.Automation/engine/interpreter/LessThanInstruction.cs b/src/System.Management.Automation/engine/interpreter/LessThanInstruction.cs index aaf632d0c77..2d6754ff2fd 100644 --- a/src/System.Management.Automation/engine/interpreter/LessThanInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/LessThanInstruction.cs @@ -144,17 +144,17 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.SByte: return s_SByte ?? (s_SByte = new LessThanSByte()); - case TypeCode.Byte: return s_byte ?? (s_byte = new LessThanByte()); - case TypeCode.Char: return s_char ?? (s_char = new LessThanChar()); - case TypeCode.Int16: return s_int16 ?? (s_int16 = new LessThanInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new LessThanInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new LessThanInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LessThanUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LessThanUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LessThanUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new LessThanSingle()); - case TypeCode.Double: return s_double ?? (s_double = new LessThanDouble()); + case TypeCode.SByte: return s_SByte ??= new LessThanSByte(); + case TypeCode.Byte: return s_byte ??= new LessThanByte(); + case TypeCode.Char: return s_char ??= new LessThanChar(); + case TypeCode.Int16: return s_int16 ??= new LessThanInt16(); + case TypeCode.Int32: return s_int32 ??= new LessThanInt32(); + case TypeCode.Int64: return s_int64 ??= new LessThanInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new LessThanUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new LessThanUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new LessThanUInt64(); + case TypeCode.Single: return s_single ??= new LessThanSingle(); + case TypeCode.Double: return s_double ??= new LessThanDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/LightCompiler.cs b/src/System.Management.Automation/engine/interpreter/LightCompiler.cs index e5d399bf480..279a36baac7 100644 --- a/src/System.Management.Automation/engine/interpreter/LightCompiler.cs +++ b/src/System.Management.Automation/engine/interpreter/LightCompiler.cs @@ -192,7 +192,7 @@ internal class DebugInfo public bool IsClear; private static readonly DebugInfoComparer s_debugComparer = new DebugInfoComparer(); - private class DebugInfoComparer : IComparer + private sealed class DebugInfoComparer : IComparer { // We allow comparison between int and DebugInfo here int IComparer.Compare(DebugInfo d1, DebugInfo d2) @@ -221,7 +221,7 @@ public static DebugInfo GetMatchingDebugInfo(DebugInfo[] debugInfos, int index) return null; } // return the last one that is smaller - i = i - 1; + i -= 1; } return debugInfos[i]; @@ -243,7 +243,7 @@ public override string ToString() // TODO: [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] [Serializable] - internal struct InterpretedFrameInfo + internal readonly struct InterpretedFrameInfo { public readonly string MethodName; @@ -288,7 +288,7 @@ internal sealed class LightCompiler private readonly LightCompiler _parent; - private static LocalDefinition[] s_emptyLocals = Array.Empty(); + private static readonly LocalDefinition[] s_emptyLocals = Array.Empty(); public LightCompiler(int compilationThreshold) { @@ -1025,7 +1025,7 @@ private void CompileConditionalExpression(Expression expr, bool asVoid) #region Loops - private void CompileLoopExpression(Expression expr) + private static void CompileLoopExpression(Expression expr) { // var node = (LoopExpression)expr; // var enterLoop = new EnterLoopInstruction(node, _locals, _compilationThreshold, _instructions.Count); @@ -1063,7 +1063,7 @@ private void CompileSwitchExpression(Expression expr) } // Test values must be constant - if (!node.Cases.All(c => c.TestValues.All(t => t is ConstantExpression))) + if (!node.Cases.All(static c => c.TestValues.All(t => t is ConstantExpression))) { throw new NotImplementedException(); } @@ -1297,8 +1297,7 @@ private bool TryPushLabelBlock(Expression node) private void DefineBlockLabels(Expression node) { - var block = node as BlockExpression; - if (block == null) + if (!(node is BlockExpression block)) { return; } @@ -1532,7 +1531,7 @@ private void CompileTryExpression(Expression expr) enterTryInstr.SetTryHandler( new TryCatchFinallyHandler(tryStart, tryEnd, gotoEnd.TargetIndex, startOfFinally.TargetIndex, _instructions.Count, - exHandlers != null ? exHandlers.ToArray() : null)); + exHandlers?.ToArray())); PopLabelBlock(LabelScopeKind.Finally); } else @@ -1574,7 +1573,7 @@ private void CompileMethodCallExpression(Expression expr) // also could be a mutable value type, Delegate.CreateDelegate and MethodInfo.Invoke both can't handle this, we // need to generate code. var declaringType = node.Method.DeclaringType; - if (!parameters.TrueForAll(p => !p.ParameterType.IsByRef) || + if (!parameters.TrueForAll(static p => !p.ParameterType.IsByRef) || (!node.Method.IsStatic && declaringType.IsValueType && !declaringType.IsPrimitive)) { _forceCompile = true; @@ -1601,7 +1600,7 @@ private void CompileNewExpression(Expression expr) if (node.Constructor != null) { var parameters = node.Constructor.GetParameters(); - if (!parameters.TrueForAll(p => !p.ParameterType.IsByRef)) + if (!parameters.TrueForAll(static p => !p.ParameterType.IsByRef)) { _forceCompile = true; } @@ -2005,7 +2004,8 @@ private void CompileNoLabelPush(Expression expr) case ExpressionType.Index: CompileIndexExpression(expr); break; case ExpressionType.Label: CompileLabelExpression(expr); break; case ExpressionType.RuntimeVariables: CompileRuntimeVariablesExpression(expr); break; - case ExpressionType.Loop: CompileLoopExpression(expr); break; + case ExpressionType.Loop: + CompileLoopExpression(expr); break; case ExpressionType.Switch: CompileSwitchExpression(expr); break; case ExpressionType.Throw: CompileThrowUnaryExpression(expr, expr.Type == typeof(void)); break; case ExpressionType.Try: CompileTryExpression(expr); break; diff --git a/src/System.Management.Automation/engine/interpreter/LightDelegateCreator.cs b/src/System.Management.Automation/engine/interpreter/LightDelegateCreator.cs index 5c96d2f6870..6f9497db987 100644 --- a/src/System.Management.Automation/engine/interpreter/LightDelegateCreator.cs +++ b/src/System.Management.Automation/engine/interpreter/LightDelegateCreator.cs @@ -169,7 +169,7 @@ internal void Compile(object state) // So change the lambda's delegate type to Func<...> or // Action<...> so it can be called from the LightLambda.Run // methods. - LambdaExpression lambda = (_lambda as LambdaExpression);// ?? (LambdaExpression)((LightLambdaExpression)_lambda).Reduce(); + LambdaExpression lambda = (_lambda as LambdaExpression); // ?? (LambdaExpression)((LightLambdaExpression)_lambda).Reduce(); if (_interpreter != null) { _compiledDelegateType = GetFuncOrAction(lambda); @@ -196,7 +196,7 @@ private static Type GetFuncOrAction(LambdaExpression lambda) // lambda.Parameters[0].IsByRef && lambda.Parameters[1].IsByRef) { // return typeof(ActionRef<,>).MakeGenericType(lambda.Parameters.Map(p => p.Type)); // } else { - Type[] types = lambda.Parameters.Map(p => p.IsByRef ? p.Type.MakeByRefType() : p.Type); + Type[] types = lambda.Parameters.Map(static p => p.IsByRef ? p.Type.MakeByRefType() : p.Type); if (isVoid) { if (Expression.TryGetActionType(types, out delegateType)) diff --git a/src/System.Management.Automation/engine/interpreter/LocalAccess.cs b/src/System.Management.Automation/engine/interpreter/LocalAccess.cs index 7b0711b1930..30596866c0c 100644 --- a/src/System.Management.Automation/engine/interpreter/LocalAccess.cs +++ b/src/System.Management.Automation/engine/interpreter/LocalAccess.cs @@ -23,10 +23,13 @@ namespace System.Management.Automation.Interpreter { + +#nullable enable internal interface IBoxableInstruction { - Instruction BoxIfIndexMatches(int index); + Instruction? BoxIfIndexMatches(int index); } +#nullable restore internal abstract class LocalAccessInstruction : Instruction { diff --git a/src/System.Management.Automation/engine/interpreter/LocalVariables.cs b/src/System.Management.Automation/engine/interpreter/LocalVariables.cs index e093877ce34..d52f1fc6840 100644 --- a/src/System.Management.Automation/engine/interpreter/LocalVariables.cs +++ b/src/System.Management.Automation/engine/interpreter/LocalVariables.cs @@ -35,7 +35,10 @@ internal sealed class LocalVariable public bool IsBoxed { - get { return (_flags & IsBoxedFlag) != 0; } + get + { + return (_flags & IsBoxedFlag) != 0; + } set { @@ -78,7 +81,7 @@ public override string ToString() } } - internal struct LocalDefinition + internal readonly struct LocalDefinition { private readonly int _index; private readonly ParameterExpression _parameter; diff --git a/src/System.Management.Automation/engine/interpreter/MulInstruction.cs b/src/System.Management.Automation/engine/interpreter/MulInstruction.cs index 486d2ebc751..3b150a7abbd 100644 --- a/src/System.Management.Automation/engine/interpreter/MulInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/MulInstruction.cs @@ -130,14 +130,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new MulInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new MulInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new MulInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new MulUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new MulUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new MulUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new MulSingle()); - case TypeCode.Double: return s_double ?? (s_double = new MulDouble()); + case TypeCode.Int16: return s_int16 ??= new MulInt16(); + case TypeCode.Int32: return s_int32 ??= new MulInt32(); + case TypeCode.Int64: return s_int64 ??= new MulInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new MulUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new MulUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new MulUInt64(); + case TypeCode.Single: return s_single ??= new MulSingle(); + case TypeCode.Double: return s_double ??= new MulDouble(); default: throw Assert.Unreachable; @@ -263,14 +263,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new MulOvfInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new MulOvfInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new MulOvfInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new MulOvfUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new MulOvfUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new MulOvfUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new MulOvfSingle()); - case TypeCode.Double: return s_double ?? (s_double = new MulOvfDouble()); + case TypeCode.Int16: return s_int16 ??= new MulOvfInt16(); + case TypeCode.Int32: return s_int32 ??= new MulOvfInt32(); + case TypeCode.Int64: return s_int64 ??= new MulOvfInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new MulOvfUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new MulOvfUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new MulOvfUInt64(); + case TypeCode.Single: return s_single ??= new MulOvfSingle(); + case TypeCode.Double: return s_double ??= new MulOvfDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/NotEqualInstruction.cs b/src/System.Management.Automation/engine/interpreter/NotEqualInstruction.cs index 42fc6639a82..79df1b9a84b 100644 --- a/src/System.Management.Automation/engine/interpreter/NotEqualInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/NotEqualInstruction.cs @@ -154,25 +154,25 @@ public static Instruction Create(Type type) var typeToUse = type.IsEnum ? Enum.GetUnderlyingType(type) : type; switch (typeToUse.GetTypeCode()) { - case TypeCode.Boolean: return s_boolean ?? (s_boolean = new NotEqualBoolean()); - case TypeCode.SByte: return s_SByte ?? (s_SByte = new NotEqualSByte()); - case TypeCode.Byte: return s_byte ?? (s_byte = new NotEqualByte()); - case TypeCode.Char: return s_char ?? (s_char = new NotEqualChar()); - case TypeCode.Int16: return s_int16 ?? (s_int16 = new NotEqualInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new NotEqualInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new NotEqualInt64()); + case TypeCode.Boolean: return s_boolean ??= new NotEqualBoolean(); + case TypeCode.SByte: return s_SByte ??= new NotEqualSByte(); + case TypeCode.Byte: return s_byte ??= new NotEqualByte(); + case TypeCode.Char: return s_char ??= new NotEqualChar(); + case TypeCode.Int16: return s_int16 ??= new NotEqualInt16(); + case TypeCode.Int32: return s_int32 ??= new NotEqualInt32(); + case TypeCode.Int64: return s_int64 ??= new NotEqualInt64(); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NotEqualInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NotEqualInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new NotEqualInt64()); + case TypeCode.UInt16: return s_UInt16 ??= new NotEqualInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new NotEqualInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new NotEqualInt64(); - case TypeCode.Single: return s_single ?? (s_single = new NotEqualSingle()); - case TypeCode.Double: return s_double ?? (s_double = new NotEqualDouble()); + case TypeCode.Single: return s_single ??= new NotEqualSingle(); + case TypeCode.Double: return s_double ??= new NotEqualDouble(); case TypeCode.Object: if (!type.IsValueType) { - return s_reference ?? (s_reference = new NotEqualReference()); + return s_reference ??= new NotEqualReference(); } // TODO: Nullable throw new NotImplementedException(); @@ -188,4 +188,3 @@ public override string ToString() } } } - diff --git a/src/System.Management.Automation/engine/interpreter/PowerShellInstructions.cs b/src/System.Management.Automation/engine/interpreter/PowerShellInstructions.cs index 926f558a72b..5592af6f526 100644 --- a/src/System.Management.Automation/engine/interpreter/PowerShellInstructions.cs +++ b/src/System.Management.Automation/engine/interpreter/PowerShellInstructions.cs @@ -15,7 +15,7 @@ namespace System.Management.Automation.Interpreter { - internal class UpdatePositionInstruction : Instruction + internal sealed class UpdatePositionInstruction : Instruction { private readonly int _sequencePoint; private readonly bool _checkBreakpoints; diff --git a/src/System.Management.Automation/engine/interpreter/SubInstruction.cs b/src/System.Management.Automation/engine/interpreter/SubInstruction.cs index c0874d47d89..486cd7f8933 100644 --- a/src/System.Management.Automation/engine/interpreter/SubInstruction.cs +++ b/src/System.Management.Automation/engine/interpreter/SubInstruction.cs @@ -130,14 +130,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new SubInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new SubInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new SubInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new SubUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new SubUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new SubUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new SubSingle()); - case TypeCode.Double: return s_double ?? (s_double = new SubDouble()); + case TypeCode.Int16: return s_int16 ??= new SubInt16(); + case TypeCode.Int32: return s_int32 ??= new SubInt32(); + case TypeCode.Int64: return s_int64 ??= new SubInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new SubUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new SubUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new SubUInt64(); + case TypeCode.Single: return s_single ??= new SubSingle(); + case TypeCode.Double: return s_double ??= new SubDouble(); default: throw Assert.Unreachable; @@ -263,14 +263,14 @@ public static Instruction Create(Type type) Debug.Assert(!type.IsEnum); switch (type.GetTypeCode()) { - case TypeCode.Int16: return s_int16 ?? (s_int16 = new SubOvfInt16()); - case TypeCode.Int32: return s_int32 ?? (s_int32 = new SubOvfInt32()); - case TypeCode.Int64: return s_int64 ?? (s_int64 = new SubOvfInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new SubOvfUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new SubOvfUInt32()); - case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new SubOvfUInt64()); - case TypeCode.Single: return s_single ?? (s_single = new SubOvfSingle()); - case TypeCode.Double: return s_double ?? (s_double = new SubOvfDouble()); + case TypeCode.Int16: return s_int16 ??= new SubOvfInt16(); + case TypeCode.Int32: return s_int32 ??= new SubOvfInt32(); + case TypeCode.Int64: return s_int64 ??= new SubOvfInt64(); + case TypeCode.UInt16: return s_UInt16 ??= new SubOvfUInt16(); + case TypeCode.UInt32: return s_UInt32 ??= new SubOvfUInt32(); + case TypeCode.UInt64: return s_UInt64 ??= new SubOvfUInt64(); + case TypeCode.Single: return s_single ??= new SubOvfSingle(); + case TypeCode.Double: return s_double ??= new SubOvfDouble(); default: throw Assert.Unreachable; diff --git a/src/System.Management.Automation/engine/interpreter/Utilities.cs b/src/System.Management.Automation/engine/interpreter/Utilities.cs index 810dea30d1a..b5b69f7415b 100644 --- a/src/System.Management.Automation/engine/interpreter/Utilities.cs +++ b/src/System.Management.Automation/engine/interpreter/Utilities.cs @@ -147,7 +147,7 @@ internal static Type MakeDelegate(Type[] types) // Can only used predefined delegates if we have no byref types and // the arity is small enough to fit in Func<...> or Action<...> - if (types.Length > MaximumArity || types.Any(t => t.IsByRef)) + if (types.Length > MaximumArity || types.Any(static t => t.IsByRef)) { throw Assert.Unreachable; // return MakeCustomDelegate(types); @@ -224,7 +224,7 @@ internal static Type MakeDelegate(Type[] types) } } - internal class ScriptingRuntimeHelpers + internal static class ScriptingRuntimeHelpers { internal static object Int32ToObject(int i) { @@ -668,7 +668,7 @@ public TValue this[TKey key] } } - private struct KeyInfo + private readonly struct KeyInfo { internal readonly TValue Value; internal readonly LinkedListNode List; @@ -779,7 +779,7 @@ public StorageInfo GetStorageInfo() private StorageInfo GetStorageInfo(StorageInfo[] curStorage) { - int threadId = Thread.CurrentThread.ManagedThreadId; + int threadId = Environment.CurrentManagedThreadId; // fast path if we already have a value in the array if (curStorage != null && curStorage.Length > threadId) @@ -829,7 +829,7 @@ private StorageInfo CreateStorageInfo() StorageInfo[] curStorage = s_updating; try { - int threadId = Thread.CurrentThread.ManagedThreadId; + int threadId = Environment.CurrentManagedThreadId; StorageInfo newInfo = new StorageInfo(Thread.CurrentThread); // set to updating while potentially resizing/mutating, then we'll @@ -1084,14 +1084,14 @@ internal static bool TrueForAll(this IEnumerable collection, Predicate return true; } - internal static U[] Map(this ICollection collection, Func select) + internal static TResult[] Map(this ICollection source, Func selector) { - int count = collection.Count; - U[] result = new U[count]; + int count = source.Count; + TResult[] result = new TResult[count]; count = 0; - foreach (T t in collection) + foreach (TSource t in source) { - result[count++] = select(t); + result[count++] = selector(t); } return result; diff --git a/src/System.Management.Automation/engine/lang/interface/PSToken.cs b/src/System.Management.Automation/engine/lang/interface/PSToken.cs index 52626cf5067..048de2facac 100644 --- a/src/System.Management.Automation/engine/lang/interface/PSToken.cs +++ b/src/System.Management.Automation/engine/lang/interface/PSToken.cs @@ -69,7 +69,7 @@ public string Content } } - private string _content; + private readonly string _content; #region Token Type @@ -300,7 +300,9 @@ public static PSTokenType GetPSTokenType(Token token) /* Type */ PSTokenType.Keyword, /* Assembly */ PSTokenType.Keyword, /* Command */ PSTokenType.Keyword, - /* Def */ PSTokenType.Keyword, + /* Hidden */ PSTokenType.Keyword, + /* Base */ PSTokenType.Keyword, + /* Default */ PSTokenType.Keyword, #endregion Flags for keywords diff --git a/src/System.Management.Automation/engine/lang/parserutils.cs b/src/System.Management.Automation/engine/lang/parserutils.cs index 99e0f0f6cbf..865f3530d71 100644 --- a/src/System.Management.Automation/engine/lang/parserutils.cs +++ b/src/System.Management.Automation/engine/lang/parserutils.cs @@ -378,8 +378,8 @@ internal static object ImplicitOp(object lval, object rval, string op, IScriptEx lval = PSObject.Base(lval); rval = PSObject.Base(rval); - Type lvalType = lval != null ? lval.GetType() : null; - Type rvalType = rval != null ? rval.GetType() : null; + Type lvalType = lval?.GetType(); + Type rvalType = rval?.GetType(); Type opType; if (lvalType == null || (lvalType.IsPrimitive)) { @@ -965,20 +965,13 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e } } + var replacer = ReplaceOperatorImpl.Create(context, rr, substitute); IEnumerator list = LanguagePrimitives.GetEnumerator(lval); if (list == null) { - string lvalString; - if (ExperimentalFeature.IsEnabled("PSCultureInvariantReplaceOperator")) - { - lvalString = PSObject.ToStringParser(context, lval) ?? string.Empty; - } - else - { - lvalString = lval?.ToString() ?? string.Empty; - } + string lvalString = PSObject.ToStringParser(context, lval) ?? string.Empty; - return ReplaceOperatorImpl(context, lvalString, rr, substitute); + return replacer.Replace(lvalString); } else { @@ -986,51 +979,84 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e while (ParserOps.MoveNext(context, errorPosition, list)) { string lvalString = PSObject.ToStringParser(context, ParserOps.Current(errorPosition, list)); - resultList.Add(ReplaceOperatorImpl(context, lvalString, rr, substitute)); + resultList.Add(replacer.Replace(lvalString)); } return resultList.ToArray(); } } - /// - /// ReplaceOperator implementation. - /// Abstracts away conversion of the optional substitute parameter to either a string or a MatchEvaluator delegate - /// and finally returns the result of the final Regex.Replace operation. - /// - /// The execution context in which to evaluate the expression. - /// The input string. - /// A Regex instance. - /// The substitute value. - /// The result of the regex.Replace operation. - private static object ReplaceOperatorImpl(ExecutionContext context, string input, Regex regex, object substitute) + private struct ReplaceOperatorImpl { - switch (substitute) + public static ReplaceOperatorImpl Create(ExecutionContext context, Regex regex, object substitute) { - case string replacementString: - return regex.Replace(input, replacementString); + return new ReplaceOperatorImpl(context, regex, substitute); + } - case ScriptBlock sb: - MatchEvaluator me = match => - { - var result = sb.DoInvokeReturnAsIs( - useLocalScope: false, /* Use current scope to be consistent with 'ForEach/Where-Object {}' and 'collection.ForEach{}/Where{}' */ - errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToCurrentErrorPipe, - dollarUnder: match, - input: AutomationNull.Value, - scriptThis: AutomationNull.Value, - args: Array.Empty()); + private readonly Regex _regex; + private readonly string _cachedReplacementString; + private readonly MatchEvaluator _cachedMatchEvaluator; + + private ReplaceOperatorImpl( + ExecutionContext context, + Regex regex, + object substitute) + { + _regex = regex; + _cachedReplacementString = null; + _cachedMatchEvaluator = null; + + switch (substitute) + { + case string replacement: + _cachedReplacementString = replacement; + break; - return PSObject.ToStringParser(context, result); - }; - return regex.Replace(input, me); + case ScriptBlock sb: + _cachedMatchEvaluator = GetMatchEvaluator(context, sb); + break; - case object val when LanguagePrimitives.TryConvertTo(val, out MatchEvaluator matchEvaluator): - return regex.Replace(input, matchEvaluator); + case object val when LanguagePrimitives.TryConvertTo(val, out _cachedMatchEvaluator): + break; - default: - string replacement = PSObject.ToStringParser(context, substitute); - return regex.Replace(input, replacement); + default: + _cachedReplacementString = PSObject.ToStringParser(context, substitute); + break; + } + } + + // Local helper function to avoid creating an instance of the generated delegate helper class + // every time 'ReplaceOperatorImpl' is invoked. + private static MatchEvaluator GetMatchEvaluator(ExecutionContext context, ScriptBlock sb) + { + return match => + { + var result = sb.DoInvokeReturnAsIs( + useLocalScope: false, /* Use current scope to be consistent with 'ForEach/Where-Object {}' and 'collection.ForEach{}/Where{}' */ + errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToCurrentErrorPipe, + dollarUnder: match, + input: AutomationNull.Value, + scriptThis: AutomationNull.Value, + args: Array.Empty()); + + return PSObject.ToStringParser(context, result); + }; + } + + /// + /// ReplaceOperator implementation. + /// Abstracts away conversion of the optional substitute parameter to either a string or a MatchEvaluator delegate + /// and finally returns the result of the final Regex.Replace operation. + /// + public object Replace(string input) + { + if (_cachedReplacementString is not null) + { + return _regex.Replace(input, _cachedReplacementString); + } + + Dbg.Assert(_cachedMatchEvaluator is not null, "_cachedMatchEvaluator should be not null when code reach here."); + return _regex.Replace(input, _cachedMatchEvaluator); } } @@ -1466,8 +1492,7 @@ internal static string GetTypeFullName(object obj) return string.Empty; } - PSObject mshObj = obj as PSObject; - if (mshObj == null) + if (!(obj is PSObject mshObj)) { return obj.GetType().FullName; } @@ -1571,9 +1596,7 @@ internal static object CallMethod( // not really a method call. if (valueToSet != AutomationNull.Value) { - PSParameterizedProperty propertyToSet = targetMethod as PSParameterizedProperty; - - if (propertyToSet == null) + if (!(targetMethod is PSParameterizedProperty propertyToSet)) { throw InterpreterError.NewInterpreterException(methodName, typeof(RuntimeException), errorPosition, "ParameterizedPropertyAssignmentFailed", ParserStrings.ParameterizedPropertyAssignmentFailed, GetTypeFullName(target), methodName); @@ -1635,14 +1658,14 @@ internal static object CallMethod( /// internal class RangeEnumerator : IEnumerator { - private int _lowerBound; + private readonly int _lowerBound; internal int LowerBound { get { return _lowerBound; } } - private int _upperBound; + private readonly int _upperBound; internal int UpperBound { @@ -1666,7 +1689,7 @@ internal int CurrentValue get { return _current; } } - private int _increment = 1; + private readonly int _increment = 1; private bool _firstElement = true; @@ -1707,7 +1730,7 @@ public bool MoveNext() /// internal class CharRangeEnumerator : IEnumerator { - private int _increment = 1; + private readonly int _increment = 1; private bool _firstElement = true; @@ -1812,7 +1835,7 @@ internal static RuntimeException NewInterpreterExceptionWithInnerException(objec try { string message; - if (args == null || 0 == args.Length) + if (args == null || args.Length == 0) { // Don't format in case the string contains literal curly braces message = resourceString; @@ -1973,7 +1996,7 @@ internal static void Trace(ExecutionContext context, int level, string messageId if (context.PSDebugTraceLevel > level) { string message; - if (args == null || 0 == args.Length) + if (args == null || args.Length == 0) { // Don't format in case the string contains literal curly braces message = resourceString; diff --git a/src/System.Management.Automation/engine/lang/scriptblock.cs b/src/System.Management.Automation/engine/lang/scriptblock.cs index 5930273ee60..0c6c1d5dff1 100644 --- a/src/System.Management.Automation/engine/lang/scriptblock.cs +++ b/src/System.Management.Automation/engine/lang/scriptblock.cs @@ -596,7 +596,7 @@ internal void InvokeAsMemberFunction(object instance, object[] args) /// Get the PSModuleInfo object for the module that defined this /// scriptblock. /// - public PSModuleInfo Module { get => SessionStateInternal != null ? SessionStateInternal.Module : null; } + public PSModuleInfo Module { get => SessionStateInternal?.Module; } /// /// Return the PSToken object for this function definition... @@ -709,7 +709,7 @@ internal SessionState SessionState } } - return SessionStateInternal != null ? SessionStateInternal.PublicSessionState : null; + return SessionStateInternal?.PublicSessionState; } set @@ -778,7 +778,7 @@ internal Delegate CreateDelegate(Type delegateType) CachedReflectionInfo.ScriptBlock_InvokeAsDelegateHelper, dollarUnderExpr, dollarThisExpr, - Expression.NewArrayInit(typeof(object), parameterExprs.Select(p => p.Cast(typeof(object))))); + Expression.NewArrayInit(typeof(object), parameterExprs.Select(static p => p.Cast(typeof(object))))); if (returnsSomething) { call = DynamicExpression.Dynamic( @@ -1113,21 +1113,21 @@ internal SteppablePipeline(ExecutionContext context, PipelineProcessor pipeline) _context = context; } - private PipelineProcessor _pipeline; - private ExecutionContext _context; + private readonly PipelineProcessor _pipeline; + private readonly ExecutionContext _context; private bool _expectInput; /// /// Begin execution of a steppable pipeline. This overload doesn't reroute output and error pipes. /// - /// true if you plan to write input into this pipe; false otherwise. + /// if you plan to write input into this pipe; otherwise. public void Begin(bool expectInput) => Begin(expectInput, commandRuntime: (ICommandRuntime)null); /// /// Begin execution of a steppable pipeline, using the command running currently in the specified context to figure /// out how to route the output and errors. /// - /// true if you plan to write input into this pipe; false otherwise. + /// if you plan to write input into this pipe; otherwise. /// Context used to figure out how to route the output and errors. public void Begin(bool expectInput, EngineIntrinsics contextToRedirectTo) { @@ -1138,7 +1138,7 @@ public void Begin(bool expectInput, EngineIntrinsics contextToRedirectTo) ExecutionContext executionContext = contextToRedirectTo.SessionState.Internal.ExecutionContext; CommandProcessorBase commandProcessor = executionContext.CurrentCommandProcessor; - ICommandRuntime crt = commandProcessor == null ? null : commandProcessor.CommandRuntime; + ICommandRuntime crt = commandProcessor?.CommandRuntime; Begin(expectInput, crt); } @@ -1313,14 +1313,6 @@ private void Dispose(bool disposing) _disposed = true; } - /// - /// Finalizer for class SteppablePipeline. - /// - ~SteppablePipeline() - { - Dispose(false); - } - #endregion IDispose } @@ -1447,13 +1439,21 @@ internal ScriptBlockInvocationEventArgs( } internal ScriptBlock ScriptBlock { get; set; } + internal bool UseLocalScope { get; set; } + internal ScriptBlock.ErrorHandlingBehavior ErrorHandlingBehavior { get; set; } + internal object DollarUnder { get; set; } + internal object Input { get; set; } + internal object ScriptThis { get; set; } + internal Pipe OutputPipe { get; set; } + internal InvocationInfo InvocationInfo { get; set; } + internal object[] Args { get; set; } /// diff --git a/src/System.Management.Automation/engine/parser/AstVisitor.cs b/src/System.Management.Automation/engine/parser/AstVisitor.cs index d87bb247a43..03b234cf41f 100644 --- a/src/System.Management.Automation/engine/parser/AstVisitor.cs +++ b/src/System.Management.Automation/engine/parser/AstVisitor.cs @@ -10,226 +10,230 @@ namespace System.Management.Automation.Language { /// /// +#nullable enable public interface ICustomAstVisitor { /// - object DefaultVisit(Ast ast) => null; + object? DefaultVisit(Ast ast) => null; /// - object VisitErrorStatement(ErrorStatementAst errorStatementAst) => DefaultVisit(errorStatementAst); + object? VisitErrorStatement(ErrorStatementAst errorStatementAst) => DefaultVisit(errorStatementAst); /// - object VisitErrorExpression(ErrorExpressionAst errorExpressionAst) => DefaultVisit(errorExpressionAst); + object? VisitErrorExpression(ErrorExpressionAst errorExpressionAst) => DefaultVisit(errorExpressionAst); #region Script Blocks /// - object VisitScriptBlock(ScriptBlockAst scriptBlockAst) => DefaultVisit(scriptBlockAst); + object? VisitScriptBlock(ScriptBlockAst scriptBlockAst) => DefaultVisit(scriptBlockAst); /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "param")] - object VisitParamBlock(ParamBlockAst paramBlockAst) => DefaultVisit(paramBlockAst); + object? VisitParamBlock(ParamBlockAst paramBlockAst) => DefaultVisit(paramBlockAst); /// - object VisitNamedBlock(NamedBlockAst namedBlockAst) => DefaultVisit(namedBlockAst); + object? VisitNamedBlock(NamedBlockAst namedBlockAst) => DefaultVisit(namedBlockAst); /// - object VisitTypeConstraint(TypeConstraintAst typeConstraintAst) => DefaultVisit(typeConstraintAst); + object? VisitTypeConstraint(TypeConstraintAst typeConstraintAst) => DefaultVisit(typeConstraintAst); /// - object VisitAttribute(AttributeAst attributeAst) => DefaultVisit(attributeAst); + object? VisitAttribute(AttributeAst attributeAst) => DefaultVisit(attributeAst); /// - object VisitNamedAttributeArgument(NamedAttributeArgumentAst namedAttributeArgumentAst) => DefaultVisit(namedAttributeArgumentAst); + object? VisitNamedAttributeArgument(NamedAttributeArgumentAst namedAttributeArgumentAst) => DefaultVisit(namedAttributeArgumentAst); /// - object VisitParameter(ParameterAst parameterAst) => DefaultVisit(parameterAst); + object? VisitParameter(ParameterAst parameterAst) => DefaultVisit(parameterAst); #endregion Script Blocks #region Statements /// - object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => DefaultVisit(functionDefinitionAst); + object? VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => DefaultVisit(functionDefinitionAst); /// - object VisitStatementBlock(StatementBlockAst statementBlockAst) => DefaultVisit(statementBlockAst); + object? VisitStatementBlock(StatementBlockAst statementBlockAst) => DefaultVisit(statementBlockAst); /// - object VisitIfStatement(IfStatementAst ifStmtAst) => DefaultVisit(ifStmtAst); + object? VisitIfStatement(IfStatementAst ifStmtAst) => DefaultVisit(ifStmtAst); /// - object VisitTrap(TrapStatementAst trapStatementAst) => DefaultVisit(trapStatementAst); + object? VisitTrap(TrapStatementAst trapStatementAst) => DefaultVisit(trapStatementAst); /// - object VisitSwitchStatement(SwitchStatementAst switchStatementAst) => DefaultVisit(switchStatementAst); + object? VisitSwitchStatement(SwitchStatementAst switchStatementAst) => DefaultVisit(switchStatementAst); /// - object VisitDataStatement(DataStatementAst dataStatementAst) => DefaultVisit(dataStatementAst); + object? VisitDataStatement(DataStatementAst dataStatementAst) => DefaultVisit(dataStatementAst); /// - object VisitForEachStatement(ForEachStatementAst forEachStatementAst) => DefaultVisit(forEachStatementAst); + object? VisitForEachStatement(ForEachStatementAst forEachStatementAst) => DefaultVisit(forEachStatementAst); /// - object VisitDoWhileStatement(DoWhileStatementAst doWhileStatementAst) => DefaultVisit(doWhileStatementAst); + object? VisitDoWhileStatement(DoWhileStatementAst doWhileStatementAst) => DefaultVisit(doWhileStatementAst); /// - object VisitForStatement(ForStatementAst forStatementAst) => DefaultVisit(forStatementAst); + object? VisitForStatement(ForStatementAst forStatementAst) => DefaultVisit(forStatementAst); /// - object VisitWhileStatement(WhileStatementAst whileStatementAst) => DefaultVisit(whileStatementAst); + object? VisitWhileStatement(WhileStatementAst whileStatementAst) => DefaultVisit(whileStatementAst); /// - object VisitCatchClause(CatchClauseAst catchClauseAst) => DefaultVisit(catchClauseAst); + object? VisitCatchClause(CatchClauseAst catchClauseAst) => DefaultVisit(catchClauseAst); /// - object VisitTryStatement(TryStatementAst tryStatementAst) => DefaultVisit(tryStatementAst); + object? VisitTryStatement(TryStatementAst tryStatementAst) => DefaultVisit(tryStatementAst); /// - object VisitBreakStatement(BreakStatementAst breakStatementAst) => DefaultVisit(breakStatementAst); + object? VisitBreakStatement(BreakStatementAst breakStatementAst) => DefaultVisit(breakStatementAst); /// - object VisitContinueStatement(ContinueStatementAst continueStatementAst) => DefaultVisit(continueStatementAst); + object? VisitContinueStatement(ContinueStatementAst continueStatementAst) => DefaultVisit(continueStatementAst); /// - object VisitReturnStatement(ReturnStatementAst returnStatementAst) => DefaultVisit(returnStatementAst); + object? VisitReturnStatement(ReturnStatementAst returnStatementAst) => DefaultVisit(returnStatementAst); /// - object VisitExitStatement(ExitStatementAst exitStatementAst) => DefaultVisit(exitStatementAst); + object? VisitExitStatement(ExitStatementAst exitStatementAst) => DefaultVisit(exitStatementAst); /// - object VisitThrowStatement(ThrowStatementAst throwStatementAst) => DefaultVisit(throwStatementAst); + object? VisitThrowStatement(ThrowStatementAst throwStatementAst) => DefaultVisit(throwStatementAst); /// - object VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst) => DefaultVisit(doUntilStatementAst); + object? VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst) => DefaultVisit(doUntilStatementAst); /// - object VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) => DefaultVisit(assignmentStatementAst); + object? VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) => DefaultVisit(assignmentStatementAst); #endregion Statements #region Pipelines /// - object VisitPipeline(PipelineAst pipelineAst) => DefaultVisit(pipelineAst); + object? VisitPipeline(PipelineAst pipelineAst) => DefaultVisit(pipelineAst); /// - object VisitCommand(CommandAst commandAst) => DefaultVisit(commandAst); + object? VisitCommand(CommandAst commandAst) => DefaultVisit(commandAst); /// - object VisitCommandExpression(CommandExpressionAst commandExpressionAst) => DefaultVisit(commandExpressionAst); + object? VisitCommandExpression(CommandExpressionAst commandExpressionAst) => DefaultVisit(commandExpressionAst); /// - object VisitCommandParameter(CommandParameterAst commandParameterAst) => DefaultVisit(commandParameterAst); + object? VisitCommandParameter(CommandParameterAst commandParameterAst) => DefaultVisit(commandParameterAst); /// - object VisitFileRedirection(FileRedirectionAst fileRedirectionAst) => DefaultVisit(fileRedirectionAst); + object? VisitFileRedirection(FileRedirectionAst fileRedirectionAst) => DefaultVisit(fileRedirectionAst); /// - object VisitMergingRedirection(MergingRedirectionAst mergingRedirectionAst) => DefaultVisit(mergingRedirectionAst); + object? VisitMergingRedirection(MergingRedirectionAst mergingRedirectionAst) => DefaultVisit(mergingRedirectionAst); #endregion Pipelines #region Expressions /// - object VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst) => DefaultVisit(binaryExpressionAst); + object? VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst) => DefaultVisit(binaryExpressionAst); /// - object VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst) => DefaultVisit(unaryExpressionAst); + object? VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst) => DefaultVisit(unaryExpressionAst); /// - object VisitConvertExpression(ConvertExpressionAst convertExpressionAst) => DefaultVisit(convertExpressionAst); + object? VisitConvertExpression(ConvertExpressionAst convertExpressionAst) => DefaultVisit(convertExpressionAst); /// - object VisitConstantExpression(ConstantExpressionAst constantExpressionAst) => DefaultVisit(constantExpressionAst); + object? VisitConstantExpression(ConstantExpressionAst constantExpressionAst) => DefaultVisit(constantExpressionAst); /// - object VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst) => DefaultVisit(stringConstantExpressionAst); + object? VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst) => DefaultVisit(stringConstantExpressionAst); /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "SubExpression")] [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "subExpression")] - object VisitSubExpression(SubExpressionAst subExpressionAst) => DefaultVisit(subExpressionAst); + object? VisitSubExpression(SubExpressionAst subExpressionAst) => DefaultVisit(subExpressionAst); /// - object VisitUsingExpression(UsingExpressionAst usingExpressionAst) => DefaultVisit(usingExpressionAst); + object? VisitUsingExpression(UsingExpressionAst usingExpressionAst) => DefaultVisit(usingExpressionAst); /// - object VisitVariableExpression(VariableExpressionAst variableExpressionAst) => DefaultVisit(variableExpressionAst); + object? VisitVariableExpression(VariableExpressionAst variableExpressionAst) => DefaultVisit(variableExpressionAst); /// - object VisitTypeExpression(TypeExpressionAst typeExpressionAst) => DefaultVisit(typeExpressionAst); + object? VisitTypeExpression(TypeExpressionAst typeExpressionAst) => DefaultVisit(typeExpressionAst); /// - object VisitMemberExpression(MemberExpressionAst memberExpressionAst) => DefaultVisit(memberExpressionAst); + object? VisitMemberExpression(MemberExpressionAst memberExpressionAst) => DefaultVisit(memberExpressionAst); /// - object VisitInvokeMemberExpression(InvokeMemberExpressionAst invokeMemberExpressionAst) => DefaultVisit(invokeMemberExpressionAst); + object? VisitInvokeMemberExpression(InvokeMemberExpressionAst invokeMemberExpressionAst) => DefaultVisit(invokeMemberExpressionAst); /// - object VisitArrayExpression(ArrayExpressionAst arrayExpressionAst) => DefaultVisit(arrayExpressionAst); + object? VisitArrayExpression(ArrayExpressionAst arrayExpressionAst) => DefaultVisit(arrayExpressionAst); /// - object VisitArrayLiteral(ArrayLiteralAst arrayLiteralAst) => DefaultVisit(arrayLiteralAst); + object? VisitArrayLiteral(ArrayLiteralAst arrayLiteralAst) => DefaultVisit(arrayLiteralAst); /// - object VisitHashtable(HashtableAst hashtableAst) => DefaultVisit(hashtableAst); + object? VisitHashtable(HashtableAst hashtableAst) => DefaultVisit(hashtableAst); /// - object VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst) => DefaultVisit(scriptBlockExpressionAst); + object? VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst) => DefaultVisit(scriptBlockExpressionAst); /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Paren")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "paren")] - object VisitParenExpression(ParenExpressionAst parenExpressionAst) => DefaultVisit(parenExpressionAst); + object? VisitParenExpression(ParenExpressionAst parenExpressionAst) => DefaultVisit(parenExpressionAst); /// - object VisitExpandableStringExpression(ExpandableStringExpressionAst expandableStringExpressionAst) => DefaultVisit(expandableStringExpressionAst); + object? VisitExpandableStringExpression(ExpandableStringExpressionAst expandableStringExpressionAst) => DefaultVisit(expandableStringExpressionAst); /// - object VisitIndexExpression(IndexExpressionAst indexExpressionAst) => DefaultVisit(indexExpressionAst); + object? VisitIndexExpression(IndexExpressionAst indexExpressionAst) => DefaultVisit(indexExpressionAst); /// - object VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst) => DefaultVisit(attributedExpressionAst); + object? VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst) => DefaultVisit(attributedExpressionAst); /// - object VisitBlockStatement(BlockStatementAst blockStatementAst) => DefaultVisit(blockStatementAst); + object? VisitBlockStatement(BlockStatementAst blockStatementAst) => DefaultVisit(blockStatementAst); #endregion Expressions } +#nullable restore /// +#nullable enable public interface ICustomAstVisitor2 : ICustomAstVisitor { /// - object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => DefaultVisit(typeDefinitionAst); + object? VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => DefaultVisit(typeDefinitionAst); /// - object VisitPropertyMember(PropertyMemberAst propertyMemberAst) => DefaultVisit(propertyMemberAst); + object? VisitPropertyMember(PropertyMemberAst propertyMemberAst) => DefaultVisit(propertyMemberAst); /// - object VisitFunctionMember(FunctionMemberAst functionMemberAst) => DefaultVisit(functionMemberAst); + object? VisitFunctionMember(FunctionMemberAst functionMemberAst) => DefaultVisit(functionMemberAst); /// - object VisitBaseCtorInvokeMemberExpression(BaseCtorInvokeMemberExpressionAst baseCtorInvokeMemberExpressionAst) => DefaultVisit(baseCtorInvokeMemberExpressionAst); + object? VisitBaseCtorInvokeMemberExpression(BaseCtorInvokeMemberExpressionAst baseCtorInvokeMemberExpressionAst) => DefaultVisit(baseCtorInvokeMemberExpressionAst); /// - object VisitUsingStatement(UsingStatementAst usingStatement) => DefaultVisit(usingStatement); + object? VisitUsingStatement(UsingStatementAst usingStatement) => DefaultVisit(usingStatement); /// - object VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst) => DefaultVisit(configurationDefinitionAst); + object? VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst) => DefaultVisit(configurationDefinitionAst); /// - object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) => DefaultVisit(dynamicKeywordAst); + object? VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) => DefaultVisit(dynamicKeywordAst); /// - object VisitTernaryExpression(TernaryExpressionAst ternaryExpressionAst) => DefaultVisit(ternaryExpressionAst); + object? VisitTernaryExpression(TernaryExpressionAst ternaryExpressionAst) => DefaultVisit(ternaryExpressionAst); /// - object VisitPipelineChain(PipelineChainAst statementChainAst) => DefaultVisit(statementChainAst); + object? VisitPipelineChain(PipelineChainAst statementChainAst) => DefaultVisit(statementChainAst); } +#nullable restore #if DEBUG internal class CheckAllParentsSet : AstVisitor2 @@ -386,7 +390,7 @@ public override AstVisitAction VisitTypeConstraint(TypeConstraintAst ast) Type type = ast.TypeName.GetReflectionType(); if (type != null) { - Diagnostics.Assert(!(type is TypeBuilder), "ReflectionType can never be TypeBuilder"); + Diagnostics.Assert(type is not TypeBuilder, "ReflectionType can never be TypeBuilder"); } return AstVisitAction.Continue; @@ -425,7 +429,7 @@ internal static bool Contains(Ast ast, Func predicate, bool searchNes var searcher = new AstSearcher(predicate, stopOnFirst: true, searchNestedScriptBlocks: searchNestedScriptBlocks); ast.InternalVisit(searcher); - return searcher.Results.Any(); + return searcher.Results.Count > 0; } internal static bool IsUsingDollarInput(Ast ast) diff --git a/src/System.Management.Automation/engine/parser/Compiler.cs b/src/System.Management.Automation/engine/parser/Compiler.cs index b08d588fa0e..bcddbee0b24 100644 --- a/src/System.Management.Automation/engine/parser/Compiler.cs +++ b/src/System.Management.Automation/engine/parser/Compiler.cs @@ -926,7 +926,10 @@ internal Type MemberFunctionReturnType return _memberFunctionReturnType; } - set { _memberFunctionReturnType = value; } + set + { + _memberFunctionReturnType = value; + } } private Type _memberFunctionReturnType; @@ -1166,7 +1169,7 @@ internal static Type GetTypeConstraintForMethodResolution(ExpressionAst expr) expr = ((AttributedExpressionAst)expr).Child; } - return firstConvert == null ? null : firstConvert.Type.TypeName.GetReflectionType(); + return firstConvert?.Type.TypeName.GetReflectionType(); } internal static PSMethodInvocationConstraints CombineTypeConstraintForMethodResolution(Type targetType, Type argType) @@ -1254,7 +1257,7 @@ internal static RuntimeDefinedParameterDictionary GetParameterMetaData(ReadOnlyC for (int index = 0; index < runtimeDefinedParamList.Count; index++) { var rdp = runtimeDefinedParamList[index]; - var paramAttribute = (ParameterAttribute)rdp.Attributes.First(attr => attr is ParameterAttribute); + var paramAttribute = (ParameterAttribute)rdp.Attributes.First(static attr => attr is ParameterAttribute); if (rdp.ParameterType != typeof(SwitchParameter)) { paramAttribute.Position = pos++; @@ -1716,7 +1719,7 @@ internal static Attribute GetAttribute(AttributeAst attributeAst) } var positionalArgCount = attributeAst.PositionalArguments.Count; - var argumentNames = attributeAst.NamedArguments.Select(name => name.ArgumentName).ToArray(); + var argumentNames = attributeAst.NamedArguments.Select(static name => name.ArgumentName).ToArray(); var totalArgCount = positionalArgCount + argumentNames.Length; var callInfo = new CallInfo(totalArgCount, argumentNames); @@ -2045,7 +2048,7 @@ internal void Compile(CompiledScriptBlockData scriptBlock, bool optimize) } } - private Action CompileTree(Expression> lambda, CompileInterpretChoice compileInterpretChoice) + private static Action CompileTree(Expression> lambda, CompileInterpretChoice compileInterpretChoice) { if (lambda == null) { @@ -2197,7 +2200,7 @@ private Func CompileSingleExpression(ExpressionAst expr return Expression.Lambda>(body, parameters).Compile(); } - private class LoopGotoTargets + private sealed class LoopGotoTargets { internal LoopGotoTargets(string label, LabelTarget breakLabel, LabelTarget continueLabel) { @@ -2265,11 +2268,9 @@ private Expression CaptureAstResults( exprs.Add(Expression.Assign(resultList, Expression.New(CachedReflectionInfo.ObjectList_ctor))); exprs.Add(Expression.Assign(s_getCurrentPipe, Expression.New(CachedReflectionInfo.Pipe_ctor, resultList))); exprs.Add(Expression.Call(oldPipe, CachedReflectionInfo.Pipe_SetVariableListForTemporaryPipe, s_getCurrentPipe)); - if (generateRedirectExprs != null) - { - // Add merge redirection expressions if delegate is provided. - generateRedirectExprs(exprs, finallyExprs); - } + + // Add merge redirection expressions if delegate is provided. + generateRedirectExprs?.Invoke(exprs, finallyExprs); exprs.Add(Compile(ast)); @@ -2385,7 +2386,7 @@ private Expression CaptureStatementResults( // We do this after evaluating the condition so that you could do something like: // if ((dir file1,file2 -ea SilentlyContinue) -and $?) { <# files both exist, otherwise $? would be $false if 0 or 1 files existed #> } // - if (context == CaptureAstContext.Condition && AstSearcher.FindFirst(stmt, ast => ast is CommandAst, searchNestedScriptBlocks: false) != null) + if (context == CaptureAstContext.Condition && AstSearcher.FindFirst(stmt, static ast => ast is CommandAst, searchNestedScriptBlocks: false) != null) { var tmp = NewTemp(result.Type, "condTmp"); result = Expression.Block( @@ -2425,7 +2426,7 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) var funcDefn = scriptBlockAst.Parent as FunctionDefinitionAst; var funcName = (funcDefn != null) ? funcDefn.Name : ""; - var rootForDefiningTypesAndUsings = scriptBlockAst.Find(ast => ast is TypeDefinitionAst || ast is UsingStatementAst, true) != null + var rootForDefiningTypesAndUsings = scriptBlockAst.Find(static ast => ast is TypeDefinitionAst || ast is UsingStatementAst, true) != null ? scriptBlockAst : null; @@ -2458,7 +2459,7 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { if (!scriptBlockAst.EndBlock.Unnamed) { - funcName = funcName + ""; + funcName += ""; } _endBlockLambda = CompileNamedBlock(scriptBlockAst.EndBlock, funcName, rootForDefiningTypesAndUsings); @@ -2565,7 +2566,7 @@ private Expression> CompileSingleLambda( // to the right place. We can avoid also avoid generating the catch if we know there aren't any traps. if (!_compilingTrap && ((traps != null && traps.Count > 0) - || statements.Any(stmt => AstSearcher.Contains(stmt, ast => ast is TrapStatementAst, searchNestedScriptBlocks: false)))) + || statements.Any(static stmt => AstSearcher.Contains(stmt, static ast => ast is TrapStatementAst, searchNestedScriptBlocks: false)))) { body = Expression.Block( new[] { s_executionContextParameter }, @@ -2591,7 +2592,7 @@ private Expression> CompileSingleLambda( return Expression.Lambda>(body, funcName, new[] { s_functionContext }); } - private void GenerateTypesAndUsings(ScriptBlockAst rootForDefiningTypesAndUsings, List exprs) + private static void GenerateTypesAndUsings(ScriptBlockAst rootForDefiningTypesAndUsings, List exprs) { // We don't postpone load assemblies, import modules from 'using' to the moment, when enclosed scriptblock is executed. // We do loading, when root of the script is compiled. @@ -2604,12 +2605,12 @@ private void GenerateTypesAndUsings(ScriptBlockAst rootForDefiningTypesAndUsings { if (rootForDefiningTypesAndUsings.UsingStatements.Count > 0) { - bool allUsingsAreNamespaces = rootForDefiningTypesAndUsings.UsingStatements.All(us => us.UsingStatementKind == UsingStatementKind.Namespace); + bool allUsingsAreNamespaces = rootForDefiningTypesAndUsings.UsingStatements.All(static us => us.UsingStatementKind == UsingStatementKind.Namespace); GenerateLoadUsings(rootForDefiningTypesAndUsings.UsingStatements, allUsingsAreNamespaces, exprs); } TypeDefinitionAst[] typeAsts = - rootForDefiningTypesAndUsings.FindAll(ast => ast is TypeDefinitionAst, true) + rootForDefiningTypesAndUsings.FindAll(static ast => ast is TypeDefinitionAst, true) .Cast() .ToArray(); @@ -2627,9 +2628,9 @@ private void GenerateTypesAndUsings(ScriptBlockAst rootForDefiningTypesAndUsings } Dictionary typesToAddToScope = - rootForDefiningTypesAndUsings.FindAll(ast => ast is TypeDefinitionAst, false) + rootForDefiningTypesAndUsings.FindAll(static ast => ast is TypeDefinitionAst, false) .Cast() - .ToDictionary(type => type.Name); + .ToDictionary(static type => type.Name); if (typesToAddToScope.Count > 0) { exprs.Add( @@ -3278,9 +3279,9 @@ private bool ShouldSetExecutionStatusToSuccess(StatementAst statementAst) /// True is the compiler should add the success setting, false otherwise. private bool ShouldSetExecutionStatusToSuccess(PipelineAst pipelineAst) { - ExpressionAst expressionAst = pipelineAst.GetPureExpression(); + ExpressionAst expressionAst = GetSingleExpressionFromPipeline(pipelineAst); - // If the pipeline is not a simple expression, it will set $? + // If the pipeline is not a single expression, it will set $? if (expressionAst == null) { return false; @@ -3290,6 +3291,22 @@ private bool ShouldSetExecutionStatusToSuccess(PipelineAst pipelineAst) return ShouldSetExecutionStatusToSuccess(expressionAst); } + /// + /// If the pipeline contains a single expression, the expression is returned, otherwise null is returned. + /// This method is different from in that it allows the single + /// expression to have redirections. + /// + private static ExpressionAst GetSingleExpressionFromPipeline(PipelineAst pipelineAst) + { + var pipelineElements = pipelineAst.PipelineElements; + if (pipelineElements.Count == 1 && pipelineElements[0] is CommandExpressionAst expr) + { + return expr.Expression; + } + + return null; + } + /// /// Determines whether an assignment statement must have an explicit setting /// for $? = $true after it by the compiler. @@ -3777,20 +3794,20 @@ public object VisitPipeline(PipelineAst pipelineAst) // one dimension because each command may have multiple redirections. Here we create the array for // each command in the pipe, either a compile time constant or created at runtime if necessary. Expression redirectionExpr; - if (commandRedirections.Any(r => r is Expression)) + if (commandRedirections.Any(static r => r is Expression)) { // If any command redirections are non-constant, commandRedirections will have a Linq.Expression in it, // in which case we must create the array at runtime redirectionExpr = Expression.NewArrayInit( typeof(CommandRedirection[]), - commandRedirections.Select(r => (r as Expression) ?? Expression.Constant(r, typeof(CommandRedirection[])))); + commandRedirections.Select(static r => (r as Expression) ?? Expression.Constant(r, typeof(CommandRedirection[])))); } - else if (commandRedirections.Any(r => r != null)) + else if (commandRedirections.Any(static r => r != null)) { // There were redirections, but all were compile time constant, so build the array at compile time. redirectionExpr = - Expression.Constant(commandRedirections.Map(r => r as CommandRedirection[])); + Expression.Constant(commandRedirections.Map(static r => r as CommandRedirection[])); } else { @@ -3838,15 +3855,15 @@ private object GetCommandRedirections(CommandBaseAst command) } // If there were any non-constant expressions, we must generate the array at runtime. - if (compiledRedirections.Any(r => r is Expression)) + if (compiledRedirections.Any(static r => r is Expression)) { return Expression.NewArrayInit( typeof(CommandRedirection), - compiledRedirections.Select(r => (r as Expression) ?? Expression.Constant(r))); + compiledRedirections.Select(static r => (r as Expression) ?? Expression.Constant(r))); } // Otherwise, we can use a compile time constant array. - return compiledRedirections.Map(r => (CommandRedirection)r); + return compiledRedirections.Map(static r => (CommandRedirection)r); } // A redirected expression requires extra work because there is no CommandProcessor or PipelineProcessor @@ -3881,7 +3898,7 @@ private Expression GetRedirectedExpression(CommandExpressionAst commandExpr, boo // For the output stream, we change funcContext.OutputPipe so all output goes to the file. // Currently output can only be redirected to a file stream. bool outputRedirected = - commandExpr.Redirections.Any(r => r is FileRedirectionAst && + commandExpr.Redirections.Any(static r => r is FileRedirectionAst && (r.FromStream == RedirectionStream.Output || r.FromStream == RedirectionStream.All)); ParameterExpression resultList = null; @@ -4276,7 +4293,7 @@ internal static Expression ThrowRuntimeError(string errorID, string resourceStri internal static Expression ThrowRuntimeError(Type exceptionType, string errorID, string resourceString, Type throwResultType, params Expression[] exceptionArgs) { var exceptionArgArray = exceptionArgs != null - ? Expression.NewArrayInit(typeof(object), exceptionArgs.Select(e => e.Cast(typeof(object)))) + ? Expression.NewArrayInit(typeof(object), exceptionArgs.Select(static e => e.Cast(typeof(object)))) : ExpressionCache.NullConstant; Expression[] argExprs = new Expression[] { @@ -5153,7 +5170,7 @@ public object VisitCatchClause(CatchClauseAst catchClauseAst) // } // // This is a little convoluted because an automatic variable isn't necessarily set. - private class AutomaticVarSaver + private sealed class AutomaticVarSaver { private readonly Compiler _compiler; private readonly int _automaticVar; @@ -5502,7 +5519,7 @@ where t.Label.Equals(labelStrAst.Value, StringComparison.OrdinalIgnoreCase) } else { - labelExpr = labelExpr ?? ExpressionCache.ConstEmptyString; + labelExpr ??= ExpressionCache.ConstEmptyString; result = Expression.Throw(Expression.New(nonLocalExceptionCtor, labelExpr.Convert(typeof(string)))); } @@ -5935,14 +5952,12 @@ public object VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst) private static Expression GetLikeRHSOperand(WildcardOptions options, Expression expr) { - var constExpr = expr as ConstantExpression; - if (constExpr == null) + if (!(expr is ConstantExpression constExpr)) { return expr; } - var val = constExpr.Value as string; - if (val == null) + if (!(constExpr.Value is string val)) { return expr; } @@ -6315,7 +6330,7 @@ internal static PSMethodInvocationConstraints GetInvokeMemberConstraints(InvokeM var targetTypeConstraint = GetTypeConstraintForMethodResolution(invokeMemberExpressionAst.Expression); return CombineTypeConstraintForMethodResolution( targetTypeConstraint, - arguments != null ? arguments.Select(Compiler.GetTypeConstraintForMethodResolution).ToArray() : null); + arguments?.Select(Compiler.GetTypeConstraintForMethodResolution).ToArray()); } internal static PSMethodInvocationConstraints GetInvokeMemberConstraints(BaseCtorInvokeMemberExpressionAst invokeMemberExpressionAst) @@ -6334,7 +6349,7 @@ internal static PSMethodInvocationConstraints GetInvokeMemberConstraints(BaseCto return CombineTypeConstraintForMethodResolution( targetTypeConstraint, - arguments != null ? arguments.Select(Compiler.GetTypeConstraintForMethodResolution).ToArray() : null); + arguments?.Select(Compiler.GetTypeConstraintForMethodResolution).ToArray()); } internal Expression InvokeMember( @@ -6347,7 +6362,7 @@ internal Expression InvokeMember( bool nullConditional = false) { var callInfo = new CallInfo(args.Count()); - var classScope = _memberFunctionType != null ? _memberFunctionType.Type : null; + var classScope = _memberFunctionType?.Type; var binder = name.Equals("new", StringComparison.OrdinalIgnoreCase) && @static ? (CallSiteBinder)PSCreateInstanceBinder.Get(callInfo, constraints, publicTypeOnly: true) : PSInvokeMemberBinder.Get(name, callInfo, @static, propertySet, constraints, classScope); @@ -6357,7 +6372,7 @@ internal Expression InvokeMember( return nullConditional ? GetNullConditionalWrappedExpression(target, dynamicExprFromBinder) : dynamicExprFromBinder; } - private Expression InvokeBaseCtorMethod(PSMethodInvocationConstraints constraints, Expression target, IEnumerable args) + private static Expression InvokeBaseCtorMethod(PSMethodInvocationConstraints constraints, Expression target, IEnumerable args) { var callInfo = new CallInfo(args.Count()); var binder = PSInvokeBaseCtorBinder.Get(callInfo, constraints); @@ -6430,7 +6445,7 @@ public object VisitArrayExpression(ArrayExpressionAst arrayExpressionAst) } } - values = values ?? CaptureAstResults(subExpr, CaptureAstContext.Enumerable); + values ??= CaptureAstResults(subExpr, CaptureAstContext.Enumerable); if (pureExprAst is ArrayLiteralAst) { @@ -6706,8 +6721,8 @@ public Expression GetValue(Compiler compiler, List exprs, List Expression.Variable(arg.Type)).ToArray(); - exprs.AddRange(args.Zip(_argExprTemps, (arg, temp) => Expression.Assign(temp, arg))); + _argExprTemps = args.Select(static arg => Expression.Variable(arg.Type)).ToArray(); + exprs.AddRange(args.Zip(_argExprTemps, static (arg, temp) => Expression.Assign(temp, arg))); temps.Add(_targetExprTemp); int tempsIndex = temps.Count; diff --git a/src/System.Management.Automation/engine/parser/ConstantValues.cs b/src/System.Management.Automation/engine/parser/ConstantValues.cs index 5813ed9d41f..a8ada5f96d5 100644 --- a/src/System.Management.Automation/engine/parser/ConstantValues.cs +++ b/src/System.Management.Automation/engine/parser/ConstantValues.cs @@ -53,7 +53,9 @@ public static bool IsConstant(Ast ast, out object constantValue, bool forAttribu } internal bool CheckingAttributeArgument { get; set; } + internal bool CheckingClassAttributeArguments { get; set; } + internal bool CheckingRequiresArgument { get; set; } public object VisitErrorStatement(ErrorStatementAst errorStatementAst) { return false; } @@ -160,8 +162,7 @@ public object VisitPipeline(PipelineAst pipelineAst) private static bool IsNullDivisor(ExpressionAst operand) { - var varExpr = operand as VariableExpressionAst; - if (varExpr == null) + if (!(operand is VariableExpressionAst varExpr)) { return false; } @@ -261,7 +262,7 @@ public object VisitTypeExpression(TypeExpressionAst typeExpressionAst) public object VisitMemberExpression(MemberExpressionAst memberExpressionAst) { - if (!memberExpressionAst.Static || !(memberExpressionAst.Expression is TypeExpressionAst)) + if (!memberExpressionAst.Static || memberExpressionAst.Expression is not TypeExpressionAst) { return false; } @@ -272,8 +273,7 @@ public object VisitMemberExpression(MemberExpressionAst memberExpressionAst) return false; } - var member = memberExpressionAst.Member as StringConstantExpressionAst; - if (member == null) + if (!(memberExpressionAst.Member is StringConstantExpressionAst member)) { return false; } @@ -324,6 +324,7 @@ public object VisitParenExpression(ParenExpressionAst parenExpressionAst) internal class ConstantValueVisitor : ICustomAstVisitor2 { internal bool AttributeArgument { get; set; } + internal bool RequiresArgument { get; set; } [Conditional("DEBUG")] diff --git a/src/System.Management.Automation/engine/parser/DebugViewWriter.cs b/src/System.Management.Automation/engine/parser/DebugViewWriter.cs index bc65cefa866..69e8aae634b 100644 --- a/src/System.Management.Automation/engine/parser/DebugViewWriter.cs +++ b/src/System.Management.Automation/engine/parser/DebugViewWriter.cs @@ -470,7 +470,7 @@ protected override Expression VisitLambda(Expression node) { private static bool IsSimpleExpression(Expression node) { var binary = node as BinaryExpression; if (binary != null) { - return !(binary.Left is BinaryExpression || binary.Right is BinaryExpression); + return binary.Left is not BinaryExpression && binary.Right is not BinaryExpression; } return false; diff --git a/src/System.Management.Automation/engine/parser/PSType.cs b/src/System.Management.Automation/engine/parser/PSType.cs index 8a18f880bab..1f961af8d11 100644 --- a/src/System.Management.Automation/engine/parser/PSType.cs +++ b/src/System.Management.Automation/engine/parser/PSType.cs @@ -14,7 +14,7 @@ namespace System.Management.Automation.Language { - internal class TypeDefiner + internal static class TypeDefiner { internal const string DynamicClassAssemblyName = "PowerShell Class Assembly"; internal const string DynamicClassAssemblyFullNamePrefix = "PowerShell Class Assembly,"; @@ -265,7 +265,7 @@ internal static void DefineCustomAttributes(EnumBuilder member, ReadOnlyCollecti } } - private class DefineTypeHelper + private sealed class DefineTypeHelper { private readonly Parser _parser; internal readonly TypeDefinitionAst _typeDefinitionAst; @@ -921,7 +921,7 @@ private void DefineConstructor(IParameterMetadataProvider ipmp, ReadOnlyCollecti (i, n) => ctor.DefineParameter(i, ParameterAttributes.None, n)); } - private string GetMetaDataName(string name, int numberOfParameters) + private static string GetMetaDataName(string name, int numberOfParameters) { int currentId = Interlocked.Increment(ref s_globalCounter); string metaDataName = name + "_" + numberOfParameters + "_" + currentId; @@ -1007,7 +1007,7 @@ private void DefineMethodBody( } } - private class DefineEnumHelper + private sealed class DefineEnumHelper { private readonly Parser _parser; private readonly TypeDefinitionAst _enumDefinitionAst; @@ -1082,7 +1082,7 @@ internal static List Sort(List defineEnumHel } // The expression may have multiple member expressions, e.g. [E]::e1 + [E]::e2 - foreach (var memberExpr in initExpr.FindAll(ast => ast is MemberExpressionAst, false)) + foreach (var memberExpr in initExpr.FindAll(static ast => ast is MemberExpressionAst, false)) { var typeExpr = ((MemberExpressionAst)memberExpr).Expression as TypeExpressionAst; if (typeExpr != null) @@ -1411,7 +1411,7 @@ private static string GetClassNameInAssembly(TypeDefinitionAst typeDefinitionAst { if (parent is IParameterMetadataProvider) { - nameParts = nameParts ?? new List(); + nameParts ??= new List(); var fnDefn = parent.Parent as FunctionDefinitionAst; if (fnDefn != null) { @@ -1437,7 +1437,7 @@ private static string GetClassNameInAssembly(TypeDefinitionAst typeDefinitionAst return string.Join(".", nameParts); } - private static OpCode[] s_ldc = + private static readonly OpCode[] s_ldc = { OpCodes.Ldc_I4_0, OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_3, OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_5, OpCodes.Ldc_I4_6, OpCodes.Ldc_I4_7, OpCodes.Ldc_I4_8 @@ -1455,7 +1455,7 @@ private static void EmitLdc(ILGenerator emitter, int c) } } - private static OpCode[] s_ldarg = + private static readonly OpCode[] s_ldarg = { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3 }; diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index e3245e91564..3afc55e9861 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -12,6 +12,9 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.DSC; +using Dsc = Microsoft.PowerShell.DesiredStateConfiguration.Internal; namespace System.Management.Automation.Language { @@ -139,6 +142,11 @@ public static ScriptBlockAst ParseInput(string input, out Token[] tokens, out Pa /// The that represents the input script file. public static ScriptBlockAst ParseInput(string input, string fileName, out Token[] tokens, out ParseError[] errors) { + if (input is null) + { + throw new ArgumentNullException(nameof(input)); + } + Parser parser = new Parser(); List tokenList = new List(); ScriptBlockAst result; @@ -198,7 +206,7 @@ private ScriptBlockAst ParseTask(string fileName, string input, List toke } catch (InsufficientExecutionStackException) { - if (recursed == false) + if (!recursed) { // We'll try parsing once more, this time on a new thread. The assumption here is // that the stack was close to overflowing before we tried to parse, and that won't @@ -732,8 +740,7 @@ internal static bool TryParseAsConstantHashtable(string input, out Hashtable res return false; } - var pipelineAst = statements[0] as PipelineAst; - if (pipelineAst == null) + if (!(statements[0] is PipelineAst pipelineAst)) { return false; } @@ -744,8 +751,7 @@ internal static bool TryParseAsConstantHashtable(string input, out Hashtable res return false; } - var hashTableAst = expr as HashtableAst; - if (hashTableAst == null) + if (!(expr is HashtableAst hashTableAst)) { return false; } @@ -1668,7 +1674,7 @@ private ScriptBlockAst ScriptBlockBodyRule(Token lCurly, List statements.Add(predefinedStatementAst); } - IScriptExtent statementListExtent = paramBlockAst != null ? paramBlockAst.Extent : null; + IScriptExtent statementListExtent = paramBlockAst?.Extent; IScriptExtent scriptBlockExtent; while (true) @@ -1709,7 +1715,7 @@ private ScriptBlockAst NamedBlockListRule(Token lCurly, List NamedBlockAst endBlock = null; IScriptExtent startExtent = lCurly != null ? lCurly.Extent - : (paramBlockAst != null) ? paramBlockAst.Extent : null; + : paramBlockAst?.Extent; IScriptExtent endExtent = null; IScriptExtent extent = null; IScriptExtent scriptBlockExtent = null; @@ -1973,7 +1979,7 @@ private StatementAst StatementRule() } else if ((token.TokenFlags & TokenFlags.Keyword) != 0) { - foreach (var attr in attributes.Where(attr => !(attr is AttributeAst))) + foreach (var attr in attributes.Where(static attr => attr is not AttributeAst)) { ReportError(attr.Extent, nameof(ParserStrings.TypeNotAllowedBeforeStatement), @@ -2044,7 +2050,7 @@ private StatementAst StatementRule() statement = BlockStatementRule(token); break; case TokenKind.Configuration: - statement = ConfigurationStatementRule(attributes != null ? attributes.OfType() : null, token); + statement = ConfigurationStatementRule(attributes?.OfType(), token); break; case TokenKind.From: case TokenKind.Define: @@ -2550,7 +2556,7 @@ private StatementAst SwitchStatementRule(LabelToken labelToken, Token switchToke { SkipToken(); endErrorStatement = switchParameterToken.Extent; - specifiedFlags = specifiedFlags ?? new Dictionary>(); + specifiedFlags ??= new Dictionary>(); if (IsSpecificParameter(switchParameterToken, "regex")) { @@ -2647,7 +2653,7 @@ private StatementAst SwitchStatementRule(LabelToken labelToken, Token switchToke if (switchParameterToken.Kind == TokenKind.Minus) { - specifiedFlags = specifiedFlags ?? new Dictionary>(); + specifiedFlags ??= new Dictionary>(); specifiedFlags.Add(VERBATIM_ARGUMENT, new Tuple(switchParameterToken, null)); } @@ -2850,7 +2856,7 @@ private StatementAst SwitchStatementRule(LabelToken labelToken, Token switchToke } return new SwitchStatementAst(ExtentOf(labelToken ?? switchToken, rCurly), - labelToken != null ? labelToken.LabelText : null, condition, flags, clauses, @default); + labelToken?.LabelText, condition, flags, clauses, @default); } private StatementAst ConfigurationStatementRule(IEnumerable customAttributes, Token configurationToken) @@ -2969,7 +2975,6 @@ private StatementAst ConfigurationStatementRule(IEnumerable custom ExpressionAst configurationBodyScriptBlock = null; - // Automatically import the PSDesiredStateConfiguration module at this point. PowerShell p = null; // Save the parser we're using so we can resume the current parse when we're done. @@ -2997,7 +3002,18 @@ private StatementAst ConfigurationStatementRule(IEnumerable custom { // Load the default CIM keywords Collection CIMKeywordErrors = new Collection(); - Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + + // DscSubsystem is auto-registered when PSDesiredStateConfiguration v3 module is loaded + // so if DscSubsystem is registered that means user intention to use v3 APIs. + ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem(); + if (dscSubsystem != null) + { + dscSubsystem.LoadDefaultKeywords(CIMKeywordErrors); + } + else + { + Dsc.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + } // Report any errors encountered while loading CIM dynamic keywords. if (CIMKeywordErrors.Count > 0) @@ -3239,7 +3255,16 @@ private StatementAst ConfigurationStatementRule(IEnumerable custom // Clear out all of the cached classes and keywords. // They will need to be reloaded when the generated function is actually run. // - Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.ClearCache(); + ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem(); + if (dscSubsystem != null) + { + dscSubsystem.ClearCache(); + } + else + { + Dsc.DscClassCache.ClearCache(); + } + System.Management.Automation.Language.DynamicKeyword.Reset(); } @@ -3441,7 +3466,7 @@ private StatementAst ForeachStatementRule(LabelToken labelToken, Token forEachTo } return new ForEachStatementAst(ExtentOf(startOfStatement, body), - labelToken != null ? labelToken.LabelText : null, + labelToken?.LabelText, flags, throttleLimit, variableAst, pipeline, body); } @@ -3554,7 +3579,7 @@ private StatementAst ForStatementRule(LabelToken labelToken, Token forToken) } return new ForStatementAst(ExtentOf(labelToken ?? forToken, body), - labelToken != null ? labelToken.LabelText : null, initializer, condition, iterator, body); + labelToken?.LabelText, initializer, condition, iterator, body); } private StatementAst WhileStatementRule(LabelToken labelToken, Token whileToken) @@ -3636,7 +3661,7 @@ private StatementAst WhileStatementRule(LabelToken labelToken, Token whileToken) } return new WhileStatementAst(ExtentOf(labelToken ?? whileToken, body), - labelToken != null ? labelToken.LabelText : null, condition, body); + labelToken?.LabelText, condition, body); } /// @@ -4131,7 +4156,7 @@ private StatementAst DoWhileStatementRule(LabelToken labelToken, Token doToken) } IScriptExtent extent = ExtentOf(startExtent, rParen); - string label = (labelToken != null) ? labelToken.LabelText : null; + string label = labelToken?.LabelText; if (whileOrUntilToken.Kind == TokenKind.Until) { return new DoUntilStatementAst(extent, label, condition, body); @@ -4285,7 +4310,7 @@ private StatementAst ClassDefinitionRule(List customAttributes ? customAttributes[0].Extent : classToken.Extent; var extent = ExtentOf(startExtent, lastExtent); - var classDefn = new TypeDefinitionAst(extent, name.Value, customAttributes == null ? null : customAttributes.OfType(), members, TypeAttributes.Class, superClassesList); + var classDefn = new TypeDefinitionAst(extent, name.Value, customAttributes?.OfType(), members, TypeAttributes.Class, superClassesList); if (customAttributes != null && customAttributes.OfType().Any()) { if (nestedAsts == null) @@ -4576,7 +4601,7 @@ private MemberAst ClassMemberRule(string className, out List astsOnError) return null; } - private bool TryUseTokenAsSimpleName(Token token) + private static bool TryUseTokenAsSimpleName(Token token) { if (token.Kind == TokenKind.Identifier || token.Kind == TokenKind.DynamicKeyword @@ -4589,7 +4614,7 @@ private bool TryUseTokenAsSimpleName(Token token) return false; } - private void RecordErrorAsts(Ast errAst, ref List astsOnError) + private static void RecordErrorAsts(Ast errAst, ref List astsOnError) { if (errAst == null) { @@ -4604,7 +4629,7 @@ private void RecordErrorAsts(Ast errAst, ref List astsOnError) astsOnError.Add(errAst); } - private void RecordErrorAsts(IEnumerable errAsts, ref List astsOnError) + private static void RecordErrorAsts(IEnumerable errAsts, ref List astsOnError) { if (errAsts == null || !errAsts.Any()) { @@ -4644,19 +4669,19 @@ private Token NextTypeIdentifierToken() private StatementAst EnumDefinitionRule(List customAttributes, Token enumToken) { - //G enum-statement: - //G 'enum' new-lines:opt enum-name '{' enum-member-list '}' - //G 'enum' new-lines:opt enum-name ':' enum-underlying-type '{' enum-member-list '}' - //G - //G enum-name: - //G simple-name - //G - //G enum-underlying-type: - //G new-lines:opt valid-type-name new-lines:opt - //G - //G enum-member-list: - //G enum-member new-lines:opt - //G enum-member-list enum-member + // G enum-statement: + // G 'enum' new-lines:opt enum-name '{' enum-member-list '}' + // G 'enum' new-lines:opt enum-name ':' enum-underlying-type '{' enum-member-list '}' + // G + // G enum-name: + // G simple-name + // G + // G enum-underlying-type: + // G new-lines:opt valid-type-name new-lines:opt + // G + // G enum-member-list: + // G enum-member new-lines:opt + // G enum-member-list enum-member const TypeCode ValidUnderlyingTypeCodes = TypeCode.Byte | TypeCode.Int16 | TypeCode.Int32 | TypeCode.Int64 | TypeCode.SByte | TypeCode.UInt16 | TypeCode.UInt32 | TypeCode.UInt64; @@ -4746,7 +4771,7 @@ private StatementAst EnumDefinitionRule(List customAttributes, ? customAttributes[0].Extent : enumToken.Extent; var extent = ExtentOf(startExtent, rCurly); - var enumDefn = new TypeDefinitionAst(extent, name.Value, customAttributes == null ? null : customAttributes.OfType(), members, TypeAttributes.Enum, underlyingTypeConstraint == null ? null : new[] { underlyingTypeConstraint }); + var enumDefn = new TypeDefinitionAst(extent, name.Value, customAttributes?.OfType(), members, TypeAttributes.Enum, underlyingTypeConstraint == null ? null : new[] { underlyingTypeConstraint }); if (customAttributes != null && customAttributes.OfType().Any()) { // No need to report error since there is error reported in method StatementRule @@ -4923,7 +4948,8 @@ private StatementAst UsingStatementRule(Token usingToken) return new ErrorStatementAst(ExtentOf(usingToken, itemToken.Extent)); } - if (!(itemAst is StringConstantExpressionAst) && (kind != UsingStatementKind.Module || !(itemAst is HashtableAst))) + if (itemAst is not StringConstantExpressionAst + && (kind != UsingStatementKind.Module || itemAst is not HashtableAst)) { ReportError(ExtentFromFirstOf(itemAst, itemToken), nameof(ParserStrings.InvalidValueForUsingItemName), @@ -5624,7 +5650,7 @@ private StatementAst DataStatementRule(Token dataToken) IScriptExtent endErrorStatement = null; SkipNewlines(); var dataVariableNameAst = SimpleNameRule(); - string dataVariableName = (dataVariableNameAst != null) ? dataVariableNameAst.Value : null; + string dataVariableName = dataVariableNameAst?.Value; SkipNewlines(); Token supportedCommandToken = PeekToken(); @@ -5999,7 +6025,7 @@ private PipelineBaseAst PipelineRule( commandAst = new CommandExpressionAst( exprExtent, expr, - redirections?.Where(r => r != null)); + redirections?.Where(static r => r != null)); } else { @@ -6630,7 +6656,7 @@ internal Ast CommandRule(bool forDynamicKeyword) return new CommandAst(ExtentOf(firstToken, endExtent), elements, dotSource || ampersand ? firstToken.Kind : TokenKind.Unknown, - redirections != null ? redirections.Where(r => r != null) : null); + redirections?.Where(static r => r != null)); } #endregion Pipelines @@ -7940,7 +7966,7 @@ private static void AssertErrorIdCorrespondsToMsgString(string errorId, string e private static object[] arrayOfOneArg { - get { return t_arrayOfOneArg ?? (t_arrayOfOneArg = new object[1]); } + get { return t_arrayOfOneArg ??= new object[1]; } } [ThreadStatic] @@ -7948,7 +7974,7 @@ private static object[] arrayOfOneArg private static object[] arrayOfTwoArgs { - get { return t_arrayOfTwoArgs ?? (t_arrayOfTwoArgs = new object[2]); } + get { return t_arrayOfTwoArgs ??= new object[2]; } } [ThreadStatic] @@ -8014,7 +8040,7 @@ internal void ReportError(ParseError error) SaveError(error); } - private void ReportErrorsAsWarnings(Collection errors) + private static void ReportErrorsAsWarnings(Collection errors) { var executionContext = Runspaces.Runspace.DefaultRunspace.ExecutionContext; if (executionContext != null && executionContext.InternalHost != null && executionContext.InternalHost.UI != null) diff --git a/src/System.Management.Automation/engine/parser/Position.cs b/src/System.Management.Automation/engine/parser/Position.cs index e9f273fed14..3c4281e5446 100644 --- a/src/System.Management.Automation/engine/parser/Position.cs +++ b/src/System.Management.Automation/engine/parser/Position.cs @@ -15,12 +15,13 @@ namespace System.Management.Automation.Language /// /// Represents a single point in a script. The script may come from a file or interactive input. /// +#nullable enable public interface IScriptPosition { /// /// The name of the file, or if the script did not come from a file, then null. /// - string File { get; } + string? File { get; } /// /// The line number of the position, with the value 1 being the first line. @@ -45,18 +46,20 @@ public interface IScriptPosition /// /// The complete script that this position is included in. /// - string GetFullScript(); + string? GetFullScript(); } +#nullable restore /// /// Represents the a span of text in a script. /// +#nullable enable public interface IScriptExtent { /// /// The filename the extent includes, or null if the extent is not included in any file. /// - string File { get; } + string? File { get; } /// /// The starting position of the extent. @@ -103,6 +106,7 @@ public interface IScriptExtent /// int EndOffset { get; } } +#nullable restore /// /// A few utility functions for script positions. @@ -571,8 +575,7 @@ internal sealed class EmptyScriptExtent : IScriptExtent public override bool Equals(object obj) { - IScriptExtent otherPosition = obj as IScriptExtent; - if (otherPosition == null) + if (!(obj is IScriptExtent otherPosition)) { return false; } @@ -645,8 +648,8 @@ public ScriptPosition( int scriptLineNumber, int offsetInLine, string line, - string fullScript) : - this(scriptName, scriptLineNumber, offsetInLine, line) + string fullScript) + : this(scriptName, scriptLineNumber, offsetInLine, line) { _fullScript = fullScript; } diff --git a/src/System.Management.Automation/engine/parser/PreOrderVisitor.cs b/src/System.Management.Automation/engine/parser/PreOrderVisitor.cs index 0bf5368fddb..33b2fadec64 100644 --- a/src/System.Management.Automation/engine/parser/PreOrderVisitor.cs +++ b/src/System.Management.Automation/engine/parser/PreOrderVisitor.cs @@ -254,6 +254,7 @@ public abstract class AstVisitor2 : AstVisitor /// Implement this interface when you implement or when /// you want to do something after possibly visiting the children of the ast. /// +#nullable enable public interface IAstPostVisitHandler { /// diff --git a/src/System.Management.Automation/engine/parser/SafeValues.cs b/src/System.Management.Automation/engine/parser/SafeValues.cs index 37320de83d1..f76269a12d7 100644 --- a/src/System.Management.Automation/engine/parser/SafeValues.cs +++ b/src/System.Management.Automation/engine/parser/SafeValues.cs @@ -356,13 +356,14 @@ public object VisitParenExpression(ParenExpressionAst parenExpressionAst) * except in the case of handling the unary operator * ExecutionContext is provided to ensure we can resolve variables */ - internal class GetSafeValueVisitor : ICustomAstVisitor2 + internal sealed class GetSafeValueVisitor : ICustomAstVisitor2 { internal enum SafeValueContext { Default, GetPowerShell, - ModuleAnalysis + ModuleAnalysis, + SkipHashtableSizeCheck, } // future proofing @@ -371,7 +372,8 @@ private GetSafeValueVisitor() { } public static object GetSafeValue(Ast ast, ExecutionContext context, SafeValueContext safeValueContext) { t_context = context; - if (IsSafeValueVisitor.IsAstSafe(ast, safeValueContext)) + + if (safeValueContext == SafeValueContext.SkipHashtableSizeCheck || IsSafeValueVisitor.IsAstSafe(ast, safeValueContext)) { return ast.Accept(new GetSafeValueVisitor()); } @@ -480,7 +482,7 @@ public static object GetSafeValue(Ast ast, ExecutionContext context, SafeValueCo // this can throw, but there really isn't useful information we can add, as the // offending expression will be presented in the case of any failure // - private object GetSingleValueFromTarget(object target, object index) + private static object GetSingleValueFromTarget(object target, object index) { var targetString = target as string; if (targetString != null) @@ -517,7 +519,7 @@ private object GetSingleValueFromTarget(object target, object index) throw new Exception(); } - private object GetIndexedValueFromTarget(object target, object index) + private static object GetIndexedValueFromTarget(object target, object index) { var indexArray = index as object[]; return indexArray != null ? ((object[])indexArray).Select(i => GetSingleValueFromTarget(target, i)).ToArray() : GetSingleValueFromTarget(target, index); diff --git a/src/System.Management.Automation/engine/parser/SemanticChecks.cs b/src/System.Management.Automation/engine/parser/SemanticChecks.cs index f46b366785b..927b2c33ae8 100644 --- a/src/System.Management.Automation/engine/parser/SemanticChecks.cs +++ b/src/System.Management.Automation/engine/parser/SemanticChecks.cs @@ -11,11 +11,13 @@ using System.Text; using Microsoft.PowerShell; +using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.DSC; using Microsoft.PowerShell.DesiredStateConfiguration.Internal; namespace System.Management.Automation.Language { - internal class SemanticChecks : AstVisitor2, IAstPostVisitHandler + internal sealed class SemanticChecks : AstVisitor2, IAstPostVisitHandler { private readonly Parser _parser; @@ -62,12 +64,12 @@ private bool AnalyzingStaticMember() return fnMemberAst != null ? fnMemberAst.IsStatic : ((PropertyMemberAst)currentMember).IsStatic; } - private bool IsValidAttributeArgument(Ast ast, IsConstantValueVisitor visitor) + private static bool IsValidAttributeArgument(Ast ast, IsConstantValueVisitor visitor) { return (bool)ast.Accept(visitor); } - private (string id, string msg) GetNonConstantAttributeArgErrorExpr(IsConstantValueVisitor visitor) + private static (string id, string msg) GetNonConstantAttributeArgErrorExpr(IsConstantValueVisitor visitor) { if (visitor.CheckingClassAttributeArguments) { @@ -100,7 +102,7 @@ private void CheckForDuplicateParameters(ReadOnlyCollection parame } var voidConstraint = - parameter.Attributes.OfType().FirstOrDefault(t => typeof(void) == t.TypeName.GetReflectionType()); + parameter.Attributes.OfType().FirstOrDefault(static t => typeof(void) == t.TypeName.GetReflectionType()); if (voidConstraint != null) { @@ -197,7 +199,8 @@ public override AstVisitAction VisitAttribute(AttributeAst attributeAst) var members = attributeType.GetMember(name, MemberTypes.Field | MemberTypes.Property, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - if (members.Length != 1 || !(members[0] is PropertyInfo || members[0] is FieldInfo)) + if (members.Length != 1 + || (members[0] is not PropertyInfo && members[0] is not FieldInfo)) { _parser.ReportError(namedArg.Extent, nameof(ParserStrings.PropertyNotFoundForAttribute), @@ -348,7 +351,7 @@ internal static void CheckArrayTypeNameDepth(ITypeName typeName, IScriptExtent e { int count = 0; ITypeName type = typeName; - while ((type is TypeName) == false) + while (type is not TypeName) { count++; if (count > 200) @@ -669,7 +672,7 @@ private static string GetLabel(ExpressionAst expr) } var str = expr as StringConstantExpressionAst; - return str != null ? str.Value : null; + return str?.Value; } public override AstVisitAction VisitBreakStatement(BreakStatementAst breakStatementAst) @@ -692,8 +695,7 @@ public override AstVisitAction VisitContinueStatement(ContinueStatementAst conti private void CheckForReturnStatement(ReturnStatementAst ast) { - var functionMemberAst = _memberScopeStack.Peek() as FunctionMemberAst; - if (functionMemberAst == null) + if (!(_memberScopeStack.Peek() is FunctionMemberAst functionMemberAst)) { return; } @@ -1026,7 +1028,9 @@ private ExpressionAst CheckUsingExpression(ExpressionAst exprAst) } var memberExpr = exprAst as MemberExpressionAst; - if (memberExpr != null && !(memberExpr is InvokeMemberExpressionAst) && (memberExpr.Member is StringConstantExpressionAst)) + if (memberExpr != null + && memberExpr is not InvokeMemberExpressionAst + && memberExpr.Member is StringConstantExpressionAst) { return CheckUsingExpression(memberExpr.Expression); } @@ -1047,7 +1051,9 @@ private ExpressionAst CheckUsingExpression(ExpressionAst exprAst) public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst) { - if (variableExpressionAst.Splatted && !(variableExpressionAst.Parent is CommandAst) && !(variableExpressionAst.Parent is UsingExpressionAst)) + if (variableExpressionAst.Splatted + && variableExpressionAst.Parent is not CommandAst + && variableExpressionAst.Parent is not UsingExpressionAst) { if (variableExpressionAst.Parent is ArrayLiteralAst && variableExpressionAst.Parent.Parent is CommandAst) { @@ -1179,7 +1185,7 @@ public override AstVisitAction VisitInvokeMemberExpression(InvokeMemberExpressio return AstVisitAction.Continue; } - private void CheckMemberAccess(MemberExpressionAst ast) + private static void CheckMemberAccess(MemberExpressionAst ast) { // If the member access is not constant, it may be considered suspicious if (ast.Member is not ConstantExpressionAst) @@ -1197,7 +1203,7 @@ private void CheckMemberAccess(MemberExpressionAst ast) } // Mark all of the parents of an AST as suspicious - private void MarkAstParentsAsSuspicious(Ast ast) + private static void MarkAstParentsAsSuspicious(Ast ast) { Ast targetAst = ast; var parent = ast; @@ -1214,7 +1220,9 @@ private void MarkAstParentsAsSuspicious(Ast ast) public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { _scopeStack.Push(scriptBlockAst); - if (scriptBlockAst.Parent == null || scriptBlockAst.Parent is ScriptBlockExpressionAst || !(scriptBlockAst.Parent.Parent is FunctionMemberAst)) + if (scriptBlockAst.Parent == null + || scriptBlockAst.Parent is ScriptBlockExpressionAst + || scriptBlockAst.Parent.Parent is not FunctionMemberAst) { _memberScopeStack.Push(null); } @@ -1380,7 +1388,7 @@ public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatem else if (!keyword.Properties.ContainsKey(propName.Value)) { IOrderedEnumerable tableKeys = keyword.Properties.Keys - .OrderBy(key => key, StringComparer.OrdinalIgnoreCase); + .OrderBy(static key => key, StringComparer.OrdinalIgnoreCase); _parser.ReportError(propName.Extent, nameof(ParserStrings.InvalidInstanceProperty), @@ -1399,7 +1407,10 @@ public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatem { StringConstantExpressionAst nameAst = dynamicKeywordStatementAst.CommandElements[0] as StringConstantExpressionAst; Diagnostics.Assert(nameAst != null, "nameAst should never be null"); - if (!DscClassCache.SystemResourceNames.Contains(nameAst.Extent.Text.Trim())) + var extentText = nameAst.Extent.Text.Trim(); + ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem(); + var extentTextIsASystemResourceName = (dscSubsystem != null) ? dscSubsystem.IsSystemResourceName(extentText) : DscClassCache.SystemResourceNames.Contains(extentText); + if (!extentTextIsASystemResourceName) { if (configAst.ConfigurationType == ConfigurationType.Meta && !dynamicKeywordStatementAst.Keyword.IsMetaDSCResource()) { @@ -1446,7 +1457,9 @@ public void PostVisit(Ast ast) var scriptBlockAst = ast as ScriptBlockAst; if (scriptBlockAst != null) { - if (scriptBlockAst.Parent == null || scriptBlockAst.Parent is ScriptBlockExpressionAst || !(scriptBlockAst.Parent.Parent is FunctionMemberAst)) + if (scriptBlockAst.Parent == null + || scriptBlockAst.Parent is ScriptBlockExpressionAst + || scriptBlockAst.Parent.Parent is not FunctionMemberAst) { _memberScopeStack.Pop(); } @@ -1583,8 +1596,7 @@ private static void LookupRequiredMembers(Parser parser, TypeDefinitionAst typeD foreach (var baseType in typeDefinitionAst.BaseTypes) { - var baseTypeName = baseType.TypeName as TypeName; - if (baseTypeName == null) + if (!(baseType.TypeName is TypeName baseTypeName)) { continue; } @@ -2271,7 +2283,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var else argBuilder.Append(", "); - argBuilder.Append("$"); + argBuilder.Append('$'); argBuilder.Append(varName); } diff --git a/src/System.Management.Automation/engine/parser/SymbolResolver.cs b/src/System.Management.Automation/engine/parser/SymbolResolver.cs index 603ae539cb1..b97496dcc0f 100644 --- a/src/System.Management.Automation/engine/parser/SymbolResolver.cs +++ b/src/System.Management.Automation/engine/parser/SymbolResolver.cs @@ -30,6 +30,7 @@ public TypeLookupResult(TypeDefinitionAst type = null) } public TypeDefinitionAst Type { get; set; } + public List ExternalNamespaces { get; set; } public bool IsAmbiguous() @@ -178,7 +179,7 @@ internal void AddTypesInScope(Ast ast) // class C1 { [C2]$x } // class C2 { [C1]$c1 } - var types = ast.FindAll(x => x is TypeDefinitionAst, searchNestedScriptBlocks: false); + var types = ast.FindAll(static x => x is TypeDefinitionAst, searchNestedScriptBlocks: false); foreach (var type in types) { AddType((TypeDefinitionAst)type); @@ -274,7 +275,7 @@ public bool IsInMethodScope() } } - internal class SymbolResolver : AstVisitor2, IAstPostVisitHandler + internal sealed class SymbolResolver : AstVisitor2, IAstPostVisitHandler { private readonly SymbolResolvePostActionVisitor _symbolResolvePostActionVisitor; internal readonly SymbolTable _symbolTable; @@ -301,7 +302,7 @@ private static PowerShell UsingStatementResolvePowerShell InitialSessionState iss = InitialSessionState.Create(); iss.Commands.Add(new SessionStateCmdletEntry("Get-Module", typeof(GetModuleCommand), null)); var sessionStateProviderEntry = new SessionStateProviderEntry(FileSystemProvider.ProviderName, typeof(FileSystemProvider), null); - var snapin = PSSnapInReader.ReadEnginePSSnapIns().FirstOrDefault(snapIn => snapIn.Name.Equals("Microsoft.PowerShell.Core", StringComparison.OrdinalIgnoreCase)); + var snapin = PSSnapInReader.ReadEnginePSSnapIns().FirstOrDefault(static snapIn => snapIn.Name.Equals("Microsoft.PowerShell.Core", StringComparison.OrdinalIgnoreCase)); sessionStateProviderEntry.SetPSSnapIn(snapin); iss.Providers.Add(sessionStateProviderEntry); t_usingStatementResolvePowerShell = PowerShell.Create(iss); diff --git a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs index 59cf5348cc8..d1e3c7155d7 100644 --- a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs +++ b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs @@ -132,7 +132,7 @@ public TypeInferenceContext() : this(PowerShell.Create(RunspaceMode.CurrentRunsp } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// The powerShell instance passed need to have a non null Runspace. /// /// The instance of powershell to use for expression evaluation needed for type inference. @@ -316,8 +316,7 @@ internal void AddMembersByInferredTypeDefinitionAst( // iterate through bases/interfaces foreach (var baseType in typename.TypeDefinitionAst.BaseTypes) { - var baseTypeName = baseType.TypeName as TypeName; - if (baseTypeName == null) + if (!(baseType.TypeName is TypeName baseTypeName)) { continue; } @@ -1178,7 +1177,7 @@ private void InferTypesFromGroupCommand(PseudoBindingInfo pseudoBinding, Command properties = new[] { stringConstant.Value }; break; case ArrayLiteralAst arrayLiteral: - properties = arrayLiteral.Elements.OfType().Select(c => c.Value).ToArray(); + properties = arrayLiteral.Elements.OfType().Select(static c => c.Value).ToArray(); scriptBlockProperty = arrayLiteral.Elements.OfType().Any(); break; case CommandElementAst _: @@ -1218,7 +1217,7 @@ bool IsInPropertyArgument(object o) } var previousPipelineElement = GetPreviousPipelineCommand(commandAst); - var typeName = "Microsoft.PowerShell.Commands.GroupInfo"; + const string typeName = "Microsoft.PowerShell.Commands.GroupInfo"; var members = new List(); foreach (var prevType in InferTypes(previousPipelineElement)) { @@ -1293,7 +1292,7 @@ void InferFromSelectProperties(AstParameterArgumentPair astParameterArgumentPair { if (astParameterArgumentPair is AstPair astPair) { - object ToWildCardOrString(string value) => WildcardPattern.ContainsWildcardCharacters(value) ? (object)new WildcardPattern(value) : value; + static object ToWildCardOrString(string value) => WildcardPattern.ContainsWildcardCharacters(value) ? (object)new WildcardPattern(value) : value; object[] properties = null; switch (astPair.Argument) { @@ -1301,7 +1300,7 @@ void InferFromSelectProperties(AstParameterArgumentPair astParameterArgumentPair properties = new[] { ToWildCardOrString(stringConstant.Value) }; break; case ArrayLiteralAst arrayLiteral: - properties = arrayLiteral.Elements.OfType().Select(c => ToWildCardOrString(c.Value)).ToArray(); + properties = arrayLiteral.Elements.OfType().Select(static c => ToWildCardOrString(c.Value)).ToArray(); break; } @@ -1484,8 +1483,7 @@ private IEnumerable InferTypesFrom(MemberExpressionAst memberExpress var expression = memberExpressionAst.Expression; // If the member name isn't simple, don't even try. - var memberAsStringConst = memberCommandElement as StringConstantExpressionAst; - if (memberAsStringConst == null) + if (!(memberCommandElement is StringConstantExpressionAst memberAsStringConst)) { return Array.Empty(); } @@ -1701,7 +1699,7 @@ private bool TryGetTypeFromMember( return false; } - private void AddTypesFromMethodCacheEntry( + private static void AddTypesFromMethodCacheEntry( DotNetAdapter.MethodCacheEntry methodCacheEntry, List result, bool isInvokeMemberExpressionAst) @@ -1728,8 +1726,7 @@ private PSTypeName[] GetExpressionType(ExpressionAst expression, bool isStatic) PSTypeName[] exprType; if (isStatic) { - var exprAsType = expression as TypeExpressionAst; - if (exprAsType == null) + if (!(expression is TypeExpressionAst exprAsType)) { return null; } @@ -2024,7 +2021,7 @@ private void InferTypeFrom(VariableExpressionAst variableExpressionAst, List /// The inferred types all the items in the array. /// The inferred strongly typed array type. - private PSTypeName GetArrayType(IEnumerable inferredTypes) + private static PSTypeName GetArrayType(IEnumerable inferredTypes) { PSTypeName foundType = null; foreach (PSTypeName inferredType in inferredTypes) @@ -2080,7 +2077,7 @@ private PSTypeName GetArrayType(IEnumerable inferredTypes) /// /// The type to infer enumerated item type from. /// The inferred enumerated item type. - private Type GetMostSpecificEnumeratedItemType(Type enumerableType) + private static Type GetMostSpecificEnumeratedItemType(Type enumerableType) { if (enumerableType.IsArray) { @@ -2144,19 +2141,19 @@ private Type GetMostSpecificEnumeratedItemType(Type enumerableType) /// The interface to test. /// /// A reference to a value indicating whether a non-generic enumerable type has been - /// seen. If is a non-generic enumerable type this - /// value will be set to . + /// seen. If is a non-generic enumerable type this + /// value will be set to . /// /// - /// A reference to a value indicating whether has been - /// seen. If is a this - /// value will be set to . + /// A reference to a value indicating whether has been + /// seen. If is a this + /// value will be set to . /// /// - /// The value of if it can be used to infer a specific - /// enumerated type, otherwise . + /// The value of if it can be used to infer a specific + /// enumerated type, otherwise . /// - private Type GetGenericCollectionLikeInterface( + private static Type GetGenericCollectionLikeInterface( Type interfaceType, ref bool hasSeenNonGeneric, ref bool hasSeenDictionaryEnumerator) @@ -2253,14 +2250,14 @@ private IEnumerable InferTypeFrom(IndexExpressionAst indexExpression } /// - /// Infers the types as if they were enumerated. For example, a - /// of type would be returned as . + /// Infers the types as if they were enumerated. For example, a + /// of type would be returned as . /// /// /// The potentially enumerable types to infer enumerated type from. /// /// The enumerated item types. - private IEnumerable GetInferredEnumeratedTypes(IEnumerable enumerableTypes) + private static IEnumerable GetInferredEnumeratedTypes(IEnumerable enumerableTypes) { foreach (PSTypeName maybeEnumerableType in enumerableTypes) { @@ -2281,8 +2278,7 @@ private IEnumerable GetInferredEnumeratedTypes(IEnumerable inferredTypes) { var argumentPair = argument as AstPair; - var scriptBlockExpressionAst = argumentPair?.Argument as ScriptBlockExpressionAst; - if (scriptBlockExpressionAst == null) + if (!(argumentPair?.Argument is ScriptBlockExpressionAst scriptBlockExpressionAst)) { return; } diff --git a/src/System.Management.Automation/engine/parser/TypeResolver.cs b/src/System.Management.Automation/engine/parser/TypeResolver.cs index fa054554b2a..dd69985bd5f 100644 --- a/src/System.Management.Automation/engine/parser/TypeResolver.cs +++ b/src/System.Management.Automation/engine/parser/TypeResolver.cs @@ -246,7 +246,7 @@ private static Type CallResolveTypeNameWorkerHelper(TypeName typeName, try { exception = null; - var currentScope = context != null ? context.EngineSessionState.CurrentScope : null; + var currentScope = context?.EngineSessionState.CurrentScope; Type result = ResolveTypeNameWorker(typeName, currentScope, typeResolutionState.assemblies, t_searchedAssemblies, typeResolutionState, /*onlySearchInGivenAssemblies*/ false, /* reportAmbiguousException */ true, out exception); if (exception == null && result == null) @@ -615,9 +615,7 @@ public override bool Equals(object obj) if (object.ReferenceEquals(this, obj)) return true; - var other = obj as TypeResolutionState; - - if (other == null) + if (!(obj is TypeResolutionState other)) return false; if (this.attribute != other.attribute) @@ -673,9 +671,9 @@ public override int GetHashCode() } } - internal class TypeCache + internal static class TypeCache { - private class KeyComparer : IEqualityComparer> + private sealed class KeyComparer : IEqualityComparer> { public bool Equals(Tuple x, Tuple y) diff --git a/src/System.Management.Automation/engine/parser/VariableAnalysis.cs b/src/System.Management.Automation/engine/parser/VariableAnalysis.cs index e512ddd3938..b38954ebfc6 100644 --- a/src/System.Management.Automation/engine/parser/VariableAnalysis.cs +++ b/src/System.Management.Automation/engine/parser/VariableAnalysis.cs @@ -25,16 +25,23 @@ internal VariableAnalysisDetails() } public int BitIndex { get; set; } + public int LocalTupleIndex { get; set; } + public Type Type { get; set; } + public string Name { get; set; } + public bool Automatic { get; set; } + public bool PreferenceVariable { get; set; } + public bool Assigned { get; set; } + public List AssociatedAsts { get; } } - internal class FindAllVariablesVisitor : AstVisitor + internal sealed class FindAllVariablesVisitor : AstVisitor { private static readonly HashSet s_hashOfPessimizingCmdlets = new HashSet(StringComparer.OrdinalIgnoreCase); @@ -103,7 +110,7 @@ internal static Dictionary Visit(IParameterMeta visitor.VisitParameters(ast.Parameters); } - localsAllocated = visitor._variables.Count(details => details.Value.LocalTupleIndex != VariableAnalysis.Unanalyzed); + localsAllocated = visitor._variables.Count(static details => details.Value.LocalTupleIndex != VariableAnalysis.Unanalyzed); return visitor._variables; } @@ -331,7 +338,7 @@ internal class VariableAnalysis : ICustomAstVisitor2 // in these cases, we rely on the setter PSVariable.Value to handle those attributes. internal const int ForceDynamic = -2; - private class LoopGotoTargets + private sealed class LoopGotoTargets { internal LoopGotoTargets(string label, Block breakTarget, Block continueTarget) { @@ -347,7 +354,7 @@ internal LoopGotoTargets(string label, Block breakTarget, Block continueTarget) internal Block ContinueTarget { get; } } - private class Block + private sealed class Block { internal readonly List _asts = new List(); private readonly List _successors = new List(); @@ -432,7 +439,7 @@ private static void VisitDepthFirstOrder(Block block, List visitData) } } - private class AssignmentTarget : Ast + private sealed class AssignmentTarget : Ast { internal readonly ExpressionAst _targetAst; internal readonly string _variableName; @@ -495,7 +502,7 @@ internal static void NoteAllScopeVariable(string variableName) internal static bool AnyVariablesCouldBeAllScope(Dictionary variableNames) { - return variableNames.Any(keyValuePair => s_allScopeVariables.ContainsKey(keyValuePair.Key)); + return variableNames.Any(static keyValuePair => s_allScopeVariables.ContainsKey(keyValuePair.Key)); } private Dictionary _variables; @@ -574,7 +581,7 @@ internal static bool AnalyzeMemberFunction(FunctionMemberAst ast) { VariableAnalysis va = (new VariableAnalysis()); va.AnalyzeImpl(ast, false, false); - return va._exitBlock._predecessors.All(b => b._returns || b._throws || b._unreachable); + return va._exitBlock._predecessors.All(static b => b._returns || b._throws || b._unreachable); } private Tuple> AnalyzeImpl(IParameterMetadataProvider ast, bool disableOptimizations, bool scriptCmdlet) @@ -626,7 +633,7 @@ private Tuple> AnalyzeImpl(IParameterMetadataProvi var varName = GetUnaliasedVariableName(variablePath); var details = _variables[varName]; details.Assigned = true; - type = type ?? details.Type ?? typeof(object); + type ??= details.Type ?? typeof(object); // automatic and preference variables are pre-allocated, so they can't be unallocated // and forced to be dynamic. @@ -1449,13 +1456,13 @@ where t.Label.Equals(labelStrAst.Value, StringComparison.OrdinalIgnoreCase) public object VisitBreakStatement(BreakStatementAst breakStatementAst) { - BreakOrContinue(breakStatementAst.Label, t => t.BreakTarget); + BreakOrContinue(breakStatementAst.Label, static t => t.BreakTarget); return null; } public object VisitContinueStatement(ContinueStatementAst continueStatementAst) { - BreakOrContinue(continueStatementAst.Label, t => t.ContinueTarget); + BreakOrContinue(continueStatementAst.Label, static t => t.ContinueTarget); return null; } diff --git a/src/System.Management.Automation/engine/parser/ast.cs b/src/System.Management.Automation/engine/parser/ast.cs index 459b6c206c4..3e1f9ce60a5 100644 --- a/src/System.Management.Automation/engine/parser/ast.cs +++ b/src/System.Management.Automation/engine/parser/ast.cs @@ -29,6 +29,8 @@ namespace System.Management.Automation.Language using System.Runtime.CompilerServices; using System.Reflection.Emit; +#nullable enable + internal interface ISupportsAssignment { IAssignableValue GetAssignableValue(); @@ -41,7 +43,7 @@ internal interface IAssignableValue /// It returns the expressions that holds the value of the ast. It may append the exprs or temps lists if the return /// value relies on temps and other expressions. /// - Expression GetValue(Compiler compiler, List exprs, List temps); + Expression? GetValue(Compiler compiler, List exprs, List temps); /// /// SetValue is called to set the result of an assignment (=) or to write back the result of @@ -49,12 +51,16 @@ internal interface IAssignableValue /// Expression SetValue(Compiler compiler, Expression rhs); } +#nullable restore internal interface IParameterMetadataProvider { bool HasAnyScriptBlockAttributes(); + RuntimeDefinedParameterDictionary GetParameterMetadata(bool automaticPositions, ref bool usesCmdletBinding); + IEnumerable GetScriptBlockAttributes(); + IEnumerable GetExperimentalAttributes(); bool UsesCmdletBinding(); @@ -195,6 +201,19 @@ public override string ToString() /// If is deemed unsafe /// public object SafeGetValue() + { + return SafeGetValue(skipHashtableSizeCheck: false); + } + + /// + /// Constructs the resultant object from the AST and returns it if it is safe. + /// + /// Set to skip hashtable limit validation. + /// The object represented by the AST as a safe object. + /// + /// If is deemed unsafe. + /// + public object SafeGetValue(bool skipHashtableSizeCheck) { try { @@ -204,7 +223,7 @@ public object SafeGetValue() context = System.Management.Automation.Runspaces.Runspace.DefaultRunspace.ExecutionContext; } - return GetSafeValueVisitor.GetSafeValue(this, context, GetSafeValueVisitor.SafeValueContext.Default); + return GetSafeValueVisitor.GetSafeValue(this, context, skipHashtableSizeCheck ? GetSafeValueVisitor.SafeValueContext.SkipHashtableSizeCheck : GetSafeValueVisitor.SafeValueContext.Default); } catch { @@ -286,6 +305,7 @@ internal void ClearParent() } internal abstract object Accept(ICustomAstVisitor visitor); + internal abstract AstVisitAction InternalVisit(AstVisitor visitor); internal static readonly PSTypeName[] EmptyPSTypeNameArray = Array.Empty(); @@ -369,7 +389,7 @@ internal static TypeDefinitionAst GetAncestorTypeDefinitionAst(Ast ast) // Nested function isn't really a member of the type so stop looking // Anonymous script blocks are though var functionDefinitionAst = ast as FunctionDefinitionAst; - if (functionDefinitionAst != null && !(functionDefinitionAst.Parent is FunctionMemberAst)) + if (functionDefinitionAst != null && functionDefinitionAst.Parent is not FunctionMemberAst) break; ast = ast.Parent; } @@ -770,6 +790,7 @@ public class ScriptBlockAst : Ast, IParameterMetadataProvider Utils.EmptyReadOnlyCollection(); internal bool HadErrors { get; set; } + internal bool IsConfiguration { get; private set; } internal bool PostParseChecksPerformed { get; set; } @@ -1227,7 +1248,7 @@ internal string ToStringForSerialization(Tuple, stri string script = this.ToString(); var newScript = new StringBuilder(); - foreach (var ast in astElements.OrderBy(ast => ast.Extent.StartOffset)) + foreach (var ast in astElements.OrderBy(static ast => ast.Extent.StartOffset)) { int astStartOffset = ast.Extent.StartOffset - indexOffset; int astEndOffset = ast.Extent.EndOffset - indexOffset; @@ -1414,7 +1435,7 @@ IEnumerable IParameterMetadataProvider.GetExperimentalAtt } } - ExperimentalAttribute GetExpAttributeHelper(AttributeAst attributeAst) + static ExperimentalAttribute GetExpAttributeHelper(AttributeAst attributeAst) { AttributeAst potentialExpAttr = null; string expAttrTypeName = typeof(ExperimentalAttribute).FullName; @@ -1545,7 +1566,7 @@ bool IParameterMetadataProvider.UsesCmdletBinding() if (ParamBlock != null) { - usesCmdletBinding = this.ParamBlock.Attributes.Any(attribute => typeof(CmdletBindingAttribute) == attribute.TypeName.GetReflectionAttributeType()); + usesCmdletBinding = this.ParamBlock.Attributes.Any(static attribute => typeof(CmdletBindingAttribute) == attribute.TypeName.GetReflectionAttributeType()); if (!usesCmdletBinding) { usesCmdletBinding = ParamBlockAst.UsesCmdletBinding(ParamBlock.Parameters); @@ -1581,7 +1602,7 @@ internal PipelineAst GetSimplePipeline(bool allowMultiplePipelines, out string e } // Make sure all statements are pipelines. - if (EndBlock.Statements.Any(ast => !(ast is PipelineAst))) + if (EndBlock.Statements.Any(ast => ast is not PipelineAst)) { errorId = "CanOnlyConvertOnePipeline"; errorMsg = AutomationExceptions.CanOnlyConvertOnePipeline; @@ -1749,7 +1770,7 @@ public class NamedBlockAst : Ast /// /// /// If is not one of the valid kinds for a named block, - /// or if is true and is neither + /// or if is and is neither /// nor . /// public NamedBlockAst(IScriptExtent extent, TokenKind blockName, StatementBlockAst statementBlock, bool unnamed) @@ -2375,7 +2396,7 @@ internal override AstVisitAction InternalVisit(AstVisitor visitor) /// public class StatementBlockAst : Ast { - private static ReadOnlyCollection s_emptyStatementCollection = Utils.EmptyReadOnlyCollection(); + private static readonly ReadOnlyCollection s_emptyStatementCollection = Utils.EmptyReadOnlyCollection(); /// /// Construct a statement block. @@ -2656,7 +2677,7 @@ public override Ast Copy() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitTypeDefinition(this) : null; + return visitor2?.VisitTypeDefinition(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -2904,7 +2925,7 @@ public override Ast Copy() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitUsingStatement(this) : null; + return visitor2?.VisitUsingStatement(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -3132,7 +3153,7 @@ internal override string GetTooltip() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitPropertyMember(this) : null; + return visitor2?.VisitPropertyMember(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -3352,7 +3373,7 @@ internal override string GetTooltip() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitFunctionMember(this) : null; + return visitor2?.VisitFunctionMember(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -3444,7 +3465,7 @@ internal bool IsReturnTypeVoid() if (ReturnType == null) return true; var typeName = ReturnType.TypeName as TypeName; - return typeName == null ? false : typeName.IsType(typeof(void)); + return typeName != null && typeName.IsType(typeof(void)); } internal Type GetReturnType() @@ -3732,7 +3753,7 @@ internal string GetParamTextFromParameterList(Tuple, Diagnostics.Assert( usingVariablesTuple.Item1 != null && usingVariablesTuple.Item1.Count > 0 && !string.IsNullOrEmpty(usingVariablesTuple.Item2), "Caller makes sure the value passed in is not null or empty."); - orderedUsingVars = usingVariablesTuple.Item1.OrderBy(varAst => varAst.Extent.StartOffset).GetEnumerator(); + orderedUsingVars = usingVariablesTuple.Item1.OrderBy(static varAst => varAst.Extent.StartOffset).GetEnumerator(); additionalNewUsingParams = usingVariablesTuple.Item2; } @@ -3756,7 +3777,7 @@ internal string GetParamTextFromParameterList(Tuple, separator = ", "; } - sb.Append(")"); + sb.Append(')'); sb.Append(Environment.NewLine); return sb.ToString(); @@ -3829,7 +3850,7 @@ IEnumerable IParameterMetadataProvider.GetExperimentalAtt ReadOnlyCollection IParameterMetadataProvider.Parameters { - get { return Parameters ?? (Body.ParamBlock != null ? Body.ParamBlock.Parameters : null); } + get { return Parameters ?? (Body.ParamBlock?.Parameters); } } PowerShell IParameterMetadataProvider.GetPowerShell(ExecutionContext context, Dictionary variables, bool isTrustedInput, @@ -4019,7 +4040,7 @@ public DataStatementAst(IScriptExtent extent, { this.CommandsAllowed = new ReadOnlyCollection(commandsAllowed.ToArray()); SetParents(CommandsAllowed); - this.HasNonConstantAllowedCommand = CommandsAllowed.Any(ast => !(ast is StringConstantExpressionAst)); + this.HasNonConstantAllowedCommand = CommandsAllowed.Any(static ast => ast is not StringConstantExpressionAst); } else { @@ -5879,7 +5900,7 @@ public CommandAst(IScriptExtent extent, public string GetCommandName() { var name = CommandElements[0] as StringConstantExpressionAst; - return name != null ? name.Value : null; + return name?.Value; } /// @@ -6422,7 +6443,7 @@ public override Ast Copy() { LCurlyToken = this.LCurlyToken, ConfigurationToken = this.ConfigurationToken, - CustomAttributes = this.CustomAttributes == null ? null : this.CustomAttributes.Select(e => (AttributeAst)e.Copy()) + CustomAttributes = this.CustomAttributes?.Select(static e => (AttributeAst)e.Copy()) }; } @@ -6431,7 +6452,7 @@ public override Ast Copy() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitConfigurationDefinition(this) : null; + return visitor2?.VisitConfigurationDefinition(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -6463,7 +6484,9 @@ internal override AstVisitAction InternalVisit(AstVisitor visitor) #region Internal methods/properties internal Token LCurlyToken { get; set; } + internal Token ConfigurationToken { get; set; } + internal IEnumerable CustomAttributes { get; set; } /// @@ -6521,7 +6544,7 @@ internal PipelineAst GenerateSetItemPipelineAst() cea.Add(new CommandParameterAst(PositionUtilities.EmptyExtent, "ResourceModuleTuplesToImport", new ConstantExpressionAst(PositionUtilities.EmptyExtent, resourceModulePairsToImport), PositionUtilities.EmptyExtent)); var scriptBlockBody = new ScriptBlockAst(Body.Extent, - CustomAttributes == null ? null : CustomAttributes.Select(att => (AttributeAst)att.Copy()).ToList(), + CustomAttributes?.Select(static att => (AttributeAst)att.Copy()).ToList(), null, new StatementBlockAst(Body.Extent, resourceBody, null), false, false); @@ -6554,9 +6577,9 @@ internal PipelineAst GenerateSetItemPipelineAst() // ) // var attribAsts = - ConfigurationBuildInParameterAttribAsts.Select(attribAst => (AttributeAst)attribAst.Copy()).ToList(); + ConfigurationBuildInParameterAttribAsts.Select(static attribAst => (AttributeAst)attribAst.Copy()).ToList(); - var paramAsts = ConfigurationBuildInParameters.Select(paramAst => (ParameterAst)paramAst.Copy()).ToList(); + var paramAsts = ConfigurationBuildInParameters.Select(static paramAst => (ParameterAst)paramAst.Copy()).ToList(); // the parameters defined in the configuration keyword will be combined with above parameters // it will be used to construct $ArgsToBody in the set-item created function boby using below statement @@ -6567,7 +6590,7 @@ internal PipelineAst GenerateSetItemPipelineAst() // $Outputpath = $psboundparameters[""Outputpath""] if (Body.ScriptBlock.ParamBlock != null) { - paramAsts.AddRange(Body.ScriptBlock.ParamBlock.Parameters.Select(parameterAst => (ParameterAst)parameterAst.Copy())); + paramAsts.AddRange(Body.ScriptBlock.ParamBlock.Parameters.Select(static parameterAst => (ParameterAst)parameterAst.Copy())); } var paramBlockAst = new ParamBlockAst(this.Extent, attribAsts, paramAsts); @@ -6575,12 +6598,12 @@ internal PipelineAst GenerateSetItemPipelineAst() var cmdAst = new CommandAst(this.Extent, cea, TokenKind.Unknown, null); var pipeLineAst = new PipelineAst(this.Extent, cmdAst, background: false); - var funcStatements = ConfigurationExtraParameterStatements.Select(statement => (StatementAst)statement.Copy()).ToList(); + var funcStatements = ConfigurationExtraParameterStatements.Select(static statement => (StatementAst)statement.Copy()).ToList(); funcStatements.Add(pipeLineAst); var statmentBlockAst = new StatementBlockAst(this.Extent, funcStatements, null); var funcBody = new ScriptBlockAst(Body.Extent, - CustomAttributes == null ? null : CustomAttributes.Select(att => (AttributeAst)att.Copy()).ToList(), + CustomAttributes?.Select(static att => (AttributeAst)att.Copy()).ToList(), paramBlockAst, statmentBlockAst, false, true); var funcBodyExp = new ScriptBlockExpressionAst(this.Extent, funcBody); @@ -6898,7 +6921,7 @@ public override Ast Copy() internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitDynamicKeywordStatement(this) : null; + return visitor2?.VisitDynamicKeywordStatement(this); } internal override AstVisitAction InternalVisit(AstVisitor visitor) @@ -6945,10 +6968,15 @@ internal DynamicKeyword Keyword private DynamicKeyword _keyword; internal Token LCurly { get; set; } + internal Token FunctionName { get; set; } + internal ExpressionAst InstanceName { get; set; } + internal ExpressionAst OriginalInstanceName { get; set; } + internal ExpressionAst BodyExpression { get; set; } + internal string ElementName { get; set; } private PipelineAst _commandCallPipelineAst; @@ -7213,8 +7241,7 @@ internal virtual bool ShouldPreserveOutputInCaseOfException() PSTraceSource.NewInvalidOperationException(); } - var commandExpr = this.Parent as CommandExpressionAst; - if (commandExpr == null) + if (!(this.Parent is CommandExpressionAst commandExpr)) { return false; } @@ -7726,8 +7753,7 @@ Expression IAssignableValue.SetValue(Compiler compiler, Expression rhs) var attributes = GetAttributes(); var assignableValue = GetActualAssignableAst().GetAssignableValue(); - var variableExpr = assignableValue as VariableExpressionAst; - if (variableExpr == null) + if (!(assignableValue is VariableExpressionAst variableExpr)) { return assignableValue.SetValue(compiler, Compiler.ConvertValue(rhs, attributes)); } @@ -8105,13 +8131,14 @@ internal override AstVisitAction InternalVisit(AstVisitor visitor) internal override object Accept(ICustomAstVisitor visitor) { var visitor2 = visitor as ICustomAstVisitor2; - return visitor2 != null ? visitor2.VisitBaseCtorInvokeMemberExpression(this) : null; + return visitor2?.VisitBaseCtorInvokeMemberExpression(this); } } /// /// The name and attributes of a type. /// +#nullable enable public interface ITypeName { /// @@ -8127,7 +8154,7 @@ public interface ITypeName /// /// The name of the assembly, if specified, otherwise null. /// - string AssemblyName { get; } + string? AssemblyName { get; } /// /// Returns true if the type names an array, false otherwise. @@ -8142,25 +8169,28 @@ public interface ITypeName /// /// Returns the that this typename represents, if such a type exists, null otherwise. /// - Type GetReflectionType(); + Type? GetReflectionType(); /// /// Assuming the typename is an attribute, returns the that this typename represents. /// By convention, the typename may omit the suffix "Attribute". Lookup will attempt to resolve the type as is, /// and if that fails, the suffix "Attribute" will be appended. /// - Type GetReflectionAttributeType(); + Type? GetReflectionAttributeType(); /// /// The extent of the typename. /// IScriptExtent Extent { get; } } +#nullable restore +#nullable enable internal interface ISupportsTypeCaching { - Type CachedType { get; set; } + Type? CachedType { get; set; } } +#nullable restore /// /// A simple type that is not an array or does not have generic arguments. @@ -8371,8 +8401,7 @@ public override string ToString() /// public override bool Equals(object obj) { - var other = obj as TypeName; - if (other == null) + if (!(obj is TypeName other)) return false; if (!_name.Equals(other._name, StringComparison.OrdinalIgnoreCase)) @@ -8690,8 +8719,7 @@ public override string ToString() /// public override bool Equals(object obj) { - var other = obj as GenericTypeName; - if (other == null) + if (!(obj is GenericTypeName other)) return false; if (!TypeName.Equals(other.TypeName)) @@ -8916,8 +8944,7 @@ public override string ToString() /// public override bool Equals(object obj) { - var other = obj as ArrayTypeName; - if (other == null) + if (!(obj is ArrayTypeName other)) return false; return ElementType.Equals(other.ElementType) && Rank == other.Rank; @@ -9018,8 +9045,7 @@ public override string ToString() /// public override bool Equals(object obj) { - var other = obj as ReflectionTypeName; - if (other == null) + if (!(obj is ReflectionTypeName other)) return false; return _type == other._type; } @@ -9239,6 +9265,7 @@ internal override AstVisitAction InternalVisit(AstVisitor visitor) internal int TupleIndex { get; set; } = VariableAnalysis.Unanalyzed; internal bool Automatic { get; set; } + internal bool Assigned { get; set; } IAssignableValue ISupportsAssignment.GetAssignableValue() diff --git a/src/System.Management.Automation/engine/parser/tokenizer.cs b/src/System.Management.Automation/engine/parser/tokenizer.cs index f896aeda376..161e53cef0c 100644 --- a/src/System.Management.Automation/engine/parser/tokenizer.cs +++ b/src/System.Management.Automation/engine/parser/tokenizer.cs @@ -12,6 +12,8 @@ using System.Text; using Microsoft.PowerShell.Commands; +using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.DSC; using Microsoft.PowerShell.DesiredStateConfiguration.Internal; namespace System.Management.Automation.Language @@ -41,7 +43,7 @@ public enum DynamicKeywordNameMode /// Name may be optionally present, expression or bare word. /// OptionalName = 4, - }; + } /// /// Defines the body mode for a dynamic keyword. It can be a scriptblock, hashtable or command which means no body. @@ -77,8 +79,7 @@ private static Dictionary DynamicKeywords { get { - return t_dynamicKeywords ?? - (t_dynamicKeywords = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return t_dynamicKeywords ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } } @@ -92,8 +93,7 @@ private static Stack> DynamicKeywordsStack { get { - return t_dynamicKeywordsStack ?? - (t_dynamicKeywordsStack = new Stack>()); + return t_dynamicKeywordsStack ??= new Stack>(); } } @@ -320,8 +320,7 @@ public Dictionary Properties { get { - return _properties ?? - (_properties = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return _properties ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } } @@ -334,8 +333,7 @@ public Dictionary Parameters { get { - return _parameters ?? - (_parameters = new Dictionary(StringComparer.OrdinalIgnoreCase)); + return _parameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } } @@ -365,7 +363,15 @@ internal static bool IsMetaDSCResource(this DynamicKeyword keyword) string implementingModule = keyword.ImplementingModule; if (implementingModule != null) { - return implementingModule.Equals(DscClassCache.DefaultModuleInfoForMetaConfigResource.Item1, StringComparison.OrdinalIgnoreCase); + ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem(); + if (dscSubsystem != null) + { + dscSubsystem.IsDefaultModuleNameForMetaConfigResource(implementingModule); + } + else + { + return implementingModule.Equals(DscClassCache.DefaultModuleInfoForMetaConfigResource.Item1, StringComparison.OrdinalIgnoreCase); + } } return false; @@ -377,7 +383,7 @@ internal static bool IsCompatibleWithConfigurationType(this DynamicKeyword keywo (ConfigurationType != ConfigurationType.Meta && !keyword.IsMetaDSCResource())); } - private static Dictionary> s_excludeKeywords = new Dictionary>(StringComparer.OrdinalIgnoreCase) + private static readonly Dictionary> s_excludeKeywords = new Dictionary>(StringComparer.OrdinalIgnoreCase) { {@"Node", new List {@"Node"}}, }; @@ -426,7 +432,7 @@ public class DynamicKeywordProperty /// public List Attributes { - get { return _attributes ?? (_attributes = new List()); } + get { return _attributes ??= new List(); } } private List _attributes; @@ -436,7 +442,7 @@ public List Attributes /// public List Values { - get { return _values ?? (_values = new List()); } + get { return _values ??= new List(); } } private List _values; @@ -446,7 +452,7 @@ public List Values /// public Dictionary ValueMap { - get { return _valueMap ?? (_valueMap = new Dictionary(StringComparer.OrdinalIgnoreCase)); } + get { return _valueMap ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } } private Dictionary _valueMap; @@ -633,18 +639,18 @@ private static readonly Dictionary s_operatorTable }; private static readonly TokenKind[] s_keywordTokenKind = new TokenKind[] { - /*1*/ TokenKind.ElseIf, TokenKind.If, TokenKind.Else, TokenKind.Switch, /*1*/ - /*2*/ TokenKind.Foreach, TokenKind.From, TokenKind.In, TokenKind.For, /*2*/ - /*3*/ TokenKind.While, TokenKind.Until, TokenKind.Do, TokenKind.Try, /*3*/ - /*4*/ TokenKind.Catch, TokenKind.Finally, TokenKind.Trap, TokenKind.Data, /*4*/ - /*5*/ TokenKind.Return, TokenKind.Continue, TokenKind.Break, TokenKind.Exit, /*5*/ - /*6*/ TokenKind.Throw, TokenKind.Begin, TokenKind.Process, TokenKind.End, /*6*/ - /*7*/ TokenKind.Dynamicparam, TokenKind.Function, TokenKind.Filter, TokenKind.Param, /*7*/ - /*8*/ TokenKind.Class, TokenKind.Define, TokenKind.Var, TokenKind.Using, /*8*/ - /*9*/ TokenKind.Workflow, TokenKind.Parallel, TokenKind.Sequence, TokenKind.InlineScript, /*9*/ - /*A*/ TokenKind.Configuration, TokenKind.Public, TokenKind.Private, TokenKind.Static, /*A*/ - /*B*/ TokenKind.Interface, TokenKind.Enum, TokenKind.Namespace,TokenKind.Module, /*B*/ - /*C*/ TokenKind.Type, TokenKind.Assembly, TokenKind.Command, TokenKind.Hidden, /*C*/ + /*1*/ TokenKind.ElseIf, TokenKind.If, TokenKind.Else, TokenKind.Switch, /*1*/ + /*2*/ TokenKind.Foreach, TokenKind.From, TokenKind.In, TokenKind.For, /*2*/ + /*3*/ TokenKind.While, TokenKind.Until, TokenKind.Do, TokenKind.Try, /*3*/ + /*4*/ TokenKind.Catch, TokenKind.Finally, TokenKind.Trap, TokenKind.Data, /*4*/ + /*5*/ TokenKind.Return, TokenKind.Continue, TokenKind.Break, TokenKind.Exit, /*5*/ + /*6*/ TokenKind.Throw, TokenKind.Begin, TokenKind.Process, TokenKind.End, /*6*/ + /*7*/ TokenKind.Dynamicparam, TokenKind.Function, TokenKind.Filter, TokenKind.Param, /*7*/ + /*8*/ TokenKind.Class, TokenKind.Define, TokenKind.Var, TokenKind.Using, /*8*/ + /*9*/ TokenKind.Workflow, TokenKind.Parallel, TokenKind.Sequence, TokenKind.InlineScript, /*9*/ + /*A*/ TokenKind.Configuration, TokenKind.Public, TokenKind.Private, TokenKind.Static, /*A*/ + /*B*/ TokenKind.Interface, TokenKind.Enum, TokenKind.Namespace, TokenKind.Module, /*B*/ + /*C*/ TokenKind.Type, TokenKind.Assembly, TokenKind.Command, TokenKind.Hidden, /*C*/ /*D*/ TokenKind.Base, TokenKind.Default, /*D*/ }; @@ -708,7 +714,7 @@ static Tokenizer() // The hash we compute is intentionally dumb, we want collisions to catch similar strings, // so we just sum up the characters. const string beginSig = "sig#beginsignatureblock"; - beginSig.Aggregate(0, (current, t) => current + t); + beginSig.Aggregate(0, static (current, t) => current + t); // Spot check to help make sure the arrays are in sync Diagnostics.Assert(s_keywordTable["using"] == TokenKind.Using, "Keyword table out of sync w/ enum"); @@ -721,6 +727,7 @@ internal Tokenizer(Parser parser) } internal TokenizerMode Mode { get; set; } + internal bool AllowSignedNumbers { get; set; } // TODO: use auto-properties when making 'ternary operator' an official feature. @@ -733,8 +740,11 @@ internal bool ForceEndNumberOnTernaryOpChars } internal bool WantSimpleName { get; set; } + internal bool InWorkflowContext { get; set; } + internal List TokenList { get; set; } + internal Token FirstToken { get; private set; } internal Token LastToken { get; private set; } @@ -826,7 +836,7 @@ internal void FinishNestedScan(TokenizerState ts) private char GetChar() { - Diagnostics.Assert(0 <= _currentIndex, "GetChar reading before start of input."); + Diagnostics.Assert(_currentIndex >= 0, "GetChar reading before start of input."); Diagnostics.Assert(_currentIndex <= _script.Length + 1, "GetChar reading after end of input."); // Increment _currentIndex, even if it goes over the Length so callers can call UngetChar to unget EOF. @@ -848,7 +858,7 @@ private void UngetChar() private char PeekChar() { - Diagnostics.Assert(0 <= _currentIndex && _currentIndex <= _script.Length, "PeekChar out of range."); + Diagnostics.Assert(_currentIndex >= 0 && _currentIndex <= _script.Length, "PeekChar out of range."); if (_currentIndex == _script.Length) { @@ -1045,7 +1055,7 @@ internal void Resync(int start) { _currentIndex = _script.Length + 1; } - else if (0 > _currentIndex) + else if (_currentIndex < 0) { _currentIndex = 0; } @@ -1269,7 +1279,7 @@ private StringToken NewStringExpandableToken(string value, string formatString, } else if ((flags & TokenFlags.TokenInError) == 0) { - if (nestedTokens.Any(tok => tok.HasError)) + if (nestedTokens.Any(static tok => tok.HasError)) { flags |= TokenFlags.TokenInError; } @@ -2110,7 +2120,7 @@ private void HandleRequiresParameter(CommandParameterAst parameter, return; } - if (argumentValue is string || !(argumentValue is IEnumerable)) + if (argumentValue is string || argumentValue is not IEnumerable) { requiredEditions = HandleRequiresPSEditionArgument(argumentAst, argumentValue, ref requiredEditions); } @@ -2165,7 +2175,7 @@ private void HandleRequiresParameter(CommandParameterAst parameter, } else if (assemblyToken.StartsWith(parameter.ParameterName, StringComparison.OrdinalIgnoreCase)) { - if (argumentValue is string || !(argumentValue is IEnumerable)) + if (argumentValue is string || argumentValue is not IEnumerable) { requiredAssemblies = HandleRequiresAssemblyArgument(argumentAst, argumentValue, requiredAssemblies); } @@ -4563,7 +4573,7 @@ internal string GetAssemblyNameSpec() if (PeekChar() == '=') { _tokenStart = _currentIndex; - sb.Append("="); + sb.Append('='); SkipChar(); NewToken(TokenKind.Equals); ScanAssemblyNameSpecToken(sb); diff --git a/src/System.Management.Automation/engine/pipeline.cs b/src/System.Management.Automation/engine/pipeline.cs index 695a0b38dc8..58ea07de6ae 100644 --- a/src/System.Management.Automation/engine/pipeline.cs +++ b/src/System.Management.Automation/engine/pipeline.cs @@ -91,14 +91,6 @@ private void Dispose(bool disposing) _disposed = true; } - /// - /// Finalizer for class PipelineProcessor. - /// - ~PipelineProcessor() - { - Dispose(false); - } - #endregion IDispose #region Execution Logging @@ -174,7 +166,7 @@ internal void LogExecutionException(Exception exception) Log(message, null, PipelineExecutionStatus.Error); } - private string GetCommand(InvocationInfo invocationInfo) + private static string GetCommand(InvocationInfo invocationInfo) { if (invocationInfo == null) return string.Empty; @@ -187,7 +179,7 @@ private string GetCommand(InvocationInfo invocationInfo) return string.Empty; } - private string GetCommand(Exception exception) + private static string GetCommand(Exception exception) { IContainsErrorRecord icer = exception as IContainsErrorRecord; if (icer != null && icer.ErrorRecord != null) @@ -228,44 +220,33 @@ private void Log(string logElement, InvocationInfo invocation, PipelineExecution } } - if (!string.IsNullOrEmpty(logElement)) + if (_needToLog && !string.IsNullOrEmpty(logElement)) { + _eventLogBuffer ??= new List(); _eventLogBuffer.Add(logElement); } } - internal void LogToEventLog() + private void LogToEventLog() { - if (NeedToLog()) + // We check to see if there is anything in the buffer before we flush it. + // Flushing the empty buffer causes a measurable performance degradation. + if (_commands?.Count > 0 && _eventLogBuffer?.Count > 0) { - // We check to see if the command is needs writing (or if there is anything in the buffer) - // before we flush it. Flushing the empty buffer causes a measurable performance degradation. - if (_commands == null || _commands.Count == 0 || _eventLogBuffer.Count == 0) - return; - - MshLog.LogPipelineExecutionDetailEvent(_commands[0].Command.Context, - _eventLogBuffer, - _commands[0].Command.MyInvocation); - } - } - - private bool NeedToLog() - { - if (_commands == null) - return false; - - foreach (CommandProcessorBase commandProcessor in _commands) - { - MshCommandRuntime cmdRuntime = commandProcessor.Command.commandRuntime as MshCommandRuntime; - - if (cmdRuntime != null && cmdRuntime.LogPipelineExecutionDetail) - return true; + InternalCommand firstCmd = _commands[0].Command; + MshLog.LogPipelineExecutionDetailEvent( + firstCmd.Context, + _eventLogBuffer, + firstCmd.MyInvocation); } - return false; + // Clear the log buffer after writing the event. + _eventLogBuffer?.Clear(); } - private List _eventLogBuffer = new List(); + private bool _needToLog = false; + private List _eventLogBuffer; + #endregion #region public_methods @@ -281,7 +262,7 @@ private bool NeedToLog() internal int Add(CommandProcessorBase commandProcessor) { commandProcessor.CommandRuntime.PipelineProcessor = this; - return AddCommand(commandProcessor, _commands.Count, false); + return AddCommand(commandProcessor, _commands.Count, readErrorQueue: false); } internal void AddRedirectionPipe(PipelineProcessor pipelineProcessor) @@ -314,7 +295,7 @@ internal void AddRedirectionPipe(PipelineProcessor pipelineProcessor) /// PipeAlreadyTaken: the downstream pipe of command /// is already taken /// - internal int AddCommand(CommandProcessorBase commandProcessor, int readFromCommand, bool readErrorQueue) + private int AddCommand(CommandProcessorBase commandProcessor, int readFromCommand, bool readErrorQueue) { if (commandProcessor == null) { @@ -344,9 +325,9 @@ internal int AddCommand(CommandProcessorBase commandProcessor, int readFromComma PipelineStrings.CommandProcessorAlreadyUsed); } - if (0 == _commands.Count) + if (_commands.Count == 0) { - if (0 != readFromCommand) + if (readFromCommand != 0) { // "First command cannot have input" throw PSTraceSource.NewArgumentException( @@ -420,6 +401,9 @@ internal int AddCommand(CommandProcessorBase commandProcessor, int readFromComma _commands.Add(commandProcessor); + // We will log event(s) about the pipeline execution details if any command in the pipeline requests that. + _needToLog |= commandProcessor.CommandRuntime.LogPipelineExecutionDetail; + // We give the Command a pointer back to the // PipelineProcessor so that it can check whether the // command has been stopped. @@ -945,7 +929,7 @@ private void Start(bool incomingStream) if (_executionStarted) return; - if (_commands == null || 0 == _commands.Count) + if (_commands == null || _commands.Count == 0) { throw PSTraceSource.NewInvalidOperationException( PipelineStrings.PipelineExecuteRequiresAtLeastOneCommand); @@ -1384,7 +1368,7 @@ private void DisposeCommands() _redirectionPipes = null; } - private object _stopReasonLock = new object(); + private readonly object _stopReasonLock = new object(); /// /// Makes an internal note of the exception, but only if this is /// the first error. @@ -1475,7 +1459,10 @@ internal void ForgetFailure() /// internal PipelineReader ExternalInput { - get { return _externalInputPipe; } + get + { + return _externalInputPipe; + } set { @@ -1501,7 +1488,10 @@ internal PipelineReader ExternalInput /// internal PipelineWriter ExternalSuccessOutput { - get { return _externalSuccessOutput; } + get + { + return _externalSuccessOutput; + } set { @@ -1528,7 +1518,10 @@ internal PipelineWriter ExternalSuccessOutput /// internal PipelineWriter ExternalErrorOutput { - get { return _externalErrorOutput; } + get + { + return _externalErrorOutput; + } set { @@ -1575,7 +1568,10 @@ internal LocalPipeline LocalPipeline /// internal SessionStateScope ExecutionScope { - get { return _executionScope; } + get + { + return _executionScope; + } set { @@ -1597,4 +1593,3 @@ internal enum PipelineExecutionStatus } } } - diff --git a/src/System.Management.Automation/engine/regex.cs b/src/System.Management.Automation/engine/regex.cs index c867f355158..dbdbcb41354 100644 --- a/src/System.Management.Automation/engine/regex.cs +++ b/src/System.Management.Automation/engine/regex.cs @@ -43,7 +43,7 @@ public enum WildcardOptions /// Specifies culture-invariant matching. /// CultureInvariant = 4 - }; + } /// /// Represents a wildcard pattern. @@ -184,7 +184,7 @@ StringComparison GetStringComparison() if (index == Pattern.Length - 1 && Pattern[index] == '*') { // No special characters present in the pattern before last position and last character is asterisk. - var patternWithoutAsterisk = Pattern.AsMemory().Slice(0, index); + var patternWithoutAsterisk = Pattern.AsMemory(0, index); _isMatch = str => str.AsSpan().StartsWith(patternWithoutAsterisk.Span, GetStringComparison()); return; } @@ -325,7 +325,7 @@ public static bool ContainsWildcardCharacters(string pattern) /// converted to their unescaped form. /// /// - /// If is null. + /// If is null. /// public static string Unescape(string pattern) { @@ -456,7 +456,7 @@ internal WildcardPatternException(ErrorRecord errorRecord) } [NonSerialized] - private ErrorRecord _errorRecord; + private readonly ErrorRecord _errorRecord; /// /// Constructs an instance of the WildcardPatternException object. @@ -729,7 +729,7 @@ internal static WildcardPatternException NewWildcardPatternException(string inva return e; } - }; + } /// /// Convert a string with wild cards into its equivalent regex. @@ -1001,7 +1001,7 @@ internal bool IsMatch(string str) } } - private class PatternPositionsVisitor : IDisposable + private sealed class PatternPositionsVisitor : IDisposable { private readonly int _lengthOfPattern; @@ -1122,7 +1122,7 @@ public override void ProcessEndOfString( } } - private class LiteralCharacterElement : QuestionMarkElement + private sealed class LiteralCharacterElement : QuestionMarkElement { private readonly char _literalCharacter; @@ -1148,7 +1148,7 @@ public override void ProcessStringCharacter( } } - private class BracketExpressionElement : QuestionMarkElement + private sealed class BracketExpressionElement : QuestionMarkElement { private readonly Regex _regex; @@ -1173,7 +1173,7 @@ public override void ProcessStringCharacter( } } - private class AsterixElement : PatternElement + private sealed class AsterixElement : PatternElement { public override void ProcessStringCharacter( char currentStringCharacter, @@ -1197,7 +1197,7 @@ public override void ProcessEndOfString( } } - private class MyWildcardPatternParser : WildcardPatternParser + private sealed class MyWildcardPatternParser : WildcardPatternParser { private readonly List _patternElements = new List(); private CharacterNormalizer _characterNormalizer; @@ -1264,17 +1264,17 @@ protected override void EndBracketExpression() } } - private struct CharacterNormalizer + private readonly struct CharacterNormalizer { private readonly CultureInfo _cultureInfo; private readonly bool _caseInsensitive; public CharacterNormalizer(WildcardOptions options) { - _caseInsensitive = 0 != (options & WildcardOptions.IgnoreCase); + _caseInsensitive = (options & WildcardOptions.IgnoreCase) != 0; if (_caseInsensitive) { - _cultureInfo = 0 != (options & WildcardOptions.CultureInvariant) + _cultureInfo = (options & WildcardOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture; } @@ -1348,4 +1348,3 @@ internal static string Parse(WildcardPattern wildcardPattern) } } } - diff --git a/src/System.Management.Automation/engine/remoting/client/ClientMethodExecutor.cs b/src/System.Management.Automation/engine/remoting/client/ClientMethodExecutor.cs index ba4e08c8f6f..8d8ba3f7e64 100644 --- a/src/System.Management.Automation/engine/remoting/client/ClientMethodExecutor.cs +++ b/src/System.Management.Automation/engine/remoting/client/ClientMethodExecutor.cs @@ -13,32 +13,32 @@ namespace System.Management.Automation.Remoting /// /// Executes methods on the client. /// - internal class ClientMethodExecutor + internal sealed class ClientMethodExecutor { /// /// Transport manager. /// - private BaseClientTransportManager _transportManager; + private readonly BaseClientTransportManager _transportManager; /// /// Client host. /// - private PSHost _clientHost; + private readonly PSHost _clientHost; /// /// Client runspace pool id. /// - private Guid _clientRunspacePoolId; + private readonly Guid _clientRunspacePoolId; /// /// Client power shell id. /// - private Guid _clientPowerShellId; + private readonly Guid _clientPowerShellId; /// /// Remote host call. /// - private RemoteHostCall _remoteHostCall; + private readonly RemoteHostCall _remoteHostCall; /// /// Remote host call. @@ -98,8 +98,7 @@ internal static void Dispatch( if (hostPrivateData != null) { PSNoteProperty allowSetShouldExit = hostPrivateData.Properties["AllowSetShouldExitFromRemote"] as PSNoteProperty; - hostAllowSetShouldExit = (allowSetShouldExit != null && allowSetShouldExit.Value is bool) ? - (bool)allowSetShouldExit.Value : false; + hostAllowSetShouldExit = allowSetShouldExit != null && allowSetShouldExit.Value is bool && (bool)allowSetShouldExit.Value; } } @@ -132,10 +131,9 @@ internal static void Dispatch( /// /// Is runspace pushed. /// - private bool IsRunspacePushed(PSHost host) + private static bool IsRunspacePushed(PSHost host) { - IHostSupportsInteractiveSession host2 = host as IHostSupportsInteractiveSession; - if (host2 == null) { return false; } + if (!(host is IHostSupportsInteractiveSession host2)) { return false; } // IsRunspacePushed can throw (not implemented exception) try @@ -157,7 +155,7 @@ internal void Execute(PSDataCollectionStream errorStream) // If error-stream is null or we are in pushed-runspace - then write error directly to console. if (errorStream == null || IsRunspacePushed(_clientHost)) { - writeErrorAction = delegate (ErrorRecord errorRecord) + writeErrorAction = (ErrorRecord errorRecord) => { try { @@ -176,10 +174,7 @@ internal void Execute(PSDataCollectionStream errorStream) // Otherwise write it to error-stream. else { - writeErrorAction = delegate (ErrorRecord errorRecord) - { - errorStream.Write(errorRecord); - }; + writeErrorAction = (ErrorRecord errorRecord) => errorStream.Write(errorRecord); } this.Execute(writeErrorAction); diff --git a/src/System.Management.Automation/engine/remoting/client/ClientRemotePowerShell.cs b/src/System.Management.Automation/engine/remoting/client/ClientRemotePowerShell.cs index 4f966f5bdba..4ea06ea2feb 100644 --- a/src/System.Management.Automation/engine/remoting/client/ClientRemotePowerShell.cs +++ b/src/System.Management.Automation/engine/remoting/client/ClientRemotePowerShell.cs @@ -20,7 +20,7 @@ internal class ClientRemotePowerShell : IDisposable #region Tracer [TraceSourceAttribute("CRPS", "ClientRemotePowerShell")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("CRPS", "ClientRemotePowerShellBase"); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("CRPS", "ClientRemotePowerShellBase"); #endregion Tracer @@ -645,7 +645,7 @@ private void HandleCloseCompleted(object sender, EventArgs args) // If RemoteSessionStateEventArgs are provided then use them to set the // session close reason when setting finished state. RemoteSessionStateEventArgs sessionEventArgs = args as RemoteSessionStateEventArgs; - Exception closeReason = (sessionEventArgs != null) ? sessionEventArgs.SessionStateInfo.Reason : null; + Exception closeReason = sessionEventArgs?.SessionStateInfo.Reason; PSInvocationState finishedState = (shell.InvocationStateInfo.State == PSInvocationState.Disconnected) ? PSInvocationState.Failed : PSInvocationState.Stopped; @@ -663,7 +663,7 @@ private void HandleCloseCompleted(object sender, EventArgs args) } } - private bool IsFinished(PSInvocationState state) + private static bool IsFinished(PSInvocationState state) { return (state == PSInvocationState.Completed || state == PSInvocationState.Failed || @@ -929,7 +929,7 @@ private void HandleRobustConnectionNotification( /// datastructure handler. We cannot send the state back to the upper layers until /// close is completed from the datastructure/transport layer. /// - private Queue _stateInfoQueue = new Queue(); + private readonly Queue _stateInfoQueue = new Queue(); private PSConnectionRetryStatus _connectionRetryStatus = PSConnectionRetryStatus.None; @@ -977,7 +977,7 @@ internal enum PSConnectionRetryStatus AutoDisconnectStarting = 4, AutoDisconnectSucceeded = 5, InternalErrorAbort = 6 - }; + } /// /// PSConnectionRetryStatusEventArgs. diff --git a/src/System.Management.Automation/engine/remoting/client/Job.cs b/src/System.Management.Automation/engine/remoting/client/Job.cs index 1758da68258..6c7efa68f28 100644 --- a/src/System.Management.Automation/engine/remoting/client/Job.cs +++ b/src/System.Management.Automation/engine/remoting/client/Job.cs @@ -214,7 +214,7 @@ public JobState CurrentState /// State of job when exception was thrown. /// [NonSerialized] - private JobState _currState = 0; + private readonly JobState _currState = 0; } /// @@ -379,12 +379,13 @@ internal JobIdentifier(int id, Guid instanceId) /// /// Interface to expose a job debugger. /// +#nullable enable public interface IJobDebugger { /// /// Job Debugger. /// - Debugger Debugger + Debugger? Debugger { get; } @@ -398,6 +399,7 @@ bool IsAsync set; } } +#nullable restore /// /// Represents a command running in background. A job object can internally @@ -668,7 +670,10 @@ public IList ChildJobs /// public string PSJobTypeName { - get { return _jobTypeName; } + get + { + return _jobTypeName; + } protected internal set { @@ -750,12 +755,10 @@ private void WriteError(Cmdlet cmdlet, ErrorRecord errorRecord) private static Exception GetExceptionFromErrorRecord(ErrorRecord errorRecord) { - RuntimeException runtimeException = errorRecord.Exception as RuntimeException; - if (runtimeException == null) + if (!(errorRecord.Exception is RuntimeException runtimeException)) return null; - RemoteException remoteException = runtimeException as RemoteException; - if (remoteException == null) + if (!(runtimeException is RemoteException remoteException)) return null; PSPropertyInfo wasThrownFromThrow = @@ -787,12 +790,12 @@ internal void WriteError(ErrorRecord errorRecord, out Exception exceptionThrownO { this.Error.Add(errorRecord); this.InvokeCmdletMethodAndWaitForResults( - delegate (Cmdlet cmdlet) - { - this.WriteError(cmdlet, errorRecord); - return null; - }, - out exceptionThrownOnCmdletThread); + (Cmdlet cmdlet) => + { + this.WriteError(cmdlet, errorRecord); + return null; + }, + out exceptionThrownOnCmdletThread); } internal virtual void WriteWarning(string message) @@ -858,15 +861,15 @@ internal virtual void NonblockingShouldProcess( string caption) { InvokeCmdletMethodAndIgnoreResults( - delegate (Cmdlet cmdlet) - { - ShouldProcessReason throwAwayProcessReason; - cmdlet.ShouldProcess( - verboseDescription, - verboseWarning, - caption, - out throwAwayProcessReason); - }); + (Cmdlet cmdlet) => + { + ShouldProcessReason throwAwayProcessReason; + cmdlet.ShouldProcess( + verboseDescription, + verboseWarning, + caption, + out throwAwayProcessReason); + }); } internal virtual bool ShouldProcess( @@ -895,7 +898,7 @@ private void InvokeCmdletMethodAndIgnoreResults(Action invokeCmdletMetho object resultsLock = new object(); CmdletMethodInvoker methodInvoker = new CmdletMethodInvoker { - Action = delegate (Cmdlet cmdlet) { invokeCmdletMethod(cmdlet); return null; }, + Action = (Cmdlet cmdlet) => { invokeCmdletMethod(cmdlet); return null; }, Finished = null, SyncObject = resultsLock }; @@ -912,18 +915,18 @@ private T InvokeCmdletMethodAndWaitForResults(Func invokeCmdletMet using (var gotResultEvent = new ManualResetEventSlim(false)) { EventHandler stateChangedEventHandler = - delegate (object sender, JobStateEventArgs eventArgs) + (object sender, JobStateEventArgs eventArgs) => + { + if (IsFinishedState(eventArgs.JobStateInfo.State) || eventArgs.JobStateInfo.State == JobState.Stopping) { - if (IsFinishedState(eventArgs.JobStateInfo.State) || eventArgs.JobStateInfo.State == JobState.Stopping) + lock (resultsLock) { - lock (resultsLock) - { - closureSafeExceptionThrownOnCmdletThread = new OperationCanceledException(); - } - - gotResultEvent.Set(); + closureSafeExceptionThrownOnCmdletThread = new OperationCanceledException(); } - }; + + gotResultEvent.Set(); + } + }; this.StateChanged += stateChangedEventHandler; Interlocked.MemoryBarrier(); try @@ -1742,8 +1745,7 @@ internal class PSRemotingJob : Job [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal PSRemotingJob(string[] computerNames, List computerNameHelpers, string remoteCommand, string name) - : - this(computerNames, computerNameHelpers, remoteCommand, 0, name) + : this(computerNames, computerNameHelpers, remoteCommand, 0, name) { } /// @@ -1760,8 +1762,7 @@ internal PSRemotingJob(string[] computerNames, /// internal PSRemotingJob(PSSession[] remoteRunspaceInfos, List runspaceHelpers, string remoteCommand, string name) - : - this(remoteRunspaceInfos, runspaceHelpers, remoteCommand, 0, name) + : this(remoteRunspaceInfos, runspaceHelpers, remoteCommand, 0, name) { } /// @@ -1910,8 +1911,7 @@ internal List GetJobsForComputer(string computerName) foreach (Job j in ChildJobs) { - PSRemotingChildJob child = j as PSRemotingChildJob; - if (child == null) continue; + if (!(j is PSRemotingChildJob child)) continue; if (string.Equals(child.Runspace.ConnectionInfo.ComputerName, computerName, StringComparison.OrdinalIgnoreCase)) { @@ -1934,8 +1934,7 @@ internal List GetJobsForRunspace(PSSession runspace) foreach (Job j in ChildJobs) { - PSRemotingChildJob child = j as PSRemotingChildJob; - if (child == null) continue; + if (!(j is PSRemotingChildJob child)) continue; if (child.Runspace.InstanceId.Equals(runspace.InstanceId)) { returnJobList.Add(child); @@ -1958,8 +1957,7 @@ internal List GetJobsForOperation(IThrottleOperation operation) foreach (Job j in ChildJobs) { - PSRemotingChildJob child = j as PSRemotingChildJob; - if (child == null) continue; + if (!(j is PSRemotingChildJob child)) continue; if (child.Helper.Equals(helper)) { returnJobList.Add(child); @@ -2021,17 +2019,14 @@ internal void ConnectJob(Guid runspaceInstanceId) SubmitAndWaitForConnect(connectJobOperations); } - private void SubmitAndWaitForConnect(List connectJobOperations) + private static void SubmitAndWaitForConnect(List connectJobOperations) { using (ThrottleManager connectThrottleManager = new ThrottleManager()) { using (ManualResetEvent connectResult = new ManualResetEvent(false)) { EventHandler throttleCompleteEventHandler = - delegate (object sender, EventArgs eventArgs) - { - connectResult.Set(); - }; + (object sender, EventArgs eventArgs) => connectResult.Set(); connectThrottleManager.ThrottleComplete += throttleCompleteEventHandler; try @@ -2053,9 +2048,9 @@ private void SubmitAndWaitForConnect(List connectJobOperatio /// /// Simple throttle operation class for connecting jobs. /// - private class ConnectJobOperation : IThrottleOperation + private sealed class ConnectJobOperation : IThrottleOperation { - private PSRemotingChildJob _psRemoteChildJob; + private readonly PSRemotingChildJob _psRemoteChildJob; internal ConnectJobOperation(PSRemotingChildJob job) { @@ -2294,7 +2289,10 @@ public override string StatusMessage /// internal bool HideComputerName { - get { return _hideComputerName; } + get + { + return _hideComputerName; + } set { @@ -2585,7 +2583,7 @@ private string ConstructLocation() foreach (PSRemotingChildJob job in ChildJobs) { location.Append(job.Location); - location.Append(","); + location.Append(','); } location.Remove(location.Length - 1, 1); @@ -2666,7 +2664,7 @@ private void HandleJobUnblocked(object sender, EventArgs eventArgs) #region Private Members - private ThrottleManager _throttleManager = new ThrottleManager(); + private readonly ThrottleManager _throttleManager = new ThrottleManager(); private readonly object _syncObject = new object(); // sync object @@ -2942,7 +2940,10 @@ public override string Location /// internal bool HideComputerName { - get { return _hideComputerName; } + get + { + return _hideComputerName; + } set { @@ -2976,7 +2977,7 @@ internal override bool CanDisconnect get { RemoteRunspace remoteRS = Runspace as RemoteRunspace; - return (remoteRS != null) ? remoteRS.CanDisconnect : false; + return remoteRS != null && remoteRS.CanDisconnect; } } @@ -3382,9 +3383,10 @@ protected void ProcessJobFailure(ExecutionCmdletHelper helper, out Exception fai fullyQualifiedErrorId, ErrorCategory.OpenError, null, null, null, null, null, errorDetails, null); } - else if ((pipeline.PipelineStateInfo.State == PipelineState.Failed) || - ((pipeline.PipelineStateInfo.State == PipelineState.Stopped) && - (pipeline.PipelineStateInfo.Reason != null && !(pipeline.PipelineStateInfo.Reason is PipelineStoppedException)))) + else if (pipeline.PipelineStateInfo.State == PipelineState.Failed + || (pipeline.PipelineStateInfo.State == PipelineState.Stopped + && pipeline.PipelineStateInfo.Reason != null + && pipeline.PipelineStateInfo.Reason is not PipelineStoppedException)) { // Pipeline stopped state is also an error condition if the associated exception is not 'PipelineStoppedException'. object targetObject = runspace.ConnectionInfo.ComputerName; @@ -3476,11 +3478,11 @@ protected override void Dispose(bool disposing) protected virtual void DoCleanupOnFinished() { bool doCleanup = false; - if (_cleanupDone == false) + if (!_cleanupDone) { lock (SyncObject) { - if (_cleanupDone == false) + if (!_cleanupDone) { _cleanupDone = true; doCleanup = true; @@ -3824,7 +3826,7 @@ private void HandleRunspaceAvailabilityChanged(object sender, RunspaceAvailabili #region Private Members // helper associated with this job object - private RemotePipeline _remotePipeline = null; + private readonly RemotePipeline _remotePipeline = null; // object used for synchronization protected object SyncObject = new object(); @@ -3849,9 +3851,9 @@ internal sealed class RemotingJobDebugger : Debugger { #region Members - private Debugger _wrappedDebugger; - private Runspace _runspace; - private string _jobName; + private readonly Debugger _wrappedDebugger; + private readonly Runspace _runspace; + private readonly string _jobName; #endregion @@ -4129,7 +4131,7 @@ private Pipeline DrainAndBlockRemoteOutput() return null; } - private void RestoreRemoteOutput(Pipeline runningCmd) + private static void RestoreRemoteOutput(Pipeline runningCmd) { if (runningCmd != null) { @@ -4171,9 +4173,9 @@ internal class PSInvokeExpressionSyncJob : PSRemotingChildJob { #region Private Members - private List _helpers = new List(); - private ThrottleManager _throttleManager; - private Dictionary _powershells = new Dictionary(); + private readonly List _helpers = new List(); + private readonly ThrottleManager _throttleManager; + private readonly Dictionary _powershells = new Dictionary(); private int _pipelineFinishedCount; private int _pipelineDisconnectedCount; @@ -4232,11 +4234,11 @@ internal PSInvokeExpressionSyncJob(List operations, Throttle protected override void DoCleanupOnFinished() { bool doCleanup = false; - if (_cleanupDone == false) + if (!_cleanupDone) { lock (SyncObject) { - if (_cleanupDone == false) + if (!_cleanupDone) { _cleanupDone = true; doCleanup = true; @@ -4525,9 +4527,10 @@ internal OutputProcessingStateEventArgs(bool processingOutput) } } +#nullable enable internal interface IOutputProcessingState { - event EventHandler OutputProcessingStateChanged; + event EventHandler? OutputProcessingStateChanged; } #endregion diff --git a/src/System.Management.Automation/engine/remoting/client/Job2.cs b/src/System.Management.Automation/engine/remoting/client/Job2.cs index 32923806cce..b89c9433697 100644 --- a/src/System.Management.Automation/engine/remoting/client/Job2.cs +++ b/src/System.Management.Automation/engine/remoting/client/Job2.cs @@ -342,10 +342,7 @@ private void RaiseCompletedHandler(int operation, AsyncCompletedEventArgs eventA #pragma warning disable 56500 try { - if (handler != null) - { - handler(this, eventArgs); - } + handler?.Invoke(this, eventArgs); } catch (Exception exception) { @@ -536,7 +533,10 @@ public sealed class ContainerParentJob : Job2 internal PSEventManager EventManager { - get { return _eventManager; } + get + { + return _eventManager; + } set { @@ -888,7 +888,7 @@ public override void StartJob() _tracer.WriteMessage(TraceClassName, "StartJob", Guid.Empty, this, "Exiting method", null); } - private static Tracer s_structuredTracer = new Tracer(); + private static readonly Tracer s_structuredTracer = new Tracer(); /// /// Starts all child jobs asynchronously. @@ -2038,7 +2038,7 @@ private string ConstructLocation() { if (ChildJobs == null || ChildJobs.Count == 0) return string.Empty; - string location = ChildJobs.Select((job) => job.Location).Aggregate((s1, s2) => s1 + ',' + s2); + string location = ChildJobs.Select(static (job) => job.Location).Aggregate((s1, s2) => s1 + ',' + s2); return location; } @@ -2058,7 +2058,7 @@ private string ConstructStatusMessage() if (i < (ChildJobs.Count - 1)) { - sb.Append(","); + sb.Append(','); } } @@ -2169,14 +2169,14 @@ protected JobFailedException(SerializationInfo serializationInfo, StreamingConte /// public Exception Reason { get { return _reason; } } - private Exception _reason; + private readonly Exception _reason; /// /// The user-focused location from where this error originated. /// public ScriptExtent DisplayScriptPosition { get { return _displayScriptPosition; } } - private ScriptExtent _displayScriptPosition; + private readonly ScriptExtent _displayScriptPosition; /// /// Gets the information for serialization. diff --git a/src/System.Management.Automation/engine/remoting/client/JobManager.cs b/src/System.Management.Automation/engine/remoting/client/JobManager.cs index 6ef47c19752..f907cf922d8 100644 --- a/src/System.Management.Automation/engine/remoting/client/JobManager.cs +++ b/src/System.Management.Automation/engine/remoting/client/JobManager.cs @@ -616,7 +616,7 @@ private List GetFilteredJobs( /// /// /// - private bool CheckTypeNames(JobSourceAdapter sourceAdapter, string[] jobSourceAdapterTypes) + private static bool CheckTypeNames(JobSourceAdapter sourceAdapter, string[] jobSourceAdapterTypes) { // If no type names were specified then allow all adapter types. if (jobSourceAdapterTypes == null || @@ -641,9 +641,9 @@ private bool CheckTypeNames(JobSourceAdapter sourceAdapter, string[] jobSourceAd return false; } - private string GetAdapterName(JobSourceAdapter sourceAdapter) + private static string GetAdapterName(JobSourceAdapter sourceAdapter) { - return (string.IsNullOrEmpty(sourceAdapter.Name) == false ? + return (!string.IsNullOrEmpty(sourceAdapter.Name) ? sourceAdapter.Name : sourceAdapter.GetType().ToString()); } diff --git a/src/System.Management.Automation/engine/remoting/client/JobSourceAdapter.cs b/src/System.Management.Automation/engine/remoting/client/JobSourceAdapter.cs index f38ac4a39d0..0ffcab271bc 100644 --- a/src/System.Management.Automation/engine/remoting/client/JobSourceAdapter.cs +++ b/src/System.Management.Automation/engine/remoting/client/JobSourceAdapter.cs @@ -238,7 +238,7 @@ public JobDefinition Definition /// public List Parameters { - get { return _parameters ?? (_parameters = new List()); } + get { return _parameters ??= new List(); } } /// @@ -361,7 +361,7 @@ private static CommandParameterCollection ConvertDictionaryToParameterCollection return null; CommandParameterCollection paramCollection = new CommandParameterCollection(); foreach (CommandParameter paramItem in - parameters.Select(param => new CommandParameter(param.Key, param.Value))) + parameters.Select(static param => new CommandParameter(param.Key, param.Value))) { paramCollection.Add(paramItem); } @@ -415,8 +415,7 @@ public void StoreJobIdForReuse(Job2 job, bool recurse) duplicateDetector.Add(job.InstanceId, job.InstanceId); foreach (Job child in job.ChildJobs) { - Job2 childJob = child as Job2; - if (childJob == null) continue; + if (!(child is Job2 childJob)) continue; StoreJobIdForReuseHelper(duplicateDetector, childJob, true); } } @@ -432,8 +431,7 @@ private void StoreJobIdForReuseHelper(Hashtable duplicateDetector, Job2 job, boo if (!recurse || job.ChildJobs == null) return; foreach (Job child in job.ChildJobs) { - Job2 childJob = child as Job2; - if (childJob == null) continue; + if (!(child is Job2 childJob)) continue; StoreJobIdForReuseHelper(duplicateDetector, childJob, recurse); } } diff --git a/src/System.Management.Automation/engine/remoting/client/PowerShellStreams.cs b/src/System.Management.Automation/engine/remoting/client/PowerShellStreams.cs index 288bc1449e9..df859a7bc2b 100644 --- a/src/System.Management.Automation/engine/remoting/client/PowerShellStreams.cs +++ b/src/System.Management.Automation/engine/remoting/client/PowerShellStreams.cs @@ -238,11 +238,11 @@ public PSDataCollection InformationStream /// public void CloseAll() { - if (_disposed == false) + if (!_disposed) { lock (_syncLock) { - if (_disposed == false) + if (!_disposed) { _outputStream.Complete(); _errorStream.Complete(); diff --git a/src/System.Management.Automation/engine/remoting/client/RemoteRunspacePoolInternal.cs b/src/System.Management.Automation/engine/remoting/client/RemoteRunspacePoolInternal.cs index 17b07b0f148..94584c613f5 100644 --- a/src/System.Management.Automation/engine/remoting/client/RemoteRunspacePoolInternal.cs +++ b/src/System.Management.Automation/engine/remoting/client/RemoteRunspacePoolInternal.cs @@ -271,8 +271,8 @@ public override RunspacePoolAvailability RunspacePoolAvailability /// internal bool IsRemoteDebugStop { - set; get; + set; } #endregion @@ -679,7 +679,7 @@ internal override void PropagateApplicationPrivateData(Runspace runspace) } private PSPrimitiveDictionary _applicationPrivateData; - private ManualResetEvent _applicationPrivateDataReceived = new ManualResetEvent(false); + private readonly ManualResetEvent _applicationPrivateDataReceived = new ManualResetEvent(false); /// /// This event is raised, when a host call is for a remote runspace @@ -1237,11 +1237,9 @@ public override RunspacePoolCapability GetCapabilities() internal static RunspacePool[] GetRemoteRunspacePools(RunspaceConnectionInfo connectionInfo, PSHost host, TypeTable typeTable) { - WSManConnectionInfo wsmanConnectionInfoParam = connectionInfo as WSManConnectionInfo; - - // Disconnect-Connect currently only supported by WSMan. - if (wsmanConnectionInfoParam == null) + if (!(connectionInfo is WSManConnectionInfo wsmanConnectionInfoParam)) { + // Disconnect-Connect currently only supported by WSMan. throw new NotSupportedException(); } @@ -1270,7 +1268,7 @@ internal static RunspacePool[] GetRemoteRunspacePools(RunspaceConnectionInfo con Guid shellId = Guid.Parse(pspShellId.Value.ToString()); // Filter returned items for PowerShell sessions. - if (strShellUri.StartsWith(WSManNativeApi.ResourceURIPrefix, StringComparison.OrdinalIgnoreCase) == false) + if (!strShellUri.StartsWith(WSManNativeApi.ResourceURIPrefix, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -1428,8 +1426,7 @@ private static void UpdateWSManConnectionInfo( string compressionModeString = pspCompressionMode.Value as string; if (compressionModeString != null) { - wsmanConnectionInfo.UseCompression = compressionModeString.Equals("NoCompression", StringComparison.OrdinalIgnoreCase) - ? false : true; + wsmanConnectionInfo.UseCompression = !compressionModeString.Equals("NoCompression", StringComparison.OrdinalIgnoreCase); } } @@ -1438,8 +1435,7 @@ private static void UpdateWSManConnectionInfo( string encodingString = pspEncoding.Value as string; if (encodingString != null) { - wsmanConnectionInfo.UseUTF16 = encodingString.Equals("UTF16", StringComparison.OrdinalIgnoreCase) - ? true : false; + wsmanConnectionInfo.UseUTF16 = encodingString.Equals("UTF16", StringComparison.OrdinalIgnoreCase); } } @@ -1448,8 +1444,7 @@ private static void UpdateWSManConnectionInfo( string machineProfileLoadedString = pspProfile.Value as string; if (machineProfileLoadedString != null) { - wsmanConnectionInfo.NoMachineProfile = machineProfileLoadedString.Equals("Yes", StringComparison.OrdinalIgnoreCase) - ? false : true; + wsmanConnectionInfo.NoMachineProfile = !machineProfileLoadedString.Equals("Yes", StringComparison.OrdinalIgnoreCase); } } @@ -1881,10 +1876,10 @@ private void WaitAndRaiseConnectEventsProc(object state) #region Private Members - private RunspaceConnectionInfo _connectionInfo; // connection info with which this + private readonly RunspaceConnectionInfo _connectionInfo; // connection info with which this // runspace is created // data structure handler handling - private RunspacePoolAsyncResult _openAsyncResult;// async result object generated on + private RunspacePoolAsyncResult _openAsyncResult; // async result object generated on // CoreOpen private RunspacePoolAsyncResult _closeAsyncResult; // async result object generated by // BeginClose @@ -1898,7 +1893,7 @@ private void WaitAndRaiseConnectEventsProc(object state) private bool _canReconnect; private string _friendlyName = string.Empty; - private System.Collections.Concurrent.ConcurrentStack _runningPowerShells; + private readonly System.Collections.Concurrent.ConcurrentStack _runningPowerShells; #endregion Private Members diff --git a/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs b/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs index dc580b95812..0de48ff6dfc 100644 --- a/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs +++ b/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs @@ -25,14 +25,15 @@ public OriginInfo OriginInfo } } - private OriginInfo _originInfo; + private readonly OriginInfo _originInfo; /// /// Constructor. /// /// The error record that is wrapped. /// Origin information. - public RemotingErrorRecord(ErrorRecord errorRecord, OriginInfo originInfo) : this(errorRecord, originInfo, null) { } + public RemotingErrorRecord(ErrorRecord errorRecord, OriginInfo originInfo) + : this(errorRecord, originInfo, null) { } /// /// Constructor that is used to wrap an error record. @@ -40,8 +41,11 @@ public RemotingErrorRecord(ErrorRecord errorRecord, OriginInfo originInfo) : thi /// /// /// - private RemotingErrorRecord(ErrorRecord errorRecord, OriginInfo originInfo, Exception replaceParentContainsErrorRecordException) : - base(errorRecord, replaceParentContainsErrorRecordException) + private RemotingErrorRecord( + ErrorRecord errorRecord, + OriginInfo originInfo, + Exception replaceParentContainsErrorRecordException) + : base(errorRecord, replaceParentContainsErrorRecordException) { if (errorRecord != null) { @@ -123,8 +127,11 @@ public OriginInfo OriginInfo /// /// The progress record that is wrapped. /// Origin information. - public RemotingProgressRecord(ProgressRecord progressRecord, OriginInfo originInfo) : - base(Validate(progressRecord).ActivityId, Validate(progressRecord).Activity, Validate(progressRecord).StatusDescription) + public RemotingProgressRecord(ProgressRecord progressRecord, OriginInfo originInfo) + : base( + Validate(progressRecord).ActivityId, + Validate(progressRecord).Activity, + Validate(progressRecord).StatusDescription) { _originInfo = originInfo; if (progressRecord != null) @@ -169,7 +176,8 @@ public OriginInfo OriginInfo /// /// The warning message that is wrapped. /// The origin information. - public RemotingWarningRecord(string message, OriginInfo originInfo) : base(message) + public RemotingWarningRecord(string message, OriginInfo originInfo) + : base(message) { _originInfo = originInfo; } @@ -210,7 +218,8 @@ public OriginInfo OriginInfo /// /// The debug message that is wrapped. /// The origin information. - public RemotingDebugRecord(string message, OriginInfo originInfo) : base(message) + public RemotingDebugRecord(string message, OriginInfo originInfo) + : base(message) { _originInfo = originInfo; } @@ -238,7 +247,8 @@ public OriginInfo OriginInfo /// /// The verbose message that is wrapped. /// The origin information. - public RemotingVerboseRecord(string message, OriginInfo originInfo) : base(message) + public RemotingVerboseRecord(string message, OriginInfo originInfo) + : base(message) { _originInfo = originInfo; } @@ -302,7 +312,7 @@ public string PSComputerName } [DataMemberAttribute()] - private string _computerName; + private readonly string _computerName; /// /// Runspace instance ID. @@ -317,7 +327,7 @@ public Guid RunspaceID } [DataMemberAttribute()] - private Guid _runspaceID; + private readonly Guid _runspaceID; /// /// Error record source instance ID. @@ -373,4 +383,3 @@ public override string ToString() } } } - diff --git a/src/System.Management.Automation/engine/remoting/client/RemotingProtocol2.cs b/src/System.Management.Automation/engine/remoting/client/RemotingProtocol2.cs index 11ce70dd186..8b8908b6e61 100644 --- a/src/System.Management.Automation/engine/remoting/client/RemotingProtocol2.cs +++ b/src/System.Management.Automation/engine/remoting/client/RemotingProtocol2.cs @@ -233,7 +233,7 @@ internal void CreatePowerShellOnServerAndInvoke(ClientRemotePowerShell shell) // Find out if this is an invoke and disconnect operation and if so whether the endpoint // supports disconnect. Throw exception if disconnect is not supported. - bool invokeAndDisconnect = (shell.Settings != null) ? shell.Settings.InvokeAndDisconnect : false; + bool invokeAndDisconnect = shell.Settings != null && shell.Settings.InvokeAndDisconnect; if (invokeAndDisconnect && !EndpointSupportsDisconnect) { throw new PSRemotingDataStructureException(RemotingErrorIdStrings.EndpointDoesNotSupportDisconnect); @@ -862,22 +862,23 @@ private void HandleSessionCreateCompleted(object sender, CreateCompleteEventArgs #region Private Members - private Guid _clientRunspacePoolId; - private object _syncObject = new object(); + private readonly Guid _clientRunspacePoolId; + private readonly object _syncObject = new object(); private bool _createRunspaceCalled = false; private Exception _closingReason; - private int _minRunspaces; - private int _maxRunspaces; - private PSHost _host; - private PSPrimitiveDictionary _applicationArguments; + private readonly int _minRunspaces; + private readonly int _maxRunspaces; + private readonly PSHost _host; + private readonly PSPrimitiveDictionary _applicationArguments; - private Dictionary _associatedPowerShellDSHandlers + private readonly Dictionary _associatedPowerShellDSHandlers = new Dictionary(); + // data structure handlers of all ClientRemotePowerShell which are // associated with this runspace pool - private object _associationSyncObject = new object(); + private readonly object _associationSyncObject = new object(); // object to synchronize operations to above - private BaseClientSessionTransportManager _transportManager; + private readonly BaseClientSessionTransportManager _transportManager; // session transport manager associated with this runspace private List _preparingForDisconnectList; @@ -937,7 +938,7 @@ internal bool EndpointSupportsDisconnect get { WSManClientSessionTransportManager wsmanTransportManager = _transportManager as WSManClientSessionTransportManager; - return (wsmanTransportManager != null) ? wsmanTransportManager.SupportsDisconnect : false; + return wsmanTransportManager != null && wsmanTransportManager.SupportsDisconnect; } } @@ -1373,7 +1374,7 @@ internal void CloseConnectionAsync(Exception sessionCloseReason) _sessionClosedReason = sessionCloseReason; // wait for the close to complete and then dispose the transport manager - TransportManager.CloseCompleted += delegate (object source, EventArgs args) + TransportManager.CloseCompleted += (object source, EventArgs args) => { if (CloseCompleted != null) { @@ -1412,7 +1413,7 @@ internal void ProcessDisconnect(RunspacePoolStateInfo rsStateInfo) // disconnect may be called on a pipeline that is already disconnected. PSInvocationStateInfo stateInfo = new PSInvocationStateInfo(PSInvocationState.Disconnected, - (rsStateInfo != null) ? rsStateInfo.Reason : null); + rsStateInfo?.Reason); Dbg.Assert(InvocationStateInfoReceived != null, "ClientRemotePowerShell should subscribe to all data structure handler events"); @@ -1604,7 +1605,7 @@ private void SetupTransportManager(bool inDisconnectMode) // object for synchronizing input to be sent // to server powershell - private object _inputSyncObject = new object(); + private readonly object _inputSyncObject = new object(); private enum connectionStates { diff --git a/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs b/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs index 270e24eb1bd..dfd1cd3bf7f 100644 --- a/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs +++ b/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs @@ -22,10 +22,10 @@ internal class RunspaceRef /// /// Runspace ref. /// - private ObjectRef _runspaceRef; + private readonly ObjectRef _runspaceRef; private bool _stopInvoke; - private object _localSyncObject; - private static RobustConnectionProgress s_RCProgress = new RobustConnectionProgress(); + private readonly object _localSyncObject; + private static readonly RobustConnectionProgress s_RCProgress = new RobustConnectionProgress(); /// /// Constructor for RunspaceRef. @@ -93,7 +93,7 @@ private PSCommand ParsePsCommandUsingScriptBlock(string line, bool? useLocalScop // and if we are not in a loopback configuration mode, in which case we always force remote script commands // to be parsed and evaluated on the remote session (not in the current local session). RemoteRunspace remoteRunspace = _runspaceRef.Value as RemoteRunspace; - bool isConfiguredLoopback = (remoteRunspace != null) ? remoteRunspace.IsConfiguredLoopBack : false; + bool isConfiguredLoopback = remoteRunspace != null && remoteRunspace.IsConfiguredLoopBack; bool isTrustedInput = !isConfiguredLoopback && (localRunspace.ExecutionContext.LanguageMode == PSLanguageMode.FullLanguage); // Create PowerShell from ScriptBlock. @@ -139,7 +139,7 @@ internal PSCommand CreatePsCommand(string line, bool isScript, bool? useNewScope /// /// Creates the PSCommand when the runspace is not overridden. /// - private PSCommand CreatePsCommandNotOverridden(string line, bool isScript, bool? useNewScope) + private static PSCommand CreatePsCommandNotOverridden(string line, bool isScript, bool? useNewScope) { PSCommand command = new PSCommand(); @@ -407,7 +407,7 @@ private void StartProgressBar( } } - private void StopProgressBar( + private static void StopProgressBar( long sourceId) { s_RCProgress.StopProgress(sourceId); diff --git a/src/System.Management.Automation/engine/remoting/client/ThrottlingJob.cs b/src/System.Management.Automation/engine/remoting/client/ThrottlingJob.cs index efb47508bcc..db2f5403dfd 100644 --- a/src/System.Management.Automation/engine/remoting/client/ThrottlingJob.cs +++ b/src/System.Management.Automation/engine/remoting/client/ThrottlingJob.cs @@ -191,8 +191,8 @@ internal enum ChildJobFlags /// /// Child job can call method - /// or - /// or + /// or + /// or /// method /// of the instance it belongs to. /// @@ -269,12 +269,12 @@ private int CountOfRunningOrReadyToRunChildJobs /// Passing 0 requests to turn off throttling (i.e. allow unlimited number of child jobs to run) /// /// - /// true if this is used from a cmdlet invoked without -AsJob switch. - /// false if this is used from a cmdlet invoked with -AsJob switch. + /// if this is used from a cmdlet invoked without -AsJob switch. + /// if this is used from a cmdlet invoked with -AsJob switch. /// - /// If is true, then + /// If is , then /// memory can be managed more aggressively (for example ChildJobs can be discarded as soon as they complete) - /// because the is not exposed to the end user. + /// because the is not exposed to the end user. /// internal ThrottlingJob(string command, string jobName, string jobTypeName, int maximumConcurrentChildJobs, bool cmdletMode) : base(command, jobName) @@ -337,10 +337,7 @@ internal void DisableFlowControlForPendingJobsQueue() while (_actionsForUnblockingChildAdditions.Count > 0) { Action a = _actionsForUnblockingChildAdditions.Dequeue(); - if (a != null) - { - a(); - } + a?.Invoke(); } } } @@ -390,7 +387,7 @@ internal void AddChildJobWithoutBlocking(StartableJob childJob, ChildJobFlags fl newJobStateInfo = new JobStateInfo(JobState.Running); } - if (ChildJobFlags.CreatesChildJobs == (ChildJobFlags.CreatesChildJobs & flags)) + if ((ChildJobFlags.CreatesChildJobs & flags) == ChildJobFlags.CreatesChildJobs) { _setOfChildJobsThatCanAddMoreChildJobs.Add(childJob.InstanceId); } @@ -406,10 +403,7 @@ internal void AddChildJobWithoutBlocking(StartableJob childJob, ChildJobFlags fl } else { - if (jobEnqueuedAction != null) - { - jobEnqueuedAction(); - } + jobEnqueuedAction?.Invoke(); } } @@ -746,10 +740,7 @@ private void childJob_StateChanged(object sender, JobStateEventArgs e) if (_actionsForUnblockingChildAdditions.Count > 0) { Action a = _actionsForUnblockingChildAdditions.Dequeue(); - if (a != null) - { - a(); - } + a?.Invoke(); } if (_cmdletMode) @@ -786,14 +777,14 @@ private List GetChildJobsSnapshot() /// /// Indicates if job has more data available. - /// true if any of the child jobs have more data OR if have not been called yet; - /// false otherwise. + /// if any of the child jobs have more data OR if have not been called yet; + /// otherwise. /// public override bool HasMoreData { get { - return this.GetChildJobsSnapshot().Any(childJob => childJob.HasMoreData) || (this.Results.Count != 0); + return this.GetChildJobsSnapshot().Any(static childJob => childJob.HasMoreData) || (this.Results.Count != 0); } } @@ -855,7 +846,7 @@ internal override void ForwardAvailableResultsToCmdlet(Cmdlet cmdlet) } } - private class ForwardingHelper : IDisposable + private sealed class ForwardingHelper : IDisposable { // This is higher than 1000 used in // RxExtensionMethods+ToEnumerableObserver.BlockingCollectionCapacity diff --git a/src/System.Management.Automation/engine/remoting/client/clientremotesession.cs b/src/System.Management.Automation/engine/remoting/client/clientremotesession.cs index a2875f819fe..772beb61040 100644 --- a/src/System.Management.Automation/engine/remoting/client/clientremotesession.cs +++ b/src/System.Management.Automation/engine/remoting/client/clientremotesession.cs @@ -56,7 +56,7 @@ internal class ClientRemoteSessionContext internal abstract class ClientRemoteSession : RemoteSession { [TraceSourceAttribute("CRSession", "ClientRemoteSession")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("CRSession", "ClientRemoteSession"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("CRSession", "ClientRemoteSession"); #region Public_Method_API @@ -178,7 +178,7 @@ internal RemoteRunspacePoolInternal GetRunspacePool(Guid clientRunspacePoolId) internal class ClientRemoteSessionImpl : ClientRemoteSession, IDisposable { [TraceSourceAttribute("CRSessionImpl", "ClientRemoteSessionImpl")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("CRSessionImpl", "ClientRemoteSessionImpl"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("CRSessionImpl", "ClientRemoteSessionImpl"); private PSRemotingCryptoHelperClient _cryptoHelper = null; @@ -604,4 +604,3 @@ public void Dispose(bool disposing) #endregion IDisposable } } - diff --git a/src/System.Management.Automation/engine/remoting/client/clientremotesessionprotocolstatemachine.cs b/src/System.Management.Automation/engine/remoting/client/clientremotesessionprotocolstatemachine.cs index ec55f22fc22..d035ce6e820 100644 --- a/src/System.Management.Automation/engine/remoting/client/clientremotesessionprotocolstatemachine.cs +++ b/src/System.Management.Automation/engine/remoting/client/clientremotesessionprotocolstatemachine.cs @@ -32,25 +32,26 @@ namespace System.Management.Automation.Remoting internal class ClientRemoteSessionDSHandlerStateMachine { [TraceSourceAttribute("CRSessionFSM", "CRSessionFSM")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("CRSessionFSM", "CRSessionFSM"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("CRSessionFSM", "CRSessionFSM"); /// /// Event handling matrix. It defines what action to take when an event occur. /// [State,Event]=>Action. /// - private EventHandler[,] _stateMachineHandle; - private Queue _clientRemoteSessionStateChangeQueue; + private readonly EventHandler[,] _stateMachineHandle; + private readonly Queue _clientRemoteSessionStateChangeQueue; /// /// Current state of session. /// private RemoteSessionState _state; - private Queue _processPendingEventsQueue + private readonly Queue _processPendingEventsQueue = new Queue(); + // all events raised through the state machine // will be queued in this - private object _syncObject = new object(); + private readonly object _syncObject = new object(); // object for synchronizing access to the above // queue @@ -161,7 +162,7 @@ private void RaiseStateMachineEvents() /// Unique identifier for this state machine. Used /// in tracing. /// - private Guid _id; + private readonly Guid _id; /// /// Handler to be used in cases, where setting the state is the @@ -277,7 +278,7 @@ private void SetStateHandler(object sender, RemoteSessionStateMachineEventArgs e Dbg.Assert(_state >= RemoteSessionState.Established, "Client can send a public key only after reaching the Established state"); - Dbg.Assert(_keyExchanged == false, "Client should do key exchange only once"); + Dbg.Assert(!_keyExchanged, "Client should do key exchange only once"); if (_state == RemoteSessionState.Established || _state == RemoteSessionState.EstablishedAndKeyRequested) @@ -775,7 +776,7 @@ private void DoFatal(object sender, RemoteSessionStateMachineEventArgs eventArgs #endregion Event Handlers - private void CleanAll() + private static void CleanAll() { } diff --git a/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs b/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs index 58931499610..164e9f11f39 100644 --- a/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs +++ b/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs @@ -20,18 +20,18 @@ internal class RemotePipeline : Pipeline #region Private Members private PowerShell _powershell; - private bool _addToHistory; + private readonly bool _addToHistory; private bool _isNested; private bool _isSteppable; - private Runspace _runspace; - private object _syncRoot = new object(); + private readonly Runspace _runspace; + private readonly object _syncRoot = new object(); private bool _disposed = false; private string _historyString; private PipelineStateInfo _pipelineStateInfo = new PipelineStateInfo(PipelineState.NotStarted); - private CommandCollection _commands = new CommandCollection(); - private string _computerName; - private Guid _runspaceId; - private ConnectCommandInfo _connectCmdInfo = null; + private readonly CommandCollection _commands = new CommandCollection(); + private readonly string _computerName; + private readonly Guid _runspaceId; + private readonly ConnectCommandInfo _connectCmdInfo = null; /// /// This is queue of all the state change event which have occured for @@ -42,7 +42,7 @@ internal class RemotePipeline : Pipeline /// private Queue _executionEventQueue = new Queue(); - private class ExecutionEventQueueItem + private sealed class ExecutionEventQueueItem { public ExecutionEventQueueItem(PipelineStateInfo pipelineStateInfo, RunspaceAvailability currentAvailability, RunspaceAvailability newAvailability) { @@ -56,7 +56,7 @@ public ExecutionEventQueueItem(PipelineStateInfo pipelineStateInfo, RunspaceAvai public RunspaceAvailability NewRunspaceAvailability; } - private bool _performNestedCheck = true; + private readonly bool _performNestedCheck = true; #endregion Private Members @@ -161,8 +161,12 @@ internal RemotePipeline(RemoteRunspace runspace) /// Pipeline to clone from. /// This constructor is private because this will /// only be called from the copy method - private RemotePipeline(RemotePipeline pipeline) : - this((RemoteRunspace)pipeline.Runspace, null, false, pipeline.IsNested) + private RemotePipeline(RemotePipeline pipeline) + : this( + (RemoteRunspace)pipeline.Runspace, + command: null, + addToHistory: false, + pipeline.IsNested) { _isSteppable = pipeline._isSteppable; @@ -360,12 +364,12 @@ public bool AddToHistory // Stream and Collection go together...a stream wraps // a corresponding collection to support // streaming behavior of the pipeline. - private PSDataCollection _outputCollection; - private PSDataCollectionStream _outputStream; - private PSDataCollection _errorCollection; - private PSDataCollectionStream _errorStream; - private PSDataCollection _inputCollection; - private PSDataCollectionStream _inputStream; + private readonly PSDataCollection _outputCollection; + private readonly PSDataCollectionStream _outputStream; + private readonly PSDataCollection _errorCollection; + private readonly PSDataCollectionStream _errorStream; + private readonly PSDataCollection _inputCollection; + private readonly PSDataCollectionStream _inputStream; /// /// Stream for providing input to PipelineProcessor. Host will write on @@ -1048,7 +1052,7 @@ internal void DoConcurrentCheck(bool syncCall) RemotePipeline currentPipeline = (RemotePipeline)((RemoteRunspace)_runspace).GetCurrentlyRunningPipeline(); - if (_isNested == false) + if (!_isNested) { if (currentPipeline == null && ((RemoteRunspace)_runspace).RunspaceAvailability != RunspaceAvailability.Busy && @@ -1093,7 +1097,7 @@ internal void DoConcurrentCheck(bool syncCall) return; } - if (syncCall == false) + if (!syncCall) { throw PSTraceSource.NewInvalidOperationException( RunspaceStrings.NestedPipelineInvokeAsync); diff --git a/src/System.Management.Automation/engine/remoting/client/remoterunspace.cs b/src/System.Management.Automation/engine/remoting/client/remoterunspace.cs index a927b49481f..7ddd657872e 100644 --- a/src/System.Management.Automation/engine/remoting/client/remoterunspace.cs +++ b/src/System.Management.Automation/engine/remoting/client/remoterunspace.cs @@ -32,11 +32,11 @@ internal class RemoteRunspace : Runspace, IDisposable { #region Private Members - private List _runningPipelines = new List(); - private object _syncRoot = new object(); + private readonly List _runningPipelines = new List(); + private readonly object _syncRoot = new object(); private RunspaceStateInfo _runspaceStateInfo = new RunspaceStateInfo(RunspaceState.BeforeOpen); - private bool _bSessionStateProxyCallInProgress = false; - private RunspaceConnectionInfo _connectionInfo; + private readonly bool _bSessionStateProxyCallInProgress = false; + private readonly RunspaceConnectionInfo _connectionInfo; private RemoteDebugger _remoteDebugger; private PSPrimitiveDictionary _applicationPrivateData; @@ -156,8 +156,8 @@ internal RemoteRunspace(RunspacePool runspacePool) { // The RemoteRunspace object can only be constructed this way with a RunspacePool that // is in the disconnected state. - if ((runspacePool.RunspacePoolStateInfo.State != RunspacePoolState.Disconnected) || - !(runspacePool.ConnectionInfo is WSManConnectionInfo)) + if (runspacePool.RunspacePoolStateInfo.State != RunspacePoolState.Disconnected + || runspacePool.ConnectionInfo is not WSManConnectionInfo) { throw PSTraceSource.NewInvalidOperationException(RunspaceStrings.InvalidRunspacePool); } @@ -1113,7 +1113,7 @@ internal void AddToRunningPipelineList(RemotePipeline pipeline) lock (_syncRoot) { - if (_bypassRunspaceStateCheck == false && + if (!_bypassRunspaceStateCheck && _runspaceStateInfo.State != RunspaceState.Opened && _runspaceStateInfo.State != RunspaceState.Disconnected) // Disconnected runspaces can have running pipelines. { @@ -1201,7 +1201,7 @@ internal void DoConcurrentCheckAndAddToRunningPipelines(RemotePipeline pipeline, /// internal override SessionStateProxy GetSessionStateProxy() { - return _sessionStateProxy ?? (_sessionStateProxy = new RemoteSessionStateProxy(this)); + return _sessionStateProxy ??= new RemoteSessionStateProxy(this); } private RemoteSessionStateProxy _sessionStateProxy = null; @@ -1792,7 +1792,7 @@ internal sealed class RemoteDebugger : Debugger, IDisposable { #region Members - private RemoteRunspace _runspace; + private readonly RemoteRunspace _runspace; private PowerShell _psDebuggerCommand; private bool _remoteDebugSupported; private bool _isActive; @@ -1936,17 +1936,17 @@ public override DebuggerCommandResults ProcessCommand(PSCommand command, PSDataC { // Allow the IncompleteParseException to throw so that the console // can handle here strings and continued parsing. - if (re.ErrorRecord.CategoryInfo.Reason == typeof(IncompleteParseException).Name) + if (re.ErrorRecord.CategoryInfo.Reason == nameof(IncompleteParseException)) { throw new IncompleteParseException( - (re.ErrorRecord.Exception != null) ? re.ErrorRecord.Exception.Message : null, + re.ErrorRecord.Exception?.Message, re.ErrorRecord.FullyQualifiedErrorId); } // Allow the RemoteException and InvalidRunspacePoolStateException to propagate so that the host can // clean up the debug session. - if ((re.ErrorRecord.CategoryInfo.Reason == typeof(InvalidRunspacePoolStateException).Name) || - (re.ErrorRecord.CategoryInfo.Reason == typeof(RemoteException).Name)) + if ((re.ErrorRecord.CategoryInfo.Reason == nameof(InvalidRunspacePoolStateException)) || + (re.ErrorRecord.CategoryInfo.Reason == nameof(RemoteException))) { throw new PSRemotingTransportException( (re.ErrorRecord.Exception != null) ? re.ErrorRecord.Exception.Message : string.Empty); @@ -2491,8 +2491,8 @@ internal void CheckStateAndRaiseStopEvent() /// internal bool IsRemoteDebug { - private set; get; + private set; } /// @@ -2660,7 +2660,7 @@ private void ProcessDebuggerStopEvent(DebuggerStopEventArgs args) // Attempt to process debugger stop event on original thread if it // is available (i.e., if it is blocked by EndInvoke). PowerShell powershell = _runspace.RunspacePool.RemoteRunspacePoolInternal.GetCurrentRunningPowerShell(); - AsyncResult invokeAsyncResult = (powershell != null) ? powershell.EndInvokeAsyncResult : null; + AsyncResult invokeAsyncResult = powershell?.EndInvokeAsyncResult; bool invokedOnBlockedThread = false; if ((invokeAsyncResult != null) && (!invokeAsyncResult.IsCompleted)) @@ -2933,7 +2933,7 @@ private void CheckRemoteBreakpointManagementSupport(string breakpointCommandName internal class RemoteSessionStateProxy : SessionStateProxy { - private RemoteRunspace _runspace; + private readonly RemoteRunspace _runspace; internal RemoteSessionStateProxy(RemoteRunspace runspace) { diff --git a/src/System.Management.Automation/engine/remoting/client/remoterunspaceinfo.cs b/src/System.Management.Automation/engine/remoting/client/remoterunspaceinfo.cs index 1a975f5a785..1fa03edf25b 100644 --- a/src/System.Management.Automation/engine/remoting/client/remoterunspaceinfo.cs +++ b/src/System.Management.Automation/engine/remoting/client/remoterunspaceinfo.cs @@ -208,7 +208,7 @@ public Runspace Runspace public override string ToString() { // PSSession is a PowerShell type name and so should not be localized. - string formatString = "[PSSession]{0}"; + const string formatString = "[PSSession]{0}"; return StringUtil.Format(formatString, Name); } @@ -347,9 +347,9 @@ private string GetTransportName() /// /// Shell configuration name. /// Display shell name. - private string GetDisplayShellName(string shell) + private static string GetDisplayShellName(string shell) { - string shellPrefix = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix; + const string shellPrefix = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix; int index = shell.IndexOf(shellPrefix, StringComparison.OrdinalIgnoreCase); return (index == 0) ? shell.Substring(shellPrefix.Length) : shell; diff --git a/src/System.Management.Automation/engine/remoting/client/remotingprotocolimplementation.cs b/src/System.Management.Automation/engine/remoting/client/remotingprotocolimplementation.cs index 8615bf3398a..d8800311127 100644 --- a/src/System.Management.Automation/engine/remoting/client/remotingprotocolimplementation.cs +++ b/src/System.Management.Automation/engine/remoting/client/remotingprotocolimplementation.cs @@ -16,22 +16,22 @@ namespace System.Management.Automation.Remoting internal class ClientRemoteSessionDSHandlerImpl : ClientRemoteSessionDataStructureHandler, IDisposable { [TraceSourceAttribute("CRSDSHdlerImpl", "ClientRemoteSessionDSHandlerImpl")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("CRSDSHdlerImpl", "ClientRemoteSessionDSHandlerImpl"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("CRSDSHdlerImpl", "ClientRemoteSessionDSHandlerImpl"); private const string resBaseName = "remotingerroridstrings"; - private BaseClientSessionTransportManager _transportManager; - private ClientRemoteSessionDSHandlerStateMachine _stateMachine; - private ClientRemoteSession _session; - private RunspaceConnectionInfo _connectionInfo; + private readonly BaseClientSessionTransportManager _transportManager; + private readonly ClientRemoteSessionDSHandlerStateMachine _stateMachine; + private readonly ClientRemoteSession _session; + private readonly RunspaceConnectionInfo _connectionInfo; // used for connection redirection. private Uri _redirectUri; private int _maxUriRedirectionCount; private bool _isCloseCalled; - private object _syncObject = new object(); - private PSRemotingCryptoHelper _cryptoHelper; + private readonly object _syncObject = new object(); + private readonly PSRemotingCryptoHelper _cryptoHelper; - private ClientRemoteSession.URIDirectionReported _uriRedirectionHandler; + private readonly ClientRemoteSession.URIDirectionReported _uriRedirectionHandler; internal override BaseClientSessionTransportManager TransportManager { @@ -444,10 +444,7 @@ private void PerformURIRedirectionStep2(System.Uri newURI) } // raise warning to report the redirection - if (_uriRedirectionHandler != null) - { - _uriRedirectionHandler(newURI); - } + _uriRedirectionHandler?.Invoke(newURI); // start a new connection _transportManager.Redirect(newURI, _connectionInfo); diff --git a/src/System.Management.Automation/engine/remoting/commands/ConnectPSSession.cs b/src/System.Management.Automation/engine/remoting/commands/ConnectPSSession.cs index c85b88eb26c..8dfdacd1226 100644 --- a/src/System.Management.Automation/engine/remoting/commands/ConnectPSSession.cs +++ b/src/System.Management.Automation/engine/remoting/commands/ConnectPSSession.cs @@ -92,7 +92,10 @@ public class ConnectPSSessionCommand : PSRunspaceCmdlet, IDisposable ParameterSetName = ConnectPSSessionCommand.ComputerNameGuidParameterSet)] public string ApplicationName { - get { return _appName; } + get + { + return _appName; + } set { @@ -117,7 +120,10 @@ public string ApplicationName ParameterSetName = ConnectPSSessionCommand.ConnectionUriGuidParameterSet)] public string ConfigurationName { - get { return _shell; } + get + { + return _shell; + } set { @@ -202,7 +208,10 @@ public override string[] Name [Credential()] public PSCredential Credential { - get { return _psCredential; } + get + { + return _psCredential; + } set { @@ -223,7 +232,10 @@ public PSCredential Credential [Parameter(ParameterSetName = ConnectPSSessionCommand.ConnectionUriGuidParameterSet)] public AuthenticationMechanism Authentication { - get { return _authentication; } + get + { + return _authentication; + } set { @@ -245,7 +257,10 @@ public AuthenticationMechanism Authentication [Parameter(ParameterSetName = ConnectPSSessionCommand.ConnectionUriGuidParameterSet)] public string CertificateThumbprint { - get { return _thumbprint; } + get + { + return _thumbprint; + } set { @@ -472,15 +487,15 @@ protected override void StopProcessing() /// /// Throttle class to perform a remoterunspace connect operation. /// - private class ConnectRunspaceOperation : IThrottleOperation + private sealed class ConnectRunspaceOperation : IThrottleOperation { private PSSession _session; private PSSession _oldSession; - private ObjectStream _writeStream; - private Collection _retryList; - private PSHost _host; - private QueryRunspaces _queryRunspaces; - private static object s_LockObject = new object(); + private readonly ObjectStream _writeStream; + private readonly Collection _retryList; + private readonly PSHost _host; + private readonly QueryRunspaces _queryRunspaces; + private static readonly object s_LockObject = new object(); internal ConnectRunspaceOperation( PSSession session, @@ -691,10 +706,7 @@ private void WriteConnectedPSSession() // and this particular method may be called on a thread that // is different from Pipeline Execution Thread. Hence using // a delegate to perform the WriteObject. - Action outputWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteObject(outSession); - }; + Action outputWriter = (Cmdlet cmdlet) => cmdlet.WriteObject(outSession); _writeStream.ObjectWriter.Write(outputWriter); } } @@ -728,10 +740,7 @@ private void WriteConnectFailed( } ErrorRecord errorRecord = new ErrorRecord(reason, FQEID, ErrorCategory.InvalidOperation, null); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); _writeStream.ObjectWriter.Write(errorWriter); } } @@ -1084,24 +1093,24 @@ private void Dispose(bool disposing) #region Private Members // Collection of PSSessions to be connected. - private Collection _allSessions = new Collection(); + private readonly Collection _allSessions = new Collection(); // Object used to perform network disconnect operations in a limited manner. - private ThrottleManager _throttleManager = new ThrottleManager(); + private readonly ThrottleManager _throttleManager = new ThrottleManager(); // Event indicating that all disconnect operations through the ThrottleManager // are complete. - private ManualResetEvent _operationsComplete = new ManualResetEvent(true); + private readonly ManualResetEvent _operationsComplete = new ManualResetEvent(true); // Object used for querying remote runspaces. - private QueryRunspaces _queryRunspaces = new QueryRunspaces(); + private readonly QueryRunspaces _queryRunspaces = new QueryRunspaces(); // Object to collect output data from multiple threads. - private ObjectStream _stream = new ObjectStream(); + private readonly ObjectStream _stream = new ObjectStream(); // Support for connection retry on failure. - private ThrottleManager _retryThrottleManager = new ThrottleManager(); - private Collection _failedSessions = new Collection(); + private readonly ThrottleManager _retryThrottleManager = new ThrottleManager(); + private readonly Collection _failedSessions = new Collection(); #endregion } diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index 71985462fc5..19c093e3687 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -589,8 +589,8 @@ protected override void ProcessRecord() restartServiceTarget, restartServiceAction, restartWSManRequiredForUI, - runAsCredential != null ? runAsCredential.UserName : null, - runAsCredential != null ? runAsCredential.Password : null, + runAsCredential?.UserName, + runAsCredential?.Password, AccessMode, isSddlSpecified, _configTableSDDL, @@ -641,7 +641,7 @@ protected override void EndProcessing() /// 1. New shell successfully registered. However cannot delete temporary plugin file {0}. /// Reason for failure: {1}. /// - private void DeleteFile(string tmpFileName) + private static void DeleteFile(string tmpFileName) { Dbg.Assert(!string.IsNullOrEmpty(tmpFileName), "tmpFile cannot be null or empty."); @@ -693,7 +693,7 @@ private void DeleteFile(string tmpFileName) /// 2. Cannot write shell configuration data into temporary file {0}. Try again. /// Reason for failure: {1}. /// - private string ConstructTemporaryFile(string pluginContent) + private static string ConstructTemporaryFile(string pluginContent) { // Path.GetTempFileName creates a temporary file whereas GetRandomFileName does not. string tmpFileName = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()) + "psshell.xml"; @@ -708,7 +708,7 @@ private string ConstructTemporaryFile(string pluginContent) try { // Make sure the file is not read only - destfile.Attributes = destfile.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden); + destfile.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden); destfile.Delete(); } catch (FileNotFoundException fnf) @@ -798,7 +798,7 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d destConfigFilePath = null; StringBuilder initParameters = new StringBuilder(); - bool assemblyAndTypeTokensSet = false; + const bool assemblyAndTypeTokensSet = false; // DISC endpoint if (Path != null) @@ -869,7 +869,7 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d if (configTable.ContainsKey(ConfigFileConstants.PowerShellVersion)) { - if (isPSVersionSpecified == false) + if (!isPSVersionSpecified) { try { @@ -1071,7 +1071,7 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d } // Default value for PSVersion - if (isPSVersionSpecified == false) + if (!isPSVersionSpecified) { psVersion = PSVersionInfo.PSVersion; } @@ -1753,8 +1753,7 @@ internal static string CreateConditionalACEFromConfig( } StringBuilder conditionalACE = new StringBuilder(); - Hashtable requiredGroupsHash = configTable[ConfigFileConstants.RequiredGroups] as Hashtable; - if (requiredGroupsHash == null) + if (!(configTable[ConfigFileConstants.RequiredGroups] is Hashtable requiredGroupsHash)) { throw new PSInvalidOperationException(RemotingErrorIdStrings.RequiredGroupsNotHashTable); } @@ -1963,7 +1962,10 @@ public string Name [Parameter(Position = 1, Mandatory = true, ParameterSetName = PSSessionConfigurationCommandBase.AssemblyNameParameterSetName)] public string AssemblyName { - get { return assemblyName; } + get + { + return assemblyName; + } set { @@ -1985,7 +1987,10 @@ public string AssemblyName [Parameter(ParameterSetName = AssemblyNameParameterSetName)] public string ApplicationBase { - get { return applicationBase; } + get + { + return applicationBase; + } set { @@ -2005,7 +2010,10 @@ public string ApplicationBase [Parameter(Position = 2, Mandatory = true, ParameterSetName = PSSessionConfigurationCommandBase.AssemblyNameParameterSetName)] public string ConfigurationTypeName { - get { return configurationTypeName; } + get + { + return configurationTypeName; + } set { @@ -2054,7 +2062,10 @@ public ApartmentState ThreadApartmentState return ApartmentState.Unknown; } - set { threadAptState = value; } + set + { + threadAptState = value; + } } internal ApartmentState? threadAptState; @@ -2075,7 +2086,10 @@ public PSThreadOptions ThreadOptions return PSThreadOptions.UseCurrentThread; } - set { threadOptions = value; } + set + { + threadOptions = value; + } } internal PSThreadOptions? threadOptions; @@ -2086,7 +2100,10 @@ public PSThreadOptions ThreadOptions [Parameter] public PSSessionConfigurationAccessMode AccessMode { - get { return _accessMode; } + get + { + return _accessMode; + } set { @@ -2125,7 +2142,10 @@ public SwitchParameter UseSharedProcess [Parameter()] public string StartupScript { - get { return configurationScript; } + get + { + return configurationScript; + } set { @@ -2145,7 +2165,10 @@ public string StartupScript [AllowNull] public double? MaximumReceivedDataSizePerCommandMB { - get { return maxCommandSizeMB; } + get + { + return maxCommandSizeMB; + } set { @@ -2172,7 +2195,10 @@ public double? MaximumReceivedDataSizePerCommandMB [AllowNull] public double? MaximumReceivedObjectSizeMB { - get { return maxObjectSizeMB; } + get + { + return maxObjectSizeMB; + } set { @@ -2199,7 +2225,10 @@ public double? MaximumReceivedObjectSizeMB [Parameter()] public string SecurityDescriptorSddl { - get { return sddl; } + get + { + return sddl; + } set { @@ -2229,7 +2258,10 @@ public string SecurityDescriptorSddl [Parameter()] public SwitchParameter ShowSecurityDescriptorUI { - get { return _showUI; } + get + { + return _showUI; + } set { @@ -2281,7 +2313,10 @@ public SwitchParameter NoServiceRestart [ValidateNotNullOrEmpty] public Version PSVersion { - get { return psVersion; } + get + { + return psVersion; + } set { @@ -2374,7 +2409,7 @@ public object[] ModulesToImport // Add this check after checking if it a path if (!string.IsNullOrEmpty(modulepath.Trim())) { - if ((modulepath.Contains("\\") || modulepath.Contains(":")) && + if ((modulepath.Contains('\\') || modulepath.Contains(':')) && !(Directory.Exists(modulepath) || File.Exists(modulepath))) { throw new ArgumentException( @@ -3963,7 +3998,7 @@ public sealed class EnablePSSessionConfigurationCommand : PSCmdlet function Test-WinRMQuickConfigNeeded {{ - # see issue #11005 - Function Test-WinRMQuickConfigNeeded needs to be updated: + # see issue #11005 - Function Test-WinRMQuickConfigNeeded needs to be updated: # 1) currently this function always returns $True # 2) checking for a firewall rule using Get-NetFirewallRule engages WinCompat code and has significant perf impact on Enable-PSRemoting; maybe change to Get-CimInstance -ClassName MSFT_NetFirewallRule return $True @@ -4168,7 +4203,7 @@ function Enable-PSSessionConfiguration $_ | Enable-PSSessionConfiguration -force $args[0] -sddl $args[1] -isSDDLSpecified $args[2] -queryForSet $args[3] -captionForSet $args[4] -queryForQC $args[5] -captionForQC $args[6] -whatif:$args[7] -confirm:$args[8] -shouldProcessDescForQC $args[9] -setEnabledTarget $args[10] -setEnabledAction $args[11] -skipNetworkProfileCheck $args[12] -noServiceRestart $args[13] "; - private static ScriptBlock s_enablePluginSb; + private static readonly ScriptBlock s_enablePluginSb; #endregion @@ -4196,7 +4231,7 @@ static EnablePSSessionConfigurationCommand() [ValidateNotNullOrEmpty] public string[] Name { get; set; } - private Collection _shellsToEnable = new Collection(); + private readonly Collection _shellsToEnable = new Collection(); /// /// Property that sets force parameter. This will allow @@ -4455,7 +4490,7 @@ function Disable-PSSessionConfiguration $_ | Disable-PSSessionConfiguration -force $args[0] -whatif:$args[1] -confirm:$args[2] -restartWinRMMessage $args[3] -setEnabledTarget $args[4] -setEnabledAction $args[5] -noServiceRestart $args[6] "; - private static ScriptBlock s_disablePluginSb; + private static readonly ScriptBlock s_disablePluginSb; #endregion @@ -4483,7 +4518,7 @@ static DisablePSSessionConfigurationCommand() [ValidateNotNullOrEmpty] public string[] Name { get; set; } - private Collection _shellsToDisable = new Collection(); + private readonly Collection _shellsToDisable = new Collection(); /// /// Property that sets force parameter. This will allow @@ -4860,7 +4895,7 @@ function Enable-PSRemoting Enable-PSRemoting -force $args[0] -queryForRegisterDefault $args[1] -captionForRegisterDefault $args[2] -queryForSet $args[3] -captionForSet $args[4] -whatif:$args[5] -confirm:$args[6] -skipNetworkProfileCheck $args[7] -errorMsgUnableToInstallPlugin $args[8] "; - private static ScriptBlock s_enableRemotingSb; + private static readonly ScriptBlock s_enableRemotingSb; #endregion @@ -5086,7 +5121,7 @@ function Disable-PSRemoting Disable-PSRemoting -force:$args[0] -queryForSet $args[1] -captionForSet $args[2] -restartWinRMMessage $args[3] -whatif:$args[4] -confirm:$args[5] "; - private static ScriptBlock s_disableRemotingSb; + private static readonly ScriptBlock s_disableRemotingSb; #endregion Private Data @@ -5234,7 +5269,7 @@ protected override void BeginProcessing() } // The validator that will be applied to the role lookup - Func validator = (role) => true; + Func validator = static (role) => true; if (!string.IsNullOrEmpty(this.Username)) { diff --git a/src/System.Management.Automation/engine/remoting/commands/DebugJob.cs b/src/System.Management.Automation/engine/remoting/commands/DebugJob.cs index 979912619f2..8e5732304e9 100644 --- a/src/System.Management.Automation/engine/remoting/commands/DebugJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/DebugJob.cs @@ -100,7 +100,6 @@ public Guid InstanceId /// /// Gets or sets a flag that tells PowerShell to automatically perform a BreakAll when the debugger is attached to the remote target. /// - [Experimental("Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace", ExperimentAction.Show)] [Parameter] public SwitchParameter BreakAll { get; set; } @@ -237,7 +236,7 @@ private bool CheckForDebuggableJob() return debuggableJobFound; } - private bool GetJobDebuggable(Job job) + private static bool GetJobDebuggable(Job job) { if (job is IJobDebugger) { diff --git a/src/System.Management.Automation/engine/remoting/commands/DisconnectPSSession.cs b/src/System.Management.Automation/engine/remoting/commands/DisconnectPSSession.cs index 0b9cfeb2d6e..74bcbac2c33 100644 --- a/src/System.Management.Automation/engine/remoting/commands/DisconnectPSSession.cs +++ b/src/System.Management.Automation/engine/remoting/commands/DisconnectPSSession.cs @@ -109,7 +109,7 @@ private PSSessionOption PSSessionOption { // no need to lock as the cmdlet parameters will not be assigned // from multiple threads. - return _sessionOption ?? (_sessionOption = new PSSessionOption()); + return _sessionOption ??= new PSSessionOption(); } } @@ -346,7 +346,7 @@ private bool ValidateIdleTimeout(PSSession session) { int idleTimeout = session.Runspace.ConnectionInfo.IdleTimeout; int maxIdleTimeout = session.Runspace.ConnectionInfo.MaxIdleTimeout; - int minIdleTimeout = BaseTransportManager.MinimumIdleTimeout; + const int minIdleTimeout = BaseTransportManager.MinimumIdleTimeout; if (idleTimeout != BaseTransportManager.UseServerDefaultIdleTimeout && (idleTimeout > maxIdleTimeout || idleTimeout < minIdleTimeout)) @@ -363,7 +363,7 @@ private bool ValidateIdleTimeout(PSSession session) return true; } - private string GetLocalhostWithNetworkAccessEnabled(Dictionary psSessions) + private static string GetLocalhostWithNetworkAccessEnabled(Dictionary psSessions) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); @@ -392,10 +392,10 @@ private string GetLocalhostWithNetworkAccessEnabled(Dictionary /// /// Throttle class to perform a remoterunspace disconnect operation. /// - private class DisconnectRunspaceOperation : IThrottleOperation + private sealed class DisconnectRunspaceOperation : IThrottleOperation { - private PSSession _remoteSession; - private ObjectStream _writeStream; + private readonly PSSession _remoteSession; + private readonly ObjectStream _writeStream; internal DisconnectRunspaceOperation(PSSession session, ObjectStream stream) { @@ -481,10 +481,7 @@ private void WriteDisconnectedPSSession() { if (_writeStream.ObjectWriter.IsOpen) { - Action outputWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteObject(_remoteSession); - }; + Action outputWriter = (Cmdlet cmdlet) => cmdlet.WriteObject(_remoteSession); _writeStream.ObjectWriter.Write(outputWriter); } } @@ -506,10 +503,7 @@ private void WriteDisconnectFailed(Exception e = null) Exception reason = new RuntimeException(msg, e); ErrorRecord errorRecord = new ErrorRecord(reason, "PSSessionDisconnectFailed", ErrorCategory.InvalidOperation, _remoteSession); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); _writeStream.ObjectWriter.Write(errorWriter); } } @@ -556,14 +550,14 @@ private void Dispose(bool disposing) #region Private Members // Object used to perform network disconnect operations in a limited manner. - private ThrottleManager _throttleManager = new ThrottleManager(); + private readonly ThrottleManager _throttleManager = new ThrottleManager(); // Event indicating that all disconnect operations through the ThrottleManager // are complete. - private ManualResetEvent _operationsComplete = new ManualResetEvent(true); + private readonly ManualResetEvent _operationsComplete = new ManualResetEvent(true); // Output data stream. - private ObjectStream _stream = new ObjectStream(); + private readonly ObjectStream _stream = new ObjectStream(); #endregion } diff --git a/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs b/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs index d7b7ca51782..756250eb8d7 100644 --- a/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs @@ -292,7 +292,7 @@ private Runspace CreateNamedPipeRunspace(NamedPipeConnectionInfo connectionInfo) return remoteRunspace; } - private void PrepareRunspace(Runspace runspace) + private static void PrepareRunspace(Runspace runspace) { string promptFn = StringUtil.Format(RemotingErrorIdStrings.EnterPSHostProcessPrompt, @"function global:prompt { """, @@ -377,7 +377,7 @@ private Process GetProcessByName(string name) private void VerifyProcess(Process process) { - if (process.Id == Process.GetCurrentProcess().Id) + if (process.Id == Environment.ProcessId) { ThrowTerminatingError( new ErrorRecord( @@ -574,7 +574,7 @@ protected override void EndProcessing() #region Private Methods - private int[] GetProcIdsFromProcs(Process[] processes) + private static int[] GetProcIdsFromProcs(Process[] processes) { List returnIds = new List(); foreach (Process process in processes) @@ -585,7 +585,7 @@ private int[] GetProcIdsFromProcs(Process[] processes) return returnIds.ToArray(); } - private int[] GetProcIdsFromNames(string[] names) + private static int[] GetProcIdsFromNames(string[] names) { if ((names == null) || (names.Length == 0)) { diff --git a/src/System.Management.Automation/engine/remoting/commands/GetJob.cs b/src/System.Management.Automation/engine/remoting/commands/GetJob.cs index 17ee25c52cf..a48cb4dcc1a 100644 --- a/src/System.Management.Automation/engine/remoting/commands/GetJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/GetJob.cs @@ -110,7 +110,7 @@ protected override void ProcessRecord() { List jobList = FindJobs(); - jobList.Sort((x, y) => x != null ? x.Id.CompareTo(y != null ? y.Id : 1) : -1); + jobList.Sort(static (x, y) => x != null ? x.Id.CompareTo(y != null ? y.Id : 1) : -1); WriteObject(jobList, true); } diff --git a/src/System.Management.Automation/engine/remoting/commands/InvokeCommandCommand.cs b/src/System.Management.Automation/engine/remoting/commands/InvokeCommandCommand.cs index daef292017f..c86f7903a1a 100644 --- a/src/System.Management.Automation/engine/remoting/commands/InvokeCommandCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/InvokeCommandCommand.cs @@ -347,14 +347,14 @@ public override string ApplicationName [Parameter(ParameterSetName = InvokeCommandCommand.FilePathContainerIdParameterSet)] public override int ThrottleLimit { - set + get { - base.ThrottleLimit = value; + return base.ThrottleLimit; } - get + set { - return base.ThrottleLimit; + base.ThrottleLimit = value; } } @@ -737,6 +737,30 @@ public override string KeyFilePath set { base.KeyFilePath = value; } } + /// + /// Gets and sets a value for the SSH subsystem to use for the remote connection. + /// + [Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)] + [Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)] + public override string Subsystem + { + get { return base.Subsystem; } + + set { base.Subsystem = value; } + } + + /// + /// Gets and sets a value in milliseconds that limits the time allowed for an SSH connection to be established. + /// + [Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)] + [Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)] + public override int ConnectingTimeout + { + get { return base.ConnectingTimeout; } + + set { base.ConnectingTimeout = value; } + } + /// /// This parameter specifies that SSH is used to establish the remote /// connection and act as the remoting transport. By default WinRM is used @@ -972,7 +996,7 @@ protected override void BeginProcessing() // of this bug in Win8 where not responding can occur during data piping. // We are reverting to Win7 behavior for {icm | icm} and {proxycommand | proxycommand} // cases. For ICM | % ICM case, we are using remote steppable pipeline. - if ((MyInvocation != null) && (MyInvocation.PipelinePosition == 1) && (MyInvocation.ExpectingInput == false)) + if ((MyInvocation != null) && (MyInvocation.PipelinePosition == 1) && !MyInvocation.ExpectingInput) { PSPrimitiveDictionary table = (object)runspaceInfo.ApplicationPrivateData[PSVersionInfo.PSVersionTableName] as PSPrimitiveDictionary; if (table != null) @@ -1007,8 +1031,7 @@ protected override void BeginProcessing() // create collection of input writers here foreach (IThrottleOperation operation in Operations) { - ExecutionCmdletHelperRunspace ecHelper = operation as ExecutionCmdletHelperRunspace; - if (ecHelper == null) + if (!(operation is ExecutionCmdletHelperRunspace ecHelper)) { // either all the operations will be of type ExecutionCmdletHelperRunspace // or not...there is no mix. @@ -1876,7 +1899,7 @@ private void StartProgressBar( this.Host); } - private void StopProgressBar( + private static void StopProgressBar( long sourceId) { s_RCProgress.StopProgress(sourceId); @@ -1955,7 +1978,7 @@ private void DetermineThrowStatementBehavior() /// Process the stream object before writing it in the specified collection. /// /// Stream object to process. - private void PreProcessStreamObject(PSStreamObject streamObject) + private static void PreProcessStreamObject(PSStreamObject streamObject) { ErrorRecord errorRecord = streamObject.Value as ErrorRecord; @@ -1984,7 +2007,7 @@ private void PreProcessStreamObject(PSStreamObject streamObject) private ThrottleManager _throttleManager = new ThrottleManager(); // throttle manager for handling all throttling operations - private ManualResetEvent _operationsComplete = new ManualResetEvent(true); + private readonly ManualResetEvent _operationsComplete = new ManualResetEvent(true); private ManualResetEvent _disconnectComplete; // the initial state is true because when no // operations actually take place as in case of a @@ -2002,17 +2025,17 @@ private void PreProcessStreamObject(PSStreamObject streamObject) private const string InProcParameterSet = "InProcess"; - private PSDataCollection _input = new PSDataCollection(); + private readonly PSDataCollection _input = new PSDataCollection(); private bool _needToCollect = false; private bool _needToStartSteppablePipelineOnServer = false; private bool _clearInvokeCommandOnRunspace = false; - private List _inputWriters = new List(); - private object _jobSyncObject = new object(); + private readonly List _inputWriters = new List(); + private readonly object _jobSyncObject = new object(); private bool _nojob = false; - private Guid _instanceId = Guid.NewGuid(); + private readonly Guid _instanceId = Guid.NewGuid(); private bool _propagateErrors = false; - private static RobustConnectionProgress s_RCProgress = new RobustConnectionProgress(); + private static readonly RobustConnectionProgress s_RCProgress = new RobustConnectionProgress(); internal static readonly string RemoteJobType = "RemoteJob"; @@ -2092,14 +2115,14 @@ namespace System.Management.Automation.Internal internal class RobustConnectionProgress { private System.Management.Automation.Host.PSHost _psHost; - private string _activity; + private readonly string _activity; private string _status; private int _secondsTotal; private int _secondsRemaining; private ProgressRecord _progressRecord; private long _sourceId; private bool _progressIsRunning; - private object _syncObject; + private readonly object _syncObject; private Timer _updateTimer; /// diff --git a/src/System.Management.Automation/engine/remoting/commands/JobRepository.cs b/src/System.Management.Automation/engine/remoting/commands/JobRepository.cs index d06eabf25a3..7bb52abcb1e 100644 --- a/src/System.Management.Automation/engine/remoting/commands/JobRepository.cs +++ b/src/System.Management.Automation/engine/remoting/commands/JobRepository.cs @@ -132,9 +132,9 @@ internal Dictionary Dictionary #region Private Members - private Dictionary _repository = new Dictionary(); - private object _syncObject = new object(); // object for synchronization - private string _identifier; + private readonly Dictionary _repository = new Dictionary(); + private readonly object _syncObject = new object(); // object for synchronization + private readonly string _identifier; #endregion Private Members } diff --git a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs index 4fe43f53cee..658876c1d8d 100644 --- a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs +++ b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs @@ -857,7 +857,7 @@ protected override void ProcessRecord() { if (Full) { - string exampleModulesToImport = "'MyCustomModule', @{ ModuleName = 'MyCustomModule'; ModuleVersion = '1.0.0.0'; GUID = '4d30d5f0-cb16-4898-812d-f20a6c596bdf' }"; + const string exampleModulesToImport = "'MyCustomModule', @{ ModuleName = 'MyCustomModule'; ModuleVersion = '1.0.0.0'; GUID = '4d30d5f0-cb16-4898-812d-f20a6c596bdf' }"; result.Append(SessionConfigurationUtils.ConfigFragment(ConfigFileConstants.ModulesToImport, RemotingErrorIdStrings.DISCModulesToImportComment, exampleModulesToImport, streamWriter, true)); } } @@ -1105,7 +1105,7 @@ protected override void ProcessRecord() SessionConfigurationUtils.CombineStringArray(_assembliesToLoad), streamWriter, isExample)); } - result.Append("}"); + result.Append('}'); streamWriter.Write(result.ToString()); } @@ -1621,7 +1621,7 @@ protected override void ProcessRecord() // Modules to import if (_modulesToImport == null) { - string exampleModulesToImport = "'MyCustomModule', @{ ModuleName = 'MyCustomModule'; ModuleVersion = '1.0.0.0'; GUID = '4d30d5f0-cb16-4898-812d-f20a6c596bdf' }"; + const string exampleModulesToImport = "'MyCustomModule', @{ ModuleName = 'MyCustomModule'; ModuleVersion = '1.0.0.0'; GUID = '4d30d5f0-cb16-4898-812d-f20a6c596bdf' }"; result.Append(SessionConfigurationUtils.ConfigFragment(ConfigFileConstants.ModulesToImport, RemotingErrorIdStrings.DISCModulesToImportComment, exampleModulesToImport, streamWriter, true)); } else @@ -1837,7 +1837,7 @@ protected override void ProcessRecord() result.Append(SessionConfigurationUtils.ConfigFragment(ConfigFileConstants.AssembliesToLoad, RemotingErrorIdStrings.DISCAssembliesToLoadComment, SessionConfigurationUtils.CombineStringArray(_assembliesToLoad), streamWriter, isExample)); - result.Append("}"); + result.Append('}'); streamWriter.Write(result.ToString()); } @@ -1855,7 +1855,7 @@ protected override void ProcessRecord() /// /// Utility methods for configuration file commands. /// - internal class SessionConfigurationUtils + internal static class SessionConfigurationUtils { /// /// This routine builds a fragment of the config file @@ -1944,7 +1944,7 @@ internal static string CombineHashtable(IDictionary table, StreamWriter writer, sb.Append("@{"); - var keys = table.Keys.Cast().OrderBy(x => x); + var keys = table.Keys.Cast().OrderBy(static x => x); foreach (var key in keys) { sb.Append(writer.NewLine); diff --git a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationOptionCommand.cs b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationOptionCommand.cs index c1b3b3b7326..fdd9d5fc6fe 100644 --- a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationOptionCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationOptionCommand.cs @@ -441,7 +441,7 @@ internal override Hashtable ConstructOptionsAsHashtable() [OutputType(typeof(WSManConfigurationOption))] public sealed class NewPSTransportOptionCommand : PSCmdlet { - private WSManConfigurationOption _option = new WSManConfigurationOption(); + private readonly WSManConfigurationOption _option = new WSManConfigurationOption(); /// /// MaxIdleTimeoutSec. diff --git a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionOptionCommand.cs b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionOptionCommand.cs index 5ad0df8910c..bb7641d2e5b 100644 --- a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionOptionCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionOptionCommand.cs @@ -48,7 +48,7 @@ public int MaximumRedirection public SwitchParameter NoCompression { get; set; } /// - /// If true then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server + /// If then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server /// which can result in a faster session creation time. This option won't have any effect if the remote machine has /// already loaded the profile (i.e. in another session). /// @@ -136,11 +136,13 @@ public int OpenTimeout { get { - return _openTimeout.HasValue ? _openTimeout.Value : - RunspaceConnectionInfo.DefaultOpenTimeout; + return _openTimeout ?? RunspaceConnectionInfo.DefaultOpenTimeout; } - set { _openTimeout = value; } + set + { + _openTimeout = value; + } } private int? _openTimeout; @@ -161,11 +163,13 @@ public int CancelTimeout { get { - return _cancelTimeout.HasValue ? _cancelTimeout.Value : - BaseTransportManager.ClientCloseTimeoutMs; + return _cancelTimeout ?? BaseTransportManager.ClientCloseTimeoutMs; } - set { _cancelTimeout = value; } + set + { + _cancelTimeout = value; + } } private int? _cancelTimeout; @@ -183,11 +187,13 @@ public int IdleTimeout { get { - return _idleTimeout.HasValue ? _idleTimeout.Value - : RunspaceConnectionInfo.DefaultIdleTimeout; + return _idleTimeout ?? RunspaceConnectionInfo.DefaultIdleTimeout; } - set { _idleTimeout = value; } + set + { + _idleTimeout = value; + } } private int? _idleTimeout; @@ -290,11 +296,13 @@ public int OperationTimeout { get { - return (_operationtimeout.HasValue ? _operationtimeout.Value : - BaseTransportManager.ClientDefaultOperationTimeoutMs); + return _operationtimeout ?? BaseTransportManager.ClientDefaultOperationTimeoutMs; } - set { _operationtimeout = value; } + set + { + _operationtimeout = value; + } } private int? _operationtimeout; @@ -308,7 +316,10 @@ public int OperationTimeout [Parameter] public SwitchParameter NoEncryption { - get { return _noencryption; } + get + { + return _noencryption; + } set { @@ -327,7 +338,10 @@ public SwitchParameter NoEncryption [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "UTF")] public SwitchParameter UseUTF16 { - get { return _useutf16; } + get + { + return _useutf16; + } set { diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs index de046236536..d4f5ca427ab 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs @@ -15,6 +15,7 @@ using System.Management.Automation.Remoting; using System.Management.Automation.Remoting.Client; using System.Management.Automation.Runspaces; +using System.Threading; using Dbg = System.Management.Automation.Diagnostics; @@ -146,7 +147,7 @@ internal string GetMessage(string resourceString, params object[] args) #region Private Members - private static string s_LOCALHOST = "localhost"; + private static readonly string s_LOCALHOST = "localhost"; // private PSETWTracer tracer = PSETWTracer.GetETWTracer(PSKeyword.Cmdlets); @@ -285,6 +286,7 @@ internal struct SSHConnection public string KeyFilePath; public int Port; public string Subsystem; + public int ConnectingTimeout; } /// @@ -620,7 +622,7 @@ public virtual string ApplicationName [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ContainerIdParameterSet)] [Parameter(ParameterSetName = PSRemotingBaseCmdlet.VMIdParameterSet)] [Parameter(ParameterSetName = PSRemotingBaseCmdlet.VMNameParameterSet)] - public virtual int ThrottleLimit { set; get; } = 0; + public virtual int ThrottleLimit { get; set; } = 0; /// /// A complete URI(s) specified for the remote computer and shell to @@ -669,7 +671,10 @@ public virtual PSSessionOption SessionOption return _sessionOption; } - set { _sessionOption = value; } + set + { + _sessionOption = value; + } } private PSSessionOption _sessionOption; @@ -707,7 +712,10 @@ public virtual AuthenticationMechanism Authentication [Parameter(ParameterSetName = NewPSSessionCommand.UriParameterSet)] public virtual string CertificateThumbprint { - get { return _thumbPrint; } + get + { + return _thumbPrint; + } set { @@ -755,6 +763,20 @@ public virtual string KeyFilePath set; } + /// + /// Gets or sets a value for the SSH subsystem to use for the remote connection. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)] + public virtual string Subsystem { get; set; } + + /// + /// Gets or sets a value in milliseconds that limits the time allowed for an SSH connection to be established. + /// Default timeout value is infinite. + /// + [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)] + public virtual int ConnectingTimeout { get; set; } = Timeout.Infinite; + /// /// This parameter specifies that SSH is used to establish the remote /// connection and act as the remoting transport. By default WinRM is used @@ -783,13 +805,6 @@ public virtual Hashtable[] SSHConnection set; } - /// - /// This parameter specifies the SSH subsystem to use for the remote connection. - /// - [Parameter(ValueFromPipelineByPropertyName = true, - ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)] - public virtual string Subsystem { get; set; } - #endregion #endregion Properties @@ -850,6 +865,7 @@ internal static void ValidateSpecifiedAuthentication(PSCredential credential, st private const string IdentityFilePathAlias = "IdentityFilePath"; private const string PortParameter = "Port"; private const string SubsystemParameter = "Subsystem"; + private const string ConnectingTimeoutParameter = "ConnectingTimeout"; #endregion @@ -896,7 +912,7 @@ protected void ParseSshHostName(string hostname, out string host, out string use /// Array of SSHConnection objects. internal SSHConnection[] ParseSSHConnectionHashTable() { - List connections = new List(); + List connections = new(); foreach (var item in this.SSHConnection) { if (item.ContainsKey(ComputerNameParameter) && item.ContainsKey(HostNameAlias)) @@ -909,7 +925,7 @@ internal SSHConnection[] ParseSSHConnectionHashTable() throw new PSArgumentException(RemotingErrorIdStrings.SSHConnectionDuplicateKeyPath); } - SSHConnection connectionInfo = new SSHConnection(); + SSHConnection connectionInfo = new(); foreach (var key in item.Keys) { string paramName = key as string; @@ -949,6 +965,10 @@ internal SSHConnection[] ParseSSHConnectionHashTable() { connectionInfo.Subsystem = GetSSHConnectionStringParameter(item[paramName]); } + else if (paramName.Equals(ConnectingTimeoutParameter, StringComparison.OrdinalIgnoreCase)) + { + connectionInfo.ConnectingTimeout = GetSSHConnectionIntParameter(item[paramName]); + } else { throw new PSArgumentException( @@ -1442,9 +1462,9 @@ protected void CreateHelpersForSpecifiedSSHComputerNames() { ParseSshHostName(computerName, out string host, out string userName, out int port); - var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port, this.Subsystem); + var sshConnectionInfo = new SSHConnectionInfo(userName, host, KeyFilePath, port, Subsystem, ConnectingTimeout); var typeTable = TypeTable.LoadDefaultTypeFiles(); - var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace; + var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, Host, typeTable) as RemoteRunspace; var pipeline = CreatePipeline(remoteRunspace); var operation = new ExecutionCmdletHelperComputerName(remoteRunspace, pipeline); @@ -1465,7 +1485,8 @@ protected void CreateHelpersForSpecifiedSSHHashComputerNames() sshConnection.ComputerName, sshConnection.KeyFilePath, sshConnection.Port, - sshConnection.Subsystem); + sshConnection.Subsystem, + sshConnection.ConnectingTimeout); var typeTable = TypeTable.LoadDefaultTypeFiles(); var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace; var pipeline = CreatePipeline(remoteRunspace); @@ -1879,7 +1900,7 @@ internal Pipeline CreatePipeline(RemoteRunspace remoteRunspace) /// /// Check the powershell version of the remote server. /// - private string GetRemoteServerPsVersion(RemoteRunspace remoteRunspace) + private static string GetRemoteServerPsVersion(RemoteRunspace remoteRunspace) { if (remoteRunspace.ConnectionInfo is NewProcessConnectionInfo) { @@ -2427,15 +2448,15 @@ private List GetUsingVariableValues(List paramUsi /// /// /// A list of UsingExpressionAsts ordered by the StartOffset. - private List GetUsingVariables(ScriptBlock localScriptBlock) + private static List GetUsingVariables(ScriptBlock localScriptBlock) { if (localScriptBlock == null) { throw new ArgumentNullException(nameof(localScriptBlock), "Caller needs to make sure the parameter value is not null"); } - var allUsingExprs = UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(localScriptBlock.Ast); - return allUsingExprs.Select(usingExpr => UsingExpressionAst.ExtractUsingVariable((UsingExpressionAst)usingExpr)).ToList(); + var allUsingExprs = UsingExpressionAstSearcher.FindAllUsingExpressions(localScriptBlock.Ast); + return allUsingExprs.Select(static usingExpr => UsingExpressionAst.ExtractUsingVariable((UsingExpressionAst)usingExpr)).ToList(); } #endregion "UsingExpression Utilities" @@ -3003,9 +3024,9 @@ private Dictionary GetMatchingRunspacesByVMNameContainerId(bool var matchingRunspaceInfos = remoteRunspaceInfos .Where(session => (supportWildChar ? inputNamePattern.IsMatch(session.VMName) : inputName.Equals(session.ContainerId)) && - ((sessionNamePattern == null) ? true : sessionNamePattern.IsMatch(session.Name)) && + (sessionNamePattern == null || sessionNamePattern.IsMatch(session.Name)) && QueryRunspaces.TestRunspaceState(session.Runspace, filterState) && - ((configurationNamePattern == null) ? true : configurationNamePattern.IsMatch(session.ConfigurationName)) && + (configurationNamePattern == null || configurationNamePattern.IsMatch(session.ConfigurationName)) && (session.ComputerType == computerType)) .ToList(); @@ -3063,7 +3084,7 @@ private Dictionary GetMatchingRunspacesByVMNameContainerIdSessi : inputName.Equals(session.ContainerId)) && sessionInstanceId.Equals(session.InstanceId) && QueryRunspaces.TestRunspaceState(session.Runspace, filterState) && - ((configurationNamePattern == null) ? true : configurationNamePattern.IsMatch(session.ConfigurationName)) && + (configurationNamePattern == null || configurationNamePattern.IsMatch(session.ConfigurationName)) && (session.ComputerType == computerType)) .ToList(); @@ -3106,9 +3127,9 @@ private Dictionary GetMatchingRunspacesByVMId(bool writeobject, var matchingRunspaceInfos = remoteRunspaceInfos .Where(session => vmId.Equals(session.VMId) && - ((sessionNamePattern == null) ? true : sessionNamePattern.IsMatch(session.Name)) && + (sessionNamePattern == null || sessionNamePattern.IsMatch(session.Name)) && QueryRunspaces.TestRunspaceState(session.Runspace, filterState) && - ((configurationNamePattern == null) ? true : configurationNamePattern.IsMatch(session.ConfigurationName)) && + (configurationNamePattern == null || configurationNamePattern.IsMatch(session.ConfigurationName)) && (session.ComputerType == TargetMachineType.VirtualMachine)) .ToList(); @@ -3143,7 +3164,7 @@ private Dictionary GetMatchingRunspacesByVMIdSessionInstanceId( .Where(session => vmId.Equals(session.VMId) && sessionInstanceId.Equals(session.InstanceId) && QueryRunspaces.TestRunspaceState(session.Runspace, filterState) && - ((configurationNamePattern == null) ? true : configurationNamePattern.IsMatch(session.ConfigurationName)) && + (configurationNamePattern == null || configurationNamePattern.IsMatch(session.ConfigurationName)) && (session.ComputerType == TargetMachineType.VirtualMachine)) .ToList(); @@ -3257,8 +3278,8 @@ internal Exception InternalException /// internal Runspace PipelineRunspace { - set; get; + set; } #region Runspace Debug @@ -3472,7 +3493,7 @@ internal class ExecutionCmdletHelperComputerName : ExecutionCmdletHelper /// Determines if the command should be invoked and then disconnect the /// remote runspace from the client. /// - private bool _invokeAndDisconnect; + private readonly bool _invokeAndDisconnect; /// /// The remote runspace created using the computer name @@ -4328,7 +4349,7 @@ public PSSessionOption() public bool NoCompression { get; set; } = false; /// - /// If true then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server + /// If then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server /// which can result in a faster session creation time. This option won't have any effect if the remote machine has /// already loaded the profile (i.e. in another session). /// @@ -4353,7 +4374,10 @@ public PSSessionOption() /// public AuthenticationMechanism ProxyAuthentication { - get { return _proxyAuthentication; } + get + { + return _proxyAuthentication; + } set { diff --git a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs index a7751e0138d..996b043d77e 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs @@ -39,7 +39,7 @@ public class EnterPSSessionCommand : PSRemotingBaseCmdlet /// /// Disable ThrottleLimit parameter inherited from base class. /// - public new int ThrottleLimit { set { } get { return 0; } } + public new int ThrottleLimit { get { return 0; } set { } } private ObjectStream _stream; private RemoteRunspace _tempRunspace; @@ -651,10 +651,7 @@ private void WriteInvalidArgumentError(PSRemotingErrorId errorId, string resourc private void HandleURIDirectionReported(object sender, RemoteDataEventArgs eventArgs) { string message = StringUtil.Format(RemotingErrorIdStrings.URIRedirectWarningToHost, eventArgs.Data.OriginalString); - Action streamObject = delegate (Cmdlet cmdlet) - { - cmdlet.WriteWarning(message); - }; + Action streamObject = (Cmdlet cmdlet) => cmdlet.WriteWarning(message); _stream.Write(streamObject); } @@ -794,15 +791,13 @@ private RemoteRunspace GetRunspaceMatchingCondition( /// private RemoteRunspace GetRunspaceMatchingRunspaceId(Guid remoteRunspaceId) { - Predicate condition = delegate (PSSession info) - { - return info.InstanceId == remoteRunspaceId; - }; - PSRemotingErrorId tooFew = PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedRunspaceId; - PSRemotingErrorId tooMany = PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedRunspaceId; - string tooFewResourceString = RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedRunspaceId; - string tooManyResourceString = RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedRunspaceId; - return GetRunspaceMatchingCondition(condition, tooFew, tooMany, tooFewResourceString, tooManyResourceString, remoteRunspaceId); + return GetRunspaceMatchingCondition( + condition: info => info.InstanceId == remoteRunspaceId, + tooFew: PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedRunspaceId, + tooMany: PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedRunspaceId, + tooFewResourceString: RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedRunspaceId, + tooManyResourceString: RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedRunspaceId, + errorArgument: remoteRunspaceId); } /// @@ -810,15 +805,13 @@ private RemoteRunspace GetRunspaceMatchingRunspaceId(Guid remoteRunspaceId) /// private RemoteRunspace GetRunspaceMatchingSessionId(int sessionId) { - Predicate condition = delegate (PSSession info) - { - return info.Id == sessionId; - }; - PSRemotingErrorId tooFew = PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedSessionId; - PSRemotingErrorId tooMany = PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedSessionId; - string tooFewResourceString = RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedSessionId; - string tooManyResourceString = RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedSessionId; - return GetRunspaceMatchingCondition(condition, tooFew, tooMany, tooFewResourceString, tooManyResourceString, sessionId); + return GetRunspaceMatchingCondition( + condition: info => info.Id == sessionId, + tooFew: PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedSessionId, + tooMany: PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedSessionId, + tooFewResourceString: RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedSessionId, + tooManyResourceString: RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedSessionId, + errorArgument: sessionId); } /// @@ -826,16 +819,13 @@ private RemoteRunspace GetRunspaceMatchingSessionId(int sessionId) /// private RemoteRunspace GetRunspaceMatchingName(string name) { - Predicate condition = delegate (PSSession info) - { - // doing case-insensitive match for session name - return info.Name.Equals(name, StringComparison.OrdinalIgnoreCase); - }; - PSRemotingErrorId tooFew = PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedName; - PSRemotingErrorId tooMany = PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedName; - string tooFewResourceString = RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedName; - string tooManyResourceString = RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedName; - return GetRunspaceMatchingCondition(condition, tooFew, tooMany, tooFewResourceString, tooManyResourceString, name); + return GetRunspaceMatchingCondition( + condition: info => info.Name.Equals(name, StringComparison.OrdinalIgnoreCase), + tooFew: PSRemotingErrorId.RemoteRunspaceNotAvailableForSpecifiedName, + tooMany: PSRemotingErrorId.RemoteRunspaceHasMultipleMatchesForSpecifiedName, + tooFewResourceString: RemotingErrorIdStrings.RemoteRunspaceNotAvailableForSpecifiedName, + tooManyResourceString: RemotingErrorIdStrings.RemoteRunspaceHasMultipleMatchesForSpecifiedName, + errorArgument: name); } private Job FindJobForRunspace(Guid id) @@ -1093,7 +1083,7 @@ private RemoteRunspace GetRunspaceForVMSession() /// /// Create temporary remote runspace. /// - private RemoteRunspace CreateTemporaryRemoteRunspaceForPowerShellDirect(PSHost host, RunspaceConnectionInfo connectionInfo) + private static RemoteRunspace CreateTemporaryRemoteRunspaceForPowerShellDirect(PSHost host, RunspaceConnectionInfo connectionInfo) { // Create and open the runspace. TypeTable typeTable = TypeTable.LoadDefaultTypeFiles(); @@ -1272,7 +1262,7 @@ private RemoteRunspace GetRunspaceForContainerSession() private RemoteRunspace GetRunspaceForSSHSession() { ParseSshHostName(HostName, out string host, out string userName, out int port); - var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port, this.Subsystem); + var sshConnectionInfo = new SSHConnectionInfo(userName, host, KeyFilePath, port, Subsystem, ConnectingTimeout); var typeTable = TypeTable.LoadDefaultTypeFiles(); // Use the class _tempRunspace field while the runspace is being opened so that StopProcessing can be handled at that time. diff --git a/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs b/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs index aa804f68691..97585f1de1b 100644 --- a/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs @@ -281,7 +281,10 @@ public SwitchParameter AutoRemoveJob [Parameter()] public SwitchParameter WriteEvents { - get { return _writeStateChangedEvents; } + get + { + return _writeStateChangedEvents; + } set { @@ -294,7 +297,10 @@ public SwitchParameter WriteEvents [Parameter()] public SwitchParameter WriteJobInResults { - get { return _outputJobFirst; } + get + { + return _outputJobFirst; + } set { @@ -768,7 +774,7 @@ private void WriteJobResults(Job job) // There is a bug in V2 that only remoting jobs work // with Receive-Job. This is being fixed - if (!(job is Job2) && job.UsesResultsCollection) + if (job is not Job2 && job.UsesResultsCollection) { // extract results and handle them Collection results = ReadAll(job.Results); diff --git a/src/System.Management.Automation/engine/remoting/commands/ReceivePSSession.cs b/src/System.Management.Automation/engine/remoting/commands/ReceivePSSession.cs index 500c5032a49..98d2afa3b5f 100644 --- a/src/System.Management.Automation/engine/remoting/commands/ReceivePSSession.cs +++ b/src/System.Management.Automation/engine/remoting/commands/ReceivePSSession.cs @@ -125,7 +125,10 @@ public class ReceivePSSessionCommand : PSRemotingCmdlet ParameterSetName = ReceivePSSessionCommand.ComputerInstanceIdParameterSet)] public string ApplicationName { - get { return _appName; } + get + { + return _appName; + } set { @@ -150,7 +153,10 @@ public string ApplicationName ParameterSetName = ReceivePSSessionCommand.ConnectionUriInstanceIdParameterSet)] public string ConfigurationName { - get { return _shell; } + get + { + return _shell; + } set { @@ -257,7 +263,10 @@ public SwitchParameter AllowRedirection [Credential()] public PSCredential Credential { - get { return _psCredential; } + get + { + return _psCredential; + } set { @@ -278,7 +287,10 @@ public PSCredential Credential [Parameter(ParameterSetName = ReceivePSSessionCommand.ConnectionUriInstanceIdParameterSet)] public AuthenticationMechanism Authentication { - get { return _authentication; } + get + { + return _authentication; + } set { @@ -300,7 +312,10 @@ public AuthenticationMechanism Authentication [Parameter(ParameterSetName = ReceivePSSessionCommand.ConnectionUriInstanceIdParameterSet)] public string CertificateThumbprint { - get { return _thumbprint; } + get + { + return _thumbprint; + } set { @@ -1115,7 +1130,7 @@ private void ConnectSessionToJob(PSSession session, PSRemotingJob job = null) /// Session to connect. /// Optional exception object. /// Connected session or null. - private PSSession ConnectSession(PSSession session, out Exception ex) + private static PSSession ConnectSession(PSSession session, out Exception ex) { ex = null; @@ -1158,8 +1173,7 @@ private PSSession ConnectSession(PSSession session, out Exception ex) /// PSSession disconnected runspace object. private PSSession TryGetSessionFromServer(PSSession session) { - RemoteRunspace remoteRunspace = session.Runspace as RemoteRunspace; - if (remoteRunspace == null) + if (!(session.Runspace is RemoteRunspace remoteRunspace)) { return null; } @@ -1303,7 +1317,7 @@ private void WriteInvalidArgumentError(PSRemotingErrorId errorId, string resourc private RemotePipeline _remotePipeline; private Job _job; private ManualResetEvent _stopPipelineReceive; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); #endregion } diff --git a/src/System.Management.Automation/engine/remoting/commands/RemoveJob.cs b/src/System.Management.Automation/engine/remoting/commands/RemoveJob.cs index 2eed427a6ff..f8c0a71a0df 100644 --- a/src/System.Management.Automation/engine/remoting/commands/RemoveJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/RemoveJob.cs @@ -540,7 +540,7 @@ internal List FindJobsMatchingByFilter(bool writeobject) /// /// /// - private bool FindJobsMatchingByFilterHelper(List matches, List jobsToSearch) + private static bool FindJobsMatchingByFilterHelper(List matches, List jobsToSearch) { // check that filter only has job properties // if so, filter on one at a time using helpers. @@ -1011,7 +1011,7 @@ private void HandleStopJobCompleted(object sender, AsyncCompletedEventArgs event #region Private Members - private HashSet _pendingJobs = new HashSet(); + private readonly HashSet _pendingJobs = new HashSet(); private readonly ManualResetEvent _waitForJobs = new ManualResetEvent(false); private readonly Dictionary> _cleanUpActions = diff --git a/src/System.Management.Automation/engine/remoting/commands/ResumeJob.cs b/src/System.Management.Automation/engine/remoting/commands/ResumeJob.cs index 1b5fcd7bbe4..6545f74f7b7 100644 --- a/src/System.Management.Automation/engine/remoting/commands/ResumeJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/ResumeJob.cs @@ -185,7 +185,7 @@ private void HandleResumeJobCompleted(object sender, AsyncCompletedEventArgs eve { foreach ( var e in - parentJob.ExecutionError.Where(e => e.FullyQualifiedErrorId == "ContainerParentJobResumeAsyncError") + parentJob.ExecutionError.Where(static e => e.FullyQualifiedErrorId == "ContainerParentJobResumeAsyncError") ) { if (e.Exception is InvalidJobStateException) diff --git a/src/System.Management.Automation/engine/remoting/commands/StartJob.cs b/src/System.Management.Automation/engine/remoting/commands/StartJob.cs index 29e6640279f..90e10bb8f44 100644 --- a/src/System.Management.Automation/engine/remoting/commands/StartJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/StartJob.cs @@ -505,7 +505,10 @@ public virtual ScriptBlock InitializationScript [ValidateNotNullOrEmpty] public virtual Version PSVersion { - get { return _psVersion; } + get + { + return _psVersion; + } set { diff --git a/src/System.Management.Automation/engine/remoting/commands/SuspendJob.cs b/src/System.Management.Automation/engine/remoting/commands/SuspendJob.cs index 1c729d8df74..983db3d76ba 100644 --- a/src/System.Management.Automation/engine/remoting/commands/SuspendJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/SuspendJob.cs @@ -292,7 +292,7 @@ private void ProcessExecutionErrorsAndReleaseWaitHandle(Job job) { foreach ( var e in - parentJob.ExecutionError.Where(e => e.FullyQualifiedErrorId == "ContainerParentJobSuspendAsyncError") + parentJob.ExecutionError.Where(static e => e.FullyQualifiedErrorId == "ContainerParentJobSuspendAsyncError") ) { if (e.Exception is InvalidJobStateException) diff --git a/src/System.Management.Automation/engine/remoting/commands/WaitJob.cs b/src/System.Management.Automation/engine/remoting/commands/WaitJob.cs index f023ca168a7..626dd5133d1 100644 --- a/src/System.Management.Automation/engine/remoting/commands/WaitJob.cs +++ b/src/System.Management.Automation/engine/remoting/commands/WaitJob.cs @@ -105,10 +105,7 @@ private void InvokeEndProcessingAction() } // Invoke action outside lock. - if (endProcessingAction != null) - { - endProcessingAction(); - } + endProcessingAction?.Invoke(); } private void CleanUpEndProcessing() @@ -247,7 +244,7 @@ private Job GetOneBlockedJob() { lock (_jobTrackingLock) { - return _jobsToWaitFor.Find(j => j.JobStateInfo.State == JobState.Blocked); + return _jobsToWaitFor.Find(static j => j.JobStateInfo.State == JobState.Blocked); } } diff --git a/src/System.Management.Automation/engine/remoting/commands/getrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/getrunspacecommand.cs index 2a3c92dfcf3..d1fc8ef531a 100644 --- a/src/System.Management.Automation/engine/remoting/commands/getrunspacecommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/getrunspacecommand.cs @@ -78,7 +78,10 @@ public class GetPSSessionCommand : PSRunspaceCmdlet, IDisposable ParameterSetName = GetPSSessionCommand.ComputerInstanceIdParameterSet)] public string ApplicationName { - get { return _appName; } + get + { + return _appName; + } set { @@ -202,7 +205,10 @@ public override Guid[] InstanceId [Credential()] public PSCredential Credential { - get { return _psCredential; } + get + { + return _psCredential; + } set { @@ -223,7 +229,10 @@ public PSCredential Credential [Parameter(ParameterSetName = GetPSSessionCommand.ConnectionUriInstanceIdParameterSet)] public AuthenticationMechanism Authentication { - get { return _authentication; } + get + { + return _authentication; + } set { @@ -245,7 +254,10 @@ public AuthenticationMechanism Authentication [Parameter(ParameterSetName = GetPSSessionCommand.ConnectionUriInstanceIdParameterSet)] public string CertificateThumbprint { - get { return _thumbprint; } + get + { + return _thumbprint; + } set { @@ -525,10 +537,10 @@ public void Dispose() #region Private Members // Object used for querying remote runspaces. - private QueryRunspaces _queryRunspaces = new QueryRunspaces(); + private readonly QueryRunspaces _queryRunspaces = new QueryRunspaces(); // Object to collect output data from multiple threads. - private ObjectStream _stream = new ObjectStream(); + private readonly ObjectStream _stream = new ObjectStream(); #endregion } diff --git a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs index 5645272bbe2..d4a0a3e7508 100644 --- a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs @@ -91,7 +91,10 @@ public class NewPSSessionCommand : PSRemotingBaseCmdlet, IDisposable [Credential()] public override PSCredential Credential { - get { return base.Credential; } + get + { + return base.Credential; + } set { @@ -397,10 +400,7 @@ private void OnRunspacePSEventReceived(object sender, PSEventArgs e) private void HandleURIDirectionReported(object sender, RemoteDataEventArgs eventArgs) { string message = StringUtil.Format(RemotingErrorIdStrings.URIRedirectWarningToHost, eventArgs.Data.OriginalString); - Action warningWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteWarning(message); - }; + Action warningWriter = (Cmdlet cmdlet) => cmdlet.WriteWarning(message); _stream.Write(warningWriter); } @@ -450,10 +450,7 @@ private void HandleRunspaceStateChanged(object sender, OperationStateEventArgs s this.RunspaceRepository.Add(remoteRunspaceInfo); - Action outputWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteObject(remoteRunspaceInfo); - }; + Action outputWriter = (Cmdlet cmdlet) => cmdlet.WriteObject(remoteRunspaceInfo); if (writer.IsOpen) { writer.Write(outputWriter); @@ -536,7 +533,7 @@ private void HandleRunspaceStateChanged(object sender, OperationStateEventArgs s transErrorCode, _defaultFQEID); - if (WSManNativeApi.ERROR_WSMAN_NO_LOGON_SESSION_EXIST == transErrorCode) + if (transErrorCode == WSManNativeApi.ERROR_WSMAN_NO_LOGON_SESSION_EXIST) { errorDetails += System.Environment.NewLine + string.Format(System.Globalization.CultureInfo.CurrentCulture, RemotingErrorIdStrings.RemotingErrorNoLogonSessionExist); } @@ -546,7 +543,7 @@ private void HandleRunspaceStateChanged(object sender, OperationStateEventArgs s ErrorCategory.OpenError, null, null, null, null, null, errorDetails, null); - Action errorWriter = delegate (Cmdlet cmdlet) + Action errorWriter = (Cmdlet cmdlet) => { // // In case of PSDirectException, we should output the precise error message @@ -589,10 +586,7 @@ private void HandleRunspaceStateChanged(object sender, OperationStateEventArgs s (connectionUri != null) ? connectionUri.AbsoluteUri : string.Empty); - Action verboseWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteVerbose(message); - }; + Action verboseWriter = (Cmdlet cmdlet) => cmdlet.WriteVerbose(message); if (writer.IsOpen) { writer.Write(verboseWriter); @@ -607,10 +601,7 @@ private void HandleRunspaceStateChanged(object sender, OperationStateEventArgs s "PSSessionStateClosed", ErrorCategory.OpenError, remoteRunspace); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); if (writer.IsOpen) { writer.Write(errorWriter); @@ -673,7 +664,7 @@ private List CreateRunspacesWhenRunspaceParameterSpecified() if (originalWSManConnectionInfo != null) { newWSManConnectionInfo = originalWSManConnectionInfo.Copy(); - newWSManConnectionInfo.EnableNetworkAccess = (newWSManConnectionInfo.EnableNetworkAccess || EnableNetworkAccess) ? true : false; + newWSManConnectionInfo.EnableNetworkAccess = newWSManConnectionInfo.EnableNetworkAccess || EnableNetworkAccess; newConnectionInfo = newWSManConnectionInfo; } else @@ -716,10 +707,7 @@ private List CreateRunspacesWhenRunspaceParameterSpecified() ErrorRecord errorRecord = new ErrorRecord(e, "CreateRemoteRunspaceFailed", ErrorCategory.InvalidArgument, remoteRunspaceInfo); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); writer.Write(errorWriter); } } @@ -853,10 +841,7 @@ private List CreateRunspacesWhenComputerNameParameterSpecified() ErrorRecord errorRecord = new ErrorRecord(e, "CreateRemoteRunspaceFailed", ErrorCategory.InvalidArgument, resolvedComputerNames[i]); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); writer.Write(errorWriter); } } @@ -1107,7 +1092,8 @@ private List CreateRunspacesForSSHHostParameterSet() host, this.KeyFilePath, port, - Subsystem); + Subsystem, + ConnectingTimeout); var typeTable = TypeTable.LoadDefaultTypeFiles(); string rsName = GetRunspaceName(index, out int rsIdUnused); index++; @@ -1133,7 +1119,8 @@ private List CreateRunspacesForSSHHostHashParameterSet() sshConnection.ComputerName, sshConnection.KeyFilePath, sshConnection.Port, - sshConnection.Subsystem); + sshConnection.Subsystem, + sshConnection.ConnectingTimeout); var typeTable = TypeTable.LoadDefaultTypeFiles(); string rsName = GetRunspaceName(index, out int rsIdUnused); index++; @@ -1262,10 +1249,7 @@ private void WriteErrorCreateRemoteRunspaceFailed(Exception e, Uri uri) ErrorRecord errorRecord = new ErrorRecord(e, "CreateRemoteRunspaceFailed", ErrorCategory.InvalidArgument, uri); - Action errorWriter = delegate (Cmdlet cmdlet) - { - cmdlet.WriteError(errorRecord); - }; + Action errorWriter = (Cmdlet cmdlet) => cmdlet.WriteError(errorRecord); writer.Write(errorWriter); } @@ -1274,10 +1258,10 @@ private void WriteErrorCreateRemoteRunspaceFailed(Exception e, Uri uri) #region Private Members private ThrottleManager _throttleManager = new ThrottleManager(); - private ObjectStream _stream = new ObjectStream(); + private readonly ObjectStream _stream = new ObjectStream(); // event that signals that all operations are // complete (including closing if any) - private ManualResetEvent _operationsComplete = new ManualResetEvent(true); + private readonly ManualResetEvent _operationsComplete = new ManualResetEvent(true); // the initial state is true because when no // operations actually take place as in case of a // parameter binding exception, then Dispose is @@ -1286,13 +1270,13 @@ private void WriteErrorCreateRemoteRunspaceFailed(Exception e, Uri uri) // BeginProcessing() // list of runspaces to dispose - private List _toDispose = new List(); + private readonly List _toDispose = new List(); // List of runspace connect operations. Need to keep for cleanup. - private Collection> _allOperations = new Collection>(); + private readonly Collection> _allOperations = new Collection>(); // Default FQEID. - private string _defaultFQEID = "PSSessionOpenFailed"; + private readonly string _defaultFQEID = "PSSessionOpenFailed"; #endregion Private Members } @@ -1310,7 +1294,7 @@ internal class OpenRunspaceOperation : IThrottleOperation, IDisposable private bool _startComplete; private bool _stopComplete; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); internal RemoteRunspace OperatedRunspace { get; } @@ -1375,7 +1359,7 @@ internal override void StopOperation() // b) To ensure all callbacks are fired by manually invoking callbacks and handling // any exceptions thrown on this thread. (ThrottleManager will not respond if it doesn't // get a start/stop complete callback). - private List> _internalCallbacks = new List>(); + private readonly List> _internalCallbacks = new List>(); internal override event EventHandler OperationComplete { diff --git a/src/System.Management.Automation/engine/remoting/commands/remotingcommandutil.cs b/src/System.Management.Automation/engine/remoting/commands/remotingcommandutil.cs index ad233ccb481..094dcedc6ad 100644 --- a/src/System.Management.Automation/engine/remoting/commands/remotingcommandutil.cs +++ b/src/System.Management.Automation/engine/remoting/commands/remotingcommandutil.cs @@ -87,7 +87,7 @@ internal static void CheckRemotingCmdletPrerequisites() return; #else bool notSupported = true; - string WSManKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\WSMAN\\"; + const string WSManKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\WSMAN\\"; CheckHostRemotingPrerequisites(); @@ -222,4 +222,3 @@ internal static void CheckIfPowerShellVersionIsInstalled(Version version) } } } - diff --git a/src/System.Management.Automation/engine/remoting/common/AsyncObject.cs b/src/System.Management.Automation/engine/remoting/common/AsyncObject.cs index a68a6f78869..88a329cb6b6 100644 --- a/src/System.Management.Automation/engine/remoting/common/AsyncObject.cs +++ b/src/System.Management.Automation/engine/remoting/common/AsyncObject.cs @@ -22,7 +22,7 @@ internal class AsyncObject where T : class /// /// Value was set. /// - private ManualResetEvent _valueWasSet; + private readonly ManualResetEvent _valueWasSet; /// /// Value. @@ -32,7 +32,7 @@ internal T Value get { bool result = _valueWasSet.WaitOne(); - if (result == false) + if (!result) { _value = null; } diff --git a/src/System.Management.Automation/engine/remoting/common/DispatchTable.cs b/src/System.Management.Automation/engine/remoting/common/DispatchTable.cs index 035d39ac84e..9dc073e6616 100644 --- a/src/System.Management.Automation/engine/remoting/common/DispatchTable.cs +++ b/src/System.Management.Automation/engine/remoting/common/DispatchTable.cs @@ -33,7 +33,7 @@ internal class DispatchTable where T : class /// /// Response async objects. /// - private Dictionary> _responseAsyncObjects = new Dictionary>(); + private readonly Dictionary> _responseAsyncObjects = new Dictionary>(); /// /// Next call id. diff --git a/src/System.Management.Automation/engine/remoting/common/Indexer.cs b/src/System.Management.Automation/engine/remoting/common/Indexer.cs index 0f6b70482c8..019eb9dfce4 100644 --- a/src/System.Management.Automation/engine/remoting/common/Indexer.cs +++ b/src/System.Management.Automation/engine/remoting/common/Indexer.cs @@ -16,12 +16,12 @@ internal class Indexer : IEnumerable, IEnumerator /// /// Current. /// - private int[] _current; + private readonly int[] _current; /// /// Lengths. /// - private int[] _lengths; + private readonly int[] _lengths; /// /// Current. @@ -49,7 +49,7 @@ internal Indexer(int[] lengths) /// Check lengths non negative. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - private bool CheckLengthsNonNegative(int[] lengths) + private static bool CheckLengthsNonNegative(int[] lengths) { for (int i = 0; i < lengths.Length; ++i) { diff --git a/src/System.Management.Automation/engine/remoting/common/ObjectRef.cs b/src/System.Management.Automation/engine/remoting/common/ObjectRef.cs index 25534b59a30..a5ae0dab19c 100644 --- a/src/System.Management.Automation/engine/remoting/common/ObjectRef.cs +++ b/src/System.Management.Automation/engine/remoting/common/ObjectRef.cs @@ -20,7 +20,7 @@ internal class ObjectRef where T : class /// /// Old value. /// - private T _oldValue; + private readonly T _oldValue; /// /// Old value. diff --git a/src/System.Management.Automation/engine/remoting/common/RemoteSessionHyperVSocket.cs b/src/System.Management.Automation/engine/remoting/common/RemoteSessionHyperVSocket.cs index 730a4aa9a2d..e71c5e82581 100644 --- a/src/System.Management.Automation/engine/remoting/common/RemoteSessionHyperVSocket.cs +++ b/src/System.Management.Automation/engine/remoting/common/RemoteSessionHyperVSocket.cs @@ -17,7 +17,7 @@ internal class HyperVSocketEndPoint : EndPoint { #region Members - private System.Net.Sockets.AddressFamily _addressFamily; + private readonly System.Net.Sockets.AddressFamily _addressFamily; private Guid _vmId; private Guid _serviceId; @@ -53,7 +53,7 @@ public Guid ServiceId { get { return _serviceId; } - set { _vmId = value; } + set { _serviceId = value; } } #endregion @@ -138,7 +138,7 @@ internal sealed class RemoteSessionHyperVSocketServer : IDisposable #region Members private readonly object _syncObject; - private PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); + private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); #endregion @@ -337,9 +337,9 @@ internal sealed class RemoteSessionHyperVSocketClient : IDisposable #region Members private readonly object _syncObject; - private PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); + private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); - private static ManualResetEvent s_connectDone = + private static readonly ManualResetEvent s_connectDone = new ManualResetEvent(false); #endregion diff --git a/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs b/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs index 49dbe5b8551..2c154f79990 100644 --- a/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs +++ b/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs @@ -110,7 +110,7 @@ internal static string CreateProcessPipeName( // There is a limit of 104 characters in total including the temp path to the named pipe file // on non-Windows systems, so we'll convert the starttime to hex and just take the first 8 characters. #if UNIX - .Append(proc.StartTime.ToFileTime().ToString("X8").Substring(1,8)) + .Append(proc.StartTime.ToFileTime().ToString("X8").AsSpan(1, 8)) #else .Append(proc.StartTime.ToFileTime().ToString(CultureInfo.InvariantCulture)) #endif @@ -341,7 +341,7 @@ public sealed class RemoteSessionNamedPipeServer : IDisposable #region Members private readonly object _syncObject; - private PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); + private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); private const string _threadName = "IPC Listener Thread"; private const int _namedPipeBufferSizeForRemoting = 32768; @@ -349,7 +349,7 @@ public sealed class RemoteSessionNamedPipeServer : IDisposable private const int _maxPipePathLengthMacOS = 104; // Singleton server. - private static object s_syncObject; + private static readonly object s_syncObject; internal static RemoteSessionNamedPipeServer IPCNamedPipeServer; internal static bool IPCNamedPipeServerEnabled; @@ -466,7 +466,7 @@ internal RemoteSessionNamedPipeServer( /// Named pipe core name. /// /// NamedPipeServerStream. - private NamedPipeServerStream CreateNamedPipe( + private static NamedPipeServerStream CreateNamedPipe( string serverName, string namespaceName, string coreName, @@ -744,7 +744,7 @@ private void WaitForConnection() [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")] private void ProcessListeningThread(object state) { - string processId = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture); + string processId = Environment.ProcessId.ToString(CultureInfo.InvariantCulture); string appDomainName = NamedPipeUtils.GetCurrentAppDomainName(); // Logging. @@ -900,10 +900,7 @@ internal static void RunServerMode(string configurationName) ManualResetEventSlim clientConnectionEnded = new ManualResetEventSlim(false); IPCNamedPipeServer.ListenerEnded -= OnIPCNamedPipeServerEnded; - IPCNamedPipeServer.ListenerEnded += (sender, e) => - { - clientConnectionEnded.Set(); - }; + IPCNamedPipeServer.ListenerEnded += (sender, e) => clientConnectionEnded.Set(); // Wait for server to service a single client connection. clientConnectionEnded.Wait(); @@ -1010,7 +1007,7 @@ internal class NamedPipeClientBase : IDisposable #region Members private NamedPipeClientStream _clientPipeStream; - private PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); + private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource(); protected string _pipeName; @@ -1144,9 +1141,8 @@ private RemoteSessionNamedPipeClient() /// /// Target process object for pipe. /// AppDomain name or null for default AppDomain. - public RemoteSessionNamedPipeClient( - System.Diagnostics.Process process, string appDomainName) : - this(NamedPipeUtils.CreateProcessPipeName(process, appDomainName)) + public RemoteSessionNamedPipeClient(System.Diagnostics.Process process, string appDomainName) + : this(NamedPipeUtils.CreateProcessPipeName(process, appDomainName)) { } /// @@ -1154,9 +1150,8 @@ public RemoteSessionNamedPipeClient( /// /// Target process Id for pipe. /// AppDomain name or null for default AppDomain. - public RemoteSessionNamedPipeClient( - int procId, string appDomainName) : - this(NamedPipeUtils.CreateProcessPipeName(procId, appDomainName)) + public RemoteSessionNamedPipeClient(int procId, string appDomainName) + : this(NamedPipeUtils.CreateProcessPipeName(procId, appDomainName)) { } /// @@ -1294,9 +1289,6 @@ public ContainerSessionNamedPipeClient( /// protected override NamedPipeClientStream DoConnect(int timeout) { - // Create pipe flags. - uint pipeFlags = NamedPipeNative.FILE_FLAG_OVERLAPPED; - // // WaitNamedPipe API is not supported by Windows Server container now, so we need to repeatedly // attempt connection to pipe server until timeout expires. @@ -1309,13 +1301,13 @@ protected override NamedPipeClientStream DoConnect(int timeout) { // Get handle to pipe. pipeHandle = NamedPipeNative.CreateFile( - _pipeName, - NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, - 0, - IntPtr.Zero, - NamedPipeNative.OPEN_EXISTING, - pipeFlags, - IntPtr.Zero); + lpFileName: _pipeName, + dwDesiredAccess: NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, + dwShareMode: 0, + SecurityAttributes: IntPtr.Zero, + dwCreationDisposition: NamedPipeNative.OPEN_EXISTING, + dwFlagsAndAttributes: NamedPipeNative.FILE_FLAG_OVERLAPPED, + hTemplateFile: IntPtr.Zero); int lastError = Marshal.GetLastWin32Error(); if (pipeHandle.IsInvalid) diff --git a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs index c134cde53cc..49763f43a13 100644 --- a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs +++ b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs @@ -208,7 +208,10 @@ public CultureInfo UICulture /// public int OpenTimeout { - get { return _openTimeout; } + get + { + return _openTimeout; + } set { @@ -598,7 +601,10 @@ public override AuthenticationMechanism AuthenticationMechanism /// public override string CertificateThumbprint { - get { return _thumbPrint; } + get + { + return _thumbPrint; + } set { @@ -642,7 +648,7 @@ public override string CertificateThumbprint public bool UseCompression { get; set; } = true; /// - /// If true then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server + /// If then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server /// which can result in a faster session creation time. This option won't have any effect if the remote machine has /// already loaded the profile (i.e. in another session). /// @@ -675,7 +681,10 @@ public override string CertificateThumbprint /// public AuthenticationMechanism ProxyAuthentication { - get { return _proxyAuthentication; } + get + { + return _proxyAuthentication; + } set { @@ -702,7 +711,10 @@ public AuthenticationMechanism ProxyAuthentication /// public PSCredential ProxyCredential { - get { return _proxyCredential; } + get + { + return _proxyCredential; + } set { @@ -829,8 +841,21 @@ public WSManConnectionInfo(string scheme, string computerName, int port, string /// max server life timeout and open timeout are /// default in this case [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Scope = "member", Target = "System.Management.Automation.Runspaces.WSManConnectionInfo.#.ctor(System.String,System.String,System.Int32,System.String,System.String,System.Management.Automation.PSCredential)", MessageId = "4#")] - public WSManConnectionInfo(string scheme, string computerName, int port, string appName, string shellUri, PSCredential credential) : - this(scheme, computerName, port, appName, shellUri, credential, DefaultOpenTimeout) + public WSManConnectionInfo( + string scheme, + string computerName, + int port, + string appName, + string shellUri, + PSCredential credential) + : this( + scheme, + computerName, + port, + appName, + shellUri, + credential, + DefaultOpenTimeout) { } @@ -844,9 +869,20 @@ public WSManConnectionInfo(string scheme, string computerName, int port, string /// /// [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "4#")] - public WSManConnectionInfo(bool useSsl, string computerName, int port, string appName, string shellUri, - PSCredential credential) : - this(useSsl ? DefaultSslScheme : DefaultScheme, computerName, port, appName, shellUri, credential) + public WSManConnectionInfo( + bool useSsl, + string computerName, + int port, + string appName, + string shellUri, + PSCredential credential) + : this( + useSsl ? DefaultSslScheme : DefaultScheme, + computerName, + port, + appName, + shellUri, + credential) { } @@ -860,8 +896,22 @@ public WSManConnectionInfo(bool useSsl, string computerName, int port, string ap /// /// [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "4#")] - public WSManConnectionInfo(bool useSsl, string computerName, int port, string appName, string shellUri, PSCredential credential, int openTimeout) : - this(useSsl ? DefaultSslScheme : DefaultScheme, computerName, port, appName, shellUri, credential, openTimeout) + public WSManConnectionInfo( + bool useSsl, + string computerName, + int port, + string appName, + string shellUri, + PSCredential credential, + int openTimeout) + : this( + useSsl ? DefaultSslScheme : DefaultScheme, + computerName, + port, + appName, + shellUri, + credential, + openTimeout) { } @@ -1096,7 +1146,7 @@ internal override BaseClientSessionTransportManager CreateClientSessionTransport #region Private Methods - private string ResolveShellUri(string shell) + private static string ResolveShellUri(string shell) { string resolvedShellUri = shell; if (string.IsNullOrEmpty(resolvedShellUri)) @@ -1104,10 +1154,9 @@ private string ResolveShellUri(string shell) resolvedShellUri = DefaultShellUri; } - if (resolvedShellUri.IndexOf( - System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix, StringComparison.OrdinalIgnoreCase) == -1) + if (!resolvedShellUri.Contains(WSManNativeApi.ResourceURIPrefix, StringComparison.OrdinalIgnoreCase)) { - resolvedShellUri = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix + resolvedShellUri; + resolvedShellUri = WSManNativeApi.ResourceURIPrefix + resolvedShellUri; } return resolvedShellUri; @@ -1124,8 +1173,7 @@ private string ResolveShellUri(string shell) internal static T ExtractPropertyAsWsManConnectionInfo(RunspaceConnectionInfo rsCI, string property, T defaultValue) { - WSManConnectionInfo wsCI = rsCI as WSManConnectionInfo; - if (wsCI == null) + if (!(rsCI is WSManConnectionInfo wsCI)) { return defaultValue; } @@ -1415,8 +1463,7 @@ internal bool UseDefaultWSManPort /// /// Default value for shell. /// - private const string DefaultShellUri = - System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix + RemotingConstants.DefaultShellName; + private const string DefaultShellUri = WSManNativeApi.ResourceURIPrefix + RemotingConstants.DefaultShellName; /// /// Default credentials - null indicates credentials of @@ -1546,7 +1593,10 @@ public override string ComputerName /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -1668,7 +1718,10 @@ public int ProcessId /// public string AppDomainName { - get { return _appDomainName; } + get + { + return _appDomainName; + } set { @@ -1701,9 +1754,8 @@ public NamedPipeConnectionInfo() /// Initializes a new instance of the class. /// /// Process Id to connect to. - public NamedPipeConnectionInfo( - int processId) : - this(processId, string.Empty, _defaultOpenTimeout) + public NamedPipeConnectionInfo(int processId) + : this(processId, string.Empty, _defaultOpenTimeout) { } /// @@ -1711,10 +1763,8 @@ public NamedPipeConnectionInfo( /// /// Process Id to connect to. /// Application domain name to connect to, or default AppDomain if blank. - public NamedPipeConnectionInfo( - int processId, - string appDomainName) : - this(processId, appDomainName, _defaultOpenTimeout) + public NamedPipeConnectionInfo(int processId, string appDomainName) + : this(processId, appDomainName, _defaultOpenTimeout) { } /// @@ -1737,9 +1787,8 @@ public NamedPipeConnectionInfo( /// Initializes a new instance of the class. /// /// Pipe name to connect to. - public NamedPipeConnectionInfo( - string customPipeName) : - this(customPipeName, _defaultOpenTimeout) + public NamedPipeConnectionInfo(string customPipeName) + : this(customPipeName, _defaultOpenTimeout) { } /// @@ -1779,7 +1828,10 @@ public override string ComputerName /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -1855,6 +1907,20 @@ internal override BaseClientSessionTransportManager CreateClientSessionTransport /// public sealed class SSHConnectionInfo : RunspaceConnectionInfo { + #region Constants + + /// + /// Default value for subsystem. + /// + private const string DefaultSubsystem = "powershell"; + + /// + /// Default value is infinite timeout. + /// + private const int DefaultConnectingTimeoutTime = Timeout.Infinite; + + #endregion + #region Properties /// @@ -1893,6 +1959,16 @@ private string Subsystem set; } + /// + /// Gets or sets a time in milliseconds after which a connection attempt is terminated. + /// Default value (-1) never times out and a connection attempt waits indefinitely. + /// + public int ConnectingTimeout + { + get; + set; + } + #endregion #region Constructors @@ -1916,11 +1992,12 @@ public SSHConnectionInfo( { if (computerName == null) { throw new PSArgumentNullException(nameof(computerName)); } - this.UserName = userName; - this.ComputerName = computerName; - this.KeyFilePath = keyFilePath; - this.Port = 0; - this.Subsystem = DefaultSubsystem; + UserName = userName; + ComputerName = computerName; + KeyFilePath = keyFilePath; + Port = 0; + Subsystem = DefaultSubsystem; + ConnectingTimeout = DefaultConnectingTimeoutTime; } /// @@ -1937,8 +2014,7 @@ public SSHConnectionInfo( int port) : this(userName, computerName, keyFilePath) { ValidatePortInRange(port); - - this.Port = port; + Port = port; } /// @@ -1954,12 +2030,29 @@ public SSHConnectionInfo( string computerName, string keyFilePath, int port, - string subsystem) : this(userName, computerName, keyFilePath) + string subsystem) : this(userName, computerName, keyFilePath, port) { - ValidatePortInRange(port); + Subsystem = string.IsNullOrEmpty(subsystem) ? DefaultSubsystem : subsystem; + } - this.Port = port; - this.Subsystem = (string.IsNullOrEmpty(subsystem)) ? DefaultSubsystem : subsystem; + /// + /// Initializes a new instance of SSHConnectionInfo. + /// + /// Name of user. + /// Name of computer. + /// Path of key file. + /// Port number for connection (default 22). + /// Subsystem to use (default 'powershell'). + /// Timeout time for terminating connection attempt. + public SSHConnectionInfo( + string userName, + string computerName, + string keyFilePath, + int port, + string subsystem, + int connectingTimeout) : this(userName, computerName, keyFilePath, port, subsystem) + { + ConnectingTimeout = connectingTimeout; } #endregion @@ -2012,11 +2105,12 @@ public override string CertificateThumbprint internal override RunspaceConnectionInfo InternalCopy() { SSHConnectionInfo newCopy = new SSHConnectionInfo(); - newCopy.ComputerName = this.ComputerName; - newCopy.UserName = this.UserName; - newCopy.KeyFilePath = this.KeyFilePath; - newCopy.Port = this.Port; - newCopy.Subsystem = this.Subsystem; + newCopy.ComputerName = ComputerName; + newCopy.UserName = UserName; + newCopy.KeyFilePath = KeyFilePath; + newCopy.Port = Port; + newCopy.Subsystem = Subsystem; + newCopy.ConnectingTimeout = ConnectingTimeout; return newCopy; } @@ -2051,9 +2145,9 @@ internal int StartSSHProcess( { string filePath = string.Empty; #if UNIX - string sshCommand = "ssh"; + const string sshCommand = "ssh"; #else - string sshCommand = "ssh.exe"; + const string sshCommand = "ssh.exe"; #endif var context = Runspaces.LocalPipeline.GetExecutionContextFromTLS(); if (context != null) @@ -2097,7 +2191,7 @@ internal int StartSSHProcess( startInfo.ArgumentList.Add(string.Format(CultureInfo.InvariantCulture, @"-i ""{0}""", this.KeyFilePath)); } - // pass "-l login_name" commmand line argument to ssh if UserName is set + // pass "-l login_name" command line argument to ssh if UserName is set // if UserName is not set, then ssh will use User from ssh_config if defined else the environment user by default if (!string.IsNullOrEmpty(this.UserName)) { @@ -2133,14 +2227,10 @@ internal int StartSSHProcess( return StartSSHProcessImpl(startInfo, out stdInWriterVar, out stdOutReaderVar, out stdErrReaderVar); } - #endregion - - #region Constants - - /// - /// Default value for subsystem. - /// - private const string DefaultSubsystem = "powershell"; + internal void KillSSHProcess(int pid) + { + KillSSHProcessImpl(pid); + } #endregion @@ -2180,6 +2270,16 @@ private static int StartSSHProcessImpl( return pid; } + private static void KillSSHProcessImpl(int pid) + { + // killing a zombie might or might not return ESRCH, so we ignore kill's return value + Platform.NonWindowsKillProcess(pid); + + // block while waiting for process to die + // shouldn't take long after SIGKILL + Platform.NonWindowsWaitPid(pid, false); + } + #region UNIX Create Process // @@ -2289,7 +2389,7 @@ private static string[] ParseArgv(ProcessStartInfo psi) var argsToParse = String.Join(" ", psi.ArgumentList).Trim(); var argsLength = argsToParse.Length; - for (int i=0; i public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -2893,7 +3001,10 @@ public override string CertificateThumbprint /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -3459,7 +3570,7 @@ private void GetContainerPropertiesInternal() } } - if (ContainerObRoot == null) + if (ContainerObRoot == null) { throw new PSInvalidOperationException(RemotingErrorIdStrings.CannotGetHostInteropTypes); } @@ -3494,7 +3605,7 @@ private void GetContainerPropertiesInternal() /// /// Run some tasks on MTA thread if needed. /// - private void RunOnMTAThread(ThreadStart threadProc) + private static void RunOnMTAThread(ThreadStart threadProc) { if (Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA) { @@ -3513,7 +3624,7 @@ private void RunOnMTAThread(ThreadStart threadProc) /// /// Get error message from the thrown exception. /// - private string GetErrorMessageFromException(Exception e) + private static string GetErrorMessageFromException(Exception e) { string errorMessage = e.Message; diff --git a/src/System.Management.Automation/engine/remoting/common/RunspacePoolStateInfo.cs b/src/System.Management.Automation/engine/remoting/common/RunspacePoolStateInfo.cs index e863a7c795e..fb4807351c3 100644 --- a/src/System.Management.Automation/engine/remoting/common/RunspacePoolStateInfo.cs +++ b/src/System.Management.Automation/engine/remoting/common/RunspacePoolStateInfo.cs @@ -17,7 +17,7 @@ namespace System.Management.Automation public sealed class RunspacePoolStateInfo { /// - /// State of the runspace pool when this event occured. + /// State of the runspace pool when this event occurred. /// public RunspacePoolState State { get; } diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs index 9188263fd54..aa22e45682a 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; +using System.Management.Automation; using System.Management.Automation.Host; using System.Management.Automation.Internal; using System.Management.Automation.Remoting; @@ -73,7 +74,7 @@ public RemotingEncodingException(string message, Exception innerException, Error /// internal static class RemotingConstants { - internal static readonly Version HostVersion = new Version(1, 0, 0, 0); + internal static readonly Version HostVersion = PSVersionInfo.PSVersion; internal static readonly Version ProtocolVersionWin7RC = new Version(2, 0); internal static readonly Version ProtocolVersionWin7RTM = new Version(2, 1); @@ -1196,10 +1197,10 @@ internal static RemoteDataObject GenerateRunspacePoolStateInfo( // Add Reason property if (stateInfo.Reason != null) { - // If Reason is of not type IContainsErrorRecord, a new ErrorRecord is - // created using this errorId - string errorId = "RemoteRunspaceStateInfoReason"; - PSNoteProperty exceptionProperty = GetExceptionProperty(stateInfo.Reason, errorId, ErrorCategory.NotSpecified); + PSNoteProperty exceptionProperty = GetExceptionProperty( + exception: stateInfo.Reason, + errorId: "RemoteRunspaceStateInfoReason", + category: ErrorCategory.NotSpecified); dataAsPSObject.Properties.Add(exceptionProperty); } @@ -1515,12 +1516,10 @@ internal static RemoteDataObject GeneratePowerShellStateInfo(PSInvocationStateIn // Add exception property if (stateInfo.Reason != null) { - // If Reason is of not type IContainsErrorRecord, - // a new ErrorRecord is created using this errorId - string errorId = "RemotePSInvocationStateInfoReason"; - PSNoteProperty exceptionProperty = - GetExceptionProperty(stateInfo.Reason, errorId, - ErrorCategory.NotSpecified); + PSNoteProperty exceptionProperty = GetExceptionProperty( + exception: stateInfo.Reason, + errorId: "RemotePSInvocationStateInfoReason", + category: ErrorCategory.NotSpecified); dataAsPSObject.Properties.Add(exceptionProperty); } @@ -1563,6 +1562,9 @@ internal static ErrorRecord GetErrorRecordFromException(Exception exception) /// /// Gets a Note Property for the exception. /// + /// + /// If is of not type IContainsErrorRecord, a new ErrorRecord is created. + /// /// /// ErrorId to use if exception is not of type IContainsErrorRecord. /// ErrorCategory to use if exception is not of type IContainsErrorRecord. @@ -1802,7 +1804,7 @@ internal static IEnumerable EnumerateListProperty(PSObject psObject, strin } } - internal static IEnumerable> EnumerateHashtableProperty(PSObject psObject, string propertyName) + internal static IEnumerable> EnumerateHashtableProperty(PSObject psObject, string propertyName) { if (psObject == null) { @@ -1819,9 +1821,9 @@ internal static IEnumerable> EnumerateHashtable { foreach (DictionaryEntry e in h) { - KeyType key = ConvertPropertyValueTo(propertyName, e.Key); - ValueType value = ConvertPropertyValueTo(propertyName, e.Value); - yield return new KeyValuePair(key, value); + TKey key = ConvertPropertyValueTo(propertyName, e.Key); + TValue value = ConvertPropertyValueTo(propertyName, e.Value); + yield return new KeyValuePair(key, value); } } } @@ -2088,8 +2090,7 @@ internal static object GetPowerShellOutput(object data) /// PSInvocationInfo. internal static PSInvocationStateInfo GetPowerShellStateInfo(object data) { - PSObject dataAsPSObject = data as PSObject; - if (dataAsPSObject == null) + if (!(data is PSObject dataAsPSObject)) { throw new PSRemotingDataStructureException( RemotingErrorIdStrings.DecodingErrorForPowerShellStateInfo); @@ -2237,7 +2238,7 @@ internal static PowerShell GetCommandDiscoveryPipeline(object data) } else { - module = new string[] { "" }; + module = new string[] { string.Empty }; } ModuleSpecification[] fullyQualifiedName = null; @@ -2281,7 +2282,7 @@ internal static PowerShell GetCommandDiscoveryPipeline(object data) /// Gets the NoInput setting from the specified data. /// /// Data to decode. - /// true if there is no pipeline input; false otherwise. + /// if there is no pipeline input; otherwise. internal static bool GetNoInput(object data) { PSObject dataAsPSObject = PSObject.AsPSObject(data); @@ -2298,7 +2299,7 @@ internal static bool GetNoInput(object data) /// Gets the AddToHistory setting from the specified data. /// /// Data to decode. - /// true if there is addToHistory data; false otherwise. + /// if there is addToHistory data; otherwise. internal static bool GetAddToHistory(object data) { PSObject dataAsPSObject = PSObject.AsPSObject(data); @@ -2315,7 +2316,7 @@ internal static bool GetAddToHistory(object data) /// Gets the IsNested setting from the specified data. /// /// Data to decode. - /// true if there is IsNested data; false otherwise. + /// if there is IsNested data; otherwise. internal static bool GetIsNested(object data) { PSObject dataAsPSObject = PSObject.AsPSObject(data); @@ -2357,9 +2358,7 @@ internal static RemoteStreamOptions GetRemoteStreamOptions(object data) /// RemoteSessionCapability object. internal static RemoteSessionCapability GetSessionCapability(object data) { - PSObject dataAsPSObject = data as PSObject; - - if (dataAsPSObject == null) + if (!(data is PSObject dataAsPSObject)) { throw new PSRemotingDataStructureException( RemotingErrorIdStrings.CantCastRemotingDataToPSObject, data.GetType().FullName); diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteDebuggingCapability.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteDebuggingCapability.cs index ee993615029..3162fa3d2bd 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteDebuggingCapability.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteDebuggingCapability.cs @@ -13,7 +13,7 @@ namespace System.Management.Automation.Remoting /// version on the server. These capabilities will be used in remote debugging sessions to /// determine what is supported by the server. /// - internal class RemoteDebuggingCapability + internal sealed class RemoteDebuggingCapability { private readonly HashSet _supportedCommands = new HashSet(); diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHost.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHost.cs index 414676dffed..c29be13487b 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHost.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHost.cs @@ -42,12 +42,12 @@ internal string MethodName /// /// Method info. /// - private RemoteHostMethodInfo _methodInfo; + private readonly RemoteHostMethodInfo _methodInfo; /// /// Call id. /// - private long _callId; + private readonly long _callId; /// /// Call id. @@ -198,7 +198,7 @@ internal void ExecuteVoidMethod(PSHost clientHost) /// /// Get remote runspace to close. /// - private RemoteRunspace GetRemoteRunspaceToClose(PSHost clientHost) + private static RemoteRunspace GetRemoteRunspaceToClose(PSHost clientHost) { // Figure out if we need to close the remote runspace. Return null if we don't. @@ -440,7 +440,7 @@ internal Collection PerformSecurityChecksOnHostMessage(string co /// /// Caption to modify. /// New modified caption. - private string ModifyCaption(string caption) + private static string ModifyCaption(string caption) { string pscaption = CredUI.PromptForCredential_DefaultCaption; @@ -465,7 +465,7 @@ private string ModifyCaption(string caption) /// computername to include in the /// message /// Message which contains a warning as well. - private string ModifyMessage(string message, string computerName) + private static string ModifyMessage(string message, string computerName) { string modifiedMessage = PSRemotingErrorInvariants.FormatResourceString( RemotingErrorIdStrings.RemoteHostPromptForCredentialModifiedMessage, @@ -485,7 +485,7 @@ private string ModifyMessage(string message, string computerName) /// Resource string to use. /// A constructed remote host call message /// which will display the warning. - private RemoteHostCall ConstructWarningMessageForSecureString(string computerName, + private static RemoteHostCall ConstructWarningMessageForSecureString(string computerName, string resourceString) { string warning = PSRemotingErrorInvariants.FormatResourceString( @@ -506,7 +506,7 @@ private RemoteHostCall ConstructWarningMessageForSecureString(string computerNam /// in warning /// A constructed remote host call message /// which will display the warning. - private RemoteHostCall ConstructWarningMessageForGetBufferContents(string computerName) + private static RemoteHostCall ConstructWarningMessageForGetBufferContents(string computerName) { string warning = PSRemotingErrorInvariants.FormatResourceString( RemotingErrorIdStrings.RemoteHostGetBufferContents, @@ -530,7 +530,7 @@ internal class RemoteHostResponse /// /// Call id. /// - private long _callId; + private readonly long _callId; /// /// Call id. @@ -546,17 +546,17 @@ internal long CallId /// /// Method id. /// - private RemoteHostMethodId _methodId; + private readonly RemoteHostMethodId _methodId; /// /// Return value. /// - private object _returnValue; + private readonly object _returnValue; /// /// Exception. /// - private Exception _exception; + private readonly Exception _exception; /// /// Constructor for RemoteHostResponse. diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHostEncoder.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHostEncoder.cs index 8a60ce277a8..3ffc278a817 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHostEncoder.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHostEncoder.cs @@ -24,7 +24,7 @@ namespace System.Management.Automation.Remoting /// guarantees that transmitting on the wire will not change the encoded /// object's type. /// - internal class RemoteHostEncoder + internal static class RemoteHostEncoder { /// /// Is known type. @@ -744,7 +744,7 @@ private static IDictionary DecodeObjectDictionary(PSObject psObject, Type dictio /// private static T SafelyGetBaseObject(PSObject psObject) { - if (psObject == null || psObject.BaseObject == null || !(psObject.BaseObject is T)) + if (psObject == null || psObject.BaseObject == null || psObject.BaseObject is not T) { throw RemoteHostExceptions.NewDecodingFailedException(); } @@ -771,7 +771,7 @@ private static T SafelyCastObject(object obj) private static T SafelyGetPropertyValue(PSObject psObject, string key) { PSPropertyInfo propertyInfo = psObject.Properties[key]; - if (propertyInfo == null || propertyInfo.Value == null || !(propertyInfo.Value is T)) + if (propertyInfo == null || propertyInfo.Value == null || propertyInfo.Value is not T) { throw RemoteHostExceptions.NewDecodingFailedException(); } diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteSessionCapability.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteSessionCapability.cs index 982a6e66cb1..d95ba65ec90 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteSessionCapability.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteSessionCapability.cs @@ -21,10 +21,10 @@ internal class RemoteSessionCapability { #region DO NOT REMOVE OR RENAME THESE FIELDS - it will break remoting compatibility with Windows PowerShell - private Version _psversion; - private Version _serversion; + private readonly Version _psversion; + private readonly Version _serversion; private Version _protocolVersion; - private RemotingDestination _remotingDestination; + private readonly RemotingDestination _remotingDestination; private static byte[] _timeZoneInByteFormat; private TimeZoneInfo _timeZone; @@ -171,14 +171,14 @@ internal enum HostDefaultDataId /// /// The HostDefaultData class. /// - internal class HostDefaultData + internal sealed class HostDefaultData { /// /// Data. /// #region DO NOT REMOVE OR RENAME THESE FIELDS - it will break remoting compatibility with Windows PowerShell - private Dictionary data; + private readonly Dictionary data; #endregion @@ -359,7 +359,7 @@ internal bool IsHostNull /// /// Is host ui null. /// - private bool _isHostUINull; + private readonly bool _isHostUINull; /// /// Is host ui null. @@ -375,7 +375,7 @@ internal bool IsHostUINull /// /// Is host raw ui null. /// - private bool _isHostRawUINull; + private readonly bool _isHostRawUINull; private readonly bool _isHostNull; diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemotingDataObject.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemotingDataObject.cs index 664c2a91ae0..c9887c54991 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemotingDataObject.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemotingDataObject.cs @@ -213,7 +213,7 @@ private void SerializeHeader(Stream streamToWriteTo) return; } - private void SerializeUInt(uint data, Stream streamToWriteTo) + private static void SerializeUInt(uint data, Stream streamToWriteTo) { Dbg.Assert(streamToWriteTo != null, "stream to write to cannot be null"); @@ -241,7 +241,7 @@ private static uint DeserializeUInt(Stream serializedDataStream) return result; } - private void SerializeGuid(Guid guid, Stream streamToWriteTo) + private static void SerializeGuid(Guid guid, Stream streamToWriteTo) { Dbg.Assert(streamToWriteTo != null, "stream to write to cannot be null"); @@ -267,7 +267,7 @@ private static Guid DeserializeGuid(Stream serializedDataStream) #endregion } - internal class RemoteDataObject : RemoteDataObject + internal sealed class RemoteDataObject : RemoteDataObject { #region Constructors / Factory diff --git a/src/System.Management.Automation/engine/remoting/common/fragmentor.cs b/src/System.Management.Automation/engine/remoting/common/fragmentor.cs index da3446e6cfc..8517fb059f5 100644 --- a/src/System.Management.Automation/engine/remoting/common/fragmentor.cs +++ b/src/System.Management.Automation/engine/remoting/common/fragmentor.cs @@ -105,7 +105,7 @@ internal FragmentedRemoteObject(byte[] blob, long objectId, long fragmentId, ObjectId = objectId; FragmentId = fragmentId; - IsStartFragment = (fragmentId == 0) ? true : false; + IsStartFragment = fragmentId == 0; IsEndFragment = isEndFragment; _blob = blob; @@ -142,7 +142,10 @@ internal FragmentedRemoteObject(byte[] blob, long objectId, long fragmentId, /// internal int BlobLength { - get { return _blobLength; } + get + { + return _blobLength; + } set { @@ -156,7 +159,10 @@ internal int BlobLength /// internal byte[] Blob { - get { return _blob; } + get + { + return _blob; + } set { @@ -205,10 +211,10 @@ internal byte[] Blob /// internal byte[] GetBytes() { - int objectIdSize = 8; // number of bytes of long - int fragmentIdSize = 8; // number of bytes of long - int flagsSize = 1; // 1 byte for IsEndOfFrag and IsControl - int blobLengthSize = 4; // number of bytes of int + const int objectIdSize = 8; // number of bytes of long + const int fragmentIdSize = 8; // number of bytes of long + const int flagsSize = 1; // 1 byte for IsEndOfFrag and IsControl + const int blobLengthSize = 4; // number of bytes of int int totalLength = objectIdSize + fragmentIdSize + flagsSize + blobLengthSize + BlobLength; @@ -427,7 +433,7 @@ internal static int GetBlobLength(byte[] fragmentBytes, int startIndex) internal class SerializedDataStream : Stream, IDisposable { [TraceSourceAttribute("SerializedDataStream", "SerializedDataStream")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("SerializedDataStream", "SerializedDataStream"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("SerializedDataStream", "SerializedDataStream"); #region Global Constants private static long s_objectIdSequenceNumber = 0; @@ -437,20 +443,20 @@ internal class SerializedDataStream : Stream, IDisposable #region Private Data private bool _isEntered; - private FragmentedRemoteObject _currentFragment; + private readonly FragmentedRemoteObject _currentFragment; private long _fragmentId; - private int _fragmentSize; - private object _syncObject; + private readonly int _fragmentSize; + private readonly object _syncObject; private bool _isDisposed; - private bool _notifyOnWriteFragmentImmediately; + private readonly bool _notifyOnWriteFragmentImmediately; // MemoryStream does not dynamically resize as data is read. This will waste // lot of memory as data sent on the network will still be there in memory. // To avoid this a queue of memory streams (each stream is of fragmentsize) // is created..so after data is sent the MemoryStream is disposed there by // clearing resources. - private Queue _queuedStreams; + private readonly Queue _queuedStreams; private MemoryStream _writeStream; private MemoryStream _readStream; private int _writeOffset; @@ -578,7 +584,7 @@ public override void Write(byte[] buffer, int offset, int count) if (dataLeftInTheFragment > 0) { int amountToWriteIntoFragment = (amountLeft > dataLeftInTheFragment) ? dataLeftInTheFragment : amountLeft; - amountLeft = amountLeft - amountToWriteIntoFragment; + amountLeft -= amountToWriteIntoFragment; // Write data into fragment Array.Copy(buffer, offsetToReadFrom, _currentFragment.Blob, _currentFragment.BlobLength, amountToWriteIntoFragment); @@ -799,7 +805,7 @@ private void WriteCurrentFragmentAndReset() } int amountToWriteIntoStream = (amountLeft > dataLeftInWriteStream) ? dataLeftInWriteStream : amountLeft; - amountLeft = amountLeft - amountToWriteIntoStream; + amountLeft -= amountToWriteIntoStream; // write data _writeStream.Position = _writeOffset; _writeStream.Write(data, offSetToReadFrom, amountToWriteIntoStream); @@ -811,10 +817,7 @@ private void WriteCurrentFragmentAndReset() } // call the callback since we have data available - if (_onDataAvailableCallback != null) - { - _onDataAvailableCallback(data, _currentFragment.IsEndFragment); - } + _onDataAvailableCallback?.Invoke(data, _currentFragment.IsEndFragment); // prepare a new fragment _currentFragment.FragmentId = ++_fragmentId; @@ -886,9 +889,11 @@ protected override void Dispose(bool disposing) /// /// public override bool CanRead { get { return true; } } + /// /// public override bool CanSeek { get { return false; } } + /// /// public override bool CanWrite { get { return true; } } @@ -896,6 +901,7 @@ protected override void Dispose(bool disposing) /// Gets the length of the stream in bytes. /// public override long Length { get { return _length; } } + /// /// public override long Position @@ -911,6 +917,7 @@ public override long Position public override void Flush() { } + /// /// /// @@ -920,6 +927,7 @@ public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } + /// /// /// @@ -957,13 +965,13 @@ public override void SetLength(long value) internal class Fragmentor { #region Global Constants - private static UTF8Encoding s_utf8Encoding = new UTF8Encoding(); + private static readonly UTF8Encoding s_utf8Encoding = new UTF8Encoding(); // This const defines the default depth to be used for serializing objects for remoting. private const int SerializationDepthForRemoting = 1; #endregion private int _fragmentSize; - private SerializationContext _serializationContext; + private readonly SerializationContext _serializationContext; #region Constructor diff --git a/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs b/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs index fa1bcb7da86..4e755893886 100644 --- a/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs +++ b/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs @@ -75,7 +75,9 @@ public class PSStreamObject /// /// public PSStreamObjectType ObjectType { get; set; } + internal object Value { get; set; } + internal Guid Id { get; set; } internal PSStreamObject(PSStreamObjectType objectType, object value, Guid id) @@ -89,8 +91,8 @@ internal PSStreamObject(PSStreamObjectType objectType, object value, Guid id) /// /// /// - public PSStreamObject(PSStreamObjectType objectType, object value) : - this(objectType, value, Guid.Empty) + public PSStreamObject(PSStreamObjectType objectType, object value) + : this(objectType, value, Guid.Empty) { } @@ -489,7 +491,7 @@ internal static void AddSourceJobNoteProperty(PSObject psObj, Guid instanceId) internal static string CreateInformationalMessage(Guid instanceId, string message) { var newMessage = new StringBuilder(instanceId.ToString()); - newMessage.Append(":"); + newMessage.Append(':'); newMessage.Append(message); return newMessage.ToString(); } diff --git a/src/System.Management.Automation/engine/remoting/common/remotesession.cs b/src/System.Management.Automation/engine/remoting/common/remotesession.cs index 662a7344068..f67b383c291 100644 --- a/src/System.Management.Automation/engine/remoting/common/remotesession.cs +++ b/src/System.Management.Automation/engine/remoting/common/remotesession.cs @@ -32,4 +32,3 @@ internal abstract class RemoteSession #endregion KeyExchange } } - diff --git a/src/System.Management.Automation/engine/remoting/common/throttlemanager.cs b/src/System.Management.Automation/engine/remoting/common/throttlemanager.cs index 9fa2233153f..afccc28362a 100644 --- a/src/System.Management.Automation/engine/remoting/common/throttlemanager.cs +++ b/src/System.Management.Automation/engine/remoting/common/throttlemanager.cs @@ -204,6 +204,11 @@ internal class ThrottleManager : IDisposable /// internal int ThrottleLimit { + get + { + return _throttleLimit; + } + set { if (value > 0 && value <= s_THROTTLE_LIMIT_MAX) @@ -211,11 +216,6 @@ internal int ThrottleLimit _throttleLimit = value; } } - - get - { - return _throttleLimit; - } } private int _throttleLimit = s_DEFAULT_THROTTLE_LIMIT; @@ -599,34 +599,34 @@ private void RaiseThrottleManagerEvents() /// Default throttle limit - the maximum number of operations /// to be processed at a time. /// - private static int s_DEFAULT_THROTTLE_LIMIT = 32; + private static readonly int s_DEFAULT_THROTTLE_LIMIT = 32; /// /// Maximum value that the throttle limit can be set to. /// - private static int s_THROTTLE_LIMIT_MAX = int.MaxValue; + private static readonly int s_THROTTLE_LIMIT_MAX = int.MaxValue; /// /// All pending operations. /// - private List _operationsQueue; + private readonly List _operationsQueue; /// /// List of items on which a StartOperation has /// been called. /// - private List _startOperationQueue; + private readonly List _startOperationQueue; /// /// List of items on which a StopOperation has /// been called. /// - private List _stopOperationQueue; + private readonly List _stopOperationQueue; /// /// Object used to synchronize access to the queues. /// - private object _syncObject; + private readonly object _syncObject; private bool _submitComplete = false; // to check if operations have been submitComplete private bool _stopping = false; // if stop is in process @@ -675,9 +675,9 @@ internal class Operation : IThrottleOperation private Thread workerThreadStart; private Thread workerThreadStop; - public bool Done { set; get; } + public bool Done { get; set; } - public int SleepTime { set; get; } = 100; + public int SleepTime { get; set; } = 100; private void WorkerThreadMethodStart() { diff --git a/src/System.Management.Automation/engine/remoting/fanin/BaseTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/BaseTransportManager.cs index 269b404a0ad..5d12914074c 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/BaseTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/BaseTransportManager.cs @@ -97,7 +97,7 @@ internal enum ConnectionStatus AutoDisconnectStarting = 4, AutoDisconnectSucceeded = 5, InternalErrorAbort = 6 - }; + } /// /// ConnectionStatusEventArgs. @@ -141,7 +141,7 @@ internal abstract class BaseTransportManager : IDisposable #region tracer [TraceSourceAttribute("Transport", "Traces BaseWSManTransportManager")] - private static PSTraceSource s_baseTracer = PSTraceSource.GetTracer("Transport", "Traces BaseWSManTransportManager"); + private static readonly PSTraceSource s_baseTracer = PSTraceSource.GetTracer("Transport", "Traces BaseWSManTransportManager"); #endregion @@ -178,7 +178,7 @@ internal abstract class BaseTransportManager : IDisposable #region Private Data // fragmentor used to fragment & defragment objects added to this collection. - private ReceiveDataCollection.OnDataAvailableCallback _onDataAvailableCallback; + private readonly ReceiveDataCollection.OnDataAvailableCallback _onDataAvailableCallback; // crypto helper used for encrypting/decrypting // secure string @@ -420,8 +420,8 @@ internal abstract class BaseClientTransportManager : BaseTransportManager, IDisp protected object syncObject = new object(); protected PrioritySendDataCollection dataToBeSent; // used to handle callbacks from the server..these are used to synchronize received callbacks - private Queue _callbackNotificationQueue; - private ReceiveDataCollection.OnDataAvailableCallback _onDataAvailableCallback; + private readonly Queue _callbackNotificationQueue; + private readonly ReceiveDataCollection.OnDataAvailableCallback _onDataAvailableCallback; private bool _isServicingCallbacks; private bool _suspendQueueServicing; private bool _isDebuggerSuspend; @@ -757,7 +757,7 @@ internal void EnqueueAndStartProcessingThread(RemoteDataObject remoteO /// /// Remote data object. /// True if remote data object requires a user response. - private bool CheckForInteractiveHostCall(RemoteDataObject remoteObject) + private static bool CheckForInteractiveHostCall(RemoteDataObject remoteObject) { bool interactiveHostCall = false; @@ -972,7 +972,7 @@ internal virtual void PrepareForConnect() #region Clean up /// - /// Finalizer. + /// Finalizes an instance of the class. /// ~BaseClientTransportManager() { @@ -983,10 +983,7 @@ internal virtual void PrepareForConnect() else { // wait for the close to be completed and then release the resources. - this.CloseCompleted += delegate (object source, EventArgs args) - { - Dispose(false); - }; + this.CloseCompleted += (object source, EventArgs args) => Dispose(false); try { @@ -1217,9 +1214,9 @@ internal abstract class AbstractServerTransportManager : BaseTransportManager { #region Private Data - private object _syncObject = new object(); + private readonly object _syncObject = new object(); // used to listen to data available events from serialized datastream. - private SerializedDataStream.OnDataAvailableCallback _onDataAvailable; + private readonly SerializedDataStream.OnDataAvailableCallback _onDataAvailable; // the following variable are used by onDataAvailableCallback. private bool _shouldFlushData; private bool _reportAsPending; @@ -1391,7 +1388,7 @@ internal void ReportError(int errorCode, string methodName) // Use thread-pool thread to raise the error handler..see explanation // in the method summary ThreadPool.QueueUserWorkItem(new WaitCallback( - delegate (object state) + (object state) => { TransportErrorOccuredEventArgs eventArgs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.Unknown); @@ -1527,7 +1524,7 @@ internal static byte[] ExtractEncodedXmlElement(string xmlBuffer, string xmlTag) XmlReader reader = XmlReader.Create(new StringReader(xmlBuffer), readerSettings); string additionalData; - if (XmlNodeType.Element == reader.MoveToContent()) + if (reader.MoveToContent() == XmlNodeType.Element) { additionalData = reader.ReadElementContentAsString(xmlTag, reader.NamespaceURI); } diff --git a/src/System.Management.Automation/engine/remoting/fanin/InitialSessionStateProvider.cs b/src/System.Management.Automation/engine/remoting/fanin/InitialSessionStateProvider.cs index 07597fd79ec..9e751dcdb7d 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/InitialSessionStateProvider.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/InitialSessionStateProvider.cs @@ -157,7 +157,7 @@ private void Update(string optionName, string optionValue) /// /// 1. "optionName" is already defined /// - private void AssertValueNotAssigned(string optionName, object originalValue) + private static void AssertValueNotAssigned(string optionName, object originalValue) { if (originalValue != null) { @@ -401,7 +401,7 @@ public virtual InitialSessionState GetInitialSessionState(PSSessionConfiguration /// /// User Identity for which this information is requested /// - /// Application private data or null + /// Application private data or public virtual PSPrimitiveDictionary GetApplicationPrivateData(PSSenderInfo senderInfo) { return null; @@ -785,10 +785,10 @@ private static string private const string configProviderApplicationBaseKeyName = "ApplicationBase"; private const string configProviderAssemblyNameKeyName = "AssemblyName"; - private static Dictionary s_ssnStateProviders = + private static readonly Dictionary s_ssnStateProviders = new Dictionary(StringComparer.OrdinalIgnoreCase); - private static object s_syncObject = new object(); + private static readonly object s_syncObject = new object(); #endregion } @@ -949,41 +949,41 @@ internal static class ConfigFileConstants internal static readonly string VisibleExternalCommands = "VisibleExternalCommands"; internal static readonly ConfigTypeEntry[] ConfigFileKeys = new ConfigTypeEntry[] { - new ConfigTypeEntry(AliasDefinitions, new ConfigTypeEntry.TypeValidationCallback(AliasDefinitionsTypeValidationCallback)), - new ConfigTypeEntry(AssembliesToLoad, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(Author, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(CompanyName, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(Copyright, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(Description, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(EnforceInputParameterValidation,new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), - new ConfigTypeEntry(EnvironmentVariables, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), - new ConfigTypeEntry(ExecutionPolicy, new ConfigTypeEntry.TypeValidationCallback(ExecutionPolicyValidationCallback)), - new ConfigTypeEntry(FormatsToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(FunctionDefinitions, new ConfigTypeEntry.TypeValidationCallback(FunctionDefinitionsTypeValidationCallback)), - new ConfigTypeEntry(GMSAAccount, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(Guid, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(LanguageMode, new ConfigTypeEntry.TypeValidationCallback(LanguageModeValidationCallback)), - new ConfigTypeEntry(ModulesToImport, new ConfigTypeEntry.TypeValidationCallback(StringOrHashtableArrayTypeValidationCallback)), - new ConfigTypeEntry(MountUserDrive, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), - new ConfigTypeEntry(PowerShellVersion, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(RequiredGroups, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), - new ConfigTypeEntry(RoleCapabilities, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(RoleCapabilityFiles, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(RoleDefinitions, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), - new ConfigTypeEntry(RunAsVirtualAccount, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), - new ConfigTypeEntry(RunAsVirtualAccountGroups, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(SchemaVersion, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(ScriptsToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(SessionType, new ConfigTypeEntry.TypeValidationCallback(ISSValidationCallback)), - new ConfigTypeEntry(TranscriptDirectory, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), - new ConfigTypeEntry(TypesToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(UserDriveMaxSize, new ConfigTypeEntry.TypeValidationCallback(IntegerTypeValidationCallback)), - new ConfigTypeEntry(VariableDefinitions, new ConfigTypeEntry.TypeValidationCallback(VariableDefinitionsTypeValidationCallback)), - new ConfigTypeEntry(VisibleAliases, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(VisibleCmdlets, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(VisibleFunctions, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(VisibleProviders, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), - new ConfigTypeEntry(VisibleExternalCommands, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(AliasDefinitions, new ConfigTypeEntry.TypeValidationCallback(AliasDefinitionsTypeValidationCallback)), + new ConfigTypeEntry(AssembliesToLoad, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(Author, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(CompanyName, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(Copyright, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(Description, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(EnforceInputParameterValidation, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), + new ConfigTypeEntry(EnvironmentVariables, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), + new ConfigTypeEntry(ExecutionPolicy, new ConfigTypeEntry.TypeValidationCallback(ExecutionPolicyValidationCallback)), + new ConfigTypeEntry(FormatsToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(FunctionDefinitions, new ConfigTypeEntry.TypeValidationCallback(FunctionDefinitionsTypeValidationCallback)), + new ConfigTypeEntry(GMSAAccount, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(Guid, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(LanguageMode, new ConfigTypeEntry.TypeValidationCallback(LanguageModeValidationCallback)), + new ConfigTypeEntry(ModulesToImport, new ConfigTypeEntry.TypeValidationCallback(StringOrHashtableArrayTypeValidationCallback)), + new ConfigTypeEntry(MountUserDrive, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), + new ConfigTypeEntry(PowerShellVersion, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(RequiredGroups, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), + new ConfigTypeEntry(RoleCapabilities, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(RoleCapabilityFiles, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(RoleDefinitions, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)), + new ConfigTypeEntry(RunAsVirtualAccount, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)), + new ConfigTypeEntry(RunAsVirtualAccountGroups, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(SchemaVersion, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(ScriptsToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(SessionType, new ConfigTypeEntry.TypeValidationCallback(ISSValidationCallback)), + new ConfigTypeEntry(TranscriptDirectory, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)), + new ConfigTypeEntry(TypesToProcess, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(UserDriveMaxSize, new ConfigTypeEntry.TypeValidationCallback(IntegerTypeValidationCallback)), + new ConfigTypeEntry(VariableDefinitions, new ConfigTypeEntry.TypeValidationCallback(VariableDefinitionsTypeValidationCallback)), + new ConfigTypeEntry(VisibleAliases, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(VisibleCmdlets, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(VisibleFunctions, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(VisibleProviders, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), + new ConfigTypeEntry(VisibleExternalCommands, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)), }; /// @@ -1326,7 +1326,7 @@ private static bool BooleanTypeValidationCallback(string key, object obj, PSCmdl private static bool IntegerTypeValidationCallback(string key, object obj, PSCmdlet cmdlet, string path) { - if (!(obj is int) && !(obj is long)) + if (obj is not int && obj is not long) { cmdlet.WriteVerbose(StringUtil.Format(RemotingErrorIdStrings.DISCTypeMustBeInteger, key, path)); return false; @@ -1686,8 +1686,8 @@ internal static void ValidateRoleDefinitions(IDictionary roleDefinitions) /// internal sealed class DISCPowerShellConfiguration : PSSessionConfiguration { - private string _configFile; - private Hashtable _configHash; + private readonly string _configFile; + private readonly Hashtable _configHash; /// /// Gets the configuration hashtable that results from parsing the specified configuration file. @@ -1711,7 +1711,7 @@ internal DISCPowerShellConfiguration(string configFile, Func roleV _configFile = configFile; if (roleVerifier == null) { - roleVerifier = (role) => false; + roleVerifier = static (role) => false; } Runspace backupRunspace = Runspace.DefaultRunspace; @@ -1896,7 +1896,7 @@ private void MergeConfigHashIntoConfigHash(IDictionary childConfigHash) } } - private string GetRoleCapabilityPath(string roleCapability) + private static string GetRoleCapabilityPath(string roleCapability) { string moduleName = "*"; if (roleCapability.Contains('\\')) @@ -2395,7 +2395,7 @@ public override InitialSessionState GetInitialSessionState(PSSenderInfo senderIn if (Convert.ToBoolean(_configHash[ConfigFileConstants.MountUserDrive], CultureInfo.InvariantCulture)) { iss.UserDriveEnabled = true; - iss.UserDriveUserName = (senderInfo != null) ? senderInfo.UserInfo.Identity.Name : null; + iss.UserDriveUserName = senderInfo?.UserInfo.Identity.Name; // Set user drive max drive if provided. if (_configHash.ContainsKey(ConfigFileConstants.UserDriveMaxSize)) @@ -2620,7 +2620,7 @@ private static void ProcessVisibleCommand(InitialSessionState iss, string comman /// /// Creates an alias entry. /// - private SessionStateAliasEntry CreateSessionStateAliasEntry(Hashtable alias, bool isAliasVisibilityDefined) + private static SessionStateAliasEntry CreateSessionStateAliasEntry(Hashtable alias, bool isAliasVisibilityDefined) { string name = TryGetValue(alias, ConfigFileConstants.AliasNameToken); @@ -2660,7 +2660,7 @@ private SessionStateAliasEntry CreateSessionStateAliasEntry(Hashtable alias, boo /// Creates a function entry. /// /// - private SessionStateFunctionEntry CreateSessionStateFunctionEntry(Hashtable function, bool isFunctionVisibilityDefined) + private static SessionStateFunctionEntry CreateSessionStateFunctionEntry(Hashtable function, bool isFunctionVisibilityDefined) { string name = TryGetValue(function, ConfigFileConstants.FunctionNameToken); @@ -2700,7 +2700,7 @@ private SessionStateFunctionEntry CreateSessionStateFunctionEntry(Hashtable func /// /// Creates a variable entry. /// - private SessionStateVariableEntry CreateSessionStateVariableEntry(Hashtable variable, PSLanguageMode languageMode) + private static SessionStateVariableEntry CreateSessionStateVariableEntry(Hashtable variable, PSLanguageMode languageMode) { string name = TryGetValue(variable, ConfigFileConstants.VariableNameToken); @@ -2804,9 +2804,7 @@ internal static Hashtable[] TryGetHashtableArray(object hashObj) for (int i = 0; i < hashArray.Length; i++) { - Hashtable hash = objArray[i] as Hashtable; - - if (hash == null) + if (!(objArray[i] is Hashtable hash)) { return null; } diff --git a/src/System.Management.Automation/engine/remoting/fanin/OutOfProcTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/OutOfProcTransportManager.cs index bc39b8f6937..75f70941856 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/OutOfProcTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/OutOfProcTransportManager.cs @@ -144,12 +144,19 @@ private static string CreatePSGuidPacket(string element, Guid psGuid) #region Packet Processing Helper Methods / Delegates internal delegate void DataPacketReceived(byte[] rawData, string stream, Guid psGuid); + internal delegate void DataAckPacketReceived(Guid psGuid); + internal delegate void CommandCreationPacketReceived(Guid psGuid); + internal delegate void CommandCreationAckReceived(Guid psGuid); + internal delegate void ClosePacketReceived(Guid psGuid); + internal delegate void CloseAckPacketReceived(Guid psGuid); + internal delegate void SignalPacketReceived(Guid psGuid); + internal delegate void SignalAckPacketReceived(Guid psGuid); internal struct DataProcessingDelegates @@ -402,9 +409,9 @@ internal class OutOfProcessTextWriter { #region Private Data - private TextWriter _writer; + private readonly TextWriter _writer; private bool _isStopped; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); #endregion @@ -466,10 +473,10 @@ internal abstract class OutOfProcessClientSessionTransportManagerBase : BaseClie private readonly BlockingCollection _sessionMessageQueue; private readonly BlockingCollection _commandMessageQueue; - private PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; + private readonly PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; private OutOfProcessUtils.DataProcessingDelegates _dataProcessingCallbacks; - private Dictionary _cmdTransportManagers; - private Timer _closeTimeOutTimer; + private readonly Dictionary _cmdTransportManagers; + private readonly Timer _closeTimeOutTimer; protected OutOfProcessTextWriter stdInWriter; protected PowerShellTraceSource _tracer; @@ -584,7 +591,7 @@ internal override void CloseAsync() // start the timer..so client can fail deterministically _closeTimeOutTimer.Change(60 * 1000, Timeout.Infinite); } - catch (IOException) + catch (Exception ex) when (ex is IOException || ex is ObjectDisposedException) { // Cannot communicate with server. Allow client to complete close operation. shouldRaiseCloseCompleted = true; @@ -628,30 +635,7 @@ internal override void Dispose(bool isDisposing) { _cmdTransportManagers.Clear(); _closeTimeOutTimer.Dispose(); - - // Stop session processing thread. - try - { - _sessionMessageQueue.CompleteAdding(); - } - catch (ObjectDisposedException) - { - // Object already disposed. - } - - _sessionMessageQueue.Dispose(); - - // Stop command processing thread. - try - { - _commandMessageQueue.CompleteAdding(); - } - catch (ObjectDisposedException) - { - // Object already disposed. - } - - _commandMessageQueue.Dispose(); + DisposeMessageQueue(); } } @@ -1048,6 +1032,37 @@ internal void OnCloseTimeOutTimerElapsed(object source) } #endregion + + #region Protected Methods + + protected void DisposeMessageQueue() + { + // Stop session processing thread. + try + { + _sessionMessageQueue.CompleteAdding(); + } + catch (ObjectDisposedException) + { + // Object already disposed. + } + + _sessionMessageQueue.Dispose(); + + // Stop command processing thread. + try + { + _commandMessageQueue.CompleteAdding(); + } + catch (ObjectDisposedException) + { + // Object already disposed. + } + + _commandMessageQueue.Dispose(); + } + + #endregion } internal class OutOfProcessClientSessionTransportManager : OutOfProcessClientSessionTransportManagerBase @@ -1055,7 +1070,7 @@ internal class OutOfProcessClientSessionTransportManager : OutOfProcessClientSes #region Private Data private Process _serverProcess; - private NewProcessConnectionInfo _connectionInfo; + private readonly NewProcessConnectionInfo _connectionInfo; private bool _processCreated = true; private PowerShellProcessInstance _processInstance; @@ -1407,7 +1422,7 @@ protected void ProcessReaderThread(object state) Dbg.Assert(false, "Need to adjust transport fragmentor to accomodate read buffer size."); } - string errorMsg = (e.Message != null) ? e.Message : string.Empty; + string errorMsg = e.Message ?? string.Empty; _tracer.WriteMessage("HyperVSocketClientSessionTransportManager", "StartReaderThread", Guid.Empty, "Transport manager reader thread ended with error: {0}", errorMsg); @@ -1426,10 +1441,10 @@ internal sealed class VMHyperVSocketClientSessionTransportManager : HyperVSocket { #region Private Data - private Guid _vmGuid; - private string _configurationName; - private VMConnectionInfo _connectionInfo; - private NetworkCredential _networkCredential; + private readonly Guid _vmGuid; + private readonly string _configurationName; + private readonly VMConnectionInfo _connectionInfo; + private readonly NetworkCredential _networkCredential; #endregion @@ -1512,8 +1527,8 @@ internal sealed class ContainerHyperVSocketClientSessionTransportManager : Hyper { #region Private Data - private Guid _targetGuid; // currently this is the utility vm guid in HyperV container scenario - private ContainerConnectionInfo _connectionInfo; + private readonly Guid _targetGuid; // currently this is the utility vm guid in HyperV container scenario + private readonly ContainerConnectionInfo _connectionInfo; #endregion @@ -1571,12 +1586,13 @@ internal sealed class SSHClientSessionTransportManager : OutOfProcessClientSessi { #region Data - private SSHConnectionInfo _connectionInfo; + private readonly SSHConnectionInfo _connectionInfo; private int _sshProcessId; private StreamWriter _stdInWriter; private StreamReader _stdOutReader; private StreamReader _stdErrReader; private bool _connectionEstablished; + private Timer _connectionTimer; private const string _threadName = "SSHTransport Reader Thread"; @@ -1634,6 +1650,49 @@ internal override void CreateAsync() // Create reader thread and send first PSRP message. StartReaderThread(_stdOutReader); + + if (_connectionInfo.ConnectingTimeout < 0) + { + return; + } + + // Start connection timeout timer if requested. + // Timer callback occurs only once after timeout time. + _connectionTimer = new Timer( + callback: (_) => + { + if (_connectionEstablished) + { + return; + } + + // Detect if SSH client process terminates prematurely. + bool sshTerminated = false; + try + { + using (var sshProcess = System.Diagnostics.Process.GetProcessById(_sshProcessId)) + { + sshTerminated = sshProcess == null || sshProcess.Handle == IntPtr.Zero || sshProcess.HasExited; + } + } + catch + { + sshTerminated = true; + } + + var errorMessage = StringUtil.Format(RemotingErrorIdStrings.SSHClientConnectTimeout, _connectionInfo.ConnectingTimeout / 1000); + if (sshTerminated) + { + errorMessage += RemotingErrorIdStrings.SSHClientConnectProcessTerminated; + } + + // Report error and terminate connection attempt. + HandleSSHError( + new PSRemotingTransportException(errorMessage)); + }, + state: null, + dueTime: _connectionInfo.ConnectingTimeout, + period: Timeout.Infinite); } internal override void CloseAsync() @@ -1653,14 +1712,20 @@ internal override void CloseAsync() private void CloseConnection() { + // Ensure message queue is disposed. + DisposeMessageQueue(); + + var connectionTimer = Interlocked.Exchange(ref _connectionTimer, null); + connectionTimer?.Dispose(); + var stdInWriter = Interlocked.Exchange(ref _stdInWriter, null); - if (stdInWriter != null) { stdInWriter.Dispose(); } + stdInWriter?.Dispose(); var stdOutReader = Interlocked.Exchange(ref _stdOutReader, null); - if (stdOutReader != null) { stdOutReader.Dispose(); } + stdOutReader?.Dispose(); var stdErrReader = Interlocked.Exchange(ref _stdErrReader, null); - if (stdErrReader != null) { stdErrReader.Dispose(); } + stdErrReader?.Dispose(); // The CloseConnection() method can be called multiple times from multiple places. // Set the _sshProcessId to zero here so that we go through the work of finding @@ -1670,11 +1735,7 @@ private void CloseConnection() { try { - var sshProcess = System.Diagnostics.Process.GetProcessById(sshProcessId); - if ((sshProcess != null) && (sshProcess.Handle != IntPtr.Zero) && !sshProcess.HasExited) - { - sshProcess.Kill(); - } + _connectionInfo.KillSSHProcess(sshProcessId); } catch (ArgumentException) { } catch (InvalidOperationException) { } @@ -1723,7 +1784,7 @@ private void ProcessErrorThread(object state) } catch (Exception e) { - string errorMsg = (e.Message != null) ? e.Message : string.Empty; + string errorMsg = e.Message ?? string.Empty; _tracer.WriteMessage("SSHClientSessionTransportManager", "ProcessErrorThread", Guid.Empty, "Transport manager error thread ended with error: {0}", errorMsg); @@ -1847,7 +1908,7 @@ private void ProcessReaderThread(object state) Dbg.Assert(false, "Need to adjust transport fragmentor to accomodate read buffer size."); } - string errorMsg = (e.Message != null) ? e.Message : string.Empty; + string errorMsg = e.Message ?? string.Empty; _tracer.WriteMessage("SSHClientSessionTransportManager", "ProcessReaderThread", Guid.Empty, "Transport manager reader thread ended with error: {0}", errorMsg); } @@ -1860,9 +1921,9 @@ internal abstract class NamedPipeClientSessionTransportManagerBase : OutOfProces { #region Data - private RunspaceConnectionInfo _connectionInfo; + private readonly RunspaceConnectionInfo _connectionInfo; protected NamedPipeClientBase _clientPipe = new NamedPipeClientBase(); - private string _threadName; + private readonly string _threadName; #endregion @@ -1974,7 +2035,7 @@ private void ProcessReaderThread(object state) Dbg.Assert(false, "Need to adjust transport fragmentor to accommodate read buffer size."); } - string errorMsg = (e.Message != null) ? e.Message : string.Empty; + string errorMsg = e.Message ?? string.Empty; _tracer.WriteMessage("NamedPipeClientSessionTransportManager", "StartReaderThread", Guid.Empty, "Transport manager reader thread ended with error: {0}", errorMsg); } @@ -1987,7 +2048,7 @@ internal sealed class NamedPipeClientSessionTransportManager : NamedPipeClientSe { #region Private Data - private NamedPipeConnectionInfo _connectionInfo; + private readonly NamedPipeConnectionInfo _connectionInfo; private const string _threadName = "NamedPipeTransport Reader Thread"; @@ -2055,7 +2116,7 @@ internal sealed class ContainerNamedPipeClientSessionTransportManager : NamedPip { #region Private Data - private ContainerConnectionInfo _connectionInfo; + private readonly ContainerConnectionInfo _connectionInfo; private const string _threadName = "ContainerNamedPipeTransport Reader Thread"; @@ -2124,9 +2185,9 @@ internal class OutOfProcessClientCommandTransportManager : BaseClientCommandTran { #region Private Data - private OutOfProcessTextWriter _stdInWriter; - private PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; - private Timer _signalTimeOutTimer; + private readonly OutOfProcessTextWriter _stdInWriter; + private readonly PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; + private readonly Timer _signalTimeOutTimer; #endregion @@ -2425,10 +2486,10 @@ internal class OutOfProcessServerSessionTransportManager : AbstractServerSession { #region Private Data - private OutOfProcessTextWriter _stdOutWriter; - private OutOfProcessTextWriter _stdErrWriter; - private Dictionary _cmdTransportManagers; - private object _syncObject = new object(); + private readonly OutOfProcessTextWriter _stdOutWriter; + private readonly OutOfProcessTextWriter _stdErrWriter; + private readonly Dictionary _cmdTransportManagers; + private readonly object _syncObject = new object(); #endregion @@ -2523,9 +2584,9 @@ internal class OutOfProcessServerTransportManager : AbstractServerTransportManag { #region Private Data - private OutOfProcessTextWriter _stdOutWriter; - private OutOfProcessTextWriter _stdErrWriter; - private Guid _powershellInstanceId; + private readonly OutOfProcessTextWriter _stdOutWriter; + private readonly OutOfProcessTextWriter _stdErrWriter; + private readonly Guid _powershellInstanceId; private bool _isDataAckSendPending; #endregion @@ -2604,4 +2665,3 @@ internal override void Close(Exception reasonForClose) #endregion } } - diff --git a/src/System.Management.Automation/engine/remoting/fanin/PSSessionConfigurationData.cs b/src/System.Management.Automation/engine/remoting/fanin/PSSessionConfigurationData.cs index 17aac7adfdf..6da557cca40 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PSSessionConfigurationData.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PSSessionConfigurationData.cs @@ -18,7 +18,9 @@ public sealed class PSSessionConfigurationData { /// /// +#pragma warning disable CA2211 // Non-constant fields should not be visible public static bool IsServerManager; +#pragma warning restore CA2211 // Non-constant fields should not be visible #region Public Properties diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 8ddd0eb8cb1..7baebdc98ae 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -55,9 +55,9 @@ internal class PrioritySendDataCollection // these callbacks are used to notify when data becomes available under // suc circumstances. private OnDataAvailableCallback _onDataAvailableCallback; - private SerializedDataStream.OnDataAvailableCallback _onSendCollectionDataAvailable; + private readonly SerializedDataStream.OnDataAvailableCallback _onSendCollectionDataAvailable; private bool _isHandlingCallback; - private object _readSyncObject = new object(); + private readonly object _readSyncObject = new object(); /// /// Callback that is called once a fragmented data is available to send. @@ -88,7 +88,10 @@ internal PrioritySendDataCollection() internal Fragmentor Fragmentor { - get { return _fragmentor; } + get + { + return _fragmentor; + } set { @@ -163,8 +166,8 @@ Verify arrays and dataToBeSent objects before referencing. */ if (_dataSyncObjects != null && _dataToBeSent != null) { - int promptResponseIndex = (int)DataPriorityType.PromptResponse; - int defaultIndex = (int)DataPriorityType.Default; + const int promptResponseIndex = (int)DataPriorityType.PromptResponse; + const int defaultIndex = (int)DataPriorityType.Default; lock (_dataSyncObjects[promptResponseIndex]) { @@ -291,13 +294,13 @@ internal class ReceiveDataCollection : IDisposable #region tracer [TraceSourceAttribute("Transport", "Traces BaseWSManTransportManager")] - private static PSTraceSource s_baseTracer = PSTraceSource.GetTracer("Transport", "Traces BaseWSManTransportManager"); + private static readonly PSTraceSource s_baseTracer = PSTraceSource.GetTracer("Transport", "Traces BaseWSManTransportManager"); #endregion #region Private Data // fragmentor used to defragment objects added to this collection. - private Fragmentor _defragmentor; + private readonly Fragmentor _defragmentor; // this stream holds incoming data..this stream doesn't know anything // about fragment boundaries. @@ -311,7 +314,7 @@ internal class ReceiveDataCollection : IDisposable // max deserialized object size in bytes private int? _maxReceivedObjectSize; private int _totalReceivedObjectSizeSoFar; - private bool _isCreateByClientTM; + private readonly bool _isCreateByClientTM; // this indicates if any off sync fragments can be ignored // this gets reset (to false) upon receiving the next "start" fragment along the stream @@ -319,7 +322,7 @@ internal class ReceiveDataCollection : IDisposable // objects need to cleanly release resources without // locking entire processing logic. - private object _syncObject; + private readonly object _syncObject; private bool _isDisposed; // holds the number of threads that are currently in // ProcessRawData method. This might happen only for @@ -738,9 +741,9 @@ internal class PriorityReceiveDataCollection : IDisposable { #region Private Data - private Fragmentor _defragmentor; - private ReceiveDataCollection[] _recvdData; - private bool _isCreateByClientTM; + private readonly Fragmentor _defragmentor; + private readonly ReceiveDataCollection[] _recvdData; + private readonly bool _isCreateByClientTM; #endregion diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs index 1b1fe2b2163..6dd3614a62f 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs @@ -192,7 +192,7 @@ internal static MarshalledObject Create(T obj) /// public void Dispose() { - if (IntPtr.Zero != _dataPtr) + if (_dataPtr != IntPtr.Zero) { Marshal.FreeHGlobal(_dataPtr); _dataPtr = IntPtr.Zero; @@ -612,7 +612,7 @@ internal enum WSManDataType : uint WSMAN_DATA_TYPE_BINARY = 2, WSMAN_DATA_TYPE_WS_XML_READER = 3, WSMAN_DATA_TYPE_DWORD = 4 - }; + } [StructLayout(LayoutKind.Sequential)] internal class WSManDataStruct @@ -635,7 +635,7 @@ internal class WSManBinaryOrTextDataStruct /// internal class WSManData_ManToUn : IDisposable { - private WSManDataStruct _internalData; + private readonly WSManDataStruct _internalData; [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] private IntPtr _marshalledObject = IntPtr.Zero; @@ -687,18 +687,6 @@ internal WSManData_ManToUn(string data) Marshal.StructureToPtr(_internalData, _marshalledObject, false); } - /// - /// Finalizer - /// - /// Note: Do not depend on the finalizer! This object should be - /// properly disposed of when no longer needed via a direct call - /// to Dispose(). - /// - ~WSManData_ManToUn() - { - Dispose(false); - } - /// /// Gets the type of data. /// @@ -747,6 +735,14 @@ private void Dispose(bool isDisposing) } } + /// + /// Finalizes an instance of the class. + /// + ~WSManData_ManToUn() + { + Dispose(false); + } + /// /// Implicit IntPtr conversion. /// @@ -869,7 +865,7 @@ internal static WSManData_UnToMan UnMarshal(IntPtr unmanagedData) { WSManData_UnToMan result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManDataStruct resultInternal = Marshal.PtrToStructure(unmanagedData); result = WSManData_UnToMan.UnMarshal(resultInternal); @@ -885,7 +881,7 @@ internal static WSManData_UnToMan UnMarshal(IntPtr unmanagedData) [StructLayout(LayoutKind.Sequential)] internal struct WSManDataDWord { - private WSManDataType _type; + private readonly WSManDataType _type; private WSManDWordDataInternal _dwordData; /// @@ -972,7 +968,7 @@ internal WSManStreamIDSet_ManToUn(string[] streamIds) /// internal void Dispose() { - if (IntPtr.Zero != _streamSetInfo.streamIDs) + if (_streamSetInfo.streamIDs != IntPtr.Zero) { int sizeOfIntPtr = Marshal.SizeOf(); for (int index = 0; index < _streamSetInfo.streamIDsCount; index++) @@ -980,7 +976,7 @@ internal void Dispose() IntPtr streamAddress = IntPtr.Zero; streamAddress = Marshal.ReadIntPtr(_streamSetInfo.streamIDs, index * sizeOfIntPtr); - if (IntPtr.Zero != streamAddress) + if (streamAddress != IntPtr.Zero) { Marshal.FreeHGlobal(streamAddress); streamAddress = IntPtr.Zero; @@ -1019,7 +1015,7 @@ internal static WSManStreamIDSet_UnToMan UnMarshal(IntPtr unmanagedData) { WSManStreamIDSet_UnToMan result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManStreamIDSetStruct resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -1140,7 +1136,7 @@ internal WSManOptionSet(WSManOption[] options) /// public void Dispose() { - if (IntPtr.Zero != _optionSet.options) + if (_optionSet.options != IntPtr.Zero) { Marshal.FreeHGlobal(_optionSet.options); _optionSet.options = IntPtr.Zero; @@ -1174,7 +1170,7 @@ public static implicit operator IntPtr(WSManOptionSet optionSet) /// internal static WSManOptionSet UnMarshal(IntPtr unmanagedData) { - if (IntPtr.Zero == unmanagedData) + if (unmanagedData == IntPtr.Zero) { return new WSManOptionSet(); } @@ -1264,7 +1260,7 @@ internal WSManCommandArgSet(byte[] firstArgument) public void Dispose() { IntPtr firstArgAddress = Marshal.ReadIntPtr(_internalData.args); - if (IntPtr.Zero != firstArgAddress) + if (firstArgAddress != IntPtr.Zero) { Marshal.FreeHGlobal(firstArgAddress); } @@ -1302,7 +1298,7 @@ internal static WSManCommandArgSet UnMarshal(IntPtr unmanagedData) { WSManCommandArgSet result = new WSManCommandArgSet(); - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManCommandArgSetInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -1486,7 +1482,7 @@ internal static WSManShellStartupInfo_UnToMan UnMarshal(IntPtr unmanagedData) { WSManShellStartupInfo_UnToMan result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManShellStartupInfoStruct resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -1522,7 +1518,7 @@ internal static WSManEnvironmentVariableSet UnMarshal(IntPtr unmanagedData) { WSManEnvironmentVariableSet result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManEnvironmentVariableSetInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -1738,7 +1734,7 @@ internal struct WSManShellAsyncCallback private GCHandle _gcHandle; [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - private IntPtr _asyncCallback; + private readonly IntPtr _asyncCallback; internal WSManShellAsyncCallback(WSManShellCompletionFunction callback) { @@ -1841,7 +1837,7 @@ internal static WSManCreateShellDataResult UnMarshal(IntPtr unmanagedData) { WSManCreateShellDataResult result = new WSManCreateShellDataResult(); - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManCreateShellDataResultInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -2058,7 +2054,7 @@ internal static WSManPluginRequest UnMarshal(IntPtr unmanagedData) // Dbg.Assert(IntPtr.Zero != unmanagedData, "unmanagedData must be non-null. This means WinRM sent a bad pointer."); WSManPluginRequest result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManPluginRequestInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -2116,7 +2112,7 @@ internal static WSManSenderDetails UnMarshal(IntPtr unmanagedData) { WSManSenderDetails result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManSenderDetailsInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -2169,7 +2165,7 @@ internal static WSManCertificateDetails UnMarshal(IntPtr unmanagedData) { WSManCertificateDetails result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManCertificateDetailsInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -2218,7 +2214,7 @@ internal static WSManOperationInfo UnMarshal(IntPtr unmanagedData) { WSManOperationInfo result = null; - if (IntPtr.Zero != unmanagedData) + if (unmanagedData != IntPtr.Zero) { WSManOperationInfoInternal resultInternal = Marshal.PtrToStructure(unmanagedData); @@ -2357,7 +2353,7 @@ internal struct WSManKeyStruct /// [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManInitialize(int flags, - [In, Out] ref IntPtr wsManAPIHandle); + [In, Out] ref IntPtr wsManAPIHandle); /// /// This API deinitializes the Winrm client stack; all operations will @@ -2390,11 +2386,11 @@ internal static extern int WSManInitialize(int flags, /// [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManCreateSession(IntPtr wsManAPIHandle, - [MarshalAs(UnmanagedType.LPWStr)]string connection, + [MarshalAs(UnmanagedType.LPWStr)] string connection, int flags, IntPtr authenticationCredentials, IntPtr proxyInfo, - [In, Out] ref IntPtr wsManSessionHandle); + [In, Out] ref IntPtr wsManSessionHandle); /// /// Frees memory of session and closes all related operations before returning; @@ -2443,9 +2439,9 @@ internal static extern int WSManSetSessionOption(IntPtr wsManSessionHandle, /// /// An int (DWORD) data. /// - /// + /// Zero on success, otherwise the error code. [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] - internal static extern void WSManGetSessionOptionAsDword(IntPtr wsManSessionHandle, + internal static extern int WSManGetSessionOptionAsDword(IntPtr wsManSessionHandle, WSManSessionOption option, out int value); @@ -2459,15 +2455,15 @@ internal static extern void WSManGetSessionOptionAsDword(IntPtr wsManSessionHand internal static string WSManGetSessionOptionAsString(IntPtr wsManAPIHandle, WSManSessionOption option) { - Dbg.Assert(IntPtr.Zero != wsManAPIHandle, "wsManAPIHandle cannot be null."); + Dbg.Assert(wsManAPIHandle != IntPtr.Zero, "wsManAPIHandle cannot be null."); // The error code taken from winerror.h used for getting buffer length. const int ERROR_INSUFFICIENT_BUFFER = 122; string returnval = string.Empty; int bufferSize = 0; // calculate buffer size required - if (ERROR_INSUFFICIENT_BUFFER != WSManGetSessionOptionAsString(wsManAPIHandle, - option, 0, null, out bufferSize)) + if (WSManGetSessionOptionAsString(wsManAPIHandle, + option, 0, null, out bufferSize) != ERROR_INSUFFICIENT_BUFFER) { return returnval; } @@ -2480,8 +2476,8 @@ internal static string WSManGetSessionOptionAsString(IntPtr wsManAPIHandle, // Now get the actual value int messageLength; - if (0 != WSManGetSessionOptionAsString(wsManAPIHandle, - option, bufferSizeInBytes, msgBufferPtr, out messageLength)) + if (WSManGetSessionOptionAsString(wsManAPIHandle, + option, bufferSizeInBytes, msgBufferPtr, out messageLength) != 0) { return returnval; } @@ -2553,13 +2549,13 @@ internal static void WSManCreateShellEx(IntPtr wsManSessionHandle, [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManCreateShellEx", SetLastError = false, CharSet = CharSet.Unicode)] private static extern void WSManCreateShellExInternal(IntPtr wsManSessionHandle, int flags, - [MarshalAs(UnmanagedType.LPWStr)]string resourceUri, - [MarshalAs(UnmanagedType.LPWStr)]string shellId, + [MarshalAs(UnmanagedType.LPWStr)] string resourceUri, + [MarshalAs(UnmanagedType.LPWStr)] string shellId, IntPtr startupInfo, IntPtr optionSet, IntPtr openContent, IntPtr asyncCallback, - [In, Out] ref IntPtr shellOperationHandle); + [In, Out] ref IntPtr shellOperationHandle); /// /// @@ -2574,12 +2570,12 @@ private static extern void WSManCreateShellExInternal(IntPtr wsManSessionHandle, [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManConnectShell", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManConnectShellEx(IntPtr wsManSessionHandle, int flags, - [MarshalAs(UnmanagedType.LPWStr)]string resourceUri, - [MarshalAs(UnmanagedType.LPWStr)]string shellId, + [MarshalAs(UnmanagedType.LPWStr)] string resourceUri, + [MarshalAs(UnmanagedType.LPWStr)] string shellId, IntPtr optionSet, IntPtr connectXml, IntPtr asyncCallback, - [In, Out] ref IntPtr shellOperationHandle); + [In, Out] ref IntPtr shellOperationHandle); /// /// @@ -2685,7 +2681,7 @@ internal static extern void WSManReceiveShellOutputEx(IntPtr shellOperationHandl int flags, IntPtr desiredStreamSet, IntPtr asyncCallback, - [In, Out] ref IntPtr receiveOperationHandle); + [In, Out] ref IntPtr receiveOperationHandle); /// /// Send data to the remote end. @@ -2726,7 +2722,7 @@ private static extern void WSManSendShellInputExInternal(IntPtr shellOperationHa IntPtr streamData, bool endOfStream, IntPtr asyncCallback, - [In, Out] ref IntPtr sendOperationHandle); + [In, Out] ref IntPtr sendOperationHandle); /// /// Closes a shell or a command; if the callback associated with the operation @@ -2805,7 +2801,7 @@ internal static extern void WSManSignalShellEx(IntPtr shellOperationHandle, /// internal static string WSManGetErrorMessage(IntPtr wsManAPIHandle, int errorCode) { - Dbg.Assert(IntPtr.Zero != wsManAPIHandle, "wsManAPIHandle cannot be null."); + Dbg.Assert(wsManAPIHandle != IntPtr.Zero, "wsManAPIHandle cannot be null."); // The error code taken from winerror.h used for getting buffer length. const int ERROR_INSUFFICIENT_BUFFER = 122; @@ -2816,8 +2812,8 @@ internal static string WSManGetErrorMessage(IntPtr wsManAPIHandle, int errorCode string returnval = string.Empty; int bufferSize = 0; // calculate buffer size required - if (ERROR_INSUFFICIENT_BUFFER != WSManGetErrorMessage(wsManAPIHandle, - 0, langCode, errorCode, 0, null, out bufferSize)) + if (WSManGetErrorMessage(wsManAPIHandle, + 0, langCode, errorCode, 0, null, out bufferSize) != ERROR_INSUFFICIENT_BUFFER) { return returnval; } @@ -2830,8 +2826,8 @@ internal static string WSManGetErrorMessage(IntPtr wsManAPIHandle, int errorCode // Now get the actual value int messageLength; - if (0 != WSManGetErrorMessage(wsManAPIHandle, - 0, langCode, errorCode, bufferSizeInBytes, msgBufferPtr, out messageLength)) + if (WSManGetErrorMessage(wsManAPIHandle, + 0, langCode, errorCode, bufferSizeInBytes, msgBufferPtr, out messageLength) != 0) { return returnval; } @@ -3019,6 +3015,7 @@ internal static extern void WSManPluginRegisterShutdownCallback( /// unit testing. /// Note: It is implemented as a class to avoid exposing it outside the module. /// +#nullable enable internal interface IWSManNativeApiFacade { // TODO: Expand this to cover the rest of the API once I prove that it works! @@ -3037,7 +3034,7 @@ int WSManPluginOperationComplete( int WSManPluginReceiveResult( IntPtr requestDetails, int flags, - string stream, + string? stream, IntPtr streamResult, string commandState, int exitCode); @@ -3052,6 +3049,7 @@ void WSManPluginRegisterShutdownCallback( IntPtr shutdownCallback, IntPtr shutdownContext); } +#nullable restore /// /// Concrete implementation of the PInvoke facade for use in the production code. diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManPlugin.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManPlugin.cs index f408b45d637..9382beb9b31 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManPlugin.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManPlugin.cs @@ -128,9 +128,9 @@ internal class WSManPluginInstance { #region Private Members - private Dictionary _activeShellSessions; - private object _syncObject; - private static Dictionary s_activePlugins = new Dictionary(); + private readonly Dictionary _activeShellSessions; + private readonly object _syncObject; + private static readonly Dictionary s_activePlugins = new Dictionary(); /// /// Enables dependency injection after the static constructor is called. @@ -247,7 +247,7 @@ internal void CreateShell( "CreateShell: NULL checks being performed", string.Empty); - if ((0 == startupInfo.inputStreamSet.streamIDsCount) || (0 == startupInfo.outputStreamSet.streamIDsCount)) + if ((startupInfo.inputStreamSet.streamIDsCount == 0) || (startupInfo.outputStreamSet.streamIDsCount == 0)) { ReportOperationComplete( requestDetails, @@ -306,10 +306,10 @@ internal void CreateShell( PSOpcode.Connect, PSTask.None, PSKeyword.ManagedPlugin | PSKeyword.UseAlwaysAnalytic, requestDetails.ToString(), senderInfo.UserInfo.Identity.Name, requestDetails.resourceUri); - ServerRemoteSession remoteShellSession = ServerRemoteSession.CreateServerRemoteSession(senderInfo, - requestDetails.resourceUri, - extraInfo, - serverTransportMgr); + ServerRemoteSession remoteShellSession = ServerRemoteSession.CreateServerRemoteSession(senderInfo, + requestDetails.resourceUri, + extraInfo, + serverTransportMgr); if (remoteShellSession == null) { @@ -333,7 +333,7 @@ internal void CreateShell( if (inboundShellInformation != null) { - if ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT != inboundShellInformation.Type) + if (inboundShellInformation.Type != (uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT) { // only text data is supported ReportOperationComplete( @@ -361,7 +361,7 @@ internal void CreateShell( requestDetails.ToString(), requestDetails.ToString()); result = wsmanPinvokeStatic.WSManPluginReportContext(requestDetails.unmanagedHandle, 0, requestDetails.unmanagedHandle); - if (WSManPluginConstants.ExitCodeSuccess != result) + if (result != WSManPluginConstants.ExitCodeSuccess) { ReportOperationComplete( requestDetails, @@ -563,7 +563,7 @@ private void AddToActiveShellSessions( lock (_syncObject) { IntPtr key = newShellSession.creationRequestDetails.unmanagedHandle; - Dbg.Assert(IntPtr.Zero != key, "NULL handles should not be provided"); + Dbg.Assert(key != IntPtr.Zero, "NULL handles should not be provided"); if (!_activeShellSessions.ContainsKey(key)) { @@ -574,7 +574,7 @@ private void AddToActiveShellSessions( } } - if (-1 != count) + if (count != -1) { // Raise session count changed event WSManServerChannelEvents.RaiseActiveSessionsChangedEvent(new ActiveSessionsChangedEventArgs(count)); @@ -614,7 +614,7 @@ private void DeleteFromActiveShellSessions( } } - if (-1 != count) + if (count != -1) { // Raise session count changed event WSManServerChannelEvents.RaiseActiveSessionsChangedEvent(new ActiveSessionsChangedEventArgs(count)); @@ -640,7 +640,7 @@ private void HandleShellSessionClosed( /// /// /// - private bool validateIncomingContexts( + private static bool validateIncomingContexts( WSManNativeApi.WSManPluginRequest requestDetails, IntPtr shellContext, string inputFunctionName) @@ -662,7 +662,7 @@ private bool validateIncomingContexts( return false; } - if (IntPtr.Zero == shellContext) + if (shellContext == IntPtr.Zero) { ReportOperationComplete( requestDetails, @@ -871,7 +871,7 @@ internal void ConnectShellOrCommand( return; } - if (IntPtr.Zero == commandContext) + if (commandContext == IntPtr.Zero) { mgdShellSession.ExecuteConnect(requestDetails, flags, inboundConnectInformation); return; @@ -964,7 +964,7 @@ internal void SendOneItemToShellOrCommand( return; } - if (IntPtr.Zero == commandContext) + if (commandContext == IntPtr.Zero) { // the data is destined for shell (runspace) session. so let shell handle it mgdShellSession.SendOneItemToSession(requestDetails, flags, stream, inboundData); @@ -1075,7 +1075,7 @@ internal void EnableShellOrCommandToSendDataToClient( "EnableShellOrCommandToSendDataToClient: Instruction destined to shell or for command", string.Empty); - if (IntPtr.Zero == commandContext) + if (commandContext == IntPtr.Zero) { // the instruction is destined for shell (runspace) session. so let shell handle it if (mgdShellSession.EnableSessionToSendDataToClient(requestDetails, flags, streamSet, ctxtToReport)) @@ -1111,7 +1111,7 @@ internal void EnableShellOrCommandToSendDataToClient( /// /// /// - private PSSenderInfo GetPSSenderInfo( + private static PSSenderInfo GetPSSenderInfo( WSManNativeApi.WSManSenderDetails senderDetails) { // senderDetails will not be null. @@ -1168,7 +1168,7 @@ private PSSenderInfo GetPSSenderInfo( /// environment variable, which is set in the WSMan layer for Virtual or RunAs accounts. /// /// ClientToken IntPtr. - private IntPtr GetRunAsClientToken() + private static IntPtr GetRunAsClientToken() { string clientTokenStr = System.Environment.GetEnvironmentVariable(WSManRunAsClientTokenName); if (clientTokenStr != null) @@ -1211,7 +1211,7 @@ protected internal bool EnsureOptionsComply( isProtocolVersionDeclared = true; } - if (0 == string.Compare(option.name, 0, WSManPluginConstants.PowerShellOptionPrefix, 0, WSManPluginConstants.PowerShellOptionPrefix.Length, StringComparison.Ordinal)) + if (string.Compare(option.name, 0, WSManPluginConstants.PowerShellOptionPrefix, 0, WSManPluginConstants.PowerShellOptionPrefix.Length, StringComparison.Ordinal) == 0) { if (option.mustComply) { @@ -1576,7 +1576,7 @@ internal static void PerformWSManPluginSignal( WSManNativeApi.WSManPluginRequest request = WSManNativeApi.WSManPluginRequest.UnMarshal(requestDetails); // Close Command - if (IntPtr.Zero != commandContext) + if (commandContext != IntPtr.Zero) { if (!string.Equals(code, WSManPluginConstants.CtrlCSignal, StringComparison.Ordinal)) { @@ -1640,7 +1640,7 @@ internal static void PerformCloseOperation( return; } - if (IntPtr.Zero == context.commandContext) + if (context.commandContext == IntPtr.Zero) { // this is targeted at shell pluginToUse.CloseShellOperation(context); @@ -1785,7 +1785,7 @@ internal static void SetThreadProperties( WSManPluginConstants.WSManPluginParamsGetRequestedLocale, outputStruct); // ref nativeLocaleData); - bool retrievingLocaleSucceeded = (0 == hResult); + bool retrievingLocaleSucceeded = (hResult == 0); WSManNativeApi.WSManData_UnToMan localeData = WSManNativeApi.WSManData_UnToMan.UnMarshal(outputStruct); // nativeLocaleData // IntPtr nativeDataLocaleData = IntPtr.Zero; @@ -1794,13 +1794,13 @@ internal static void SetThreadProperties( WSManPluginConstants.WSManPluginParamsGetRequestedDataLocale, outputStruct); // ref nativeDataLocaleData); - bool retrievingDataLocaleSucceeded = ((int)WSManPluginErrorCodes.NoError == hResult); + bool retrievingDataLocaleSucceeded = (hResult == (int)WSManPluginErrorCodes.NoError); WSManNativeApi.WSManData_UnToMan dataLocaleData = WSManNativeApi.WSManData_UnToMan.UnMarshal(outputStruct); // nativeDataLocaleData // Set the UI Culture try { - if (retrievingLocaleSucceeded && ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT == localeData.Type)) + if (retrievingLocaleSucceeded && (localeData.Type == (uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT)) { CultureInfo uiCultureToUse = new CultureInfo(localeData.Text); Thread.CurrentThread.CurrentUICulture = uiCultureToUse; @@ -1814,7 +1814,7 @@ internal static void SetThreadProperties( // Set the Culture try { - if (retrievingDataLocaleSucceeded && ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT == dataLocaleData.Type)) + if (retrievingDataLocaleSucceeded && (dataLocaleData.Type == (uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT)) { CultureInfo cultureToUse = new CultureInfo(dataLocaleData.Text); Thread.CurrentThread.CurrentCulture = cultureToUse; @@ -1883,7 +1883,7 @@ internal static void ReportOperationComplete( WSManPluginErrorCodes errorCode) { if (requestDetails != null && - IntPtr.Zero != requestDetails.unmanagedHandle) + requestDetails.unmanagedHandle != IntPtr.Zero) { wsmanPinvokeStatic.WSManPluginOperationComplete( requestDetails.unmanagedHandle, @@ -1906,7 +1906,7 @@ internal static void ReportOperationComplete( WSManPluginErrorCodes errorCode, string errorMessage = "") { - if (IntPtr.Zero == requestDetails) + if (requestDetails == IntPtr.Zero) { // cannot report if requestDetails is null. return; diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginFacade.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginFacade.cs index 4c3a2953660..f01797fd760 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginFacade.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginFacade.cs @@ -33,7 +33,7 @@ namespace System.Management.Automation.Remoting /// PCWSTR. /// WSMAN_SHELL_STARTUP_INFO*. /// WSMAN_DATA*. - internal delegate void WSMPluginShellDelegate( // TODO: Rename to WSManPluginShellDelegate once I remove the MC++ module. + internal delegate void WSManPluginShellDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -45,7 +45,7 @@ internal delegate void WSMPluginShellDelegate( // TODO: Rename to WSManPluginShe /// /// PVOID. /// PVOID. - internal delegate void WSMPluginReleaseShellContextDelegate( + internal delegate void WSManPluginReleaseShellContextDelegate( IntPtr pluginContext, IntPtr shellContext); @@ -57,7 +57,7 @@ internal delegate void WSMPluginReleaseShellContextDelegate( /// PVOID. /// PVOID optional. /// WSMAN_DATA* optional. - internal delegate void WSMPluginConnectDelegate( + internal delegate void WSManPluginConnectDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -73,7 +73,7 @@ internal delegate void WSMPluginConnectDelegate( /// PVOID. /// PCWSTR. /// WSMAN_COMMAND_ARG_SET*. - internal delegate void WSMPluginCommandDelegate( + internal delegate void WSManPluginCommandDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -85,7 +85,7 @@ internal delegate void WSMPluginCommandDelegate( /// Delegate that is passed to native layer for callback on operation shutdown notifications. /// /// IntPtr. - internal delegate void WSMPluginOperationShutdownDelegate( + internal delegate void WSManPluginOperationShutdownDelegate( IntPtr shutdownContext); /// @@ -93,7 +93,7 @@ internal delegate void WSMPluginOperationShutdownDelegate( /// PVOID. /// PVOID. /// PVOID. - internal delegate void WSMPluginReleaseCommandContextDelegate( + internal delegate void WSManPluginReleaseCommandContextDelegate( IntPtr pluginContext, IntPtr shellContext, IntPtr commandContext); @@ -107,7 +107,7 @@ internal delegate void WSMPluginReleaseCommandContextDelegate( /// PVOID. /// PCWSTR. /// WSMAN_DATA*. - internal delegate void WSMPluginSendDelegate( + internal delegate void WSManPluginSendDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -124,7 +124,7 @@ internal delegate void WSMPluginSendDelegate( /// PVOID. /// PVOID optional. /// WSMAN_STREAM_ID_SET* optional. - internal delegate void WSMPluginReceiveDelegate( + internal delegate void WSManPluginReceiveDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -140,7 +140,7 @@ internal delegate void WSMPluginReceiveDelegate( /// PVOID. /// PVOID optional. /// PCWSTR. - internal delegate void WSMPluginSignalDelegate( + internal delegate void WSManPluginSignalDelegate( IntPtr pluginContext, IntPtr requestDetails, int flags, @@ -160,7 +160,7 @@ internal delegate void WaitOrTimerCallbackDelegate( /// /// /// PVOID. - internal delegate void WSMShutdownPluginDelegate( + internal delegate void WSManShutdownPluginDelegate( IntPtr pluginContext); /// @@ -170,7 +170,7 @@ internal sealed class WSManPluginEntryDelegates : IDisposable #region Private Members // Holds the delegate pointers in a structure that has identical layout to the native structure. - private WSManPluginEntryDelegatesInternal _unmanagedStruct = new WSManPluginEntryDelegatesInternal(); + private readonly WSManPluginEntryDelegatesInternal _unmanagedStruct = new WSManPluginEntryDelegatesInternal(); internal WSManPluginEntryDelegatesInternal UnmanagedStruct { @@ -192,7 +192,7 @@ internal WSManPluginEntryDelegatesInternal UnmanagedStruct private GCHandle _pluginSignalGCHandle; private GCHandle _pluginConnectGCHandle; private GCHandle _shutdownPluginGCHandle; - private GCHandle _WSMPluginOperationShutdownGCHandle; + private GCHandle _WSManPluginOperationShutdownGCHandle; #endregion @@ -234,11 +234,7 @@ private void Dispose(bool disposing) } /// - /// Use C# destructor syntax for finalization code. - /// This destructor will run only if the Dispose method - /// does not get called. - /// It gives your base class the opportunity to finalize. - /// Do not provide destructors in types derived from this class. + /// Finalizes an instance of the class. /// ~WSManPluginEntryDelegates() { @@ -259,57 +255,57 @@ private void populateDelegates() // disposal. Using GCHandle without pinning reduces fragmentation potential // of the managed heap. { - WSMPluginShellDelegate pluginShell = new WSMPluginShellDelegate(WSManPluginManagedEntryWrapper.WSManPluginShell); + WSManPluginShellDelegate pluginShell = new WSManPluginShellDelegate(WSManPluginManagedEntryWrapper.WSManPluginShell); _pluginShellGCHandle = GCHandle.Alloc(pluginShell); // marshal the delegate to a unmanaged function pointer so that AppDomain reference is stored correctly. // Populate the outgoing structure so the caller has access to the entry points _unmanagedStruct.wsManPluginShellCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginShell); } { - WSMPluginReleaseShellContextDelegate pluginReleaseShellContext = new WSMPluginReleaseShellContextDelegate(WSManPluginManagedEntryWrapper.WSManPluginReleaseShellContext); + WSManPluginReleaseShellContextDelegate pluginReleaseShellContext = new WSManPluginReleaseShellContextDelegate(WSManPluginManagedEntryWrapper.WSManPluginReleaseShellContext); _pluginReleaseShellContextGCHandle = GCHandle.Alloc(pluginReleaseShellContext); _unmanagedStruct.wsManPluginReleaseShellContextCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginReleaseShellContext); } { - WSMPluginCommandDelegate pluginCommand = new WSMPluginCommandDelegate(WSManPluginManagedEntryWrapper.WSManPluginCommand); + WSManPluginCommandDelegate pluginCommand = new WSManPluginCommandDelegate(WSManPluginManagedEntryWrapper.WSManPluginCommand); _pluginCommandGCHandle = GCHandle.Alloc(pluginCommand); _unmanagedStruct.wsManPluginCommandCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginCommand); } { - WSMPluginReleaseCommandContextDelegate pluginReleaseCommandContext = new WSMPluginReleaseCommandContextDelegate(WSManPluginManagedEntryWrapper.WSManPluginReleaseCommandContext); + WSManPluginReleaseCommandContextDelegate pluginReleaseCommandContext = new WSManPluginReleaseCommandContextDelegate(WSManPluginManagedEntryWrapper.WSManPluginReleaseCommandContext); _pluginReleaseCommandContextGCHandle = GCHandle.Alloc(pluginReleaseCommandContext); _unmanagedStruct.wsManPluginReleaseCommandContextCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginReleaseCommandContext); } { - WSMPluginSendDelegate pluginSend = new WSMPluginSendDelegate(WSManPluginManagedEntryWrapper.WSManPluginSend); + WSManPluginSendDelegate pluginSend = new WSManPluginSendDelegate(WSManPluginManagedEntryWrapper.WSManPluginSend); _pluginSendGCHandle = GCHandle.Alloc(pluginSend); _unmanagedStruct.wsManPluginSendCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginSend); } { - WSMPluginReceiveDelegate pluginReceive = new WSMPluginReceiveDelegate(WSManPluginManagedEntryWrapper.WSManPluginReceive); + WSManPluginReceiveDelegate pluginReceive = new WSManPluginReceiveDelegate(WSManPluginManagedEntryWrapper.WSManPluginReceive); _pluginReceiveGCHandle = GCHandle.Alloc(pluginReceive); _unmanagedStruct.wsManPluginReceiveCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginReceive); } { - WSMPluginSignalDelegate pluginSignal = new WSMPluginSignalDelegate(WSManPluginManagedEntryWrapper.WSManPluginSignal); + WSManPluginSignalDelegate pluginSignal = new WSManPluginSignalDelegate(WSManPluginManagedEntryWrapper.WSManPluginSignal); _pluginSignalGCHandle = GCHandle.Alloc(pluginSignal); _unmanagedStruct.wsManPluginSignalCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginSignal); } { - WSMPluginConnectDelegate pluginConnect = new WSMPluginConnectDelegate(WSManPluginManagedEntryWrapper.WSManPluginConnect); + WSManPluginConnectDelegate pluginConnect = new WSManPluginConnectDelegate(WSManPluginManagedEntryWrapper.WSManPluginConnect); _pluginConnectGCHandle = GCHandle.Alloc(pluginConnect); _unmanagedStruct.wsManPluginConnectCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginConnect); } { - WSMShutdownPluginDelegate shutdownPlugin = new WSMShutdownPluginDelegate(WSManPluginManagedEntryWrapper.ShutdownPlugin); + WSManShutdownPluginDelegate shutdownPlugin = new WSManShutdownPluginDelegate(WSManPluginManagedEntryWrapper.ShutdownPlugin); _shutdownPluginGCHandle = GCHandle.Alloc(shutdownPlugin); _unmanagedStruct.wsManPluginShutdownPluginCallbackNative = Marshal.GetFunctionPointerForDelegate(shutdownPlugin); } if (!Platform.IsWindows) { - WSMPluginOperationShutdownDelegate pluginShutDownDelegate = new WSMPluginOperationShutdownDelegate(WSManPluginManagedEntryWrapper.WSManPSShutdown); - _WSMPluginOperationShutdownGCHandle = GCHandle.Alloc(pluginShutDownDelegate); + WSManPluginOperationShutdownDelegate pluginShutDownDelegate = new WSManPluginOperationShutdownDelegate(WSManPluginManagedEntryWrapper.WSManPSShutdown); + _WSManPluginOperationShutdownGCHandle = GCHandle.Alloc(pluginShutDownDelegate); _unmanagedStruct.wsManPluginShutdownCallbackNative = Marshal.GetFunctionPointerForDelegate(pluginShutDownDelegate); } } @@ -332,7 +328,7 @@ private void CleanUpDelegates() _shutdownPluginGCHandle.Free(); if (!Platform.IsWindows) { - _WSMPluginOperationShutdownGCHandle.Free(); + _WSManPluginOperationShutdownGCHandle.Free(); } } } @@ -433,7 +429,7 @@ private WSManPluginManagedEntryWrapper() { } public static int InitPlugin( IntPtr wkrPtrs) { - if (IntPtr.Zero == wkrPtrs) + if (wkrPtrs == IntPtr.Zero) { return WSManPluginConstants.ExitCodeFailure; } @@ -473,7 +469,7 @@ public static void WSManPluginConnect( IntPtr commandContext, IntPtr inboundConnectInformation) { - if (IntPtr.Zero == pluginContext) + if (pluginContext == IntPtr.Zero) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -505,7 +501,7 @@ public static void WSManPluginShell( IntPtr startupInfo, IntPtr inboundShellInformation) { - if (IntPtr.Zero == pluginContext) + if (pluginContext == IntPtr.Zero) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -561,7 +557,7 @@ public static void WSManPluginCommand( [MarshalAs(UnmanagedType.LPWStr)] string commandLine, IntPtr arguments) { - if (IntPtr.Zero == pluginContext) + if (pluginContext == IntPtr.Zero) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -622,7 +618,7 @@ public static void WSManPluginSend( [MarshalAs(UnmanagedType.LPWStr)] string stream, IntPtr inboundData) { - if (IntPtr.Zero == pluginContext) + if (pluginContext == IntPtr.Zero) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -654,7 +650,7 @@ public static void WSManPluginReceive( IntPtr commandContext, IntPtr streamSet) { - if (IntPtr.Zero == pluginContext) + if (pluginContext == IntPtr.Zero) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -686,7 +682,7 @@ public static void WSManPluginSignal( IntPtr commandContext, [MarshalAs(UnmanagedType.LPWStr)] string code) { - if ((IntPtr.Zero == pluginContext) || (IntPtr.Zero == shellContext)) + if ((pluginContext == IntPtr.Zero) || (shellContext == IntPtr.Zero)) { WSManPluginInstance.ReportOperationComplete( requestDetails, @@ -766,11 +762,7 @@ private void Dispose(bool disposing) } /// - /// Use C# destructor syntax for finalization code. - /// This destructor will run only if the Dispose method - /// does not get called. - /// It gives your base class the opportunity to finalize. - /// Do not provide destructors in types derived from this class. + /// Finalizes an instance of the class. /// ~WSManPluginManagedEntryInstanceWrapper() { diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginShellSession.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginShellSession.cs index e6a857c1434..51635922e0b 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginShellSession.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginShellSession.cs @@ -25,7 +25,7 @@ namespace System.Management.Automation.Remoting /// internal abstract class WSManPluginServerSession : IDisposable { - private object _syncObject; + private readonly object _syncObject; protected bool isClosed; protected bool isContextReported; @@ -111,11 +111,7 @@ protected virtual void Dispose(bool disposing) } /// - /// Use C# destructor syntax for finalization code. - /// This destructor will run only if the Dispose method - /// does not get called. - /// It gives your base class the opportunity to finalize. - /// Do not provide destructors in types derived from this class. + /// Finalizes an instance of the class. /// ~WSManPluginServerSession() { @@ -152,7 +148,7 @@ internal void SendOneItemToSession( return; } - if ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_BINARY != inboundData.Type) + if (inboundData.Type != (uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_BINARY) { // only binary data is supported WSManPluginInstance.ReportOperationComplete( @@ -202,7 +198,7 @@ internal bool EnableSessionToSendDataToClient( } if ((streamSet == null) || - (1 != streamSet.streamIDsCount)) + (streamSet.streamIDsCount != 1)) { // only "stdout" is the supported output stream. WSManPluginInstance.ReportOperationComplete( @@ -256,7 +252,7 @@ internal void ReportContext() // TO BE FIXED - As soon as this API is called, WinRM service will send CommandResponse back and Signal is expected anytime // If Signal comes and executes before registering the notification handle, cleanup will be messed result = WSManNativeApi.WSManPluginReportContext(creationRequestDetails.unmanagedHandle, 0, creationRequestDetails.unmanagedHandle); - if (Platform.IsWindows && (WSManPluginConstants.ExitCodeSuccess == result)) + if (Platform.IsWindows && (result == WSManPluginConstants.ExitCodeSuccess)) { registeredShutdownNotification = 1; @@ -281,7 +277,7 @@ internal void ReportContext() } } - if ((WSManPluginConstants.ExitCodeSuccess != result) || (isRegisterWaitForSingleObjectFailed)) + if ((result != WSManPluginConstants.ExitCodeSuccess) || (isRegisterWaitForSingleObjectFailed)) { string errorMessage; if (isRegisterWaitForSingleObjectFailed) @@ -399,8 +395,8 @@ internal class WSManPluginShellSession : WSManPluginServerSession { #region Private Members - private Dictionary _activeCommandSessions; - private ServerRemoteSession _remoteSession; + private readonly Dictionary _activeCommandSessions; + private readonly ServerRemoteSession _remoteSession; #endregion @@ -591,7 +587,7 @@ private void AddToActiveCmdSessions( } IntPtr key = newCmdSession.creationRequestDetails.unmanagedHandle; - Dbg.Assert(IntPtr.Zero != key, "NULL handles should not be provided"); + Dbg.Assert(key != IntPtr.Zero, "NULL handles should not be provided"); if (!_activeCommandSessions.ContainsKey(key)) { @@ -729,7 +725,7 @@ internal class WSManPluginCommandSession : WSManPluginServerSession { #region Private Members - private ServerRemoteSession _remoteSession; + private readonly ServerRemoteSession _remoteSession; #endregion @@ -756,7 +752,7 @@ internal WSManPluginCommandSession( internal bool ProcessArguments( WSManNativeApi.WSManCommandArgSet arguments) { - if (1 != arguments.argsCount) + if (arguments.argsCount != 1) { return false; } diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginTransportManager.cs index 13b5267f486..9cc10ce435e 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManPluginTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManPluginTransportManager.cs @@ -23,9 +23,9 @@ internal class WSManPluginServerTransportManager : AbstractServerSessionTranspor // the following variables are used to block thread from sending // data to the client until the client sends a receive request. private bool _isRequestPending; - private object _syncObject; - private ManualResetEvent _waitHandle; - private Dictionary _activeCmdTransportManagers; + private readonly object _syncObject; + private readonly ManualResetEvent _waitHandle; + private readonly Dictionary _activeCmdTransportManagers; private bool _isClosed; // used to keep track of last error..this will be used // for reporting operation complete to WSMan. @@ -181,7 +181,7 @@ internal override void ReportExecutionStatusAsRunning() } } - if ((int)WSManPluginErrorCodes.NoError != result) + if (result != (int)WSManPluginErrorCodes.NoError) { ReportError(result, "WSManPluginReceiveResult"); } @@ -247,7 +247,7 @@ protected override void SendDataToClient( } } - if ((int)WSManPluginErrorCodes.NoError != result) + if (result != (int)WSManPluginErrorCodes.NoError) { ReportError(result, "WSManPluginReceiveResult"); } @@ -304,6 +304,7 @@ internal override void RemoveCommandTransportManager( _activeCmdTransportManagers.Remove(cmdId); } } + #endregion internal bool EnableTransportManagerSendDataToClient( WSManNativeApi.WSManPluginRequest requestDetails, @@ -387,7 +388,7 @@ internal void PerformStop() internal class WSManPluginCommandTransportManager : WSManPluginServerTransportManager { - private WSManPluginServerTransportManager _serverTransportMgr; + private readonly WSManPluginServerTransportManager _serverTransportMgr; private System.Guid _cmdId; // Create Cmd Transport Manager for this sessn transport manager diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs index 92cb98664e3..60e4228c9a3 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs @@ -38,7 +38,7 @@ internal static class WSManTransportManagerUtils #region Static Data // Fully qualified error Id modifiers based on transport (WinRM) error codes. - private static Dictionary s_transportErrorCodeToFQEID = new Dictionary() + private static readonly Dictionary s_transportErrorCodeToFQEID = new Dictionary() { {WSManNativeApi.ERROR_WSMAN_ACCESS_DENIED, "AccessDenied"}, {WSManNativeApi.ERROR_WSMAN_OUTOF_MEMORY, "ServerOutOfMemory"}, @@ -305,7 +305,7 @@ private enum CompletionNotification #region CompletionEventArgs - private class CompletionEventArgs : EventArgs + private sealed class CompletionEventArgs : EventArgs { internal CompletionEventArgs(CompletionNotification notification) { @@ -335,10 +335,10 @@ internal CompletionEventArgs(CompletionNotification notification) private WSManTransportManagerUtils.tmStartModes _startMode = WSManTransportManagerUtils.tmStartModes.None; - private string _sessionName; + private readonly string _sessionName; // callbacks - private PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; + private readonly PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; // instance callback handlers private WSManNativeApi.WSManShellAsync _createSessionCallback; @@ -452,10 +452,11 @@ private void ProcessShellData(string data) // This dictionary maintains active session transport managers to be used from various // callbacks. - private static Dictionary s_sessionTMHandles = + private static readonly Dictionary s_sessionTMHandles = new Dictionary(); private static long s_sessionTMSeed; + // generate unique session id private static long GetNextSessionTMHandleId() { @@ -499,8 +500,8 @@ private static bool TryGetSessionTransportManager(IntPtr operationContext, #region SHIM: Redirection delegates for test purposes - private static Delegate s_sessionSendRedirect = null; - private static Delegate s_protocolVersionRedirect = null; + private static readonly Delegate s_sessionSendRedirect = null; + private static readonly Delegate s_protocolVersionRedirect = null; #endregion @@ -557,9 +558,12 @@ static WSManClientSessionTransportManager() /// /// 1. Create Session failed with a non-zero error code. /// - internal WSManClientSessionTransportManager(Guid runspacePoolInstanceId, + internal WSManClientSessionTransportManager( + Guid runspacePoolInstanceId, WSManConnectionInfo connectionInfo, - PSRemotingCryptoHelper cryptoHelper, string sessionName) : base(runspacePoolInstanceId, cryptoHelper) + PSRemotingCryptoHelper cryptoHelper, + string sessionName) + : base(runspacePoolInstanceId, cryptoHelper) { // Initialize WSMan instance WSManAPIData = new WSManAPIDataCommon(); @@ -1203,7 +1207,7 @@ internal override void CloseAsync() else if (_startMode == WSManTransportManagerUtils.tmStartModes.Create || _startMode == WSManTransportManagerUtils.tmStartModes.Connect) { - if (IntPtr.Zero == _wsManShellOperationHandle) + if (_wsManShellOperationHandle == IntPtr.Zero) { shouldRaiseCloseCompleted = true; } @@ -1472,7 +1476,7 @@ private void Initialize(Uri connectionUri, WSManConnectionInfo connectionInfo) proxyAuthCredentials = new WSManNativeApi.WSManUserNameAuthenticationCredentials(userName, password, authMechanism); } - WSManNativeApi.WSManProxyInfo proxyInfo = (ProxyAccessType.None == connectionInfo.ProxyAccessType) ? + WSManNativeApi.WSManProxyInfo proxyInfo = (connectionInfo.ProxyAccessType == ProxyAccessType.None) ? null : new WSManNativeApi.WSManProxyInfo(connectionInfo.ProxyAccessType, proxyAuthCredentials); @@ -1546,8 +1550,13 @@ private void Initialize(Uri connectionUri, WSManConnectionInfo connectionInfo) throw new PSRemotingTransportException(PSRemotingErrorId.ConnectFailed, RemotingErrorIdStrings.BasicAuthOverHttpNotSupported); } - // Allow HTTPS on Unix only if SkipCACheck and SkipCNCheck are selected, because OMI client does not support validating server certificates. - if (isSSLSpecified && (!connectionInfo.SkipCACheck || !connectionInfo.SkipCNCheck)) + // The OMI client distributed with PowerShell does not support validating server certificates on Unix. + // Check if third-party psrpclient and MI support the verification. + // If WSManGetSessionOptionAsDword does not return 0 then it's not supported. + bool verificationAvailable = WSManNativeApi.WSManGetSessionOptionAsDword(_wsManSessionHandle, + WSManNativeApi.WSManSessionOption.WSMAN_OPTION_SKIP_CA_CHECK, out _) == 0; + + if (isSSLSpecified && !verificationAvailable && (!connectionInfo.SkipCACheck || !connectionInfo.SkipCNCheck)) { throw new PSRemotingTransportException(PSRemotingErrorId.ConnectSkipCheckFailed, RemotingErrorIdStrings.UnixOnlyHttpsWithoutSkipCACheckNotSupported); } @@ -1690,7 +1699,7 @@ internal void ClearReceiveOrSendResources(int flags, bool shouldClearSend) } // For send..clear always - if (IntPtr.Zero != _wsManSendOperationHandle) + if (_wsManSendOperationHandle != IntPtr.Zero) { WSManNativeApi.WSManCloseOperation(_wsManSendOperationHandle, 0); _wsManSendOperationHandle = IntPtr.Zero; @@ -1701,7 +1710,7 @@ internal void ClearReceiveOrSendResources(int flags, bool shouldClearSend) // clearing for receive..Clear only when the end of operation is reached. if (flags == (int)WSManNativeApi.WSManCallbackFlags.WSMAN_FLAG_CALLBACK_END_OF_OPERATION) { - if (IntPtr.Zero != _wsManReceiveOperationHandle) + if (_wsManReceiveOperationHandle != IntPtr.Zero) { WSManNativeApi.WSManCloseOperation(_wsManReceiveOperationHandle, 0); _wsManReceiveOperationHandle = IntPtr.Zero; @@ -1889,7 +1898,7 @@ private static void OnCreateSessionCallback(IntPtr operationContext, } } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -1919,7 +1928,7 @@ private static void OnCreateSessionCallback(IntPtr operationContext, } // check if the session supports disconnect - sessionTM.SupportsDisconnect = ((flags & (int)WSManNativeApi.WSManCallbackFlags.WSMAN_FLAG_CALLBACK_SHELL_SUPPORTS_DISCONNECT) != 0) ? true : false; + sessionTM.SupportsDisconnect = (flags & (int)WSManNativeApi.WSManCallbackFlags.WSMAN_FLAG_CALLBACK_SHELL_SUPPORTS_DISCONNECT) != 0; // openContent is used by redirection ie., while redirecting to // a new machine.. this is not needed anymore as the connection @@ -1990,7 +1999,7 @@ private static void OnCloseSessionCompleted(IntPtr operationContext, sessionTM.RunspacePoolInstanceId.ToString(), "OnCloseSessionCompleted"); - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2049,7 +2058,7 @@ private static void OnRemoteSessionDisconnectCompleted(IntPtr operationContext, sessionTM._disconnectSessionCompleted = null; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2131,7 +2140,7 @@ private static void OnRemoteSessionReconnectCompleted(IntPtr operationContext, sessionTM._reconnectSessionCompleted = null; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2241,7 +2250,7 @@ private static void OnRemoteSessionConnectCallback(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2348,7 +2357,7 @@ private static void OnRemoteSessionSendCompleted(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2418,7 +2427,7 @@ private static void OnRemoteSessionDataReceived(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); @@ -2571,7 +2580,7 @@ private void CloseSessionAndClearResources() ThreadPool.QueueUserWorkItem(new WaitCallback( // wsManSessionHandle is passed as parameter to allow the thread to be independent // of the rest of the parent object. - delegate (object state) + (object state) => { IntPtr sessionHandle = (IntPtr)state; if (sessionHandle != IntPtr.Zero) @@ -2621,11 +2630,7 @@ private void DisposeWSManAPIDataAsync() // Dispose and de-initialize the WSManAPIData instance object on separate worker thread to ensure // it is not run on a WinRM thread (which will fail). // Note that WSManAPIData.Dispose() method is thread safe. - System.Threading.ThreadPool.QueueUserWorkItem( - (state) => - { - tempWSManApiData.Dispose(); - }); + ThreadPool.QueueUserWorkItem((_) => tempWSManApiData.Dispose()); } #endregion @@ -2645,9 +2650,9 @@ internal class WSManAPIDataCommon : IDisposable private WSManNativeApi.WSManStreamIDSet_ManToUn _outputStreamSet; // Dispose private bool _isDisposed; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); #if !UNIX - private WindowsIdentity _identityToImpersonate; + private readonly WindowsIdentity _identityToImpersonate; #endif /// @@ -2729,7 +2734,7 @@ public void Dispose() _inputStreamSet.Dispose(); _outputStreamSet.Dispose(); - if (IntPtr.Zero != _handle) + if (_handle != IntPtr.Zero) { int result = 0; @@ -2782,7 +2787,7 @@ internal sealed class WSManClientCommandTransportManager : BaseClientCommandTran #region Private Data // operation handles - private IntPtr _wsManShellOperationHandle; + private readonly IntPtr _wsManShellOperationHandle; [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] private IntPtr _wsManCmdOperationHandle; @@ -2798,7 +2803,7 @@ internal sealed class WSManClientCommandTransportManager : BaseClientCommandTran // this is used with WSMan callbacks to represent a command transport manager. private long _cmdContextId; - private PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; + private readonly PrioritySendDataCollection.OnDataAvailableCallback _onDataAvailableToSendCallback; // should be integrated with receiveDataInitiated private bool _shouldStartReceivingData; @@ -2825,10 +2830,10 @@ internal sealed class WSManClientCommandTransportManager : BaseClientCommandTran // will be sent during subsequent SendOneItem() private SendDataChunk _chunkToSend; - private string _cmdLine; + private readonly string _cmdLine; private readonly WSManClientSessionTransportManager _sessnTm; - private class SendDataChunk + private sealed class SendDataChunk { public SendDataChunk(byte[] data, DataPriorityType type) { @@ -2910,14 +2915,15 @@ static WSManClientCommandTransportManager() /// Session transport manager creating this command transport manager instance. /// Used by Command TM to apply session specific properties /// - internal WSManClientCommandTransportManager(WSManConnectionInfo connectionInfo, + internal WSManClientCommandTransportManager( + WSManConnectionInfo connectionInfo, IntPtr wsManShellOperationHandle, ClientRemotePowerShell shell, bool noInput, - WSManClientSessionTransportManager sessnTM) : - base(shell, sessnTM.CryptoHelper, sessnTM) + WSManClientSessionTransportManager sessnTM) + : base(shell, sessnTM.CryptoHelper, sessnTM) { - Dbg.Assert(IntPtr.Zero != wsManShellOperationHandle, "Shell operation handle cannot be IntPtr.Zero."); + Dbg.Assert(wsManShellOperationHandle != IntPtr.Zero, "Shell operation handle cannot be IntPtr.Zero."); Dbg.Assert(connectionInfo != null, "connectionInfo cannot be null"); _wsManShellOperationHandle = wsManShellOperationHandle; @@ -2940,7 +2946,7 @@ internal WSManClientCommandTransportManager(WSManConnectionInfo connectionInfo, #region SHIM: Redirection delegate for command code send. - private static Delegate s_commandCodeSendRedirect = null; + private static readonly Delegate s_commandCodeSendRedirect = null; #endregion @@ -3159,7 +3165,7 @@ internal override void CloseAsync() // There is no valid cmd operation handle..so just // raise close completed. - if (IntPtr.Zero == _wsManCmdOperationHandle) + if (_wsManCmdOperationHandle == IntPtr.Zero) { shouldRaiseCloseCompleted = true; } @@ -3285,7 +3291,7 @@ internal void ClearReceiveOrSendResources(int flags, bool shouldClearSend) } // For send..clear always - if (IntPtr.Zero != _wsManSendOperationHandle) + if (_wsManSendOperationHandle != IntPtr.Zero) { WSManNativeApi.WSManCloseOperation(_wsManSendOperationHandle, 0); _wsManSendOperationHandle = IntPtr.Zero; @@ -3296,7 +3302,7 @@ internal void ClearReceiveOrSendResources(int flags, bool shouldClearSend) // clearing for receive..Clear only when the end of operation is reached. if (flags == (int)WSManNativeApi.WSManCallbackFlags.WSMAN_FLAG_CALLBACK_END_OF_OPERATION) { - if (IntPtr.Zero != _wsManReceiveOperationHandle) + if (_wsManReceiveOperationHandle != IntPtr.Zero) { WSManNativeApi.WSManCloseOperation(_wsManReceiveOperationHandle, 0); _wsManReceiveOperationHandle = IntPtr.Zero; @@ -3385,7 +3391,7 @@ private static void OnCreateCmdCompleted(IntPtr operationContext, // Remove this once WSMan fixes its code. cmdTM._wsManCmdOperationHandle = commandOperationHandle; - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) @@ -3483,7 +3489,7 @@ private static void OnConnectCmdCompleted(IntPtr operationContext, cmdTM._wsManCmdOperationHandle = commandOperationHandle; - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) @@ -3654,7 +3660,7 @@ private static void OnRemoteCmdSendCompleted(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); // Ignore Command aborted error. Command aborted is raised by WSMan to @@ -3731,7 +3737,7 @@ private static void OnRemoteCmdDataReceived(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) @@ -3811,7 +3817,7 @@ private static void OnReconnectCmdCompleted(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) @@ -3884,7 +3890,7 @@ private static void OnRemoteCmdSignalCompleted(IntPtr operationContext, } // release the resources related to signal - if (IntPtr.Zero != cmdTM._cmdSignalOperationHandle) + if (cmdTM._cmdSignalOperationHandle != IntPtr.Zero) { WSManNativeApi.WSManCloseOperation(cmdTM._cmdSignalOperationHandle, 0); cmdTM._cmdSignalOperationHandle = IntPtr.Zero; @@ -3903,7 +3909,7 @@ private static void OnRemoteCmdSignalCompleted(IntPtr operationContext, return; } - if (IntPtr.Zero != error) + if (error != IntPtr.Zero) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) @@ -3986,7 +3992,7 @@ private void OnDataAvailableCallback(byte[] data, DataPriorityType priorityType) #region SHIM: Redirection delegate for command data send. - private static Delegate s_commandSendRedirect = null; + private static readonly Delegate s_commandSendRedirect = null; #endregion @@ -4116,7 +4122,7 @@ internal override void Dispose(bool isDisposing) // This dictionary maintains active command transport managers to be used from various // callbacks. - private static Dictionary s_cmdTMHandles = + private static readonly Dictionary s_cmdTMHandles = new Dictionary(); private static long s_cmdTMSeed; diff --git a/src/System.Management.Automation/engine/remoting/host/RemoteHostMethodInfo.cs b/src/System.Management.Automation/engine/remoting/host/RemoteHostMethodInfo.cs index 63185ebc13f..e24f8961b9a 100644 --- a/src/System.Management.Automation/engine/remoting/host/RemoteHostMethodInfo.cs +++ b/src/System.Management.Automation/engine/remoting/host/RemoteHostMethodInfo.cs @@ -144,35 +144,35 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHost), "get_Name", typeof(string), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetVersion: return new RemoteHostMethodInfo( typeof(PSHost), "get_Version", typeof(Version), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetInstanceId: return new RemoteHostMethodInfo( typeof(PSHost), "get_InstanceId", typeof(Guid), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetCurrentCulture: return new RemoteHostMethodInfo( typeof(PSHost), "get_CurrentCulture", typeof(System.Globalization.CultureInfo), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetCurrentUICulture: return new RemoteHostMethodInfo( typeof(PSHost), "get_CurrentUICulture", typeof(System.Globalization.CultureInfo), - new Type[] { }); + Array.Empty()); // Host methods. @@ -188,28 +188,28 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHost), "EnterNestedPrompt", typeof(void), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.ExitNestedPrompt: return new RemoteHostMethodInfo( typeof(PSHost), "ExitNestedPrompt", typeof(void), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.NotifyBeginApplication: return new RemoteHostMethodInfo( typeof(PSHost), "NotifyBeginApplication", typeof(void), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.NotifyEndApplication: return new RemoteHostMethodInfo( typeof(PSHost), "NotifyEndApplication", typeof(void), - new Type[] { }); + Array.Empty()); // Host UI methods. @@ -218,14 +218,14 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostUserInterface), "ReadLine", typeof(string), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.ReadLineAsSecureString: return new RemoteHostMethodInfo( typeof(PSHostUserInterface), "ReadLineAsSecureString", typeof(System.Security.SecureString), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.Write1: return new RemoteHostMethodInfo( @@ -246,7 +246,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostUserInterface), "WriteLine", typeof(void), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.WriteLine2: return new RemoteHostMethodInfo( @@ -339,7 +339,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_ForegroundColor", typeof(ConsoleColor), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetForegroundColor: return new RemoteHostMethodInfo( @@ -353,7 +353,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_BackgroundColor", typeof(ConsoleColor), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetBackgroundColor: return new RemoteHostMethodInfo( @@ -367,7 +367,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_CursorPosition", typeof(Coordinates), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetCursorPosition: return new RemoteHostMethodInfo( @@ -381,7 +381,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_WindowPosition", typeof(Coordinates), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetWindowPosition: return new RemoteHostMethodInfo( @@ -395,7 +395,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_CursorSize", typeof(int), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetCursorSize: return new RemoteHostMethodInfo( @@ -409,7 +409,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_BufferSize", typeof(Size), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetBufferSize: return new RemoteHostMethodInfo( @@ -423,7 +423,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_WindowSize", typeof(Size), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetWindowSize: return new RemoteHostMethodInfo( @@ -437,7 +437,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_WindowTitle", typeof(string), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetWindowTitle: return new RemoteHostMethodInfo( @@ -453,21 +453,21 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "get_MaxWindowSize", typeof(Size), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetMaxPhysicalWindowSize: return new RemoteHostMethodInfo( typeof(PSHostRawUserInterface), "get_MaxPhysicalWindowSize", typeof(Size), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetKeyAvailable: return new RemoteHostMethodInfo( typeof(PSHostRawUserInterface), "get_KeyAvailable", typeof(bool), - new Type[] { }); + Array.Empty()); // Host raw UI methods. @@ -483,7 +483,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(PSHostRawUserInterface), "FlushInputBuffer", typeof(void), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.SetBufferContents1: return new RemoteHostMethodInfo( @@ -527,7 +527,7 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(IHostSupportsInteractiveSession), "PopRunspace", typeof(void), - new Type[] { }); + Array.Empty()); // IHostSupportsInteractiveSession properties. @@ -536,14 +536,14 @@ internal static RemoteHostMethodInfo LookUp(RemoteHostMethodId methodId) typeof(IHostSupportsInteractiveSession), "get_IsRunspacePushed", typeof(bool), - new Type[] { }); + Array.Empty()); case RemoteHostMethodId.GetRunspace: return new RemoteHostMethodInfo( typeof(IHostSupportsInteractiveSession), "get_Runspace", typeof(System.Management.Automation.Runspaces.Runspace), - new Type[] { }); + Array.Empty()); default: Dbg.Assert(false, "All RemoteHostMethodId's should be handled. This code should not be reached."); diff --git a/src/System.Management.Automation/engine/remoting/server/OutOfProcServerMediator.cs b/src/System.Management.Automation/engine/remoting/server/OutOfProcServerMediator.cs index 67817c8c6e2..fe17a31f0cb 100644 --- a/src/System.Management.Automation/engine/remoting/server/OutOfProcServerMediator.cs +++ b/src/System.Management.Automation/engine/remoting/server/OutOfProcServerMediator.cs @@ -8,7 +8,6 @@ #if !UNIX using System.Security.Principal; #endif -using Microsoft.Win32.SafeHandles; using Dbg = System.Management.Automation.Diagnostics; @@ -73,14 +72,6 @@ protected void ProcessingThreadStart(object state) { try { -#if !CORECLR - // CurrentUICulture is not available in Thread Class in CSS - // WinBlue: 621775. Thread culture is not properly set - // for local background jobs causing experience differences - // between local console and local background jobs. - Thread.CurrentThread.CurrentUICulture = Microsoft.PowerShell.NativeCultureResolver.UICulture; - Thread.CurrentThread.CurrentCulture = Microsoft.PowerShell.NativeCultureResolver.Culture; -#endif string data = state as string; OutOfProcessUtils.ProcessData(data, callbacks); } @@ -125,7 +116,7 @@ protected void OnDataPacketReceived(byte[] rawData, string stream, Guid psGuid) streamTemp = System.Management.Automation.Remoting.Client.WSManNativeApi.WSMAN_STREAM_ID_PROMPTRESPONSE; } - if (Guid.Empty == psGuid) + if (psGuid == Guid.Empty) { lock (_syncObject) { @@ -307,7 +298,10 @@ protected void OnCloseAckPacketReceived(Guid psGuid) #region Methods - protected OutOfProcessServerSessionTransportManager CreateSessionTransportManager(string configurationName, PSRemotingCryptoHelperServer cryptoHelper, string workingDirectory) + protected OutOfProcessServerSessionTransportManager CreateSessionTransportManager( + string configurationName, + PSRemotingCryptoHelperServer cryptoHelper, + string workingDirectory) { PSSenderInfo senderInfo; #if !UNIX @@ -335,7 +329,11 @@ protected OutOfProcessServerSessionTransportManager CreateSessionTransportManage return tm; } - protected void Start(string initialCommand, PSRemotingCryptoHelperServer cryptoHelper, string workingDirectory = null, string configurationName = null) + protected void Start( + string initialCommand, + PSRemotingCryptoHelperServer cryptoHelper, + string workingDirectory, + string configurationName) { _initialCommand = initialCommand; @@ -417,35 +415,13 @@ protected void Start(string initialCommand, PSRemotingCryptoHelperServer cryptoH } #endregion - - #region Static Methods - - internal static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs args) - { - // args can never be null. - Exception exception = (Exception)args.ExceptionObject; - // log the exception to crimson event logs - PSEtwLog.LogOperationalError(PSEventId.AppDomainUnhandledException, - PSOpcode.Close, PSTask.None, - PSKeyword.UseAlwaysOperational, - exception.GetType().ToString(), exception.Message, - exception.StackTrace); - - PSEtwLog.LogAnalyticError(PSEventId.AppDomainUnhandledException_Analytic, - PSOpcode.Close, PSTask.None, - PSKeyword.ManagedPlugin | PSKeyword.UseAlwaysAnalytic, - exception.GetType().ToString(), exception.Message, - exception.StackTrace); - } - - #endregion } - internal sealed class OutOfProcessMediator : OutOfProcessMediatorBase + internal sealed class StdIOProcessMediator : OutOfProcessMediatorBase { #region Private Data - private static OutOfProcessMediator s_singletonInstance; + private static StdIOProcessMediator s_singletonInstance; #endregion @@ -453,10 +429,10 @@ internal sealed class OutOfProcessMediator : OutOfProcessMediatorBase /// /// The mediator will take actions from the StdIn stream and responds to them. - /// It will replace StdIn,StdOut and StdErr stream with TextWriter.Null's. This is + /// It will replace StdIn,StdOut and StdErr stream with TextWriter.Null. This is /// to make sure these streams are totally used by our Mediator. /// - private OutOfProcessMediator() : base(true) + private StdIOProcessMediator() : base(true) { // Create input stream reader from Console standard input stream. // We don't use the provided Console.In TextReader because it can have @@ -465,9 +441,6 @@ private OutOfProcessMediator() : base(true) // stream encoding. This way the stream encoding is determined by the // stream BOM as needed. originalStdIn = new StreamReader(Console.OpenStandardInput(), true); - - // replacing StdIn with Null so that no other app messes with the - // original stream. Console.SetIn(TextReader.Null); // replacing StdOut with Null so that no other app messes with the @@ -490,72 +463,11 @@ private OutOfProcessMediator() : base(true) /// /// Specifies the initialization script. /// Specifies the initial working directory. The working directory is set before the initial command. - internal static void Run(string initialCommand, string workingDirectory) - { - lock (SyncObject) - { - if (s_singletonInstance != null) - { - Dbg.Assert(false, "Run should not be called multiple times"); - return; - } - - s_singletonInstance = new OutOfProcessMediator(); - } - -#if !CORECLR // AppDomain is not available in CoreCLR - // Setup unhandled exception to log events - AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException); -#endif - s_singletonInstance.Start(initialCommand, new PSRemotingCryptoHelperServer(), workingDirectory); - } - - #endregion - } - - internal sealed class SSHProcessMediator : OutOfProcessMediatorBase - { - #region Private Data - - private static SSHProcessMediator s_singletonInstance; - - #endregion - - #region Constructors - - private SSHProcessMediator() : base(true) - { -#if !UNIX - var inputHandle = PlatformInvokes.GetStdHandle((uint)PlatformInvokes.StandardHandleId.Input); - originalStdIn = new StreamReader( - new FileStream(new SafeFileHandle(inputHandle, false), FileAccess.Read)); - - var outputHandle = PlatformInvokes.GetStdHandle((uint)PlatformInvokes.StandardHandleId.Output); - originalStdOut = new OutOfProcessTextWriter( - new StreamWriter( - new FileStream(new SafeFileHandle(outputHandle, false), FileAccess.Write))); - - var errorHandle = PlatformInvokes.GetStdHandle((uint)PlatformInvokes.StandardHandleId.Error); - originalStdErr = new OutOfProcessTextWriter( - new StreamWriter( - new FileStream(new SafeFileHandle(errorHandle, false), FileAccess.Write))); -#else - originalStdIn = new StreamReader(Console.OpenStandardInput(), true); - originalStdOut = new OutOfProcessTextWriter( - new StreamWriter(Console.OpenStandardOutput())); - originalStdErr = new OutOfProcessTextWriter( - new StreamWriter(Console.OpenStandardError())); -#endif - } - - #endregion - - #region Static Methods - - /// - /// - /// - internal static void Run(string initialCommand) + /// Specifies an optional configuration name that configures the endpoint session. + internal static void Run( + string initialCommand, + string workingDirectory, + string configurationName) { lock (SyncObject) { @@ -565,10 +477,14 @@ internal static void Run(string initialCommand) return; } - s_singletonInstance = new SSHProcessMediator(); + s_singletonInstance = new StdIOProcessMediator(); } - s_singletonInstance.Start(initialCommand, new PSRemotingCryptoHelperServer()); + s_singletonInstance.Start( + initialCommand: initialCommand, + cryptoHelper: new PSRemotingCryptoHelperServer(), + workingDirectory: workingDirectory, + configurationName: configurationName); } #endregion @@ -637,11 +553,11 @@ internal static void Run( s_singletonInstance = new NamedPipeProcessMediator(namedPipeServer); } -#if !CORECLR - // AppDomain is not available in CoreCLR - AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException); -#endif - s_singletonInstance.Start(initialCommand, new PSRemotingCryptoHelperServer(), namedPipeServer.ConfigurationName); + s_singletonInstance.Start( + initialCommand: initialCommand, + cryptoHelper: new PSRemotingCryptoHelperServer(), + workingDirectory: null, + configurationName: namedPipeServer.ConfigurationName); } #endregion @@ -727,12 +643,11 @@ internal static void Run( s_instance = new HyperVSocketMediator(); } -#if !CORECLR - // AppDomain is not available in CoreCLR - AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException); -#endif - - s_instance.Start(initialCommand, new PSRemotingCryptoHelperServer(), configurationName); + s_instance.Start( + initialCommand: initialCommand, + cryptoHelper: new PSRemotingCryptoHelperServer(), + workingDirectory: null, + configurationName: configurationName); } #endregion diff --git a/src/System.Management.Automation/engine/remoting/server/ServerMethodExecutor.cs b/src/System.Management.Automation/engine/remoting/server/ServerMethodExecutor.cs index 0c0fb0a0c42..d98239c3c33 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerMethodExecutor.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerMethodExecutor.cs @@ -21,27 +21,27 @@ internal class ServerMethodExecutor /// /// Client runspace pool id. /// - private Guid _clientRunspacePoolId; + private readonly Guid _clientRunspacePoolId; /// /// Client power shell id. /// - private Guid _clientPowerShellId; + private readonly Guid _clientPowerShellId; /// /// Server dispatch table. /// - private ServerDispatchTable _serverDispatchTable; + private readonly ServerDispatchTable _serverDispatchTable; /// /// Remote host call data type. /// - private RemotingDataType _remoteHostCallDataType; + private readonly RemotingDataType _remoteHostCallDataType; /// /// Transport manager. /// - private AbstractServerTransportManager _transportManager; + private readonly AbstractServerTransportManager _transportManager; /// /// Constructor for ServerMethodExecutor. @@ -92,7 +92,7 @@ internal void ExecuteVoidMethod(RemoteHostMethodId methodId, object[] parameters Dbg.Assert(parameters != null, "Expected parameters != null"); // Use void call ID so that the call is known to not have a return value. - long callId = ServerDispatchTable.VoidCallId; + const long callId = ServerDispatchTable.VoidCallId; RemoteHostCall remoteHostCall = new RemoteHostCall(callId, methodId, parameters); // Dispatch the call but don't wait for response since the return value is void. diff --git a/src/System.Management.Automation/engine/remoting/server/ServerPowerShellDriver.cs b/src/System.Management.Automation/engine/remoting/server/ServerPowerShellDriver.cs index e52cffd5ce0..6a49d6f3a4a 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerPowerShellDriver.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerPowerShellDriver.cs @@ -23,31 +23,31 @@ internal class ServerPowerShellDriver private bool _extraPowerShellAlreadyScheduled; // extra PowerShell at the server to be run after localPowerShell - private PowerShell _extraPowerShell; + private readonly PowerShell _extraPowerShell; // output buffer for the local PowerShell that is associated with this powershell driver // associated with this powershell data structure handler object to handle all communications with the client - private PSDataCollection _localPowerShellOutput; + private readonly PSDataCollection _localPowerShellOutput; // if the remaining data has been sent to the client before sending state information - private bool[] _datasent = new bool[2]; + private readonly bool[] _datasent = new bool[2]; // sync object for synchronizing sending data to client - private object _syncObject = new object(); + private readonly object _syncObject = new object(); // there is no input when this driver was created - private bool _noInput; - private bool _addToHistory; + private readonly bool _noInput; + private readonly bool _addToHistory; // the server remote host instance // associated with this powershell - private ServerRemoteHost _remoteHost; + private readonly ServerRemoteHost _remoteHost; // apartment state for this powershell - private ApartmentState apartmentState; + private readonly ApartmentState apartmentState; // Handles nested invocation of PS drivers. - private IRSPDriverInvoke _psDriverInvoker; + private readonly IRSPDriverInvoke _psDriverInvoker; #endregion Private Members diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHost.cs b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHost.cs index 921f9f456f1..ca7ff805c02 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHost.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHost.cs @@ -20,22 +20,22 @@ internal class ServerRemoteHost : PSHost, IHostSupportsInteractiveSession /// /// Remote host user interface. /// - private ServerRemoteHostUserInterface _remoteHostUserInterface; + private readonly ServerRemoteHostUserInterface _remoteHostUserInterface; /// /// Server method executor. /// - private ServerMethodExecutor _serverMethodExecutor; + private readonly ServerMethodExecutor _serverMethodExecutor; /// /// Client runspace pool id. /// - private Guid _clientRunspacePoolId; + private readonly Guid _clientRunspacePoolId; /// /// Client power shell id. /// - private Guid _clientPowerShellId; + private readonly Guid _clientPowerShellId; /// /// Transport manager. @@ -45,7 +45,7 @@ internal class ServerRemoteHost : PSHost, IHostSupportsInteractiveSession /// /// ServerDriverRemoteHost. /// - private ServerDriverRemoteHost _serverDriverRemoteHost; + private readonly ServerDriverRemoteHost _serverDriverRemoteHost; #endregion @@ -327,16 +327,15 @@ public override void PushRunspace(Runspace runspace) throw new PSInvalidOperationException(RemotingErrorIdStrings.ServerDriverRemoteHostAlreadyPushed); } - RemoteRunspace remoteRunspace = runspace as RemoteRunspace; - if (remoteRunspace == null) + if (!(runspace is RemoteRunspace remoteRunspace)) { throw new PSInvalidOperationException(RemotingErrorIdStrings.ServerDriverRemoteHostNotRemoteRunspace); } // PSEdit support. Existence of RemoteSessionOpenFileEvent event indicates host supports PSEdit _hostSupportsPSEdit = false; - PSEventManager localEventManager = (Runspace != null) ? Runspace.Events : null; - _hostSupportsPSEdit = (localEventManager != null) ? localEventManager.GetEventSubscribers(HostUtilities.RemoteSessionOpenFileEvent).GetEnumerator().MoveNext() : false; + PSEventManager localEventManager = Runspace?.Events; + _hostSupportsPSEdit = localEventManager != null && localEventManager.GetEventSubscribers(HostUtilities.RemoteSessionOpenFileEvent).GetEnumerator().MoveNext(); if (_hostSupportsPSEdit) { AddPSEditForRunspace(remoteRunspace); diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostRawUserInterface.cs b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostRawUserInterface.cs index 1a709b11246..05448d02d9b 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostRawUserInterface.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostRawUserInterface.cs @@ -17,12 +17,12 @@ internal class ServerRemoteHostRawUserInterface : PSHostRawUserInterface /// /// Remote host user interface. /// - private ServerRemoteHostUserInterface _remoteHostUserInterface; + private readonly ServerRemoteHostUserInterface _remoteHostUserInterface; /// /// Server method executor. /// - private ServerMethodExecutor _serverMethodExecutor; + private readonly ServerMethodExecutor _serverMethodExecutor; /// /// Host default data. diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostUserInterface.cs b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostUserInterface.cs index 89a5ef97569..314fc25587f 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostUserInterface.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRemoteHostUserInterface.cs @@ -20,7 +20,7 @@ internal class ServerRemoteHostUserInterface : PSHostUserInterface, IHostUISuppo /// /// Server method executor. /// - private ServerMethodExecutor _serverMethodExecutor; + private readonly ServerMethodExecutor _serverMethodExecutor; /// /// Constructor for ServerRemoteHostUserInterface. diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRemotingProtocol2.cs b/src/System.Management.Automation/engine/remoting/server/ServerRemotingProtocol2.cs index 72e7db24ae5..f87f89b5bac 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRemotingProtocol2.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRemotingProtocol2.cs @@ -409,17 +409,18 @@ private void HandleRemoveAssociation(object sender, EventArgs e) #region Private Members - private Guid _clientRunspacePoolId; + private readonly Guid _clientRunspacePoolId; // transport manager using which this // runspace pool driver handles all client // communication - private AbstractServerSessionTransportManager _transportManager; + private readonly AbstractServerSessionTransportManager _transportManager; - private Dictionary _associatedShells + private readonly Dictionary _associatedShells = new Dictionary(); + // powershell data structure handlers associated with this // runspace pool data structure handler - private object _associationSyncObject = new object(); + private readonly object _associationSyncObject = new object(); // object to synchronize operations to above #endregion Private Members @@ -435,10 +436,10 @@ internal class ServerPowerShellDataStructureHandler // transport manager using which this // powershell driver handles all client // communication - private AbstractServerTransportManager _transportManager; - private Guid _clientRunspacePoolId; - private Guid _clientPowerShellId; - private RemoteStreamOptions _streamSerializationOptions; + private readonly AbstractServerTransportManager _transportManager; + private readonly Guid _clientRunspacePoolId; + private readonly Guid _clientPowerShellId; + private readonly RemoteStreamOptions _streamSerializationOptions; private Runspace _rsUsedToInvokePowerShell; #endregion Private Members diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs b/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs index 486383ec4dc..69866f2d4ee 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs @@ -28,12 +28,16 @@ namespace System.Management.Automation /// Interface exposing driver single thread invoke enter/exit /// nested pipeline. /// +#nullable enable internal interface IRSPDriverInvoke { void EnterNestedPipeline(); + void ExitNestedPipeline(); + bool HandleStopSignal(); } +#nullable restore /// /// This class wraps a RunspacePoolInternal object. It is used to function @@ -49,7 +53,7 @@ internal class ServerRunspacePoolDriver : IRSPDriverInvoke private readonly string _initialLocation; // Script to run after a RunspacePool/Runspace is created in this session. - private ConfigurationDataFromXML _configData; + private readonly ConfigurationDataFromXML _configData; // application private data to send back to the client in when we get into "opened" state private PSPrimitiveDictionary _applicationPrivateData; @@ -61,35 +65,35 @@ internal class ServerRunspacePoolDriver : IRSPDriverInvoke // with the client // powershell's associated with this runspace pool - private Dictionary _associatedShells + private readonly Dictionary _associatedShells = new Dictionary(); // remote host associated with this runspacepool - private ServerDriverRemoteHost _remoteHost; + private readonly ServerDriverRemoteHost _remoteHost; private bool _isClosed; // server capability reported to the client during negotiation (not the actual capability) - private RemoteSessionCapability _serverCapability; + private readonly RemoteSessionCapability _serverCapability; private Runspace _rsToUseForSteppablePipeline; // steppable pipeline event subscribers exist per-session - private ServerSteppablePipelineSubscriber _eventSubscriber = new ServerSteppablePipelineSubscriber(); + private readonly ServerSteppablePipelineSubscriber _eventSubscriber = new ServerSteppablePipelineSubscriber(); private PSDataCollection _inputCollection; // PowerShell driver input collection // Object to invoke nested PowerShell drivers on single pipeline worker thread. - private PowerShellDriverInvoker _driverNestedInvoker; + private readonly PowerShellDriverInvoker _driverNestedInvoker; // Remote wrapper for script debugger. private ServerRemoteDebugger _serverRemoteDebugger; // Version of PowerShell client. - private Version _clientPSVersion; + private readonly Version _clientPSVersion; // Optional endpoint configuration name. // Used in OutOfProc scenarios that do not support PSSession endpoint configuration. // Results in a configured remote runspace pushed onto driver host. - private string _configurationName; + private readonly string _configurationName; /// /// Event that get raised when the RunspacePool is closed. @@ -164,7 +168,7 @@ internal ServerRunspacePoolDriver( // The default server settings is to make new commands execute in the calling thread...this saves // thread switching time and thread pool pressure on the service. // Users can override the server settings only if they are administrators - PSThreadOptions serverThreadOptions = configData.ShellThreadOptions.HasValue ? configData.ShellThreadOptions.Value : PSThreadOptions.UseCurrentThread; + PSThreadOptions serverThreadOptions = configData.ShellThreadOptions ?? PSThreadOptions.UseCurrentThread; if (threadOptions == PSThreadOptions.Default || threadOptions == serverThreadOptions) { RunspacePool.ThreadOptions = serverThreadOptions; @@ -180,7 +184,7 @@ internal ServerRunspacePoolDriver( } // Set Thread ApartmentState for this RunspacePool - ApartmentState serverApartmentState = configData.ShellThreadApartmentState.HasValue ? configData.ShellThreadApartmentState.Value : Runspace.DefaultApartmentState; + ApartmentState serverApartmentState = configData.ShellThreadApartmentState ?? Runspace.DefaultApartmentState; if (apartmentState == ApartmentState.Unknown || apartmentState == serverApartmentState) { @@ -557,7 +561,7 @@ private PSDataCollection InvokePowerShell(PowerShell powershell, Runsp Exception lastException = errorList[0] as Exception; if (lastException != null) { - exceptionThrown = (lastException.Message != null) ? lastException.Message : string.Empty; + exceptionThrown = lastException.Message ?? string.Empty; } else { @@ -831,7 +835,7 @@ private void HandleCreateAndInvokePowerShell(object _, RemoteDataEventArgs publicGetCommandEntries = iss .Commands["Get-Command"] - .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); + .Where(static entry => entry.Visibility == SessionStateEntryVisibility.Public); SessionStateFunctionEntry getCommandProxy = publicGetCommandEntries.OfType().FirstOrDefault(); if (getCommandProxy != null) { @@ -1246,9 +1250,9 @@ private enum PreProcessCommandResult /// The PreProcessCommandResult used for managing breakpoints. /// BreakpointManagement, - }; + } - private class DebuggerCommandArgument + private sealed class DebuggerCommandArgument { public DebugModes? Mode { get; set; } @@ -1484,9 +1488,7 @@ private static PreProcessCommandResult PreProcessDebuggerCommand( Breakpoint breakpoint = serverRemoteDebugger.GetBreakpoint(breakpointId, runspaceId); preProcessOutput.Add( - breakpoint == null - ? false - : serverRemoteDebugger.RemoveBreakpoint(breakpoint, runspaceId)); + breakpoint != null && serverRemoteDebugger.RemoveBreakpoint(breakpoint, runspaceId)); result = PreProcessCommandResult.BreakpointManagement; } @@ -1587,7 +1589,7 @@ private sealed class PowerShellDriverInvoker { #region Private Members - private ConcurrentStack _invokePumpStack; + private readonly ConcurrentStack _invokePumpStack; #endregion @@ -1626,7 +1628,7 @@ public bool IsAvailable pump = null; } - return (pump != null) ? !(pump.IsBusy) : false; + return (pump != null) && !(pump.IsBusy); } } @@ -1690,9 +1692,9 @@ public void PopInvoker() /// private sealed class InvokePump { - private Queue _driverInvokeQueue; - private ManualResetEvent _processDrivers; - private object _syncObject; + private readonly Queue _driverInvokeQueue; + private readonly ManualResetEvent _processDrivers; + private readonly object _syncObject; private bool _stopPump; private bool _isDisposed; @@ -1802,9 +1804,9 @@ internal sealed class ServerRemoteDebugger : Debugger, IDisposable { #region Private Members - private IRSPDriverInvoke _driverInvoker; - private Runspace _runspace; - private ObjectRef _wrappedDebugger; + private readonly IRSPDriverInvoke _driverInvoker; + private readonly Runspace _runspace; + private readonly ObjectRef _wrappedDebugger; private bool _inDebugMode; private DebuggerStopEventArgs _debuggerStopEventArgs; @@ -2064,7 +2066,7 @@ public override bool IsActive public override void SetDebuggerStepMode(bool enabled) { // Enable both the wrapper and wrapped debuggers for debugging before setting step mode. - DebugModes mode = DebugModes.LocalScript | DebugModes.RemoteScript; + const DebugModes mode = DebugModes.LocalScript | DebugModes.RemoteScript; base.SetDebugMode(mode); _wrappedDebugger.Value.SetDebugMode(mode); @@ -2248,10 +2250,10 @@ public void Dispose() private sealed class ThreadCommandProcessing { // Members - private ManualResetEventSlim _commandCompleteEvent; - private Debugger _wrappedDebugger; - private PSCommand _command; - private PSDataCollection _output; + private readonly ManualResetEventSlim _commandCompleteEvent; + private readonly Debugger _wrappedDebugger; + private readonly PSCommand _command; + private readonly PSDataCollection _output; private DebuggerCommandResults _results; private Exception _exception; #if !UNIX @@ -2710,7 +2712,7 @@ internal void StartPowerShellCommand( powershell.InvocationStateChanged += HandlePowerShellInvocationStateChanged; powershell.SetIsNested(false); - string script = @" + const string script = @" param ($Debugger, $Commands, $output) trap { throw $_ } diff --git a/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineDriver.cs b/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineDriver.cs index 240395bb567..57df27e2d4b 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineDriver.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineDriver.cs @@ -14,9 +14,9 @@ namespace System.Management.Automation /// /// Execution context used for stepping. /// - internal class ExecutionContextForStepping : IDisposable + internal sealed class ExecutionContextForStepping : IDisposable { - private ExecutionContext _executionContext; + private readonly ExecutionContext _executionContext; private PSInformationalBuffers _originalInformationalBuffers; private PSHost _originalHost; @@ -72,13 +72,13 @@ internal class ServerSteppablePipelineDriver // information // data to client // was created - private bool _addToHistory; + private readonly bool _addToHistory; // associated with this powershell - private ApartmentState apartmentState; // apartment state for this powershell + private readonly ApartmentState apartmentState; // apartment state for this powershell // pipeline that runs the actual command. - private ServerSteppablePipelineSubscriber _eventSubscriber; - private PSDataCollection _powershellInput; // input collection of the PowerShell pipeline + private readonly ServerSteppablePipelineSubscriber _eventSubscriber; + private readonly PSDataCollection _powershellInput; // input collection of the PowerShell pipeline #endregion diff --git a/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineSubscriber.cs b/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineSubscriber.cs index 850993cf162..328571647cb 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineSubscriber.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerSteppablePipelineSubscriber.cs @@ -29,7 +29,7 @@ internal class ServerSteppablePipelineSubscriber { #region Private data - private object _syncObject = new object(); + private readonly object _syncObject = new object(); private bool _initialized = false; private PSLocalEventManager _eventManager; private PSEventSubscriber _startSubscriber; @@ -62,6 +62,7 @@ internal void SubscribeEvents(ServerSteppablePipelineDriver driver) #region Events and Handlers public event EventHandler StartSteppablePipeline; + public event EventHandler RunProcessRecord; /// diff --git a/src/System.Management.Automation/engine/remoting/server/WSManChannelEvents.cs b/src/System.Management.Automation/engine/remoting/server/WSManChannelEvents.cs index 3b1174f0fff..9fbcb9e0cf9 100644 --- a/src/System.Management.Automation/engine/remoting/server/WSManChannelEvents.cs +++ b/src/System.Management.Automation/engine/remoting/server/WSManChannelEvents.cs @@ -30,11 +30,7 @@ public static class WSManServerChannelEvents /// internal static void RaiseShuttingDownEvent() { - EventHandler handler = ShuttingDown; - if (handler != null) - { - handler(null, EventArgs.Empty); - } + ShuttingDown?.Invoke(null, EventArgs.Empty); } /// @@ -42,11 +38,7 @@ internal static void RaiseShuttingDownEvent() /// internal static void RaiseActiveSessionsChangedEvent(ActiveSessionsChangedEventArgs eventArgs) { - EventHandler handler = ActiveSessionsChanged; - if (handler != null) - { - handler(null, eventArgs); - } + ActiveSessionsChanged?.Invoke(null, eventArgs); } #endregion internal members diff --git a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs index 16978ff04e3..7b08c674301 100644 --- a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs +++ b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs @@ -70,11 +70,11 @@ internal ServerRemoteSessionContext() internal class ServerRemoteSession : RemoteSession { [TraceSourceAttribute("ServerRemoteSession", "ServerRemoteSession")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("ServerRemoteSession", "ServerRemoteSession"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("ServerRemoteSession", "ServerRemoteSession"); - private PSSenderInfo _senderInfo; - private string _configProviderId; - private string _initParameters; + private readonly PSSenderInfo _senderInfo; + private readonly string _configProviderId; + private readonly string _initParameters; private string _initScriptForOutOfProcRS; private PSSessionConfiguration _sessionConfigProvider; @@ -83,7 +83,7 @@ internal class ServerRemoteSession : RemoteSession private int? _maxRecvdDataSizeCommand; private ServerRunspacePoolDriver _runspacePoolDriver; - private PSRemotingCryptoHelperServer _cryptoHelper; + private readonly PSRemotingCryptoHelperServer _cryptoHelper; // Specifies an optional endpoint configuration for out-of-proc session use. // Creates a pushed remote runspace session created with this configuration name. @@ -206,7 +206,7 @@ internal static ServerRemoteSession CreateServerRemoteSession( throw PSTraceSource.NewInvalidOperationException("RemotingErrorIdStrings.NonExistentInitialSessionStateProvider", configurationProviderId); } - string shellPrefix = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix; + const string shellPrefix = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix; int index = configurationProviderId.IndexOf(shellPrefix, StringComparison.OrdinalIgnoreCase); senderInfo.ConfigurationName = (index == 0) ? configurationProviderId.Substring(shellPrefix.Length) : string.Empty; ServerRemoteSession result = new ServerRemoteSession( @@ -285,10 +285,10 @@ internal override RemotingDestination MySelf /// This parameter contains the remote data received from client. /// /// - /// If the parameter is null. + /// If the parameter is null. /// /// - /// If the parameter does not contain remote data. + /// If the parameter does not contain remote data. /// /// /// If the destination of the data is not for server. @@ -696,7 +696,7 @@ internal void ExecuteConnect(byte[] connectData, out byte[] connectResponseData) // as this is executed only when connecting from a new client that does not have any previous fragments context. // no problem even if fragment Ids in this response and the sessiontransport stream clash (interfere) and its guaranteed // that the fragments in connect response are always complete (enclose a complete object). - SerializedDataStream stream = new SerializedDataStream(4 * 1024);//Each message with fragment headers cannot cross 4k + SerializedDataStream stream = new SerializedDataStream(4 * 1024); //Each message with fragment headers cannot cross 4k stream.Enter(); capability.Serialize(stream, fragmentor); stream.Exit(); @@ -712,7 +712,7 @@ internal void ExecuteConnect(byte[] connectData, out byte[] connectResponseData) // enqueue a connect event in state machine to let session do any other post-connect operation // Do this outside of the synchronous connect operation, as otherwise connect can easily get deadlocked ThreadPool.QueueUserWorkItem(new WaitCallback( - delegate (object state) + (object state) => { RemoteSessionStateMachineEventArgs startEventArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ConnectSession); SessionDataStructureHandler.StateMachine.RaiseEvent(startEventArg); diff --git a/src/System.Management.Automation/engine/remoting/server/serverremotesessionstatemachine.cs b/src/System.Management.Automation/engine/remoting/server/serverremotesessionstatemachine.cs index 9a77d2a86bd..732e5a836ab 100644 --- a/src/System.Management.Automation/engine/remoting/server/serverremotesessionstatemachine.cs +++ b/src/System.Management.Automation/engine/remoting/server/serverremotesessionstatemachine.cs @@ -32,13 +32,14 @@ namespace System.Management.Automation.Remoting internal class ServerRemoteSessionDSHandlerStateMachine { [TraceSourceAttribute("ServerRemoteSessionDSHandlerStateMachine", "ServerRemoteSessionDSHandlerStateMachine")] - private static PSTraceSource s_trace = PSTraceSource.GetTracer("ServerRemoteSessionDSHandlerStateMachine", "ServerRemoteSessionDSHandlerStateMachine"); + private static readonly PSTraceSource s_trace = PSTraceSource.GetTracer("ServerRemoteSessionDSHandlerStateMachine", "ServerRemoteSessionDSHandlerStateMachine"); - private ServerRemoteSession _session; - private object _syncObject; + private readonly ServerRemoteSession _session; + private readonly object _syncObject; - private Queue _processPendingEventsQueue + private readonly Queue _processPendingEventsQueue = new Queue(); + // whether some thread is actively processing events // in a loop. If this is set then other threads // should simply add to the queue and not attempt @@ -47,7 +48,7 @@ private Queue _processPendingEventsQueue // and processed private bool _eventsInProcess = false; - private EventHandler[,] _stateMachineHandle; + private readonly EventHandler[,] _stateMachineHandle; private RemoteSessionState _state; /// @@ -1001,7 +1002,7 @@ private void HandleKeyExchangeTimeout(object sender) /// It can also be used for graceful shutdown of the server process, which is not currently /// implemented. /// - private void CleanAll() + private static void CleanAll() { } diff --git a/src/System.Management.Automation/engine/remoting/server/serverremotingprotocolimplementation.cs b/src/System.Management.Automation/engine/remoting/server/serverremotingprotocolimplementation.cs index 1e72be279c7..06fbca348cc 100644 --- a/src/System.Management.Automation/engine/remoting/server/serverremotingprotocolimplementation.cs +++ b/src/System.Management.Automation/engine/remoting/server/serverremotingprotocolimplementation.cs @@ -12,9 +12,9 @@ namespace System.Management.Automation.Remoting /// internal class ServerRemoteSessionDSHandlerImpl : ServerRemoteSessionDataStructureHandler { - private AbstractServerSessionTransportManager _transportManager; - private ServerRemoteSessionDSHandlerStateMachine _stateMachine; - private ServerRemoteSession _session; + private readonly AbstractServerSessionTransportManager _transportManager; + private readonly ServerRemoteSessionDSHandlerStateMachine _stateMachine; + private readonly ServerRemoteSession _session; internal override AbstractServerSessionTransportManager TransportManager { @@ -242,4 +242,3 @@ internal override void RaiseDataReceivedEvent(RemoteDataEventArgs dataArg) #endregion Overrides } } - diff --git a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs index 70790906e8a..a4917d5af6b 100644 --- a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs +++ b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs @@ -444,7 +444,7 @@ internal static DynamicMetaObject UpdateComRestrictionsForPsObject(this DynamicM } } - internal class BinderUtils + internal static class BinderUtils { internal static BindingRestrictions GetVersionCheck(DynamicMetaObjectBinder binder, int expectedVersionNumber) { @@ -513,7 +513,7 @@ internal static BindingRestrictions GetOptionalVersionAndLanguageCheckForType(Dy /// The standard interop ConvertBinder is used to allow third party dynamic objects to get the first chance /// at the conversion in case they do support enumeration, but do not implement IEnumerable directly. /// - internal class PSEnumerableBinder : ConvertBinder + internal sealed class PSEnumerableBinder : ConvertBinder { private static readonly PSEnumerableBinder s_binder = new PSEnumerableBinder(); @@ -550,7 +550,7 @@ private DynamicMetaObject NullResult(DynamicMetaObject target) // The object is not enumerable from PowerShell's perspective. Rather than raise an exception, we let the // caller check for null and take the appropriate action. return new DynamicMetaObject( - MaybeDebase(this, e => ExpressionCache.NullEnumerator, target), + MaybeDebase(this, static e => ExpressionCache.NullEnumerator, target), GetRestrictions(target)); } @@ -599,7 +599,7 @@ public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, Dyna if (targetValue.GetType().IsArray) { return (new DynamicMetaObject( - MaybeDebase(this, e => Expression.Call(Expression.Convert(e, typeof(Array)), typeof(Array).GetMethod("GetEnumerator")), + MaybeDebase(this, static e => Expression.Call(Expression.Convert(e, typeof(Array)), typeof(Array).GetMethod("GetEnumerator")), target), GetRestrictions(target))).WriteToDebugLog(this); } @@ -674,7 +674,7 @@ public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, Dyna } return (new DynamicMetaObject( - MaybeDebase(this, e => Expression.Call(CachedReflectionInfo.EnumerableOps_GetEnumerator, Expression.Convert(e, typeof(IEnumerable))), + MaybeDebase(this, static e => Expression.Call(CachedReflectionInfo.EnumerableOps_GetEnumerator, Expression.Convert(e, typeof(IEnumerable))), target), GetRestrictions(target))).WriteToDebugLog(this); } @@ -683,7 +683,7 @@ public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, Dyna if (enumerator != null) { return (new DynamicMetaObject( - MaybeDebase(this, e => e.Cast(typeof(IEnumerator)), target), + MaybeDebase(this, static e => e.Cast(typeof(IEnumerator)), target), GetRestrictions(target))).WriteToDebugLog(this); } @@ -737,7 +737,11 @@ private static IEnumerator NotEnumerableRule(CallSite site, object obj) return null; } - if (!(obj is PSObject) && !(obj is IEnumerable) && !(obj is IEnumerator) && !(obj is DataTable) && !Marshal.IsComObject(obj)) + if (obj is not PSObject + && obj is not IEnumerable + && obj is not IEnumerator + && obj is not DataTable + && !Marshal.IsComObject(obj)) { return null; } @@ -776,7 +780,7 @@ private static IEnumerator PSObjectStringRule(CallSite site, object obj) /// /// This binder is used for the @() operator. /// - internal class PSToObjectArrayBinder : DynamicMetaObjectBinder + internal sealed class PSToObjectArrayBinder : DynamicMetaObjectBinder { private static readonly PSToObjectArrayBinder s_binder = new PSToObjectArrayBinder(); @@ -821,7 +825,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje if (value is List) { return new DynamicMetaObject( - Expression.Call(PSEnumerableBinder.MaybeDebase(this, e => e.Cast(typeof(List)), target), CachedReflectionInfo.ObjectList_ToArray), + Expression.Call(PSEnumerableBinder.MaybeDebase(this, static e => e.Cast(typeof(List)), target), CachedReflectionInfo.ObjectList_ToArray), PSEnumerableBinder.GetRestrictions(target)).WriteToDebugLog(this); } @@ -832,7 +836,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje } } - internal class PSPipeWriterBinder : DynamicMetaObjectBinder + internal sealed class PSPipeWriterBinder : DynamicMetaObjectBinder { private static readonly PSPipeWriterBinder s_binder = new PSPipeWriterBinder(); @@ -885,7 +889,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje restrictions)).WriteToDebugLog(this); } - bool needsToDispose = !(PSObject.Base(target.Value) is IEnumerator); + bool needsToDispose = PSObject.Base(target.Value) is not IEnumerator; return (new DynamicMetaObject( Expression.Call(CachedReflectionInfo.EnumerableOps_WriteEnumerableToPipe, enumerable.Expression, @@ -926,7 +930,7 @@ private static void AutomationNullRule(CallSite site, object obj, Pipe pipe, Exe /// The target in this binder is the RHS, the result expression is an IList where the Count matches the /// number of values assigned (_elements) on the left hand side of the assign. /// - internal class PSArrayAssignmentRHSBinder : DynamicMetaObjectBinder + internal sealed class PSArrayAssignmentRHSBinder : DynamicMetaObjectBinder { private static readonly List s_binders = new List(); private readonly int _elements; @@ -1045,7 +1049,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje /// case, the format string is generated by the parser, so we know that there is no custom /// formatting to consider. /// - internal class PSToStringBinder : DynamicMetaObjectBinder + internal sealed class PSToStringBinder : DynamicMetaObjectBinder { private static readonly PSToStringBinder s_binder = new PSToStringBinder(); @@ -1110,7 +1114,7 @@ internal static Expression InvokeToString(Expression context, Expression target) /// /// This binder is used to optimize the conversion of the result. /// - internal class PSPipelineResultToBoolBinder : DynamicMetaObjectBinder + internal sealed class PSPipelineResultToBoolBinder : DynamicMetaObjectBinder { private static readonly PSPipelineResultToBoolBinder s_binder = new PSPipelineResultToBoolBinder(); @@ -1171,9 +1175,9 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje } } - internal class PSInvokeDynamicMemberBinder : DynamicMetaObjectBinder + internal sealed class PSInvokeDynamicMemberBinder : DynamicMetaObjectBinder { - private class KeyComparer : IEqualityComparer + private sealed class KeyComparer : IEqualityComparer { public bool Equals(PSInvokeDynamicMemberBinderKeyType x, PSInvokeDynamicMemberBinderKeyType y) { @@ -1198,7 +1202,7 @@ internal static PSInvokeDynamicMemberBinder Get(CallInfo callInfo, TypeDefinitio { PSInvokeDynamicMemberBinder result; - var classScope = classScopeAst != null ? classScopeAst.Type : null; + var classScope = classScopeAst?.Type; lock (s_binderCache) { var key = Tuple.Create(callInfo, constraints, propertySetter, @static, classScope); @@ -1282,7 +1286,7 @@ public int GetHashCode(PSGetOrSetDynamicMemberBinderKeyType obj) } } - internal class PSGetDynamicMemberBinder : DynamicMetaObjectBinder + internal sealed class PSGetDynamicMemberBinder : DynamicMetaObjectBinder { private static readonly Dictionary s_binderCache = new Dictionary(new PSDynamicGetOrSetBinderKeyComparer()); @@ -1292,7 +1296,7 @@ internal static PSGetDynamicMemberBinder Get(TypeDefinitionAst classScope, bool PSGetDynamicMemberBinder binder; lock (s_binderCache) { - var type = classScope != null ? classScope.Type : null; + var type = classScope?.Type; var tuple = Tuple.Create(type, @static); if (!s_binderCache.TryGetValue(tuple, out binder)) { @@ -1392,7 +1396,7 @@ internal static object GetIDictionaryMember(IDictionary hash, object key) } } - internal class PSSetDynamicMemberBinder : DynamicMetaObjectBinder + internal sealed class PSSetDynamicMemberBinder : DynamicMetaObjectBinder { private static readonly Dictionary s_binderCache = new Dictionary(new PSDynamicGetOrSetBinderKeyComparer()); @@ -1402,7 +1406,7 @@ internal static PSSetDynamicMemberBinder Get(TypeDefinitionAst classScope, bool PSSetDynamicMemberBinder binder; lock (s_binderCache) { - var type = classScope != null ? classScope.Type : null; + var type = classScope?.Type; var tuple = Tuple.Create(type, @static); if (!s_binderCache.TryGetValue(tuple, out binder)) { @@ -1484,7 +1488,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje } } - internal class PSSwitchClauseEvalBinder : DynamicMetaObjectBinder + internal sealed class PSSwitchClauseEvalBinder : DynamicMetaObjectBinder { // Increase this cache size if we add a new flag to the switch statement that: // - Influences evaluation of switch elements @@ -1604,7 +1608,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje // This class implements the standard binder CreateInstanceBinder, but this binder handles the CallInfo a little differently. // The ArgumentNames are not used to invoke a constructor, instead they are used to set properties/fields in the attribute. - internal class PSAttributeGenerator : CreateInstanceBinder + internal sealed class PSAttributeGenerator : CreateInstanceBinder { private static readonly Dictionary s_binderCache = new Dictionary(); @@ -1649,7 +1653,7 @@ public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject targe newConstructors, invocationConstraints: null, allowCastingToByRefLikeType: false, - args.Take(positionalArgCount).Select(arg => arg.Value).ToArray(), + args.Take(positionalArgCount).Select(static arg => arg.Value).ToArray(), ref errorId, ref errorMsg, out expandParamsOnBest, @@ -1722,7 +1726,8 @@ public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject targe { var members = attributeType.GetMember(name, MemberTypes.Field | MemberTypes.Property, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - if (members.Length != 1 || !(members[0] is PropertyInfo || members[0] is FieldInfo)) + if (members.Length != 1 + || (members[0] is not PropertyInfo && members[0] is not FieldInfo)) { return target.ThrowRuntimeError(args, BindingRestrictions.Empty, "PropertyNotFoundForType", ParserStrings.PropertyNotFoundForType, Expression.Constant(name), @@ -1784,7 +1789,7 @@ public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject targe } } - internal class PSCustomObjectConverter : DynamicMetaObjectBinder + internal sealed class PSCustomObjectConverter : DynamicMetaObjectBinder { private static readonly PSCustomObjectConverter s_binder = new PSCustomObjectConverter(); @@ -1820,7 +1825,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje } } - internal class PSDynamicConvertBinder : DynamicMetaObjectBinder + internal sealed class PSDynamicConvertBinder : DynamicMetaObjectBinder { private static readonly PSDynamicConvertBinder s_binder = new PSDynamicConvertBinder(); @@ -1858,7 +1863,7 @@ public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObje /// /// This binder is used to copy mutable value types when assigning to variables, otherwise just assigning the target object directly. /// - internal class PSVariableAssignmentBinder : DynamicMetaObjectBinder + internal sealed class PSVariableAssignmentBinder : DynamicMetaObjectBinder { private static readonly PSVariableAssignmentBinder s_binder = new PSVariableAssignmentBinder(); internal static int s_mutableValueWithInstanceMemberVersion; @@ -2011,7 +2016,7 @@ private static object IntRule(CallSite site, object obj) private static object ObjectRule(CallSite site, object obj) { - if (!(obj is ValueType) && !(obj is PSObject)) { return obj; } + if (obj is not ValueType && obj is not PSObject) { return obj; } return ((CallSite>)site).Update(site, obj); } @@ -2030,36 +2035,39 @@ private static object NullRule(CallSite site, object obj) internal static bool IsValueTypeMutable(Type type) { - if (type.IsPrimitive || type.IsEnum) + // First, check for enums/primitives and compiler-defined attributes. + if (type.IsPrimitive + || type.IsEnum + || type.IsDefined(typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute), inherit: false)) { return false; } - // If there are any fields, the type is mutable. - if (type.GetFields(BindingFlags.Public | BindingFlags.Instance).Length > 0) + // If the builtin attribute is not present, check for a custom attribute from by the compiler. If the + // library targets netstandard2.0, the compiler can't be sure the attribute will be provided by the runtime, + // and defines its own attribute of the same name during compilation. To account for this, we must check the + // type by name, not by reference. + foreach (object attribute in type.GetCustomAttributes(inherit: false)) { - return true; + if (attribute.GetType().FullName.Equals( + "System.Runtime.CompilerServices.IsReadOnlyAttribute", + StringComparison.Ordinal)) + { + return false; + } } - // If there are any properties with setters, the type is mutable. - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - for (int index = 0; index < properties.Length; index++) + // Fallback: check all fields (public + private) to verify whether they're all readonly. + // If any field is not readonly, the value type is potentially mutable. + foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { - var property = properties[index]; - if (property.CanWrite) + if (!field.IsInitOnly) { return true; } } - // If there are any methods other than the property getters, the type might - // be mutable, so assume the type is mutable. - var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); - if (methods.Length != properties.Length) - { - return true; - } - + // If all fields are init-only (read-only), then the value type is immutable. return false; } @@ -2108,7 +2116,7 @@ internal static BindingRestrictions GetVersionCheck(int expectedVersionNumber) /// /// The binder for common binary operators. PowerShell specific binary operators are handled elsewhere. /// - internal class PSBinaryOperationBinder : BinaryOperationBinder + internal sealed class PSBinaryOperationBinder : BinaryOperationBinder { #region Constructors and factory methods @@ -3179,7 +3187,7 @@ private DynamicMetaObject CompareLT(DynamicMetaObject target, } return BinaryComparisonCommon(enumerable, target, arg) - ?? BinaryComparison(target, arg, e => Expression.LessThan(e, ExpressionCache.Constant(0))); + ?? BinaryComparison(target, arg, static e => Expression.LessThan(e, ExpressionCache.Constant(0))); } private DynamicMetaObject CompareLE(DynamicMetaObject target, @@ -3199,7 +3207,7 @@ private DynamicMetaObject CompareLE(DynamicMetaObject target, } return BinaryComparisonCommon(enumerable, target, arg) - ?? BinaryComparison(target, arg, e => Expression.LessThanOrEqual(e, ExpressionCache.Constant(0))); + ?? BinaryComparison(target, arg, static e => Expression.LessThanOrEqual(e, ExpressionCache.Constant(0))); } private DynamicMetaObject CompareGT(DynamicMetaObject target, @@ -3221,7 +3229,7 @@ private DynamicMetaObject CompareGT(DynamicMetaObject target, } return BinaryComparisonCommon(enumerable, target, arg) - ?? BinaryComparison(target, arg, e => Expression.GreaterThan(e, ExpressionCache.Constant(0))); + ?? BinaryComparison(target, arg, static e => Expression.GreaterThan(e, ExpressionCache.Constant(0))); } private DynamicMetaObject CompareGE(DynamicMetaObject target, @@ -3243,7 +3251,7 @@ private DynamicMetaObject CompareGE(DynamicMetaObject target, } return BinaryComparisonCommon(enumerable, target, arg) - ?? BinaryComparison(target, arg, e => Expression.GreaterThanOrEqual(e, ExpressionCache.Constant(0))); + ?? BinaryComparison(target, arg, static e => Expression.GreaterThanOrEqual(e, ExpressionCache.Constant(0))); } private DynamicMetaObject BinaryComparison(DynamicMetaObject target, DynamicMetaObject arg, Func toResult) @@ -3403,7 +3411,7 @@ private DynamicMetaObject BinaryComparisonCommon(DynamicMetaObject targetAsEnume /// /// The binder for unary operators like !, -, or +. /// - internal class PSUnaryOperationBinder : UnaryOperationBinder + internal sealed class PSUnaryOperationBinder : UnaryOperationBinder { private static PSUnaryOperationBinder s_notBinder; private static PSUnaryOperationBinder s_bnotBinder; @@ -3719,7 +3727,7 @@ private DynamicMetaObject IncrDecr(DynamicMetaObject target, int valueToAdd, Dyn /// /// The binder for converting a value, e.g. [int]"42" /// - internal class PSConvertBinder : ConvertBinder + internal sealed class PSConvertBinder : ConvertBinder { private static readonly Dictionary s_binderCache = new Dictionary(); internal int _version; @@ -3836,7 +3844,7 @@ internal static Expression ConvertToByRefLikeTypeViaCasting(DynamicMetaObject ar var baseObject = PSObject.Base(argument.Value); // Source value cannot be null or AutomationNull, and it cannot be a pure PSObject. - if (baseObject != null && !(baseObject is PSObject)) + if (baseObject != null && baseObject is not PSObject) { Type fromType = baseObject.GetType(); ConversionRank rank = ConversionRank.None; @@ -3918,7 +3926,7 @@ private static string StringToStringRule(CallSite site, object obj) /// /// The binder to get the value of an indexable object, e.g. $x[1] /// - internal class PSGetIndexBinder : GetIndexBinder + internal sealed class PSGetIndexBinder : GetIndexBinder { private static readonly Dictionary, PSGetIndexBinder> s_binderCache = new Dictionary, PSGetIndexBinder>(); @@ -3975,13 +3983,13 @@ internal static void InvalidateCache() public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { - if (!target.HasValue || indexes.Any(mo => !mo.HasValue)) + if (!target.HasValue || indexes.Any(static mo => !mo.HasValue)) { return Defer(indexes.Prepend(target).ToArray()).WriteToDebugLog(this); } if ((target.Value is PSObject && (PSObject.Base(target.Value) != target.Value)) || - indexes.Any(mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) + indexes.Any(static mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) { return this.DeferForPSObject(indexes.Prepend(target).ToArray()).WriteToDebugLog(this); } @@ -4076,7 +4084,7 @@ private DynamicMetaObject CannotIndexTarget(DynamicMetaObject target, DynamicMet bindingRestrictions = bindingRestrictions.Merge(BinderUtils.GetLanguageModeCheckIfHasEverUsedConstrainedLanguage()); var call = Expression.Call(CachedReflectionInfo.ArrayOps_GetNonIndexable, target.Expression.Cast(typeof(object)), - Expression.NewArrayInit(typeof(object), indexes.Select(d => d.Expression.Cast(typeof(object))))); + Expression.NewArrayInit(typeof(object), indexes.Select(static d => d.Expression.Cast(typeof(object))))); return new DynamicMetaObject(call, bindingRestrictions); } @@ -4259,7 +4267,7 @@ private DynamicMetaObject GetIndexArray(DynamicMetaObject target, DynamicMetaObj new DynamicMetaObject(target.Expression.Cast(target.LimitType), target.PSGetTypeRestriction()), new DynamicMetaObject(indexAsInt, indexes[0].PSGetTypeRestriction()), target.LimitType.GetProperty("Length"), - (t, i) => Expression.ArrayIndex(t, i).Cast(typeof(object))); + static (t, i) => Expression.ArrayIndex(t, i).Cast(typeof(object))); } private DynamicMetaObject GetIndexMultiDimensionArray(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) @@ -4305,7 +4313,7 @@ private DynamicMetaObject GetIndexMultiDimensionArray(DynamicMetaObject target, target.CombineRestrictions(indexes)); } - var intIndexes = indexes.Select(index => ConvertIndex(index, typeof(int))).Where(i => i != null).ToArray(); + var intIndexes = indexes.Select(static index => ConvertIndex(index, typeof(int))).Where(static i => i != null).ToArray(); if (intIndexes.Length != indexes.Length) { if (!_allowSlicing) @@ -4469,7 +4477,7 @@ private DynamicMetaObject InvokeSlicingIndexer(DynamicMetaObject target, Dynamic Expression.Call(CachedReflectionInfo.ArrayOps_SlicingIndex, target.Expression.Cast(typeof(object)), Expression.NewArrayInit(typeof(object), - indexes.Select(dmo => dmo.Expression.Cast(typeof(object)))), + indexes.Select(static dmo => dmo.Expression.Cast(typeof(object)))), Expression.Constant(GetNonSlicingIndexer())), target.CombineRestrictions(indexes)); } @@ -4509,7 +4517,7 @@ private Func GetNonSlicingIndexer() /// /// The binder for setting the value of an indexable element, like $x[1] = 5. /// - internal class PSSetIndexBinder : SetIndexBinder + internal sealed class PSSetIndexBinder : SetIndexBinder { private static readonly Dictionary, PSSetIndexBinder> s_binderCache = new Dictionary, PSSetIndexBinder>(); @@ -4564,13 +4572,13 @@ public override DynamicMetaObject FallbackSetIndex( DynamicMetaObject value, DynamicMetaObject errorSuggestion) { - if (!target.HasValue || indexes.Any(mo => !mo.HasValue) || !value.HasValue) + if (!target.HasValue || indexes.Any(static mo => !mo.HasValue) || !value.HasValue) { return Defer(indexes.Prepend(target).Append(value).ToArray()).WriteToDebugLog(this); } if (target.Value is PSObject && (PSObject.Base(target.Value) != target.Value) || - indexes.Any(mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) + indexes.Any(static mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) { return this.DeferForPSObject(indexes.Prepend(target).Append(value).ToArray()).WriteToDebugLog(this); } @@ -4673,7 +4681,9 @@ private DynamicMetaObject InvokeIndexer( } } - if (paramLength == 2 && setterParams[0].ParameterType == typeof(int) && !(target.Value is IDictionary)) + if (paramLength == 2 + && setterParams[0].ParameterType == typeof(int) + && target.Value is not IDictionary) { // PowerShell supports negative indexing for some types (specifically, those with a single // int parameter to the indexer, and also have either a Length or Count property.) For @@ -4784,7 +4794,7 @@ private DynamicMetaObject SetIndexArray(DynamicMetaObject target, ParserStrings.ArraySliceAssignmentFailed, Expression.Call(CachedReflectionInfo.ArrayOps_IndexStringMessage, Expression.NewArrayInit(typeof(object), - indexes.Select(i => i.Expression.Cast(typeof(object)))))); + indexes.Select(static i => i.Expression.Cast(typeof(object)))))); } var intIndex = PSGetIndexBinder.ConvertIndex(indexes[0], typeof(int)); @@ -4806,7 +4816,7 @@ private DynamicMetaObject SetIndexArray(DynamicMetaObject target, new DynamicMetaObject(target.Expression.Cast(target.LimitType), target.PSGetTypeRestriction()), new DynamicMetaObject(intIndex, indexes[0].PSGetTypeRestriction()), new DynamicMetaObject(valueExpr, value.PSGetTypeRestriction()), target.LimitType.GetProperty("Length"), - (t, i, v) => Expression.Assign(Expression.ArrayAccess(t, i), v)); + static (t, i, v) => Expression.Assign(Expression.ArrayAccess(t, i), v)); } private DynamicMetaObject SetIndexMultiDimensionArray(DynamicMetaObject target, @@ -4849,7 +4859,7 @@ private DynamicMetaObject SetIndexMultiDimensionArray(DynamicMetaObject target, ExpressionCache.Constant(array.Rank), Expression.Call(CachedReflectionInfo.ArrayOps_IndexStringMessage, Expression.NewArrayInit(typeof(object), - indexes.Select(i => i.Expression.Cast(typeof(object)))))); + indexes.Select(static i => i.Expression.Cast(typeof(object)))))); } var indexExprs = new Expression[indexes.Length]; @@ -4877,7 +4887,7 @@ private DynamicMetaObject SetIndexMultiDimensionArray(DynamicMetaObject target, /// internal class PSGetMemberBinder : GetMemberBinder { - private class KeyComparer : IEqualityComparer + private sealed class KeyComparer : IEqualityComparer { public bool Equals(PSGetMemberBinderKeyType x, PSGetMemberBinderKeyType y) { @@ -4901,7 +4911,7 @@ public int GetHashCode(PSGetMemberBinderKeyType obj) } } - private class ReservedMemberBinder : PSGetMemberBinder + private sealed class ReservedMemberBinder : PSGetMemberBinder { internal ReservedMemberBinder(string name, bool ignoreCase, bool @static) : base(name, null, ignoreCase, @static, nonEnumerating: false) { @@ -4997,7 +5007,7 @@ internal static void SetHasInstanceMember(string memberName) // This way, we can avoid the call to TryGetInstanceMember for binders when we know there aren't any instance // members, yet invalidate those rules once somebody adds an instance member. - var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, _ => new List()); + var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, static _ => new List()); lock (binderList) { @@ -5028,7 +5038,7 @@ internal static void SetHasInstanceMember(string memberName) internal static void TypeTableMemberAdded(string memberName) { - var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, _ => new List()); + var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, static _ => new List()); lock (binderList) { @@ -5051,7 +5061,7 @@ internal static void TypeTableMemberAdded(string memberName) internal static void TypeTableMemberPossiblyUpdated(string memberName) { - var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, _ => new List()); + var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, static _ => new List()); lock (binderList) { @@ -5064,7 +5074,7 @@ internal static void TypeTableMemberPossiblyUpdated(string memberName) public static PSGetMemberBinder Get(string memberName, TypeDefinitionAst classScope, bool @static) { - return Get(memberName, classScope != null ? classScope.Type : null, @static, false); + return Get(memberName, classScope?.Type, @static, false); } public static PSGetMemberBinder Get(string memberName, Type classScope, bool @static) @@ -5099,7 +5109,7 @@ private static PSGetMemberBinder Get(string memberName, Type classScope, bool @s result = new PSGetMemberBinder(memberName, classScope, true, @static, nonEnumerating); if (!@static) { - var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, _ => new List()); + var binderList = s_binderCacheIgnoringCase.GetOrAdd(memberName, static _ => new List()); lock (binderList) { if (binderList.Count > 0) @@ -5397,18 +5407,6 @@ internal static Expression GetTargetExpr(DynamicMetaObject target, Type castToTy var type = castToType ?? ((value != null) ? value.GetType() : typeof(object)); - // Assemblies in CoreCLR might not allow reflection execution on their internal types. In such case, we walk up - // the derivation chain to find the first public parent, and use reflection methods on the public parent. - if (!TypeResolver.IsPublic(type) && DotNetAdapter.DisallowPrivateReflection(type)) - { - var publicType = DotNetAdapter.GetFirstPublicParentType(type); - if (publicType != null) - { - type = publicType; - } - // else we'll probably fail, but the error message might be more helpful than NullReferenceException - } - if (expr.Type != type) { // Unbox value types (or use Nullable.Value) to avoid a copy in case the value is mutated. @@ -5622,7 +5620,7 @@ internal PSMemberInfo GetPSMemberInfo(DynamicMetaObject target, PSMemberInfo memberInfo = null; ConsolidatedString typenames = null; var context = LocalPipeline.GetExecutionContextFromTLS(); - var typeTable = context != null ? context.TypeTable : null; + var typeTable = context?.TypeTable; if (hasTypeTableMember) { @@ -5758,7 +5756,7 @@ internal PSMemberInfo GetPSMemberInfo(DynamicMetaObject target, if (psMethodInfo != null) { var cacheEntry = (DotNetAdapter.MethodCacheEntry)psMethodInfo.adapterData; - candidateMethods.AddRange(cacheEntry.methodInformationStructures.Select(e => e.method)); + candidateMethods.AddRange(cacheEntry.methodInformationStructures.Select(static e => e.method)); memberInfo = null; } @@ -5769,7 +5767,7 @@ internal PSMemberInfo GetPSMemberInfo(DynamicMetaObject target, } else { - DotNetAdapter.MethodCacheEntry method = new DotNetAdapter.MethodCacheEntry(candidateMethods.ToArray()); + DotNetAdapter.MethodCacheEntry method = new DotNetAdapter.MethodCacheEntry(candidateMethods); memberInfo = PSMethod.Create(this.Name, PSObject.DotNetInstanceAdapter, null, method); } } @@ -5835,7 +5833,7 @@ internal static object GetAdaptedValue(object obj, string member) } } - var adapterSet = PSObject.GetMappedAdapter(obj, context != null ? context.TypeTable : null); + var adapterSet = PSObject.GetMappedAdapter(obj, context?.TypeTable); if (memberInfo == null) { memberInfo = adapterSet.OriginalAdapter.BaseGetMember(obj, member); @@ -5874,7 +5872,7 @@ internal static bool IsTypeNameSame(object value, string typeName) internal static TypeTable GetTypeTableFromTLS() { var executionContext = LocalPipeline.GetExecutionContextFromTLS(); - return executionContext != null ? executionContext.TypeTable : null; + return executionContext?.TypeTable; } internal static bool TryGetInstanceMember(object value, string memberName, out PSMemberInfo memberInfo) @@ -5926,7 +5924,7 @@ internal static bool TryGetGenericDictionaryValue(IDictionary hash /// internal class PSSetMemberBinder : SetMemberBinder { - private class KeyComparer : IEqualityComparer + private sealed class KeyComparer : IEqualityComparer { public bool Equals(PSSetMemberBinderKeyType x, PSSetMemberBinderKeyType y) { @@ -5957,7 +5955,7 @@ private static readonly Dictionary public static PSSetMemberBinder Get(string memberName, TypeDefinitionAst classScopeAst, bool @static) { - var classScope = classScopeAst != null ? classScopeAst.Type : null; + var classScope = classScopeAst?.Type; return Get(memberName, classScope, @static); } @@ -5991,7 +5989,7 @@ public override string ToString() return string.Format(CultureInfo.InvariantCulture, "SetMember: {0}{1} ver:{2}", _static ? "static " : string.Empty, Name, _getMemberBinder._version); } - private Expression GetTransformedExpression(IEnumerable transformationAttributes, Expression originalExpression) + private static Expression GetTransformedExpression(IEnumerable transformationAttributes, Expression originalExpression) { if (transformationAttributes == null) { @@ -6279,7 +6277,7 @@ public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, Dy if (value.Value == null) { expr = Expression.Block( - Expression.Assign(lhs, this.GetTransformedExpression(argumentTransformationAttributes, Expression.Constant(null, lhsType))), + Expression.Assign(lhs, GetTransformedExpression(argumentTransformationAttributes, Expression.Constant(null, lhsType))), ExpressionCache.NullConstant); } else @@ -6288,7 +6286,7 @@ public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, Dy Expression assignmentExpression; if (transformationNeeded) { - var transformedExpr = this.GetTransformedExpression(argumentTransformationAttributes, value.Expression); + var transformedExpr = GetTransformedExpression(argumentTransformationAttributes, value.Expression); assignmentExpression = DynamicExpression.Dynamic(PSConvertBinder.Get(nullableUnderlyingType), nullableUnderlyingType, transformedExpr); } else @@ -6310,7 +6308,7 @@ public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, Dy if (transformationNeeded) { assignedValue = DynamicExpression.Dynamic(PSConvertBinder.Get(lhsType), lhsType, - this.GetTransformedExpression(argumentTransformationAttributes, value.Expression)); + GetTransformedExpression(argumentTransformationAttributes, value.Expression)); } else { @@ -6439,7 +6437,7 @@ internal static object SetAdaptedValue(object obj, string member, object value) } } - var adapterSet = PSObject.GetMappedAdapter(obj, context != null ? context.TypeTable : null); + var adapterSet = PSObject.GetMappedAdapter(obj, context?.TypeTable); if (memberInfo == null) { memberInfo = adapterSet.OriginalAdapter.BaseGetMember(obj, member); @@ -6498,7 +6496,7 @@ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, Dynam } } - internal class PSInvokeMemberBinder : InvokeMemberBinder + internal sealed class PSInvokeMemberBinder : InvokeMemberBinder { internal enum MethodInvocationType { @@ -6509,7 +6507,7 @@ internal enum MethodInvocationType NonVirtual, } - private class KeyComparer : IEqualityComparer + private sealed class KeyComparer : IEqualityComparer { public bool Equals(PSInvokeMemberBinderKeyType x, PSInvokeMemberBinderKeyType y) { @@ -6602,14 +6600,14 @@ public override string ToString() public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { - if (!target.HasValue || args.Any(arg => !arg.HasValue)) + if (!target.HasValue || args.Any(static arg => !arg.HasValue)) { return Defer(args.Prepend(target).ToArray()); } // Defer COM objects or arguments wrapped in PSObjects if ((target.Value is PSObject && (PSObject.Base(target.Value) != target.Value)) || - args.Any(mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) + args.Any(static mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value))) { object baseObject = PSObject.Base(target.Value); if (baseObject != null && Marshal.IsComObject(baseObject)) @@ -6640,7 +6638,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, Expression.Call(Expression.NewArrayInit(typeof(object)), CachedReflectionInfo.IEnumerable_GetEnumerator), BindingRestrictions.GetInstanceRestriction(Expression.Call(CachedReflectionInfo.PSObject_Base, target.Expression), null)) .WriteToDebugLog(this); - BindingRestrictions argRestrictions = args.Aggregate(BindingRestrictions.Empty, (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); + BindingRestrictions argRestrictions = args.Aggregate(BindingRestrictions.Empty, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); if (string.Equals(Name, "Where", StringComparison.OrdinalIgnoreCase)) { @@ -6685,7 +6683,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, Expression.Call(CachedReflectionInfo.PSInvokeMemberBinder_TryGetInstanceMethod, target.Expression.Cast(typeof(object)), Expression.Constant(Name), methodInfoVar), Expression.Call(methodInfoVar, CachedReflectionInfo.PSMethodInfo_Invoke, - Expression.NewArrayInit(typeof(object), args.Select(dmo => dmo.Expression.Cast(typeof(object))))), + Expression.NewArrayInit(typeof(object), args.Select(static dmo => dmo.Expression.Cast(typeof(object))))), this.GetUpdateExpression(typeof(object))); return (new DynamicMetaObject(Expression.Block(new[] { methodInfoVar }, expr), @@ -6696,7 +6694,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, bool canOptimize; Type aliasConversionType; var methodInfo = _getMemberBinder.GetPSMemberInfo(target, out restrictions, out canOptimize, out aliasConversionType, MemberTypes.Method) as PSMethodInfo; - restrictions = args.Aggregate(restrictions, (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); + restrictions = args.Aggregate(restrictions, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); // If the process has ever used ConstrainedLanguage, then we need to add the language mode // to the binding restrictions, and check whether it is allowed. We can't limit @@ -6728,7 +6726,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, PSGetMemberBinder.GetTargetExpr(target, typeof(object)), Expression.Constant(Name), Expression.NewArrayInit(typeof(object), - args.Take(args.Length - 1).Select(arg => arg.Expression.Cast(typeof(object)))), + args.Take(args.Length - 1).Select(static arg => arg.Expression.Cast(typeof(object)))), args.Last().Expression.Cast(typeof(object))); } else @@ -6738,7 +6736,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, PSGetMemberBinder.GetTargetExpr(target, typeof(object)), Expression.Constant(Name), Expression.NewArrayInit(typeof(object), - args.Select(arg => arg.Expression.Cast(typeof(object))))); + args.Select(static arg => arg.Expression.Cast(typeof(object))))); } return new DynamicMetaObject(call, restrictions).WriteToDebugLog(this); @@ -6764,7 +6762,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, // If we get here, then the target value should have 'isDeserialized == false', otherwise we cannot get a .NET methodInfo // from _getMemberBinder.GetPSMemberInfo(). This is because when 'isDeserialized' is true, we use the PSObject to find the // corresponding Adapter -- PSObjectAdapter, which cannot be optimized. - Diagnostics.Assert(psObj.IsDeserialized == false, + Diagnostics.Assert(!psObj.IsDeserialized, "isDeserialized should be false, because if not, we cannot get a .NET method/parameterizedProperty from GetPSMemberInfo"); restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction( @@ -6790,7 +6788,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, Expression.Constant(scriptMethod.Script), target.Expression.Cast(typeof(object)), Expression.NewArrayInit(typeof(object), - args.Select(e => e.Expression.Cast(typeof(object))))), + args.Select(static e => e.Expression.Cast(typeof(object))))), restrictions).WriteToDebugLog(this); } @@ -6957,7 +6955,7 @@ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicExpression.Dynamic( new PSInvokeBinder(CallInfo), typeof(object), - args.Prepend(target).Select(dmo => dmo.Expression) + args.Prepend(target).Select(static dmo => dmo.Expression) ), target.Restrictions.Merge(BindingRestrictions.Combine(args)) )); @@ -6985,7 +6983,7 @@ internal static MethodInfo FindBestMethod(DynamicMetaObject target, data.methodInformationStructures, invocationConstraints, allowCastingToByRefLikeType: true, - args.Select(arg => arg.Value == AutomationNull.Value ? null : arg.Value).ToArray(), + args.Select(static arg => arg.Value == AutomationNull.Value ? null : arg.Value).ToArray(), ref errorId, ref errorMsg, out expandParameters, @@ -7175,7 +7173,7 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target, CachedReflectionInfo.ClassOps_CallBaseCtor, targetExpr, Expression.Constant(constructorInfo, typeof(ConstructorInfo)), - Expression.NewArrayInit(typeof(object), argExprs.Select(x => x.Cast(typeof(object))))); + Expression.NewArrayInit(typeof(object), argExprs.Select(static x => x.Cast(typeof(object))))); } else { @@ -7192,7 +7190,7 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target, : CachedReflectionInfo.ClassOps_CallMethodNonVirtually, PSGetMemberBinder.GetTargetExpr(target, methodInfo.DeclaringType), Expression.Constant(methodInfo, typeof(MethodInfo)), - Expression.NewArrayInit(typeof(object), argExprs.Select(x => x.Cast(typeof(object))))); + Expression.NewArrayInit(typeof(object), argExprs.Select(static x => x.Cast(typeof(object))))); } else { @@ -7222,14 +7220,14 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target, private DynamicMetaObject InvokeMemberOnCollection(DynamicMetaObject targetEnumerator, DynamicMetaObject[] args, Type typeForMessage, BindingRestrictions restrictions) { - var d = DynamicExpression.Dynamic(this, this.ReturnType, args.Select(a => a.Expression).Prepend(ExpressionCache.NullConstant)); + var d = DynamicExpression.Dynamic(this, this.ReturnType, args.Select(static a => a.Expression).Prepend(ExpressionCache.NullConstant)); return new DynamicMetaObject( Expression.Call(CachedReflectionInfo.EnumerableOps_MethodInvoker, Expression.Constant(this.GetNonEnumeratingBinder()), Expression.Constant(d.DelegateType, typeof(Type)), targetEnumerator.Expression, Expression.NewArrayInit(typeof(object), - args.Select(a => a.Expression.Cast(typeof(object)))), + args.Select(static a => a.Expression.Cast(typeof(object)))), Expression.Constant(typeForMessage, typeof(Type)) ), targetEnumerator.Restrictions.Merge(restrictions)); @@ -7330,7 +7328,7 @@ private DynamicMetaObject InvokeForEachOnCollection(DynamicMetaObject targetEnum if (args.Length > 1) { argsToPass = Expression.NewArrayInit(typeof(object), - args.Skip(1).Select(a => a.Expression.Cast(typeof(object)))); + args.Skip(1).Select(static a => a.Expression.Cast(typeof(object)))); } else { @@ -7394,7 +7392,7 @@ internal static bool IsHeterogeneousArray(object[] args) internal static object InvokeAdaptedMember(object obj, string methodName, object[] args) { var context = LocalPipeline.GetExecutionContextFromTLS(); - var adapterSet = PSObject.GetMappedAdapter(obj, context != null ? context.TypeTable : null); + var adapterSet = PSObject.GetMappedAdapter(obj, context?.TypeTable); var methodInfo = adapterSet.OriginalAdapter.BaseGetMember(obj, methodName) as PSMethodInfo; if (methodInfo == null && adapterSet.DotNetAdapter != null) { @@ -7439,7 +7437,7 @@ internal static object InvokeAdaptedMember(object obj, string methodName, object internal static object InvokeAdaptedSetMember(object obj, string methodName, object[] args, object valueToSet) { var context = LocalPipeline.GetExecutionContextFromTLS(); - var adapterSet = PSObject.GetMappedAdapter(obj, context != null ? context.TypeTable : null); + var adapterSet = PSObject.GetMappedAdapter(obj, context?.TypeTable); var methodInfo = adapterSet.OriginalAdapter.BaseGetMember(obj, methodName); if (methodInfo == null && adapterSet.DotNetAdapter != null) { @@ -7499,7 +7497,7 @@ internal class PSCreateInstanceBinder : CreateInstanceBinder private readonly bool _publicTypeOnly; private int _version; - private class KeyComparer : IEqualityComparer> + private sealed class KeyComparer : IEqualityComparer> { public bool Equals(Tuple x, Tuple y) @@ -7565,7 +7563,7 @@ public override string ToString() public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { - if (!target.HasValue || args.Any(arg => !arg.HasValue)) + if (!target.HasValue || args.Any(static arg => !arg.HasValue)) { return Defer(args.Prepend(target).ToArray()); } @@ -7629,7 +7627,7 @@ public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject targe return target.ThrowRuntimeError(restrictions, "CannotCreateTypeConstrainedLanguage", ParserStrings.CannotCreateTypeConstrainedLanguage).WriteToDebugLog(this); } - restrictions = args.Aggregate(restrictions, (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); + restrictions = args.Aggregate(restrictions, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); var newConstructors = DotNetAdapter.GetMethodInformationArray(ctors); return PSInvokeMemberBinder.InvokeDotNetMethod(_callInfo, "new", _constraints, PSInvokeMemberBinder.MethodInvocationType.Ordinary, target, args, restrictions, newConstructors, typeof(MethodException)).WriteToDebugLog(this); @@ -7677,7 +7675,7 @@ internal class PSInvokeBaseCtorBinder : InvokeMemberBinder private readonly CallInfo _callInfo; private readonly PSMethodInvocationConstraints _constraints; - private class KeyComparer : IEqualityComparer> + private sealed class KeyComparer : IEqualityComparer> { public bool Equals(Tuple x, Tuple y) @@ -7723,7 +7721,7 @@ internal PSInvokeBaseCtorBinder(CallInfo callInfo, PSMethodInvocationConstraints public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { - if (!target.HasValue || args.Any(arg => !arg.HasValue)) + if (!target.HasValue || args.Any(static arg => !arg.HasValue)) { return Defer(args.Prepend(target).ToArray()); } @@ -7733,8 +7731,8 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, var restrictions = target.Value is PSObject ? BindingRestrictions.GetTypeRestriction(target.Expression, target.Value.GetType()) : target.PSGetTypeRestriction(); - restrictions = args.Aggregate(restrictions, (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); - var newConstructors = DotNetAdapter.GetMethodInformationArray(ctors.Where(c => c.IsPublic || c.IsFamily).ToArray()); + restrictions = args.Aggregate(restrictions, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction())); + var newConstructors = DotNetAdapter.GetMethodInformationArray(ctors.Where(static c => c.IsPublic || c.IsFamily).ToArray()); return PSInvokeMemberBinder.InvokeDotNetMethod(_callInfo, "new", _constraints, PSInvokeMemberBinder.MethodInvocationType.BaseCtor, target, args, restrictions, newConstructors, typeof(MethodException)); } @@ -7745,7 +7743,7 @@ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, Dynam DynamicExpression.Dynamic( new PSInvokeBinder(CallInfo), typeof(object), - args.Prepend(target).Select(dmo => dmo.Expression) + args.Prepend(target).Select(static dmo => dmo.Expression) ), target.Restrictions.Merge(BindingRestrictions.Combine(args)) )); diff --git a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs index f441a84470c..2e6db041126 100644 --- a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs +++ b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs @@ -105,7 +105,7 @@ private void InitializeMetadata() { if (attribute is CmdletBindingAttribute c) { - cmdletBindingAttribute = cmdletBindingAttribute ?? c; + cmdletBindingAttribute ??= c; } else if (attribute is DebuggerHiddenAttribute) { @@ -193,8 +193,7 @@ private void ReallyCompile(bool optimize) private void PerformSecurityChecks() { - var scriptBlockAst = Ast as ScriptBlockAst; - if (scriptBlockAst == null) + if (!(Ast is ScriptBlockAst scriptBlockAst)) { // Checks are only needed at the top level. return; @@ -263,14 +262,12 @@ bool IsScriptBlockInFactASafeHashtable() return false; } - PipelineAst pipelineAst = endBlock.Statements[0] as PipelineAst; - if (pipelineAst == null) + if (!(endBlock.Statements[0] is PipelineAst pipelineAst)) { return false; } - HashtableAst hashtableAst = pipelineAst.GetPureExpression() as HashtableAst; - if (hashtableAst == null) + if (!(pipelineAst.GetPureExpression() is HashtableAst hashtableAst)) { return false; } @@ -310,18 +307,29 @@ private IParameterMetadataProvider DelayParseScriptText() } internal Type LocalsMutableTupleType { get; set; } + internal Type UnoptimizedLocalsMutableTupleType { get; set; } + internal Func LocalsMutableTupleCreator { get; set; } + internal Func UnoptimizedLocalsMutableTupleCreator { get; set; } + internal Dictionary NameToIndexMap { get; set; } internal Action DynamicParamBlock { get; set; } + internal Action UnoptimizedDynamicParamBlock { get; set; } + internal Action BeginBlock { get; set; } + internal Action UnoptimizedBeginBlock { get; set; } + internal Action ProcessBlock { get; set; } + internal Action UnoptimizedProcessBlock { get; set; } + internal Action EndBlock { get; set; } + internal Action UnoptimizedEndBlock { get; set; } internal IScriptExtent[] SequencePoints { get; set; } @@ -335,11 +343,15 @@ private IParameterMetadataProvider DelayParseScriptText() private bool? _isProductCode; internal bool DebuggerHidden { get; set; } + internal bool DebuggerStepThrough { get; set; } + internal Guid Id { get; private set; } internal bool HasLogged { get; set; } + internal bool SkipLogging { get; set; } + internal bool IsFilter { get; } internal bool IsProductCode @@ -428,7 +440,7 @@ internal CmdletBindingAttribute CmdletBindingAttribute } return _usesCmdletBinding - ? (CmdletBindingAttribute)Array.Find(_attributes, attr => attr is CmdletBindingAttribute) + ? (CmdletBindingAttribute)Array.Find(_attributes, static attr => attr is CmdletBindingAttribute) : null; } } @@ -442,7 +454,7 @@ internal ObsoleteAttribute ObsoleteAttribute InitializeMetadata(); } - return (ObsoleteAttribute)Array.Find(_attributes, attr => attr is ObsoleteAttribute); + return (ObsoleteAttribute)Array.Find(_attributes, static attr => attr is ObsoleteAttribute); } } @@ -523,8 +535,8 @@ public partial class ScriptBlock : ISerializable { private readonly CompiledScriptBlockData _scriptBlockData; - internal ScriptBlock(IParameterMetadataProvider ast, bool isFilter) : - this(new CompiledScriptBlockData(ast, isFilter)) + internal ScriptBlock(IParameterMetadataProvider ast, bool isFilter) + : this(new CompiledScriptBlockData(ast, isFilter)) { } @@ -600,8 +612,8 @@ internal static void CacheScriptBlock(ScriptBlock scriptBlock, string fileName, // TODO(sevoroby): we can optimize it to ignore 'using' if there are no actual type usage in locally defined types. // using is always a top-level statements in scriptBlock, we don't need to search in child blocks. - if (scriptBlock.Ast.Find(ast => IsUsingTypes(ast), false) != null - || scriptBlock.Ast.Find(ast => IsDynamicKeyword(ast), true) != null) + if (scriptBlock.Ast.Find(static ast => IsUsingTypes(ast), false) != null + || scriptBlock.Ast.Find(static ast => IsDynamicKeyword(ast), true) != null) { return; } @@ -726,7 +738,7 @@ internal PowerShell GetPowerShellImpl( internal SteppablePipeline GetSteppablePipelineImpl(CommandOrigin commandOrigin, object[] args) { var pipelineAst = GetSimplePipeline( - resourceString => { throw PSTraceSource.NewInvalidOperationException(resourceString); }); + resourceString => throw PSTraceSource.NewInvalidOperationException(resourceString)); Diagnostics.Assert(pipelineAst != null, "This should be checked by GetSimplePipeline"); if (pipelineAst.PipelineElements[0] is not CommandAst) @@ -739,7 +751,7 @@ internal SteppablePipeline GetSteppablePipelineImpl(CommandOrigin commandOrigin, private PipelineAst GetSimplePipeline(Func errorHandler) { - errorHandler = errorHandler ?? (_ => null); + errorHandler ??= (static _ => null); if (HasBeginBlock || HasProcessBlock) { @@ -763,8 +775,7 @@ private PipelineAst GetSimplePipeline(Func errorHandler) return errorHandler(AutomationExceptions.CantConvertScriptBlockWithTrap); } - var pipeAst = statements[0] as PipelineAst; - if (pipeAst == null) + if (!(statements[0] is PipelineAst pipeAst)) { return errorHandler(AutomationExceptions.CanOnlyConvertOnePipeline); } @@ -833,7 +844,7 @@ internal bool SkipLogging set { _scriptBlockData.SkipLogging = value; } } - internal Assembly AssemblyDefiningPSTypes { set; get; } + internal Assembly AssemblyDefiningPSTypes { get; set; } internal HelpInfo GetHelpInfo( ExecutionContext context, @@ -993,7 +1004,7 @@ internal void InvokeWithPipeImpl( args = Array.Empty(); } - bool runOptimized = context._debuggingMode > 0 ? false : createLocalScope; + bool runOptimized = context._debuggingMode <= 0 && createLocalScope; var codeToInvoke = GetCodeToInvoke(ref runOptimized, clauseToInvoke); if (codeToInvoke == null) { @@ -1716,13 +1727,13 @@ private static bool GetAndValidateEncryptionRecipients( return true; } - private static object s_syncObject = new object(); + private static readonly object s_syncObject = new object(); private static string s_lastSeenCertificate = string.Empty; private static bool s_hasProcessedCertificate = false; private static CmsMessageRecipient[] s_encryptionRecipients = null; - private static Lazy s_sbLoggingSettingCache = new Lazy( - () => Utils.GetPolicySetting(Utils.SystemWideThenCurrentUserConfig), + private static readonly Lazy s_sbLoggingSettingCache = new Lazy( + static () => Utils.GetPolicySetting(Utils.SystemWideThenCurrentUserConfig), isThreadSafe: true); // Reset any static caches if the certificate has changed @@ -1778,7 +1789,7 @@ internal static string CheckSuspiciousContent(Ast scriptBlockAst) return null; } - private class SuspiciousContentChecker + private static class SuspiciousContentChecker { // Based on a (bad) random number generator, but good enough // for our simple needs. @@ -2001,7 +2012,7 @@ public static string Match(string text) uint h = text[i]; if (h >= 'A' && h <= 'Z') { - h = h | 0x20; // ToLower + h |= 0x20; // ToLower } else if (!((h >= 'a' && h <= 'z') || h == '-')) { @@ -2185,7 +2196,7 @@ internal sealed class PSScriptCmdlet : PSCmdlet, IDynamicParameters, IDisposable private readonly bool _fromScriptFile; private readonly bool _useLocalScope; private readonly bool _runOptimized; - private bool _rethrowExitException; + private readonly bool _rethrowExitException; private MshCommandRuntime _commandRuntime; private readonly MutableTuple _localsTuple; private bool _exitWasCalled; @@ -2196,7 +2207,7 @@ public PSScriptCmdlet(ScriptBlock scriptBlock, bool useNewScope, bool fromScript _scriptBlock = scriptBlock; _useLocalScope = useNewScope; _fromScriptFile = fromScriptFile; - _runOptimized = _scriptBlock.Compile(optimized: context._debuggingMode > 0 ? false : useNewScope); + _runOptimized = _scriptBlock.Compile(optimized: context._debuggingMode <= 0 && useNewScope); _localsTuple = _scriptBlock.MakeLocalsTuple(_runOptimized); _localsTuple.SetAutomaticVariable(AutomaticVariable.PSCmdlet, this, context); _scriptBlock.SetPSScriptRootAndPSCommandPath(_localsTuple, context); diff --git a/src/System.Management.Automation/engine/runtime/MutableTuple.cs b/src/System.Management.Automation/engine/runtime/MutableTuple.cs index de923e2df8b..49c5eadc4aa 100644 --- a/src/System.Management.Automation/engine/runtime/MutableTuple.cs +++ b/src/System.Management.Automation/engine/runtime/MutableTuple.cs @@ -149,6 +149,7 @@ public void SetValue(int index, object value) } protected abstract object GetValueImpl(int index); + protected abstract void SetValueImpl(int index, object value); /// @@ -503,7 +504,7 @@ public abstract int Capacity /// public static Expression Create(params Expression[] values) { - return CreateNew(MakeTupleType(values.Select(x => x.Type).ToArray()), 0, values.Length, values); + return CreateNew(MakeTupleType(values.Select(static x => x.Type).ToArray()), 0, values.Length, values); } private static int PowerOfTwoRound(int value) @@ -511,7 +512,7 @@ private static int PowerOfTwoRound(int value) int res = 1; while (value > res) { - res = res << 1; + res <<= 1; } return res; @@ -563,7 +564,7 @@ internal static Expression CreateNew(Type tupleType, int start, int end, Express } } - return Expression.New(tupleType.GetConstructor(newValues.Select(x => x.Type).ToArray()), newValues); + return Expression.New(tupleType.GetConstructor(newValues.Select(static x => x.Type).ToArray()), newValues); } } diff --git a/src/System.Management.Automation/engine/runtime/Operations/ArrayOps.cs b/src/System.Management.Automation/engine/runtime/Operations/ArrayOps.cs index d340f8c2667..fa4c2c2b565 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/ArrayOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/ArrayOps.cs @@ -52,7 +52,10 @@ internal static T[] Multiply(T[] array, uint times) if (times == 0 || array.Length == 0) { - return new T[0]; // don't use Utils.EmptyArray, always return a new array +#pragma warning disable CA1825 // Avoid zero-length array allocations + // Don't use Array.Empty(); always return a new instance. + return new T[0]; +#pragma warning restore CA1825 // Avoid zero-length array allocations } var context = LocalPipeline.GetExecutionContextFromTLS(); @@ -231,7 +234,7 @@ internal static string IndexStringMessage(object index) // Convert this index into something printable (we hope)... string msgString = PSObject.ToString(null, index, ",", null, null, true, true); if (msgString.Length > 20) - msgString = msgString.Substring(0, 20) + " ..."; + msgString = string.Concat(msgString.AsSpan(0, 20), " ..."); return msgString; } diff --git a/src/System.Management.Automation/engine/runtime/Operations/ClassOps.cs b/src/System.Management.Automation/engine/runtime/Operations/ClassOps.cs index 7b06697afa1..d0651719886 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/ClassOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/ClassOps.cs @@ -284,7 +284,7 @@ public static void ValidateSetProperty(Type type, string propertyName, object va { var validateAttributes = type.GetProperty(propertyName).GetCustomAttributes(); var executionContext = LocalPipeline.GetExecutionContextFromTLS(); - var engineIntrinsics = executionContext == null ? null : executionContext.EngineIntrinsics; + var engineIntrinsics = executionContext?.EngineIntrinsics; foreach (var validateAttribute in validateAttributes) { validateAttribute.InternalValidate(value, engineIntrinsics); @@ -356,7 +356,7 @@ private static DynamicMethod CreateDynamicMethod(MethodInfo mi) { // Pass in the declaring type because instance method has a hidden parameter 'this' as the first parameter. var paramTypes = new List { mi.DeclaringType }; - paramTypes.AddRange(mi.GetParameters().Select(x => x.ParameterType)); + paramTypes.AddRange(mi.GetParameters().Select(static x => x.ParameterType)); var dm = new DynamicMethod("PSNonVirtualCall_" + mi.Name, mi.ReturnType, paramTypes.ToArray(), mi.DeclaringType); ILGenerator il = dm.GetILGenerator(); diff --git a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs index 2b5d1771ed3..de9ef697fc6 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs @@ -104,7 +104,7 @@ private static CommandProcessorBase AddCommand(PipelineProcessor pipe, else { var commandName = command as string ?? PSObject.ToStringParser(context, command); - invocationName = invocationName ?? commandName; + invocationName ??= commandName; if (string.IsNullOrEmpty(commandName)) { @@ -407,7 +407,7 @@ private static string GetParameterText(string parameterName) else { string whitespaces = parameterName.Substring(endPosition); - parameterText = "-" + parameterName.Substring(0, endPosition) + ":" + whitespaces; + parameterText = string.Concat("-", parameterName.AsSpan(0, endPosition), ":", whitespaces); } return parameterText; @@ -449,7 +449,7 @@ internal static void InvokePipeline(object input, for (int i = 0; i < pipeElements.Length; i++) { - commandRedirection = commandRedirections != null ? commandRedirections[i] : null; + commandRedirection = commandRedirections?[i]; commandProcessor = AddCommand(pipelineProcessor, pipeElements[i], pipeElementAsts[i], commandRedirection, context); } @@ -529,7 +529,7 @@ internal static void InvokePipelineInBackground( // For background jobs rewrite the pipeline as a Start-Job command var scriptblockBodyString = pipelineAst.Extent.Text; var pipelineOffset = pipelineAst.Extent.StartOffset; - var variables = pipelineAst.FindAll(x => x is VariableExpressionAst, true); + var variables = pipelineAst.FindAll(static x => x is VariableExpressionAst, true); // Used to make sure that the job runs in the current directory const string cmdPrefix = @"Microsoft.PowerShell.Management\Set-Location -LiteralPath $using:pwd ; "; @@ -551,10 +551,10 @@ internal static void InvokePipelineInBackground( } // Skip PowerShell magic variables - if (Regex.Match( + if (!Regex.Match( variableName, "^(global:){0,1}(PID|PSVersionTable|PSEdition|PSHOME|HOST|TRUE|FALSE|NULL)$", - RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).Success == false) + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).Success) { updatedScriptblock.Append(scriptblockBodyString.AsSpan(position, v.Extent.StartOffset - pipelineOffset - position)); updatedScriptblock.Append("${using:"); @@ -1280,8 +1280,7 @@ internal static void DefineFunction(ExecutionContext context, } catch (Exception exception) { - var rte = exception as RuntimeException; - if (rte == null) + if (!(exception is RuntimeException rte)) { throw ExceptionHandlingOps.ConvertToRuntimeException(exception, functionDefinitionAst.Extent); } @@ -1309,7 +1308,7 @@ internal ScriptBlock GetScriptBlock(ExecutionContext context, bool isFilter) Diagnostics.Assert(_scriptBlock == null || _scriptBlock.SessionStateInternal == null, "Cached script block should not hold on to session state"); - var result = (_scriptBlock ?? (_scriptBlock = new ScriptBlock(_ast, isFilter))).Clone(); + var result = (_scriptBlock ??= new ScriptBlock(_ast, isFilter)).Clone(); result.SessionStateInternal = context.EngineSessionState; return result; } @@ -1380,7 +1379,7 @@ internal class CatchAll { } /// /// Represent a handler search result. /// - private class HandlerSearchResult + private sealed class HandlerSearchResult { internal HandlerSearchResult() { @@ -1419,7 +1418,7 @@ private static int[] RankExceptionTypes(Type[] types) if (types[length - 1].Equals(typeof(CatchAll))) { ranks[length - 1] = length - 1; - length = length - 1; + length -= 1; } // For each type check if it's a sub-class of any types after it. @@ -3228,7 +3227,10 @@ internal static object Multiply(IEnumerator enumerator, uint times) if (originalList.Count == 0) { - return new object[0]; // don't use Utils.EmptyArray, always return a new array +#pragma warning disable CA1825 // Avoid zero-length array allocations + // Don't use Array.Empty(); always return a new instance. + return new object[0]; +#pragma warning restore CA1825 // Avoid zero-length array allocations } return ArrayOps.Multiply(originalList.ToArray(), times); diff --git a/src/System.Management.Automation/engine/runtime/Operations/VariableOps.cs b/src/System.Management.Automation/engine/runtime/Operations/VariableOps.cs index d337c56ab2b..6799d1bd989 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/VariableOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/VariableOps.cs @@ -277,7 +277,7 @@ private static UsingResult GetUsingValueFromTuple(MutableTuple tuple, string usi return null; } - private class UsingResult + private sealed class UsingResult { public object Value { get; set; } } diff --git a/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs b/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs index 4e6d81e9208..fc1dba4aed8 100644 --- a/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs +++ b/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs @@ -16,6 +16,7 @@ internal class ScriptBlockToPowerShellChecker : AstVisitor private readonly HashSet _validVariables = new HashSet(StringComparer.OrdinalIgnoreCase); internal ScriptBlockAst ScriptBeingConverted { get; set; } + internal bool UsesParameter { get; private set; } internal bool HasUsingExpr { get; private set; } @@ -171,13 +172,16 @@ internal static void ThrowError(ScriptBlockToPowerShellNotSupportedException ex, } } - internal class UsingExpressionAstSearcher : AstSearcher + internal sealed class UsingExpressionAstSearcher : AstSearcher { - internal static IEnumerable FindAllUsingExpressionExceptForWorkflow(Ast ast) + internal static IEnumerable FindAllUsingExpressions(Ast ast) { Diagnostics.Assert(ast != null, "caller to verify arguments"); - var searcher = new UsingExpressionAstSearcher(astParam => astParam is UsingExpressionAst, stopOnFirst: false, searchNestedScriptBlocks: true); + var searcher = new UsingExpressionAstSearcher( + callback: astParam => astParam is UsingExpressionAst, + stopOnFirst: false, + searchNestedScriptBlocks: true); ast.InternalVisit(searcher); return searcher.Results; } @@ -203,7 +207,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast /// Converts a ScriptBlock to a PowerShell object by traversing the /// given Ast. /// - internal class ScriptBlockToPowerShellConverter + internal sealed class ScriptBlockToPowerShellConverter { private readonly PowerShell _powershell; private ExecutionContext _context; @@ -312,6 +316,145 @@ internal static PowerShell Convert(ScriptBlockAst body, } } + /// + /// Get using values as dictionary for the Foreach-Object parallel cmdlet. + /// Ignore any using expressions that are associated with inner nested Foreach-Object parallel calls, + /// since they are only effective in the nested call scope and not the current outer scope. + /// + /// Scriptblock to search. + /// True when input is trusted. + /// Execution context. + /// List of foreach command names and aliases. + /// Dictionary of using variable map. + internal static Dictionary GetUsingValuesForEachParallel( + ScriptBlock scriptBlock, + bool isTrustedInput, + ExecutionContext context, + string[] foreachNames) + { + // Using variables for Foreach-Object -Parallel use are restricted to be within the + // Foreach-Object -Parallel call scope. This will filter the using variable map to variables + // only within the current (outer) Foreach-Object -Parallel call scope. + var usingAsts = UsingExpressionAstSearcher.FindAllUsingExpressions(scriptBlock.Ast).ToList(); + UsingExpressionAst usingAst = null; + var usingValueMap = new Dictionary(usingAsts.Count); + Version oldStrictVersion = null; + try + { + if (context != null) + { + oldStrictVersion = context.EngineSessionState.CurrentScope.StrictModeVersion; + context.EngineSessionState.CurrentScope.StrictModeVersion = PSVersionInfo.PSVersion; + } + + for (int i = 0; i < usingAsts.Count; ++i) + { + usingAst = (UsingExpressionAst)usingAsts[i]; + if (IsInForeachParallelCallingScope(usingAst, foreachNames)) + { + var value = Compiler.GetExpressionValue(usingAst.SubExpression, isTrustedInput, context); + string usingAstKey = PsUtils.GetUsingExpressionKey(usingAst); + usingValueMap.TryAdd(usingAstKey, value); + } + } + } + catch (RuntimeException rte) + { + if (rte.ErrorRecord.FullyQualifiedErrorId.Equals("VariableIsUndefined", StringComparison.Ordinal)) + { + throw InterpreterError.NewInterpreterException( + targetObject: null, + exceptionType: typeof(RuntimeException), + errorPosition: usingAst.Extent, + resourceIdAndErrorId: "UsingVariableIsUndefined", + resourceString: AutomationExceptions.UsingVariableIsUndefined, + args: rte.ErrorRecord.TargetObject); + } + } + finally + { + if (context != null) + { + context.EngineSessionState.CurrentScope.StrictModeVersion = oldStrictVersion; + } + } + + return usingValueMap; + } + + /// + /// Walks the using Ast to verify it is used within a foreach-object -parallel command + /// and parameter set scope, and not from within a nested foreach-object -parallel call. + /// + /// Using Ast to check. + /// List of foreach-object command names. + /// True if using expression is in current call scope. + private static bool IsInForeachParallelCallingScope( + UsingExpressionAst usingAst, + string[] foreachNames) + { + /* + Example: + $Test1 = "Hello" + 1 | ForEach-Object -Parallel { + $using:Test1 + $Test2 = "Goodbye" + 1 | ForEach-Object -Parallel { + $using:Test1 # Invalid using scope + $using:Test2 # Valid using scope + } + } + */ + Diagnostics.Assert(usingAst != null, "usingAst argument cannot be null."); + + // Search up the parent Ast chain for 'Foreach-Object -Parallel' commands. + Ast currentParent = usingAst.Parent; + int foreachNestedCount = 0; + while (currentParent != null) + { + // Look for Foreach-Object outer commands + if (currentParent is CommandAst commandAst) + { + foreach (var commandElement in commandAst.CommandElements) + { + if (commandElement is StringConstantExpressionAst commandName) + { + bool found = false; + foreach (var foreachName in foreachNames) + { + if (commandName.Value.Equals(foreachName, StringComparison.OrdinalIgnoreCase)) + { + found = true; + break; + } + } + + if (found) + { + // Verify this is foreach-object with parallel parameter set. + var bindingResult = StaticParameterBinder.BindCommand(commandAst); + if (bindingResult.BoundParameters.ContainsKey("Parallel")) + { + foreachNestedCount++; + break; + } + } + } + } + } + + if (foreachNestedCount > 1) + { + // This using expression Ast is outside the original calling scope. + return false; + } + + currentParent = currentParent.Parent; + } + + return foreachNestedCount == 1; + } + /// /// Get using values in the dictionary form. /// @@ -342,11 +485,16 @@ internal static object[] GetUsingValuesAsArray(ScriptBlock scriptBlock, bool isT /// A tuple of the dictionary-form and the array-form using values. /// If the array-form using value is null, then there are UsingExpressions used in different scopes. /// - private static Tuple, object[]> GetUsingValues(Ast body, bool isTrustedInput, ExecutionContext context, Dictionary variables, bool filterNonUsingVariables) + private static Tuple, object[]> GetUsingValues( + Ast body, + bool isTrustedInput, + ExecutionContext context, + Dictionary variables, + bool filterNonUsingVariables) { Diagnostics.Assert(context != null || variables != null, "can't retrieve variables with no context and no variables"); - var usingAsts = UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(body).ToList(); + var usingAsts = UsingExpressionAstSearcher.FindAllUsingExpressions(body).ToList(); var usingValueArray = new object[usingAsts.Count]; var usingValueMap = new Dictionary(usingAsts.Count); HashSet usingVarNames = (variables != null && filterNonUsingVariables) ? new HashSet() : null; @@ -386,8 +534,7 @@ private static Tuple, object[]> GetUsingValues(Ast bo if (variables != null) { - var variableAst = usingAst.SubExpression as VariableExpressionAst; - if (variableAst == null) + if (!(usingAst.SubExpression is VariableExpressionAst variableAst)) { throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException), usingAst.Extent, "CantGetUsingExpressionValueWithSpecifiedVariableDictionary", AutomationExceptions.CantGetUsingExpressionValueWithSpecifiedVariableDictionary, usingAst.Extent.Text); @@ -456,7 +603,7 @@ private static Tuple, object[]> GetUsingValues(Ast bo /// Check if the given UsingExpression is in a different scope from the previous UsingExpression that we analyzed. /// /// - /// Note that the value of is retrieved by calling 'UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow'. + /// Note that the value of is retrieved by calling 'UsingExpressionAstSearcher.FindAllUsingExpressions'. /// So is guaranteed not inside a workflow. /// /// The UsingExpression to analyze. @@ -547,7 +694,6 @@ private void ConvertCommand(CommandAst commandAst, bool isTrustedInput) Diagnostics.Assert(commandAst.Redirections.Count == 1, "only 1 kind of redirection is supported"); Diagnostics.Assert(commandAst.Redirections[0] is MergingRedirectionAst, "unexpected redirection type"); - PipelineResultTypes toType = PipelineResultTypes.Output; PipelineResultTypes fromType; switch (commandAst.Redirections[0].FromStream) { @@ -581,7 +727,7 @@ private void ConvertCommand(CommandAst commandAst, bool isTrustedInput) break; } - command.MergeMyResults(fromType, toType); + command.MergeMyResults(fromType, toResult: PipelineResultTypes.Output); } _powershell.AddCommand(command); diff --git a/src/System.Management.Automation/engine/serialization.cs b/src/System.Management.Automation/engine/serialization.cs index de5d107404c..ce21d8258be 100644 --- a/src/System.Management.Automation/engine/serialization.cs +++ b/src/System.Management.Automation/engine/serialization.cs @@ -82,10 +82,8 @@ internal SerializationContext(int depth, SerializationOptions options, PSRemotin /// /// This class provides public functionality for serializing a PSObject. /// - public class PSSerializer + public static class PSSerializer { - internal PSSerializer() { } - /// /// Serializes an object into PowerShell CliXml. /// @@ -174,7 +172,7 @@ public static object[] DeserializeAsList(string source) /// /// Default depth of serialization. /// - private static int s_mshDefaultSerializationDepth = 1; + private static readonly int s_mshDefaultSerializationDepth = 1; } /// @@ -201,7 +199,7 @@ internal Serializer(XmlWriter writer) /// Writer to be used for serialization. /// Depth of serialization. /// - /// if true then types.ps1xml can override depth + /// if then types.ps1xml can override depth /// for a particular types (using SerializationDepth property) /// internal Serializer(XmlWriter writer, int depth, bool useDepthFromTypes) @@ -322,7 +320,7 @@ internal DeserializationContext(DeserializationOptions options, PSRemotingCrypto /// is used by PriorityReceivedDataCollection (remoting) to process incoming data from the /// remote end. A value of Null means that the max memory is unlimited. /// - internal int? MaximumAllowedMemory { set; get; } + internal int? MaximumAllowedMemory { get; set; } /// /// Logs that memory used by deserialized objects is not related to the size of input xml. @@ -346,7 +344,7 @@ internal void LogExtraMemoryUsage(int amountOfExtraMemory) throw new XmlException(message); } - _totalDataProcessedSoFar = _totalDataProcessedSoFar + amountOfExtraMemory; + _totalDataProcessedSoFar += amountOfExtraMemory; } } @@ -540,7 +538,7 @@ private void Start() // If version is not provided, we assume it is the default string version = InternalSerializer.DefaultVersion; - if (DeserializationOptions.NoRootElement == (_context.options & DeserializationOptions.NoRootElement)) + if ((_context.options & DeserializationOptions.NoRootElement) == DeserializationOptions.NoRootElement) { _done = _reader.EOF; } @@ -569,9 +567,9 @@ private void Start() internal bool Done() { - if (_done == false) + if (!_done) { - if (DeserializationOptions.NoRootElement == (_context.options & DeserializationOptions.NoRootElement)) + if ((_context.options & DeserializationOptions.NoRootElement) == DeserializationOptions.NoRootElement) { _done = _reader.EOF; } @@ -661,7 +659,7 @@ internal static void AddDeserializationPrefix(ref string type) /// /// /// - /// true if is either a live or deserialized instance of class or one of its subclasses; false otherwise. + /// if is either a live or deserialized instance of class or one of its subclasses; otherwise. internal static bool IsInstanceOfType(object o, Type type) { if (type == null) @@ -682,7 +680,7 @@ internal static bool IsInstanceOfType(object o, Type type) /// /// /// - /// true if is a deserialized instance of class or one of its subclasses; false otherwise. + /// if is a deserialized instance of class or one of its subclasses; otherwise. internal static bool IsDeserializedInstanceOfType(object o, Type type) { if (type == null) @@ -791,7 +789,7 @@ internal enum ContainerType List, Enumerable, None - }; + } /// /// This internal helper class provides methods for serializing mshObject. @@ -866,7 +864,7 @@ internal TypeTable TypeTable /// internal void Start() { - if (SerializationOptions.NoRootElement != (_context.options & SerializationOptions.NoRootElement)) + if ((_context.options & SerializationOptions.NoRootElement) != SerializationOptions.NoRootElement) { this.WriteStartElement(SerializationStrings.RootElementTag); this.WriteAttribute(SerializationStrings.VersionAttribute, InternalSerializer.DefaultVersion); @@ -878,7 +876,7 @@ internal void Start() /// internal void End() { - if (SerializationOptions.NoRootElement != (_context.options & SerializationOptions.NoRootElement)) + if ((_context.options & SerializationOptions.NoRootElement) != SerializationOptions.NoRootElement) { _writer.WriteEndElement(); } @@ -1543,7 +1541,7 @@ int depth _writer.WriteEndElement(); } - private static Lazy s_cimSerializer = new Lazy(CimSerializer.Create); + private static readonly Lazy s_cimSerializer = new Lazy(CimSerializer.Create); private void PrepareCimInstanceForSerialization(PSObject psObject, CimInstance cimInstance) { @@ -1610,8 +1608,8 @@ private void PrepareCimInstanceForSerialization(PSObject psObject, CimInstance c // ATTACH INSTANCE METADATA TO THE OBJECT BEING SERIALIZED List namesOfModifiedProperties = cimInstance .CimInstanceProperties - .Where(p => p.IsValueModified) - .Select(p => p.Name) + .Where(static p => p.IsValueModified) + .Select(static p => p.Name) .ToList(); if (namesOfModifiedProperties.Count != 0) { @@ -1893,9 +1891,8 @@ private Collection> ExtendedMembersCollection { get { - return _extendedMembersCollection ?? - (_extendedMembersCollection = - PSObject.GetMemberCollection(PSMemberViewTypes.Extended, _typeTable)); + return _extendedMembersCollection ??= + PSObject.GetMemberCollection(PSMemberViewTypes.Extended, _typeTable); } } @@ -1905,8 +1902,7 @@ private Collection> AllPropertiesCollection { get { - return _allPropertiesCollection ?? - (_allPropertiesCollection = PSObject.GetPropertyCollection(PSMemberViewTypes.All, _typeTable)); + return _allPropertiesCollection ??= PSObject.GetPropertyCollection(PSMemberViewTypes.All, _typeTable); } } @@ -1982,8 +1978,7 @@ int depth foreach (PSMemberInfo info in propertyCollection) { - PSProperty prop = info as PSProperty; - if (prop == null) + if (!(info is PSProperty prop)) { continue; } @@ -2311,7 +2306,7 @@ private int GetDepthOfSerialization(object source, int depth) return 1; } - if (0 != (_context.options & SerializationOptions.UseDepthFromTypes)) + if ((_context.options & SerializationOptions.UseDepthFromTypes) != 0) { // get the depth from the PSObject // NOTE: we assume that the depth out of the PSObject is > 0 @@ -2331,7 +2326,7 @@ private int GetDepthOfSerialization(object source, int depth) } } - if (0 != (_context.options & SerializationOptions.PreserveSerializationSettingOfOriginal)) + if ((_context.options & SerializationOptions.PreserveSerializationSettingOfOriginal) != 0) { if ((pso.IsDeserialized) && (depth <= 0)) { @@ -2751,7 +2746,7 @@ internal static void WriteSecureString(InternalSerializer serializer, string str private void WriteStartElement(string elementTag) { Dbg.Assert(!string.IsNullOrEmpty(elementTag), "Caller should validate the parameter"); - if (SerializationOptions.NoNamespace == (_context.options & SerializationOptions.NoNamespace)) + if ((_context.options & SerializationOptions.NoNamespace) == SerializationOptions.NoNamespace) { _writer.WriteStartElement(elementTag); } @@ -2829,7 +2824,7 @@ internal static string EncodeString(string s) /// /// This is the real workhorse that encodes strings. - /// See for more information. + /// See for more information. /// /// String to encode. /// IndexOfFirstEncodableCharacter. @@ -2909,7 +2904,7 @@ private void WriteEncodedElementString(string name, string value) value = EncodeString(value); - if (SerializationOptions.NoNamespace == (_context.options & SerializationOptions.NoNamespace)) + if ((_context.options & SerializationOptions.NoNamespace) == SerializationOptions.NoNamespace) { _writer.WriteElementString(name, value); } @@ -2958,6 +2953,10 @@ private bool UnknownTagsAllowed } } + [SuppressMessage( + "Performance", + "CA1822:Mark members as static", + Justification = "Accesses instance members in preprocessor branch.")] private bool DuplicateRefIdsAllowed { get @@ -3006,7 +3005,7 @@ internal InternalDeserializer(XmlReader reader, DeserializationContext context) #region Known CIMTypes - private static Lazy> s_knownCimArrayTypes = new Lazy>( + private static readonly Lazy> s_knownCimArrayTypes = new Lazy>( () => new HashSet { @@ -3197,7 +3196,7 @@ private void CheckIfStopping() internal const string CimHashCodeProperty = "Hash"; internal const string CimMiXmlProperty = "MiXml"; - private bool RehydrateCimInstanceProperty( + private static bool RehydrateCimInstanceProperty( CimInstance cimInstance, PSPropertyInfo deserializedProperty, HashSet namesOfModifiedProperties) @@ -3298,7 +3297,7 @@ private bool RehydrateCimInstanceProperty( return true; } - private static Lazy s_cimDeserializer = new Lazy(CimDeserializer.Create); + private static readonly Lazy s_cimDeserializer = new Lazy(CimDeserializer.Create); private CimClass RehydrateCimClass(PSPropertyInfo classMetadataProperty) { @@ -3331,32 +3330,28 @@ private CimClass RehydrateCimClass(PSPropertyInfo classMetadataProperty) PSObject psoDeserializedClass = PSObject.AsPSObject(deserializedClass); - PSPropertyInfo namespaceProperty = psoDeserializedClass.InstanceMembers[InternalDeserializer.CimNamespaceProperty] as PSPropertyInfo; - if (namespaceProperty == null) + if (!(psoDeserializedClass.InstanceMembers[InternalDeserializer.CimNamespaceProperty] is PSPropertyInfo namespaceProperty)) { return null; } string cimNamespace = namespaceProperty.Value as string; - PSPropertyInfo classNameProperty = psoDeserializedClass.InstanceMembers[InternalDeserializer.CimClassNameProperty] as PSPropertyInfo; - if (classNameProperty == null) + if (!(psoDeserializedClass.InstanceMembers[InternalDeserializer.CimClassNameProperty] is PSPropertyInfo classNameProperty)) { return null; } string cimClassName = classNameProperty.Value as string; - PSPropertyInfo computerNameProperty = psoDeserializedClass.InstanceMembers[InternalDeserializer.CimServerNameProperty] as PSPropertyInfo; - if (computerNameProperty == null) + if (!(psoDeserializedClass.InstanceMembers[InternalDeserializer.CimServerNameProperty] is PSPropertyInfo computerNameProperty)) { return null; } string computerName = computerNameProperty.Value as string; - PSPropertyInfo hashCodeProperty = psoDeserializedClass.InstanceMembers[InternalDeserializer.CimHashCodeProperty] as PSPropertyInfo; - if (hashCodeProperty == null) + if (!(psoDeserializedClass.InstanceMembers[InternalDeserializer.CimHashCodeProperty] is PSPropertyInfo hashCodeProperty)) { return null; } @@ -3473,8 +3468,7 @@ private PSObject RehydrateCimInstance(PSObject deserializedObject) { foreach (PSMemberInfo deserializedMemberInfo in deserializedObject.AdaptedMembers) { - PSPropertyInfo deserializedProperty = deserializedMemberInfo as PSPropertyInfo; - if (deserializedProperty == null) + if (!(deserializedMemberInfo is PSPropertyInfo deserializedProperty)) { continue; } @@ -3494,8 +3488,7 @@ private PSObject RehydrateCimInstance(PSObject deserializedObject) // process properties that were originally "extended" properties foreach (PSMemberInfo deserializedMemberInfo in deserializedObject.InstanceMembers) { - PSPropertyInfo deserializedProperty = deserializedMemberInfo as PSPropertyInfo; - if (deserializedProperty == null) + if (!(deserializedMemberInfo is PSPropertyInfo deserializedProperty)) { continue; } @@ -3622,7 +3615,7 @@ private PSObject ReadPSObject() PSObject dso = ReadAttributeAndCreatePSObject(); // Read start element tag - if (ReadStartElementAndHandleEmpty(SerializationStrings.PSObjectTag) == false) + if (!ReadStartElementAndHandleEmpty(SerializationStrings.PSObjectTag)) { // Empty element. return dso; @@ -4425,7 +4418,7 @@ internal static object DeserializeScriptBlock(InternalDeserializer deserializer) { Dbg.Assert(deserializer != null, "Caller should validate the parameter"); string scriptBlockBody = deserializer.ReadDecodedElementString(SerializationStrings.ScriptBlockTag); - if (DeserializationOptions.DeserializeScriptBlocks == (deserializer._context.options & DeserializationOptions.DeserializeScriptBlocks)) + if ((deserializer._context.options & DeserializationOptions.DeserializeScriptBlocks) == DeserializationOptions.DeserializeScriptBlocks) { return ScriptBlock.Create(scriptBlockBody); } @@ -4659,7 +4652,7 @@ internal static object DeserializeProgressRecord(InternalDeserializer deserializ activityId = int.Parse(deserializer.ReadDecodedElementString(SerializationStrings.ProgressRecordActivityId), CultureInfo.InvariantCulture); object tmp = deserializer.ReadOneObject(); - currentOperation = (tmp == null) ? null : tmp.ToString(); + currentOperation = tmp?.ToString(); parentActivityId = int.Parse(deserializer.ReadDecodedElementString(SerializationStrings.ProgressRecordParentActivityId), CultureInfo.InvariantCulture); percentComplete = int.Parse(deserializer.ReadDecodedElementString(SerializationStrings.ProgressRecordPercentComplete), CultureInfo.InvariantCulture); @@ -4742,7 +4735,7 @@ private bool IsNextElement(string tag) { Dbg.Assert(!string.IsNullOrEmpty(tag), "Caller should validate the parameter"); return (_reader.LocalName == tag) && - ((0 != (_context.options & DeserializationOptions.NoNamespace)) || + (((_context.options & DeserializationOptions.NoNamespace) != 0) || (_reader.NamespaceURI == SerializationStrings.MonadNamespace)); } @@ -4762,7 +4755,7 @@ internal bool ReadStartElementAndHandleEmpty(string element) // This takes care of the case: or . In // this case isEmpty is false. - if (isEmpty == false && _reader.NodeType == XmlNodeType.EndElement) + if (!isEmpty && _reader.NodeType == XmlNodeType.EndElement) { ReadEndElement(); isEmpty = true; @@ -4775,7 +4768,7 @@ private void ReadStartElement(string element) { Dbg.Assert(!string.IsNullOrEmpty(element), "Caller should validate the parameter"); - if (DeserializationOptions.NoNamespace == (_context.options & DeserializationOptions.NoNamespace)) + if ((_context.options & DeserializationOptions.NoNamespace) == DeserializationOptions.NoNamespace) { _reader.ReadStartElement(element); } @@ -4799,7 +4792,7 @@ private string ReadDecodedElementString(string element) this.CheckIfStopping(); string temp = null; - if (DeserializationOptions.NoNamespace == (_context.options & DeserializationOptions.NoNamespace)) + if ((_context.options & DeserializationOptions.NoNamespace) == DeserializationOptions.NoNamespace) { temp = _reader.ReadElementContentAsString(element, string.Empty); } @@ -4976,7 +4969,7 @@ internal string SetRefId(T t) } /// - /// Gets a RefId already assigned for the given object or null if there is no associated ref id. + /// Gets a RefId already assigned for the given object or if there is no associated ref id. /// /// /// @@ -5644,7 +5637,7 @@ internal static object GetPropertyValueInThreadSafeManner(PSPropertyInfo propert /// type of dictionary values internal class WeakReferenceDictionary : IDictionary { - private class WeakReferenceEqualityComparer : IEqualityComparer + private sealed class WeakReferenceEqualityComparer : IEqualityComparer { public bool Equals(WeakReference x, WeakReference y) { @@ -5937,7 +5930,7 @@ private PSPrimitiveDictionary(System.Runtime.Serialization.SerializationInfo inf #region Plumbing to make Hashtable reject all non-primitive types - private string VerifyKey(object key) + private static string VerifyKey(object key) { key = PSObject.Base(key); string keyAsString = key as string; @@ -6037,7 +6030,7 @@ private void VerifyValue(object value) /// public override void Add(object key, object value) { - string keyAsString = this.VerifyKey(key); + string keyAsString = VerifyKey(key); this.VerifyValue(value); base.Add(keyAsString, value); } @@ -6048,7 +6041,7 @@ public override void Add(object key, object value) /// The key whose value to get or set. /// The value associated with the specified key. /// - /// If the specified key is not found, attempting to get it returns null + /// If the specified key is not found, attempting to get it returns /// and attempting to set it creates a new element using the specified key. /// /// @@ -6065,7 +6058,7 @@ public override object this[object key] set { - string keyAsString = this.VerifyKey(key); + string keyAsString = VerifyKey(key); this.VerifyValue(value); base[keyAsString] = value; } @@ -6077,7 +6070,7 @@ public override object this[object key] /// The key whose value to get or set. /// The value associated with the specified key. /// - /// If the specified key is not found, attempting to get it returns null + /// If the specified key is not found, attempting to get it returns /// and attempting to set it creates a new element using the specified key. /// /// @@ -6539,7 +6532,7 @@ internal static PSPrimitiveDictionary CloneAndAddPSVersionTable(PSPrimitiveDicti /// The root dictionary. /// /// A chain of keys leading from the root dictionary () to the value. - /// true if the value was found and was of the correct type; false otherwise. + /// if the value was found and was of the correct type; otherwise. internal static bool TryPathGet(IDictionary data, out T result, params string[] keys) { Dbg.Assert(keys != null, "Caller should verify that keys != null"); @@ -6857,14 +6850,14 @@ internal static T GetPropertyValue(PSObject pso, string propertyName, Rehydra Dbg.Assert(!string.IsNullOrEmpty(propertyName), "Caller should verify propertyName != null"); PSPropertyInfo property = pso.Properties[propertyName]; - if ((property == null) && (RehydrationFlags.MissingPropertyOk == (flags & RehydrationFlags.MissingPropertyOk))) + if ((property == null) && ((flags & RehydrationFlags.MissingPropertyOk) == RehydrationFlags.MissingPropertyOk)) { return default(T); } else { object propertyValue = property.Value; - if ((propertyValue == null) && (RehydrationFlags.NullValueOk == (flags & RehydrationFlags.NullValueOk))) + if ((propertyValue == null) && ((flags & RehydrationFlags.NullValueOk) == RehydrationFlags.NullValueOk)) { return default(T); } @@ -6876,27 +6869,27 @@ internal static T GetPropertyValue(PSObject pso, string propertyName, Rehydra } } - private static ListType RehydrateList(PSObject pso, string propertyName, RehydrationFlags flags) - where ListType : IList, new() + private static TList RehydrateList(PSObject pso, string propertyName, RehydrationFlags flags) + where TList : IList, new() { ArrayList deserializedList = GetPropertyValue(pso, propertyName, flags); if (deserializedList == null) { - if (RehydrationFlags.NullValueMeansEmptyList == (flags & RehydrationFlags.NullValueMeansEmptyList)) + if ((flags & RehydrationFlags.NullValueMeansEmptyList) == RehydrationFlags.NullValueMeansEmptyList) { - return new ListType(); + return new TList(); } else { - return default(ListType); + return default(TList); } } else { - ListType newList = new ListType(); + TList newList = new TList(); foreach (object deserializedItem in deserializedList) { - ItemType item = (ItemType)LanguagePrimitives.ConvertTo(deserializedItem, typeof(ItemType), CultureInfo.InvariantCulture); + TItem item = (TItem)LanguagePrimitives.ConvertTo(deserializedItem, typeof(TItem), CultureInfo.InvariantCulture); newList.Add(item); } @@ -7279,8 +7272,7 @@ public static UInt32 GetParameterSetMetadataFlags(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - ParameterSetMetadata parameterSetMetadata = instance.BaseObject as ParameterSetMetadata; - if (parameterSetMetadata == null) + if (!(instance.BaseObject is ParameterSetMetadata parameterSetMetadata)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -7301,8 +7293,7 @@ public static PSObject GetInvocationInfo(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - DebuggerStopEventArgs dbgStopEventArgs = instance.BaseObject as DebuggerStopEventArgs; - if (dbgStopEventArgs == null) + if (!(instance.BaseObject is DebuggerStopEventArgs dbgStopEventArgs)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -7561,8 +7552,7 @@ public static Guid GetFormatViewDefinitionInstanceId(PSObject instance) throw PSTraceSource.NewArgumentNullException(nameof(instance)); } - FormatViewDefinition formatViewDefinition = instance.BaseObject as FormatViewDefinition; - if (formatViewDefinition == null) + if (!(instance.BaseObject is FormatViewDefinition formatViewDefinition)) { throw PSTraceSource.NewArgumentNullException(nameof(instance)); } @@ -7614,4 +7604,3 @@ private static ExtendedTypeDefinition RehydrateExtendedTypeDefinition(PSObject d #endregion } } - diff --git a/src/System.Management.Automation/help/AliasHelpInfo.cs b/src/System.Management.Automation/help/AliasHelpInfo.cs index b51d1b192dc..8ac441e4e60 100644 --- a/src/System.Management.Automation/help/AliasHelpInfo.cs +++ b/src/System.Management.Automation/help/AliasHelpInfo.cs @@ -8,7 +8,7 @@ namespace System.Management.Automation /// /// Stores help information related to Alias Commands. /// - internal class AliasHelpInfo : HelpInfo + internal sealed class AliasHelpInfo : HelpInfo { /// /// Initializes a new instance of the AliasHelpInfo class. @@ -70,7 +70,7 @@ internal override HelpCategory HelpCategory } } - private PSObject _fullHelpObject; + private readonly PSObject _fullHelpObject; /// /// Returns full help object for alias help. diff --git a/src/System.Management.Automation/help/AliasHelpProvider.cs b/src/System.Management.Automation/help/AliasHelpProvider.cs index 670c0202bc7..f14f815891a 100644 --- a/src/System.Management.Automation/help/AliasHelpProvider.cs +++ b/src/System.Management.Automation/help/AliasHelpProvider.cs @@ -40,7 +40,7 @@ internal AliasHelpProvider(HelpSystem helpSystem) : base(helpSystem) /// of wildcard search patterns. This is currently not achievable /// through _commandDiscovery. /// - private SessionState _sessionState; + private readonly SessionState _sessionState; /// /// Command Discovery object for current session. @@ -50,7 +50,7 @@ internal AliasHelpProvider(HelpSystem helpSystem) : base(helpSystem) /// The AliasInfo object returned from _commandDiscovery is essential /// in creating AliasHelpInfo. /// - private CommandDiscovery _commandDiscovery; + private readonly CommandDiscovery _commandDiscovery; #region Common Properties @@ -261,7 +261,7 @@ private static bool Match(HelpInfo helpInfo, HelpRequest helpRequest) if (helpRequest == null) return true; - if (0 == (helpRequest.HelpCategory & helpInfo.HelpCategory)) + if ((helpRequest.HelpCategory & helpInfo.HelpCategory) == 0) { return false; } diff --git a/src/System.Management.Automation/help/CabinetAPI.cs b/src/System.Management.Automation/help/CabinetAPI.cs index eb407f2ec62..9ccdc08baa6 100644 --- a/src/System.Management.Automation/help/CabinetAPI.cs +++ b/src/System.Management.Automation/help/CabinetAPI.cs @@ -78,9 +78,9 @@ internal abstract class ICabinetExtractorLoader /// /// Used to create a CabinetExtractor class. /// - internal class CabinetExtractorFactory + internal static class CabinetExtractorFactory { - private static ICabinetExtractorLoader s_cabinetLoader; + private static readonly ICabinetExtractorLoader s_cabinetLoader; internal static readonly ICabinetExtractor EmptyExtractor = new EmptyCabinetExtractor(); /// @@ -137,4 +137,3 @@ protected override void Dispose(bool disposing) } } } - diff --git a/src/System.Management.Automation/help/CabinetNativeApi.cs b/src/System.Management.Automation/help/CabinetNativeApi.cs index 833ed6506f0..76e8fe853a4 100644 --- a/src/System.Management.Automation/help/CabinetNativeApi.cs +++ b/src/System.Management.Automation/help/CabinetNativeApi.cs @@ -84,7 +84,7 @@ protected override void Dispose(bool disposing) } /// - /// Finalizer to ensure destruction of unmanaged resources. + /// Finalizes an instance of the class. /// ~CabinetExtractor() { @@ -164,7 +164,7 @@ private void CleanUpDelegates() _fdiNotifyHandle.Free(); } } - }; + } // CabinetExtractor loader implementation internal class CabinetExtractorLoader : ICabinetExtractorLoader @@ -175,7 +175,7 @@ internal class CabinetExtractorLoader : ICabinetExtractorLoader internal static CabinetExtractorLoader GetInstance() { - if (0 == System.Threading.Interlocked.CompareExchange(ref s_created, 1, 0)) + if (System.Threading.Interlocked.CompareExchange(ref s_created, 1, 0) == 0) { s_instance = new CabinetExtractorLoader(); s_extractorInstance = new CabinetExtractor(); @@ -188,7 +188,7 @@ internal override ICabinetExtractor GetCabinetExtractor() { return s_extractorInstance; } - }; + } internal static class CabinetNativeApi { @@ -458,27 +458,27 @@ internal static FileMode ConvertOpflagToFileMode(int oflag) { // Note: This is not done in a switch because the order of tests matters. - if ((int)(OpFlags.Create | OpFlags.Excl) == (oflag & (int)(OpFlags.Create | OpFlags.Excl))) + if ((oflag & (int)(OpFlags.Create | OpFlags.Excl)) == (int)(OpFlags.Create | OpFlags.Excl)) { return FileMode.CreateNew; } - else if ((int)(OpFlags.Create | OpFlags.Truncate) == (oflag & (int)(OpFlags.Create | OpFlags.Truncate))) + else if ((oflag & (int)(OpFlags.Create | OpFlags.Truncate)) == (int)(OpFlags.Create | OpFlags.Truncate)) { return FileMode.OpenOrCreate; } - else if (0 != (oflag & (int)OpFlags.Append)) + else if ((oflag & (int)OpFlags.Append) != 0) { return FileMode.Append; } - else if (0 != (oflag & (int)OpFlags.Create)) + else if ((oflag & (int)OpFlags.Create) != 0) { return FileMode.Create; } - else if (0 != (oflag & (int)OpFlags.RdWr)) + else if ((oflag & (int)OpFlags.RdWr) != 0) { return FileMode.Open; } - else if (0 != (oflag & (int)OpFlags.Truncate)) + else if ((oflag & (int)OpFlags.Truncate) != 0) { return FileMode.Truncate; } @@ -497,15 +497,15 @@ internal static FileAccess ConvertPermissionModeToFileAccess(int pmode) { // Note: This is not done in a switch because the order of tests matters. - if ((int)(PermissionMode.Read | PermissionMode.Write) == (pmode & (int)(PermissionMode.Read | PermissionMode.Write))) + if ((pmode & (int)(PermissionMode.Read | PermissionMode.Write)) == (int)(PermissionMode.Read | PermissionMode.Write)) { return FileAccess.ReadWrite; } - else if (0 != (pmode & (int)PermissionMode.Read)) + else if ((pmode & (int)PermissionMode.Read) != 0) { return FileAccess.Read; } - else if (0 != (pmode & (int)PermissionMode.Write)) + else if ((pmode & (int)PermissionMode.Write) != 0) { return FileAccess.Write; } @@ -524,15 +524,15 @@ internal static FileShare ConvertPermissionModeToFileShare(int pmode) { // Note: This is not done in a switch because the order of tests matters. - if ((int)(PermissionMode.Read | PermissionMode.Write) == (pmode & (int)(PermissionMode.Read | PermissionMode.Write))) + if ((pmode & (int)(PermissionMode.Read | PermissionMode.Write)) == (int)(PermissionMode.Read | PermissionMode.Write)) { return FileShare.ReadWrite; } - else if (0 != (pmode & (int)PermissionMode.Read)) + else if ((pmode & (int)PermissionMode.Read) != 0) { return FileShare.Read; } - else if (0 != (pmode & (int)PermissionMode.Write)) + else if ((pmode & (int)PermissionMode.Write) != 0) { return FileShare.Write; } @@ -589,7 +589,7 @@ internal class FdiNotification internal short iCabinet; // USHORT internal short iFolder; // USHORT internal int fdie; // FDIERROR - }; + } internal enum FdiNotificationType : int { @@ -607,7 +607,7 @@ internal class FdiERF internal int erfOper; internal int erfType; internal bool fError; - }; + } internal sealed class FdiContextHandle : SafeHandleZeroOrMinusOneIsInvalid { diff --git a/src/System.Management.Automation/help/CommandHelpProvider.cs b/src/System.Management.Automation/help/CommandHelpProvider.cs index 7dd893d2c7c..2abfbeaee22 100644 --- a/src/System.Management.Automation/help/CommandHelpProvider.cs +++ b/src/System.Management.Automation/help/CommandHelpProvider.cs @@ -48,7 +48,7 @@ static CommandHelpProvider() s_engineModuleHelpFileCache.Add("Microsoft.WSMan.Management", "Microsoft.Wsman.Management.dll-Help.xml"); } - private static Dictionary s_engineModuleHelpFileCache = new Dictionary(); + private static readonly Dictionary s_engineModuleHelpFileCache = new Dictionary(); private readonly ExecutionContext _context; @@ -84,7 +84,7 @@ internal override HelpCategory HelpCategory #region Help Provider Interface - private void GetModulePaths(CommandInfo commandInfo, out string moduleName, out string moduleDir, out string nestedModulePath) + private static void GetModulePaths(CommandInfo commandInfo, out string moduleName, out string moduleDir, out string nestedModulePath) { Dbg.Assert(commandInfo != null, "Caller should verify that commandInfo != null"); @@ -132,7 +132,7 @@ private void GetModulePaths(CommandInfo commandInfo, out string moduleName, out } } - private string GetHelpName(CommandInfo commandInfo) + private static string GetHelpName(CommandInfo commandInfo) { Dbg.Assert(commandInfo != null, "Caller should verify that commandInfo != null"); @@ -765,9 +765,7 @@ private void ProcessUserDefinedHelpData(string mshSnapInId, UserDefinedHelpData if (helpInfo == null) return; - MamlCommandHelpInfo commandHelpInfo = helpInfo as MamlCommandHelpInfo; - - if (commandHelpInfo == null) + if (!(helpInfo is MamlCommandHelpInfo commandHelpInfo)) return; commandHelpInfo.AddUserDefinedData(userDefinedHelpData); @@ -1024,7 +1022,7 @@ internal override IEnumerable SearchHelp(HelpRequest helpRequest, bool { if (decoratedSearch) { - if (target.IndexOf(StringLiterals.CommandVerbNounSeparator) >= 0) + if (target.Contains(StringLiterals.CommandVerbNounSeparator)) { patternList.Add(target + "*"); } @@ -1173,7 +1171,7 @@ private static bool Match(HelpInfo helpInfo, HelpRequest helpRequest, CommandInf if (helpRequest == null) return true; - if (0 == (helpRequest.HelpCategory & commandInfo.HelpCategory)) + if ((helpRequest.HelpCategory & commandInfo.HelpCategory) == 0) { return false; } @@ -1252,7 +1250,7 @@ private static bool Match(string target, ICollection patterns) /// The result helpInfo objects after processing. internal override IEnumerable ProcessForwardedHelp(HelpInfo helpInfo, HelpRequest helpRequest) { - HelpCategory categoriesHandled = (HelpCategory.Alias + const HelpCategory categoriesHandled = (HelpCategory.Alias | HelpCategory.ExternalScript | HelpCategory.Filter | HelpCategory.Function | HelpCategory.ScriptCommand); if ((helpInfo.HelpCategory & categoriesHandled) != 0) @@ -1361,7 +1359,7 @@ internal virtual CommandSearcher GetCommandSearcherForSearch(string pattern, Exe /// Legally, user-defined Help Data should be within the same file as the corresponding /// commandHelp and it should appear after the commandHelp. /// - internal class UserDefinedHelpData + internal sealed class UserDefinedHelpData { private UserDefinedHelpData() { diff --git a/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs b/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs index 8035e7e502a..34b1bd84cef 100644 --- a/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs +++ b/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs @@ -40,7 +40,7 @@ public int Compare(object x, object y) /// is present in the box. This class mimics the exact same structure as that of a MAML /// node, so that the default UX does not introduce regressions. /// - internal class DefaultCommandHelpObjectBuilder + internal static class DefaultCommandHelpObjectBuilder { internal static readonly string TypeNameForDefaultHelp = "ExtendedCmdletHelpInfo"; /// @@ -886,7 +886,7 @@ private static string GetPipelineInputString(ParameterAttribute paramAttrib) } } - sb.Append(")"); + sb.Append(')'); return sb.ToString(); } diff --git a/src/System.Management.Automation/help/DscResourceHelpProvider.cs b/src/System.Management.Automation/help/DscResourceHelpProvider.cs index c29ed02b456..42412926a47 100644 --- a/src/System.Management.Automation/help/DscResourceHelpProvider.cs +++ b/src/System.Management.Automation/help/DscResourceHelpProvider.cs @@ -279,7 +279,7 @@ private void LoadHelpFile(string helpFile, string helpFileIdentifier, string com } if (e != null) - s_tracer.WriteLine("Error occured in DscResourceHelpProvider {0}", e.Message); + s_tracer.WriteLine("Error occurred in DscResourceHelpProvider {0}", e.Message); if (reportErrors && (e != null)) { diff --git a/src/System.Management.Automation/help/HelpCategoryInvalidException.cs b/src/System.Management.Automation/help/HelpCategoryInvalidException.cs index 57e360bcc61..d9ccee7bae6 100644 --- a/src/System.Management.Automation/help/HelpCategoryInvalidException.cs +++ b/src/System.Management.Automation/help/HelpCategoryInvalidException.cs @@ -23,7 +23,8 @@ public class HelpCategoryInvalidException : ArgumentException, IContainsErrorRec /// Initializes a new instance of the HelpCategoryInvalidException class. /// /// The name of help category that is invalid. - public HelpCategoryInvalidException(string helpCategory) : base() + public HelpCategoryInvalidException(string helpCategory) + : base() { _helpCategory = helpCategory; CreateErrorRecord(); @@ -32,7 +33,8 @@ public HelpCategoryInvalidException(string helpCategory) : base() /// /// Initializes a new instance of the HelpCategoryInvalidException class. /// - public HelpCategoryInvalidException() : base() + public HelpCategoryInvalidException() + : base() { CreateErrorRecord(); } @@ -42,8 +44,10 @@ public HelpCategoryInvalidException() : base() /// /// The name of help category that is invalid. /// The inner exception of this exception. - public HelpCategoryInvalidException(string helpCategory, Exception innerException) : - base((innerException != null) ? innerException.Message : string.Empty, innerException) + public HelpCategoryInvalidException(string helpCategory, Exception innerException) + : base( + (innerException != null) ? innerException.Message : string.Empty, + innerException) { _helpCategory = helpCategory; CreateErrorRecord(); @@ -72,7 +76,7 @@ public ErrorRecord ErrorRecord } } - private string _helpCategory = System.Management.Automation.HelpCategory.None.ToString(); + private readonly string _helpCategory = System.Management.Automation.HelpCategory.None.ToString(); /// /// Gets name of the help category that is invalid. diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 852db86c267..00a9cca8ea8 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -68,7 +68,7 @@ public GetHelpCommand() IgnoreCase = true)] public string[] Category { get; set; } - private string _provider = string.Empty; + private readonly string _provider = string.Empty; /// /// Changes the view of HelpObject returned. @@ -185,6 +185,11 @@ public SwitchParameter Examples [Parameter(ParameterSetName = "Online", Mandatory = true)] public SwitchParameter Online { + get + { + return _showOnlineHelp; + } + set { _showOnlineHelp = value; @@ -193,11 +198,6 @@ public SwitchParameter Online VerifyParameterForbiddenInRemoteRunspace(this, "Online"); } } - - get - { - return _showOnlineHelp; - } } private bool _showOnlineHelp; @@ -262,7 +262,7 @@ protected override void ProcessRecord() this.graphicalHostReflectionWrapper = GraphicalHostReflectionWrapper.GetGraphicalHostReflectionWrapper(this, "Microsoft.PowerShell.Commands.Internal.HelpWindowHelper"); } #endif - helpSystem.OnProgress += new HelpSystem.HelpProgressHandler(HelpSystem_OnProgress); + helpSystem.OnProgress += HelpSystem_OnProgress; bool failed = false; HelpCategory helpCategory = ToHelpCategory(Category, ref failed); @@ -302,7 +302,7 @@ protected override void ProcessRecord() return; } - if (0 == countOfHelpInfos) + if (countOfHelpInfos == 0) { firstHelpInfoObject = helpInfo; } @@ -328,7 +328,7 @@ protected override void ProcessRecord() Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI.ReportGetHelpTelemetry(Name, countOfHelpInfos, _timer.ElapsedMilliseconds, _updatedHelp); #endif // Write full help as there is only one help info object - if (1 == countOfHelpInfos) + if (countOfHelpInfos == 1) { WriteObjectsOrShowOnlineHelp(firstHelpInfoObject, true); } @@ -354,7 +354,7 @@ protected override void ProcessRecord() } finally { - helpSystem.OnProgress -= new HelpSystem.HelpProgressHandler(HelpSystem_OnProgress); + helpSystem.OnProgress -= HelpSystem_OnProgress; HelpSystem_OnComplete(); // finally clear the ScriptBlockAst -> Token[] cache @@ -516,7 +516,7 @@ private void ValidateAndThrowIfError(HelpCategory cat) } // categories that support -Parameter, -Role, -Functionality, -Component parameters - HelpCategory supportedCategories = + const HelpCategory supportedCategories = HelpCategory.Alias | HelpCategory.Cmdlet | HelpCategory.ExternalScript | HelpCategory.Filter | HelpCategory.Function | HelpCategory.ScriptCommand; @@ -683,7 +683,7 @@ private void LaunchOnlineHelp(Uri uriToLaunch) #endregion - private void HelpSystem_OnProgress(object sender, HelpProgressInfo arg) + private void HelpSystem_OnProgress(object sender, HelpProgressEventArgs arg) { var record = new ProgressRecord(0, this.CommandInfo.Name, arg.Activity) { @@ -723,7 +723,7 @@ internal static void VerifyParameterForbiddenInRemoteRunspace(Cmdlet cmdlet, str #region trace [TraceSourceAttribute("GetHelpCommand ", "GetHelpCommand ")] - private static PSTraceSource s_tracer = PSTraceSource.GetTracer("GetHelpCommand ", "GetHelpCommand "); + private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("GetHelpCommand ", "GetHelpCommand "); #endregion } @@ -734,34 +734,38 @@ internal static void VerifyParameterForbiddenInRemoteRunspace(Cmdlet cmdlet, str public static class GetHelpCodeMethods { /// - /// Verifies if the InitialSessionState of the current process. - /// - /// + /// Checks whether the default runspace associated with the current thread has the standard Get-Help cmdlet. + /// + /// True if Get-Help is found, false otherwise. private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() { - InitialSessionState iss = - System.Management.Automation.Runspaces.Runspace.DefaultRunspace.InitialSessionState; - if (iss != null) - { - IEnumerable publicGetHelpEntries = iss - .Commands["Get-Help"] - .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); - if (publicGetHelpEntries.Count() != 1) + InitialSessionState iss = Runspace.DefaultRunspace.InitialSessionState; + if (iss is null) + { + return false; + } + + Collection getHelpEntries = iss.Commands["Get-Help"]; + SessionStateCommandEntry getHelpEntry = null; + for (int i = 0; i < getHelpEntries.Count; ++i) + { + if (getHelpEntries[i].Visibility is not SessionStateEntryVisibility.Public) { - return false; + continue; } - foreach (SessionStateCommandEntry getHelpEntry in publicGetHelpEntries) + // If we have multiple entries for Get-Help, + // our assumption is that the standard Get-Help is not available. + if (getHelpEntry is not null) { - SessionStateCmdletEntry getHelpCmdlet = getHelpEntry as SessionStateCmdletEntry; - if ((getHelpCmdlet != null) && (getHelpCmdlet.ImplementingType.Equals(typeof(GetHelpCommand)))) - { - return true; - } + return false; } + + getHelpEntry = getHelpEntries[i]; } - return false; + return getHelpEntry is SessionStateCmdletEntry getHelpCmdlet + && getHelpCmdlet.ImplementingType == typeof(GetHelpCommand); } /// @@ -835,7 +839,7 @@ public static string GetHelpUri(PSObject commandInfoPSObject) foreach ( Uri result in currentContext.HelpSystem.ExactMatchHelp(helpRequest).Select( - helpInfo => helpInfo.GetUriForOnlineHelp()).Where(result => result != null)) + helpInfo => helpInfo.GetUriForOnlineHelp()).Where(static result => result != null)) { return result.OriginalString; } @@ -888,4 +892,3 @@ Uri result in } } } - diff --git a/src/System.Management.Automation/help/HelpCommentsParser.cs b/src/System.Management.Automation/help/HelpCommentsParser.cs index 77347527ab4..36d0cb6450e 100644 --- a/src/System.Management.Automation/help/HelpCommentsParser.cs +++ b/src/System.Management.Automation/help/HelpCommentsParser.cs @@ -20,7 +20,7 @@ namespace System.Management.Automation /// /// Parses help comments and turns them into HelpInfo objects. /// - internal class HelpCommentsParser + internal sealed class HelpCommentsParser { private HelpCommentsParser() { @@ -61,10 +61,10 @@ private HelpCommentsParser(CommandInfo commandInfo, List parameterDescri private readonly List _links = new List(); internal bool isExternalHelpSet = false; - private ScriptBlock _scriptBlock; - private CommandMetadata _commandMetadata; - private string _commandName; - private List _parameterDescriptions; + private readonly ScriptBlock _scriptBlock; + private readonly CommandMetadata _commandMetadata; + private readonly string _commandName; + private readonly List _parameterDescriptions; private XmlDocument _doc; internal static readonly string mshURI = "http://msh"; internal static readonly string mamlURI = "http://schemas.microsoft.com/maml/2004/10"; @@ -448,7 +448,7 @@ internal XmlDocument BuildXmlFromComments() foreach (string link in _links) { XmlElement navigationLink = _doc.CreateElement("maml:navigationLink", mamlURI); - bool isOnlineHelp = Uri.IsWellFormedUriString(Uri.EscapeUriString(link), UriKind.Absolute); + bool isOnlineHelp = Uri.IsWellFormedUriString(link, UriKind.Absolute); string nodeName = isOnlineHelp ? "maml:uri" : "maml:linkText"; XmlElement linkText = _doc.CreateElement(nodeName, mamlURI); XmlText linkText_text = _doc.CreateTextNode(link); @@ -482,7 +482,7 @@ private void BuildSyntaxForParameterSet(XmlElement command, XmlElement syntax, M CompiledCommandParameter parameter = mergedParameter.Parameter; ParameterSetSpecificMetadata parameterSetData = parameter.GetParameterSetData(1u << i); string description = GetParameterDescription(parameter.Name); - bool supportsWildcards = parameter.CompiledAttributes.Any(attribute => attribute is SupportsWildcardsAttribute); + bool supportsWildcards = parameter.CompiledAttributes.Any(static attribute => attribute is SupportsWildcardsAttribute); XmlElement parameterElement = BuildXmlForParameter(parameter.Name, parameterSetData.IsMandatory, parameterSetData.ValueFromPipeline, parameterSetData.ValueFromPipelineByPropertyName, @@ -496,7 +496,7 @@ private void BuildSyntaxForParameterSet(XmlElement command, XmlElement syntax, M private static void GetExampleSections(string content, out string prompt_str, out string code_str, out string remarks_str) { - string default_prompt_str = "PS > "; + const string default_prompt_str = "PS > "; var promptMatch = Regex.Match(content, "^.*?>"); prompt_str = promptMatch.Success ? promptMatch.Value : default_prompt_str; @@ -628,7 +628,7 @@ private static string GetSection(List commentLines, ref int i) start++; } - sb.Append(line.Substring(start)); + sb.Append(line.AsSpan(start)); sb.Append('\n'); } diff --git a/src/System.Management.Automation/help/HelpErrorTracer.cs b/src/System.Management.Automation/help/HelpErrorTracer.cs index 9c9fd0165b5..e5a9fea9e67 100644 --- a/src/System.Management.Automation/help/HelpErrorTracer.cs +++ b/src/System.Management.Automation/help/HelpErrorTracer.cs @@ -52,12 +52,12 @@ internal class HelpErrorTracer internal sealed class TraceFrame : IDisposable { // Following are help context information - private string _helpFile = string.Empty; + private readonly string _helpFile = string.Empty; // ErrorRecords accumulated during the help content loading. - private Collection _errors = new Collection(); + private readonly Collection _errors = new Collection(); - private HelpErrorTracer _helpTracer; + private readonly HelpErrorTracer _helpTracer; /// /// Constructor. Here help context information will be collected. /// diff --git a/src/System.Management.Automation/help/HelpFileHelpInfo.cs b/src/System.Management.Automation/help/HelpFileHelpInfo.cs index 1df1b70411b..104111777ef 100644 --- a/src/System.Management.Automation/help/HelpFileHelpInfo.cs +++ b/src/System.Management.Automation/help/HelpFileHelpInfo.cs @@ -9,7 +9,7 @@ namespace System.Management.Automation /// Class HelpFileHelpInfo keeps track of help information to be returned by /// command help provider. /// - internal class HelpFileHelpInfo : HelpInfo + internal sealed class HelpFileHelpInfo : HelpInfo { /// /// Constructor for HelpFileHelpInfo. @@ -50,8 +50,8 @@ private HelpFileHelpInfo(string name, string text, string filename) /// Name for the help info internal override string Name { get; } = string.Empty; - private string _filename = string.Empty; - private string _synopsis = string.Empty; + private readonly string _filename = string.Empty; + private readonly string _synopsis = string.Empty; /// /// Synopsis for the help info. /// diff --git a/src/System.Management.Automation/help/HelpFileHelpProvider.cs b/src/System.Management.Automation/help/HelpFileHelpProvider.cs index 2c527d2f95a..4591ddbf863 100644 --- a/src/System.Management.Automation/help/HelpFileHelpProvider.cs +++ b/src/System.Management.Automation/help/HelpFileHelpProvider.cs @@ -268,7 +268,7 @@ internal override IEnumerable SearchHelp(HelpRequest helpRequest, bool } } - private void GetModuleNameAndVersion(string psmodulePathRoot, string filePath, out string moduleName, out Version moduleVersion) + private static void GetModuleNameAndVersion(string psmodulePathRoot, string filePath, out string moduleName, out Version moduleVersion) { moduleVersion = null; moduleName = null; @@ -368,9 +368,9 @@ internal Collection GetExtendedSearchPaths() { // Get all the directories under the module path // * and SearchOption.AllDirectories gets all the version directories. - string[] directories = Directory.GetDirectories(psModulePath, "*", SearchOption.AllDirectories); + IEnumerable directories = Directory.EnumerateDirectories(psModulePath, "*", SearchOption.AllDirectories); - var possibleModuleDirectories = directories.Where(directory => !ModuleUtils.IsPossibleResourceDirectory(directory)); + var possibleModuleDirectories = directories.Where(static directory => !ModuleUtils.IsPossibleResourceDirectory(directory)); foreach (string directory in possibleModuleDirectories) { @@ -415,9 +415,8 @@ internal override void Reset() /// /// This will avoid one help file getting loaded again and again. /// - private Hashtable _helpFiles = new Hashtable(); + private readonly Hashtable _helpFiles = new Hashtable(); #endregion } } - diff --git a/src/System.Management.Automation/help/HelpNotFoundException.cs b/src/System.Management.Automation/help/HelpNotFoundException.cs index b604156b5cd..6008b4afbc1 100644 --- a/src/System.Management.Automation/help/HelpNotFoundException.cs +++ b/src/System.Management.Automation/help/HelpNotFoundException.cs @@ -22,7 +22,8 @@ public class HelpNotFoundException : SystemException, IContainsErrorRecord /// Initializes a new instance of the HelpNotFoundException class with the give help topic. /// /// The help topic for which help is not found. - public HelpNotFoundException(string helpTopic) : base() + public HelpNotFoundException(string helpTopic) + : base() { _helpTopic = helpTopic; CreateErrorRecord(); @@ -31,7 +32,8 @@ public HelpNotFoundException(string helpTopic) : base() /// /// Initializes a new instance of the HelpNotFoundException class. /// - public HelpNotFoundException() : base() + public HelpNotFoundException() + : base() { CreateErrorRecord(); } @@ -42,8 +44,10 @@ public HelpNotFoundException() : base() /// /// The help topic for which help is not found. /// The inner exception. - public HelpNotFoundException(string helpTopic, Exception innerException) : - base((innerException != null) ? innerException.Message : string.Empty, innerException) + public HelpNotFoundException(string helpTopic, Exception innerException) + : base( + (innerException != null) ? innerException.Message : string.Empty, + innerException) { _helpTopic = helpTopic; CreateErrorRecord(); @@ -77,7 +81,7 @@ public ErrorRecord ErrorRecord } } - private string _helpTopic = string.Empty; + private readonly string _helpTopic = string.Empty; /// /// Gets help topic for which help is not found. diff --git a/src/System.Management.Automation/help/HelpProvider.cs b/src/System.Management.Automation/help/HelpProvider.cs index 76ce3168432..3280a8d2540 100644 --- a/src/System.Management.Automation/help/HelpProvider.cs +++ b/src/System.Management.Automation/help/HelpProvider.cs @@ -50,7 +50,7 @@ internal HelpProvider(HelpSystem helpSystem) _helpSystem = helpSystem; } - private HelpSystem _helpSystem; + private readonly HelpSystem _helpSystem; internal HelpSystem HelpSystem { @@ -175,7 +175,7 @@ internal virtual IEnumerable ProcessForwardedHelp(HelpInfo helpInfo, H { // Win8: 508648. Remove the current provides category for resolving forward help as the current // help provider already process it. - helpInfo.ForwardHelpCategory = helpInfo.ForwardHelpCategory ^ this.HelpCategory; + helpInfo.ForwardHelpCategory ^= this.HelpCategory; yield return helpInfo; } @@ -226,8 +226,7 @@ internal string GetDefaultShellSearchPath() string shellID = this.HelpSystem.ExecutionContext.ShellID; // Beginning in PowerShell 6.0.0.12, the $pshome is no longer registry specified, we search the application base instead. // We use executing assemblies location in case registry entry not found - return Utils.GetApplicationBase(shellID) - ?? Path.GetDirectoryName(PsUtils.GetMainModule(System.Diagnostics.Process.GetCurrentProcess()).FileName); + return Utils.GetApplicationBase(shellID) ?? Path.GetDirectoryName(Environment.ProcessPath); } /// diff --git a/src/System.Management.Automation/help/HelpProviderWithCache.cs b/src/System.Management.Automation/help/HelpProviderWithCache.cs index 99dc3fa7a19..495ec6a0b5d 100644 --- a/src/System.Management.Automation/help/HelpProviderWithCache.cs +++ b/src/System.Management.Automation/help/HelpProviderWithCache.cs @@ -28,7 +28,7 @@ internal HelpProviderWithCache(HelpSystem helpSystem) : base(helpSystem) /// /// This hashtable is made case-insensitive so that helpInfo can be retrieved case insensitively. /// - private Hashtable _helpCache = new Hashtable(StringComparer.OrdinalIgnoreCase); + private readonly Hashtable _helpCache = new Hashtable(StringComparer.OrdinalIgnoreCase); /// /// Exact match help for a target. diff --git a/src/System.Management.Automation/help/HelpSystem.cs b/src/System.Management.Automation/help/HelpSystem.cs index a022027ce78..a7c86bd5ebd 100644 --- a/src/System.Management.Automation/help/HelpSystem.cs +++ b/src/System.Management.Automation/help/HelpSystem.cs @@ -103,7 +103,7 @@ internal HelpSystem(ExecutionContext context) Initialize(); } - private ExecutionContext _executionContext; + private readonly ExecutionContext _executionContext; /// /// ExecutionContext for the help system. Different help providers @@ -121,9 +121,7 @@ internal ExecutionContext ExecutionContext #region Progress Callback - internal delegate void HelpProgressHandler(object sender, HelpProgressInfo arg); - - internal event HelpProgressHandler OnProgress; + internal event EventHandler OnProgress; #endregion @@ -173,7 +171,7 @@ internal IEnumerable GetHelp(HelpRequest helpRequest) #region Error Handling - private Collection _lastErrors = new Collection(); + private readonly Collection _lastErrors = new Collection(); /// /// This is for tracking the last set of errors happened during the help @@ -463,7 +461,7 @@ private IEnumerable SearchHelp(HelpRequest helpRequest) bool searchInHelpContent = false; bool shouldBreak = false; - HelpProgressInfo progress = new HelpProgressInfo(); + HelpProgressEventArgs progress = new HelpProgressEventArgs(); progress.Activity = StringUtil.Format(HelpDisplayStrings.SearchingForHelpContent, helpRequest.Target); progress.Completed = false; @@ -540,7 +538,7 @@ private IEnumerable SearchHelp(HelpRequest helpRequest) #region Help Provider Manager - private ArrayList _helpProviders = new ArrayList(); + private readonly ArrayList _helpProviders = new ArrayList(); /// /// Return the list of help providers initialized. @@ -802,11 +800,13 @@ internal void ClearScriptBlockTokenCache() /// /// Help progress info. /// - internal class HelpProgressInfo + internal class HelpProgressEventArgs : EventArgs { - internal bool Completed; - internal string Activity; - internal int PercentComplete; + internal bool Completed { get; set; } + + internal string Activity { get; set; } + + internal int PercentComplete { get; set; } } /// diff --git a/src/System.Management.Automation/help/HelpUtils.cs b/src/System.Management.Automation/help/HelpUtils.cs index 0c0770173be..d4f2abe255b 100644 --- a/src/System.Management.Automation/help/HelpUtils.cs +++ b/src/System.Management.Automation/help/HelpUtils.cs @@ -9,7 +9,7 @@ namespace System.Management.Automation { - internal class HelpUtils + internal static class HelpUtils { private static string userHomeHelpPath = null; diff --git a/src/System.Management.Automation/help/MUIFileSearcher.cs b/src/System.Management.Automation/help/MUIFileSearcher.cs index 2101e268dc1..1873a341c42 100644 --- a/src/System.Management.Automation/help/MUIFileSearcher.cs +++ b/src/System.Management.Automation/help/MUIFileSearcher.cs @@ -10,7 +10,7 @@ namespace System.Management.Automation { - internal class MUIFileSearcher + internal sealed class MUIFileSearcher { /// /// Constructor. It is private so that MUIFileSearcher is used only internal for this class. @@ -86,7 +86,7 @@ internal Collection Result /// _uniqueMatches is used to track matches already found during the search process. /// This is useful for ignoring duplicates in the case of unique search. /// - private Hashtable _uniqueMatches = new Hashtable(StringComparer.OrdinalIgnoreCase); + private readonly Hashtable _uniqueMatches = new Hashtable(StringComparer.OrdinalIgnoreCase); /// /// Search for files using the target, searchPaths member of this class. @@ -113,7 +113,7 @@ private void SearchForFiles() } } - private string[] GetFiles(string path, string pattern) + private static string[] GetFiles(string path, string pattern) { #if UNIX // On Linux, file names are case sensitive, so we need to add @@ -127,7 +127,7 @@ private string[] GetFiles(string path, string pattern) foreach (string filePath in files) { - if (filePath.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0) + if (filePath.Contains(pattern, StringComparison.OrdinalIgnoreCase)) { result.Add(filePath); break; @@ -372,4 +372,3 @@ internal enum SearchMode Unique } } - diff --git a/src/System.Management.Automation/help/MamlClassHelpInfo.cs b/src/System.Management.Automation/help/MamlClassHelpInfo.cs index 002eecb3bfe..042ab21e703 100644 --- a/src/System.Management.Automation/help/MamlClassHelpInfo.cs +++ b/src/System.Management.Automation/help/MamlClassHelpInfo.cs @@ -42,7 +42,7 @@ private MamlClassHelpInfo(XmlNode xmlNode, HelpCategory helpCategory) /// /// PSObject representation on help. /// - private PSObject _fullHelpObject; + private readonly PSObject _fullHelpObject; #region Load diff --git a/src/System.Management.Automation/help/MamlCommandHelpInfo.cs b/src/System.Management.Automation/help/MamlCommandHelpInfo.cs index 998e647cd05..774ef1fc1c0 100644 --- a/src/System.Management.Automation/help/MamlCommandHelpInfo.cs +++ b/src/System.Management.Automation/help/MamlCommandHelpInfo.cs @@ -98,7 +98,7 @@ internal void OverrideProviderSpecificHelpWithGenericHelp(HelpInfo genericHelpIn #region Basic Help Properties - private PSObject _fullHelpObject; + private readonly PSObject _fullHelpObject; /// /// Full help object for this help item. diff --git a/src/System.Management.Automation/help/MamlNode.cs b/src/System.Management.Automation/help/MamlNode.cs index 51fda0bc244..8f8df05bb79 100644 --- a/src/System.Management.Automation/help/MamlNode.cs +++ b/src/System.Management.Automation/help/MamlNode.cs @@ -74,7 +74,7 @@ internal MamlNode(XmlNode xmlNode) _xmlNode = xmlNode; } - private XmlNode _xmlNode; + private readonly XmlNode _xmlNode; /// /// Underline xmlNode for this MamlNode object. @@ -123,7 +123,7 @@ internal PSObject PSObject /// /// In this case, an PSObject that wraps string "atomic xml text" will be returned with following properties /// attribute => name - /// 3. Composite xml, which is an xmlNode with structured child nodes, but not a special case for Maml formating. + /// 3. Composite xml, which is an xmlNode with structured child nodes, but not a special case for Maml formatting. /// /// /// single child node text @@ -646,7 +646,7 @@ private PSObject[] GetMamlFormattingPSObjects(XmlNode xmlNode) /// /// /// - private int GetParaMamlNodeCount(XmlNodeList nodes) + private static int GetParaMamlNodeCount(XmlNodeList nodes) { int i = 0; diff --git a/src/System.Management.Automation/help/MamlUtil.cs b/src/System.Management.Automation/help/MamlUtil.cs index 7ace664b728..d809655f97f 100644 --- a/src/System.Management.Automation/help/MamlUtil.cs +++ b/src/System.Management.Automation/help/MamlUtil.cs @@ -9,7 +9,7 @@ namespace System.Management.Automation /// /// The MamlUtil class. /// - internal class MamlUtil + internal static class MamlUtil { /// /// Takes Name value from maml2 and overrides it in maml1. @@ -206,7 +206,7 @@ internal static PSPropertyInfo GetPropertyInfo(PSObject psObject, string[] path) return propertyInfo; } - if (propertyInfo == null || !(propertyInfo.Value is PSObject)) + if (propertyInfo == null || propertyInfo.Value is not PSObject) { return null; } @@ -317,7 +317,7 @@ internal static void EnsurePropertyInfoPathExists(PSObject psObject, string[] pa } // If we are not on the last path element, let's make sure we can extend the path. - if (propertyInfo.Value == null || !(propertyInfo.Value is PSObject)) + if (propertyInfo.Value == null || propertyInfo.Value is not PSObject) { propertyInfo.Value = new PSObject(); } diff --git a/src/System.Management.Automation/help/PSClassHelpProvider.cs b/src/System.Management.Automation/help/PSClassHelpProvider.cs index ee65529a026..e4c74c6398a 100644 --- a/src/System.Management.Automation/help/PSClassHelpProvider.cs +++ b/src/System.Management.Automation/help/PSClassHelpProvider.cs @@ -80,11 +80,9 @@ internal override IEnumerable SearchHelp(HelpRequest helpRequest, bool else patternList.Add(target); - bool useWildCards = true; - foreach (string pattern in patternList) { - PSClassSearcher searcher = new PSClassSearcher(pattern, useWildCards, _context); + PSClassSearcher searcher = new PSClassSearcher(pattern, useWildCards: true, _context); foreach (var helpInfo in GetHelpInfo(searcher)) { @@ -108,10 +106,7 @@ internal override IEnumerable ExactMatchHelp(HelpRequest helpRequest) yield return null; } - string target = helpRequest.Target; - bool useWildCards = false; - - PSClassSearcher searcher = new PSClassSearcher(target, useWildCards, _context); + PSClassSearcher searcher = new PSClassSearcher(helpRequest.Target, useWildCards: false, _context); foreach (var helpInfo in GetHelpInfo(searcher)) { diff --git a/src/System.Management.Automation/help/ProviderCommandHelpInfo.cs b/src/System.Management.Automation/help/ProviderCommandHelpInfo.cs index 6d9bedf4fac..d51fb716b82 100644 --- a/src/System.Management.Automation/help/ProviderCommandHelpInfo.cs +++ b/src/System.Management.Automation/help/ProviderCommandHelpInfo.cs @@ -13,7 +13,7 @@ internal class ProviderCommandHelpInfo : HelpInfo /// /// Help info. /// - private HelpInfo _helpInfo; + private readonly HelpInfo _helpInfo; /// /// Constructor for ProviderCommandHelpInfo. diff --git a/src/System.Management.Automation/help/ProviderContext.cs b/src/System.Management.Automation/help/ProviderContext.cs index 184ad5526fa..cb24ece0593 100644 --- a/src/System.Management.Automation/help/ProviderContext.cs +++ b/src/System.Management.Automation/help/ProviderContext.cs @@ -108,11 +108,9 @@ internal MamlCommandHelpInfo GetProviderSpecificHelpInfo(string helpItemName) // Does the provider know how to generate MAML. CmdletProvider cmdletProvider = providerInfo.CreateInstance(); - ICmdletProviderSupportsHelp provider = cmdletProvider as ICmdletProviderSupportsHelp; - - // Under JEA sessions the resolvedProviderPath will be null, we should allow get-help to continue. - if (provider == null) + if (!(cmdletProvider is ICmdletProviderSupportsHelp provider)) { + // Under JEA sessions the resolvedProviderPath will be null, we should allow get-help to continue. return null; } diff --git a/src/System.Management.Automation/help/ProviderHelpInfo.cs b/src/System.Management.Automation/help/ProviderHelpInfo.cs index 39eebe0c23a..01ae3729420 100644 --- a/src/System.Management.Automation/help/ProviderHelpInfo.cs +++ b/src/System.Management.Automation/help/ProviderHelpInfo.cs @@ -10,7 +10,7 @@ namespace System.Management.Automation /// Class ProviderHelpInfo keeps track of help information to be returned by /// command help provider. /// - internal class ProviderHelpInfo : HelpInfo + internal sealed class ProviderHelpInfo : HelpInfo { /// /// Constructor for HelpProvider. @@ -136,7 +136,7 @@ internal override HelpCategory HelpCategory } } - private PSObject _fullHelpObject; + private readonly PSObject _fullHelpObject; /// /// Full help object for this provider help info. diff --git a/src/System.Management.Automation/help/RemoteHelpInfo.cs b/src/System.Management.Automation/help/RemoteHelpInfo.cs index a80ba7a7736..1aa113dd86b 100644 --- a/src/System.Management.Automation/help/RemoteHelpInfo.cs +++ b/src/System.Management.Automation/help/RemoteHelpInfo.cs @@ -13,7 +13,7 @@ namespace System.Management.Automation /// internal class RemoteHelpInfo : BaseCommandHelpInfo { - private PSObject _deserializedRemoteHelp; + private readonly PSObject _deserializedRemoteHelp; internal RemoteHelpInfo( ExecutionContext context, diff --git a/src/System.Management.Automation/help/SaveHelpCommand.cs b/src/System.Management.Automation/help/SaveHelpCommand.cs index 3c4d18af00a..94803728c99 100644 --- a/src/System.Management.Automation/help/SaveHelpCommand.cs +++ b/src/System.Management.Automation/help/SaveHelpCommand.cs @@ -188,7 +188,7 @@ internal override bool ProcessModuleWithCulture(UpdatableHelpModuleInfo module, if (_credential != null) { - if (path.Contains("*")) + if (path.Contains('*')) { // Deal with wildcards @@ -484,7 +484,7 @@ public override object Transform(EngineIntrinsics engineIntrinsics, object input return inputData; } - private bool TryConvertFromDeserializedModuleInfo(object inputData, out PSModuleInfo moduleInfo) + private static bool TryConvertFromDeserializedModuleInfo(object inputData, out PSModuleInfo moduleInfo) { moduleInfo = null; PSObject pso = inputData as PSObject; diff --git a/src/System.Management.Automation/help/SyntaxHelpInfo.cs b/src/System.Management.Automation/help/SyntaxHelpInfo.cs index 469ab94a913..261fdd7f849 100644 --- a/src/System.Management.Automation/help/SyntaxHelpInfo.cs +++ b/src/System.Management.Automation/help/SyntaxHelpInfo.cs @@ -7,7 +7,7 @@ namespace System.Management.Automation /// Class HelpFileHelpInfo keeps track of help information to be returned by /// command help provider. /// - internal class SyntaxHelpInfo : BaseCommandHelpInfo + internal sealed class SyntaxHelpInfo : BaseCommandHelpInfo { /// /// Constructor for SyntaxHelpInfo. diff --git a/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs b/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs index e9f601aba52..49d1e67e5d9 100644 --- a/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs +++ b/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs @@ -31,7 +31,7 @@ public class UpdatableHelpCommandBase : PSCmdlet internal bool _stopping; internal int activityId; - private Dictionary _exceptions; + private readonly Dictionary _exceptions; #region Parameters @@ -102,7 +102,7 @@ public SwitchParameter UseDefaultCredentials } } - internal bool _useDefaultCredentials = false; + private bool _useDefaultCredentials = false; /// /// Forces the operation to complete. @@ -161,7 +161,7 @@ private void HandleProgressChanged(object sender, UpdatableHelpProgressEventArgs #region Constructor - private static Dictionary s_metadataCache; + private static readonly Dictionary s_metadataCache; /// /// Static constructor @@ -299,9 +299,9 @@ private Dictionary, UpdatableHelpModuleInfo> GetModuleInf } } - // Match wildcards - WildcardOptions wildcardOptions = WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant; - IEnumerable patternList = SessionStateUtilities.CreateWildcardsFromStrings(new string[1] { moduleNamePattern }, wildcardOptions); + IEnumerable patternList = SessionStateUtilities.CreateWildcardsFromStrings( + globPatterns: new[] { moduleNamePattern }, + options: WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); foreach (KeyValuePair name in s_metadataCache) { @@ -397,7 +397,7 @@ protected override void EndProcessing() /// FullyQualifiedNames. internal void Process(IEnumerable moduleNames, IEnumerable fullyQualifiedNames) { - _helpSystem.WebClient.UseDefaultCredentials = _useDefaultCredentials; + _helpSystem.UseDefaultCredentials = _useDefaultCredentials; if (moduleNames != null) { @@ -784,7 +784,7 @@ private IEnumerable RecursiveResolvePathHelper(string path) { yield return path; - foreach (string subDirectory in Directory.GetDirectories(path)) + foreach (string subDirectory in Directory.EnumerateDirectories(path)) { foreach (string subDirectory2 in RecursiveResolvePathHelper(subDirectory)) { diff --git a/src/System.Management.Automation/help/UpdatableHelpModuleInfo.cs b/src/System.Management.Automation/help/UpdatableHelpModuleInfo.cs index 6da6c256dc5..b46717920f4 100644 --- a/src/System.Management.Automation/help/UpdatableHelpModuleInfo.cs +++ b/src/System.Management.Automation/help/UpdatableHelpModuleInfo.cs @@ -54,7 +54,7 @@ internal Guid ModuleGuid } } - private Guid _moduleGuid; + private readonly Guid _moduleGuid; /// /// Module path. diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index 0a45b9a7605..31fe5362d77 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -233,14 +233,16 @@ internal UpdatableHelpProgressEventArgs(string moduleName, UpdatableHelpCommandT /// internal class UpdatableHelpSystem : IDisposable { - private TimeSpan _defaultTimeout; - private Collection _progressEvents; + private readonly TimeSpan _defaultTimeout; + private readonly Collection _progressEvents; private bool _stopping; - private object _syncObject; - private UpdatableHelpCommandBase _cmdlet; - private CancellationTokenSource _cancelTokenSource; + private readonly object _syncObject; + private readonly UpdatableHelpCommandBase _cmdlet; + private readonly CancellationTokenSource _cancelTokenSource; - internal WebClient WebClient { get; } + internal HttpClient HttpClient { get; } + + internal bool UseDefaultCredentials; internal string CurrentModule { get; set; } @@ -249,7 +251,7 @@ internal class UpdatableHelpSystem : IDisposable /// internal UpdatableHelpSystem(UpdatableHelpCommandBase cmdlet, bool useDefaultCredentials) { - WebClient = new WebClient(); + HttpClient = new HttpClient(); _defaultTimeout = new TimeSpan(0, 0, 30); _progressEvents = new Collection(); Errors = new Collection(); @@ -258,7 +260,7 @@ internal UpdatableHelpSystem(UpdatableHelpCommandBase cmdlet, bool useDefaultCre _cmdlet = cmdlet; _cancelTokenSource = new CancellationTokenSource(); - WebClient.UseDefaultCredentials = useDefaultCredentials; + UseDefaultCredentials = useDefaultCredentials; #if !CORECLR WebClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(HandleDownloadProgressChanged); @@ -275,7 +277,7 @@ public void Dispose() _completionEvent.Dispose(); #endif _cancelTokenSource.Dispose(); - WebClient.Dispose(); + HttpClient.Dispose(); GC.SuppressFinalize(this); } @@ -339,7 +341,7 @@ internal UpdatableHelpInfo GetHelpInfo(UpdatableHelpCommandType commandType, str string xml; using (HttpClientHandler handler = new HttpClientHandler()) { - handler.UseDefaultCredentials = WebClient.UseDefaultCredentials; + handler.UseDefaultCredentials = UseDefaultCredentials; using (HttpClient client = new HttpClient(handler)) { client.Timeout = _defaultTimeout; @@ -420,7 +422,7 @@ private string ResolveUri(string baseUri, bool verbose) using (HttpClientHandler handler = new HttpClientHandler()) { handler.AllowAutoRedirect = false; - handler.UseDefaultCredentials = WebClient.UseDefaultCredentials; + handler.UseDefaultCredentials = UseDefaultCredentials; using (HttpClient client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 0, 30); // Set 30 second timeout @@ -513,6 +515,9 @@ private string ResolveUri(string baseUri, bool verbose) private const string HelpInfoXmlNamespace = "http://schemas.microsoft.com/powershell/help/2010/05"; private const string HelpInfoXmlValidationFailure = "HelpInfoXmlValidationFailure"; + private const string MamlXmlNamespace = "http://schemas.microsoft.com/maml/2004/10"; + private const string CommandXmlNamespace = "http://schemas.microsoft.com/maml/dev/command/2004/10"; + private const string DscResourceXmlNamespace = "http://schemas.microsoft.com/maml/dev/dscResource/2004/10"; /// /// Creates a HelpInfo object. @@ -586,8 +591,9 @@ internal UpdatableHelpInfo CreateHelpInfo(string xml, string moduleName, Guid mo if (!string.IsNullOrEmpty(currentCulture)) { - WildcardOptions wildcardOptions = WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant; - IEnumerable patternList = SessionStateUtilities.CreateWildcardsFromStrings(new string[1] { currentCulture }, wildcardOptions); + IEnumerable patternList = SessionStateUtilities.CreateWildcardsFromStrings( + globPatterns: new[] { currentCulture }, + options: WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); for (int i = 0; i < updatableHelpItem.Length; i++) { @@ -617,7 +623,7 @@ internal UpdatableHelpInfo CreateHelpInfo(string xml, string moduleName, Guid mo /// Xml schema. /// Validation event handler. /// HelpInfo or HelpContent? - private XmlDocument CreateValidXmlDocument(string xml, string ns, string schema, ValidationEventHandler handler, + private static XmlDocument CreateValidXmlDocument(string xml, string ns, string schema, ValidationEventHandler handler, bool helpInfo) { XmlReaderSettings settings = new XmlReaderSettings(); @@ -781,7 +787,7 @@ private bool DownloadHelpContentHttpClient(string uri, string fileName, Updatabl using (HttpClientHandler handler = new HttpClientHandler()) { handler.AllowAutoRedirect = false; - handler.UseDefaultCredentials = WebClient.UseDefaultCredentials; + handler.UseDefaultCredentials = UseDefaultCredentials; using (HttpClient client = new HttpClient(handler)) { client.Timeout = _defaultTimeout; @@ -994,7 +1000,7 @@ internal void GenerateHelpInfo(string moduleName, Guid moduleGuid, string conten /// Removes the read only attribute. /// /// - private void RemoveReadOnly(string path) + private static void RemoveReadOnly(string path) { if (File.Exists(path)) { @@ -1002,7 +1008,7 @@ private void RemoveReadOnly(string path) if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { - attributes = (attributes & ~FileAttributes.ReadOnly); + attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(path, attributes); } } @@ -1089,7 +1095,7 @@ internal void InstallHelpContent(UpdatableHelpCommandType commandType, Execution } #if UNIX - private bool ExpandArchive(string source, string destination) + private static bool ExpandArchive(string source, string destination) { bool sucessfulDecompression = false; @@ -1121,7 +1127,7 @@ private bool ExpandArchive(string source, string destination) /// Source path. /// Destination path. /// Is set to false if we find a single file placeholder.txt in cab. This means we no longer need to install help files. - private void UnzipHelpContent(ExecutionContext context, string srcPath, string destPath, out bool needToCopy) + private static void UnzipHelpContent(ExecutionContext context, string srcPath, string destPath, out bool needToCopy) { needToCopy = true; @@ -1305,8 +1311,6 @@ private void ValidateAndCopyHelpContent(string sourcePath, Collection de Debug.Assert(helpItemsNode != null, "helpItemsNode must not be null"); - string targetNamespace = "http://schemas.microsoft.com/maml/2004/10"; - foreach (XmlNode node in helpItemsNode.ChildNodes) { if (node.NodeType == XmlNodeType.Element) @@ -1315,11 +1319,11 @@ private void ValidateAndCopyHelpContent(string sourcePath, Collection de { if (node.LocalName.Equals("para", StringComparison.OrdinalIgnoreCase)) { - if (!node.NamespaceURI.Equals("http://schemas.microsoft.com/maml/2004/10", StringComparison.OrdinalIgnoreCase)) + if (!node.NamespaceURI.Equals(MamlXmlNamespace, StringComparison.OrdinalIgnoreCase)) { throw new UpdatableHelpSystemException("HelpContentXmlValidationFailure", StringUtil.Format(HelpDisplayStrings.HelpContentXmlValidationFailure, - StringUtil.Format(HelpDisplayStrings.HelpContentMustBeInTargetNamespace, targetNamespace)), ErrorCategory.InvalidData, null, null); + StringUtil.Format(HelpDisplayStrings.HelpContentMustBeInTargetNamespace, MamlXmlNamespace)), ErrorCategory.InvalidData, null, null); } else { @@ -1327,16 +1331,16 @@ private void ValidateAndCopyHelpContent(string sourcePath, Collection de } } - if (!node.NamespaceURI.Equals("http://schemas.microsoft.com/maml/dev/command/2004/10", StringComparison.OrdinalIgnoreCase) && - !node.NamespaceURI.Equals("http://schemas.microsoft.com/maml/dev/dscResource/2004/10", StringComparison.OrdinalIgnoreCase)) + if (!node.NamespaceURI.Equals(CommandXmlNamespace, StringComparison.OrdinalIgnoreCase) && + !node.NamespaceURI.Equals(DscResourceXmlNamespace, StringComparison.OrdinalIgnoreCase)) { throw new UpdatableHelpSystemException("HelpContentXmlValidationFailure", StringUtil.Format(HelpDisplayStrings.HelpContentXmlValidationFailure, - StringUtil.Format(HelpDisplayStrings.HelpContentMustBeInTargetNamespace, targetNamespace)), ErrorCategory.InvalidData, null, null); + StringUtil.Format(HelpDisplayStrings.HelpContentMustBeInTargetNamespace, MamlXmlNamespace)), ErrorCategory.InvalidData, null, null); } } - CreateValidXmlDocument(node.OuterXml, targetNamespace, xsd, + CreateValidXmlDocument(node.OuterXml, MamlXmlNamespace, xsd, new ValidationEventHandler(HelpContentValidationHandler), false); } @@ -1579,8 +1583,8 @@ private void HandleDownloadProgressChanged(object sender, DownloadProgressChange /// internal class UpdatableHelpSystemDrive : IDisposable { - private string _driveName; - private PSCmdlet _cmdlet; + private readonly string _driveName; + private readonly PSCmdlet _cmdlet; /// /// Gets the drive name. diff --git a/src/System.Management.Automation/help/UpdateHelpCommand.cs b/src/System.Management.Automation/help/UpdateHelpCommand.cs index bccd7418476..01b17cbad7e 100644 --- a/src/System.Management.Automation/help/UpdateHelpCommand.cs +++ b/src/System.Management.Automation/help/UpdateHelpCommand.cs @@ -348,7 +348,7 @@ internal override bool ProcessModuleWithCulture(UpdatableHelpModuleInfo module, foreach (UpdatableHelpUri contentUri in newHelpInfo.HelpContentUriCollection) { - Version currentHelpVersion = (currentHelpInfo != null) ? currentHelpInfo.GetCultureVersion(contentUri.Culture) : null; + Version currentHelpVersion = currentHelpInfo?.GetCultureVersion(contentUri.Culture); string updateHelpShouldProcessAction = string.Format(CultureInfo.InvariantCulture, HelpDisplayStrings.UpdateHelpShouldProcessActionMessage, module.ModuleName, @@ -488,7 +488,7 @@ internal override bool ProcessModuleWithCulture(UpdatableHelpModuleInfo module, /// /// /// - private void ThrowPathMustBeValidContainersException(string path, Exception e) + private static void ThrowPathMustBeValidContainersException(string path, Exception e) { throw new UpdatableHelpSystemException("PathMustBeValidContainers", StringUtil.Format(HelpDisplayStrings.PathMustBeValidContainers, path), ErrorCategory.InvalidArgument, diff --git a/src/System.Management.Automation/logging/MshLog.cs b/src/System.Management.Automation/logging/MshLog.cs index 23c687b58ee..89c8231311e 100644 --- a/src/System.Management.Automation/logging/MshLog.cs +++ b/src/System.Management.Automation/logging/MshLog.cs @@ -60,13 +60,13 @@ internal static class MshLog /// The value of this dictionary is never empty. A value of type DummyProvider means /// no logging. /// - private static ConcurrentDictionary> s_logProviders = + private static readonly ConcurrentDictionary> s_logProviders = new ConcurrentDictionary>(); private const string _crimsonLogProviderAssemblyName = "MshCrimsonLog"; private const string _crimsonLogProviderTypeName = "System.Management.Automation.Logging.CrimsonLogProvider"; - private static Collection s_ignoredCommands = new Collection(); + private static readonly Collection s_ignoredCommands = new Collection(); /// /// Static constructor. @@ -469,7 +469,8 @@ internal static void LogCommandLifecycleEvent(ExecutionContext executionContext, if (NeedToLogCommandLifecycleEvent(provider, executionContext)) { provider.LogCommandLifecycleEvent( - () => logContext ?? (logContext = GetLogContext(executionContext, invocationInfo)), commandState); + () => logContext ??= GetLogContext(executionContext, invocationInfo), + commandState); } } } @@ -1085,7 +1086,7 @@ internal enum Severity /// Informational. /// Informational - }; + } /// /// Enum for command states. @@ -1103,7 +1104,7 @@ internal enum CommandState /// /// Terminated = 2 - }; + } /// /// Enum for provider states. @@ -1117,7 +1118,7 @@ internal enum ProviderState /// /// Stopped = 1, - }; + } #endregion } diff --git a/src/System.Management.Automation/namespaces/AliasProvider.cs b/src/System.Management.Automation/namespaces/AliasProvider.cs index d6b99155630..8782a0d9bb5 100644 --- a/src/System.Management.Automation/namespaces/AliasProvider.cs +++ b/src/System.Management.Automation/namespaces/AliasProvider.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Collections.ObjectModel; using System.Management.Automation; @@ -332,7 +331,10 @@ public class AliasProviderDynamicParameters [Parameter] public ScopedItemOptions Options { - get { return _options; } + get + { + return _options; + } set { @@ -355,4 +357,3 @@ internal bool OptionsSet private bool _optionsSet = false; } } - diff --git a/src/System.Management.Automation/namespaces/ContainerProviderBase.cs b/src/System.Management.Automation/namespaces/ContainerProviderBase.cs index c70fe238b44..cc3e0ac83e2 100644 --- a/src/System.Management.Automation/namespaces/ContainerProviderBase.cs +++ b/src/System.Management.Automation/namespaces/ContainerProviderBase.cs @@ -999,7 +999,7 @@ protected virtual bool HasChildItems(string path) } /// - /// Copies an item at the specified path to an item at the . + /// Copies an item at the specified path to an item at the . /// /// /// The path of the item to copy. @@ -1084,4 +1084,3 @@ protected virtual object CopyItemDynamicParameters( #endregion ContainerCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/CoreCommandContext.cs b/src/System.Management.Automation/namespaces/CoreCommandContext.cs index 0bf72583c32..5446b6b71cb 100644 --- a/src/System.Management.Automation/namespaces/CoreCommandContext.cs +++ b/src/System.Management.Automation/namespaces/CoreCommandContext.cs @@ -32,7 +32,7 @@ internal sealed class CmdletProviderContext [Dbg.TraceSourceAttribute( "CmdletProviderContext", "The context under which a core command is being run.")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("CmdletProviderContext", "The context under which a core command is being run."); @@ -294,12 +294,12 @@ internal CmdletProviderContext( /// If the constructor that takes a context to copy is /// called, this will be set to the context being copied. /// - private CmdletProviderContext _copiedContext; + private readonly CmdletProviderContext _copiedContext; /// /// The credentials under which the operation should run. /// - private PSCredential _credentials = PSCredential.Empty; + private readonly PSCredential _credentials = PSCredential.Empty; /// /// The force parameter gives guidance to providers on how vigorously they @@ -312,7 +312,7 @@ internal CmdletProviderContext( /// made visible to anyone and should only be set through the /// constructor. /// - private Cmdlet _command; + private readonly Cmdlet _command; /// /// This makes the origin of the provider request visible to the internals. @@ -327,17 +327,17 @@ internal CmdletProviderContext( /// If it is false, the objects will be accumulated until the /// GetErrorObjects method is called. /// - private bool _streamErrors; + private readonly bool _streamErrors; /// /// A collection in which objects that are written using the WriteObject(s) - /// methods are accumulated if is false. + /// methods are accumulated if is false. /// private Collection _accumulatedObjects = new Collection(); /// /// A collection in which objects that are written using the WriteError - /// method are accumulated if is false. + /// method are accumulated if is false. /// private Collection _accumulatedErrorObjects = new Collection(); @@ -1191,4 +1191,3 @@ internal bool HasIncludeOrExclude #endregion Public methods } } - diff --git a/src/System.Management.Automation/namespaces/DriveProviderBase.cs b/src/System.Management.Automation/namespaces/DriveProviderBase.cs index d69f17e94ee..91b47619be7 100644 --- a/src/System.Management.Automation/namespaces/DriveProviderBase.cs +++ b/src/System.Management.Automation/namespaces/DriveProviderBase.cs @@ -4,8 +4,6 @@ using System.Collections.ObjectModel; using System.Management.Automation.Internal; -using Dbg = System.Management.Automation; - namespace System.Management.Automation.Provider { #region DriveCmdletProvider @@ -238,4 +236,3 @@ protected virtual Collection InitializeDefaultDrives() #endregion DriveCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/EnvironmentProvider.cs b/src/System.Management.Automation/namespaces/EnvironmentProvider.cs index 4f1fd8eb0b0..1ea71d1b1ed 100644 --- a/src/System.Management.Automation/namespaces/EnvironmentProvider.cs +++ b/src/System.Management.Automation/namespaces/EnvironmentProvider.cs @@ -245,4 +245,3 @@ internal override object GetValueOfItem(object item) #endregion protected members } } - diff --git a/src/System.Management.Automation/namespaces/FileSystemContentStream.cs b/src/System.Management.Automation/namespaces/FileSystemContentStream.cs index 6a81206e221..1a9935cb1ad 100644 --- a/src/System.Management.Automation/namespaces/FileSystemContentStream.cs +++ b/src/System.Management.Automation/namespaces/FileSystemContentStream.cs @@ -38,33 +38,33 @@ internal class FileSystemContentReaderWriter : IContentReader, IContentWriter [Dbg.TraceSourceAttribute( "FileSystemContentStream", "The provider content reader and writer for the file system")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("FileSystemContentStream", "The provider content reader and writer for the file system"); #endregion tracer - private string _path; - private string _streamName; - private FileMode _mode; - private FileAccess _access; - private FileShare _share; - private Encoding _encoding; - private CmdletProvider _provider; + private readonly string _path; + private readonly string _streamName; + private readonly FileMode _mode; + private readonly FileAccess _access; + private readonly FileShare _share; + private readonly Encoding _encoding; + private readonly CmdletProvider _provider; private FileStream _stream; private StreamReader _reader; private StreamWriter _writer; - private bool _usingByteEncoding; + private readonly bool _usingByteEncoding; private const char DefaultDelimiter = '\n'; - private string _delimiter = $"{DefaultDelimiter}"; - private int[] _offsetDictionary; - private bool _usingDelimiter; - private StringBuilder _currentLineContent; + private readonly string _delimiter = $"{DefaultDelimiter}"; + private readonly int[] _offsetDictionary; + private readonly bool _usingDelimiter; + private readonly StringBuilder _currentLineContent; private bool _waitForChanges; - private bool _isRawStream; + private readonly bool _isRawStream; private long _fileOffset; private FileAttributes _oldAttributes; @@ -75,7 +75,7 @@ internal class FileSystemContentReaderWriter : IContentReader, IContentWriter private bool _alreadyDetectEncoding = false; // False to add a newline to the end of the output string, true if not. - private bool _suppressNewline = false; + private readonly bool _suppressNewline = false; /// /// Constructor for the content stream. @@ -109,10 +109,26 @@ internal class FileSystemContentReaderWriter : IContentReader, IContentWriter /// Indicates raw stream. /// public FileSystemContentReaderWriter( - string path, FileMode mode, FileAccess access, - FileShare share, Encoding encoding, bool usingByteEncoding, - bool waitForChanges, CmdletProvider provider, bool isRawStream) : - this(path, null, mode, access, share, encoding, usingByteEncoding, waitForChanges, provider, isRawStream) + string path, + FileMode mode, + FileAccess access, + FileShare share, + Encoding encoding, + bool usingByteEncoding, + bool waitForChanges, + CmdletProvider provider, + bool isRawStream) + : this( + path, + streamName: null, + mode, + access, + share, + encoding, + usingByteEncoding, + waitForChanges, + provider, + isRawStream) { } @@ -551,7 +567,7 @@ internal void SeekItemsBackward(int backCount) (e is UnauthorizedAccessException) || (e is ArgumentNullException)) { - // Exception contains specific message about the error occured and so no need for errordetails. + // Exception contains specific message about the error occurred and so no need for errordetails. _provider.WriteError(new ErrorRecord(e, "GetContentReaderIOError", ErrorCategory.ReadError, _path)); } else @@ -903,8 +919,8 @@ private void WaitForChanges(string filePath, FileMode fileMode, FileAccess fileA { ErrorEventArgs errorEventArgs = null; var tcs = new TaskCompletionSource(); - FileSystemEventHandler onChangedHandler = (object source, FileSystemEventArgs e) => { tcs.TrySetResult(e); }; - RenamedEventHandler onRenamedHandler = (object source, RenamedEventArgs e) => { tcs.TrySetResult(e); }; + FileSystemEventHandler onChangedHandler = (object source, FileSystemEventArgs e) => tcs.TrySetResult(e); + RenamedEventHandler onRenamedHandler = (object source, RenamedEventArgs e) => tcs.TrySetResult(e); ErrorEventHandler onErrorHandler = (object source, ErrorEventArgs e) => { errorEventArgs = e; @@ -1515,7 +1531,7 @@ internal struct CPINFO [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_LEADBYTES)] public byte[] LeadBytes; - }; + } /// /// Get information on a named code page. diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index be4b95dc935..37229a18db4 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -51,16 +51,10 @@ public sealed partial class FileSystemProvider : NavigationCmdletProvider, ISecurityDescriptorCmdletProvider, ICmdletProviderSupportsHelp { -#if UNIX - // This is the errno returned by the rename() syscall - // when an item is attempted to be renamed across filesystem mount boundaries. - private const int UNIX_ERRNO_EXDEV = 18; -#endif - // 4MB gives the best results without spiking the resources on the remote connection for file transfers between pssessions. // NOTE: The script used to copy file data from session (PSCopyFromSessionHelper) has a // maximum fragment size value for security. If FILETRANSFERSIZE changes make sure the - // copy script will accomodate the new value. + // copy script will accommodate the new value. private const int FILETRANSFERSIZE = 4 * 1024 * 1024; // The name of the key in an exception's Data dictionary when attempting @@ -72,7 +66,7 @@ public sealed partial class FileSystemProvider : NavigationCmdletProvider, /// using "FileSystemProvider" as the category. /// [Dbg.TraceSourceAttribute("FileSystemProvider", "The namespace navigation provider for the file system")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("FileSystemProvider", "The namespace navigation provider for the file system"); /// @@ -90,7 +84,7 @@ public FileSystemProvider() private Collection _excludeMatcher = null; - private static System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions + private static readonly System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions { MatchType = MatchType.Win32, MatchCasing = MatchCasing.CaseInsensitive, @@ -476,10 +470,11 @@ protected override ProviderInfo Start(ProviderInfo providerInfo) // The placeholder mode management APIs Rtl(Set|Query)(Process|Thread)PlaceholderCompatibilityMode // are only supported starting with Windows 10 version 1803 (build 17134) Version minBuildForPlaceHolderAPIs = new Version(10, 0, 17134, 0); + if (Environment.OSVersion.Version >= minBuildForPlaceHolderAPIs) { // let's be safe, don't change the PlaceHolderCompatibilityMode if the current one is not what we expect - if (NativeMethods.PHCM_DISGUISE_PLACEHOLDER == NativeMethods.RtlQueryProcessPlaceholderCompatibilityMode()) + if (NativeMethods.RtlQueryProcessPlaceholderCompatibilityMode() == NativeMethods.PHCM_DISGUISE_PLACEHOLDER) { NativeMethods.RtlSetProcessPlaceholderCompatibilityMode(NativeMethods.PHCM_EXPOSE_PLACEHOLDERS); } @@ -709,7 +704,7 @@ private void WinMapNetworkDrive(PSDriveInfo drive) /// /// /// - private bool IsNetworkMappedDrive(PSDriveInfo drive) + private static bool IsNetworkMappedDrive(PSDriveInfo drive) { bool shouldMapNetworkDrive = (drive != null && !string.IsNullOrEmpty(drive.Root) && PathIsNetworkPath(drive.Root)) && (drive.Persist || (drive.Credential != null && !drive.Credential.Equals(PSCredential.Empty))); @@ -789,7 +784,7 @@ private PSDriveInfo WinRemoveDrive(PSDriveInfo drive) /// PS Drive Info. /// /// True if the drive can be persisted or else false. - private bool IsSupportedDriveForPersistence(PSDriveInfo drive) + private static bool IsSupportedDriveForPersistence(PSDriveInfo drive) { bool isSupportedDriveForPersistence = false; if (drive != null && !string.IsNullOrEmpty(drive.Name) && drive.Name.Length == 1) @@ -1311,35 +1306,36 @@ protected override void GetItem(string path) // If we want to retrieve the file streams, retrieve them. if (retrieveStreams) { - if (!isContainer) + foreach (string desiredStream in dynamicParameters.Stream) { - foreach (string desiredStream in dynamicParameters.Stream) - { - // See that it matches the name specified - WildcardPattern p = WildcardPattern.Get(desiredStream, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); - bool foundStream = false; + // See that it matches the name specified + WildcardPattern p = WildcardPattern.Get(desiredStream, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); + bool foundStream = false; - foreach (AlternateStreamData stream in AlternateDataStreamUtilities.GetStreams(result.FullName)) + foreach (AlternateStreamData stream in AlternateDataStreamUtilities.GetStreams(result.FullName)) + { + if (!p.IsMatch(stream.Stream)) { - if (!p.IsMatch(stream.Stream)) { continue; } - - string outputPath = result.FullName + ":" + stream.Stream; - WriteItemObject(stream, outputPath, isContainer); - foundStream = true; + continue; } - if ((!WildcardPattern.ContainsWildcardCharacters(desiredStream)) && (!foundStream)) - { - string errorMessage = StringUtil.Format( - FileSystemProviderStrings.AlternateDataStreamNotFound, desiredStream, result.FullName); - Exception e = new FileNotFoundException(errorMessage, result.FullName); - - WriteError(new ErrorRecord( - e, - "AlternateDataStreamNotFound", - ErrorCategory.ObjectNotFound, - path)); - } + string outputPath = result.FullName + ":" + stream.Stream; + // Alternate data streams can never be containers. + WriteItemObject(stream, outputPath, isContainer: false); + foundStream = true; + } + + if ((!WildcardPattern.ContainsWildcardCharacters(desiredStream)) && (!foundStream)) + { + string errorMessage = StringUtil.Format( + FileSystemProviderStrings.AlternateDataStreamNotFound, desiredStream, result.FullName); + Exception e = new FileNotFoundException(errorMessage, result.FullName); + + WriteError(new ErrorRecord( + e, + "AlternateDataStreamNotFound", + ErrorCategory.ObjectNotFound, + path)); } } } @@ -1363,7 +1359,7 @@ protected override void GetItem(string path) } catch (IOException ioError) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. ErrorRecord er = new ErrorRecord(ioError, "GetItemIOError", ErrorCategory.ReadError, path); WriteError(er); } @@ -1786,7 +1782,7 @@ private void Dir( foreach (IEnumerable childList in target) { // On some systems, this is already sorted. For consistency, always sort again. - IEnumerable sortedChildList = childList.OrderBy(c => c.Name, StringComparer.CurrentCultureIgnoreCase); + IEnumerable sortedChildList = childList.OrderBy(static c => c.Name, StringComparer.CurrentCultureIgnoreCase); foreach (FileSystemInfo filesystemInfo in sortedChildList) { @@ -1895,9 +1891,14 @@ private void Dir( } bool hidden = false; + bool checkReparsePoint = true; if (!Force) { hidden = (recursiveDirectory.Attributes & FileAttributes.Hidden) != 0; + + // We've already taken the expense of initializing the Attributes property here, + // so we can use that to avoid needing to call IsReparsePointLikeSymlink() later. + checkReparsePoint = recursiveDirectory.Attributes.HasFlag(FileAttributes.ReparsePoint); } // if "Hidden" is explicitly specified anywhere in the attribute filter, then override @@ -1911,7 +1912,7 @@ private void Dir( // c) it is not a reparse point with a target (not OneDrive or an AppX link). if (tracker == null) { - if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointWithTarget(recursiveDirectory)) + if (checkReparsePoint && InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(recursiveDirectory)) { continue; } @@ -2019,7 +2020,7 @@ string ToModeString(FileSystemInfo fileSystemInfo) FileAttributes fileAttributes = fileSystemInfo.Attributes; bool isReparsePoint = InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileSystemInfo); - bool isLink = isReparsePoint || (excludeHardLink ? false : InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileSystemInfo)); + bool isLink = isReparsePoint || (!excludeHardLink && InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileSystemInfo)); if (!isLink) { // special casing for the common cases - no allocations @@ -2062,11 +2063,43 @@ string ToModeString(FileSystemInfo fileSystemInfo) /// Name if a file or directory, Name -> Target if symlink. public static string NameString(PSObject instance) { - return instance?.BaseObject is FileSystemInfo fileInfo - ? InternalSymbolicLinkLinkCodeMethods.IsReparsePointWithTarget(fileInfo) - ? $"{fileInfo.Name} -> {InternalSymbolicLinkLinkCodeMethods.GetTarget(instance)}" - : fileInfo.Name - : string.Empty; + if (ExperimentalFeature.IsEnabled("PSAnsiRenderingFileInfo")) + { + if (instance?.BaseObject is FileSystemInfo fileInfo) + { + if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(fileInfo)) + { + return $"{PSStyle.Instance.FileInfo.SymbolicLink}{fileInfo.Name}{PSStyle.Instance.Reset} -> {fileInfo.LinkTarget}"; + } + else if (fileInfo.Attributes.HasFlag(FileAttributes.Directory)) + { + return $"{PSStyle.Instance.FileInfo.Directory}{fileInfo.Name}{PSStyle.Instance.Reset}"; + } + else if (PSStyle.Instance.FileInfo.Extension.ContainsKey(fileInfo.Extension)) + { + return $"{PSStyle.Instance.FileInfo.Extension[fileInfo.Extension]}{fileInfo.Name}{PSStyle.Instance.Reset}"; + } + else if ((Platform.IsWindows && CommandDiscovery.PathExtensions.Contains(fileInfo.Extension.ToLower())) || + (!Platform.IsWindows && Platform.NonWindowsIsExecutable(fileInfo.FullName))) + { + return $"{PSStyle.Instance.FileInfo.Executable}{fileInfo.Name}{PSStyle.Instance.Reset}"; + } + else + { + return fileInfo.Name; + } + } + + return string.Empty; + } + else + { + return instance?.BaseObject is FileSystemInfo fileInfo + ? InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(fileInfo) + ? $"{fileInfo.Name} -> {fileInfo.LinkTarget}" + : fileInfo.Name + : string.Empty; + } } /// @@ -2217,7 +2250,7 @@ protected override void RenameItem( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "RenameItemIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -2241,7 +2274,7 @@ protected override void RenameItem( /// Specify "directory" or "container" to create a directory. /// /// - /// If is "file" then this parameter becomes the content + /// If is "file" then this parameter becomes the content /// of the file to be created. /// /// @@ -2329,7 +2362,7 @@ protected override void NewItem( } catch (IOException exception) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(exception, "NewItemIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -2376,7 +2409,7 @@ protected override void NewItem( if (strTargetPath.StartsWith(".\\", StringComparison.OrdinalIgnoreCase) || strTargetPath.StartsWith("./", StringComparison.OrdinalIgnoreCase)) { - normalizedTargetPath = Path.Join(SessionState.Internal.CurrentLocation.ProviderPath, strTargetPath.AsSpan().Slice(2)); + normalizedTargetPath = Path.Join(SessionState.Internal.CurrentLocation.ProviderPath, strTargetPath.AsSpan(2)); } GetFileSystemInfo(normalizedTargetPath, out isDirectory); @@ -2721,7 +2754,7 @@ private enum ItemType SymbolicLink, Junction, HardLink - }; + } private static ItemType GetItemType(string input) { @@ -2825,7 +2858,7 @@ private void CreateDirectory(string path, bool streamOutput) // Ignore the error if force was specified if (!Force) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "CreateDirectoryIOError", ErrorCategory.WriteError, path)); } } @@ -2900,7 +2933,7 @@ private bool CreateIntermediateDirectories(string path) } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "CreateIntermediateDirectoriesIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -3043,7 +3076,7 @@ protected override void RemoveItem(string path, bool recurse) } catch (IOException exception) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(exception, "RemoveItemIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -3103,22 +3136,31 @@ private void RemoveDirectoryInfoItem(DirectoryInfo directory, bool recurse, bool continueRemoval = ShouldProcess(directory.FullName, action); } - if (directory.Attributes.HasFlag(FileAttributes.ReparsePoint)) + if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(directory)) { + void WriteErrorHelper(Exception exception) + { + WriteError(new ErrorRecord(exception, errorId: "DeleteSymbolicLinkFailed", ErrorCategory.WriteError, directory)); + } + try { - // TODO: - // Different symlinks seem to vary by behavior. - // In particular, OneDrive symlinks won't remove without recurse, - // but the .NET API here does not allow us to distinguish them. - // We may need to revisit using p/Invokes here to get the right behavior - directory.Delete(); + if (InternalTestHooks.OneDriveTestOn) + { + WriteErrorHelper(new IOException()); + return; + } + else + { + // Name surrogates should just be detached. + directory.Delete(); + } } catch (Exception e) { string error = StringUtil.Format(FileSystemProviderStrings.CannotRemoveItem, directory.FullName, e.Message); var exception = new IOException(error, e); - WriteError(new ErrorRecord(exception, errorId: "DeleteSymbolicLinkFailed", ErrorCategory.WriteError, directory)); + WriteErrorHelper(exception); } return; @@ -3267,7 +3309,7 @@ private void RemoveFileSystemItem(FileSystemInfo fileSystemInfo, bool force) // if they've specified force. if (force) { - fileSystemInfo.Attributes = fileSystemInfo.Attributes & ~(FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System); + fileSystemInfo.Attributes &= ~(FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System); attributeRecoveryRequired = true; } @@ -3883,7 +3925,7 @@ private void CopyDirectoryInfoItem( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "CopyDirectoryInfoItemIOError", ErrorCategory.WriteError, file)); } catch (UnauthorizedAccessException accessException) @@ -3914,7 +3956,7 @@ private void CopyDirectoryInfoItem( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "CopyDirectoryInfoItemIOError", ErrorCategory.WriteError, childDir)); } catch (UnauthorizedAccessException accessException) @@ -3999,8 +4041,7 @@ private void CopyFileInfoItem(FileInfo file, string destinationPath, bool force, // try again FileInfo destinationItem = new FileInfo(destinationPath); - destinationItem.Attributes = - destinationItem.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden); + destinationItem.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden); } else { @@ -4196,7 +4237,7 @@ private void RemoveFunctionsPSCopyFileFromRemoteSession(System.Management.Automa return; } - string remoteScript = @" + const string remoteScript = @" Microsoft.PowerShell.Management\Remove-Item function:PSCopyFromSessionHelper -ea SilentlyContinue -Force Microsoft.PowerShell.Management\Remove-Item function:PSCopyRemoteUtils -ea SilentlyContinue -Force "; @@ -4204,7 +4245,7 @@ private void RemoveFunctionsPSCopyFileFromRemoteSession(System.Management.Automa SafeInvokeCommand.Invoke(ps, this, null, false); } - private bool ValidRemoteSessionForScripting(Runspace runspace) + private static bool ValidRemoteSessionForScripting(Runspace runspace) { if (runspace is not RemoteRunspace) { @@ -4256,19 +4297,19 @@ private void SetFileMetadata(string sourceFileFullName, FileInfo destinationFile { if (string.Equals(value, "ReadOnly", StringComparison.OrdinalIgnoreCase)) { - destinationFile.Attributes = destinationFile.Attributes | FileAttributes.ReadOnly; + destinationFile.Attributes |= FileAttributes.ReadOnly; } else if (string.Equals(value, "Hidden", StringComparison.OrdinalIgnoreCase)) { - destinationFile.Attributes = destinationFile.Attributes | FileAttributes.Hidden; + destinationFile.Attributes |= FileAttributes.Hidden; } else if (string.Equals(value, "Archive", StringComparison.OrdinalIgnoreCase)) { - destinationFile.Attributes = destinationFile.Attributes | FileAttributes.Archive; + destinationFile.Attributes |= FileAttributes.Archive; } else if (string.Equals(value, "System", StringComparison.OrdinalIgnoreCase)) { - destinationFile.Attributes = destinationFile.Attributes | FileAttributes.System; + destinationFile.Attributes |= FileAttributes.System; } } } @@ -4361,7 +4402,7 @@ private bool PerformCopyFileFromRemoteSession(string sourceFileFullName, FileInf // If force is specified, and the file already exist at the destination, mask of the readonly, hidden, and system attributes if (force && File.Exists(destinationFile.FullName)) { - destinationFile.Attributes = destinationFile.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System); + destinationFile.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System); } wStream = new FileStream(destinationFile.FullName, FileMode.Create); @@ -4374,7 +4415,7 @@ private bool PerformCopyFileFromRemoteSession(string sourceFileFullName, FileInf wStream = AlternateDataStreamUtilities.CreateFileStream(destinationFile.FullName, streamName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); } #endif - long fragmentSize = FILETRANSFERSIZE; + const long fragmentSize = FILETRANSFERSIZE; long copiedSoFar = 0; long currentIndex = 0; @@ -4421,7 +4462,7 @@ private bool PerformCopyFileFromRemoteSession(string sourceFileFullName, FileInf } } - // To accomodate empty files + // To accommodate empty files string content = string.Empty; if (op["b64Fragment"] != null) { @@ -4507,7 +4548,7 @@ private void RemoveFunctionPSCopyFileToRemoteSession(System.Management.Automatio { if ((ps == null) || !ValidRemoteSessionForScripting(ps.Runspace)) { return; } - string remoteScript = @" + const string remoteScript = @" Microsoft.PowerShell.Management\Remove-Item function:PSCopyToSessionHelper -ea SilentlyContinue -Force Microsoft.PowerShell.Management\Remove-Item function:PSCopyRemoteUtils -ea SilentlyContinue -Force "; @@ -4625,7 +4666,7 @@ private bool CopyFileStreamToRemoteSession(FileInfo file, string destinationPath WriteProgress(progress); // 4MB gives the best results without spiking the resources on the remote connection. - int fragmentSize = FILETRANSFERSIZE; + const int fragmentSize = FILETRANSFERSIZE; byte[] fragment = null; int iteration = 0; bool success = false; @@ -4769,7 +4810,7 @@ private bool CopyFileStreamToRemoteSession(FileInfo file, string destinationPath // Returns a hash table with metadata about this file info. // - private Hashtable GetFileMetadata(FileInfo file) + private static Hashtable GetFileMetadata(FileInfo file) { Hashtable metadata = new Hashtable(); @@ -5213,7 +5254,7 @@ protected override string NormalizeRelativePath( } catch (IOException ioError) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioError, "NormalizeRelativePathIOError", ErrorCategory.ReadError, path)); break; } @@ -5410,7 +5451,7 @@ private string NormalizeRelativePathHelper(string path, string basePath) #if !UNIX if (!string.IsNullOrEmpty(alternateDataStream)) { - result = result + alternateDataStream; + result += alternateDataStream; } #endif @@ -5810,6 +5851,15 @@ protected override void MoveItem( destination = MakePath(destination, dir.Name); } + // Don't allow moving a directory into itself + if (destination.StartsWith(Path.TrimEndingDirectorySeparator(path) + Path.DirectorySeparatorChar)) + { + string error = StringUtil.Format(FileSystemProviderStrings.TargetCannotBeSubdirectoryOfSource, destination); + var e = new IOException(error); + WriteError(new ErrorRecord(e, "MoveItemArgumentError", ErrorCategory.InvalidArgument, destination)); + return; + } + // Get the confirmation text string action = FileSystemProviderStrings.MoveItemActionDirectory; @@ -5857,7 +5907,7 @@ protected override void MoveItem( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "MoveItemIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -5901,8 +5951,7 @@ private void MoveFileInfoItem( try { // mask off the readonly and hidden bits and try again - file.Attributes = - file.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden); + file.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden); file.MoveTo(destination); @@ -5950,7 +5999,7 @@ private void MoveFileInfoItem( try { // Make sure the file is not read only - destfile.Attributes = destfile.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden); + destfile.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden); destfile.Delete(); file.MoveTo(destination); @@ -5971,7 +6020,7 @@ private void MoveFileInfoItem( (exception is ArgumentNullException) || (exception is IOException)) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "MoveFileInfoItemIOError", ErrorCategory.WriteError, destfile)); } else @@ -5980,13 +6029,13 @@ private void MoveFileInfoItem( } else { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "MoveFileInfoItemIOError", ErrorCategory.WriteError, file)); } } else { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "MoveFileInfoItemIOError", ErrorCategory.WriteError, file)); } } @@ -6022,8 +6071,7 @@ private void MoveDirectoryInfoItem( try { // mask off the readonly and hidden bits and try again - directory.Attributes = - directory.Attributes & ~(FileAttributes.ReadOnly | FileAttributes.Hidden); + directory.Attributes &= ~(FileAttributes.ReadOnly | FileAttributes.Hidden); MoveDirectoryInfoUnchecked(directory, destination, force); @@ -6058,7 +6106,7 @@ private void MoveDirectoryInfoItem( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "MoveDirectoryItemIOError", ErrorCategory.WriteError, directory)); } } @@ -6073,35 +6121,31 @@ private void MoveDirectoryInfoItem( /// If true, force move the directory, overwriting anything at the destination. private void MoveDirectoryInfoUnchecked(DirectoryInfo directory, string destinationPath, bool force) { -#if UNIX try { if (InternalTestHooks.ThrowExdevErrorOnMoveDirectory) { - throw new IOException("Invalid cross-device link", hresult: UNIX_ERRNO_EXDEV); + throw new IOException("Invalid cross-device link"); } directory.MoveTo(destinationPath); } - catch (IOException e) when (e.HResult == UNIX_ERRNO_EXDEV) +#if UNIX + // This is the errno returned by the rename() syscall + // when an item is attempted to be renamed across filesystem mount boundaries. + // 0x80131620 is returned if the source and destination do not have the same root path + catch (IOException e) when (e.HResult == 18 || e.HResult == -2146232800) +#else + // 0x80070005 ACCESS_DENIED is returned when trying to move files across volumes like DFS + // 0x80131620 is returned if the source and destination do not have the same root path + catch (IOException e) when (e.HResult == -2147024891 || e.HResult == -2146232800) +#endif { // Rather than try to ascertain whether we can rename a directory ahead of time, // it's both faster and more correct to try to rename it and fall back to copy/deleting it // See also: https://github.com/coreutils/coreutils/blob/439741053256618eb651e6d43919df29625b8714/src/mv.c#L212-L216 CopyAndDelete(directory, destinationPath, force); } -#else - // On Windows, being able to rename vs copy/delete a file - // is just a question of the drive - if (IsSameWindowsVolume(directory.FullName, destinationPath)) - { - directory.MoveTo(destinationPath); - } - else - { - CopyAndDelete(directory, destinationPath, force); - } -#endif } private void CopyAndDelete(DirectoryInfo directory, string destination, bool force) @@ -6139,16 +6183,6 @@ private void CopyAndDelete(DirectoryInfo directory, string destination, bool for } } -#if !UNIX - private bool IsSameWindowsVolume(string source, string destination) - { - FileInfo src = new FileInfo(source); - FileInfo dest = new FileInfo(destination); - - return (src.Directory.Root.Name == dest.Directory.Root.Name); - } -#endif - #endregion MoveItem #endregion NavigationCmdletProvider members @@ -6162,8 +6196,8 @@ private bool IsSameWindowsVolume(string source, string destination) /// /// The list of properties to get. Examples include "Attributes", "LastAccessTime," /// and other properties defined by - /// and - /// + /// and + /// /// public void GetProperty(string path, Collection providerSpecificPickList) { @@ -6243,7 +6277,7 @@ public void GetProperty(string path, Collection providerSpecificPickList } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "GetPropertyIOError", ErrorCategory.ReadError, path)); } catch (UnauthorizedAccessException accessException) @@ -6543,7 +6577,7 @@ public void ClearProperty( } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "ClearPropertyIOError", ErrorCategory.WriteError, path)); } } @@ -6666,7 +6700,14 @@ public IContentReader GetContentReader(string path) try { - if (Directory.Exists(path)) + // Get-Content will write a non-terminating error if the target is a directory. + // On Windows, the streamName must be null or empty for it to write the error. Otherwise, the + // alternate data stream is not a directory, even if it's set on a directory. + if (Directory.Exists(path) +#if !UNIX + && string.IsNullOrEmpty(streamName) +#endif + ) { string errMsg = StringUtil.Format(SessionStateStrings.GetContainerContentException, path); ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "GetContainerContentException", ErrorCategory.InvalidOperation, null); @@ -6716,7 +6757,7 @@ public IContentReader GetContentReader(string path) } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "GetContentReaderIOError", ErrorCategory.ReadError, path)); } catch (System.Security.SecurityException securityException) @@ -6774,7 +6815,7 @@ public IContentWriter GetContentWriter(string path) bool usingByteEncoding = false; bool streamTypeSpecified = false; Encoding encoding = ClrFacade.GetDefaultEncoding(); - FileMode filemode = FileMode.OpenOrCreate; + const FileMode filemode = FileMode.OpenOrCreate; string streamName = null; bool suppressNewline = false; @@ -6821,7 +6862,14 @@ public IContentWriter GetContentWriter(string path) try { - if (Directory.Exists(path)) + // Add-Content and Set-Content will write a non-terminating error if the target is a directory. + // On Windows, the streamName must be null or empty for it to write the error. Otherwise, the + // alternate data stream is not a directory, even if it's set on a directory. + if (Directory.Exists(path) +#if !UNIX + && string.IsNullOrEmpty(streamName) +#endif + ) { string errMsg = StringUtil.Format(SessionStateStrings.WriteContainerContentException, path); ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "WriteContainerContentException", ErrorCategory.InvalidOperation, null); @@ -6849,7 +6897,7 @@ public IContentWriter GetContentWriter(string path) } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "GetContentWriterIOError", ErrorCategory.WriteError, path)); } catch (System.Security.SecurityException securityException) @@ -6899,13 +6947,6 @@ public void ClearContent(string path) path = NormalizePath(path); - if (Directory.Exists(path)) - { - string errorMsg = StringUtil.Format(SessionStateStrings.ClearDirectoryContent, path); - WriteError(new ErrorRecord(new NotSupportedException(errorMsg), "ClearDirectoryContent", ErrorCategory.InvalidOperation, path)); - return; - } - try { #if !UNIX @@ -6957,6 +6998,26 @@ public void ClearContent(string path) clearStream = false; } +#endif + // On Windows, determine if our argument is a directory only after we determine if + // we're being asked to work with an alternate data stream, because directories can have + // alternate data streams on them that are not child items. These alternate data streams + // must be treated as data streams, even if they're attached to directories. However, + // if asked to work with a directory without a data stream specified, write a non-terminating + // error instead of clearing all child items of the directory. (On non-Windows, alternate + // data streams don't exist, so in that environment always write the error when addressing + // a directory.) + if (Directory.Exists(path) +#if !UNIX + && !clearStream +#endif + ) + { + string errorMsg = StringUtil.Format(SessionStateStrings.ClearDirectoryContent, path); + WriteError(new ErrorRecord(new NotSupportedException(errorMsg), "ClearDirectoryContent", ErrorCategory.InvalidOperation, path)); + return; + } +#if !UNIX if (clearStream) { FileStream fileStream = null; @@ -7002,7 +7063,7 @@ public void ClearContent(string path) } catch (IOException ioException) { - // IOException contains specific message about the error occured and so no need for errordetails. + // IOException contains specific message about the error occurred and so no need for errordetails. WriteError(new ErrorRecord(ioException, "ClearContentIOError", ErrorCategory.WriteError, path)); } catch (UnauthorizedAccessException accessException) @@ -7134,7 +7195,7 @@ private static class NativeMethods /// /// If connection is established to the network resource /// then success is returned or else the error code describing the - /// type of failure that occured while establishing + /// type of failure that occurred while establishing /// the connection is returned. [DllImport("mpr.dll", CharSet = CharSet.Unicode)] internal static extern int WNetAddConnection2(ref NetResource netResource, byte[] password, string username, int flags); @@ -7154,7 +7215,7 @@ private static class NativeMethods /// if there are open files or jobs. /// /// If connection is removed then success is returned or - /// else the error code describing the type of failure that occured while + /// else the error code describing the type of failure that occurred while /// trying to remove the connection is returned. /// [DllImport("mpr.dll", CharSet = CharSet.Unicode)] @@ -7372,9 +7433,9 @@ private struct NetResource /// /// Tracks visited files/directories by caching their device IDs and inodes. /// - private class InodeTracker + private sealed class InodeTracker { - private HashSet<(UInt64, UInt64)> _visitations; + private readonly HashSet<(UInt64, UInt64)> _visitations; /// /// Construct a new InodeTracker with an initial path. @@ -7521,7 +7582,7 @@ internal sealed class GetChildDynamicParameters /// Gets or sets the filter directory flag. /// [Parameter] - [Alias("ad", "d")] + [Alias("ad")] public SwitchParameter Directory { get { return _attributeDirectory; } @@ -7598,7 +7659,7 @@ internal FileSystemContentDynamicParametersBase(FileSystemProvider provider) _provider = provider; } - private FileSystemProvider _provider; + private readonly FileSystemProvider _provider; /// /// Gets or sets the encoding method used when @@ -7699,7 +7760,7 @@ public SwitchParameter NoNewline /// public class FileSystemContentReaderDynamicParameters : FileSystemContentDynamicParametersBase { - internal FileSystemContentReaderDynamicParameters(FileSystemProvider provider) : base (provider) { } + internal FileSystemContentReaderDynamicParameters(FileSystemProvider provider) : base(provider) { } /// /// Gets or sets the delimiter to use when reading the file. Custom delimiters @@ -7840,8 +7901,6 @@ public static class InternalSymbolicLinkLinkCodeMethods // data is 16KB, plus there's a header. private const int MAX_REPARSE_SIZE = (16 * 1024) + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE; - private const int ERROR_NOT_A_REPARSE_POINT = 4390; - private const int FSCTL_GET_REPARSE_POINT = 0x000900A8; private const int FSCTL_SET_REPARSE_POINT = 0x000900A4; @@ -7943,18 +8002,6 @@ private struct REPARSE_DATA_BUFFER_MOUNTPOINT public byte[] PathBuffer; } - [StructLayout(LayoutKind.Sequential)] - private struct REPARSE_DATA_BUFFER_APPEXECLINK - { - public uint ReparseTag; - public ushort ReparseDataLength; - public ushort Reserved; - public uint StringCount; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3FF0)] - public byte[] StringList; - } - [StructLayout(LayoutKind.Sequential)] private struct BY_HANDLE_FILE_INFORMATION { @@ -8029,8 +8076,7 @@ protected override bool ReleaseHandle() private static extern bool FindClose(IntPtr handle); } - // SetLastError is false as the use of this API doesn't not require GetLastError() to be called - [DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode)] private static extern SafeFindHandle FindFirstFileEx(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags); internal enum FINDEX_INFO_LEVELS : uint @@ -8068,15 +8114,18 @@ internal unsafe struct WIN32_FIND_DATA /// /// The object of FileInfo or DirectoryInfo type. /// The target of the reparse point. + [Obsolete("This method is now obsolete. Please use the .NET API 'FileSystemInfo.LinkTarget'", error: true)] public static string GetTarget(PSObject instance) { if (instance.BaseObject is FileSystemInfo fileSysInfo) { -#if !UNIX - return WinInternalGetTarget(fileSysInfo.FullName); -#else - return UnixInternalGetTarget(fileSysInfo.FullName); -#endif + if (!fileSysInfo.Exists) + { + throw new ArgumentException( + StringUtil.Format(SessionStateStrings.PathNotFound, fileSysInfo.FullName)); + } + + return fileSysInfo.LinkTarget; } return null; @@ -8099,20 +8148,6 @@ public static string GetLinkType(PSObject instance) return null; } -#if UNIX - private static string UnixInternalGetTarget(string filePath) - { - string link = Platform.NonWindowsInternalGetTarget(filePath); - - if (string.IsNullOrEmpty(link)) - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } - - return link; - } -#endif - private static string InternalGetLinkType(FileSystemInfo fileInfo) { if (Platform.IsWindows) @@ -8128,16 +8163,11 @@ private static string InternalGetLinkType(FileSystemInfo fileInfo) [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] private static string WinInternalGetLinkType(string filePath) { - if (!Platform.IsWindows) - { - throw new PlatformNotSupportedException(); - } - // We set accessMode parameter to zero because documentation says: // If this parameter is zero, the application can query certain metadata // such as file, directory, or device attributes without accessing // that file or device, even if GENERIC_READ access would have been denied. - using (SafeFileHandle handle = OpenReparsePoint(filePath, FileDesiredAccess.GenericZero)) + using (SafeFileHandle handle = WinOpenReparsePoint(filePath, FileDesiredAccess.GenericZero)) { int outBufferSize = Marshal.SizeOf(); @@ -8156,16 +8186,20 @@ private static string WinInternalGetLinkType(string filePath) // Get Buffer size IntPtr dangerousHandle = handle.DangerousGetHandle(); - bool result = DeviceIoControl(dangerousHandle, FSCTL_GET_REPARSE_POINT, - IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); + bool result = DeviceIoControl( + dangerousHandle, + FSCTL_GET_REPARSE_POINT, + InBuffer: IntPtr.Zero, + nInBufferSize: 0, + outBuffer, + outBufferSize, + out bytesReturned, + lpOverlapped: IntPtr.Zero); if (!result) { - int lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_NOT_A_REPARSE_POINT) - linkType = null; - else - throw new Win32Exception(lastError); + // It's not a reparse point or the file system doesn't support reparse points. + return IsHardLink(ref dangerousHandle) ? "HardLink" : null; } REPARSE_DATA_BUFFER_SYMBOLICLINK reparseDataBuffer = Marshal.PtrToStructure(outBuffer); @@ -8180,12 +8214,8 @@ private static string WinInternalGetLinkType(string filePath) linkType = "Junction"; break; - case IO_REPARSE_TAG_APPEXECLINK: - linkType = "AppExeCLink"; - break; - default: - linkType = IsHardLink(ref dangerousHandle) ? "HardLink" : null; + linkType = null; break; } @@ -8217,28 +8247,55 @@ internal static bool IsReparsePoint(FileSystemInfo fileInfo) return fileInfo.Attributes.HasFlag(System.IO.FileAttributes.ReparsePoint); } - internal static bool IsReparsePointWithTarget(FileSystemInfo fileInfo) + internal static bool IsReparsePointLikeSymlink(FileSystemInfo fileInfo) { - if (!IsReparsePoint(fileInfo)) +#if UNIX + // Reparse point on Unix is a symlink. + return IsReparsePoint(fileInfo); +#else + if (InternalTestHooks.OneDriveTestOn && fileInfo.Name == InternalTestHooks.OneDriveTestSymlinkName) { - return false; + return !InternalTestHooks.OneDriveTestRecurseOn; } -#if !UNIX - // It is a reparse point and we should check some reparse point tags. - var data = new WIN32_FIND_DATA(); - using (var handle = FindFirstFileEx(fileInfo.FullName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0)) + + WIN32_FIND_DATA data = default; + string fullPath = Path.TrimEndingDirectorySeparator(fileInfo.FullName); + if (fullPath.Length > MAX_PATH) + { + fullPath = PathUtils.EnsureExtendedPrefix(fullPath); + } + + using (SafeFindHandle handle = FindFirstFileEx(fullPath, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0)) { + if (handle.IsInvalid) + { + // Our handle could be invalidated by something else touching the filesystem, + // so ensure we deal with that possibility here + int lastError = Marshal.GetLastWin32Error(); + throw new Win32Exception(lastError); + } + + // We already have the file attribute information from our Win32 call, + // so no need to take the expense of the FileInfo.FileAttributes call + const int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400; + if ((data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) + { + // Not a reparse point. + return false; + } + // The name surrogate bit 0x20000000 is defined in https://docs.microsoft.com/windows/win32/fileio/reparse-point-tags // Name surrogates (0x20000000) are reparse points that point to other named entities local to the filesystem // (like symlinks and mount points). // In the case of OneDrive, they are not name surrogates and would be safe to recurse into. - if (!handle.IsInvalid && (data.dwReserved0 & 0x20000000) == 0 && (data.dwReserved0 != IO_REPARSE_TAG_APPEXECLINK)) + if ((data.dwReserved0 & 0x20000000) == 0 && (data.dwReserved0 != IO_REPARSE_TAG_APPEXECLINK)) { return false; } } -#endif + return true; +#endif } internal static bool WinIsHardLink(FileSystemInfo fileInfo) @@ -8290,10 +8347,10 @@ internal static bool IsSameFileSystemItem(string pathOne, string pathTwo) #if !UNIX private static bool WinIsSameFileSystemItem(string pathOne, string pathTwo) { - var access = FileAccess.Read; - var share = FileShare.Read; - var creation = FileMode.Open; - var attributes = FileAttributes.BackupSemantics | FileAttributes.PosixSemantics; + const FileAccess access = FileAccess.Read; + const FileShare share = FileShare.Read; + const FileMode creation = FileMode.Open; + const FileAttributes attributes = FileAttributes.BackupSemantics | FileAttributes.PosixSemantics; using (var sfOne = AlternateDataStreamUtilities.NativeMethods.CreateFile(pathOne, access, share, IntPtr.Zero, creation, (int)attributes, IntPtr.Zero)) using (var sfTwo = AlternateDataStreamUtilities.NativeMethods.CreateFile(pathTwo, access, share, IntPtr.Zero, creation, (int)attributes, IntPtr.Zero)) @@ -8329,10 +8386,10 @@ internal static bool GetInodeData(string path, out System.ValueTuple inodeData) { - var access = FileAccess.Read; - var share = FileShare.Read; - var creation = FileMode.Open; - var attributes = FileAttributes.BackupSemantics | FileAttributes.PosixSemantics; + const FileAccess access = FileAccess.Read; + const FileShare share = FileShare.Read; + const FileMode creation = FileMode.Open; + const FileAttributes attributes = FileAttributes.BackupSemantics | FileAttributes.PosixSemantics; using (var sf = AlternateDataStreamUtilities.NativeMethods.CreateFile(path, access, share, IntPtr.Zero, creation, (int)attributes, IntPtr.Zero)) { @@ -8353,9 +8410,11 @@ private static bool WinGetInodeData(string path, out System.ValueTuple 1); } -#if !UNIX - internal static string WinInternalGetTarget(string path) - { - // We set accessMode parameter to zero because documentation says: - // If this parameter is zero, the application can query certain metadata - // such as file, directory, or device attributes without accessing - // that file or device, even if GENERIC_READ access would have been denied. - using (SafeFileHandle handle = OpenReparsePoint(path, FileDesiredAccess.GenericZero)) - { - return WinInternalGetTarget(handle); - } - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] - private static string WinInternalGetTarget(SafeFileHandle handle) - { - int outBufferSize = Marshal.SizeOf(); - - IntPtr outBuffer = Marshal.AllocHGlobal(outBufferSize); - bool success = false; - - try - { - int bytesReturned; - - // OACR warning 62001 about using DeviceIOControl has been disabled. - // According to MSDN guidance DangerousAddRef() and DangerousRelease() have been used. - handle.DangerousAddRef(ref success); - - bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_GET_REPARSE_POINT, - IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); - - if (!result) - { - int lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_NOT_A_REPARSE_POINT) - return null; - - throw new Win32Exception(lastError); - } - - string targetDir = null; - - REPARSE_DATA_BUFFER_SYMBOLICLINK reparseDataBuffer = Marshal.PtrToStructure(outBuffer); - - switch (reparseDataBuffer.ReparseTag) - { - case IO_REPARSE_TAG_SYMLINK: - targetDir = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer, reparseDataBuffer.SubstituteNameOffset, reparseDataBuffer.SubstituteNameLength); - break; - - case IO_REPARSE_TAG_MOUNT_POINT: - REPARSE_DATA_BUFFER_MOUNTPOINT reparseMountPointDataBuffer = Marshal.PtrToStructure(outBuffer); - targetDir = Encoding.Unicode.GetString(reparseMountPointDataBuffer.PathBuffer, reparseMountPointDataBuffer.SubstituteNameOffset, reparseMountPointDataBuffer.SubstituteNameLength); - break; - - case IO_REPARSE_TAG_APPEXECLINK: - REPARSE_DATA_BUFFER_APPEXECLINK reparseAppExeDataBuffer = Marshal.PtrToStructure(outBuffer); - // The target file is at index 2 - if (reparseAppExeDataBuffer.StringCount >= 3) - { - string temp = Encoding.Unicode.GetString(reparseAppExeDataBuffer.StringList); - targetDir = temp.Split('\0')[2]; - } - break; - - default: - return null; - } - - if (targetDir != null && targetDir.StartsWith(NonInterpretedPathPrefix, StringComparison.OrdinalIgnoreCase)) - { - targetDir = targetDir.Substring(NonInterpretedPathPrefix.Length); - } - - return targetDir; - } - finally - { - if (success) - { - handle.DangerousRelease(); - } - - Marshal.FreeHGlobal(outBuffer); - } - } -#endif - internal static bool CreateJunction(string path, string target) { - // this is a purely Windows specific feature, no feature flag - // used for that reason + // this is a purely Windows specific feature, no feature flag used for that reason. if (Platform.IsWindows) { return WinCreateJunction(path, target); } - else - { - return false; - } + + return false; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] private static bool WinCreateJunction(string path, string target) { - if (!string.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) { - if (!string.IsNullOrEmpty(target)) - { - using (SafeHandle handle = OpenReparsePoint(path, FileDesiredAccess.GenericWrite)) - { - byte[] mountPointBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Path.GetFullPath(target)); + throw new ArgumentNullException(nameof(path)); + } - REPARSE_DATA_BUFFER_MOUNTPOINT mountPoint = new REPARSE_DATA_BUFFER_MOUNTPOINT(); - mountPoint.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - mountPoint.ReparseDataLength = (ushort)(mountPointBytes.Length + 12); // Added space for the header and null endo - mountPoint.SubstituteNameOffset = 0; - mountPoint.SubstituteNameLength = (ushort)mountPointBytes.Length; - mountPoint.PrintNameOffset = (ushort)(mountPointBytes.Length + 2); // 2 as unicode null take 2 bytes. - mountPoint.PrintNameLength = 0; - mountPoint.PathBuffer = new byte[0x3FF0]; // Buffer for max size. - Array.Copy(mountPointBytes, mountPoint.PathBuffer, mountPointBytes.Length); + if (string.IsNullOrEmpty(target)) + { + throw new ArgumentNullException(nameof(target)); + } - int nativeBufferSize = Marshal.SizeOf(mountPoint); - IntPtr nativeBuffer = Marshal.AllocHGlobal(nativeBufferSize); - bool success = false; + using (SafeHandle handle = WinOpenReparsePoint(path, FileDesiredAccess.GenericWrite)) + { + byte[] mountPointBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Path.GetFullPath(target)); - try - { - Marshal.StructureToPtr(mountPoint, nativeBuffer, false); + var mountPoint = new REPARSE_DATA_BUFFER_MOUNTPOINT(); + mountPoint.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + mountPoint.ReparseDataLength = (ushort)(mountPointBytes.Length + 12); // Added space for the header and null endo + mountPoint.SubstituteNameOffset = 0; + mountPoint.SubstituteNameLength = (ushort)mountPointBytes.Length; + mountPoint.PrintNameOffset = (ushort)(mountPointBytes.Length + 2); // 2 as unicode null take 2 bytes. + mountPoint.PrintNameLength = 0; + mountPoint.PathBuffer = new byte[0x3FF0]; // Buffer for max size. + Array.Copy(mountPointBytes, mountPoint.PathBuffer, mountPointBytes.Length); - int bytesReturned = 0; + int nativeBufferSize = Marshal.SizeOf(mountPoint); + IntPtr nativeBuffer = Marshal.AllocHGlobal(nativeBufferSize); + bool success = false; - // OACR warning 62001 about using DeviceIOControl has been disabled. - // According to MSDN guidance DangerousAddRef() and DangerousRelease() have been used. - handle.DangerousAddRef(ref success); + try + { + Marshal.StructureToPtr(mountPoint, nativeBuffer, false); - bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT, nativeBuffer, mountPointBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); + int bytesReturned = 0; - if (!result) - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } + // OACR warning 62001 about using DeviceIOControl has been disabled. + // According to MSDN guidance DangerousAddRef() and DangerousRelease() have been used. + handle.DangerousAddRef(ref success); - return result; - } - finally - { - Marshal.FreeHGlobal(nativeBuffer); + bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT, nativeBuffer, mountPointBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); - if (success) - { - handle.DangerousRelease(); - } - } + if (!result) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); } + + return result; } - else + finally { - throw new ArgumentNullException(nameof(target)); + Marshal.FreeHGlobal(nativeBuffer); + + if (success) + { + handle.DangerousRelease(); + } } } - else - { - throw new ArgumentNullException(nameof(path)); - } - } - - private static SafeFileHandle OpenReparsePoint(string reparsePoint, FileDesiredAccess accessMode) - { -#if UNIX - throw new PlatformNotSupportedException(); -#else - return WinOpenReparsePoint(reparsePoint, accessMode); -#endif } private static SafeFileHandle WinOpenReparsePoint(string reparsePoint, FileDesiredAccess accessMode) @@ -8622,7 +8576,22 @@ internal static List GetStreams(string path) SafeFindHandle handle = NativeMethods.FindFirstStreamW( path, NativeMethods.StreamInfoLevels.FindStreamInfoStandard, findStreamData, 0); - if (handle.IsInvalid) throw new Win32Exception(); + + if (handle.IsInvalid) + { + int error = Marshal.GetLastWin32Error(); + + // Directories don't normally have alternate streams, so this is not an exceptional state. + // If a directory has no alternate data streams, FindFirstStreamW returns ERROR_HANDLE_EOF. + if (error == NativeMethods.ERROR_HANDLE_EOF) + { + return alternateStreams; + } + + // An unexpected error was returned, that we don't know how to interpret. The most helpful + // thing we can do at this point is simply throw the raw Win32 exception. + throw new Win32Exception(error); + } try { @@ -8632,7 +8601,7 @@ internal static List GetStreams(string path) findStreamData.Name = findStreamData.Name.Substring(1); // And trailing :$DATA (as long as it's not the default data stream) - string dataStream = ":$DATA"; + const string dataStream = ":$DATA"; if (!string.Equals(findStreamData.Name, dataStream, StringComparison.OrdinalIgnoreCase)) { findStreamData.Name = findStreamData.Name.Replace(dataStream, string.Empty); @@ -8757,6 +8726,7 @@ internal static void SetZoneOfOrigin(string path, SecurityZone securityZone) internal static class NativeMethods { internal const int ERROR_HANDLE_EOF = 38; + internal const int ERROR_INVALID_PARAMETER = 87; internal enum StreamInfoLevels { FindStreamInfoStandard = 0 } @@ -8830,9 +8800,9 @@ internal static class CopyFileRemoteUtils internal const string PSCopyToSessionHelperName = @"PSCopyToSessionHelper"; - private static string s_driveMaxSizeErrorFormatString = FileSystemProviderStrings.DriveMaxSizeError; - private static string s_PSCopyToSessionHelperDefinition = StringUtil.Format(PSCopyToSessionHelperDefinitionFormat, @"[ValidateNotNullOrEmpty()]", s_driveMaxSizeErrorFormatString); - private static string s_PSCopyToSessionHelperDefinitionRestricted = StringUtil.Format(PSCopyToSessionHelperDefinitionFormat, @"[ValidateUserDrive()]", s_driveMaxSizeErrorFormatString); + private static readonly string s_driveMaxSizeErrorFormatString = FileSystemProviderStrings.DriveMaxSizeError; + private static readonly string s_PSCopyToSessionHelperDefinition = StringUtil.Format(PSCopyToSessionHelperDefinitionFormat, @"[ValidateNotNullOrEmpty()]", s_driveMaxSizeErrorFormatString); + private static readonly string s_PSCopyToSessionHelperDefinitionRestricted = StringUtil.Format(PSCopyToSessionHelperDefinitionFormat, @"[ValidateUserDrive()]", s_driveMaxSizeErrorFormatString); private const string PSCopyToSessionHelperDefinitionFormat = @" param ( @@ -9281,13 +9251,13 @@ function PSCreateDirectoryOnRemoteSession }} "; - private static string s_PSCopyToSessionHelper = functionToken + PSCopyToSessionHelperName + @" + private static readonly string s_PSCopyToSessionHelper = functionToken + PSCopyToSessionHelperName + @" { " + s_PSCopyToSessionHelperDefinition + @" } "; - private static Hashtable s_PSCopyToSessionHelperFunction = new Hashtable() { + private static readonly Hashtable s_PSCopyToSessionHelperFunction = new Hashtable() { {nameToken, PSCopyToSessionHelperName}, {definitionToken, s_PSCopyToSessionHelperDefinitionRestricted} }; @@ -9298,8 +9268,8 @@ function PSCreateDirectoryOnRemoteSession internal const string PSCopyFromSessionHelperName = @"PSCopyFromSessionHelper"; - private static string s_PSCopyFromSessionHelperDefinition = StringUtil.Format(PSCopyFromSessionHelperDefinitionFormat, @"[ValidateNotNullOrEmpty()]"); - private static string s_PSCopyFromSessionHelperDefinitionRestricted = StringUtil.Format(PSCopyFromSessionHelperDefinitionFormat, @"[ValidateUserDrive()]"); + private static readonly string s_PSCopyFromSessionHelperDefinition = StringUtil.Format(PSCopyFromSessionHelperDefinitionFormat, @"[ValidateNotNullOrEmpty()]"); + private static readonly string s_PSCopyFromSessionHelperDefinitionRestricted = StringUtil.Format(PSCopyFromSessionHelperDefinitionFormat, @"[ValidateUserDrive()]"); private const string PSCopyFromSessionHelperDefinitionFormat = @" param ( @@ -9778,7 +9748,7 @@ PSGetPathDirAndFiles @params } "; - private static Hashtable s_PSCopyFromSessionHelperFunction = new Hashtable() { + private static readonly Hashtable s_PSCopyFromSessionHelperFunction = new Hashtable() { {nameToken, PSCopyFromSessionHelperName}, {definitionToken, s_PSCopyFromSessionHelperDefinitionRestricted} }; @@ -9790,7 +9760,7 @@ PSGetPathDirAndFiles @params internal const string PSCopyRemoteUtilsName = @"PSCopyRemoteUtils"; internal static readonly string PSCopyRemoteUtilsDefinition = StringUtil.Format(PSCopyRemoteUtilsDefinitionFormat, @"[ValidateNotNullOrEmpty()]", PSValidatePathFunction); - private static string s_PSCopyRemoteUtilsDefinitionRestricted = StringUtil.Format(PSCopyRemoteUtilsDefinitionFormat, @"[ValidateUserDrive()]", PSValidatePathFunction); + private static readonly string s_PSCopyRemoteUtilsDefinitionRestricted = StringUtil.Format(PSCopyRemoteUtilsDefinitionFormat, @"[ValidateUserDrive()]", PSValidatePathFunction); private const string PSCopyRemoteUtilsDefinitionFormat = @" param ( diff --git a/src/System.Management.Automation/namespaces/FileSystemSecurity.cs b/src/System.Management.Automation/namespaces/FileSystemSecurity.cs index 8a95b16ee8b..97ab38158ae 100644 --- a/src/System.Management.Automation/namespaces/FileSystemSecurity.cs +++ b/src/System.Management.Automation/namespaces/FileSystemSecurity.cs @@ -340,4 +340,3 @@ private static ErrorRecord CreateErrorRecord(string path, #endregion ISecurityDescriptorCmdletProvider members } } - diff --git a/src/System.Management.Automation/namespaces/FunctionProvider.cs b/src/System.Management.Automation/namespaces/FunctionProvider.cs index 1843d1edff8..ea3d9a7509c 100644 --- a/src/System.Management.Automation/namespaces/FunctionProvider.cs +++ b/src/System.Management.Automation/namespaces/FunctionProvider.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Collections.ObjectModel; using System.Management.Automation; @@ -362,7 +361,10 @@ public class FunctionProviderDynamicParameters [Parameter] public ScopedItemOptions Options { - get { return _options; } + get + { + return _options; + } set { @@ -385,4 +387,3 @@ internal bool OptionsSet private bool _optionsSet; } } - diff --git a/src/System.Management.Automation/namespaces/IContentProvider.cs b/src/System.Management.Automation/namespaces/IContentProvider.cs index 7c91019124d..b3773ca0973 100644 --- a/src/System.Management.Automation/namespaces/IContentProvider.cs +++ b/src/System.Management.Automation/namespaces/IContentProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable namespace System.Management.Automation.Provider { #region IContentCmdletProvider @@ -46,7 +47,7 @@ public interface IContentCmdletProvider /// the user unless the Force property is set to true. An error should be sent to the WriteError method if /// the path represents an item that is hidden from the user and Force is set to false. /// - IContentReader GetContentReader(string path); + IContentReader? GetContentReader(string path); /// /// Gives the provider an opportunity to attach additional parameters to the @@ -63,7 +64,7 @@ public interface IContentCmdletProvider /// /// The default implementation returns null. (no additional parameters) /// - object GetContentReaderDynamicParameters(string path); + object? GetContentReaderDynamicParameters(string path); /// /// Gets the content writer for the item at the specified path. @@ -87,7 +88,7 @@ public interface IContentCmdletProvider /// the user unless the Force property is set to true. An error should be sent to the WriteError method if /// the path represents an item that is hidden from the user and Force is set to false. /// - IContentWriter GetContentWriter(string path); + IContentWriter? GetContentWriter(string path); /// /// Gives the provider an opportunity to attach additional parameters to the @@ -104,7 +105,7 @@ public interface IContentCmdletProvider /// /// The default implementation returns null. (no additional parameters) /// - object GetContentWriterDynamicParameters(string path); + object? GetContentWriterDynamicParameters(string path); /// /// Clears the content from the specified item. @@ -141,9 +142,8 @@ public interface IContentCmdletProvider /// /// The default implementation returns null. (no additional parameters) /// - object ClearContentDynamicParameters(string path); + object? ClearContentDynamicParameters(string path); } #endregion IContentCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/IContentReader.cs b/src/System.Management.Automation/namespaces/IContentReader.cs index 8835d948ddd..6046fee73ed 100644 --- a/src/System.Management.Automation/namespaces/IContentReader.cs +++ b/src/System.Management.Automation/namespaces/IContentReader.cs @@ -4,6 +4,7 @@ using System.Collections; using System.IO; +#nullable enable namespace System.Management.Automation.Provider { #region IContentReader @@ -65,4 +66,3 @@ public interface IContentReader : IDisposable #endregion IContentReader } - diff --git a/src/System.Management.Automation/namespaces/IContentWriter.cs b/src/System.Management.Automation/namespaces/IContentWriter.cs index e01ed0c9cb4..621808af80c 100644 --- a/src/System.Management.Automation/namespaces/IContentWriter.cs +++ b/src/System.Management.Automation/namespaces/IContentWriter.cs @@ -4,6 +4,7 @@ using System.Collections; using System.IO; +#nullable enable namespace System.Management.Automation.Provider { #region IContentWriter @@ -66,4 +67,3 @@ public interface IContentWriter : IDisposable #endregion IContentWriter } - diff --git a/src/System.Management.Automation/namespaces/IDynamicPropertyProvider.cs b/src/System.Management.Automation/namespaces/IDynamicPropertyProvider.cs index d7265e7380f..232f3f5d78b 100644 --- a/src/System.Management.Automation/namespaces/IDynamicPropertyProvider.cs +++ b/src/System.Management.Automation/namespaces/IDynamicPropertyProvider.cs @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable namespace System.Management.Automation.Provider { #region IDynamicPropertyCmdletProvider - /// /// An interface that can be implemented on a Cmdlet provider to expose the dynamic /// manipulation of properties. @@ -61,7 +61,7 @@ void NewProperty( string path, string propertyName, string propertyTypeName, - object value); + object? value); /// /// Gives the provider an opportunity to attach additional parameters to the @@ -87,11 +87,11 @@ void NewProperty( /// /// The default implementation returns null. (no additional parameters) /// - object NewPropertyDynamicParameters( + object? NewPropertyDynamicParameters( string path, string propertyName, string propertyTypeName, - object value); + object? value); /// /// Removes a property on the item specified by the path. @@ -196,7 +196,7 @@ void RenameProperty( /// /// The default implementation returns null. (no additional parameters) /// - object RenamePropertyDynamicParameters( + object? RenamePropertyDynamicParameters( string path, string sourceProperty, string destinationProperty); @@ -262,7 +262,7 @@ void CopyProperty( /// /// The default implementation returns null. (no additional parameters) /// - object CopyPropertyDynamicParameters( + object? CopyPropertyDynamicParameters( string sourcePath, string sourceProperty, string destinationPath, @@ -328,7 +328,7 @@ void MoveProperty( /// /// The default implementation returns null. (no additional parameters) /// - object MovePropertyDynamicParameters( + object? MovePropertyDynamicParameters( string sourcePath, string sourceProperty, string destinationPath, @@ -337,4 +337,3 @@ object MovePropertyDynamicParameters( #endregion IDynamicPropertyCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/IPermissionProvider.cs b/src/System.Management.Automation/namespaces/IPermissionProvider.cs index 13b41261a19..c4f548e08a7 100644 --- a/src/System.Management.Automation/namespaces/IPermissionProvider.cs +++ b/src/System.Management.Automation/namespaces/IPermissionProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable using System.Security.AccessControl; namespace System.Management.Automation.Provider diff --git a/src/System.Management.Automation/namespaces/IPropertiesProvider.cs b/src/System.Management.Automation/namespaces/IPropertiesProvider.cs index 2a347fafbce..1f4a6c168fe 100644 --- a/src/System.Management.Automation/namespaces/IPropertiesProvider.cs +++ b/src/System.Management.Automation/namespaces/IPropertiesProvider.cs @@ -3,6 +3,7 @@ using System.Collections.ObjectModel; +#nullable enable namespace System.Management.Automation.Provider { #region IPropertyCmdletProvider @@ -58,7 +59,7 @@ public interface IPropertyCmdletProvider /// void GetProperty( string path, - Collection providerSpecificPickList); + Collection? providerSpecificPickList); /// /// Gives the provider an opportunity to attach additional parameters to the @@ -79,9 +80,9 @@ void GetProperty( /// /// The default implementation returns null. (no additional parameters) /// - object GetPropertyDynamicParameters( + object? GetPropertyDynamicParameters( string path, - Collection providerSpecificPickList); + Collection? providerSpecificPickList); /// /// Sets the specified properties of the item at the specified path. @@ -137,7 +138,7 @@ void SetProperty( /// /// The default implementation returns null. (no additional parameters) /// - object SetPropertyDynamicParameters( + object? SetPropertyDynamicParameters( string path, PSObject propertyValue); @@ -191,11 +192,10 @@ void ClearProperty( /// /// The default implementation returns null. (no additional parameters) /// - object ClearPropertyDynamicParameters( + object? ClearPropertyDynamicParameters( string path, Collection propertyToClear); } #endregion IPropertyCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/ItemProviderBase.cs b/src/System.Management.Automation/namespaces/ItemProviderBase.cs index c563f48aaec..eff6782f713 100644 --- a/src/System.Management.Automation/namespaces/ItemProviderBase.cs +++ b/src/System.Management.Automation/namespaces/ItemProviderBase.cs @@ -688,4 +688,3 @@ protected virtual string[] ExpandPath(string path) #endregion ItemCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/LocationGlobber.cs b/src/System.Management.Automation/namespaces/LocationGlobber.cs index d5e60b652c9..e4ab1f3cfc5 100644 --- a/src/System.Management.Automation/namespaces/LocationGlobber.cs +++ b/src/System.Management.Automation/namespaces/LocationGlobber.cs @@ -25,7 +25,7 @@ internal sealed class LocationGlobber [Dbg.TraceSourceAttribute( "LocationGlobber", "The location globber converts PowerShell paths with glob characters to zero or more paths.")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("LocationGlobber", "The location globber converts PowerShell paths with glob characters to zero or more paths."); @@ -35,7 +35,7 @@ internal sealed class LocationGlobber [Dbg.TraceSourceAttribute( "PathResolution", "Traces the path resolution algorithm.")] - private static Dbg.PSTraceSource s_pathResolutionTracer = + private static readonly Dbg.PSTraceSource s_pathResolutionTracer = Dbg.PSTraceSource.GetTracer( "PathResolution", "Traces the path resolution algorithm.", @@ -52,7 +52,7 @@ internal sealed class LocationGlobber /// The instance of session state on which this location globber acts. /// /// - /// If is null. + /// If is null. /// internal LocationGlobber(SessionState sessionState) { @@ -1654,7 +1654,7 @@ internal bool IsAbsolutePath(string path, out string driveName) /// /// The instance of session state on which this globber acts. /// - private SessionState _sessionState; + private readonly SessionState _sessionState; /// /// Removes the back tick "`" from any of the glob characters in the path. @@ -1666,7 +1666,7 @@ internal bool IsAbsolutePath(string path, out string driveName) /// The path with the glob characters unescaped. /// /// - /// If is null. + /// If is null. /// private static string RemoveGlobEscaping(string path) { @@ -1699,7 +1699,7 @@ private static string RemoveGlobEscaping(string path) /// false otherwise. /// /// - /// If is null. + /// If is null. /// /// /// The comparison is done using a case-insensitive comparison using the @@ -1763,7 +1763,7 @@ internal bool IsShellVirtualDrive(string driveName, out SessionStateScope scope) /// /// /// This out parameter returns the drive that was specified - /// by the . If is + /// by the . If is /// an absolute path this value may be something other than /// the current working drive. /// @@ -1789,7 +1789,7 @@ internal bool IsShellVirtualDrive(string driveName, out SessionStateScope scope) /// This is internal so that it can be called from SessionState /// /// - /// If is null. + /// If is null. /// /// /// If the refers to a drive that could not be found. @@ -2272,7 +2272,7 @@ internal string GenerateRelativePath( return driveRootRelativeWorkingPath; } - private bool HasRelativePathTokens(string path) + private static bool HasRelativePathTokens(string path) { string comparePath = path.Replace('/', '\\'); @@ -2417,7 +2417,7 @@ private static string ParseProviderPath(string path, out string providerId) /// paths. Instead an appropriate path will be returned as if it did exist. /// /// - /// The provider that will be used to glob the . + /// The provider that will be used to glob the . /// /// /// The context under which the command is occurring. @@ -3273,27 +3273,27 @@ internal static string RemoveProviderQualifier(string path) /// /// Generates a collection of containers and/or leaves that are children of the containers /// in the currentDirs parameter and match the glob expression in the - /// parameter. + /// parameter. /// /// /// A collection of paths that should be searched for leaves that match the - /// expression. + /// expression. /// /// /// The drive the Msh path is relative to. /// /// /// A single element of a path that may or may not contain a glob expression. This parameter - /// is used to search the containers in for children that + /// is used to search the containers in for children that /// match the glob expression. /// /// - /// True if the is the last element to glob over. If false, we + /// True if the is the last element to glob over. If false, we /// need to get all container names from the provider even if they don't match the filter. /// /// /// The provider associated with the paths that are being passed in the - /// and parameters. + /// and parameters. /// The provider must derive from ContainerCmdletProvider or NavigationCmdletProvider /// in order to get globbing. /// @@ -3302,10 +3302,10 @@ internal static string RemoveProviderQualifier(string path) /// /// /// A collection of fully qualified namespace paths whose leaf element matches the - /// expression. + /// expression. /// /// - /// If or + /// If or /// is null. /// /// @@ -3892,24 +3892,24 @@ internal Collection ExpandGlobPath( /// /// Generates a collection of containers and/or leaves that are children of the containers /// in the currentDirs parameter and match the glob expression in the - /// parameter. + /// parameter. /// /// /// A collection of paths that should be searched for leaves that match the - /// expression. + /// expression. /// /// /// A single element of a path that may or may not contain a glob expression. This parameter - /// is used to search the containers in for children that + /// is used to search the containers in for children that /// match the glob expression. /// /// - /// True if the is the last element to glob over. If false, we + /// True if the is the last element to glob over. If false, we /// need to get all container names from the provider even if they don't match the filter. /// /// /// The provider associated with the paths that are being passed in the - /// and parameters. + /// and parameters. /// The provider must derive from ContainerCmdletProvider or NavigationCmdletProvider /// in order to get globbing. /// @@ -3918,10 +3918,10 @@ internal Collection ExpandGlobPath( /// /// /// A collection of fully qualified namespace paths whose leaf element matches the - /// expression. + /// expression. /// /// - /// If or + /// If or /// is null. /// /// diff --git a/src/System.Management.Automation/namespaces/NavigationProviderBase.cs b/src/System.Management.Automation/namespaces/NavigationProviderBase.cs index 42dd3b32b36..da8a16869d1 100644 --- a/src/System.Management.Automation/namespaces/NavigationProviderBase.cs +++ b/src/System.Management.Automation/namespaces/NavigationProviderBase.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Management.Automation.Internal; -using System.Text; namespace System.Management.Automation.Provider { @@ -651,7 +650,7 @@ internal string ContractRelativePath( if (originalPathHadTrailingSlash) { - result = result + StringLiterals.DefaultPathSeparator; + result += StringLiterals.DefaultPathSeparator; } return result; @@ -1037,8 +1036,7 @@ private static Stack NormalizeThePath( if (!allowNonExistingPaths) { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(path), SessionStateStrings.NormalizeRelativePathOutsideBase, path, @@ -1094,4 +1092,3 @@ private string CreateNormalizedRelativePathFromStack(Stack normalizedPat #endregion NavigationCmdletProvider } - diff --git a/src/System.Management.Automation/namespaces/PathInfo.cs b/src/System.Management.Automation/namespaces/PathInfo.cs index cd91845f84c..f49d478c5e1 100644 --- a/src/System.Management.Automation/namespaces/PathInfo.cs +++ b/src/System.Management.Automation/namespaces/PathInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Dbg = System.Management.Automation; - namespace System.Management.Automation { /// @@ -78,7 +76,7 @@ public string ProviderPath } private string _providerPath; - private SessionState _sessionState; + private readonly SessionState _sessionState; /// /// Gets the MSH path that this object represents. @@ -91,9 +89,9 @@ public string Path } } - private PSDriveInfo _drive; - private ProviderInfo _provider; - private string _path = string.Empty; + private readonly PSDriveInfo _drive; + private readonly ProviderInfo _provider; + private readonly string _path = string.Empty; /// /// Gets a string representing the MSH path. diff --git a/src/System.Management.Automation/namespaces/ProviderBase.cs b/src/System.Management.Automation/namespaces/ProviderBase.cs index 326d4d51b04..d3fad54bdd7 100644 --- a/src/System.Management.Automation/namespaces/ProviderBase.cs +++ b/src/System.Management.Automation/namespaces/ProviderBase.cs @@ -9,17 +9,18 @@ using System.Management.Automation.Runspaces; using System.Management.Automation.Internal; using System.Management.Automation.Host; -using System.Reflection; using System.Resources; using System.Diagnostics.CodeAnalysis; // for fxcop using System.Security.AccessControl; namespace System.Management.Automation.Provider { + /// /// This interface needs to be implemented by providers that want users to see /// provider-specific help. /// +#nullable enable public interface ICmdletProviderSupportsHelp { /// @@ -38,7 +39,7 @@ public interface ICmdletProviderSupportsHelp [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Maml", Justification = "Maml is an acronym.")] string GetHelpMaml(string helpItemName, string path); } - +#nullable restore #region CmdletProvider /// @@ -259,9 +260,7 @@ internal void GetProperty( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -299,9 +298,7 @@ internal object GetPropertyDynamicParameters( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { return null; } @@ -330,9 +327,7 @@ internal void SetProperty( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -370,9 +365,7 @@ internal object SetPropertyDynamicParameters( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { return null; } @@ -404,9 +397,7 @@ internal void ClearProperty( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -444,9 +435,7 @@ internal object ClearPropertyDynamicParameters( { Context = cmdletProviderContext; - IPropertyCmdletProvider propertyProvider = this as IPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IPropertyCmdletProvider propertyProvider)) { return null; } @@ -490,9 +479,7 @@ internal void NewProperty( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -537,9 +524,7 @@ internal object NewPropertyDynamicParameters( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { return null; } @@ -571,9 +556,7 @@ internal void RemoveProperty( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -610,9 +593,7 @@ internal object RemovePropertyDynamicParameters( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { return null; } @@ -648,9 +629,7 @@ internal void RenameProperty( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -691,9 +670,7 @@ internal object RenamePropertyDynamicParameters( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { return null; } @@ -733,9 +710,7 @@ internal void CopyProperty( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -780,9 +755,7 @@ internal object CopyPropertyDynamicParameters( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { return null; } @@ -822,9 +795,7 @@ internal void MoveProperty( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -869,9 +840,7 @@ internal object MovePropertyDynamicParameters( { Context = cmdletProviderContext; - IDynamicPropertyCmdletProvider propertyProvider = this as IDynamicPropertyCmdletProvider; - - if (propertyProvider == null) + if (!(this is IDynamicPropertyCmdletProvider propertyProvider)) { return null; } @@ -902,9 +871,7 @@ internal IContentReader GetContentReader( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -937,9 +904,7 @@ internal object GetContentReaderDynamicParameters( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { return null; } @@ -966,9 +931,7 @@ internal IContentWriter GetContentWriter( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -1001,9 +964,7 @@ internal object GetContentWriterDynamicParameters( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { return null; } @@ -1027,9 +988,7 @@ internal void ClearContent( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { throw PSTraceSource.NewNotSupportedException( @@ -1062,9 +1021,7 @@ internal object ClearContentDynamicParameters( { Context = cmdletProviderContext; - IContentCmdletProvider contentProvider = this as IContentCmdletProvider; - - if (contentProvider == null) + if (!(this is IContentCmdletProvider contentProvider)) { return null; } @@ -1462,6 +1419,7 @@ public virtual string GetResourceString(string baseName, string resourceId) #region ThrowTerminatingError /// + [System.Diagnostics.CodeAnalysis.DoesNotReturn] public void ThrowTerminatingError(ErrorRecord errorRecord) { using (PSTransactionManager.GetEngineProtectionScope()) @@ -1865,11 +1823,11 @@ private PSObject WrapOutputInPSObject( #if UNIX // Add a commonstat structure to file system objects - if (ExperimentalFeature.IsEnabled("PSUnixFileStat") && ProviderInfo.ImplementingType == typeof(Microsoft.PowerShell.Commands.FileSystemProvider)) + if (ProviderInfo.ImplementingType == typeof(Microsoft.PowerShell.Commands.FileSystemProvider)) { try { - // Use LStat because if you get a link, you want the information about the + // Use LStat because if you get a link, you want the information about the // link, not the file. var commonStat = Platform.Unix.GetLStat(path); result.AddOrSetProperty("UnixStat", commonStat); diff --git a/src/System.Management.Automation/namespaces/ProviderDeclarationAttribute.cs b/src/System.Management.Automation/namespaces/ProviderDeclarationAttribute.cs index dbc03a69181..d0c7bd018a1 100644 --- a/src/System.Management.Automation/namespaces/ProviderDeclarationAttribute.cs +++ b/src/System.Management.Automation/namespaces/ProviderDeclarationAttribute.cs @@ -52,7 +52,7 @@ public CmdletProviderAttribute( ProviderCapabilities = providerCapabilities; } - private char[] _illegalCharacters = new char[] { ':', '\\', '[', ']', '?', '*' }; + private readonly char[] _illegalCharacters = new char[] { ':', '\\', '[', ']', '?', '*' }; /// /// Gets the name of the provider. diff --git a/src/System.Management.Automation/namespaces/RegistryProvider.cs b/src/System.Management.Automation/namespaces/RegistryProvider.cs index c0212c700bf..1898c960620 100644 --- a/src/System.Management.Automation/namespaces/RegistryProvider.cs +++ b/src/System.Management.Automation/namespaces/RegistryProvider.cs @@ -76,7 +76,7 @@ public sealed partial class RegistryProvider : [Dbg.TraceSourceAttribute( "RegistryProvider", "The namespace navigation provider for the Windows Registry")] - private static Dbg.PSTraceSource s_tracer = + private static readonly Dbg.PSTraceSource s_tracer = Dbg.PSTraceSource.GetTracer("RegistryProvider", "The namespace navigation provider for the Windows Registry"); @@ -799,7 +799,7 @@ private static string EscapeSpecialChars(string path) if (textElement.Contains(charactersThatNeedEscaping)) { // This text element needs espacing - result.Append("`"); + result.Append('`'); } result.Append(textElement); @@ -848,7 +848,7 @@ private static string EscapeChildName(string name) if (textElement.Contains(charactersThatNeedEscaping)) { // This text element needs espacing - result.Append("`"); + result.Append('`'); } result.Append(textElement); @@ -1819,7 +1819,7 @@ public void GetProperty( // as the property name when adding the note, as // PSObject does not allow an empty propertyName - notePropertyName = GetLocalizedDefaultToken(); + notePropertyName = LocalizedDefaultToken; } propertyResults.Properties.Add(new PSNoteProperty(notePropertyName, key.GetValue(valueName))); @@ -2024,7 +2024,7 @@ public void ClearProperty( string propertyNameToAdd = valueName; if (string.IsNullOrEmpty(valueName)) { - propertyNameToAdd = GetLocalizedDefaultToken(); + propertyNameToAdd = LocalizedDefaultToken; } result.Properties.Add(new PSNoteProperty(propertyNameToAdd, defaultValue)); @@ -2956,7 +2956,7 @@ private string NormalizePath(string path) return result; } - private bool HasRelativePathTokens(string path) + private static bool HasRelativePathTokens(string path) { return ( path.StartsWith('\\') || @@ -3056,13 +3056,13 @@ private void GetFilteredRegistryKeyProperties(string path, if (!string.IsNullOrEmpty(requestedValueName)) { - valueNameToMatch = GetLocalizedDefaultToken(); + valueNameToMatch = LocalizedDefaultToken; } } if ( expandAll || - ((Context.SuppressWildcardExpansion == false) && (valueNameMatcher.IsMatch(valueNameToMatch))) || + ((!Context.SuppressWildcardExpansion) && (valueNameMatcher.IsMatch(valueNameToMatch))) || ((Context.SuppressWildcardExpansion) && (string.Equals(valueNameToMatch, requestedValueName, StringComparison.OrdinalIgnoreCase)))) { if (string.IsNullOrEmpty(valueNameToMatch)) @@ -3071,7 +3071,7 @@ private void GetFilteredRegistryKeyProperties(string path, // as the property name when adding the note, as // PSObject does not allow an empty propertyName - valueNameToMatch = GetLocalizedDefaultToken(); + valueNameToMatch = LocalizedDefaultToken; } hadAMatch = true; @@ -3195,7 +3195,7 @@ private object ResetRegistryKeyValue(IRegistryWrapper key, string valueName) /// /// true if the path is empty, a \ or a /, else false /// - private bool IsHiveContainer(string path) + private static bool IsHiveContainer(string path) { bool result = false; if (path == null) @@ -3783,7 +3783,7 @@ private void WriteWrappedPropertyObject(object value, string propertyName, strin string propertyNameToAdd = propertyName; if (string.IsNullOrEmpty(propertyName)) { - propertyNameToAdd = GetLocalizedDefaultToken(); + propertyNameToAdd = LocalizedDefaultToken; } result.Properties.Add(new PSNoteProperty(propertyNameToAdd, value)); @@ -3814,7 +3814,7 @@ private static object ConvertValueToKind(object value, RegistryValueKind kind) value, typeof(byte[]), CultureInfo.CurrentCulture) - : new byte[] { }; + : Array.Empty(); break; case RegistryValueKind.DWord: @@ -3834,7 +3834,9 @@ private static object ConvertValueToKind(object value, RegistryValueKind kind) { value = 0; } - } break; + } + + break; case RegistryValueKind.ExpandString: value = (value != null) @@ -3851,7 +3853,7 @@ private static object ConvertValueToKind(object value, RegistryValueKind kind) value, typeof(string[]), CultureInfo.CurrentCulture) - : new string[] { }; + : Array.Empty(); break; case RegistryValueKind.QWord: @@ -3871,7 +3873,9 @@ private static object ConvertValueToKind(object value, RegistryValueKind kind) { value = 0; } - } break; + } + + break; case RegistryValueKind.String: value = (value != null) @@ -4029,7 +4033,7 @@ private void WriteRegistryItemObject( if (string.IsNullOrEmpty(valueNames[index])) { // The first unnamed value becomes the default value - valueNames[index] = GetLocalizedDefaultToken(); + valueNames[index] = LocalizedDefaultToken; break; } } @@ -4104,16 +4108,13 @@ private bool ParseKind(string type, out RegistryValueKind kind) /// Gets the default value name token from the resource. /// In English that token is "(default)" without the quotes. /// + /// + /// This should not be localized as it will break scripts. + /// /// /// A string containing the default value name. /// - private string GetLocalizedDefaultToken() - { - // This shouldn't be localized as it will break scripts - - string defaultValueName = "(default)"; - return defaultValueName; - } + private static string LocalizedDefaultToken => "(default)"; /// /// Converts an empty or null userEnteredPropertyName to the localized @@ -4136,7 +4137,7 @@ private string GetPropertyName(string userEnteredPropertyName) if (stringComparer.Compare( userEnteredPropertyName, - GetLocalizedDefaultToken(), + LocalizedDefaultToken, CompareOptions.IgnoreCase) == 0) { result = null; diff --git a/src/System.Management.Automation/namespaces/RegistrySecurity.cs b/src/System.Management.Automation/namespaces/RegistrySecurity.cs index e2452a4e0f9..9308c50dddc 100644 --- a/src/System.Management.Automation/namespaces/RegistrySecurity.cs +++ b/src/System.Management.Automation/namespaces/RegistrySecurity.cs @@ -3,7 +3,6 @@ #if !UNIX -using System; using System.Management.Automation; using System.Management.Automation.Provider; using System.Security.AccessControl; @@ -165,7 +164,7 @@ public void SetSecurityDescriptor( /// Specifies the parts of a security descriptor to create. /// /// - /// An instance of object. + /// An instance of object. /// /// and are not used by this method. public ObjectSecurity NewSecurityDescriptorFromPath( @@ -192,7 +191,7 @@ public ObjectSecurity NewSecurityDescriptorFromPath( /// Specifies the parts of a security descriptor to create. /// /// - /// An instance of object. + /// An instance of object. /// public ObjectSecurity NewSecurityDescriptorOfType( string type, diff --git a/src/System.Management.Automation/namespaces/RegistryWrapper.cs b/src/System.Management.Automation/namespaces/RegistryWrapper.cs index 6f0c3e3d66f..ebdbe833839 100644 --- a/src/System.Management.Automation/namespaces/RegistryWrapper.cs +++ b/src/System.Management.Automation/namespaces/RegistryWrapper.cs @@ -17,30 +17,45 @@ namespace Microsoft.PowerShell.Commands { + +#nullable enable internal interface IRegistryWrapper { - void SetValue(string name, object value); - void SetValue(string name, object value, RegistryValueKind valueKind); + void SetValue(string? name, object value); + + void SetValue(string? name, object value, RegistryValueKind valueKind); + string[] GetValueNames(); + void DeleteValue(string name); + string[] GetSubKeyNames(); - IRegistryWrapper CreateSubKey(string subkey); - IRegistryWrapper OpenSubKey(string name, bool writable); + + IRegistryWrapper? CreateSubKey(string subkey); + + IRegistryWrapper? OpenSubKey(string name, bool writable); + void DeleteSubKeyTree(string subkey); - object GetValue(string name); - object GetValue(string name, object defaultValue, RegistryValueOptions options); - RegistryValueKind GetValueKind(string name); + + object? GetValue(string? name); + + object? GetValue(string? name, object? defaultValue, RegistryValueOptions options); + + RegistryValueKind GetValueKind(string? name); object RegistryKey { get; } void SetAccessControl(ObjectSecurity securityDescriptor); + ObjectSecurity GetAccessControl(AccessControlSections includeSections); + void Close(); string Name { get; } int SubKeyCount { get; } } +#nullable restore internal static class RegistryWrapperUtils { @@ -114,7 +129,7 @@ public static object ConvertUIntToValueForRegistryIfNeeded(object value, Registr internal class RegistryWrapper : IRegistryWrapper { - private RegistryKey _regKey; + private readonly RegistryKey _regKey; internal RegistryWrapper(RegistryKey regKey) { @@ -246,8 +261,8 @@ public ObjectSecurity GetAccessControl(AccessControlSections includeSections) internal class TransactedRegistryWrapper : IRegistryWrapper { - private TransactedRegistryKey _txRegKey; - private CmdletProvider _provider; + private readonly TransactedRegistryKey _txRegKey; + private readonly CmdletProvider _provider; internal TransactedRegistryWrapper(TransactedRegistryKey txRegKey, CmdletProvider provider) { diff --git a/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs b/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs index 33b043ce919..3f0f52c942e 100644 --- a/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs +++ b/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs @@ -326,7 +326,7 @@ protected override void GetChildItems(string path, bool recurse) } sortedEntries.Sort( - delegate (DictionaryEntry left, DictionaryEntry right) + (DictionaryEntry left, DictionaryEntry right) => { string leftKey = (string)left.Key; string rightKey = (string)right.Key; @@ -708,8 +708,7 @@ protected override void NewItem(string path, string type, object newItem) if (ItemExists(path) && !Force) { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(path), SessionStateStrings.NewItemAlreadyExists, path); @@ -838,8 +837,7 @@ protected override void CopyItem(string path, string copyPath, bool recurse) else { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(path), SessionStateStrings.CopyItemDoesntExist, path); @@ -897,8 +895,7 @@ protected override void RenameItem(string name, string newName) if (ItemExists(newName) && !Force) { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(newName), SessionStateStrings.NewItemAlreadyExists, newName); @@ -984,8 +981,7 @@ protected override void RenameItem(string name, string newName) else { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(name), SessionStateStrings.RenameItemDoesntExist, name); @@ -1116,8 +1112,8 @@ internal SessionStateProviderBaseContentReaderWriter(string path, SessionStatePr _provider = provider; } - private string _path; - private SessionStateProviderBase _provider; + private readonly string _path; + private readonly SessionStateProviderBase _provider; /// /// Reads the content from the item. diff --git a/src/System.Management.Automation/namespaces/VariableProvider.cs b/src/System.Management.Automation/namespaces/VariableProvider.cs index 5da5351ebad..5f9934d326c 100644 --- a/src/System.Management.Automation/namespaces/VariableProvider.cs +++ b/src/System.Management.Automation/namespaces/VariableProvider.cs @@ -236,4 +236,3 @@ internal override bool CanRenameItem(object item) } } - diff --git a/src/System.Management.Automation/namespaces/Win32Native.cs b/src/System.Management.Automation/namespaces/Win32Native.cs index 5833f347b6b..b9c7d8a7a71 100644 --- a/src/System.Management.Automation/namespaces/Win32Native.cs +++ b/src/System.Management.Automation/namespaces/Win32Native.cs @@ -16,16 +16,10 @@ namespace Microsoft.PowerShell.Commands.Internal { using System; using System.Security; - using System.Text; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Management.Automation; using System.Diagnostics.CodeAnalysis; - using System.Runtime.ConstrainedExecution; - - using BOOL = System.Int32; - using DWORD = System.UInt32; - using ULONG = System.UInt32; /** * Win32 encapsulation for MSCORLIB. diff --git a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx index 1b4d1159e59..9c232ae836e 100644 --- a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx +++ b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx @@ -345,4 +345,7 @@ Skip already-visited directory {0}. + + Destination path cannot be a subdirectory of the source: {0}. + diff --git a/src/System.Management.Automation/resources/PSConfigurationStrings.resx b/src/System.Management.Automation/resources/PSConfigurationStrings.resx new file mode 100644 index 00000000000..a1671d7f9e8 --- /dev/null +++ b/src/System.Management.Automation/resources/PSConfigurationStrings.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + PowerShell has stopped working because of a security issue: Cannot read the configuration file: {0} + + diff --git a/src/System.Management.Automation/resources/PSStyleStrings.resx b/src/System.Management.Automation/resources/PSStyleStrings.resx new file mode 100644 index 00000000000..bc7acb1c200 --- /dev/null +++ b/src/System.Management.Automation/resources/PSStyleStrings.resx @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The specified string contains printable content when it should only contain ANSI escape sequences: {0} + + + The MaxWidth for the Progress rendering must be at least 18 to render correctly. + + + When adding or removing extensions, the extension must start with a period. + + diff --git a/src/System.Management.Automation/resources/ParserStrings.resx b/src/System.Management.Automation/resources/ParserStrings.resx index f38b78f074b..d21719157ac 100644 --- a/src/System.Management.Automation/resources/ParserStrings.resx +++ b/src/System.Management.Automation/resources/ParserStrings.resx @@ -1452,29 +1452,14 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent Conflict in using PsDscRunAsCredential for Resource {0} because it already specifies PsDscRunAsCredential value. We can only use one PsDscRunAsCredential for the composite resource. - - {0} - - - Command pipeline not supported for implicit remoting batching. - - - Command is not a simple pipeline and cannot be batched. - - - The pipeline command '{0}' is not an implicit remoting command or an approved batching command. + + Unable to find DSC schema store at "{0}". Please ensure PSDesiredStateConfiguration v3 module is installed. - - The pipeline command '{0}' is for a different remote session and cannot be batched. + + PS7DscSupport experimental feature is disabled; use Enable-ExperimentalFeature or update powershell.config.json to enable this feature. - - The implicit remoting PSSession for batching could not be retrieved. - - - Exception while checking the command for implicit remoting batching: {0} - - - Implicit remoting command pipeline has been batched for execution on remote target. + + {0} This script contains content that has been flagged as suspicious through a policy setting and has been blocked with error code {0}. Contact your administrator for more information. diff --git a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx index b4f9dc40a89..441228c9c44 100644 --- a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx +++ b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx @@ -1625,6 +1625,13 @@ All WinRM sessions connected to PowerShell session configurations, such as Micro The SSH client session has ended with error message: {0} + + SSH connection attempt failed after time out: {0} seconds. + + + +SSH client process terminated before connection could be established. + The provided SSHConnection hashtable is missing the required ComputerName or HostName parameter. diff --git a/src/System.Management.Automation/resources/RunspaceInit.resx b/src/System.Management.Automation/resources/RunspaceInit.resx index c4a485121c7..a2497961901 100644 --- a/src/System.Management.Automation/resources/RunspaceInit.resx +++ b/src/System.Management.Automation/resources/RunspaceInit.resx @@ -153,6 +153,9 @@ The text encoding used when piping text to a native executable file + + Configuration controlling how text is rendered. + Variable to contain the name of the email server. This can be used instead of the HostName parameter in the Send-MailMessage cmdlet. @@ -186,6 +189,9 @@ If true, WhatIf is considered to be enabled for all commands. + + Dictates how arguments are passed to native executables. + Dictates the limit of enumeration on formatting IEnumerable objects diff --git a/src/System.Management.Automation/resources/StringDecoratedStrings.resx b/src/System.Management.Automation/resources/StringDecoratedStrings.resx new file mode 100644 index 00000000000..e16aa999992 --- /dev/null +++ b/src/System.Management.Automation/resources/StringDecoratedStrings.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Only 'ANSI' or 'PlainText' is supported for this method. + + diff --git a/src/System.Management.Automation/security/Authenticode.cs b/src/System.Management.Automation/security/Authenticode.cs index 0abdafa956c..70b6778c37e 100644 --- a/src/System.Management.Automation/security/Authenticode.cs +++ b/src/System.Management.Automation/security/Authenticode.cs @@ -543,7 +543,6 @@ private static X509Certificate2 GetCertFromChain(IntPtr pSigner) if (pCert != IntPtr.Zero) { NativeMethods.CRYPT_PROVIDER_CERT provCert = - (NativeMethods.CRYPT_PROVIDER_CERT) Marshal.PtrToStructure(pCert); signerCert = new X509Certificate2(provCert.pCert); } @@ -618,7 +617,6 @@ private static bool TryGetProviderSigner(IntPtr wvtStateData, out IntPtr pProvSi if (pProvSigner != IntPtr.Zero) { NativeMethods.CRYPT_PROVIDER_SGNR provSigner = - (NativeMethods.CRYPT_PROVIDER_SGNR) Marshal.PtrToStructure(pProvSigner); if (provSigner.csCounterSigners == 1) { diff --git a/src/System.Management.Automation/security/CatalogHelper.cs b/src/System.Management.Automation/security/CatalogHelper.cs index 4b68cc86f6a..585ef801881 100644 --- a/src/System.Management.Automation/security/CatalogHelper.cs +++ b/src/System.Management.Automation/security/CatalogHelper.cs @@ -3,18 +3,12 @@ #if !UNIX -using Dbg = System.Management.Automation; -using System; -using System.Text; using System.Security.Cryptography; using System.Collections.Generic; -using System.Collections; using System.Collections.ObjectModel; -using System.ComponentModel; using System.IO; using System.Linq; using System.Management.Automation.Internal; -using System.Management.Automation.Provider; using System.Management.Automation.Security; using System.Runtime.InteropServices; using DWORD = System.UInt32; @@ -74,14 +68,14 @@ public class CatalogInformation internal static class CatalogHelper { // Catalog Version is (0X100 = 256) for Catalog Version 1 - private static int catalogVersion1 = 256; + private const int catalogVersion1 = 256; // Catalog Version is (0X200 = 512) for Catalog Version 2 - private static int catalogVersion2 = 512; + private const int catalogVersion2 = 512; // Hash Algorithms supported by Windows Catalog - private static string HashAlgorithmSHA1 = "SHA1"; - private static string HashAlgorithmSHA256 = "SHA256"; + private const string HashAlgorithmSHA1 = "SHA1"; + private const string HashAlgorithmSHA256 = "SHA256"; private static PSCmdlet _cmdlet = null; /// @@ -343,7 +337,7 @@ internal static FileInfo GenerateCatalog(PSCmdlet cmdlet, Collection Pat { // Generate Path for Catalog Definition File string cdfFilePath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); - cdfFilePath = cdfFilePath + ".cdf"; + cdfFilePath += ".cdf"; try { cdfFilePath = GenerateCDFFile(Path, catalogFilePath, cdfFilePath, catalogVersion, hashAlgorithm); @@ -415,8 +409,8 @@ internal static string CalculateFileHash(string filePath, string hashAlgorithm) _cmdlet.ThrowTerminatingError(errorRecord); } - DWORD GENERIC_READ = 0x80000000; - DWORD OPEN_EXISTING = 3; + const DWORD GENERIC_READ = 0x80000000; + const DWORD OPEN_EXISTING = 3; IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); // Open the file that is to be hashed for reading and get its handle diff --git a/src/System.Management.Automation/security/MshSignature.cs b/src/System.Management.Automation/security/MshSignature.cs index df20f7d0e63..96ff8a9638a 100644 --- a/src/System.Management.Automation/security/MshSignature.cs +++ b/src/System.Management.Automation/security/MshSignature.cs @@ -5,7 +5,6 @@ using System.Management.Automation.Internal; using System.Security.Cryptography.X509Certificates; -using Dbg = System.Management.Automation; using DWORD = System.UInt32; namespace System.Management.Automation @@ -72,7 +71,7 @@ public enum SignatureStatus /// with the current system. /// Incompatible - }; + } /// /// Defines the valid types of signatures. @@ -93,7 +92,7 @@ public enum SignatureType /// The signature is a catalog signature. /// Catalog = 2 - }; + } /// /// Represents a digital signature on a signed @@ -390,6 +389,5 @@ private static string GetSignatureStatusMessage(SignatureStatus status, return message; } - }; + } } - diff --git a/src/System.Management.Automation/security/SecureStringHelper.cs b/src/System.Management.Automation/security/SecureStringHelper.cs index e6180dc39b7..ddb94e52ee8 100644 --- a/src/System.Management.Automation/security/SecureStringHelper.cs +++ b/src/System.Management.Automation/security/SecureStringHelper.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Management.Automation; @@ -216,8 +217,6 @@ internal static SecureString Unprotect(string input) /// A string (see summary). internal static EncryptionResult Encrypt(SecureString input, SecureString key) { - EncryptionResult output = null; - // // get clear text key from the SecureString key // @@ -226,14 +225,14 @@ internal static EncryptionResult Encrypt(SecureString input, SecureString key) // // encrypt the data // - output = Encrypt(input, keyBlob); - - // - // clear the clear text key - // - Array.Clear(keyBlob, 0, keyBlob.Length); - - return output; + try + { + return Encrypt(input, keyBlob); + } + finally + { + Array.Clear(keyBlob); + } } /// @@ -253,48 +252,46 @@ internal static EncryptionResult Encrypt(SecureString input, byte[] key, byte[] Utils.CheckSecureStringArg(input, "input"); Utils.CheckKeyArg(key, "key"); - byte[] encryptedData = null; - MemoryStream ms = null; - ICryptoTransform encryptor = null; - CryptoStream cs = null; - // // prepare the crypto stuff. Initialization Vector is // randomized by default. // - Aes aes = Aes.Create(); - if (iv == null) - iv = aes.IV; - - encryptor = aes.CreateEncryptor(key, iv); - ms = new MemoryStream(); - - using (cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) + using (Aes aes = Aes.Create()) { + if (iv is null) + { + iv = aes.IV; + } + // // get clear text data from the input SecureString // byte[] data = GetData(input); + try + { + using (ICryptoTransform encryptor = aes.CreateEncryptor(key, iv)) + using (var sourceStream = new MemoryStream(data)) + using (var encryptedStream = new MemoryStream()) + { + // + // encrypt it + // + using (var cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write)) + { + sourceStream.CopyTo(cryptoStream); + } - // - // encrypt it - // - cs.Write(data, 0, data.Length); - cs.FlushFinalBlock(); - - // - // clear the clear text data array - // - Array.Clear(data, 0, data.Length); - - // - // convert the encrypted blob to a string - // - encryptedData = ms.ToArray(); - - EncryptionResult output = new EncryptionResult(ByteArrayToString(encryptedData), Convert.ToBase64String(iv)); - - return output; + // + // return encrypted data + // + byte[] encryptedData = encryptedStream.ToArray(); + return new EncryptionResult(ByteArrayToString(encryptedData), Convert.ToBase64String(iv)); + } + } + finally + { + Array.Clear(data, 0, data.Length); + } } } @@ -310,8 +307,6 @@ internal static EncryptionResult Encrypt(SecureString input, byte[] key, byte[] /// SecureString . internal static SecureString Decrypt(string input, SecureString key, byte[] IV) { - SecureString output = null; - // // get clear text key from the SecureString key // @@ -320,14 +315,14 @@ internal static SecureString Decrypt(string input, SecureString key, byte[] IV) // // decrypt the data // - output = Decrypt(input, keyBlob, IV); - - // - // clear the clear text key - // - Array.Clear(keyBlob, 0, keyBlob.Length); - - return output; + try + { + return Decrypt(input, keyBlob, IV); + } + finally + { + Array.Clear(keyBlob); + } } /// @@ -345,46 +340,55 @@ internal static SecureString Decrypt(string input, byte[] key, byte[] IV) Utils.CheckArgForNullOrEmpty(input, "input"); Utils.CheckKeyArg(key, "key"); - byte[] decryptedData = null; - byte[] encryptedData = null; - SecureString s = null; - // // prepare the crypto stuff // - Aes aes = Aes.Create(); - encryptedData = ByteArrayFromString(input); - - var decryptor = aes.CreateDecryptor(key, IV ?? aes.IV); - - MemoryStream ms = new MemoryStream(encryptedData); - - using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) + using (var aes = Aes.Create()) { - byte[] tempDecryptedData = new byte[encryptedData.Length]; - - int numBytesRead = 0; - - // - // decrypt the data - // - numBytesRead = cs.Read(tempDecryptedData, 0, - tempDecryptedData.Length); - - decryptedData = new byte[numBytesRead]; - - for (int i = 0; i < numBytesRead; i++) + using (ICryptoTransform decryptor = aes.CreateDecryptor(key, IV ?? aes.IV)) + using (var encryptedStream = new MemoryStream(ByteArrayFromString(input))) + using (var targetStream = new MemoryStream()) { - decryptedData[i] = tempDecryptedData[i]; + // + // decrypt the data and return as SecureString + // + using (var sourceStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read)) + { + sourceStream.CopyTo(targetStream); + } + + byte[] decryptedData = targetStream.ToArray(); + try + { + return New(decryptedData); + } + finally + { + Array.Clear(decryptedData); + } } + } + } - s = New(decryptedData); - Array.Clear(decryptedData, 0, decryptedData.Length); - Array.Clear(tempDecryptedData, 0, tempDecryptedData.Length); +#nullable enable + /// Creates a new from a . + /// Plain text string. Must not be null. + /// A new SecureString. + internal static unsafe SecureString FromPlainTextString(string plainTextString) + { + Debug.Assert(plainTextString is not null); - return s; + if (plainTextString.Length == 0) + { + return new SecureString(); + } + + fixed (char* charsPtr = plainTextString) + { + return new SecureString(charsPtr, plainTextString.Length); } } +#nullable restore } /// @@ -617,23 +621,23 @@ internal static bool ErrorMayBeCausedByUnloadedProfile(int errorCode) [DllImport("CRYPT32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptProtectData( - [In] IntPtr pDataIn, - [In] string szDataDescr, - [In] IntPtr pOptionalEntropy, - [In] IntPtr pvReserved, - [In] IntPtr pPromptStruct, - [In] uint dwFlags, + [In] IntPtr pDataIn, + [In] string szDataDescr, + [In] IntPtr pOptionalEntropy, + [In] IntPtr pvReserved, + [In] IntPtr pPromptStruct, + [In] uint dwFlags, [In, Out] IntPtr pDataBlob); [DllImport("CRYPT32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptUnprotectData( - [In] IntPtr pDataIn, - [In] IntPtr ppszDataDescr, - [In] IntPtr pOptionalEntropy, - [In] IntPtr pvReserved, - [In] IntPtr pPromptStruct, - [In] uint dwFlags, + [In] IntPtr pDataIn, + [In] IntPtr ppszDataDescr, + [In] IntPtr pOptionalEntropy, + [In] IntPtr pvReserved, + [In] IntPtr pPromptStruct, + [In] uint dwFlags, [In, Out] IntPtr pDataBlob); [DllImport("ntdll.dll", EntryPoint = "RtlZeroMemory", SetLastError = true)] @@ -647,4 +651,3 @@ internal static extern bool CryptUnprotectData( #endif } - diff --git a/src/System.Management.Automation/security/SecurityManager.cs b/src/System.Management.Automation/security/SecurityManager.cs index f6ae0fdf1f3..c82b03b99c7 100644 --- a/src/System.Management.Automation/security/SecurityManager.cs +++ b/src/System.Management.Automation/security/SecurityManager.cs @@ -11,6 +11,7 @@ using System.Management.Automation.Security; using System.Security; using System.Security.Cryptography.X509Certificates; +using System.Text; using Dbg = System.Management.Automation; @@ -68,7 +69,7 @@ internal enum RunPromptDecision private ExecutionPolicy _executionPolicy; // shellId supplied by runspace configuration - private string _shellId; + private readonly string _shellId; /// /// Initializes a new instance of the PSAuthorizationManager @@ -139,10 +140,6 @@ private bool CheckPolicy(ExternalScriptInfo script, PSHost host, out Exception r // Get the execution policy _executionPolicy = SecuritySupport.GetExecutionPolicy(_shellId); - // See if they want to bypass the authorization manager - if (_executionPolicy == ExecutionPolicy.Bypass) - return true; - // Always check the SAFER APIs if code integrity isn't being handled system-wide through // WLDP or AppLocker. In those cases, the scripts will be run in ConstrainedLanguage. // Otherwise, block. @@ -183,6 +180,13 @@ private bool CheckPolicy(ExternalScriptInfo script, PSHost host, out Exception r } } + // WLDP and Applocker takes priority over powershell exeuction policy. + // See if they want to bypass the authorization manager + if (_executionPolicy == ExecutionPolicy.Bypass) + { + return true; + } + if (_executionPolicy == ExecutionPolicy.Unrestricted) { // Product binaries are always trusted @@ -368,7 +372,7 @@ private bool CheckPolicy(ExternalScriptInfo script, PSHost host, out Exception r return policyCheckPassed; } - private bool SetPolicyFromAuthenticodePrompt(string path, PSHost host, ref Exception reason, Signature signature) + private static bool SetPolicyFromAuthenticodePrompt(string path, PSHost host, ref Exception reason, Signature signature) { bool policyCheckPassed = false; @@ -383,7 +387,9 @@ private bool SetPolicyFromAuthenticodePrompt(string path, PSHost host, ref Excep { TrustPublisher(signature); policyCheckPassed = true; - } break; + } + + break; case RunPromptDecision.DoNotRun: policyCheckPassed = false; reasonMessage = StringUtil.Format(Authenticode.Reason_DoNotRun, path); @@ -395,13 +401,15 @@ private bool SetPolicyFromAuthenticodePrompt(string path, PSHost host, ref Excep reasonMessage = StringUtil.Format(Authenticode.Reason_NeverRun, path); reason = new UnauthorizedAccessException(reasonMessage); policyCheckPassed = false; - } break; + } + + break; } return policyCheckPassed; } - private bool IsLocalFile(string filename) + private static bool IsLocalFile(string filename) { #if UNIX return true; @@ -421,7 +429,7 @@ private bool IsLocalFile(string filename) // Checks that a publisher is trusted by the system or is one of // the signed product binaries - private bool IsTrustedPublisher(Signature signature, string file) + private static bool IsTrustedPublisher(Signature signature, string file) { // Get the thumbprint of the current signature X509Certificate2 signerCertificate = signature.SignerCertificate; @@ -440,7 +448,7 @@ private bool IsTrustedPublisher(Signature signature, string file) return false; } - private bool IsUntrustedPublisher(Signature signature, string file) + private static bool IsUntrustedPublisher(Signature signature, string file) { // Get the thumbprint of the current signature X509Certificate2 signerCertificate = signature.SignerCertificate; @@ -463,7 +471,7 @@ private bool IsUntrustedPublisher(Signature signature, string file) /// Trust a publisher by adding it to the "Trusted Publishers" store. /// /// - private void TrustPublisher(Signature signature) + private static void TrustPublisher(Signature signature) { // Get the certificate of the signer X509Certificate2 signerCertificate = signature.SignerCertificate; @@ -481,7 +489,7 @@ private void TrustPublisher(Signature signature) } } - private void UntrustPublisher(Signature signature) + private static void UntrustPublisher(Signature signature) { // Get the certificate of the signer X509Certificate2 signerCertificate = signature.SignerCertificate; @@ -512,15 +520,28 @@ private void UntrustPublisher(Signature signature) } } - private Signature GetSignatureWithEncodingRetry(string path, ExternalScriptInfo script) + // Check the signature via the SIP which should never erroneously validate an invalid signature + // or altered script. + private static Signature GetSignatureWithEncodingRetry(string path, ExternalScriptInfo script) { - string verificationContents = System.Text.Encoding.Unicode.GetString(script.OriginalEncoding.GetPreamble()) + script.ScriptContents; - Signature signature = SignatureHelper.GetSignature(path, verificationContents); + // Invoke the SIP directly with the most simple method + Signature signature = SignatureHelper.GetSignature(path, fileContent: null); + if (signature.Status == SignatureStatus.Valid) + { + return signature; + } + // try harder to validate the signature by being explicit about encoding + // and providing the script contents + string verificationContents = Encoding.Unicode.GetString(script.OriginalEncoding.GetPreamble()) + script.ScriptContents; + signature = SignatureHelper.GetSignature(path, verificationContents); + + // A last ditch effort - // If the file was originally ASCII or UTF8, the SIP may have added the Unicode BOM - if ((signature.Status != SignatureStatus.Valid) && (script.OriginalEncoding != System.Text.Encoding.Unicode)) + if (signature.Status != SignatureStatus.Valid + && script.OriginalEncoding != Encoding.Unicode) { - verificationContents = System.Text.Encoding.Unicode.GetString(System.Text.Encoding.Unicode.GetPreamble()) + script.ScriptContents; + verificationContents = Encoding.Unicode.GetString(Encoding.Unicode.GetPreamble()) + script.ScriptContents; Signature fallbackSignature = SignatureHelper.GetSignature(path, verificationContents); if (fallbackSignature.Status == SignatureStatus.Valid) @@ -636,7 +657,7 @@ protected internal override bool ShouldRun(CommandInfo commandInfo, return allowRun; } - private RunPromptDecision AuthenticodePrompt(string path, + private static RunPromptDecision AuthenticodePrompt(string path, Signature signature, PSHost host) { @@ -709,7 +730,7 @@ private RunPromptDecision AuthenticodePrompt(string path, return decision; } - private RunPromptDecision RemoteFilePrompt(string path, PSHost host) + private static RunPromptDecision RemoteFilePrompt(string path, PSHost host) { if ((host == null) || (host.UI == null)) { @@ -739,7 +760,7 @@ private RunPromptDecision RemoteFilePrompt(string path, PSHost host) } } - private Collection GetAuthenticodePromptChoices() + private static Collection GetAuthenticodePromptChoices() { Collection choices = new Collection(); @@ -760,7 +781,7 @@ private Collection GetAuthenticodePromptChoices() return choices; } - private Collection GetRemoteFilePromptChoices() + private static Collection GetRemoteFilePromptChoices() { Collection choices = new Collection(); @@ -779,4 +800,3 @@ private Collection GetRemoteFilePromptChoices() } } } - diff --git a/src/System.Management.Automation/security/SecuritySupport.cs b/src/System.Management.Automation/security/SecuritySupport.cs index 90d4a71d73b..e41b64db625 100644 --- a/src/System.Management.Automation/security/SecuritySupport.cs +++ b/src/System.Management.Automation/security/SecuritySupport.cs @@ -63,7 +63,7 @@ public enum ExecutionPolicy /// Default - The most restrictive policy available. /// Default = Restricted - }; + } /// /// Defines the available configuration scopes for an execution @@ -248,7 +248,7 @@ private static bool IsCurrentProcessLaunchedByGpScript() while (currentProcess != null) { if (string.Equals(gpScriptPath, - PsUtils.GetMainModule(currentProcess).FileName, StringComparison.OrdinalIgnoreCase)) + currentProcess.MainModule.FileName, StringComparison.OrdinalIgnoreCase)) { foundGpScriptParent = true; break; @@ -704,7 +704,6 @@ internal static Collection GetCertEKU(X509Certificate2 cert) out structSize)) { Security.NativeMethods.CERT_ENHKEY_USAGE ekuStruct = - (Security.NativeMethods.CERT_ENHKEY_USAGE) Marshal.PtrToStructure(ekuBuffer); IntPtr ep = ekuStruct.rgpszUsageIdentifier; IntPtr ekuptr; @@ -996,7 +995,7 @@ public CmsMessageRecipient(string identifier) this.Certificates = new X509Certificate2Collection(); } - private string _identifier = null; + private readonly string _identifier; /// /// Creates an instance of the CmsMessageRecipient class. @@ -1008,7 +1007,7 @@ public CmsMessageRecipient(X509Certificate2 certificate) this.Certificates = new X509Certificate2Collection(); } - private X509Certificate2 _pendingCertificate = null; + private readonly X509Certificate2 _pendingCertificate; /// /// Gets the certificate associated with this recipient. @@ -1335,42 +1334,29 @@ public enum ResolutionPurpose Decryption } - internal class AmsiUtils + internal static class AmsiUtils { - private static string GetProcessHostName(string processName) - { - return string.Concat("PowerShell_", processName, ".exe_0.0.0.0"); - } - internal static int Init() { Diagnostics.Assert(s_amsiContext == IntPtr.Zero, "Init should be called just once"); lock (s_amsiLockObject) { - Process currentProcess = Process.GetCurrentProcess(); - string hostname; + string appName; try { - var processModule = PsUtils.GetMainModule(currentProcess); - hostname = string.Concat("PowerShell_", processModule.FileName, "_", - processModule.FileVersionInfo.ProductVersion); - } - catch (ComponentModel.Win32Exception) - { - // This exception can be thrown during thread impersonation (Access Denied for process module access). - hostname = GetProcessHostName(currentProcess.ProcessName); + appName = string.Concat("PowerShell_", Environment.ProcessPath, "_", PSVersionInfo.ProductVersion); } - catch (FileNotFoundException) + catch (Exception) { - // This exception can occur if the file is renamed or moved to some other folder - // (This has occurred during Exchange set up). - hostname = GetProcessHostName(currentProcess.ProcessName); + // Fall back to 'Process.ProcessName' in case 'Environment.ProcessPath' throws exception. + Process currentProcess = Process.GetCurrentProcess(); + appName = string.Concat("PowerShell_", currentProcess.ProcessName, ".exe_", PSVersionInfo.ProductVersion); } AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; - var hr = AmsiNativeMethods.AmsiInitialize(hostname, ref s_amsiContext); + var hr = AmsiNativeMethods.AmsiInitialize(appName, ref s_amsiContext); if (!Utils.Succeeded(hr)) { s_amsiInitFailed = true; @@ -1407,7 +1393,7 @@ internal static AmsiNativeMethods.AMSI_RESULT WinScanContent(string content, str const string EICAR_STRING = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"; if (InternalTestHooks.UseDebugAmsiImplementation) { - if (content.IndexOf(EICAR_STRING, StringComparison.Ordinal) >= 0) + if (content.Contains(EICAR_STRING, StringComparison.Ordinal)) { return AmsiNativeMethods.AMSI_RESULT.AMSI_RESULT_DETECTED; } @@ -1513,7 +1499,7 @@ internal static void CurrentDomain_ProcessExit(object sender, EventArgs e) private static IntPtr s_amsiSession = IntPtr.Zero; private static bool s_amsiInitFailed = false; - private static object s_amsiLockObject = new object(); + private static readonly object s_amsiLockObject = new object(); /// /// Reset the AMSI session (used to track related script invocations) @@ -1581,7 +1567,7 @@ internal static void WinUninitialize() public static bool AmsiInitialized = false; public static bool AmsiCleanedUp = false; - internal class AmsiNativeMethods + internal static class AmsiNativeMethods { internal enum AMSI_RESULT { @@ -1605,7 +1591,7 @@ internal enum AMSI_RESULT [DefaultDllImportSearchPathsAttribute(DllImportSearchPath.System32)] [DllImportAttribute("amsi.dll", EntryPoint = "AmsiInitialize", CallingConvention = CallingConvention.StdCall)] internal static extern int AmsiInitialize( - [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string appName, ref System.IntPtr amsiContext); + [InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string appName, ref System.IntPtr amsiContext); /// Return Type: void ///amsiContext: HAMSICONTEXT->HAMSICONTEXT__* @@ -1638,7 +1624,7 @@ internal static extern int AmsiInitialize( [DllImportAttribute("amsi.dll", EntryPoint = "AmsiScanBuffer", CallingConvention = CallingConvention.StdCall)] internal static extern int AmsiScanBuffer( System.IntPtr amsiContext, System.IntPtr buffer, uint length, - [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string contentName, System.IntPtr amsiSession, ref AMSI_RESULT result); + [InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string contentName, System.IntPtr amsiSession, ref AMSI_RESULT result); /// Return Type: HRESULT->LONG->int ///amsiContext: HAMSICONTEXT->HAMSICONTEXT__* @@ -1649,8 +1635,8 @@ internal static extern int AmsiScanBuffer( [DefaultDllImportSearchPathsAttribute(DllImportSearchPath.System32)] [DllImportAttribute("amsi.dll", EntryPoint = "AmsiScanString", CallingConvention = CallingConvention.StdCall)] internal static extern int AmsiScanString( - System.IntPtr amsiContext, [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string @string, - [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string contentName, System.IntPtr amsiSession, ref AMSI_RESULT result); + System.IntPtr amsiContext, [InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string @string, + [InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string contentName, System.IntPtr amsiSession, ref AMSI_RESULT result); } } } diff --git a/src/System.Management.Automation/security/nativeMethods.cs b/src/System.Management.Automation/security/nativeMethods.cs index 2131fee6989..165c4063003 100644 --- a/src/System.Management.Automation/security/nativeMethods.cs +++ b/src/System.Management.Automation/security/nativeMethods.cs @@ -7,14 +7,13 @@ using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Management.Automation.Internal; -using System.Runtime.ConstrainedExecution; using DWORD = System.UInt32; using BOOL = System.UInt32; namespace System.Management.Automation.Security { // Crypto API native constants - internal partial class NativeConstants + internal static partial class NativeConstants { internal const int CRYPT_OID_INFO_OID_KEY = 1; internal const int CRYPT_OID_INFO_NAME_KEY = 2; @@ -557,7 +556,7 @@ internal enum CryptUIFlags { CRYPTUI_WIZ_NO_UI = 0x0001 // other flags not used - }; + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO @@ -576,14 +575,14 @@ internal struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO internal DWORD dwAdditionalCertChoice; internal IntPtr pSignExtInfo; // PCCRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO - }; + } [Flags] internal enum SignInfoSubjectChoice { CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE = 0x01 // CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB = 0x02 NotUsed - }; + } [Flags] internal enum SignInfoCertChoice @@ -591,14 +590,14 @@ internal enum SignInfoCertChoice CRYPTUI_WIZ_DIGITAL_SIGN_CERT = 0x01 // CRYPTUI_WIZ_DIGITAL_SIGN_STORE = 0x02, NotUsed // CRYPTUI_WIZ_DIGITAL_SIGN_PVK = 0x03, NotUsed - }; + } [Flags] internal enum SignInfoAdditionalCertChoice { CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN = 1, CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN_NO_ROOT = 2 - }; + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO @@ -619,7 +618,7 @@ internal struct CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO internal IntPtr hAdditionalCertStoreNotUsed; // HCERTSTORE internal IntPtr psAuthenticatedNotUsed; // PCRYPT_ATTRIBUTES internal IntPtr psUnauthenticatedNotUsed; // PCRYPT_ATTRIBUTES - }; + } [ArchitectureSensitive] internal static CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO @@ -807,7 +806,7 @@ internal struct WINTRUST_FILE_INFO internal IntPtr hFileNotUsed; // optional, HANDLE to pcwszFilePath internal IntPtr pgKnownSubjectNotUsed; // optional: GUID* : fill if the // subject type is known - }; + } [StructLayoutAttribute(LayoutKind.Sequential)] internal struct WINTRUST_BLOB_INFO @@ -872,7 +871,7 @@ internal enum WintrustUIChoice WTD_UI_NONE = 2, WTD_UI_NOBAD = 3, WTD_UI_NOGOOD = 4 - }; + } [Flags] internal enum WintrustUnionChoice @@ -882,7 +881,7 @@ internal enum WintrustUnionChoice WTD_CHOICE_BLOB = 3, // WTD_CHOICE_SIGNER = 4, // WTD_CHOICE_CERT = 5, - }; + } [Flags] internal enum WintrustProviderFlags @@ -900,7 +899,7 @@ internal enum WintrustProviderFlags WTD_USE_DEFAULT_OSVER_CHECK = 0x00000400, WTD_LIFETIME_SIGNING_FLAG = 0x00000800, WTD_CACHE_ONLY_URL_RETRIEVAL = 0x00001000 - }; + } [Flags] internal enum WintrustAction @@ -910,7 +909,7 @@ internal enum WintrustAction WTD_STATEACTION_CLOSE = 0x00000002, WTD_STATEACTION_AUTO_CACHE = 0x00000003, WTD_STATEACTION_AUTO_CACHE_FLUSH = 0x00000004 - }; + } [StructLayoutAttribute(LayoutKind.Explicit)] internal struct WinTrust_Choice @@ -1089,37 +1088,39 @@ internal static DWORD DestroyWintrustDataStruct(WINTRUST_DATA wtd) [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_PROVIDER_CERT { +#pragma warning disable IDE0044 private DWORD _cbStruct; +#pragma warning restore IDE0044 internal IntPtr pCert; // PCCERT_CONTEXT - private BOOL _fCommercial; - private BOOL _fTrustedRoot; - private BOOL _fSelfSigned; - private BOOL _fTestCert; - private DWORD _dwRevokedReason; - private DWORD _dwConfidence; - private DWORD _dwError; - private IntPtr _pTrustListContext; // CTL_CONTEXT* - private BOOL _fTrustListSignerCert; - private IntPtr _pCtlContext; // PCCTL_CONTEXT - private DWORD _dwCtlError; - private BOOL _fIsCyclic; - private IntPtr _pChainElement; // PCERT_CHAIN_ELEMENT - }; + private readonly BOOL _fCommercial; + private readonly BOOL _fTrustedRoot; + private readonly BOOL _fSelfSigned; + private readonly BOOL _fTestCert; + private readonly DWORD _dwRevokedReason; + private readonly DWORD _dwConfidence; + private readonly DWORD _dwError; + private readonly IntPtr _pTrustListContext; // CTL_CONTEXT* + private readonly BOOL _fTrustListSignerCert; + private readonly IntPtr _pCtlContext; // PCCTL_CONTEXT + private readonly DWORD _dwCtlError; + private readonly BOOL _fIsCyclic; + private readonly IntPtr _pChainElement; // PCERT_CHAIN_ELEMENT + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_PROVIDER_SGNR { - private DWORD _cbStruct; + private readonly DWORD _cbStruct; private FILETIME _sftVerifyAsOf; - private DWORD _csCertChain; - private IntPtr _pasCertChain; // CRYPT_PROVIDER_CERT* - private DWORD _dwSignerType; - private IntPtr _psSigner; // CMSG_SIGNER_INFO* - private DWORD _dwError; + private readonly DWORD _csCertChain; + private readonly IntPtr _pasCertChain; // CRYPT_PROVIDER_CERT* + private readonly DWORD _dwSignerType; + private readonly IntPtr _psSigner; // CMSG_SIGNER_INFO* + private readonly DWORD _dwError; internal DWORD csCounterSigners; internal IntPtr pasCounterSigners; // CRYPT_PROVIDER_SGNR* - private IntPtr _pChainContext; // PCCERT_CHAIN_CONTEXT - }; + private readonly IntPtr _pChainContext; // PCCERT_CHAIN_CONTEXT + } [DllImport("wintrust.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern @@ -1152,7 +1153,7 @@ DWORD idxCert ///ppCertContext: void** ///phWVTStateData: HANDLE* [DllImportAttribute("wintrust.dll", EntryPoint = "WTGetSignatureInfo", CallingConvention = CallingConvention.StdCall)] - internal static extern int WTGetSignatureInfo([InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string pszFile, [InAttribute()] System.IntPtr hFile, SIGNATURE_INFO_FLAGS sigInfoFlags, ref SIGNATURE_INFO psiginfo, ref System.IntPtr ppCertContext, ref System.IntPtr phWVTStateData); + internal static extern int WTGetSignatureInfo([InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string pszFile, [InAttribute()] System.IntPtr hFile, SIGNATURE_INFO_FLAGS sigInfoFlags, ref SIGNATURE_INFO psiginfo, ref System.IntPtr ppCertContext, ref System.IntPtr phWVTStateData); internal static void FreeWVTStateData(System.IntPtr phWVTStateData) { @@ -1211,7 +1212,7 @@ internal struct CERT_ENHKEY_USAGE // [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] // internal string[] rgpszUsageIdentifier; // LPSTR* internal IntPtr rgpszUsageIdentifier; - }; + } internal enum SIGNATURE_STATE { @@ -1878,7 +1879,7 @@ internal static bool IsSystem32DllPresent(string DllName) NativeMethods.LOAD_LIBRARY_AS_DATAFILE | NativeMethods.LOAD_LIBRARY_AS_IMAGE_RESOURCE | NativeMethods.LOAD_LIBRARY_SEARCH_SYSTEM32); - if (IntPtr.Zero != module) + if (module != IntPtr.Zero) { FreeLibrary(module); DllExists = true; @@ -1956,19 +1957,19 @@ internal struct SIP_INDIRECT_DATA } [StructLayout(LayoutKind.Sequential)] - internal struct CRYPTCATCDF + internal readonly struct CRYPTCATCDF { - private DWORD _cbStruct; - private IntPtr _hFile; - private DWORD _dwCurFilePos; - private DWORD _dwLastMemberOffset; - private BOOL _fEOF; + private readonly DWORD _cbStruct; + private readonly IntPtr _hFile; + private readonly DWORD _dwCurFilePos; + private readonly DWORD _dwLastMemberOffset; + private readonly BOOL _fEOF; [MarshalAs(UnmanagedType.LPWStr)] - private string _pwszResultDir; + private readonly string _pwszResultDir; - private IntPtr _hCATStore; - }; + private readonly IntPtr _hCATStore; + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPTCATMEMBER @@ -1989,39 +1990,39 @@ internal struct CRYPTCATMEMBER internal IntPtr hReserved; internal CRYPT_ATTR_BLOB sEncodedIndirectData; internal CRYPT_ATTR_BLOB sEncodedMemberInfo; - }; + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPTCATATTRIBUTE { - private DWORD _cbStruct; + private readonly DWORD _cbStruct; [MarshalAs(UnmanagedType.LPWStr)] internal string pwszReferenceTag; - private DWORD _dwAttrTypeAndAction; + private readonly DWORD _dwAttrTypeAndAction; internal DWORD cbValue; internal System.IntPtr pbValue; - private DWORD _dwReserved; - }; + private readonly DWORD _dwReserved; + } [StructLayout(LayoutKind.Sequential)] internal struct CRYPTCATSTORE { - private DWORD _cbStruct; + private readonly DWORD _cbStruct; internal DWORD dwPublicVersion; [MarshalAs(UnmanagedType.LPWStr)] internal string pwszP7File; - private IntPtr _hProv; - private DWORD _dwEncodingType; - private DWORD _fdwStoreFlags; - private IntPtr _hReserved; - private IntPtr _hAttrs; - private IntPtr _hCryptMsg; - private IntPtr _hSorted; - }; + private readonly IntPtr _hProv; + private readonly DWORD _dwEncodingType; + private readonly DWORD _fdwStoreFlags; + private readonly IntPtr _hReserved; + private readonly IntPtr _hAttrs; + private readonly IntPtr _hCryptMsg; + private readonly IntPtr _hSorted; + } [DllImport("wintrust.dll", CharSet = CharSet.Unicode)] internal static extern IntPtr CryptCATCDFOpen( diff --git a/src/System.Management.Automation/security/wldpNativeMethods.cs b/src/System.Management.Automation/security/wldpNativeMethods.cs index e9665f4dfa8..02cbf8f1815 100644 --- a/src/System.Management.Automation/security/wldpNativeMethods.cs +++ b/src/System.Management.Automation/security/wldpNativeMethods.cs @@ -7,7 +7,6 @@ #if !UNIX using System.Management.Automation.Internal; -using Microsoft.Win32; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; @@ -69,7 +68,7 @@ public static SystemEnforcementMode GetSystemLockdownPolicy() return s_systemLockdownPolicy.Value; } - private static object s_systemLockdownPolicyLock = new object(); + private static readonly object s_systemLockdownPolicyLock = new object(); private static SystemEnforcementMode? s_systemLockdownPolicy = null; private static bool s_allowDebugOverridePolicy = false; @@ -79,28 +78,31 @@ public static SystemEnforcementMode GetSystemLockdownPolicy() /// An EnforcementMode that describes policy. public static SystemEnforcementMode GetLockdownPolicy(string path, SafeHandle handle) { - // Check the WLDP API - SystemEnforcementMode lockdownPolicy = GetWldpPolicy(path, handle); - if (lockdownPolicy == SystemEnforcementMode.Enforce) + // Check the WLDP File policy via API + var wldpFilePolicy = GetWldpPolicy(path, handle); + if (wldpFilePolicy == SystemEnforcementMode.Enforce) { - return lockdownPolicy; + return wldpFilePolicy; + } + + // Check the AppLocker File policy via API + // This needs to be checked before WLDP audit policy + // So, that we don't end up in Audit mode, + // when we should be enforce mode. + var appLockerFilePolicy = GetAppLockerPolicy(path, handle); + if (appLockerFilePolicy == SystemEnforcementMode.Enforce) + { + return appLockerFilePolicy; } // At this point, LockdownPolicy = Audit or Allowed. // If there was a WLDP policy, but WLDP didn't block it, // then it was explicitly allowed. Therefore, return the result for the file. SystemEnforcementMode systemWldpPolicy = s_cachedWldpSystemPolicy.GetValueOrDefault(SystemEnforcementMode.None); - if ((systemWldpPolicy == SystemEnforcementMode.Enforce) || - (systemWldpPolicy == SystemEnforcementMode.Audit)) - { - return lockdownPolicy; - } - - // Check the AppLocker API - lockdownPolicy = GetAppLockerPolicy(path, handle); - if (lockdownPolicy == SystemEnforcementMode.Enforce) + if ((systemWldpPolicy == SystemEnforcementMode.Audit) || + (systemWldpPolicy == SystemEnforcementMode.Enforce)) { - return lockdownPolicy; + return wldpFilePolicy; } // If there was a system-wide AppLocker policy, but AppLocker didn't block it, @@ -108,7 +110,7 @@ public static SystemEnforcementMode GetLockdownPolicy(string path, SafeHandle ha if (s_cachedSaferSystemPolicy.GetValueOrDefault(SaferPolicy.Allowed) == SaferPolicy.Disallowed) { - return lockdownPolicy; + return appLockerFilePolicy; } // If it's not set to 'Enforce' by the platform, allow debug overrides @@ -231,7 +233,7 @@ private static SystemEnforcementMode GetAppLockerPolicy(string path, SafeHandle // AppLocker fails when you try to check a policy on a file // with no content. So create a scratch file and test on that. - string dtAppLockerTestFileContents = AppLockerTestFileContents + DateTime.Now; + string dtAppLockerTestFileContents = AppLockerTestFileContents + Environment.TickCount64; IO.File.WriteAllText(testPathScript, dtAppLockerTestFileContents); IO.File.WriteAllText(testPathModule, dtAppLockerTestFileContents); } @@ -359,7 +361,7 @@ private static SystemEnforcementMode GetDebugLockdownPolicy(string path) { // Assume everything under SYSTEM32 is trusted, with a purposefully sloppy // check so that we can actually put it in the filename during testing. - if (path.IndexOf("System32", StringComparison.OrdinalIgnoreCase) >= 0) + if (path.Contains("System32", StringComparison.OrdinalIgnoreCase)) { return SystemEnforcementMode.None; } @@ -389,6 +391,14 @@ private static SystemEnforcementMode GetDebugLockdownPolicy(string path) /// True if the COM object is allowed, False otherwise. internal static bool IsClassInApprovedList(Guid clsid) { + // This method is called only if there is an AppLocker and/or WLDP system wide lock down enforcement policy. + if (s_cachedWldpSystemPolicy.GetValueOrDefault(SystemEnforcementMode.None) != SystemEnforcementMode.Enforce) + { + // No WLDP policy implies only AppLocker policy enforcement. Disallow all COM object instantiation. + return false; + } + + // WLDP policy must be in system wide enforcement, look up COM Id in WLDP approval list. try { WLDP_HOST_INFORMATION hostInformation = new WLDP_HOST_INFORMATION(); @@ -489,7 +499,7 @@ internal static string DumpLockdownState(uint pdwLockdownState) /// /// Native constants for dealing with the lockdown policy. /// - internal class WldpNativeConstants + internal static class WldpNativeConstants { internal const uint WLDP_HOST_INFORMATION_REVISION = 0x00000001; @@ -539,7 +549,7 @@ internal struct WLDP_HOST_INFORMATION /// /// Native methods for dealing with the lockdown policy. /// - internal class WldpNativeMethods + internal static class WldpNativeMethods { /// Return Type: HRESULT->LONG->int /// pHostInformation: PWLDP_HOST_INFORMATION->_WLDP_HOST_INFORMATION* diff --git a/src/System.Management.Automation/singleshell/config/MshConsoleLoadException.cs b/src/System.Management.Automation/singleshell/config/MshConsoleLoadException.cs index 9e8c2585215..291914614f5 100644 --- a/src/System.Management.Automation/singleshell/config/MshConsoleLoadException.cs +++ b/src/System.Management.Automation/singleshell/config/MshConsoleLoadException.cs @@ -78,7 +78,7 @@ private void CreateErrorRecord() { foreach (PSSnapInException e in PSSnapInExceptions) { - sb.Append("\n"); + sb.Append('\n'); sb.Append(e.Message); } } @@ -86,7 +86,7 @@ private void CreateErrorRecord() _errorRecord = new ErrorRecord(new ParentContainsErrorRecordException(this), "ConsoleLoadFailure", ErrorCategory.ResourceUnavailable, null); } - private Collection _PSSnapInExceptions = new Collection(); + private readonly Collection _PSSnapInExceptions = new Collection(); internal Collection PSSnapInExceptions { @@ -115,4 +115,3 @@ public override string Message } } } - diff --git a/src/System.Management.Automation/singleshell/config/MshSnapinInfo.cs b/src/System.Management.Automation/singleshell/config/MshSnapinInfo.cs index 33ef4a0cb9d..b7e5d60f001 100644 --- a/src/System.Management.Automation/singleshell/config/MshSnapinInfo.cs +++ b/src/System.Management.Automation/singleshell/config/MshSnapinInfo.cs @@ -262,8 +262,8 @@ internal string AbsoluteModulePath /// public Collection Formats { get; } - private string _descriptionIndirect; - private string _descriptionFallback = string.Empty; + private readonly string _descriptionIndirect; + private readonly string _descriptionFallback = string.Empty; private string _description; /// /// Description of mshsnapin. @@ -281,8 +281,8 @@ public string Description } } - private string _vendorIndirect; - private string _vendorFallback = string.Empty; + private readonly string _vendorIndirect; + private readonly string _vendorFallback = string.Empty; private string _vendor; /// /// Vendor of mshsnapin. @@ -954,8 +954,8 @@ internal static PSSnapInInfo ReadCoreEngineSnapIn() // System.Management.Automation formats & types files Collection types = new Collection(new string[] { "types.ps1xml", "typesv3.ps1xml" }); Collection formats = new Collection(new string[] - {"Certificate.format.ps1xml","DotNetTypes.format.ps1xml","FileSystem.format.ps1xml", - "Help.format.ps1xml","HelpV3.format.ps1xml","PowerShellCore.format.ps1xml","PowerShellTrace.format.ps1xml", + {"Certificate.format.ps1xml", "DotNetTypes.format.ps1xml", "FileSystem.format.ps1xml", + "Help.format.ps1xml", "HelpV3.format.ps1xml", "PowerShellCore.format.ps1xml", "PowerShellTrace.format.ps1xml", "Registry.format.ps1xml"}); string strongName = string.Format(CultureInfo.InvariantCulture, "{0}, Version={1}, Culture={2}, PublicKeyToken={3}, ProcessorArchitecture={4}", @@ -1007,8 +1007,8 @@ internal static Collection ReadEnginePSSnapIns() // System.Management.Automation formats & types files Collection smaFormats = new Collection(new string[] - {"Certificate.format.ps1xml","DotNetTypes.format.ps1xml","FileSystem.format.ps1xml", - "Help.format.ps1xml","HelpV3.format.ps1xml","PowerShellCore.format.ps1xml","PowerShellTrace.format.ps1xml", + {"Certificate.format.ps1xml", "DotNetTypes.format.ps1xml", "FileSystem.format.ps1xml", + "Help.format.ps1xml", "HelpV3.format.ps1xml", "PowerShellCore.format.ps1xml", "PowerShellTrace.format.ps1xml", "Registry.format.ps1xml"}); Collection smaTypes = new Collection(new string[] { "types.ps1xml", "typesv3.ps1xml" }); @@ -1305,18 +1305,18 @@ private static IList DefaultMshSnapins "GetEventResources,Description", "GetEventResources,Vendor"), #endif new DefaultPSSnapInInformation("Microsoft.PowerShell.Host", "Microsoft.PowerShell.ConsoleHost", null, - "HostMshSnapInResources,Description","HostMshSnapInResources,Vendor"), + "HostMshSnapInResources,Description", "HostMshSnapInResources,Vendor"), s_coreSnapin, new DefaultPSSnapInInformation("Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Commands.Utility", null, - "UtilityMshSnapInResources,Description","UtilityMshSnapInResources,Vendor"), + "UtilityMshSnapInResources,Description", "UtilityMshSnapInResources,Vendor"), new DefaultPSSnapInInformation("Microsoft.PowerShell.Management", "Microsoft.PowerShell.Commands.Management", null, - "ManagementMshSnapInResources,Description","ManagementMshSnapInResources,Vendor"), + "ManagementMshSnapInResources,Description", "ManagementMshSnapInResources,Vendor"), new DefaultPSSnapInInformation("Microsoft.PowerShell.Security", "Microsoft.PowerShell.Security", null, - "SecurityMshSnapInResources,Description","SecurityMshSnapInResources,Vendor") + "SecurityMshSnapInResources,Description", "SecurityMshSnapInResources,Vendor") }; #if !UNIX @@ -1335,11 +1335,10 @@ private static IList DefaultMshSnapins } private static IList s_defaultMshSnapins = null; - private static object s_syncObject = new object(); + private static readonly object s_syncObject = new object(); #endregion - private static PSTraceSource s_mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false); + private static readonly PSTraceSource s_mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false); } } - diff --git a/src/System.Management.Automation/singleshell/config/MshSnapinLoadException.cs b/src/System.Management.Automation/singleshell/config/MshSnapinLoadException.cs index 6ed8a54f8d2..05c30ea82c2 100644 --- a/src/System.Management.Automation/singleshell/config/MshSnapinLoadException.cs +++ b/src/System.Management.Automation/singleshell/config/MshSnapinLoadException.cs @@ -116,7 +116,7 @@ private void CreateErrorRecord() } } - private bool _warning = false; + private readonly bool _warning = false; private ErrorRecord _errorRecord; private bool _isErrorRecordOriginallyNull; @@ -146,8 +146,8 @@ public override ErrorRecord ErrorRecord } } - private string _PSSnapin = string.Empty; - private string _reason = string.Empty; + private readonly string _PSSnapin = string.Empty; + private readonly string _reason = string.Empty; /// /// Gets message for this exception. @@ -203,4 +203,3 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont #endregion Serialization } } - diff --git a/src/System.Management.Automation/utils/BackgroundDispatcher.cs b/src/System.Management.Automation/utils/BackgroundDispatcher.cs index 583eecfa836..8ef105ce0ea 100644 --- a/src/System.Management.Automation/utils/BackgroundDispatcher.cs +++ b/src/System.Management.Automation/utils/BackgroundDispatcher.cs @@ -70,12 +70,7 @@ public BackgroundDispatcher(EventProvider transferProvider, EventDescriptor tran // internal for unit testing only. Otherwise, would be private. internal BackgroundDispatcher(IMethodInvoker etwActivityMethodInvoker) { - if (etwActivityMethodInvoker == null) - { - throw new ArgumentNullException("etwActivityMethodInvoker"); - } - - _etwActivityMethodInvoker = etwActivityMethodInvoker; + _etwActivityMethodInvoker = etwActivityMethodInvoker ?? throw new ArgumentNullException(nameof(etwActivityMethodInvoker)); _invokerWaitCallback = DoInvoker; } diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index 0638891eaa2..0372b249ca1 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -2,24 +2,16 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; -using System.Linq; using System.Management.Automation.Internal; using System.Management.Automation.Language; using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; using System.Runtime.Loader; using System.Security; using System.Text; using System.Text.RegularExpressions; -using System.Threading; - -using Microsoft.Win32.SafeHandles; namespace System.Management.Automation { @@ -242,7 +234,7 @@ private static SecurityZone MapSecurityZone(string filePath) // has 'dot' in it, the file will be treated as in Internet security zone. Otherwise, it's // in Intranet security zone. string hostName = uri.Host; - return hostName.Contains('.') ? SecurityZone.Intranet : SecurityZone.Internet; + return hostName.Contains('.') ? SecurityZone.Internet : SecurityZone.Intranet; } string root = Path.GetPathRoot(filePath); @@ -357,12 +349,12 @@ internal static string ToDmtfDateTime(DateTime date) string dmtfDateTime = date.Year.ToString(frmInt32).PadLeft(4, '0'); - dmtfDateTime = (dmtfDateTime + date.Month.ToString(frmInt32).PadLeft(2, '0')); - dmtfDateTime = (dmtfDateTime + date.Day.ToString(frmInt32).PadLeft(2, '0')); - dmtfDateTime = (dmtfDateTime + date.Hour.ToString(frmInt32).PadLeft(2, '0')); - dmtfDateTime = (dmtfDateTime + date.Minute.ToString(frmInt32).PadLeft(2, '0')); - dmtfDateTime = (dmtfDateTime + date.Second.ToString(frmInt32).PadLeft(2, '0')); - dmtfDateTime = (dmtfDateTime + "."); + dmtfDateTime += date.Month.ToString(frmInt32).PadLeft(2, '0'); + dmtfDateTime += date.Day.ToString(frmInt32).PadLeft(2, '0'); + dmtfDateTime += date.Hour.ToString(frmInt32).PadLeft(2, '0'); + dmtfDateTime += date.Minute.ToString(frmInt32).PadLeft(2, '0'); + dmtfDateTime += date.Second.ToString(frmInt32).PadLeft(2, '0'); + dmtfDateTime += "."; // Construct a DateTime with with the precision to Second as same as the passed DateTime and so get // the ticks difference so that the microseconds can be calculated @@ -376,9 +368,9 @@ internal static string ToDmtfDateTime(DateTime date) strMicrosec = strMicrosec.Substring(0, 6); } - dmtfDateTime = dmtfDateTime + strMicrosec.PadLeft(6, '0'); + dmtfDateTime += strMicrosec.PadLeft(6, '0'); // adding the UTC offset - dmtfDateTime = dmtfDateTime + UtcString; + dmtfDateTime += UtcString; return dmtfDateTime; #else diff --git a/src/System.Management.Automation/utils/CommandDiscoveryExceptions.cs b/src/System.Management.Automation/utils/CommandDiscoveryExceptions.cs index 0e855a8914b..e08d8e1a65c 100644 --- a/src/System.Management.Automation/utils/CommandDiscoveryExceptions.cs +++ b/src/System.Management.Automation/utils/CommandDiscoveryExceptions.cs @@ -4,7 +4,6 @@ using System.Collections.ObjectModel; using System.Management.Automation.Internal; using System.Runtime.Serialization; -using System.Security.Permissions; using System.Text; namespace System.Management.Automation @@ -152,8 +151,8 @@ public string CommandName #endregion Properties #region Private - private string _errorId = "CommandNotFoundException"; - private ErrorCategory _errorCategory = ErrorCategory.ObjectNotFound; + private readonly string _errorId = "CommandNotFoundException"; + private readonly ErrorCategory _errorCategory = ErrorCategory.ObjectNotFound; private static string BuildMessage( string commandName, @@ -162,7 +161,7 @@ params object[] messageArgs ) { object[] a; - if (messageArgs != null && 0 < messageArgs.Length) + if (messageArgs != null && messageArgs.Length > 0) { a = new object[messageArgs.Length + 1]; a[0] = commandName; @@ -414,7 +413,7 @@ public string CommandName get { return _commandName; } } - private string _commandName = string.Empty; + private readonly string _commandName = string.Empty; /// /// Gets the PSVersion that the script requires. @@ -424,7 +423,7 @@ public Version RequiresPSVersion get { return _requiresPSVersion; } } - private Version _requiresPSVersion; + private readonly Version _requiresPSVersion; /// /// Gets the missing snap-ins that the script requires. @@ -434,7 +433,7 @@ public ReadOnlyCollection MissingPSSnapIns get { return _missingPSSnapIns; } } - private ReadOnlyCollection _missingPSSnapIns = new ReadOnlyCollection(Array.Empty()); + private readonly ReadOnlyCollection _missingPSSnapIns = new ReadOnlyCollection(Array.Empty()); /// /// Gets or sets the ID of the shell. @@ -444,7 +443,7 @@ public string RequiresShellId get { return _requiresShellId; } } - private string _requiresShellId; + private readonly string _requiresShellId; /// /// Gets or sets the path to the incompatible shell. @@ -454,7 +453,7 @@ public string RequiresShellPath get { return _requiresShellPath; } } - private string _requiresShellPath; + private readonly string _requiresShellPath; #endregion Properties @@ -534,4 +533,3 @@ private static string BuildMessage(string commandName) #endregion Private } } - diff --git a/src/System.Management.Automation/utils/CryptoUtils.cs b/src/System.Management.Automation/utils/CryptoUtils.cs index 43e04754fce..a8f27732a7b 100644 --- a/src/System.Management.Automation/utils/CryptoUtils.cs +++ b/src/System.Management.Automation/utils/CryptoUtils.cs @@ -64,7 +64,7 @@ internal static class PSCryptoNativeConverter private static int ToInt32LE(byte[] bytes, int offset) { - return (bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1 ] << 8) | bytes[offset]; + return (bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1] << 8) | bytes[offset]; } private static uint ToUInt32LE(byte[] bytes, int offset) @@ -140,7 +140,7 @@ private static RSAParameters GetParametersFromCapiPublicKeyBlob(byte[] blob, int try { - if ((blob[offset] != PUBLICKEYBLOB) || // PUBLICKEYBLOB (0x06) + if ((blob[offset] != PUBLICKEYBLOB) || // PUBLICKEYBLOB (0x06) (blob[offset + 1] != CUR_BLOB_VERSION) || // Version (0x02) (blob[offset + 2] != 0x00) || // Reserved (word) (blob[offset + 3] != 0x00) || @@ -278,7 +278,7 @@ internal class PSCryptoException : Exception { #region Private Members - private uint _errorCode; + private readonly uint _errorCode; #endregion Private Members @@ -302,7 +302,8 @@ internal uint ErrorCode /// /// Default constructor. /// - public PSCryptoException() : this(0, new StringBuilder(string.Empty)) { } + public PSCryptoException() + : this(0, new StringBuilder(string.Empty)) { } /// /// Constructor that will be used from within CryptoUtils. @@ -320,7 +321,8 @@ public PSCryptoException(uint errorCode, StringBuilder message) /// Constructor with just message but no inner exception. /// /// Error message associated with this failure. - public PSCryptoException(string message) : this(message, null) { } + public PSCryptoException(string message) + : this(message, null) { } /// /// Constructor with inner exception. @@ -329,8 +331,8 @@ public PSCryptoException(string message) : this(message, null) { } /// Inner exception. /// This constructor is currently not called /// explicitly from crypto utils - public PSCryptoException(string message, Exception innerException) : - base(message, innerException) + public PSCryptoException(string message, Exception innerException) + : base(message, innerException) { _errorCode = unchecked((uint)-1); } @@ -343,8 +345,7 @@ public PSCryptoException(string message, Exception innerException) : /// Currently no custom type-specific serialization logic is /// implemented protected PSCryptoException(SerializationInfo info, StreamingContext context) - : - base(info, context) + : base(info, context) { _errorCode = unchecked(0xFFFFFFF); Dbg.Assert(false, "type-specific serialization logic not implemented and so this constructor should not be called"); @@ -369,7 +370,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont /// A reverse compatible implementation of session key exchange. This supports the CAPI /// keyblob formats but uses dotnet std abstract AES and RSA classes for all crypto operations. /// - internal class PSRSACryptoServiceProvider : IDisposable + internal sealed class PSRSACryptoServiceProvider : IDisposable { #region Private Members @@ -386,7 +387,7 @@ internal class PSRSACryptoServiceProvider : IDisposable // bool indicating if session key was generated before private bool _sessionKeyGenerated = false; - private static object s_syncObject = new object(); + private static readonly object s_syncObject = new object(); #endregion Private Members @@ -611,7 +612,7 @@ public void Dispose() System.GC.SuppressFinalize(this); } - protected void Dispose(bool disposing) + private void Dispose(bool disposing) { if (disposing) { @@ -627,18 +628,6 @@ protected void Dispose(bool disposing) } } - /// - /// Destructor. - /// - ~PSRSACryptoServiceProvider() - { - // When Dispose() is called, GC.SuppressFinalize() - // is called and therefore this finalizer will not - // be invoked. Hence this is run only on process - // shutdown - Dispose(true); - } - #endregion IDisposable } diff --git a/src/System.Management.Automation/utils/EncodingUtils.cs b/src/System.Management.Automation/utils/EncodingUtils.cs index b5859155d1c..e9802488006 100644 --- a/src/System.Management.Automation/utils/EncodingUtils.cs +++ b/src/System.Management.Automation/utils/EncodingUtils.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Globalization; -using System.IO; using System.Text; using System.Management.Automation.Internal; @@ -66,7 +64,7 @@ internal static Encoding Convert(Cmdlet cmdlet, string encoding) if (encodingMap.TryGetValue(encoding, out foundEncoding)) { // Write a warning if using utf7 as it is obsolete in .NET5 - if (string.Compare(encoding, Utf7, StringComparison.OrdinalIgnoreCase) == 0) + if (string.Equals(encoding, Utf7, StringComparison.OrdinalIgnoreCase)) { cmdlet.WriteWarning(PathUtilsStrings.Utf7EncodingObsolete); } diff --git a/src/System.Management.Automation/utils/ExecutionExceptions.cs b/src/System.Management.Automation/utils/ExecutionExceptions.cs index aa779ffcdeb..226a9cb8cdd 100644 --- a/src/System.Management.Automation/utils/ExecutionExceptions.cs +++ b/src/System.Management.Automation/utils/ExecutionExceptions.cs @@ -7,7 +7,6 @@ using System.Runtime.Serialization; using System.Diagnostics.CodeAnalysis; using System.Management.Automation.Internal; -using System.Security.Permissions; #pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings @@ -275,7 +274,7 @@ public ProviderInvocationException ProviderInvocationException } [NonSerialized] - private ProviderInvocationException _providerInvocationException; + private readonly ProviderInvocationException _providerInvocationException; /// /// This is the ProviderInfo associated with the provider which @@ -286,9 +285,7 @@ public ProviderInfo ProviderInfo { get { - return (_providerInvocationException == null) - ? null - : _providerInvocationException.ProviderInfo; + return _providerInvocationException?.ProviderInfo; } } @@ -297,7 +294,7 @@ public ProviderInfo ProviderInfo #region Internal private static Exception GetInnerException(Exception e) { - return (e == null) ? null : e.InnerException; + return e?.InnerException; } #endregion Internal } @@ -710,7 +707,7 @@ public override string Message { get { - return _message ?? (_message = (_wrapperException != null) ? _wrapperException.Message : string.Empty); + return _message ??= (_wrapperException != null) ? _wrapperException.Message : string.Empty; } } diff --git a/src/System.Management.Automation/utils/ExtensionMethods.cs b/src/System.Management.Automation/utils/ExtensionMethods.cs index 127c9a226cf..f3dc94c047b 100644 --- a/src/System.Management.Automation/utils/ExtensionMethods.cs +++ b/src/System.Management.Automation/utils/ExtensionMethods.cs @@ -12,18 +12,12 @@ internal static class ExtensionMethods { public static void SafeInvoke(this EventHandler eventHandler, object sender, EventArgs eventArgs) { - if (eventHandler != null) - { - eventHandler(sender, eventArgs); - } + eventHandler?.Invoke(sender, eventArgs); } public static void SafeInvoke(this EventHandler eventHandler, object sender, T eventArgs) where T : EventArgs { - if (eventHandler != null) - { - eventHandler(sender, eventArgs); - } + eventHandler?.Invoke(sender, eventArgs); } } @@ -49,10 +43,10 @@ internal static int SequenceGetHashCode(this IEnumerable xs) int hash = 41; // 41 is a random prime number foreach (T x in xs) { - hash = hash * 59; // 59 is a random prime number + hash *= 59; // 59 is a random prime number if (x != null) { - hash = hash + x.GetHashCode(); + hash += x.GetHashCode(); } } diff --git a/src/System.Management.Automation/utils/FormatAndTypeDataHelper.cs b/src/System.Management.Automation/utils/FormatAndTypeDataHelper.cs index db68073deb4..87da1d2a1d7 100644 --- a/src/System.Management.Automation/utils/FormatAndTypeDataHelper.cs +++ b/src/System.Management.Automation/utils/FormatAndTypeDataHelper.cs @@ -5,9 +5,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; -using System.Management.Automation.Host; using System.Management.Automation.Internal; -using System.Reflection; using System.Text; namespace System.Management.Automation.Runspaces @@ -75,7 +73,7 @@ internal static class FormatAndTypeDataHelper private static string GetBaseFolder(Collection independentErrors) { - return Path.GetDirectoryName(PsUtils.GetMainModule(System.Diagnostics.Process.GetCurrentProcess()).FileName); + return Path.GetDirectoryName(Environment.ProcessPath); } private static string GetAndCheckFullFileName( @@ -173,7 +171,7 @@ internal static void ThrowExceptionOnError( ConcurrentBag errors, Category category) { - if (errors.Count == 0) + if (errors.IsEmpty) { return; } @@ -210,4 +208,3 @@ internal enum Category } } } - diff --git a/src/System.Management.Automation/utils/FuzzyMatch.cs b/src/System.Management.Automation/utils/FuzzyMatch.cs index 3052cf6e3f2..5b21022a6ef 100644 --- a/src/System.Management.Automation/utils/FuzzyMatch.cs +++ b/src/System.Management.Automation/utils/FuzzyMatch.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Globalization; namespace System.Management.Automation diff --git a/src/System.Management.Automation/utils/GraphicalHostReflectionWrapper.cs b/src/System.Management.Automation/utils/GraphicalHostReflectionWrapper.cs index 7579245980b..a0b12f986de 100644 --- a/src/System.Management.Automation/utils/GraphicalHostReflectionWrapper.cs +++ b/src/System.Management.Automation/utils/GraphicalHostReflectionWrapper.cs @@ -18,7 +18,7 @@ namespace System.Management.Automation.Internal /// 2) show-command window implementation (the actual cmdlet is in Microsoft.PowerShell.Commands.Utility.dll) /// 3) the help window used in the System.Management.Automation.dll's get-help cmdlet when -ShowWindow is specified. /// - internal class GraphicalHostReflectionWrapper + internal sealed class GraphicalHostReflectionWrapper { /// /// Initialized in GetGraphicalHostReflectionWrapper with the Microsoft.PowerShell.GraphicalHost.dll assembly. @@ -128,12 +128,12 @@ internal static GraphicalHostReflectionWrapper GetGraphicalHostReflectionWrapper ConstructorInfo constructor = returnValue._graphicalHostHelperType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, - new Type[] { }, + Array.Empty(), null); if (constructor != null) { - returnValue._graphicalHostHelperObject = constructor.Invoke(new object[] { }); + returnValue._graphicalHostHelperObject = constructor.Invoke(Array.Empty()); Diagnostics.Assert(returnValue._graphicalHostHelperObject != null, "the constructor does not throw anything"); } @@ -187,7 +187,7 @@ internal object GetPropertyValue(string propertyName) Diagnostics.Assert(_graphicalHostHelperObject != null, "there should be a constructor in order to get an instance property value"); PropertyInfo property = _graphicalHostHelperType.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance); Diagnostics.Assert(property != null, "property " + propertyName + " exists in graphicalHostHelperType is verified by caller"); - return property.GetValue(_graphicalHostHelperObject, new object[] { }); + return property.GetValue(_graphicalHostHelperObject, Array.Empty()); } /// @@ -199,7 +199,7 @@ internal object GetStaticPropertyValue(string propertyName) { PropertyInfo property = _graphicalHostHelperType.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Static); Diagnostics.Assert(property != null, "property " + propertyName + " exists in graphicalHostHelperType is verified by caller"); - return property.GetValue(null, new object[] { }); + return property.GetValue(null, Array.Empty()); } /// diff --git a/src/System.Management.Automation/utils/HostInterfacesExceptions.cs b/src/System.Management.Automation/utils/HostInterfacesExceptions.cs index dab2568a2f7..91e742fa3c5 100644 --- a/src/System.Management.Automation/utils/HostInterfacesExceptions.cs +++ b/src/System.Management.Automation/utils/HostInterfacesExceptions.cs @@ -19,8 +19,8 @@ class HostException : RuntimeException /// Initializes a new instance of the HostException class. /// public - HostException() : base( - StringUtil.Format(HostInterfaceExceptionsStrings.DefaultCtorMessageTemplate, typeof(HostException).FullName)) + HostException() + : base(StringUtil.Format(HostInterfaceExceptionsStrings.DefaultCtorMessageTemplate, typeof(HostException).FullName)) { SetDefaultErrorRecord(); } @@ -32,7 +32,8 @@ class HostException : RuntimeException /// The error message that explains the reason for the exception. /// public - HostException(string message) : base(message) + HostException(string message) + : base(message) { SetDefaultErrorRecord(); } @@ -79,8 +80,12 @@ class HostException : RuntimeException /// Intentionally public, third-party hosts can call this /// public - HostException(string message, Exception innerException, string errorId, ErrorCategory errorCategory) : - base(message, innerException) + HostException( + string message, + Exception innerException, + string errorId, + ErrorCategory errorCategory) + : base(message, innerException) { SetErrorId(errorId); SetErrorCategory(errorCategory); @@ -101,6 +106,7 @@ class HostException : RuntimeException : base(info, context) { } + #endregion #region private private void SetDefaultErrorRecord() @@ -124,7 +130,8 @@ class PromptingException : HostException /// Initializes a new instance of the PromptingException class. /// public - PromptingException() : base(StringUtil.Format(HostInterfaceExceptionsStrings.DefaultCtorMessageTemplate, typeof(PromptingException).FullName)) + PromptingException() + : base(StringUtil.Format(HostInterfaceExceptionsStrings.DefaultCtorMessageTemplate, typeof(PromptingException).FullName)) { SetDefaultErrorRecord(); } @@ -136,7 +143,8 @@ class PromptingException : HostException /// The error message that explains the reason for the exception. /// public - PromptingException(string message) : base(message) + PromptingException(string message) + : base(message) { SetDefaultErrorRecord(); } @@ -183,8 +191,12 @@ class PromptingException : HostException /// Intentionally public, third-party hosts can call this /// public - PromptingException(string message, Exception innerException, string errorId, ErrorCategory errorCategory) : - base(message, innerException, errorId, errorCategory) + PromptingException( + string message, + Exception innerException, + string errorId, + ErrorCategory errorCategory) + : base(message, innerException, errorId, errorCategory) { } diff --git a/src/System.Management.Automation/utils/IObjectReader.cs b/src/System.Management.Automation/utils/IObjectReader.cs index a4fb4a53f37..c2ef1d6cf32 100644 --- a/src/System.Management.Automation/utils/IObjectReader.cs +++ b/src/System.Management.Automation/utils/IObjectReader.cs @@ -5,8 +5,6 @@ using System.Collections.ObjectModel; using System.Threading; -using Dbg = System.Management.Automation.Diagnostics; - namespace System.Management.Automation.Runspaces { /// diff --git a/src/System.Management.Automation/utils/IObjectWriter.cs b/src/System.Management.Automation/utils/IObjectWriter.cs index eaed1ef5e55..49181e34584 100644 --- a/src/System.Management.Automation/utils/IObjectWriter.cs +++ b/src/System.Management.Automation/utils/IObjectWriter.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections; using System.Threading; @@ -124,7 +123,7 @@ public abstract int MaxCapacity internal class DiscardingPipelineWriter : PipelineWriter { - private ManualResetEvent _waitHandle = new ManualResetEvent(true); + private readonly ManualResetEvent _waitHandle = new ManualResetEvent(true); public override WaitHandle WaitHandle { @@ -161,7 +160,7 @@ public override void Flush() public override int Write(object obj) { - int numberOfObjectsWritten = 1; + const int numberOfObjectsWritten = 1; _count += numberOfObjectsWritten; return numberOfObjectsWritten; } @@ -192,4 +191,3 @@ public override int Write(object obj, bool enumerateCollection) } } } - diff --git a/src/System.Management.Automation/utils/MetadataExceptions.cs b/src/System.Management.Automation/utils/MetadataExceptions.cs index 21f9a9b842c..53f2328fc3d 100644 --- a/src/System.Management.Automation/utils/MetadataExceptions.cs +++ b/src/System.Management.Automation/utils/MetadataExceptions.cs @@ -54,8 +54,14 @@ public MetadataException(string message, Exception innerException) : base(messag SetErrorCategory(ErrorCategory.MetadataError); } - internal MetadataException(string errorId, Exception innerException, string resourceStr, params object[] arguments) : - base(StringUtil.Format(resourceStr, arguments), innerException) + internal MetadataException( + string errorId, + Exception innerException, + string resourceStr, + params object[] arguments) + : base( + StringUtil.Format(resourceStr, arguments), + innerException) { SetErrorCategory(ErrorCategory.MetadataError); SetErrorId(errorId); @@ -121,8 +127,12 @@ public ValidationMetadataException(string message) : this(message, false) { } /// The exceptions's inner exception. public ValidationMetadataException(string message, Exception innerException) : base(message, innerException) { } - internal ValidationMetadataException(string errorId, Exception innerException, string resourceStr, params object[] arguments) : - base(errorId, innerException, resourceStr, arguments) + internal ValidationMetadataException( + string errorId, + Exception innerException, + string resourceStr, + params object[] arguments) + : base(errorId, innerException, resourceStr, arguments) { } @@ -151,7 +161,7 @@ internal bool SwallowException get { return _swallowException; } } - private bool _swallowException = false; + private readonly bool _swallowException = false; } /// @@ -167,26 +177,37 @@ public class ArgumentTransformationMetadataException : MetadataException /// /// Serialization information. /// Streaming context. - protected ArgumentTransformationMetadataException(SerializationInfo info, StreamingContext context) : base(info, context) { } + protected ArgumentTransformationMetadataException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + /// /// Initializes a new instance of ArgumentTransformationMetadataException with the message set /// to typeof(ArgumentTransformationMetadataException).FullName. /// - public ArgumentTransformationMetadataException() : base(typeof(ArgumentTransformationMetadataException).FullName) { } + public ArgumentTransformationMetadataException() + : base(typeof(ArgumentTransformationMetadataException).FullName) { } + /// /// Initializes a new instance of ArgumentTransformationMetadataException setting the message. /// /// The exception's message. - public ArgumentTransformationMetadataException(string message) : base(message) { } + public ArgumentTransformationMetadataException(string message) + : base(message) { } + /// /// Initializes a new instance of ArgumentTransformationMetadataException setting the message and innerException. /// /// The exception's message. /// The exceptions's inner exception. - public ArgumentTransformationMetadataException(string message, Exception innerException) : base(message, innerException) { } + public ArgumentTransformationMetadataException(string message, Exception innerException) + : base(message, innerException) { } - internal ArgumentTransformationMetadataException(string errorId, Exception innerException, string resourceStr, params object[] arguments) : - base(errorId, innerException, resourceStr, arguments) + internal ArgumentTransformationMetadataException( + string errorId, + Exception innerException, + string resourceStr, + params object[] arguments) + : base(errorId, innerException, resourceStr, arguments) { } } @@ -204,28 +225,38 @@ public class ParsingMetadataException : MetadataException /// /// Serialization information. /// Streaming context. - protected ParsingMetadataException(SerializationInfo info, StreamingContext context) : base(info, context) { } + protected ParsingMetadataException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + /// /// Initializes a new instance of ParsingMetadataException with the message set /// to typeof(ParsingMetadataException).FullName. /// - public ParsingMetadataException() : base(typeof(ParsingMetadataException).FullName) { } + public ParsingMetadataException() + : base(typeof(ParsingMetadataException).FullName) { } + /// /// Initializes a new instance of ParsingMetadataException setting the message. /// /// The exception's message. - public ParsingMetadataException(string message) : base(message) { } + public ParsingMetadataException(string message) + : base(message) { } + /// /// Initializes a new instance of ParsingMetadataException setting the message and innerException. /// /// The exception's message. /// The exceptions's inner exception. - public ParsingMetadataException(string message, Exception innerException) : base(message, innerException) { } + public ParsingMetadataException(string message, Exception innerException) + : base(message, innerException) { } - internal ParsingMetadataException(string errorId, Exception innerException, string resourceStr, params object[] arguments) : - base(errorId, innerException, resourceStr, arguments) + internal ParsingMetadataException( + string errorId, + Exception innerException, + string resourceStr, + params object[] arguments) + : base(errorId, innerException, resourceStr, arguments) { } } } - diff --git a/src/System.Management.Automation/utils/MshArgumentException.cs b/src/System.Management.Automation/utils/MshArgumentException.cs index 73a117d107f..d9c9ce725eb 100644 --- a/src/System.Management.Automation/utils/MshArgumentException.cs +++ b/src/System.Management.Automation/utils/MshArgumentException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -136,7 +135,7 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "Argument"; + private readonly string _errorId = "Argument"; /// /// See @@ -151,7 +150,6 @@ public override string Message get { return string.IsNullOrEmpty(_message) ? base.Message : _message; } } - private string _message; + private readonly string _message; } } - diff --git a/src/System.Management.Automation/utils/MshArgumentNullException.cs b/src/System.Management.Automation/utils/MshArgumentNullException.cs index 95d5dfa00df..be20163607b 100644 --- a/src/System.Management.Automation/utils/MshArgumentNullException.cs +++ b/src/System.Management.Automation/utils/MshArgumentNullException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -134,7 +133,7 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "ArgumentNull"; + private readonly string _errorId = "ArgumentNull"; /// /// See @@ -149,7 +148,6 @@ public override string Message get { return string.IsNullOrEmpty(_message) ? base.Message : _message; } } - private string _message; + private readonly string _message; } } - diff --git a/src/System.Management.Automation/utils/MshArgumentOutOfRangeException.cs b/src/System.Management.Automation/utils/MshArgumentOutOfRangeException.cs index 158354bcc7e..2bf48e9047f 100644 --- a/src/System.Management.Automation/utils/MshArgumentOutOfRangeException.cs +++ b/src/System.Management.Automation/utils/MshArgumentOutOfRangeException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -132,7 +131,6 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "ArgumentOutOfRange"; + private readonly string _errorId = "ArgumentOutOfRange"; } } - diff --git a/src/System.Management.Automation/utils/MshInvalidOperationException.cs b/src/System.Management.Automation/utils/MshInvalidOperationException.cs index f09671cbde1..f9a65fcf8aa 100644 --- a/src/System.Management.Automation/utils/MshInvalidOperationException.cs +++ b/src/System.Management.Automation/utils/MshInvalidOperationException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -137,8 +136,7 @@ internal void SetErrorId(string errorId) _errorId = errorId; } - private ErrorCategory _errorCategory = ErrorCategory.InvalidOperation; - private object _target = null; + private readonly ErrorCategory _errorCategory = ErrorCategory.InvalidOperation; + private readonly object _target = null; } } - diff --git a/src/System.Management.Automation/utils/MshNotImplementedException.cs b/src/System.Management.Automation/utils/MshNotImplementedException.cs index 463be0dc053..6c2dd504cf0 100644 --- a/src/System.Management.Automation/utils/MshNotImplementedException.cs +++ b/src/System.Management.Automation/utils/MshNotImplementedException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -113,7 +112,6 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "NotImplemented"; + private readonly string _errorId = "NotImplemented"; } } - diff --git a/src/System.Management.Automation/utils/MshNotSupportedException.cs b/src/System.Management.Automation/utils/MshNotSupportedException.cs index f438596d524..7614080dcff 100644 --- a/src/System.Management.Automation/utils/MshNotSupportedException.cs +++ b/src/System.Management.Automation/utils/MshNotSupportedException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -113,7 +112,6 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "NotSupported"; + private readonly string _errorId = "NotSupported"; } } - diff --git a/src/System.Management.Automation/utils/MshObjectDisposedException.cs b/src/System.Management.Automation/utils/MshObjectDisposedException.cs index 53204ab2a6c..b8d4ab421cc 100644 --- a/src/System.Management.Automation/utils/MshObjectDisposedException.cs +++ b/src/System.Management.Automation/utils/MshObjectDisposedException.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -119,7 +118,6 @@ public ErrorRecord ErrorRecord } private ErrorRecord _errorRecord; - private string _errorId = "ObjectDisposed"; + private readonly string _errorId = "ObjectDisposed"; } } - diff --git a/src/System.Management.Automation/utils/MshTraceSource.cs b/src/System.Management.Automation/utils/MshTraceSource.cs index 946267d2800..8ed5949c31a 100644 --- a/src/System.Management.Automation/utils/MshTraceSource.cs +++ b/src/System.Management.Automation/utils/MshTraceSource.cs @@ -49,7 +49,7 @@ public partial class PSTraceSource /// /// Lock object for the GetTracer method. /// - private static object s_getTracerLock = new object(); + private static readonly object s_getTracerLock = new object(); /// /// A helper to get an instance of the PSTraceSource class. @@ -554,4 +554,3 @@ internal static PSObjectDisposedException NewObjectDisposedException(string obje #endregion TraceFlags.New*Exception methods/helpers } } - diff --git a/src/System.Management.Automation/utils/ObjectReader.cs b/src/System.Management.Automation/utils/ObjectReader.cs index deb056a180e..b333ec25be2 100644 --- a/src/System.Management.Automation/utils/ObjectReader.cs +++ b/src/System.Management.Automation/utils/ObjectReader.cs @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.ObjectModel; -using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Runtime.InteropServices; using System.Threading; @@ -23,7 +21,7 @@ internal abstract class ObjectReaderBase : PipelineReader, IDisposable /// /// The stream to read. /// Thrown if the specified stream is null. - public ObjectReaderBase([In, Out] ObjectStreamBase stream) + protected ObjectReaderBase([In, Out] ObjectStreamBase stream) { if (stream == null) { @@ -203,7 +201,7 @@ private void OnDataReady(object sender, EventArgs args) /// we are protected from outside code interfering in our /// critical section. Thanks to Wintellect for the hint. /// - private object _monitorObject = new object(); + private readonly object _monitorObject = new object(); #endregion Private fields @@ -485,12 +483,12 @@ private static Collection MakePSObjectCollection( /// commands concurrently. /// Only Read() operation is supported currently. /// - internal class PSDataCollectionReader - : ObjectReaderBase + internal class PSDataCollectionReader + : ObjectReaderBase { #region Private Data - private PSDataCollectionEnumerator _enumerator; + private readonly PSDataCollectionEnumerator _enumerator; #endregion @@ -500,12 +498,12 @@ internal class PSDataCollectionReader /// /// The stream to read. /// Thrown if the specified stream is null. - public PSDataCollectionReader(PSDataCollectionStream stream) + public PSDataCollectionReader(PSDataCollectionStream stream) : base(stream) { System.Management.Automation.Diagnostics.Assert(stream.ObjectStore != null, "Stream should have a valid data store"); - _enumerator = (PSDataCollectionEnumerator)stream.ObjectStore.GetEnumerator(); + _enumerator = (PSDataCollectionEnumerator)stream.ObjectStore.GetEnumerator(); } #endregion ctor @@ -515,7 +513,7 @@ public PSDataCollectionReader(PSDataCollectionStream stream) /// /// The maximum number of objects to read. /// The objects read. - public override Collection Read(int count) + public override Collection Read(int count) { throw new NotSupportedException(); } @@ -530,7 +528,7 @@ public override Collection Read(int count) /// /// This method blocks if the buffer is empty. /// - public override ReturnType Read() + public override TResult Read() { object result = AutomationNull.Value; if (_enumerator.MoveNext()) @@ -546,7 +544,7 @@ public override ReturnType Read() /// /// /// - public override Collection ReadToEnd() + public override Collection ReadToEnd() { throw new NotSupportedException(); } @@ -556,7 +554,7 @@ public override Collection ReadToEnd() /// /// /// - public override Collection NonBlockingRead() + public override Collection NonBlockingRead() { return NonBlockingRead(Int32.MaxValue); } @@ -569,7 +567,7 @@ public override Collection NonBlockingRead() /// /// Return no more than maxRequested objects. /// - public override Collection NonBlockingRead(int maxRequested) + public override Collection NonBlockingRead(int maxRequested) { if (maxRequested < 0) { @@ -578,31 +576,31 @@ public override Collection NonBlockingRead(int maxRequested) if (maxRequested == 0) { - return new Collection(); + return new Collection(); } - Collection results = new Collection(); + Collection result = new Collection(); int readCount = maxRequested; while (readCount > 0) { if (_enumerator.MoveNext(false)) { - results.Add(ConvertToReturnType(_enumerator.Current)); + result.Add(ConvertToReturnType(_enumerator.Current)); continue; } break; } - return results; + return result; } /// /// This method is not supported. /// /// - public override ReturnType Peek() + public override TResult Peek() { throw new NotSupportedException(); } @@ -619,12 +617,12 @@ protected override void Dispose(bool disposing) } } - private ReturnType ConvertToReturnType(object inputObject) + private static TResult ConvertToReturnType(object inputObject) { - Type resultType = typeof(ReturnType); + Type resultType = typeof(TResult); if (typeof(PSObject) == resultType || typeof(object) == resultType) { - ReturnType result; + TResult result; LanguagePrimitives.TryConvertTo(inputObject, out result); return result; } @@ -644,12 +642,12 @@ private ReturnType ConvertToReturnType(object inputObject) /// commands concurrently. /// Only Read() operation is supported currently. /// - internal class PSDataCollectionPipelineReader - : ObjectReaderBase + internal class PSDataCollectionPipelineReader + : ObjectReaderBase { #region Private Data - private PSDataCollection _datastore; + private readonly PSDataCollection _datastore; #endregion Private Data @@ -660,7 +658,7 @@ internal class PSDataCollectionPipelineReader /// The stream to read. /// /// - internal PSDataCollectionPipelineReader(PSDataCollectionStream stream, + internal PSDataCollectionPipelineReader(PSDataCollectionStream stream, string computerName, Guid runspaceId) : base(stream) { @@ -690,7 +688,7 @@ internal PSDataCollectionPipelineReader(PSDataCollectionStream st /// /// The maximum number of objects to read. /// The objects read. - public override Collection Read(int count) + public override Collection Read(int count) { throw new NotSupportedException(); } @@ -705,14 +703,14 @@ public override Collection Read(int count) /// /// This method blocks if the buffer is empty. /// - public override ReturnType Read() + public override TReturn Read() { object result = AutomationNull.Value; if (_datastore.Count > 0) { - Collection resultCollection = _datastore.ReadAndRemove(1); + Collection resultCollection = _datastore.ReadAndRemove(1); - // ReadAndRemove returns a Collection type but we + // ReadAndRemove returns a Collection type but we // just want the single object contained in the collection. if (resultCollection.Count == 1) { @@ -728,7 +726,7 @@ public override ReturnType Read() /// /// /// - public override Collection ReadToEnd() + public override Collection ReadToEnd() { throw new NotSupportedException(); } @@ -738,7 +736,7 @@ public override Collection ReadToEnd() /// /// /// - public override Collection NonBlockingRead() + public override Collection NonBlockingRead() { return NonBlockingRead(Int32.MaxValue); } @@ -751,7 +749,7 @@ public override Collection NonBlockingRead() /// /// Return no more than maxRequested objects. /// - public override Collection NonBlockingRead(int maxRequested) + public override Collection NonBlockingRead(int maxRequested) { if (maxRequested < 0) { @@ -760,10 +758,10 @@ public override Collection NonBlockingRead(int maxRequested) if (maxRequested == 0) { - return new Collection(); + return new Collection(); } - Collection results = new Collection(); + Collection results = new Collection(); int readCount = maxRequested; while (readCount > 0) @@ -785,7 +783,7 @@ public override Collection NonBlockingRead(int maxRequested) /// This method is not supported. /// /// - public override ReturnType Peek() + public override TReturn Peek() { throw new NotSupportedException(); } @@ -795,12 +793,12 @@ public override ReturnType Peek() /// /// Input object to convert. /// Input object converted to the specified return type. - private ReturnType ConvertToReturnType(object inputObject) + private static TReturn ConvertToReturnType(object inputObject) { - Type resultType = typeof(ReturnType); + Type resultType = typeof(TReturn); if (typeof(PSObject) == resultType || typeof(object) == resultType) { - ReturnType result; + TReturn result; LanguagePrimitives.TryConvertTo(inputObject, out result); return result; } diff --git a/src/System.Management.Automation/utils/ObjectStream.cs b/src/System.Management.Automation/utils/ObjectStream.cs index bd3fb0c6a64..2f4cbef8a08 100644 --- a/src/System.Management.Automation/utils/ObjectStream.cs +++ b/src/System.Management.Automation/utils/ObjectStream.cs @@ -401,7 +401,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable // PERF-2003/08/22-JonN We should probably use Queue instead // PERF-2004/06/30-JonN Probably more efficient to use type // Collection as the underlying store - private List _objects; + private readonly List _objects; /// /// Is the stream open or closed for writing? @@ -420,7 +420,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// the stream is closed for reading. Instead, use WaitAny on /// this handle and also _readClosedHandle. /// - private AutoResetEvent _readHandle; + private readonly AutoResetEvent _readHandle; /// /// Handle returned to callers for blocking on data ready. @@ -431,7 +431,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// When this handle is set, the stream is closed for reading, /// so all blocked readers should be released. /// - private ManualResetEvent _readClosedHandle; + private readonly ManualResetEvent _readClosedHandle; /// /// Write handle - signaled with the number of objects in the @@ -446,7 +446,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// the stream is closed for writing. Instead, use WaitAny on /// this handle and also _writeClosedHandle. /// - private AutoResetEvent _writeHandle; + private readonly AutoResetEvent _writeHandle; /// /// Handle returned to callers for blocking until buffer space @@ -458,7 +458,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// When this handle is set, the stream is closed for writing, /// so all blocked readers should be released. /// - private ManualResetEvent _writeClosedHandle; + private readonly ManualResetEvent _writeClosedHandle; #endregion Synchronization handles /// @@ -493,7 +493,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// Note that this is not permitted to be more than Int32.MaxValue, /// since the underlying list has this limitation. /// - private int _capacity = Int32.MaxValue; + private readonly int _capacity = Int32.MaxValue; /// /// This object is used to acquire an exclusive lock on the stream. @@ -503,7 +503,7 @@ internal sealed class ObjectStream : ObjectStreamBase, IDisposable /// we are protected from outside code interfering in our /// critical section. Thanks to Wintellect for the hint. /// - private object _monitorObject = new object(); + private readonly object _monitorObject = new object(); /// /// Indicates if this stream has already been disposed. @@ -755,7 +755,7 @@ internal override bool EndOfPipeline lock (_monitorObject) { - endOfStream = (_objects.Count == 0 && _isOpen == false); + endOfStream = (_objects.Count == 0 && !_isOpen); } return endOfStream; @@ -824,7 +824,7 @@ internal override int Count /// private bool WaitRead() { - if (EndOfPipeline == false) + if (!EndOfPipeline) { try { @@ -839,7 +839,7 @@ private bool WaitRead() } } - return EndOfPipeline == false; + return !EndOfPipeline; } /// @@ -1383,7 +1383,7 @@ internal override int Write(object obj, bool enumerateCollection) // wait for buffer available // false indicates EndOfPipeline - if (WaitWrite() == false) + if (!WaitWrite()) { break; } @@ -1403,7 +1403,7 @@ internal override int Write(object obj, bool enumerateCollection) // subtraction to ensure we don't have an // overflow exception int freeSpace = _capacity - _objects.Count; - if (0 >= freeSpace) + if (freeSpace <= 0) { // NOTE: lock is released in finally continue; @@ -1551,15 +1551,15 @@ internal sealed class PSDataCollectionStream : ObjectStreamBase { #region Private Fields - private PSDataCollection _objects; - private Guid _psInstanceId; + private readonly PSDataCollection _objects; + private readonly Guid _psInstanceId; private bool _isOpen; private PipelineWriter _writer; private PipelineReader _objectReader; private PipelineReader _psobjectReader; private PipelineReader _objectReaderForPipeline; private PipelineReader _psobjectReaderForPipeline; - private object _syncObject = new object(); + private readonly object _syncObject = new object(); private bool _disposed = false; #endregion @@ -1979,4 +1979,3 @@ protected override void Dispose(bool disposing) #endregion IDisposable } } - diff --git a/src/System.Management.Automation/utils/ObjectWriter.cs b/src/System.Management.Automation/utils/ObjectWriter.cs index f6bf752062e..fe7b9c6deac 100644 --- a/src/System.Management.Automation/utils/ObjectWriter.cs +++ b/src/System.Management.Automation/utils/ObjectWriter.cs @@ -199,7 +199,7 @@ private void OnWriteReady (object sender, EventArgs args) /// The underlying stream. /// /// Can never be null - private ObjectStreamBase _stream; + private readonly ObjectStreamBase _stream; #endregion Private Fields } @@ -232,4 +232,3 @@ public PSDataCollectionWriter(PSDataCollectionStream stream) #endregion } } - diff --git a/src/System.Management.Automation/utils/PInvokeDllNames.cs b/src/System.Management.Automation/utils/PInvokeDllNames.cs index 7dd28be8cdd..bff2ca2656e 100644 --- a/src/System.Management.Automation/utils/PInvokeDllNames.cs +++ b/src/System.Management.Automation/utils/PInvokeDllNames.cs @@ -116,27 +116,26 @@ internal static class PinvokeDllNames internal const string PeekConsoleInputDllName = "api-ms-win-core-console-l2-1-0.dll"; /*103*/ internal const string GetNumberOfConsoleInputEventsDllName = "api-ms-win-core-console-l1-1-0.dll"; /*104*/ internal const string SetConsoleCtrlHandlerDllName = "api-ms-win-core-console-l1-1-0.dll"; /*105*/ - internal const string SetConsoleCursorPositionDllName = "api-ms-win-core-console-l2-1-0.dll"; /*106*/ - internal const string SetConsoleModeDllName = "api-ms-win-core-console-l1-1-0.dll"; /*107*/ - internal const string SetConsoleScreenBufferSizeDllName = "api-ms-win-core-console-l2-1-0.dll"; /*108*/ - internal const string SetConsoleTextAttributeDllName = "api-ms-win-core-console-l2-1-0.dll"; /*109*/ - internal const string SetConsoleWindowInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*110*/ - internal const string WriteConsoleOutputDllName = "api-ms-win-core-console-l2-1-0.dll"; /*111*/ - internal const string ReadConsoleOutputDllName = "api-ms-win-core-console-l2-1-0.dll"; /*112*/ - internal const string ScrollConsoleScreenBufferDllName = "api-ms-win-core-console-l2-1-0.dll"; /*113*/ - internal const string SendInputDllName = "ext-ms-win-ntuser-keyboard-l1-2-1.dll"; /*114*/ - internal const string GetConsoleCursorInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*115*/ - internal const string SetConsoleCursorInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*116*/ - internal const string ReadConsoleInputDllName = "api-ms-win-core-console-l1-1-0.dll"; /*117*/ - internal const string GetVersionExDllName = "api-ms-win-core-sysinfo-l1-1-0.dll"; /*118*/ - internal const string FormatMessageDllName = "api-ms-win-core-localization-l1-2-0.dll"; /*119*/ - internal const string CreateToolhelp32SnapshotDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*120*/ - internal const string Process32FirstDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*121*/ - internal const string Process32NextDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*122*/ - internal const string GetACPDllName = "api-ms-win-core-localization-l1-2-0.dll"; /*123*/ - internal const string DeleteServiceDllName = "api-ms-win-service-management-l1-1-0.dll"; /*124*/ - internal const string QueryServiceConfigDllName = "api-ms-win-service-management-l2-1-0.dll"; /*125*/ - internal const string QueryServiceConfig2DllName = "api-ms-win-service-management-l2-1-0.dll"; /*126*/ - internal const string SetServiceObjectSecurityDllName = "api-ms-win-service-management-l2-1-0.dll"; /*127*/ + internal const string SetConsoleModeDllName = "api-ms-win-core-console-l1-1-0.dll"; /*106*/ + internal const string SetConsoleScreenBufferSizeDllName = "api-ms-win-core-console-l2-1-0.dll"; /*107*/ + internal const string SetConsoleTextAttributeDllName = "api-ms-win-core-console-l2-1-0.dll"; /*108*/ + internal const string SetConsoleWindowInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*109*/ + internal const string WriteConsoleOutputDllName = "api-ms-win-core-console-l2-1-0.dll"; /*110*/ + internal const string ReadConsoleOutputDllName = "api-ms-win-core-console-l2-1-0.dll"; /*111*/ + internal const string ScrollConsoleScreenBufferDllName = "api-ms-win-core-console-l2-1-0.dll"; /*112*/ + internal const string SendInputDllName = "ext-ms-win-ntuser-keyboard-l1-2-1.dll"; /*113*/ + internal const string GetConsoleCursorInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*114*/ + internal const string SetConsoleCursorInfoDllName = "api-ms-win-core-console-l2-1-0.dll"; /*115*/ + internal const string ReadConsoleInputDllName = "api-ms-win-core-console-l1-1-0.dll"; /*116*/ + internal const string GetVersionExDllName = "api-ms-win-core-sysinfo-l1-1-0.dll"; /*117*/ + internal const string FormatMessageDllName = "api-ms-win-core-localization-l1-2-0.dll"; /*118*/ + internal const string CreateToolhelp32SnapshotDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*119*/ + internal const string Process32FirstDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*120*/ + internal const string Process32NextDllName = "api-ms-win-core-toolhelp-l1-1-0"; /*121*/ + internal const string GetACPDllName = "api-ms-win-core-localization-l1-2-0.dll"; /*122*/ + internal const string DeleteServiceDllName = "api-ms-win-service-management-l1-1-0.dll"; /*123*/ + internal const string QueryServiceConfigDllName = "api-ms-win-service-management-l2-1-0.dll"; /*124*/ + internal const string QueryServiceConfig2DllName = "api-ms-win-service-management-l2-1-0.dll"; /*125*/ + internal const string SetServiceObjectSecurityDllName = "api-ms-win-service-management-l2-1-0.dll"; /*126*/ } } diff --git a/src/System.Management.Automation/utils/ParameterBinderExceptions.cs b/src/System.Management.Automation/utils/ParameterBinderExceptions.cs index 4a7fa883167..841523f6bdb 100644 --- a/src/System.Management.Automation/utils/ParameterBinderExceptions.cs +++ b/src/System.Management.Automation/utils/ParameterBinderExceptions.cs @@ -4,7 +4,6 @@ using System.Management.Automation.Internal; using System.Management.Automation.Language; using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -385,7 +384,7 @@ public ParameterBindingException( /// public override string Message { - get { return _message ?? (_message = BuildMessage()); } + get { return _message ??= BuildMessage(); } } private string _message; @@ -402,7 +401,7 @@ public string ParameterName } } - private string _parameterName = string.Empty; + private readonly string _parameterName = string.Empty; /// /// Gets the type the parameter is expecting. @@ -415,7 +414,7 @@ public Type ParameterType } } - private Type _parameterType; + private readonly Type _parameterType; /// /// Gets the Type that was specified as the parameter value. @@ -428,7 +427,7 @@ public Type TypeSpecified } } - private Type _typeSpecified; + private readonly Type _typeSpecified; /// /// Gets the errorId of this ParameterBindingException. @@ -441,7 +440,7 @@ public string ErrorId } } - private string _errorId; + private readonly string _errorId; /// /// Gets the line in the script at which the error occurred. @@ -454,7 +453,7 @@ public Int64 Line } } - private Int64 _line = Int64.MinValue; + private readonly Int64 _line = Int64.MinValue; /// /// Gets the offset on the line in the script at which the error occurred. @@ -467,7 +466,7 @@ public Int64 Offset } } - private Int64 _offset = Int64.MinValue; + private readonly Int64 _offset = Int64.MinValue; /// /// Gets the invocation information about the command. @@ -480,14 +479,14 @@ public InvocationInfo CommandInvocation } } - private InvocationInfo _invocationInfo; + private readonly InvocationInfo _invocationInfo; #endregion Properties #region private - private string _resourceString; - private object[] _args = Array.Empty(); - private string _commandName; + private readonly string _resourceString; + private readonly object[] _args = Array.Empty(); + private readonly string _commandName; private string BuildMessage() { @@ -1061,4 +1060,3 @@ protected ParameterBindingParameterDefaultValueException( #endregion serialization } } - diff --git a/src/System.Management.Automation/utils/ParserException.cs b/src/System.Management.Automation/utils/ParserException.cs index 22010873d9f..5e36704ff8f 100644 --- a/src/System.Management.Automation/utils/ParserException.cs +++ b/src/System.Management.Automation/utils/ParserException.cs @@ -16,7 +16,7 @@ public class ParseException : RuntimeException { private const string errorIdString = "Parse"; - private ParseError[] _errors; + private readonly ParseError[] _errors; /// /// The list of parser errors. @@ -161,8 +161,8 @@ public override string Message // Report at most the first 10 errors var errorsToReport = (_errors.Length > 10) - ? _errors.Take(10).Select(e => e.ToString()).Append(ParserStrings.TooManyErrors) - : _errors.Select(e => e.ToString()); + ? _errors.Take(10).Select(static e => e.ToString()).Append(ParserStrings.TooManyErrors) + : _errors.Select(static e => e.ToString()); return string.Join(Environment.NewLine + Environment.NewLine, errorsToReport); } diff --git a/src/System.Management.Automation/utils/PathUtils.cs b/src/System.Management.Automation/utils/PathUtils.cs index ad92bc37fff..0034681e126 100644 --- a/src/System.Management.Automation/utils/PathUtils.cs +++ b/src/System.Management.Automation/utils/PathUtils.cs @@ -4,9 +4,10 @@ using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Management.Automation.Internal; +using System.Runtime.CompilerServices; using System.Text; -using System.Management.Automation.Internal; using Dbg = System.Management.Automation.Diagnostics; namespace System.Management.Automation @@ -23,13 +24,13 @@ internal static class PathUtils /// Cmdlet that is opening the file (used mainly for error reporting). /// Path to the file (as specified on the command line - this method will resolve the path). /// Encoding (this method will convert the command line string to an Encoding instance). - /// If true, then we will use default .NET encoding instead of the encoding specified in parameter. + /// If , then we will use default .NET encoding instead of the encoding specified in parameter. /// /// /// /// Result1: opened for writing. /// Result2: (inherits from ) opened for writing. - /// Result3: file info that should be used to restore file attributes after done with the file (null is this is not needed). + /// Result3: file info that should be used to restore file attributes after done with the file ( is this is not needed). /// True if wildcard expansion should be bypassed. internal static void MasterStreamOpen( PSCmdlet cmdlet, @@ -57,13 +58,13 @@ bool isLiteralPath /// Cmdlet that is opening the file (used mainly for error reporting). /// Path to the file (as specified on the command line - this method will resolve the path). /// Encoding (this method will convert the command line string to an Encoding instance). - /// If true, then we will use default .NET encoding instead of the encoding specified in parameter. + /// If , then we will use default .NET encoding instead of the encoding specified in parameter. /// /// /// /// Result1: opened for writing. /// Result2: (inherits from ) opened for writing. - /// Result3: file info that should be used to restore file attributes after done with the file (null is this is not needed). + /// Result3: file info that should be used to restore file attributes after done with the file ( is this is not needed). /// True if wildcard expansion should be bypassed. internal static void MasterStreamOpen( PSCmdlet cmdlet, @@ -443,9 +444,118 @@ internal static bool TryDeleteFile(string filepath) { // file is in use on Windows } + catch (UnauthorizedAccessException) + { + // user does not have permissions + } } return false; } + + #region Helpers for long paths from .Net Runtime + + // Code here is copied from .NET's internal path helper implementation: + // https://github.com/dotnet/runtime/blob/dcce0f56e10f5ac9539354b049341a2d7c0cdebf/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs + // It has been left as a verbatim copy. + + internal static string EnsureExtendedPrefix(string path) + { + if (IsPartiallyQualified(path) || IsDevice(path)) + return path; + + // Given \\server\share in longpath becomes \\?\UNC\server\share + if (path.StartsWith(UncPathPrefix, StringComparison.OrdinalIgnoreCase)) + return path.Insert(2, UncDevicePrefixToInsert); + + return ExtendedDevicePathPrefix + path; + } + + private const string ExtendedDevicePathPrefix = @"\\?\"; + private const string UncPathPrefix = @"\\"; + private const string UncDevicePrefixToInsert = @"?\UNC\"; + private const string UncExtendedPathPrefix = @"\\?\UNC\"; + private const string DevicePathPrefix = @"\\.\"; + + // \\?\, \\.\, \??\ + private const int DevicePrefixLength = 4; + + /// + /// Returns true if the given character is a valid drive letter + /// + private static bool IsValidDriveChar(char value) + { + return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z')); + } + + private static bool IsDevice(string path) + { + return IsExtended(path) + || + ( + path.Length >= DevicePrefixLength + && IsDirectorySeparator(path[0]) + && IsDirectorySeparator(path[1]) + && (path[2] == '.' || path[2] == '?') + && IsDirectorySeparator(path[3]) + ); + } + + private static bool IsExtended(string path) + { + return path.Length >= DevicePrefixLength + && path[0] == '\\' + && (path[1] == '\\' || path[1] == '?') + && path[2] == '?' + && path[3] == '\\'; + } + + /// + /// Returns true if the path specified is relative to the current drive or working directory. + /// Returns false if the path is fixed to a specific drive or UNC path. This method does no + /// validation of the path (URIs will be returned as relative as a result). + /// + /// + /// Handles paths that use the alternate directory separator. It is a frequent mistake to + /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case. + /// "C:a" is drive relative- meaning that it will be resolved against the current directory + /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory + /// will not be used to modify the path). + /// + private static bool IsPartiallyQualified(string path) + { + if (path.Length < 2) + { + // It isn't fixed, it must be relative. There is no way to specify a fixed + // path with one character (or less). + return true; + } + + if (IsDirectorySeparator(path[0])) + { + // There is no valid way to specify a relative path with two initial slashes or + // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\ + return !(path[1] == '?' || IsDirectorySeparator(path[1])); + } + + // The only way to specify a fixed path that doesn't begin with two slashes + // is the drive, colon, slash format- i.e. C:\ + return !((path.Length >= 3) + && (path[1] == Path.VolumeSeparatorChar) + && IsDirectorySeparator(path[2]) + // To match old behavior we'll check the drive character for validity as the path is technically + // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream. + && IsValidDriveChar(path[0])); + } + /// + /// True if the given character is a directory separator. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsDirectorySeparator(char c) + { + return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar; + } + + #endregion } } diff --git a/src/System.Management.Automation/utils/PlatformInvokes.cs b/src/System.Management.Automation/utils/PlatformInvokes.cs index 516d7059470..2901f7d9b6e 100644 --- a/src/System.Management.Automation/utils/PlatformInvokes.cs +++ b/src/System.Management.Automation/utils/PlatformInvokes.cs @@ -2,15 +2,13 @@ // Licensed under the MIT License. using System.Diagnostics.CodeAnalysis; -using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -using System.Security.Permissions; using Microsoft.Win32.SafeHandles; namespace System.Management.Automation { - internal class PlatformInvokes + internal static class PlatformInvokes { [StructLayout(LayoutKind.Sequential)] internal class FILETIME @@ -34,7 +32,7 @@ public long ToTicks() { return ((long)dwHighDateTime << 32) + dwLowDateTime; } - }; + } [Flags] // dwDesiredAccess of CreateFile @@ -690,24 +688,6 @@ public static extern System.IntPtr CreateFileW( UInt32 dwFlagsAndAttributes, System.IntPtr hTemplateFile); -#endif - - #endregion - - #region GetStdHandle - -#if !UNIX - - internal enum StandardHandleId : uint - { - Error = unchecked((uint)-12), - Output = unchecked((uint)-11), - Input = unchecked((uint)-10), - } - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern IntPtr GetStdHandle(uint handleId); - #endif #endregion diff --git a/src/System.Management.Automation/utils/PowerShellETWTracer.cs b/src/System.Management.Automation/utils/PowerShellETWTracer.cs index 7631d760b2d..c22e738a35f 100644 --- a/src/System.Management.Automation/utils/PowerShellETWTracer.cs +++ b/src/System.Management.Automation/utils/PowerShellETWTracer.cs @@ -866,7 +866,7 @@ private bool Trace(PowerShellTraceEvent traceEvent, PowerShellTraceLevel level, } } - return _provider.WriteEvent(ref ed, args); + return _provider.WriteEvent(in ed, args); } /// @@ -988,7 +988,7 @@ public void Dispose() /// public PowerShellTraceTask Task { get; set; } = PowerShellTraceTask.None; - private bool IsEtwSupported + private static bool IsEtwSupported { get { @@ -1189,7 +1189,7 @@ public void WriteMessage(string className, string methodName, Guid workflowId, J PSKeyword.UseAlwaysAnalytic, className, methodName, workflowId.ToString(), parameters == null ? message : StringUtil.Format(message, parameters), - sb.ToString(),// Job + sb.ToString(), // Job string.Empty, // Activity name string.Empty, // Activity GUID string.Empty); diff --git a/src/System.Management.Automation/utils/PowerShellExecutionHelper.cs b/src/System.Management.Automation/utils/PowerShellExecutionHelper.cs index d6d845c7281..dcfc2682bcd 100644 --- a/src/System.Management.Automation/utils/PowerShellExecutionHelper.cs +++ b/src/System.Management.Automation/utils/PowerShellExecutionHelper.cs @@ -189,7 +189,7 @@ internal static string SafeToString(object obj) if (pso != null) { object baseObject = pso.BaseObject; - if (baseObject != null && !(baseObject is PSCustomObject)) + if (baseObject != null && baseObject is not PSCustomObject) result = baseObject.ToString(); else result = pso.ToString(); diff --git a/src/System.Management.Automation/utils/PsUtils.cs b/src/System.Management.Automation/utils/PsUtils.cs index 5866e3d52f9..574f42eace3 100644 --- a/src/System.Management.Automation/utils/PsUtils.cs +++ b/src/System.Management.Automation/utils/PsUtils.cs @@ -20,65 +20,9 @@ namespace System.Management.Automation /// internal static class PsUtils { - /// - /// Safely retrieves the MainModule property of a - /// process. Version 2.0 and below of the .NET Framework are - /// impacted by a Win32 API usability knot that throws an - /// exception if API tries to enumerate the process' modules - /// while it is still loading them. This generates the error - /// message: Only part of a ReadProcessMemory or - /// WriteProcessMemory request was completed. - /// The BCL fix in V3 was to just try more, so we do the same - /// thing. - /// - /// Note: If you attempt to retrieve the MainModule of a 64-bit - /// process from a WOW64 (32-bit) process, the Win32 API has a fatal - /// flaw that causes this to return the same error. - /// - /// If you need the MainModule of a 64-bit process from a WOW64 - /// process, you will need to write the P/Invoke yourself. - /// - /// The process from which to - /// retrieve the MainModule - /// - /// You are trying to access the MainModule property for a process that is running - /// on a remote computer. This property is available only for processes that are - /// running on the local computer. - /// - /// - /// The process Id is not available (or) The process has exited. - /// - /// - /// - internal static ProcessModule GetMainModule(Process targetProcess) - { - int caughtCount = 0; - - while (true) - { - try - { - return targetProcess.MainModule; - } - catch (System.ComponentModel.Win32Exception e) - { - // If this is an Access Denied error (which can happen with thread impersonation) - // then re-throw immediately. - if (e.NativeErrorCode == 5) - throw; - - // Otherwise retry to ensure module is loaded. - caughtCount++; - System.Threading.Thread.Sleep(100); - if (caughtCount == 5) - throw; - } - } - } - // Cache of the current process' parentId private static int? s_currentParentProcessId; - private static readonly int s_currentProcessId = Process.GetCurrentProcess().Id; + private static readonly int s_currentProcessId = Environment.ProcessId; /// /// Retrieve the parent process of a process. @@ -386,8 +330,7 @@ internal static Hashtable EvaluatePowerShellDataFile( ex.Message); } - var retResult = evaluationResult as Hashtable; - if (retResult == null) + if (!(evaluationResult is Hashtable retResult)) { throw PSTraceSource.NewInvalidOperationException( ParserStrings.InvalidPowerShellDataFile, @@ -532,23 +475,21 @@ internal static object[] Base64ToArgsConverter(string base64) object dso; Deserializer deserializer = new Deserializer(reader); dso = deserializer.Deserialize(); - if (deserializer.Done() == false) + if (!deserializer.Done()) { // This helper function should move to host and it should provide appropriate // error message there. throw PSTraceSource.NewArgumentException(MinishellParameterBinderController.ArgsParameter); } - PSObject mo = dso as PSObject; - if (mo == null) + if (!(dso is PSObject mo)) { // This helper function should move the host. Provide appropriate error message. // Format of args parameter is not correct. throw PSTraceSource.NewArgumentException(MinishellParameterBinderController.ArgsParameter); } - var argsList = mo.BaseObject as ArrayList; - if (argsList == null) + if (!(mo.BaseObject is ArrayList argsList)) { // This helper function should move the host. Provide appropriate error message. // Format of args parameter is not correct. @@ -563,12 +504,12 @@ internal static object[] Base64ToArgsConverter(string base64) /// A simple implementation of CRC32. /// See "CRC-32 algorithm" in https://en.wikipedia.org/wiki/Cyclic_redundancy_check. /// - internal class CRC32Hash + internal static class CRC32Hash { // CRC-32C polynomial representations private const uint polynomial = 0x1EDC6F41; - private static uint[] table; + private static readonly uint[] table; static CRC32Hash() { @@ -648,4 +589,3 @@ int IEqualityComparer.GetHashCode(object obj) #endregion } - diff --git a/src/System.Management.Automation/utils/ResourceManagerCache.cs b/src/System.Management.Automation/utils/ResourceManagerCache.cs index 302fd0c48cf..f5e029ede25 100644 --- a/src/System.Management.Automation/utils/ResourceManagerCache.cs +++ b/src/System.Management.Automation/utils/ResourceManagerCache.cs @@ -16,13 +16,13 @@ internal static class ResourceManagerCache /// to the default resource assembly. The value is another dictionary that is keyed based on the base /// name for the resource that is being retrieved. The value for this dictionary is the ResourceManager. /// - private static Dictionary> s_resourceManagerCache = + private static readonly Dictionary> s_resourceManagerCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); /// /// Used to synchronize access to the ResourceManagerCache. /// - private static object s_syncRoot = new object(); + private static readonly object s_syncRoot = new object(); /// /// Gets the ResourceManager from the cache or gets an instance of the ResourceManager @@ -242,4 +242,3 @@ private static ResourceManager InitRMWithAssembly(string baseName, Assembly asse } } } - diff --git a/src/System.Management.Automation/utils/RuntimeException.cs b/src/System.Management.Automation/utils/RuntimeException.cs index 3a2cbd5c05f..4ba776799e7 100644 --- a/src/System.Management.Automation/utils/RuntimeException.cs +++ b/src/System.Management.Automation/utils/RuntimeException.cs @@ -3,7 +3,6 @@ using System.Management.Automation.Language; using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -225,7 +224,7 @@ internal static string RetrieveMessage(ErrorRecord errorRecord) { if (errorRecord == null) return string.Empty; - if (null != errorRecord.ErrorDetails && + if (errorRecord.ErrorDetails != null && !string.IsNullOrEmpty(errorRecord.ErrorDetails.Message)) { return errorRecord.ErrorDetails.Message; @@ -241,8 +240,7 @@ internal static string RetrieveMessage(Exception e) if (e == null) return string.Empty; - IContainsErrorRecord icer = e as IContainsErrorRecord; - if (icer == null) + if (!(e is IContainsErrorRecord icer)) return e.Message; ErrorRecord er = icer.ErrorRecord; if (er == null) @@ -265,7 +263,10 @@ internal static Exception RetrieveException(ErrorRecord errorRecord) /// public bool WasThrownFromThrowStatement { - get { return _thrownByThrowStatement; } + get + { + return _thrownByThrowStatement; + } set { diff --git a/src/System.Management.Automation/utils/SessionStateExceptions.cs b/src/System.Management.Automation/utils/SessionStateExceptions.cs index e5394a5130b..a08e7615dc5 100644 --- a/src/System.Management.Automation/utils/SessionStateExceptions.cs +++ b/src/System.Management.Automation/utils/SessionStateExceptions.cs @@ -4,7 +4,6 @@ using System.Collections.ObjectModel; using System.Management.Automation.Internal; using System.Runtime.Serialization; -using System.Security.Permissions; namespace System.Management.Automation { @@ -323,7 +322,7 @@ public override string Message } [NonSerialized] - private string _message /* = null */; + private readonly string _message /* = null */; #endregion Private/Internal } @@ -521,7 +520,7 @@ public string ItemName get { return _itemName; } } - private string _itemName = string.Empty; + private readonly string _itemName = string.Empty; /// /// Gets the category of session state object the error occurred on. @@ -531,12 +530,12 @@ public SessionStateCategory SessionStateCategory get { return _sessionStateCategory; } } - private SessionStateCategory _sessionStateCategory = SessionStateCategory.Variable; + private readonly SessionStateCategory _sessionStateCategory = SessionStateCategory.Variable; #endregion Properties #region Private - private string _errorId = "SessionStateException"; - private ErrorCategory _errorCategory = ErrorCategory.InvalidArgument; + private readonly string _errorId = "SessionStateException"; + private readonly ErrorCategory _errorCategory = ErrorCategory.InvalidArgument; private static string BuildMessage( string itemName, @@ -544,7 +543,7 @@ private static string BuildMessage( params object[] messageArgs) { object[] a; - if (messageArgs != null && 0 < messageArgs.Length) + if (messageArgs != null && messageArgs.Length > 0) { a = new object[messageArgs.Length + 1]; a[0] = itemName; @@ -854,7 +853,7 @@ public ReadOnlyCollection PossibleMatches } } - private ReadOnlyCollection _possibleMatches; + private readonly ReadOnlyCollection _possibleMatches; #endregion public properties } @@ -1025,4 +1024,3 @@ protected ItemNotFoundException( #endregion Serialization } } - diff --git a/src/System.Management.Automation/utils/StructuredTraceSource.cs b/src/System.Management.Automation/utils/StructuredTraceSource.cs index 88b4cc1a436..287ad5bdd6d 100644 --- a/src/System.Management.Automation/utils/StructuredTraceSource.cs +++ b/src/System.Management.Automation/utils/StructuredTraceSource.cs @@ -542,16 +542,14 @@ internal IDisposable TraceMethod( string methodName = GetCallingMethodNameAndParameters(1); // Create the method tracer object - return - (IDisposable) - new ScopeTracer( - this, - PSTraceSourceOptions.Method, - methodOutputFormatter, - methodLeavingFormatter, - methodName, - format, - args); + return (IDisposable)new ScopeTracer( + this, + PSTraceSourceOptions.Method, + methodOutputFormatter, + methodLeavingFormatter, + methodName, + format, + args); } catch { @@ -591,15 +589,13 @@ internal IDisposable TraceEventHandlers() string methodName = GetCallingMethodNameAndParameters(1); // Create the scope tracer object - return - (IDisposable) - new ScopeTracer( - this, - PSTraceSourceOptions.Events, - eventHandlerOutputFormatter, - eventHandlerLeavingFormatter, - methodName, - string.Empty); + return (IDisposable)new ScopeTracer( + this, + PSTraceSourceOptions.Events, + eventHandlerOutputFormatter, + eventHandlerLeavingFormatter, + methodName, + string.Empty); } catch { @@ -643,16 +639,14 @@ internal IDisposable TraceEventHandlers( string methodName = GetCallingMethodNameAndParameters(1); // Create the scope tracer object - return - (IDisposable) - new ScopeTracer( - this, - PSTraceSourceOptions.Events, - eventHandlerOutputFormatter, - eventHandlerLeavingFormatter, - methodName, - format, - args); + return (IDisposable)new ScopeTracer( + this, + PSTraceSourceOptions.Events, + eventHandlerOutputFormatter, + eventHandlerLeavingFormatter, + methodName, + format, + args); } catch { @@ -707,14 +701,12 @@ internal IDisposable TraceLock(string lockName) { try { - return - (IDisposable) - new ScopeTracer( - this, - PSTraceSourceOptions.Lock, - lockEnterFormatter, - lockLeavingFormatter, - lockName); + return (IDisposable)new ScopeTracer( + this, + PSTraceSourceOptions.Lock, + lockEnterFormatter, + lockLeavingFormatter, + lockName); } catch { @@ -1189,7 +1181,7 @@ private static string GetCallingMethodNameAndParameters(int skipFrames) declaringType.Name, callingMethod.Name); - methodAndParameters.Append(")"); + methodAndParameters.Append(')'); } catch { @@ -1436,14 +1428,14 @@ internal static int ThreadIndentLevel /// internal string FullName { get; } = string.Empty; - private string _name; + private readonly string _name; /// /// Creates an instance of the TraceSource on demand. /// internal TraceSource TraceSource { - get { return _traceSource ?? (_traceSource = new MonadTraceSource(_name)); } + get { return _traceSource ??= new MonadTraceSource(_name); } } private TraceSource _traceSource; @@ -1457,7 +1449,10 @@ internal TraceSource TraceSource /// public PSTraceSourceOptions Options { - get { return _flags; } + get + { + return _flags; + } set { @@ -1765,7 +1760,7 @@ public void Dispose() /// /// The trace object that is used for any output. /// - private PSTraceSource _tracer; + private readonly PSTraceSource _tracer; /// /// The flag which caused this scope object to be created. @@ -1869,4 +1864,3 @@ protected override string[] GetSupportedAttributes() } #endregion MonadTraceSource } - diff --git a/src/System.Management.Automation/utils/Telemetry.cs b/src/System.Management.Automation/utils/Telemetry.cs index feb731c2141..105feef73e1 100644 --- a/src/System.Management.Automation/utils/Telemetry.cs +++ b/src/System.Management.Automation/utils/Telemetry.cs @@ -10,6 +10,7 @@ using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.Extensibility.Implementation; namespace Microsoft.PowerShell.Telemetry { @@ -93,7 +94,7 @@ public static class ApplicationInsightsTelemetry /// Use a hashset for quick lookups. /// We send telemetry only a known set of modules. /// If it's not in the list (initialized in the static constructor), then we report anonymous. - private static HashSet s_knownModules; + private static readonly HashSet s_knownModules; /// Gets a value indicating whether telemetry can be sent. public static bool CanSendTelemetry { get; private set; } @@ -118,6 +119,9 @@ static ApplicationInsightsTelemetry() configuration.TelemetryChannel.DeveloperMode = false; s_telemetryClient = new TelemetryClient(configuration); + // Be sure to obscure any information about the client node. + s_telemetryClient.Context.Cloud.RoleInstance = string.Empty; + s_telemetryClient.Context.GetInternalContext().NodeName = string.Empty; s_sessionId = Guid.NewGuid().ToString(); // use a hashset when looking for module names, it should be quicker than a string comparison @@ -383,13 +387,18 @@ static ApplicationInsightsTelemetry() "Microsoft.PowerApps.Checker.PowerShell", "Microsoft.PowerShell.Archive", "Microsoft.PowerShell.Core", + "Microsoft.PowerShell.Crescendo", "Microsoft.PowerShell.Diagnostics", "Microsoft.PowerShell.Host", "Microsoft.PowerShell.LocalAccounts", "Microsoft.PowerShell.Management", "Microsoft.PowerShell.ODataUtils", "Microsoft.PowerShell.Operation.Validation", + "Microsoft.PowerShell.RemotingTools", + "Microsoft.PowerShell.SecretManagement", + "Microsoft.PowerShell.SecretStore", "Microsoft.PowerShell.Security", + "Microsoft.PowerShell.TextUtility", "Microsoft.PowerShell.Utility", "Microsoft.SharePoint.Powershell", "Microsoft.SystemCenter.ServiceManagementAutomation", @@ -559,19 +568,56 @@ private static bool GetEnvironmentVariableAsBool(string name, bool defaultValue) return defaultValue; } - switch (str.ToLowerInvariant()) + var boolStr = str.AsSpan(); + + if (boolStr.Length == 1) { - case "true": - case "1": - case "yes": + if (boolStr[0] == '1') + { return true; - case "false": - case "0": - case "no": + } + + if (boolStr[0] == '0') + { return false; - default: - return defaultValue; + } + } + + if (boolStr.Length == 3 && + (boolStr[0] == 'y' || boolStr[0] == 'Y') && + (boolStr[1] == 'e' || boolStr[1] == 'E') && + (boolStr[2] == 's' || boolStr[2] == 'S')) + { + return true; + } + + if (boolStr.Length == 2 && + (boolStr[0] == 'n' || boolStr[0] == 'N') && + (boolStr[1] == 'o' || boolStr[1] == 'O')) + { + return false; } + + if (boolStr.Length == 4 && + (boolStr[0] == 't' || boolStr[0] == 'T') && + (boolStr[1] == 'r' || boolStr[1] == 'R') && + (boolStr[2] == 'u' || boolStr[2] == 'U') && + (boolStr[3] == 'e' || boolStr[3] == 'E')) + { + return true; + } + + if (boolStr.Length == 5 && + (boolStr[0] == 'f' || boolStr[0] == 'F') && + (boolStr[1] == 'a' || boolStr[1] == 'A') && + (boolStr[2] == 'l' || boolStr[2] == 'L') && + (boolStr[3] == 's' || boolStr[3] == 'S') && + (boolStr[4] == 'e' || boolStr[4] == 'E')) + { + return false; + } + + return defaultValue; } /// @@ -794,29 +840,30 @@ private static Guid GetUniqueIdentifier() // Multiple processes may start simultaneously so we need a system wide // way to control access to the file in the case (although remote) when we have - // simulataneous shell starts without the persisted file which attempt to create the file. - using (var m = new Mutex(true, "CreateUniqueUserId")) + // simultaneous shell starts without the persisted file which attempt to create the file. + try { // TryCreateUniqueIdentifierAndFile shouldn't throw, but the mutex might + using var m = new Mutex(true, "CreateUniqueUserId"); + m.WaitOne(); try { - m.WaitOne(); if (TryCreateUniqueIdentifierAndFile(uuidPath, out id)) { return id; } } - catch (Exception) - { - // Any problem in generating a uuid will result in no telemetry being sent. - // Try to send the failure in telemetry, but it will have no unique id. - s_telemetryClient.GetMetric(_telemetryFailure, "Detail").TrackValue(1, "mutex"); - } finally { m.ReleaseMutex(); } } + catch (Exception) + { + // Any problem in generating a uuid will result in no telemetry being sent. + // Try to send the failure in telemetry, but it will have no unique id. + s_telemetryClient.GetMetric(_telemetryFailure, "Detail").TrackValue(1, "mutex"); + } // something bad happened, turn off telemetry since the unique id wasn't set. CanSendTelemetry = false; diff --git a/src/System.Management.Automation/utils/Verbs.cs b/src/System.Management.Automation/utils/Verbs.cs index 0e220935a91..c6019047fb9 100644 --- a/src/System.Management.Automation/utils/Verbs.cs +++ b/src/System.Management.Automation/utils/Verbs.cs @@ -1311,8 +1311,8 @@ static Verbs() #endif } - private static Dictionary s_validVerbs = new Dictionary(StringComparer.OrdinalIgnoreCase); - private static Dictionary s_recommendedAlternateVerbs = new Dictionary(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary s_validVerbs = new Dictionary(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary s_recommendedAlternateVerbs = new Dictionary(StringComparer.OrdinalIgnoreCase); internal static bool IsStandard(string verb) { diff --git a/src/System.Management.Automation/utils/assert.cs b/src/System.Management.Automation/utils/assert.cs index 921ed42c0f3..cee958a5337 100644 --- a/src/System.Management.Automation/utils/assert.cs +++ b/src/System.Management.Automation/utils/assert.cs @@ -72,7 +72,7 @@ internal static string StackTrace(int framesToSkip) return frameString.ToString(); } - private static object s_throwInsteadOfAssertLock = 1; + private static readonly object s_throwInsteadOfAssertLock = 1; private static bool s_throwInsteadOfAssert = false; /// @@ -204,4 +204,3 @@ internal static void } } } - diff --git a/src/System.Management.Automation/utils/perfCounters/CounterSetInstanceBase.cs b/src/System.Management.Automation/utils/perfCounters/CounterSetInstanceBase.cs index 89b2a69e7b4..fc3f048b828 100644 --- a/src/System.Management.Automation/utils/perfCounters/CounterSetInstanceBase.cs +++ b/src/System.Management.Automation/utils/perfCounters/CounterSetInstanceBase.cs @@ -400,7 +400,7 @@ public override bool UpdateCounterByValue(string counterName, long stepAmount, b // retrieve counter id associated with the counter name if (counterName == null) { - ArgumentNullException argNullException = new ArgumentNullException("counterName"); + ArgumentNullException argNullException = new ArgumentNullException(nameof(counterName)); _tracer.TraceException(argNullException); return false; } @@ -484,7 +484,7 @@ public override bool SetCounterValue(string counterName, long counterValue, bool // retrieve counter id associated with the counter name if (counterName == null) { - ArgumentNullException argNullException = new ArgumentNullException("counterName"); + ArgumentNullException argNullException = new ArgumentNullException(nameof(counterName)); _tracer.TraceException(argNullException); return false; } @@ -568,7 +568,7 @@ public override bool GetCounterValue(string counterName, bool isNumerator, out l // retrieve counter id associated with the counter name if (counterName == null) { - ArgumentNullException argNullException = new ArgumentNullException("counterName"); + ArgumentNullException argNullException = new ArgumentNullException(nameof(counterName)); _tracer.TraceException(argNullException); return false; } diff --git a/src/System.Management.Automation/utils/perfCounters/CounterSetRegistrarBase.cs b/src/System.Management.Automation/utils/perfCounters/CounterSetRegistrarBase.cs index 155a3db99c9..69cea42b5af 100644 --- a/src/System.Management.Automation/utils/perfCounters/CounterSetRegistrarBase.cs +++ b/src/System.Management.Automation/utils/perfCounters/CounterSetRegistrarBase.cs @@ -110,7 +110,7 @@ protected CounterSetRegistrarBase( if ((counterInfoArray == null) || (counterInfoArray.Length == 0)) { - throw new ArgumentNullException("counterInfoArray"); + throw new ArgumentNullException(nameof(counterInfoArray)); } CounterInfoArray = new CounterInfo[counterInfoArray.Length]; @@ -136,7 +136,7 @@ protected CounterSetRegistrarBase( { if (srcCounterSetRegistrarBase == null) { - throw new ArgumentNullException("srcCounterSetRegistrarBase"); + throw new ArgumentNullException(nameof(srcCounterSetRegistrarBase)); } ProviderId = srcCounterSetRegistrarBase.ProviderId; @@ -243,7 +243,7 @@ public PSCounterSetRegistrar( { if (srcPSCounterSetRegistrar == null) { - throw new ArgumentNullException("srcPSCounterSetRegistrar"); + throw new ArgumentNullException(nameof(srcPSCounterSetRegistrar)); } } diff --git a/src/System.Management.Automation/utils/tracing/EtwActivity.cs b/src/System.Management.Automation/utils/tracing/EtwActivity.cs index a29e7284717..b8b4ac330f9 100644 --- a/src/System.Management.Automation/utils/tracing/EtwActivity.cs +++ b/src/System.Management.Automation/utils/tracing/EtwActivity.cs @@ -94,16 +94,16 @@ public abstract class EtwActivity /// This is a helper class that is used to wrap many multi-threading scenarios /// and makes correlation event to be logged easily. /// - private class CorrelatedCallback + private sealed class CorrelatedCallback { - private CallbackNoParameter callbackNoParam; - private CallbackWithState callbackWithState; - private AsyncCallback asyncCallback; + private readonly CallbackNoParameter callbackNoParam; + private readonly CallbackWithState callbackWithState; + private readonly AsyncCallback asyncCallback; /// /// ParentActivityId. /// - protected readonly Guid parentActivityId; + private readonly Guid parentActivityId; private readonly EtwActivity tracer; /// @@ -175,7 +175,7 @@ public CorrelatedCallback(EtwActivity tracer, AsyncCallback callback) /// /// It is to be used in System.Timers.Timer scenarios. /// - private CallbackWithStateAndArgs callbackWithStateAndArgs; + private readonly CallbackWithStateAndArgs callbackWithStateAndArgs; /// /// EtwCorrelator Constructor. @@ -252,10 +252,10 @@ public void Callback(IAsyncResult asyncResult) } } - private static Dictionary providers = new Dictionary(); - private static object syncLock = new object(); + private static readonly Dictionary providers = new Dictionary(); + private static readonly object syncLock = new object(); - private static EventDescriptor _WriteTransferEvent = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000); + private static readonly EventDescriptor _WriteTransferEvent = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000); private EventProvider currentProvider; @@ -328,7 +328,7 @@ public void CorrelateWithActivity(Guid parentActivityId) if (parentActivityId != Guid.Empty) { EventDescriptor transferEvent = TransferEvent; - provider.WriteTransferEvent(ref transferEvent, parentActivityId, activityId, parentActivityId); + provider.WriteTransferEvent(in transferEvent, parentActivityId, activityId, parentActivityId); } } @@ -473,7 +473,7 @@ protected void WriteEvent(EventDescriptor ed, params object[] payload) } } - bool success = provider.WriteEvent(ref ed, payload); + bool success = provider.WriteEvent(in ed, payload); if (EventWritten != null) { EventWritten.Invoke(this, new EtwEventArgs(ed, success, payload)); diff --git a/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs b/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs index a7a257ceb21..7885006146c 100644 --- a/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs +++ b/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable #if !UNIX namespace System.Management.Automation.Tracing @@ -20,7 +21,7 @@ public interface IEtwActivityReverter : /// Reverts the ETW activity ID of the current thread to its original value. /// /// - /// Calling has the same effect as + /// Calling has the same effect as /// calling this method and is useful in the C# "using" syntax. /// void RevertCurrentActivityId(); diff --git a/src/System.Management.Automation/utils/tracing/EtwEventCorrelator.cs b/src/System.Management.Automation/utils/tracing/EtwEventCorrelator.cs index 4895a582223..a421b918eb8 100644 --- a/src/System.Management.Automation/utils/tracing/EtwEventCorrelator.cs +++ b/src/System.Management.Automation/utils/tracing/EtwEventCorrelator.cs @@ -12,6 +12,7 @@ namespace System.Management.Automation.Tracing /// An object that can be used to manage the ETW activity ID of the current thread. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Etw")] +#nullable enable public interface IEtwEventCorrelator { /// @@ -19,8 +20,8 @@ public interface IEtwEventCorrelator /// /// /// This method should only be used for advanced scenarios - /// or diagnostics. Prefer using - /// or instead. + /// or diagnostics. Prefer using + /// or instead. /// Guid CurrentActivityId { get; set; } @@ -29,7 +30,7 @@ public interface IEtwEventCorrelator /// the new activity with another activity. /// /// The ID of an existing activity to be correlated with the - /// new activity or if correlation is not desired. + /// new activity or if correlation is not desired. /// An object which can be used to revert the activity ID of the current thread once /// the new activity yields control of the current thread. IEtwActivityReverter StartActivity(Guid relatedActivityId); @@ -42,9 +43,10 @@ public interface IEtwEventCorrelator /// the new activity yields control of the current thread. IEtwActivityReverter StartActivity(); } +#nullable restore /// - /// A simple implementation of . + /// A simple implementation of . /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Etw")] public class EtwEventCorrelator : @@ -54,11 +56,11 @@ public class EtwEventCorrelator : private readonly EventDescriptor _transferEvent; /// - /// Creates an . + /// Creates an . /// - /// The to use when logging transfer events + /// The to use when logging transfer events /// during activity correlation. - /// The to use when logging transfer events + /// The to use when logging transfer events /// during activity correlation. public EtwEventCorrelator(EventProvider transferProvider, EventDescriptor transferEvent) { @@ -72,7 +74,7 @@ public EtwEventCorrelator(EventProvider transferProvider, EventDescriptor transf } /// - /// Implements . + /// Implements . /// public Guid CurrentActivityId { @@ -88,7 +90,7 @@ public Guid CurrentActivityId } /// - /// Implements . + /// Implements . /// public IEtwActivityReverter StartActivity(Guid relatedActivityId) { @@ -98,14 +100,14 @@ public IEtwActivityReverter StartActivity(Guid relatedActivityId) if (relatedActivityId != Guid.Empty) { var tempTransferEvent = _transferEvent; - _transferProvider.WriteTransferEvent(ref tempTransferEvent, relatedActivityId); + _transferProvider.WriteTransferEvent(in tempTransferEvent, relatedActivityId); } return retActivity; } /// - /// Implements . + /// Implements . /// public IEtwActivityReverter StartActivity() { diff --git a/src/System.Management.Automation/utils/tracing/IMethodInvoker.cs b/src/System.Management.Automation/utils/tracing/IMethodInvoker.cs index daf52e80409..7382380bfbd 100644 --- a/src/System.Management.Automation/utils/tracing/IMethodInvoker.cs +++ b/src/System.Management.Automation/utils/tracing/IMethodInvoker.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + #if !UNIX namespace System.Management.Automation.Tracing @@ -11,7 +13,7 @@ internal interface IMethodInvoker { Delegate Invoker { get; } - object[] CreateInvokerArgs(Delegate methodToInvoke, object[] methodToInvokeArgs); + object[] CreateInvokerArgs(Delegate methodToInvoke, object?[]? methodToInvokeArgs); } } diff --git a/src/System.Management.Automation/utils/tracing/PSEtwLog.cs b/src/System.Management.Automation/utils/tracing/PSEtwLog.cs index ec772fe549c..ca8471749eb 100644 --- a/src/System.Management.Automation/utils/tracing/PSEtwLog.cs +++ b/src/System.Management.Automation/utils/tracing/PSEtwLog.cs @@ -13,9 +13,9 @@ namespace System.Management.Automation.Tracing internal static class PSEtwLog { #if UNIX - private static PSSysLogProvider provider; + private static readonly PSSysLogProvider provider; #else - private static PSEtwLogProvider provider; + private static readonly PSEtwLogProvider provider; #endif /// diff --git a/src/System.Management.Automation/utils/tracing/PSEtwLogProvider.cs b/src/System.Management.Automation/utils/tracing/PSEtwLogProvider.cs index b9581755dd5..a13dac02e15 100755 --- a/src/System.Management.Automation/utils/tracing/PSEtwLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/PSEtwLogProvider.cs @@ -15,9 +15,9 @@ namespace System.Management.Automation.Tracing /// internal class PSEtwLogProvider : LogProvider { - private static EventProvider etwProvider; + private static readonly EventProvider etwProvider; internal static readonly Guid ProviderGuid = new Guid("F90714A8-5509-434A-BF6D-B1624C8A19A2"); - private static EventDescriptor _xferEventDescriptor = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000); + private static readonly EventDescriptor _xferEventDescriptor = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000); /// /// Class constructor. @@ -284,7 +284,7 @@ internal void WriteEvent(PSEventId id, PSChannel channel, PSOpcode opcode, PSLev EventDescriptor desc = new EventDescriptor((int)id, (byte)PSEventVersion.One, (byte)channel, (byte)level, (byte)opcode, (int)task, longKeyword); - etwProvider.WriteEvent(ref desc, args); + etwProvider.WriteEvent(in desc, args); } /// @@ -292,7 +292,7 @@ internal void WriteEvent(PSEventId id, PSChannel channel, PSOpcode opcode, PSLev /// internal void WriteTransferEvent(Guid parentActivityId) { - etwProvider.WriteTransferEvent(ref _xferEventDescriptor, parentActivityId, EtwActivity.GetActivityId(), parentActivityId); + etwProvider.WriteTransferEvent(in _xferEventDescriptor, parentActivityId, EtwActivity.GetActivityId(), parentActivityId); } /// diff --git a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs index e8b6d88c732..011d7577239 100755 --- a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs @@ -16,10 +16,10 @@ namespace System.Management.Automation.Tracing /// internal class PSSysLogProvider : LogProvider { - private static SysLogProvider s_provider; + private static readonly SysLogProvider s_provider; // by default, do not include channel bits - internal const PSKeyword DefaultKeywords = (PSKeyword) (0x00FFFFFFFFFFFFFF); + internal const PSKeyword DefaultKeywords = (PSKeyword)(0x00FFFFFFFFFFFFFF); // the default enabled channel(s) internal const PSChannel DefaultChannels = PSChannel.Operational; diff --git a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs index 699f5628d03..27d0e133fd5 100755 --- a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs @@ -80,12 +80,12 @@ namespace System.Management.Automation.Tracing internal class SysLogProvider { // Ensure the string pointer is not garbage collected. - static IntPtr _nativeSyslogIdent = IntPtr.Zero; - static NativeMethods.SysLogPriority _facility = NativeMethods.SysLogPriority.Local0; + private static IntPtr _nativeSyslogIdent = IntPtr.Zero; + private static readonly NativeMethods.SysLogPriority _facility = NativeMethods.SysLogPriority.Local0; - byte _channelFilter; - ulong _keywordFilter; - byte _levelFilter; + private readonly byte _channelFilter; + private readonly ulong _keywordFilter; + private readonly byte _levelFilter; /// /// Initializes a new instance of this class. @@ -103,16 +103,16 @@ public SysLogProvider(string applicationId, PSLevel level, PSKeyword keywords, P _nativeSyslogIdent = Marshal.StringToHGlobalAnsi(applicationId); NativeMethods.OpenLog(_nativeSyslogIdent, _facility); _keywordFilter = (ulong)keywords; - _levelFilter = (byte) level; - _channelFilter = (byte) channels; - if ((_channelFilter & (ulong) PSChannel.Operational) != 0) + _levelFilter = (byte)level; + _channelFilter = (byte)channels; + if ((_channelFilter & (ulong)PSChannel.Operational) != 0) { - _keywordFilter |= (ulong) PSKeyword.UseAlwaysOperational; + _keywordFilter |= (ulong)PSKeyword.UseAlwaysOperational; } - if ((_channelFilter & (ulong) PSChannel.Analytic) != 0) + if ((_channelFilter & (ulong)PSChannel.Analytic) != 0) { - _keywordFilter |= (ulong) PSKeyword.UseAlwaysAnalytic; + _keywordFilter |= (ulong)PSKeyword.UseAlwaysAnalytic; } } @@ -148,13 +148,13 @@ private static StringBuilder MessageBuilder /// to ensure correct thread initialization. /// [ThreadStatic] - static Guid? t_activity; + private static Guid? t_activity; private static Guid Activity { get { - if (t_activity.HasValue == false) + if (!t_activity.HasValue) { // NOTE: Thread static fields must be explicitly initialized for each thread. t_activity = Guid.NewGuid(); @@ -177,8 +177,8 @@ private static Guid Activity /// True if the specified level and keywords are enabled for logging. internal bool IsEnabled(PSLevel level, PSKeyword keywords) { - return ( ((ulong) keywords & _keywordFilter) != 0 && - ((int) level <= _levelFilter) ); + return ((ulong)keywords & _keywordFilter) != 0 + && ((int)level <= _levelFilter); } // NOTE: There are a number of places where PowerShell code sends analytic events @@ -188,8 +188,8 @@ internal bool IsEnabled(PSLevel level, PSKeyword keywords) // filtering is performed to suppress analytic events. private bool ShouldLog(PSLevel level, PSKeyword keywords, PSChannel channel) { - return ((_channelFilter & (ulong)channel) != 0 && - IsEnabled(level, keywords)); + return (_channelFilter & (ulong)channel) != 0 + && IsEnabled(level, keywords); } #region resource manager @@ -251,7 +251,7 @@ private static string GetResourceString(string resourceName) private static void GetEventMessage(StringBuilder sb, PSEventId eventId, params object[] args ) { int parameterCount; - string resourceName = EventResource.GetMessage((int) eventId, out parameterCount); + string resourceName = EventResource.GetMessage((int)eventId, out parameterCount); if (resourceName == null) { @@ -276,7 +276,7 @@ private static void GetEventMessage(StringBuilder sb, PSEventId eventId, params #region logging // maps a LogLevel to an associated SysLogPriority. - static NativeMethods.SysLogPriority[] _levels = + private static readonly NativeMethods.SysLogPriority[] _levels = { NativeMethods.SysLogPriority.Info, NativeMethods.SysLogPriority.Critical, @@ -293,7 +293,7 @@ private static void GetEventMessage(StringBuilder sb, PSEventId eventId, params public void LogTransfer(Guid parentActivityId) { // NOTE: always log - int threadId = Thread.CurrentThread.ManagedThreadId; + int threadId = Environment.CurrentManagedThreadId; string message = string.Format(CultureInfo.InvariantCulture, "({0}:{1:X}:{2:X}) [Transfer]:{3} {4}", PSVersionInfo.GitCommitId, threadId, PSChannel.Operational, @@ -309,7 +309,7 @@ public void LogTransfer(Guid parentActivityId) /// The Guid activity identifier. public void SetActivity(Guid activity) { - int threadId = Thread.CurrentThread.ManagedThreadId; + int threadId = Environment.CurrentManagedThreadId; Activity = activity; // NOTE: always log @@ -333,7 +333,7 @@ public void Log(PSEventId eventId, PSChannel channel, PSTask task, PSOpcode opco { if (ShouldLog(level, keyword, channel)) { - int threadId = Thread.CurrentThread.ManagedThreadId; + int threadId = Environment.CurrentManagedThreadId; StringBuilder sb = MessageBuilder; sb.Clear(); @@ -347,7 +347,7 @@ public void Log(PSEventId eventId, PSChannel channel, PSTask task, PSOpcode opco GetEventMessage(sb, eventId, args); NativeMethods.SysLogPriority priority; - if ((int) level <= _levels.Length) + if ((int)level <= _levels.Length) { priority = _levels[(int)level]; } @@ -375,7 +375,7 @@ internal enum LogLevel : uint internal static class NativeMethods { - const string libpslnative = "libpsl-native"; + private const string libpslnative = "libpsl-native"; /// /// Write a message to the system logger, which in turn writes the message to the system console, log files, etc. /// See man 3 syslog for more info. @@ -443,97 +443,97 @@ internal enum SysLogPriority : uint /// /// Kernel messages. /// - Kernel = (0<<3), + Kernel = (0 << 3), /// /// Random user-level messages. /// - User = (1<<3), + User = (1 << 3), /// /// Mail system. /// - Mail = (2<<3), + Mail = (2 << 3), /// /// System daemons. /// - Daemon = (3<<3), + Daemon = (3 << 3), /// /// Authorization messages. /// - Authorization = (4<<3), + Authorization = (4 << 3), /// /// Messages generated internally by syslogd. /// - Syslog = (5<<3), + Syslog = (5 << 3), /// /// Line printer subsystem. /// - Lpr = (6<<3), + Lpr = (6 << 3), /// /// Network news subsystem. /// - News = (7<<3), + News = (7 << 3), /// /// UUCP subsystem. /// - Uucp = (8<<3), + Uucp = (8 << 3), /// /// Clock daemon. /// - Cron = (9<<3), + Cron = (9 << 3), /// /// Security/authorization messages (private) /// - Authpriv = (10<<3), + Authpriv = (10 << 3), /// /// FTP daemon. /// - Ftp = (11<<3), + Ftp = (11 << 3), // Reserved for system use /// /// Reserved for local use. /// - Local0 = (16<<3), + Local0 = (16 << 3), /// /// Reserved for local use. /// - Local1 = (17<<3), + Local1 = (17 << 3), /// /// Reserved for local use. /// - Local2 = (18<<3), + Local2 = (18 << 3), /// /// Reserved for local use. /// - Local3 = (19<<3), + Local3 = (19 << 3), /// /// Reserved for local use. /// - Local4 = (20<<3), + Local4 = (20 << 3), /// /// Reserved for local use. /// - Local5 = (21<<3), + Local5 = (21 << 3), /// /// Reserved for local use. /// - Local6 = (22<<3), + Local6 = (22 << 3), /// /// Reserved for local use. /// - Local7 = (23<<3), + Local7 = (23 << 3), } } } diff --git a/src/System.Management.Automation/utils/tracing/TracingGen.cs b/src/System.Management.Automation/utils/tracing/TracingGen.cs index ea369e4513a..05f088b7f93 100644 --- a/src/System.Management.Automation/utils/tracing/TracingGen.cs +++ b/src/System.Management.Automation/utils/tracing/TracingGen.cs @@ -37,89 +37,89 @@ public sealed partial class Tracer : System.Management.Automation.Tracing.EtwAct /// public const long KeywordAll = 0xFFFFFFFF; - private static Guid providerId = Guid.Parse("a0c1853b-5c40-4b15-8766-3cf1c58f985a"); - private static EventDescriptor WriteTransferEventEvent; - private static EventDescriptor DebugMessageEvent; - private static EventDescriptor M3PAbortingWorkflowExecutionEvent; - private static EventDescriptor M3PActivityExecutionFinishedEvent; - private static EventDescriptor M3PActivityExecutionQueuedEvent; - private static EventDescriptor M3PActivityExecutionStartedEvent; - private static EventDescriptor M3PBeginContainerParentJobExecutionEvent; - private static EventDescriptor M3PBeginCreateNewJobEvent; - private static EventDescriptor M3PBeginJobLogicEvent; - private static EventDescriptor M3PBeginProxyChildJobEventHandlerEvent; - private static EventDescriptor M3PBeginProxyJobEventHandlerEvent; - private static EventDescriptor M3PBeginProxyJobExecutionEvent; - private static EventDescriptor M3PBeginRunGarbageCollectionEvent; - private static EventDescriptor M3PBeginStartWorkflowApplicationEvent; - private static EventDescriptor M3PBeginWorkflowExecutionEvent; - private static EventDescriptor M3PCancellingWorkflowExecutionEvent; - private static EventDescriptor M3PChildWorkflowJobAdditionEvent; - private static EventDescriptor M3PEndContainerParentJobExecutionEvent; - private static EventDescriptor M3PEndCreateNewJobEvent; - private static EventDescriptor M3PEndJobLogicEvent; - private static EventDescriptor M3PEndpointDisabledEvent; - private static EventDescriptor M3PEndpointEnabledEvent; - private static EventDescriptor M3PEndpointModifiedEvent; - private static EventDescriptor M3PEndpointRegisteredEvent; - private static EventDescriptor M3PEndpointUnregisteredEvent; - private static EventDescriptor M3PEndProxyChildJobEventHandlerEvent; - private static EventDescriptor M3PEndProxyJobEventHandlerEvent; - private static EventDescriptor M3PEndProxyJobExecutionEvent; - private static EventDescriptor M3PEndRunGarbageCollectionEvent; - private static EventDescriptor M3PEndStartWorkflowApplicationEvent; - private static EventDescriptor M3PEndWorkflowExecutionEvent; - private static EventDescriptor M3PErrorImportingWorkflowFromXamlEvent; - private static EventDescriptor M3PForcedWorkflowShutdownErrorEvent; - private static EventDescriptor M3PForcedWorkflowShutdownFinishedEvent; - private static EventDescriptor M3PForcedWorkflowShutdownStartedEvent; - private static EventDescriptor M3PImportedWorkflowFromXamlEvent; - private static EventDescriptor M3PImportingWorkflowFromXamlEvent; - private static EventDescriptor M3PJobCreationCompleteEvent; - private static EventDescriptor M3PJobErrorEvent; - private static EventDescriptor M3PJobRemovedEvent; - private static EventDescriptor M3PJobRemoveErrorEvent; - private static EventDescriptor M3PJobStateChangedEvent; - private static EventDescriptor M3PLoadingWorkflowForExecutionEvent; - private static EventDescriptor M3POutOfProcessRunspaceStartedEvent; - private static EventDescriptor M3PParameterSplattingWasPerformedEvent; - private static EventDescriptor M3PParentJobCreatedEvent; - private static EventDescriptor M3PPersistenceStoreMaxSizeReachedEvent; - private static EventDescriptor M3PPersistingWorkflowEvent; - private static EventDescriptor M3PProxyJobRemoteJobAssociationEvent; - private static EventDescriptor M3PRemoveJobStartedEvent; - private static EventDescriptor M3PRunspaceAvailabilityChangedEvent; - private static EventDescriptor M3PRunspaceStateChangedEvent; - private static EventDescriptor M3PTrackingGuidContainerParentJobCorrelationEvent; - private static EventDescriptor M3PUnloadingWorkflowEvent; - private static EventDescriptor M3PWorkflowActivityExecutionFailedEvent; - private static EventDescriptor M3PWorkflowActivityValidatedEvent; - private static EventDescriptor M3PWorkflowActivityValidationFailedEvent; - private static EventDescriptor M3PWorkflowCleanupPerformedEvent; - private static EventDescriptor M3PWorkflowDeletedFromDiskEvent; - private static EventDescriptor M3PWorkflowEngineStartedEvent; - private static EventDescriptor M3PWorkflowExecutionAbortedEvent; - private static EventDescriptor M3PWorkflowExecutionCancelledEvent; - private static EventDescriptor M3PWorkflowExecutionErrorEvent; - private static EventDescriptor M3PWorkflowExecutionFinishedEvent; - private static EventDescriptor M3PWorkflowExecutionStartedEvent; - private static EventDescriptor M3PWorkflowJobCreatedEvent; - private static EventDescriptor M3PWorkflowLoadedForExecutionEvent; - private static EventDescriptor M3PWorkflowLoadedFromDiskEvent; - private static EventDescriptor M3PWorkflowManagerCheckpointEvent; - private static EventDescriptor M3PWorkflowPersistedEvent; - private static EventDescriptor M3PWorkflowPluginRequestedToShutdownEvent; - private static EventDescriptor M3PWorkflowPluginRestartedEvent; - private static EventDescriptor M3PWorkflowPluginStartedEvent; - private static EventDescriptor M3PWorkflowQuotaViolatedEvent; - private static EventDescriptor M3PWorkflowResumedEvent; - private static EventDescriptor M3PWorkflowResumingEvent; - private static EventDescriptor M3PWorkflowRunspacePoolCreatedEvent; - private static EventDescriptor M3PWorkflowStateChangedEvent; - private static EventDescriptor M3PWorkflowUnloadedEvent; - private static EventDescriptor M3PWorkflowValidationErrorEvent; - private static EventDescriptor M3PWorkflowValidationFinishedEvent; - private static EventDescriptor M3PWorkflowValidationStartedEvent; + private static readonly Guid providerId = Guid.Parse("a0c1853b-5c40-4b15-8766-3cf1c58f985a"); + private static readonly EventDescriptor WriteTransferEventEvent; + private static readonly EventDescriptor DebugMessageEvent; + private static readonly EventDescriptor M3PAbortingWorkflowExecutionEvent; + private static readonly EventDescriptor M3PActivityExecutionFinishedEvent; + private static readonly EventDescriptor M3PActivityExecutionQueuedEvent; + private static readonly EventDescriptor M3PActivityExecutionStartedEvent; + private static readonly EventDescriptor M3PBeginContainerParentJobExecutionEvent; + private static readonly EventDescriptor M3PBeginCreateNewJobEvent; + private static readonly EventDescriptor M3PBeginJobLogicEvent; + private static readonly EventDescriptor M3PBeginProxyChildJobEventHandlerEvent; + private static readonly EventDescriptor M3PBeginProxyJobEventHandlerEvent; + private static readonly EventDescriptor M3PBeginProxyJobExecutionEvent; + private static readonly EventDescriptor M3PBeginRunGarbageCollectionEvent; + private static readonly EventDescriptor M3PBeginStartWorkflowApplicationEvent; + private static readonly EventDescriptor M3PBeginWorkflowExecutionEvent; + private static readonly EventDescriptor M3PCancellingWorkflowExecutionEvent; + private static readonly EventDescriptor M3PChildWorkflowJobAdditionEvent; + private static readonly EventDescriptor M3PEndContainerParentJobExecutionEvent; + private static readonly EventDescriptor M3PEndCreateNewJobEvent; + private static readonly EventDescriptor M3PEndJobLogicEvent; + private static readonly EventDescriptor M3PEndpointDisabledEvent; + private static readonly EventDescriptor M3PEndpointEnabledEvent; + private static readonly EventDescriptor M3PEndpointModifiedEvent; + private static readonly EventDescriptor M3PEndpointRegisteredEvent; + private static readonly EventDescriptor M3PEndpointUnregisteredEvent; + private static readonly EventDescriptor M3PEndProxyChildJobEventHandlerEvent; + private static readonly EventDescriptor M3PEndProxyJobEventHandlerEvent; + private static readonly EventDescriptor M3PEndProxyJobExecutionEvent; + private static readonly EventDescriptor M3PEndRunGarbageCollectionEvent; + private static readonly EventDescriptor M3PEndStartWorkflowApplicationEvent; + private static readonly EventDescriptor M3PEndWorkflowExecutionEvent; + private static readonly EventDescriptor M3PErrorImportingWorkflowFromXamlEvent; + private static readonly EventDescriptor M3PForcedWorkflowShutdownErrorEvent; + private static readonly EventDescriptor M3PForcedWorkflowShutdownFinishedEvent; + private static readonly EventDescriptor M3PForcedWorkflowShutdownStartedEvent; + private static readonly EventDescriptor M3PImportedWorkflowFromXamlEvent; + private static readonly EventDescriptor M3PImportingWorkflowFromXamlEvent; + private static readonly EventDescriptor M3PJobCreationCompleteEvent; + private static readonly EventDescriptor M3PJobErrorEvent; + private static readonly EventDescriptor M3PJobRemovedEvent; + private static readonly EventDescriptor M3PJobRemoveErrorEvent; + private static readonly EventDescriptor M3PJobStateChangedEvent; + private static readonly EventDescriptor M3PLoadingWorkflowForExecutionEvent; + private static readonly EventDescriptor M3POutOfProcessRunspaceStartedEvent; + private static readonly EventDescriptor M3PParameterSplattingWasPerformedEvent; + private static readonly EventDescriptor M3PParentJobCreatedEvent; + private static readonly EventDescriptor M3PPersistenceStoreMaxSizeReachedEvent; + private static readonly EventDescriptor M3PPersistingWorkflowEvent; + private static readonly EventDescriptor M3PProxyJobRemoteJobAssociationEvent; + private static readonly EventDescriptor M3PRemoveJobStartedEvent; + private static readonly EventDescriptor M3PRunspaceAvailabilityChangedEvent; + private static readonly EventDescriptor M3PRunspaceStateChangedEvent; + private static readonly EventDescriptor M3PTrackingGuidContainerParentJobCorrelationEvent; + private static readonly EventDescriptor M3PUnloadingWorkflowEvent; + private static readonly EventDescriptor M3PWorkflowActivityExecutionFailedEvent; + private static readonly EventDescriptor M3PWorkflowActivityValidatedEvent; + private static readonly EventDescriptor M3PWorkflowActivityValidationFailedEvent; + private static readonly EventDescriptor M3PWorkflowCleanupPerformedEvent; + private static readonly EventDescriptor M3PWorkflowDeletedFromDiskEvent; + private static readonly EventDescriptor M3PWorkflowEngineStartedEvent; + private static readonly EventDescriptor M3PWorkflowExecutionAbortedEvent; + private static readonly EventDescriptor M3PWorkflowExecutionCancelledEvent; + private static readonly EventDescriptor M3PWorkflowExecutionErrorEvent; + private static readonly EventDescriptor M3PWorkflowExecutionFinishedEvent; + private static readonly EventDescriptor M3PWorkflowExecutionStartedEvent; + private static readonly EventDescriptor M3PWorkflowJobCreatedEvent; + private static readonly EventDescriptor M3PWorkflowLoadedForExecutionEvent; + private static readonly EventDescriptor M3PWorkflowLoadedFromDiskEvent; + private static readonly EventDescriptor M3PWorkflowManagerCheckpointEvent; + private static readonly EventDescriptor M3PWorkflowPersistedEvent; + private static readonly EventDescriptor M3PWorkflowPluginRequestedToShutdownEvent; + private static readonly EventDescriptor M3PWorkflowPluginRestartedEvent; + private static readonly EventDescriptor M3PWorkflowPluginStartedEvent; + private static readonly EventDescriptor M3PWorkflowQuotaViolatedEvent; + private static readonly EventDescriptor M3PWorkflowResumedEvent; + private static readonly EventDescriptor M3PWorkflowResumingEvent; + private static readonly EventDescriptor M3PWorkflowRunspacePoolCreatedEvent; + private static readonly EventDescriptor M3PWorkflowStateChangedEvent; + private static readonly EventDescriptor M3PWorkflowUnloadedEvent; + private static readonly EventDescriptor M3PWorkflowValidationErrorEvent; + private static readonly EventDescriptor M3PWorkflowValidationFinishedEvent; + private static readonly EventDescriptor M3PWorkflowValidationStartedEvent; /// /// Static constructor. diff --git a/src/TypeCatalogGen/TypeCatalogGen.cs b/src/TypeCatalogGen/TypeCatalogGen.cs index e05f8b63e13..8749c19814b 100644 --- a/src/TypeCatalogGen/TypeCatalogGen.cs +++ b/src/TypeCatalogGen/TypeCatalogGen.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerShell.CoreCLR { - public class TypeCatalogGen + public static class TypeCatalogGen { // Help messages private const string Param_TargetCSharpFilePath = "TargetCSharpFilePath"; @@ -431,7 +431,7 @@ namespace System.Management.Automation {{ internal partial class PowerShellAssemblyLoadContext {{ - private Dictionary InitializeTypeCatalog() + private static Dictionary InitializeTypeCatalog() {{ return new Dictionary({0}, StringComparer.OrdinalIgnoreCase) {{"; const string SourceEnd = @" @@ -459,7 +459,7 @@ private Dictionary InitializeTypeCatalog() /// /// Helper class to keep the metadata of a type. /// - private class TypeMetadata + private sealed class TypeMetadata { internal readonly string AssemblyName; internal readonly bool IsObsolete; diff --git a/src/TypeCatalogGen/TypeCatalogGen.csproj b/src/TypeCatalogGen/TypeCatalogGen.csproj index 1ba3029ff18..e81e027ea75 100644 --- a/src/TypeCatalogGen/TypeCatalogGen.csproj +++ b/src/TypeCatalogGen/TypeCatalogGen.csproj @@ -2,7 +2,8 @@ Generates CorePsTypeCatalog.cs given powershell.inc - net5.0 + net6.0 + true TypeCatalogGen Exe true diff --git a/src/powershell/Program.cs b/src/powershell/Program.cs index a2c6a7852e0..3fee683618f 100644 --- a/src/powershell/Program.cs +++ b/src/powershell/Program.cs @@ -19,7 +19,7 @@ public sealed class ManagedPSEntry /// /// Exception to signify an early startup failure. /// - private class StartupException : Exception + private sealed class StartupException : Exception { /// /// Construct a new startup exception instance. @@ -185,7 +185,6 @@ private static void AttemptExecPwshLogin(string[] args) // We can reuse this value later to prevent needing to call a .NET API // to generate our exec invocation. - // We don't care about argc's value, since argv[0] must always exist. // Skip over argc, but remember where exec_path is for later executablePathPtr = IntPtr.Add(procargs, sizeof(int)); @@ -267,8 +266,8 @@ private static bool IsParam( // Check arg chars in order and allow prefixes for (int i = 1; i < arg.Length; i++) { - if (arg[i] != paramToCheck[i-1] - && arg[i] != paramToCheckUpper[i-1]) + if (arg[i] != paramToCheck[i - 1] + && arg[i] != paramToCheckUpper[i - 1]) { return false; } @@ -321,7 +320,7 @@ private static int ExecPwshLogin(string[] args, string pwshPath, bool isMacOS) // // Since command_name is ignored and we can't use null (it's the terminator) // we use empty string - execArgs[4] = ""; + execArgs[4] = string.Empty; // Add the arguments passed to pwsh on the end. args.CopyTo(execArgs, 5); @@ -371,7 +370,7 @@ private static void CreatePwshInvocation( (string path, int quotedLength) invocationInfo) { // "exec " - string prefix = "exec "; + const string prefix = "exec "; prefix.AsSpan().CopyTo(strBuf); // The quoted path to pwsh, like "'/opt/microsoft/powershell/7/pwsh'" @@ -381,7 +380,7 @@ private static void CreatePwshInvocation( i += invocationInfo.quotedLength; // ' "$@"' the argument vector splat to pass pwsh arguments through - string suffix = " \"$@\""; + const string suffix = " \"$@\""; Span bufSuffix = strBuf.Slice(i); suffix.AsSpan().CopyTo(bufSuffix); } @@ -502,7 +501,7 @@ private static void ThrowOnFailure(string call, int code) CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)] - private static unsafe extern int SysCtl(int *mib, int mibLength, void *oldp, int *oldlenp, IntPtr newp, int newlenp); + private static extern unsafe int SysCtl(int *mib, int mibLength, void *oldp, int *oldlenp, IntPtr newp, int newlenp); #endif } } diff --git a/test/SSHRemoting/SSHRemoting.Basic.Tests.ps1 b/test/SSHRemoting/SSHRemoting.Basic.Tests.ps1 index 40fa0ec1027..7383cc2b8a1 100644 --- a/test/SSHRemoting/SSHRemoting.Basic.Tests.ps1 +++ b/test/SSHRemoting/SSHRemoting.Basic.Tests.ps1 @@ -6,72 +6,202 @@ Describe "SSHRemoting Basic Tests" -tags CI { # SSH remoting is set up to automatically authenticate current user via SSH keys # All tests connect back to localhost machine + $script:TestConnectingTimeout = 5000 # Milliseconds + + function RestartSSHDService + { + if ($IsWindows) + { + Write-Verbose -Verbose "Restarting Windows SSHD service..." + Restart-Service sshd + Write-Verbose -Verbose "SSHD service status: $(Get-Service sshd | Out-String)" + } + else + { + Write-Verbose -Verbose "Restarting Unix SSHD service..." + sudo service ssh restart + $status = sudo service ssh status + Write-Verbose -Verbose "SSHD service status: $status" + } + } + + function TryNewPSSession + { + param( + [string[]] $HostName, + [string[]] $Name, + [int] $Port, + [string] $UserName, + [string] $KeyFilePath, + [string] $Subsystem + ) + + Write-Verbose -Verbose "Starting TryNewPSSession ..." + + # Try creating a new SSH connection + $timeout = $script:TestConnectingTimeout + $connectionError = $null + $session = $null + $count = 0 + while (($null -eq $session) -and ($count++ -lt 2)) + { + $session = New-PSSession @PSBoundParameters -ConnectingTimeout $timeout -ErrorVariable connectionError -ErrorAction SilentlyContinue + if ($null -eq $session) + { + Write-Verbose -Verbose "SSH New-PSSession remoting connect failed." + + if ($count -eq 1) + { + # Try restarting sshd service + RestartSSHDService + } + } + } + + if ($null -eq $session) + { + $message = "New-PSSession unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Exception.Message)" + throw [System.Management.Automation.PSInvalidOperationException]::new($message) + } + + Write-Verbose -Verbose "SSH New-PSSession remoting connect succeeded." + Write-Output $session + } + + function TryNewPSSessionHash + { + param ( + [hashtable[]] $SSHConnection, + [string[]] $Name + ) + + Write-Verbose -Verbose "Starting TryNewPSSessionHash ..." + + foreach ($connect in $SSHConnection) + { + $connect.Add('ConnectingTimeout', $script:TestConnectingTimeout) + } + + # Try creating a new SSH connection + $connectionError = $null + $session = $null + $count = 0 + while (($null -eq $session) -and ($count++ -lt 2)) + { + $session = New-PSSession @PSBoundParameters -ErrorVariable connectionError -ErrorAction SilentlyContinue + if ($null -eq $session) + { + Write-Verbose -Verbose "SSH New-PSSession remoting connect failed." + + if ($count -eq 1) + { + # Try restarting sshd service + RestartSSHDService + } + } + } + + if ($null -eq $session) + { + $message = "New-PSSession unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Exception.Message)" + throw [System.Management.Automation.PSInvalidOperationException]::new($message) + } + + Write-Verbose -Verbose "SSH New-PSSession remoting connect succeeded." + Write-Output $session + } + function VerifySession { param ( [System.Management.Automation.Runspaces.PSSession] $session ) + if ($null -eq $session) + { + return + } + + Write-Verbose -Verbose "VerifySession called for session: $($session.Id)" + $session.State | Should -BeExactly 'Opened' $session.ComputerName | Should -BeExactly 'localhost' $session.Transport | Should -BeExactly 'SSH' + Write-Verbose -Verbose "Invoking whoami" Invoke-Command -Session $session -ScriptBlock { whoami } | Should -BeExactly $(whoami) + Write-Verbose -Verbose "Invoking PSSenderInfo" $psRemoteVersion = Invoke-Command -Session $session -ScriptBlock { $PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion } $psRemoteVersion.Major | Should -BeExactly $PSVersionTable.PSVersion.Major $psRemoteVersion.Minor | Should -BeExactly $PSVersionTable.PSVersion.Minor + Write-Verbose -Verbose "VerifySession complete" } Context "New-PSSession Tests" { AfterEach { + Write-Verbose -Verbose "Starting New-PSSession AfterEach" if ($script:session -ne $null) { Remove-PSSession -Session $script:session } if ($script:sessions -ne $null) { Remove-PSSession -Session $script:sessions } + Write-Verbose -Verbose "AfterEach complete" } It "Verifies new connection with implicit current User" { - $script:session = New-PSSession -HostName localhost -ErrorVariable err - $err | Should -HaveCount 0 + Write-Verbose -Verbose "It Starting: Verifies new connection with implicit current User" + $script:session = TryNewPSSession -HostName localhost + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session + Write-Verbose -Verbose "It Complete" } It "Verifies new connection with explicit User parameter" { - $script:session = New-PSSession -HostName localhost -UserName (whoami) -ErrorVariable err - $err | Should -HaveCount 0 + Write-Verbose -Verbose "It Starting: Verifies new connection with explicit User parameter" + $script:session = TryNewPSSession -HostName localhost -UserName (whoami) + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session + Write-Verbose -Verbose "It Complete" } It "Verifies explicit Name parameter" { + Write-Verbose -Verbose "It Starting: Verifies explicit Name parameter" $sessionName = 'TestSessionNameA' - $script:session = New-PSSession -HostName localhost -Name $sessionName -ErrorVariable err - $err | Should -HaveCount 0 + $script:session = TryNewPSSession -HostName localhost -Name $sessionName + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session $script:session.Name | Should -BeExactly $sessionName + Write-Verbose -Verbose "It Complete" } It "Verifies explicit Port parameter" { + Write-Verbose -Verbose "It Starting: Verifies explicit Port parameter" $portNum = 22 - $script:session = New-PSSession -HostName localhost -Port $portNum -ErrorVariable err - $err | Should -HaveCount 0 + $script:session = TryNewPSSession -HostName localhost -Port $portNum + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session + Write-Verbose -Verbose "It Complete" } It "Verifies explicit Subsystem parameter" { + Write-Verbose -Verbose "It Starting: Verifies explicit Subsystem parameter" $portNum = 22 $subSystem = 'powershell' - $script:session = New-PSSession -HostName localhost -Port $portNum -SubSystem $subSystem -ErrorVariable err - $err | Should -HaveCount 0 + $script:session = TryNewPSSession -HostName localhost -Port $portNum -SubSystem $subSystem + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session + Write-Verbose -Verbose "It Complete" } It "Verifies explicit KeyFilePath parameter" { + Write-Verbose -Verbose "It Starting: Verifies explicit KeyFilePath parameter" $keyFilePath = "$HOME/.ssh/id_rsa" $portNum = 22 $subSystem = 'powershell' - $script:session = New-PSSession -HostName localhost -Port $portNum -SubSystem $subSystem -KeyFilePath $keyFilePath -ErrorVariable err - $err | Should -HaveCount 0 + $script:session = TryNewPSSession -HostName localhost -Port $portNum -SubSystem $subSystem -KeyFilePath $keyFilePath + $script:session | Should -Not -BeNullOrEmpty VerifySession $script:session + Write-Verbose -Verbose "It Complete" } It "Verifies SSHConnection hash table parameters" { + Write-Verbose -Verbose "It Starting: Verifies SSHConnection hash table parameters" $sshConnection = @( @{ HostName = 'localhost' @@ -85,14 +215,62 @@ Describe "SSHRemoting Basic Tests" -tags CI { KeyFilePath = "$HOME/.ssh/id_rsa" Subsystem = 'powershell' }) - $script:sessions = New-PSSession -SSHConnection $sshConnection -Name 'Connection1','Connection2' -ErrorVariable err - $err | Should -HaveCount 0 + $script:sessions = TryNewPSSessionHash -SSHConnection $sshConnection -Name 'Connection1','Connection2' $script:sessions | Should -HaveCount 2 $script:sessions[0].Name | Should -BeLike 'Connection*' $script:sessions[1].Name | Should -BeLike 'Connection*' VerifySession $script:sessions[0] VerifySession $script:sessions[1] + Write-Verbose -Verbose "It Complete" + } + } + + function TryCreateRunspace + { + param ( + [string] $UserName, + [string] $ComputerName, + [string] $KeyFilePath, + [int] $Port, + [string] $Subsystem + ) + + Write-Verbose -Verbose "Starting TryCreateRunspace ..." + + $timeout = $script:TestConnectingTimeout + $connectionError = $null + $count = 0 + $rs = $null + $ci = [System.Management.Automation.Runspaces.SSHConnectionInfo]::new($UserName, $ComputerName, $KeyFilePath, $Port, $Subsystem, $timeout) + while (($null -eq $rs) -and ($count++ -lt 2)) + { + try + { + $rs = [runspacefactory]::CreateRunspace($host, $ci) + $null = $rs.Open() + } + catch + { + $connectionError = $_ + $rs = $null + Write-Verbose -Verbose "SSH Runspace Open remoting connect failed." + + if ($count -eq 1) + { + # Try restarting sshd service + RestartSSHDService + } + } } + + if ($null -eq $rs) + { + $message = "Runspace open unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Message)" + throw [System.Management.Automation.PSInvalidOperationException]::new($message) + } + + Write-Verbose -Verbose "SSH Runspace Open remoting connect succeeded." + Write-Output $rs } function VerifyRunspace { @@ -100,19 +278,29 @@ Describe "SSHRemoting Basic Tests" -tags CI { [runspace] $rs ) + if ($null -eq $rs) + { + return + } + + Write-Verbose -Verbose "VerifyRunspace called for runspace: $($rs.Id)" + $rs.RunspaceStateInfo.State | Should -BeExactly 'Opened' $rs.RunspaceAvailability | Should -BeExactly 'Available' $rs.RunspaceIsRemote | Should -BeTrue $ps = [powershell]::Create() try { + Write-Verbose -Verbose "VerifyRunspace: Invoking PSSenderInfo" $ps.Runspace = $rs $psRemoteVersion = $ps.AddScript('$PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion').Invoke() $psRemoteVersion.Major | Should -BeExactly $PSVersionTable.PSVersion.Major $psRemoteVersion.Minor | Should -BeExactly $PSVersionTable.PSVersion.Minor $ps.Commands.Clear() + Write-Verbose -Verbose "VerifyRunspace: Invoking whoami" $ps.AddScript('whoami').Invoke() | Should -BeExactly $(whoami) + Write-Verbose -Verbose "VerifyRunspace complete" } finally { @@ -123,7 +311,9 @@ Describe "SSHRemoting Basic Tests" -tags CI { Context "SSH Remoting API Tests" { AfterEach { + Write-Verbose -Verbose "Starting Runspace close AfterEach" if ($script:rs -ne $null) { $script:rs.Dispose() } + Write-Verbose -Verbose "AfterEach complete" } $testCases = @( @@ -175,13 +365,15 @@ Describe "SSHRemoting Basic Tests" -tags CI { $ComputerName, $KeyFilePath, $Port, - $SubSystem + $SubSystem, + $TestName ) - $ci = [System.Management.Automation.Runspaces.SSHConnectionInfo]::new($UserName, $ComputerName, $KeyFilePath, $Port, $Subsystem) - $script:rs = [runspacefactory]::CreateRunspace($host, $ci) - $script:rs.Open() + Write-Verbose -Verbose "It Starting: $TestName" + $script:rs = TryCreateRunspace -UserName $UserName -ComputerName $ComputerName -KeyFilePath $KeyFilePath -Port $Port -Subsystem $Subsystem + $script:rs | Should -Not -BeNullOrEmpty VerifyRunspace $script:rs + Write-Verbose -Verbose "It Complete" } } } diff --git a/test/Test.Common.props b/test/Test.Common.props index 5ee96f48726..a1b4b8686d6 100644 --- a/test/Test.Common.props +++ b/test/Test.Common.props @@ -1,15 +1,27 @@ + + PowerShell Test Microsoft Corporation (c) Microsoft Corporation. - net5.0 + net6.0 9.0 true true true + true + true + + + + strict + + + + true diff --git a/test/common/markdown/markdown-link.tests.ps1 b/test/common/markdown/markdown-link.tests.ps1 index 21c3632b530..4339c0174ae 100644 --- a/test/common/markdown/markdown-link.tests.ps1 +++ b/test/common/markdown/markdown-link.tests.ps1 @@ -7,7 +7,7 @@ Describe "Verify Markdown Links" { { Write-Verbose "installing markdown-link-check ..." -Verbose start-nativeExecution { - sudo yarn global add markdown-link-check@3.7.2 + sudo yarn global add markdown-link-check@3.8.5 } } @@ -36,7 +36,7 @@ Describe "Verify Markdown Links" { param([object] $group) foreach($file in $group.Group) { - $results = markdown-link-check $file 2>&1 + $results = markdown-link-check -r $file 2>&1 Write-Output ([PSCustomObject]@{ file = $file results = $results @@ -99,7 +99,8 @@ Describe "Verify Markdown Links" { # check against the allowed failures $allowedFailures = [System.Net.HttpStatusCode[]]( 503, # Service Unavailable - 504 # Gateway Timeout + 504, # Gateway Timeout + 403 # Forbidden, some sites block with from AzDO with this code ) $prefix = $url.Substring(0,7) @@ -116,7 +117,7 @@ Describe "Verify Markdown Links" { catch [Microsoft.PowerShell.Commands.HttpResponseException] { if ( $allowedFailures -notcontains $_.Exception.Response.StatusCode ) { - throw "Failed to complete request to `"$url`". $($_.Exception.Message)" + throw "Failed to complete request to `"$url`". $($_.Exception.Response.StatusCode) $($_.Exception.Message)" } } } diff --git a/test/common/markdown/package.json b/test/common/markdown/package.json index f5d23fa8a59..416b07882b2 100644 --- a/test/common/markdown/package.json +++ b/test/common/markdown/package.json @@ -6,8 +6,17 @@ "main": "gulpfile.js", "dependencies": { "gulp": "^4.0.2", - "markdownlint": "^0.20.2", - "through2": "^3.0.1" + "markdownlint": "^0.22.0", + "through2": "^4.0.2" + }, + "resolutions": { + "yargs-parser": "^13.1.2" , + "y18n": "^5.0.5", + "ini": "^1.3.6", + "copy-props":"^2.0.5", + "glob-parent":"^5.1.2", + "hosted-git-info":"^3.0.8", + "set-value":"^4.0.1" }, "devDependencies": { "gulp-concat": "^2.6.1", diff --git a/test/common/markdown/yarn.lock b/test/common/markdown/yarn.lock index 7b1055e2836..b3af62fe76e 100644 --- a/test/common/markdown/yarn.lock +++ b/test/common/markdown/yarn.lock @@ -4,38 +4,38 @@ ansi-colors@^1.0.1: version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz" integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== dependencies: ansi-wrap "^0.1.0" ansi-gray@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz" integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= dependencies: ansi-wrap "0.1.0" ansi-regex@^2.0.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= anymatch@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz" integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" @@ -43,60 +43,58 @@ anymatch@^2.0.0: append-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz" integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= dependencies: buffer-equal "^1.0.0" archy@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== arr-diff@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-filter@^1.1.1: version "1.1.2" - resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" + resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz" integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= dependencies: make-iterator "^1.0.0" arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-map@^2.0.0, arr-map@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" + resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz" integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= dependencies: make-iterator "^1.0.0" arr-union@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-each@^1.0.0, array-each@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz" integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= array-initial@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" + resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz" integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= dependencies: array-slice "^1.0.0" @@ -104,19 +102,19 @@ array-initial@^1.0.0: array-last@^1.1.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" + resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz" integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== dependencies: is-number "^4.0.0" array-slice@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz" integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== array-sort@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz" integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== dependencies: default-compare "^1.0.0" @@ -125,17 +123,17 @@ array-sort@^1.0.0: array-unique@^0.3.2: version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-done@^1.2.0, async-done@^1.2.2: version "1.3.2" - resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz" integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== dependencies: end-of-stream "^1.1.0" @@ -145,24 +143,24 @@ async-done@^1.2.0, async-done@^1.2.2: async-each@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-settle@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" + resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz" integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= dependencies: async-done "^1.2.2" atob@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== bach@^1.0.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" + resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz" integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= dependencies: arr-filter "^1.1.1" @@ -177,12 +175,12 @@ bach@^1.0.0: balanced-match@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base@^0.11.1: version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz" integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" @@ -195,19 +193,19 @@ base@^0.11.1: binary-extensions@^1.0.0: version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== bindings@^1.5.0: version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -215,7 +213,7 @@ brace-expansion@^1.1.7: braces@^2.3.1, braces@^2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" @@ -231,17 +229,17 @@ braces@^2.3.1, braces@^2.3.2: buffer-equal@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= buffer-from@^1.0.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz" integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" @@ -254,14 +252,27 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + camelcase@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz" integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + chalk@^2.3.0: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -270,7 +281,7 @@ chalk@^2.3.0: chokidar@^2.0.0: version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" @@ -289,7 +300,7 @@ chokidar@^2.0.0: class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz" integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" @@ -299,7 +310,7 @@ class-utils@^0.3.5: cliui@^3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz" integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" @@ -308,22 +319,22 @@ cliui@^3.2.0: clone-buffer@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz" integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= clone-stats@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz" integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= clone@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= cloneable-readable@^1.0.0: version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz" integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== dependencies: inherits "^2.0.1" @@ -332,12 +343,12 @@ cloneable-readable@^1.0.0: code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= collection-map@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" + resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz" integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= dependencies: arr-map "^2.0.2" @@ -346,7 +357,7 @@ collection-map@^1.0.0: collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz" integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" @@ -354,34 +365,34 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-support@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== component-emitter@^1.2.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.6.0: version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" @@ -391,39 +402,39 @@ concat-stream@^1.6.0: concat-with-sourcemaps@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz" integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== dependencies: source-map "^0.6.1" convert-source-map@^1.5.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-props@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" - integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== +copy-props@^2.0.1, copy-props@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.5.tgz#03cf9ae328d4ebb36f8f1d804448a6af9ee3f2d2" + integrity sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw== dependencies: - each-props "^1.3.0" - is-plain-object "^2.0.1" + each-props "^1.3.2" + is-plain-object "^5.0.0" core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= d@1, d@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz" integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== dependencies: es5-ext "^0.10.50" @@ -431,57 +442,57 @@ d@1, d@^1.0.1: debug@^2.2.0, debug@^2.3.3: version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -decamelize@^1.1.1: +decamelize@^1.1.1, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= default-compare@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz" integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== dependencies: kind-of "^5.0.2" default-resolution@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" + resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz" integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= -define-properties@^1.1.2: +define-properties@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz" integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz" integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz" integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" @@ -489,12 +500,12 @@ define-property@^2.0.2: detect-file@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= duplexify@^3.6.0: version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz" integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== dependencies: end-of-stream "^1.0.0" @@ -502,7 +513,7 @@ duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" -each-props@^1.3.0: +each-props@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== @@ -512,26 +523,26 @@ each-props@^1.3.0: end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" entities@~2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" - integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== error-ex@^1.2.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz" integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== dependencies: es6-iterator "~2.0.3" @@ -540,7 +551,7 @@ es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" @@ -549,7 +560,7 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz" integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== dependencies: d "^1.0.1" @@ -557,7 +568,7 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: es6-weak-map@^2.0.1: version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz" integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== dependencies: d "1" @@ -567,12 +578,12 @@ es6-weak-map@^2.0.1: escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz" integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" @@ -585,28 +596,28 @@ expand-brackets@^2.1.4: expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz" integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" ext@^1.1.2: version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz" integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== dependencies: type "^2.0.0" extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz" integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz" integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" @@ -614,12 +625,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extglob@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz" integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" @@ -633,7 +644,7 @@ extglob@^2.0.4: fancy-log@^1.3.2: version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz" integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== dependencies: ansi-gray "^0.1.1" @@ -641,14 +652,19 @@ fancy-log@^1.3.2: parse-node-version "^1.0.0" time-stamp "^1.0.0" +fast-levenshtein@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz" + integrity sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk= + file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== fill-range@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz" integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" @@ -658,7 +674,7 @@ fill-range@^4.0.0: find-up@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz" integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" @@ -666,7 +682,7 @@ find-up@^1.0.0: findup-sync@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz" integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= dependencies: detect-file "^1.0.0" @@ -676,7 +692,7 @@ findup-sync@^2.0.0: findup-sync@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz" integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== dependencies: detect-file "^1.0.0" @@ -686,7 +702,7 @@ findup-sync@^3.0.0: fined@^1.0.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz" integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== dependencies: expand-tilde "^2.0.2" @@ -697,12 +713,12 @@ fined@^1.0.1: flagged-respawn@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz" integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== flush-write-stream@^1.0.2: version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz" integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== dependencies: inherits "^2.0.3" @@ -710,26 +726,26 @@ flush-write-stream@^1.0.2: for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz" integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= dependencies: for-in "^1.0.1" fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz" integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fs-mkdirp-stream@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz" integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= dependencies: graceful-fs "^4.1.11" @@ -737,12 +753,12 @@ fs-mkdirp-stream@^1.0.0: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz" integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" @@ -750,35 +766,43 @@ fsevents@^1.2.7: function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== get-caller-file@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= +glob-parent@^3.1.0, glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" + is-glob "^4.0.1" glob-stream@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz" integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= dependencies: extend "^3.0.0" @@ -793,20 +817,21 @@ glob-stream@^6.1.0: unique-stream "^2.0.2" glob-watcher@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" - integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + version "5.0.5" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.5.tgz" + integrity sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw== dependencies: anymatch "^2.0.0" async-done "^1.2.0" chokidar "^2.0.0" is-negated-glob "^1.0.0" just-debounce "^1.0.0" + normalize-path "^3.0.0" object.defaults "^1.1.0" glob@^7.1.1: version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" @@ -818,7 +843,7 @@ glob@^7.1.1: global-modules@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz" integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" @@ -827,7 +852,7 @@ global-modules@^1.0.0: global-prefix@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz" integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: expand-tilde "^2.0.2" @@ -838,20 +863,20 @@ global-prefix@^1.0.1: glogg@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz" integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== dependencies: sparkles "^1.0.0" graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== gulp-cli@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.2.1.tgz#376e427661b7996430a89d71c15df75defa3360a" - integrity sha512-yEMxrXqY8mJFlaauFQxNrCpzWJThu0sH1sqlToaTOT063Hub9s/Nt2C+GSLe6feQ/IMWrHvGOOsyES7CQc9O+A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz" + integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A== dependencies: ansi-colors "^1.0.1" archy "^1.0.0" @@ -861,7 +886,7 @@ gulp-cli@^2.2.0: copy-props "^2.0.1" fancy-log "^1.3.2" gulplog "^1.0.0" - interpret "^1.1.0" + interpret "^1.4.0" isobject "^3.0.1" liftoff "^3.1.0" matchdep "^2.0.0" @@ -869,12 +894,12 @@ gulp-cli@^2.2.0: pretty-hrtime "^1.0.0" replace-homedir "^1.0.0" semver-greatest-satisfied-range "^1.1.0" - v8flags "^3.0.1" + v8flags "^3.2.0" yargs "^7.1.0" gulp-concat@^2.6.1: version "2.6.1" - resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" + resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz" integrity sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M= dependencies: concat-with-sourcemaps "^1.0.0" @@ -883,7 +908,7 @@ gulp-concat@^2.6.1: gulp-debug@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-debug/-/gulp-debug-4.0.0.tgz#036f9539c3fb6af720e01a9ea5c195fc73f29d5b" + resolved "https://registry.yarnpkg.com/gulp-debug/-/gulp-debug-4.0.0.tgz" integrity sha512-cn/GhMD2nVZCVxAl5vWao4/dcoZ8wUJ8w3oqTvQaGDmC1vT7swNOEbhQTWJp+/otKePT64aENcqAQXDcdj5H1g== dependencies: chalk "^2.3.0" @@ -895,7 +920,7 @@ gulp-debug@^4.0.0: gulp@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz" integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== dependencies: glob-watcher "^5.0.3" @@ -905,24 +930,24 @@ gulp@^4.0.2: gulplog@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz" integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= dependencies: glogg "^1.0.0" has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: +has-symbols@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-value@^0.3.1: version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz" integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" @@ -931,7 +956,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz" integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" @@ -940,32 +965,41 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz" integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz" integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + homedir-polyfill@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz" integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" -hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== +hosted-git-info@^2.1.4, hosted-git-info@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" + integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== + dependencies: + lru-cache "^6.0.0" inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -973,32 +1007,32 @@ inflight@^1.0.4: inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +ini@^1.3.4, ini@^1.3.6: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -interpret@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== invert-kv@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= irregular-plurals@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz" integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== is-absolute@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz" integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== dependencies: is-relative "^1.0.0" @@ -1006,52 +1040,59 @@ is-absolute@^1.0.0: is-accessor-descriptor@^0.1.6: version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz" integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz" integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" @@ -1060,7 +1101,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz" integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" @@ -1069,36 +1110,36 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz" integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-glob@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz" integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -1107,126 +1148,136 @@ is-glob@^4.0.0: is-negated-glob@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz" integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= is-number@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz" integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz" integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-primitive@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-3.0.1.tgz#98c4db1abff185485a657fc2905052b940524d05" + integrity sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w== + is-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-relative@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz" integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== dependencies: is-unc-path "^1.0.0" is-unc-path@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz" integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== dependencies: unc-path-regex "^0.1.2" is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-valid-glob@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz" integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= just-debounce@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz" integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz" integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0, kind-of@^5.0.2: version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== last-run@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" + resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz" integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= dependencies: default-resolution "^2.0.0" @@ -1234,28 +1285,28 @@ last-run@^1.1.0: lazystream@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz" integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= dependencies: readable-stream "^2.0.5" lcid@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz" integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lead@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz" integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= dependencies: flush-write-stream "^1.0.2" liftoff@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz" integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== dependencies: extend "^3.0.0" @@ -1267,16 +1318,16 @@ liftoff@^3.1.0: rechoir "^0.6.2" resolve "^1.1.7" -linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== +linkify-it@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz" + integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== dependencies: uc.micro "^1.0.1" load-json-file@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz" integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" @@ -1285,46 +1336,53 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-iterator@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz" integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== dependencies: kind-of "^6.0.2" map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz" integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" -markdown-it@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" - integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== +markdown-it@12.0.2: + version "12.0.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.2.tgz#4401beae8df8aa2221fc6565a7188e60a06ef0ed" + integrity sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA== dependencies: - argparse "^1.0.7" + argparse "^2.0.1" entities "~2.0.0" - linkify-it "^2.0.0" + linkify-it "^3.0.1" mdurl "^1.0.1" uc.micro "^1.0.5" -markdownlint@^0.20.2: - version "0.20.3" - resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.20.3.tgz#6f56d3e16d990af79d42e58bd2849f70b3358595" - integrity sha512-J93s59tGvSFvAPWVUtEgxqPI0CHayTx1Z8poj1/4UJAquHGPIruWRMurkRldiNbgBiaQ4OOt15rHZbFfU6u05A== +markdownlint@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.22.0.tgz#4ed95b61c17ae9f4dfca6a01f038c744846c0a72" + integrity sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w== dependencies: - markdown-it "10.0.0" + markdown-it "12.0.2" matchdep@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" + resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz" integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= dependencies: findup-sync "^2.0.0" @@ -1334,12 +1392,12 @@ matchdep@^2.0.0: mdurl@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -1358,14 +1416,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" @@ -1373,22 +1431,22 @@ mixin-deep@^1.2.0: ms@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= mute-stdout@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" + resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz" integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== nan@^2.12.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz" integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" @@ -1405,12 +1463,12 @@ nanomatch@^1.2.9: next-tick@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= normalize-package-data@^2.3.2: version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" @@ -1420,62 +1478,62 @@ normalize-package-data@^2.3.2: normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== now-and-later@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz" integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== dependencies: once "^1.3.2" number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz" integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11, object-keys@^1.0.12: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz" integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.0.4: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz" integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= dependencies: array-each "^1.0.1" @@ -1485,7 +1543,7 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: object.map@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz" integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= dependencies: for-own "^1.0.0" @@ -1493,14 +1551,14 @@ object.map@^1.0.0: object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" object.reduce@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" + resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz" integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= dependencies: for-own "^1.0.0" @@ -1508,33 +1566,33 @@ object.reduce@^1.0.0: once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" ordered-read-streams@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz" integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= dependencies: readable-stream "^2.0.1" os-homedir@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz" integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" parse-filepath@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz" integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= dependencies: is-absolute "^1.0.0" @@ -1543,63 +1601,58 @@ parse-filepath@^1.0.1: parse-json@^2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz" integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parse-node-version@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz" integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== parse-passwd@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-exists@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz" integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-parse@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-root-regex@^0.1.0: version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz" integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= path-root@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz" integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= dependencies: path-root-regex "^0.1.0" path-type@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz" integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" @@ -1608,46 +1661,46 @@ path-type@^1.0.0: pify@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pinkie-promise@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz" integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= plur@^3.0.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" + resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz" integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== dependencies: irregular-plurals "^2.0.0" posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pretty-hrtime@^1.0.0: version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== pump@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz" integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" @@ -1655,7 +1708,7 @@ pump@^2.0.0: pumpify@^1.3.5: version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz" integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: duplexify "^3.6.0" @@ -1664,7 +1717,7 @@ pumpify@^1.3.5: read-pkg-up@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz" integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" @@ -1672,16 +1725,16 @@ read-pkg-up@^1.0.1: read-pkg@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz" integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" path-type "^1.0.0" -"readable-stream@2 || 3": +readable-stream@3: version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" @@ -1690,7 +1743,7 @@ read-pkg@^1.0.0: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" @@ -1703,7 +1756,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readdirp@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" @@ -1712,14 +1765,14 @@ readdirp@^2.2.1: rechoir@^0.6.2: version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz" integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz" integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" @@ -1727,7 +1780,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: remove-bom-buffer@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz" integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== dependencies: is-buffer "^1.1.5" @@ -1735,7 +1788,7 @@ remove-bom-buffer@^3.0.0: remove-bom-stream@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz" integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= dependencies: remove-bom-buffer "^3.0.0" @@ -1744,27 +1797,27 @@ remove-bom-stream@^1.2.0: remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.6.1: version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= replace-ext@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz" integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== replace-homedir@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" + resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz" integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= dependencies: homedir-polyfill "^1.0.1" @@ -1773,17 +1826,17 @@ replace-homedir@^1.0.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-main-filename@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz" integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= dependencies: expand-tilde "^2.0.0" @@ -1791,75 +1844,74 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-options@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz" integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= dependencies: value-or-function "^3.0.0" resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.4.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: + is-core-module "^2.1.0" path-parse "^1.0.6" ret@~0.1.10: version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz" integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" semver-greatest-satisfied-range@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" + resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz" integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= dependencies: sver-compat "^1.5.0" "semver@2 || 3 || 4 || 5": version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== +set-value@^2.0.0, set-value@^2.0.1, set-value@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.1.0.tgz#aa433662d87081b75ad88a4743bd450f044e7d09" + integrity sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw== dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" + is-plain-object "^2.0.4" + is-primitive "^3.0.1" snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz" integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" @@ -1868,14 +1920,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz" integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz" integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" @@ -1889,7 +1941,7 @@ snapdragon@^0.8.1: source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" @@ -1900,27 +1952,27 @@ source-map-resolve@^0.5.0: source-map-url@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.6: version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sparkles@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz" integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== spdx-correct@^3.0.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz" integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" @@ -1928,42 +1980,37 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== -split-string@^3.0.1, split-string@^3.0.2: +split-string@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz" integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - stack-trace@0.0.10: version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz" integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" @@ -1971,17 +2018,17 @@ static-extend@^0.1.1: stream-exhaust@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" + resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz" integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== stream-shift@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" @@ -1990,21 +2037,21 @@ string-width@^1.0.1, string-width@^1.0.2: string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-object@^3.0.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz" integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== dependencies: get-own-enumerable-property-symbols "^3.0.0" @@ -2013,28 +2060,28 @@ stringify-object@^3.0.0: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-bom@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz" integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" sver-compat@^1.5.0: version "1.5.0" - resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" + resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz" integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= dependencies: es6-iterator "^2.0.1" @@ -2042,7 +2089,7 @@ sver-compat@^1.5.0: through2-filter@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz" integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== dependencies: through2 "~2.0.0" @@ -2050,34 +2097,34 @@ through2-filter@^3.0.0: through2@^2.0.0, through2@^2.0.3, through2@~2.0.0: version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" xtend "~4.0.1" -through2@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== +through2@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz" + integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== dependencies: - readable-stream "2 || 3" + readable-stream "3" tildify@^1.1.2: version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz" integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= dependencies: os-homedir "^1.0.0" time-stamp@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz" integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= to-absolute-glob@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz" integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= dependencies: is-absolute "^1.0.0" @@ -2085,14 +2132,14 @@ to-absolute-glob@^2.0.0: to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz" integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" @@ -2100,7 +2147,7 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz" integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" @@ -2110,51 +2157,52 @@ to-regex@^3.0.1, to-regex@^3.0.2: to-through@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz" integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= dependencies: through2 "^2.0.3" type@^1.0.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz" integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz" + integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== unc-path-regex@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz" integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= undertaker-registry@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" + resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz" integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= undertaker@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" - integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.3.0.tgz" + integrity sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg== dependencies: arr-flatten "^1.0.1" arr-map "^2.0.0" bach "^1.0.0" collection-map "^1.0.0" es6-weak-map "^2.0.1" + fast-levenshtein "^1.0.0" last-run "^1.1.0" object.defaults "^1.0.0" object.reduce "^1.0.0" @@ -2162,7 +2210,7 @@ undertaker@^1.2.1: union-value@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz" integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" @@ -2172,7 +2220,7 @@ union-value@^1.0.0: unique-stream@^2.0.2: version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz" integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== dependencies: json-stable-stringify-without-jsonify "^1.0.1" @@ -2180,7 +2228,7 @@ unique-stream@^2.0.2: unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz" integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" @@ -2188,34 +2236,34 @@ unset-value@^1.0.0: upath@^1.1.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== urix@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= use@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -v8flags@^3.0.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" - integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w== +v8flags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz" + integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== dependencies: homedir-polyfill "^1.0.1" validate-npm-package-license@^3.0.1: version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" @@ -2223,12 +2271,12 @@ validate-npm-package-license@^3.0.1: value-or-function@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= vinyl-fs@^3.0.0: version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz" integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== dependencies: fs-mkdirp-stream "^1.0.0" @@ -2251,7 +2299,7 @@ vinyl-fs@^3.0.0: vinyl-sourcemap@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz" integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= dependencies: append-buffer "^1.0.2" @@ -2263,9 +2311,9 @@ vinyl-sourcemap@^1.1.0: vinyl "^2.0.0" vinyl@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" - integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== dependencies: clone "^2.1.1" clone-buffer "^1.0.0" @@ -2276,19 +2324,19 @@ vinyl@^2.0.0: which-module@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz" integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which@^1.2.14: version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wrap-ansi@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz" integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" @@ -2296,30 +2344,35 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= +y18n@^3.2.1, y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@5.0.0-security.0: - version "5.0.0-security.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz#4ff7271d25f90ac15643b86076a2ab499ec9ee24" - integrity sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ== +yargs-parser@5.0.0-security.0, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: - camelcase "^3.0.0" - object.assign "^4.1.0" + camelcase "^5.0.0" + decamelize "^1.2.0" yargs@^7.1.0: version "7.1.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz" integrity sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g== dependencies: camelcase "^3.0.0" diff --git a/test/hosting/NuGet.Config b/test/hosting/NuGet.Config index c2c6e1b7c2d..765346e5343 100644 --- a/test/hosting/NuGet.Config +++ b/test/hosting/NuGet.Config @@ -2,8 +2,6 @@ - - diff --git a/test/hosting/test_HostingBasic.cs b/test/hosting/test_HostingBasic.cs index efd3043d514..6cff7978e48 100644 --- a/test/hosting/test_HostingBasic.cs +++ b/test/hosting/test_HostingBasic.cs @@ -51,7 +51,7 @@ public static void TestCommandFromCore() foreach (dynamic item in results) { - Assert.Equal(6,item); + Assert.Equal(6, item); } } } diff --git a/test/packaging/windows/exe.tests.ps1 b/test/packaging/windows/exe.tests.ps1 new file mode 100644 index 00000000000..5a72195900e --- /dev/null +++ b/test/packaging/windows/exe.tests.ps1 @@ -0,0 +1,126 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe -Name "Windows EXE" -Fixture { + BeforeAll { + function Test-Elevated { + [CmdletBinding()] + [OutputType([bool])] + Param() + + # if the current Powershell session was called with administrator privileges, + # the Administrator Group's well-known SID will show up in the Groups for the current identity. + # Note that the SID won't show up unless the process is elevated. + return (([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -contains "S-1-5-32-544") + } + + function Invoke-ExeInstaller { + param( + [Parameter(ParameterSetName = 'Install', Mandatory)] + [Switch]$Install, + + [Parameter(ParameterSetName = 'Uninstall', Mandatory)] + [Switch]$Uninstall, + + [Parameter(Mandatory)] + [ValidateScript({Test-Path -Path $_})] + [String]$ExePath + ) + $action = "$($PSCmdlet.ParameterSetName)ing" + if ($Install) { + $switch = '/install' + } else { + $switch = '/uninstall' + } + + $installProcess = Start-Process -wait $ExePath -ArgumentList $switch, '/quiet', '/norestart' -PassThru + if ($installProcess.ExitCode -ne 0) { + $exitCode = $installProcess.ExitCode + throw "$action EXE failed and returned error code $exitCode." + } + } + + $exePath = $env:PsExePath + $channel = $env:PSMsiChannel + $runtime = $env:PSMsiRuntime + + # Get any existing powershell in the path + $beforePath = @(([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | + Where-Object {$_ -like '*files\powershell*'}) + + foreach ($pathPart in $beforePath) { + Write-Warning "Found existing PowerShell path: $pathPart" + } + + if (!(Test-Elevated)) { + Write-Warning "Tests must be elevated" + } + } + BeforeEach { + $error.Clear() + } + + Context "$Channel-$Runtime" { + BeforeAll { + Write-Verbose "cr-$channel-$runtime" -Verbose + switch ("$channel-$runtime") { + "preview-win7-x64" { + $msiUpgradeCode = '39243d76-adaf-42b1-94fb-16ecf83237c8' + } + "stable-win7-x64" { + $msiUpgradeCode = '31ab5147-9a97-4452-8443-d9709f0516e1' + } + "preview-win7-x86" { + $msiUpgradeCode = '86abcfbd-1ccc-4a88-b8b2-0facfde29094' + } + "stable-win7-x86" { + $msiUpgradeCode = '1d00683b-0f84-4db8-a64f-2f98ad42fe06' + } + default { + throw "'$_' not a valid channel runtime combination" + } + } + } + + It "$Channel MSI should not be installed before test" -Skip:(!(Test-Elevated)) { + $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$msiUpgradeCode}'") + $result.Count | Should -Be 0 -Because "Query should return nothing if $channel $runtime is not installed" + } + + It "EXE should install without error" -Skip:(!(Test-Elevated)) { + { + Invoke-ExeInstaller -Install -ExePath $exePath + } | Should -Not -Throw + } + + It "Upgrade code should be correct" -Skip:(!(Test-Elevated)) { + $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$msiUpgradeCode}'") + $result.Count | Should -Be 1 -Because "Query should return 1 result if Upgrade code is for $runtime $channel" + } + + It "MSI should have updated path" -Skip:(!(Test-Elevated)) { + if ($channel -eq 'preview') { + $pattern = '*files*\powershell*\preview*' + } else { + $pattern = '*files*\powershell*' + } + + $psPath = ([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | + Where-Object { $_ -like $pattern -and $_ -notin $beforePath } + + if (!$psPath) { + ([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | + Where-Object { $_ -notin $beforePath } | + ForEach-Object { Write-Verbose -Verbose $_ } + } + + $psPath | Should -Not -BeNullOrEmpty + } + + It "MSI should uninstall without error" -Skip:(!(Test-Elevated)) { + { + Invoke-ExeInstaller -Uninstall -ExePath $exePath + } | Should -Not -Throw + } + } +} diff --git a/test/packaging/windows/msi.tests.ps1 b/test/packaging/windows/msi.tests.ps1 index d9541b74f06..9d1c218c4c0 100644 --- a/test/packaging/windows/msi.tests.ps1 +++ b/test/packaging/windows/msi.tests.ps1 @@ -3,6 +3,7 @@ Describe -Name "Windows MSI" -Fixture { BeforeAll { + Set-StrictMode -Off function Test-Elevated { [CmdletBinding()] [OutputType([bool])] @@ -14,6 +15,43 @@ Describe -Name "Windows MSI" -Fixture { return (([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -contains "S-1-5-32-544") } + function Test-IsMuEnabled { + $sm = (New-Object -ComObject Microsoft.Update.ServiceManager) + $mu = $sm.Services | Where-Object { $_.ServiceId -eq '7971f918-a847-4430-9279-4a52d1efe18d' } + if ($mu) { + return $true + } + return $false + } + + function Invoke-TestAndUploadLogOnFailure { + param ( + [scriptblock] $Test + ) + + try { + & $Test + } + catch { + Send-VstsLogFile -Path $msiLog + throw + } + } + + function Get-UseMU { + $useMu = 0 + $key = 'HKLM:\SOFTWARE\Microsoft\PowerShellCore\' + if ($runtime -like '*x86*') { + $key = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\PowerShellCore\' + } + + try { + $useMu = Get-ItemPropertyValue -Path $key -Name UseMU -ErrorAction SilentlyContinue + } catch {} + + return $useMu + } + function Invoke-Msiexec { param( [Parameter(ParameterSetName = 'Install', Mandatory)] @@ -45,6 +83,7 @@ Describe -Name "Windows MSI" -Fixture { } $argumentList = "$switch $MsiPath /quiet /l*vx $msiLog $additionalOptions" + Write-Verbose -Message "running msiexec $argumentList" $msiExecProcess = Start-Process msiexec.exe -Wait -ArgumentList $argumentList -NoNewWindow -PassThru if ($msiExecProcess.ExitCode -ne 0) { $exitCode = $msiExecProcess.ExitCode @@ -53,6 +92,9 @@ Describe -Name "Windows MSI" -Fixture { } $msiX64Path = $env:PsMsiX64Path + $channel = $env:PSMsiChannel + $runtime = $env:PSMsiRuntime + $muEnabled = Test-IsMuEnabled # Get any existing powershell in the path $beforePath = @(([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | @@ -69,25 +111,51 @@ Describe -Name "Windows MSI" -Fixture { } $uploadedLog = $false } + + AfterAll { + Set-StrictMode -Version 3.0 + } + BeforeEach { $error.Clear() } - AfterEach { - if ($error.Count -ne 0 -and !$uploadedLog) { - Copy-Item -Path $msiLog -Destination $env:temp -Force - Write-Verbose "MSI log is at $env:temp\msilog.txt" -Verbose - $uploadedLog = $true - } - } Context "Upgrade code" { BeforeAll { - $previewUpgladeCode = '39243d76-adaf-42b1-94fb-16ecf83237c8' + Write-Verbose "cr-$channel-$runtime" -Verbose + $pwshPath = Join-Path $env:ProgramFiles -ChildPath "PowerShell" + $pwshx86Path = Join-Path ${env:ProgramFiles(x86)} -ChildPath "PowerShell" + + switch ("$channel-$runtime") { + "preview-win7-x64" { + $versionPath = Join-Path -Path $pwshPath -ChildPath '7-preview' + $revisionRange = 0, 99 + $msiUpgradeCode = '39243d76-adaf-42b1-94fb-16ecf83237c8' + } + "stable-win7-x64" { + $versionPath = Join-Path -Path $pwshPath -ChildPath '7' + $revisionRange = 500, 500 + $msiUpgradeCode = '31ab5147-9a97-4452-8443-d9709f0516e1' + } + "preview-win7-x86" { + $versionPath = Join-Path -Path $pwshx86Path -ChildPath '7-preview' + $revisionRange = 0, 99 + $msiUpgradeCode = '86abcfbd-1ccc-4a88-b8b2-0facfde29094' + } + "stable-win7-x86" { + $versionPath = Join-Path -Path $pwshx86Path -ChildPath '7' + $revisionRange = 500, 500 + $msiUpgradeCode = '1d00683b-0f84-4db8-a64f-2f98ad42fe06' + } + default { + throw "'$_' not a valid channel runtime combination" + } + } } - It "Preview MSI should not be installed before test" -Skip:(!(Test-Elevated)) { - $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$previewUpgladeCode}'") - $result.Count | Should -Be 0 -Because 'Query should return nothing if preview x64 is not installed' + It "$Channel MSI should not be installed before test" -Skip:(!(Test-Elevated)) { + $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$msiUpgradeCode}'") + $result.Count | Should -Be 0 -Because "Query should return nothing if $channel $runtime is not installed" } It "MSI should install without error" -Skip:(!(Test-Elevated)) { @@ -97,8 +165,16 @@ Describe -Name "Windows MSI" -Fixture { } It "Upgrade code should be correct" -Skip:(!(Test-Elevated)) { - $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$previewUpgladeCode}'") - $result.Count | Should -Be 1 -Because 'Query should return 1 result if Upgrade code is for x64 preview' + $result = @(Get-CimInstance -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' and Value = '{$msiUpgradeCode}'") + $result.Count | Should -Be 1 -Because "Query should return 1 result if Upgrade code is for $runtime $channel" + } + + It "Revision should be in correct range" -Skip:(!(Test-Elevated)) { + $pwshDllPath = Join-Path -Path $versionPath -ChildPath "pwsh.dll" + [version] $version = (Get-ChildItem $pwshDllPath).VersionInfo.FileVersion + Write-Verbose "pwsh.dll version: $version" -Verbose + $version.Revision | Should -BeGreaterOrEqual $revisionRange[0] -Because "$channel revision should between $($revisionRange[0]) and $($revisionRange[1])" + $version.Revision | Should -BeLessOrEqual $revisionRange[1] -Because "$channel revision should between $($revisionRange[0]) and $($revisionRange[1])" } It "MSI should uninstall without error" -Skip:(!(Test-Elevated)) { @@ -111,17 +187,45 @@ Describe -Name "Windows MSI" -Fixture { Context "Add Path disabled" { It "MSI should install without error" -Skip:(!(Test-Elevated)) { { - Invoke-MsiExec -Install -MsiPath $msiX64Path -Properties @{ADD_PATH = 0} + Invoke-MsiExec -Install -MsiPath $msiX64Path -Properties @{ADD_PATH = 0; USE_MU = 1; ENABLE_MU = 1} } | Should -Not -Throw } It "MSI should have not be updated path" -Skip:(!(Test-Elevated)) { $psPath = ([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | - Where-Object {$_ -like '*files\powershell*' -and $_ -notin $beforePath} + Where-Object { $_ -like '*files\powershell*' -and $_ -notin $beforePath } $psPath | Should -BeNullOrEmpty } + It "UseMU should be 1" -Skip:(!(Test-Elevated)) { + Invoke-TestAndUploadLogOnFailure -Test { + $useMu = Get-UseMU + $useMu | Should -Be 1 + } + } + + It "MSI should uninstall without error" -Skip:(!(Test-Elevated)) { + { + Invoke-MsiExec -Uninstall -MsiPath $msiX64Path + } | Should -Not -Throw + } + } + + Context "USE_MU disabled" { + It "MSI should install without error" -Skip:(!(Test-Elevated)) { + { + Invoke-MsiExec -Install -MsiPath $msiX64Path -Properties @{USE_MU = 0} + } | Should -Not -Throw + } + + It "UseMU should be 0" -Skip:(!(Test-Elevated)) { + Invoke-TestAndUploadLogOnFailure -Test { + $useMu = Get-UseMU + $useMu | Should -Be 0 + } + } + It "MSI should uninstall without error" -Skip:(!(Test-Elevated)) { { Invoke-MsiExec -Uninstall -MsiPath $msiX64Path @@ -137,8 +241,20 @@ Describe -Name "Windows MSI" -Fixture { } It "MSI should have updated path" -Skip:(!(Test-Elevated)) { + if ($channel -eq 'preview') { + $pattern = '*files*\powershell*\preview*' + } else { + $pattern = '*files*\powershell*' + } + $psPath = ([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | - Where-Object {$_ -like '*files\powershell*\preview*' -and $_ -notin $beforePath} + Where-Object { $_ -like $pattern -and $_ -notin $beforePath } + + if (!$psPath) { + ([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | + Where-Object { $_ -notin $beforePath } | + ForEach-Object { Write-Verbose -Verbose $_ } + } $psPath | Should -Not -BeNullOrEmpty } diff --git a/test/perf/benchmarks/Categories.cs b/test/perf/benchmarks/Categories.cs new file mode 100644 index 00000000000..09f71064930 --- /dev/null +++ b/test/perf/benchmarks/Categories.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace MicroBenchmarks +{ + public static class Categories + { + /// + /// Benchmarks belonging to this category are executed for CI jobs. + /// + public const string Components = "Components"; + + /// + /// Benchmarks belonging to this category are executed for CI jobs. + /// + public const string Engine = "Engine"; + + /// + /// Benchmarks belonging to this category are targeting internal APIs. + /// + public const string Internal = "Internal"; + + /// + /// Benchmarks belonging to this category are targeting public APIs. + /// + public const string Public = "Public"; + } +} diff --git a/test/perf/benchmarks/Engine.Parser.cs b/test/perf/benchmarks/Engine.Parser.cs new file mode 100644 index 00000000000..10538e3201a --- /dev/null +++ b/test/perf/benchmarks/Engine.Parser.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Management.Automation.Language; +using BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace Engine +{ + [BenchmarkCategory(Categories.Engine, Categories.Public)] + public class Parsing + { + [Benchmark] + public Ast UsingStatement() + { + const string Script = @" + using module moduleA + using Assembly assemblyA + using namespace System.IO"; + return Parser.ParseInput(Script, out _, out _); + } + } +} diff --git a/test/perf/benchmarks/Engine.ScriptBlock.cs b/test/perf/benchmarks/Engine.ScriptBlock.cs new file mode 100644 index 00000000000..ad373dd5f99 --- /dev/null +++ b/test/perf/benchmarks/Engine.ScriptBlock.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace Engine +{ + [BenchmarkCategory(Categories.Engine, Categories.Public)] + public class Scripting + { + private Runspace runspace; + private ScriptBlock scriptBlock; + + private void SetupRunspace() + { + // Unless you want to run commands from any built-in modules, using 'CreateDefault2' is enough. + runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2()); + runspace.Open(); + Runspace.DefaultRunspace = runspace; + } + + #region Invoke-Method + + [ParamsSource(nameof(ValuesForScript))] + public string InvokeMethodScript { get; set; } + + public IEnumerable ValuesForScript() + { + yield return @"'String'.GetType()"; + yield return @"[System.IO.Path]::HasExtension('')"; + + // Test on COM method invocation. + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return @"$sh=New-Object -ComObject Shell.Application; $sh.Namespace('c:\')"; + yield return @"$fs=New-Object -ComObject scripting.filesystemobject; $fs.Drives"; + } + } + + [GlobalSetup(Target = nameof(InvokeMethod))] + public void GlobalSetup() + { + SetupRunspace(); + scriptBlock = ScriptBlock.Create(InvokeMethodScript); + + // Run it once to get the C# code jitted and the script compiled. + // The first call to this takes relatively too long, which makes the BDN's heuristic incorrectly + // believe that there is no need to run many ops in each interation. However, the subsequent runs + // of this method is much faster than the first run, and this causes 'MinIterationTime' warnings + // to our benchmarks and make the benchmark results not reliable. + // Calling this method once in 'GlobalSetup' is a workaround. + // See https://github.com/dotnet/BenchmarkDotNet/issues/837#issuecomment-828600157 + scriptBlock.Invoke(); + } + + [Benchmark] + public Collection InvokeMethod() + { + return scriptBlock.Invoke(); + } + + #endregion + + [GlobalCleanup] + public void GlobalCleanup() + { + runspace.Dispose(); + Runspace.DefaultRunspace = null; + } + } +} diff --git a/test/perf/benchmarks/Program.cs b/test/perf/benchmarks/Program.cs new file mode 100644 index 00000000000..2b3aafdb127 --- /dev/null +++ b/test/perf/benchmarks/Program.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using BenchmarkDotNet.Running; +using BenchmarkDotNet.Extensions; + +namespace MicroBenchmarks +{ + public class Program + { + public static int Main(string[] args) + { + var argsList = new List(args); + int? partitionCount; + int? partitionIndex; + List exclusionFilterValue; + List categoryExclusionFilterValue; + bool getDiffableDisasm; + + // Parse and remove any additional parameters that we need that aren't part of BDN (BenchmarkDotnet) + try + { + CommandLineOptions.ParseAndRemoveIntParameter(argsList, "--partition-count", out partitionCount); + CommandLineOptions.ParseAndRemoveIntParameter(argsList, "--partition-index", out partitionIndex); + CommandLineOptions.ParseAndRemoveStringsParameter(argsList, "--exclusion-filter", out exclusionFilterValue); + CommandLineOptions.ParseAndRemoveStringsParameter(argsList, "--category-exclusion-filter", out categoryExclusionFilterValue); + CommandLineOptions.ParseAndRemoveBooleanParameter(argsList, "--disasm-diff", out getDiffableDisasm); + + CommandLineOptions.ValidatePartitionParameters(partitionCount, partitionIndex); + } + catch (ArgumentException e) + { + Console.WriteLine("ArgumentException: {0}", e.Message); + return 1; + } + + return BenchmarkSwitcher + .FromAssembly(typeof(Program).Assembly) + .Run( + argsList.ToArray(), + RecommendedConfig.Create( + artifactsPath: new DirectoryInfo(Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "BenchmarkDotNet.Artifacts")), + mandatoryCategories: ImmutableHashSet.Create(Categories.Components, Categories.Engine), + partitionCount: partitionCount, + partitionIndex: partitionIndex, + exclusionFilterValue: exclusionFilterValue, + categoryExclusionFilterValue: categoryExclusionFilterValue, + getDiffableDisasm: getDiffableDisasm)) + .ToExitCode(); + } + } +} diff --git a/test/perf/benchmarks/README.md b/test/perf/benchmarks/README.md new file mode 100644 index 00000000000..cf2b96c184c --- /dev/null +++ b/test/perf/benchmarks/README.md @@ -0,0 +1,92 @@ +## Micro Benchmarks + +This folder contains micro benchmarks that test the performance of PowerShell Engine. + +### Requirement + +1. A good suite of benchmarks + Something that measures only the thing that we are interested in and _produces accurate, stable and repeatable results_. +2. A set of machine with the same configurations. +3. Automation for regression detection. + +### Design Decision + +1. This project is internal visible to `System.Management.Automation`. + We want to be able to target some internal APIs to get measurements on specific scoped scenarios, + such as measuring the time to compile AST to a delegate by the compiler. +2. This project makes `ProjectReference` to other PowerShell assemblies. + This makes it easy to run benchmarks with the changes made in the codebase. + To run benchmarks with a specific version of PowerShell, + just replace the `ProjectReference` with a `PackageReference` to the `Microsoft.PowerShell.SDK` NuGet package of the corresponding version. + +### Quick Start + +You can run the benchmarks directly using `dotnet run` in this directory: +1. To run the benchmarks in Interactive Mode, where you will be asked which benchmark(s) to run: + ``` + dotnet run -c Release -f net6.0 + ``` + +2. To list all available benchmarks ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Listing-the-Benchmarks)): + ``` + dotnet run -c Release -f net6.0 --list [flat/tree] + ``` + +3. To filter the benchmarks using a glob pattern applied to `namespace.typeName.methodName` ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Filtering-the-Benchmarks)]): + ``` + dotnet run -c Release -f net6.0 --filter *script* --list flat + ``` + +4. To profile the benchmarked code and produce an ETW Trace file ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Profiling)) + ``` + dotnet run -c Release -f net6.0 --filter *script* --profiler ETW + ``` + +You can also use the function `Start-Benchmarking` from the module [`perf.psm1`](../perf.psm1) to run the benchmarks: +```powershell +Start-Benchmarking [-TargetFramework ] [-List ] [-Filter ] [-Artifacts ] [-KeepFiles] [] + +Start-Benchmarking [-TargetPSVersion ] [-Filter ] [-Artifacts ] [-KeepFiles] [] + +Start-Benchmarking -Runtime [-Filter ] [-Artifacts ] [-KeepFiles] [] +``` +Run `Get-Help Start-Benchmarking -Full` to see the description of each parameter. + +### Regression Detection + +We use the tool [`ResultsComparer`](../dotnet-tools/ResultsComparer) to compare the provided benchmark results. +See the [README.md](../dotnet-tools/ResultsComparer/README.md) for `ResultsComparer` for more details. + +The module `perf.psm1` also provides `Compare-BenchmarkResult` that wraps `ResultsComparer`. +Here is an example of using it: + +``` +## Run benchmarks targeting the current code base +PS:1> Start-Benchmarking -Filter *script* -Artifacts C:\arena\tmp\BenchmarkDotNet.Artifacts\current\ + +## Run benchmarks targeting the 7.1.3 version of PS package +PS:2> Start-Benchmarking -Filter *script* -Artifacts C:\arena\tmp\BenchmarkDotNet.Artifacts\7.1.3 -TargetPSVersion 7.1.3 + +## Compare the results using 5% threshold +PS:3> Compare-BenchmarkResult -BaseResultPath C:\arena\tmp\BenchmarkDotNet.Artifacts\7.1.3\ -DiffResultPath C:\arena\tmp\BenchmarkDotNet.Artifacts\current\ -Threshold 1% +summary: +better: 4, geomean: 1.057 +total diff: 4 + +No Slower results for the provided threshold = 1% and noise filter = 0.3ns. + +| Faster | base/diff | Base Median (ns) | Diff Median (ns) | Modality| +| -------------------------------------------------------------------------------- | ---------:| ----------------:| ----------------:| --------:| +| Engine.Scripting.InvokeMethod(Script: "$fs=New-Object -ComObject scripting.files | 1.07 | 50635.77 | 47116.42 | | +| Engine.Scripting.InvokeMethod(Script: "$sh=New-Object -ComObject Shell.Applicati | 1.07 | 1063085.23 | 991602.08 | | +| Engine.Scripting.InvokeMethod(Script: "'String'.GetType()") | 1.06 | 1329.93 | 1252.51 | | +| Engine.Scripting.InvokeMethod(Script: "[System.IO.Path]::HasExtension('')") | 1.02 | 1322.04 | 1297.72 | | + +No file given +``` + +## References + +- [Getting started with BenchmarkDotNet](https://benchmarkdotnet.org/articles/guides/getting-started.html) +- [Micro-benchmark Design Guidelines](https://github.com/dotnet/performance/blob/main/docs/microbenchmark-design-guidelines.md) +- [Adam SITNIK: Powerful benchmarking in .NET](https://www.youtube.com/watch?v=pdcrSG4tOLI&t=351s) diff --git a/test/perf/benchmarks/powershell-perf.csproj b/test/perf/benchmarks/powershell-perf.csproj new file mode 100644 index 00000000000..78608c2e96f --- /dev/null +++ b/test/perf/benchmarks/powershell-perf.csproj @@ -0,0 +1,65 @@ + + + + + + + PowerShell Performance Tests + powershell-perf + Exe + + $(NoWarn);CS8002 + true + + AnyCPU + portable + true + + + $(PERF_TARGET_VERSION) + + + + netcoreapp3.1;net5.0;net6.0 + + 7.1.3 + 7.0.6 + + + + true + ../../../src/signing/visualstudiopublic.snk + true + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj new file mode 100644 index 00000000000..1383cfc1d62 --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj @@ -0,0 +1,17 @@ + + + + Library + netstandard2.0 + + + + + + + + + + + + diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/CommandLineOptions.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/CommandLineOptions.cs new file mode 100644 index 00000000000..3c8b343fc57 --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/CommandLineOptions.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; + +namespace BenchmarkDotNet.Extensions +{ + public class CommandLineOptions + { + // Find and parse given parameter with expected int value, then remove it and its value from the list of arguments to then pass to BenchmarkDotNet + // Throws ArgumentException if the parameter does not have a value or that value is not parsable as an int + public static List ParseAndRemoveIntParameter(List argsList, string parameter, out int? parameterValue) + { + int parameterIndex = argsList.IndexOf(parameter); + parameterValue = null; + + if (parameterIndex != -1) + { + if (parameterIndex + 1 < argsList.Count && Int32.TryParse(argsList[parameterIndex+1], out int parsedParameterValue)) + { + // remove --partition-count args + parameterValue = parsedParameterValue; + argsList.RemoveAt(parameterIndex+1); + argsList.RemoveAt(parameterIndex); + } + else + { + throw new ArgumentException(String.Format("{0} must be followed by an integer", parameter)); + } + } + + return argsList; + } + + public static List ParseAndRemoveStringsParameter(List argsList, string parameter, out List parameterValue) + { + int parameterIndex = argsList.IndexOf(parameter); + parameterValue = new List(); + + if (parameterIndex + 1 < argsList.Count) + { + while (parameterIndex + 1 < argsList.Count && !argsList[parameterIndex + 1].StartsWith("-")) + { + // remove each filter string and stop when we get to the next argument flag + parameterValue.Add(argsList[parameterIndex + 1]); + argsList.RemoveAt(parameterIndex + 1); + } + } + //We only want to remove the --exclusion-filter if it exists + if (parameterIndex != -1) + { + argsList.RemoveAt(parameterIndex); + } + + return argsList; + } + + public static void ParseAndRemoveBooleanParameter(List argsList, string parameter, out bool parameterValue) + { + int parameterIndex = argsList.IndexOf(parameter); + + if (parameterIndex != -1) + { + argsList.RemoveAt(parameterIndex); + + parameterValue = true; + } + else + { + parameterValue = false; + } + } + + public static void ValidatePartitionParameters(int? count, int? index) + { + // Either count and index must both be specified or neither specified + if (!(count.HasValue == index.HasValue)) + { + throw new ArgumentException("If either --partition-count or --partition-index is specified, both must be specified"); + } + // Check values of count and index parameters + else if (count.HasValue && index.HasValue) + { + if (count < 2) + { + throw new ArgumentException("When specified, value of --partition-count must be greater than 1"); + } + else if (!(index < count)) + { + throw new ArgumentException("Value of --partition-index must be less than --partition-count"); + } + else if (index < 0) + { + throw new ArgumentException("Value of --partition-index must be greater than or equal to 0"); + } + } + } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/DiffableDisassemblyExporter.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/DiffableDisassemblyExporter.cs new file mode 100644 index 00000000000..d45977ed5bf --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/DiffableDisassemblyExporter.cs @@ -0,0 +1,90 @@ +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Disassemblers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace BenchmarkDotNet.Extensions +{ + // a simplified copy of internal BDN type: https://github.com/dotnet/BenchmarkDotNet/blob/0445917bf93059f17cb09e7d48cdb5e27a096c37/src/BenchmarkDotNet/Disassemblers/Exporters/GithubMarkdownDisassemblyExporter.cs#L35-L80 + internal static class DiffableDisassemblyExporter + { + private static readonly Lazy> GetSource = new Lazy>(() => GetElementGetter("Source")); + private static readonly Lazy> GetTextRepresentation = new Lazy>(() => GetElementGetter("TextRepresentation")); + + private static readonly Lazy>> Prettify + = new Lazy>>(GetPrettifyMethod); + + internal static string BuildDisassemblyString(DisassemblyResult disassemblyResult, DisassemblyDiagnoserConfig config) + { + StringBuilder sb = new StringBuilder(); + + int methodIndex = 0; + foreach (var method in disassemblyResult.Methods.Where(method => string.IsNullOrEmpty(method.Problem))) + { + sb.AppendLine("```assembly"); + + sb.AppendLine($"; {method.Name}"); + + var pretty = Prettify.Value.Invoke(method, disassemblyResult, config, $"M{methodIndex++:00}"); + + ulong totalSizeInBytes = 0; + foreach (var element in pretty) + { + if (element.Source() is Asm asm) + { + checked + { + totalSizeInBytes += (uint)asm.Instruction.Length; + } + + sb.AppendLine($" {element.TextRepresentation()}"); + } + else // it's a DisassemblyPrettifier.Label (internal type..) + { + sb.AppendLine($"{element.TextRepresentation()}:"); + } + } + + sb.AppendLine($"; Total bytes of code {totalSizeInBytes}"); + sb.AppendLine("```"); + } + + return sb.ToString(); + } + + private static SourceCode Source(this object element) => GetSource.Value.Invoke(element); + + private static string TextRepresentation(this object element) => GetTextRepresentation.Value.Invoke(element); + + private static Func GetElementGetter(string name) + { + var type = typeof(DisassemblyDiagnoser).Assembly.GetType("BenchmarkDotNet.Disassemblers.Exporters.DisassemblyPrettifier"); + + type = type.GetNestedType("Element", BindingFlags.Instance | BindingFlags.NonPublic); + + var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic); + + var method = property.GetGetMethod(nonPublic: true); + + var generic = typeof(Func<,>).MakeGenericType(type, typeof(T)); + + var @delegate = method.CreateDelegate(generic); + + return (obj) => (T)@delegate.DynamicInvoke(obj); // cast to (Func) throws + } + + private static Func> GetPrettifyMethod() + { + var type = typeof(DisassemblyDiagnoser).Assembly.GetType("BenchmarkDotNet.Disassemblers.Exporters.DisassemblyPrettifier"); + + var method = type.GetMethod("Prettify", BindingFlags.Static | BindingFlags.NonPublic); + + var @delegate = method.CreateDelegate(typeof(Func>)); + + return (Func>)@delegate; + } + } +} diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ExclusionFilter.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ExclusionFilter.cs new file mode 100644 index 00000000000..b3ee453123f --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ExclusionFilter.cs @@ -0,0 +1,52 @@ +using BenchmarkDotNet.Filters; +using BenchmarkDotNet.Running; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BenchmarkDotNet.Extensions +{ + class ExclusionFilter : IFilter + { + private readonly GlobFilter globFilter; + + public ExclusionFilter(List _filter) + { + if (_filter != null && _filter.Count != 0) + { + globFilter = new GlobFilter(_filter.ToArray()); + } + } + + public bool Predicate(BenchmarkCase benchmarkCase) + { + if(globFilter == null) + { + return true; + } + return !globFilter.Predicate(benchmarkCase); + } + } + + class CategoryExclusionFilter : IFilter + { + private readonly AnyCategoriesFilter filter; + + public CategoryExclusionFilter(List patterns) + { + if (patterns != null) + { + filter = new AnyCategoriesFilter(patterns.ToArray()); + } + } + + public bool Predicate(BenchmarkCase benchmarkCase) + { + if (filter == null) + { + return true; + } + return !filter.Predicate(benchmarkCase); + } + } +} diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/Extensions.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/Extensions.cs new file mode 100644 index 00000000000..7d0631b896b --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/Extensions.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Reports; + +namespace BenchmarkDotNet.Extensions +{ + public static class SummaryExtensions + { + public static int ToExitCode(this IEnumerable summaries) + { + // an empty summary means that initial filtering and validation did not allow to run + if (!summaries.Any()) + return 1; + + // if anything has failed, it's an error + if (summaries.Any(summary => summary.HasCriticalValidationErrors || summary.Reports.Any(report => !report.BuildResult.IsBuildSuccess || !report.AllMeasurements.Any()))) + return 1; + + return 0; + } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs new file mode 100644 index 00000000000..7b3b2d38f3b --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using BenchmarkDotNet.Validators; + +namespace BenchmarkDotNet.Extensions +{ + /// + /// this class makes sure that every benchmark belongs to a mandatory category + /// categories are used by the CI for filtering + /// + public class MandatoryCategoryValidator : IValidator + { + private readonly ImmutableHashSet _mandatoryCategories; + + public bool TreatsWarningsAsErrors => true; + + public MandatoryCategoryValidator(ImmutableHashSet categories) => _mandatoryCategories = categories; + + public IEnumerable Validate(ValidationParameters validationParameters) + => validationParameters.Benchmarks + .Where(benchmark => !benchmark.Descriptor.Categories.Any(category => _mandatoryCategories.Contains(category))) + .Select(benchmark => benchmark.Descriptor.GetFilterName()) + .Distinct() + .Select(benchmarkId => + new ValidationError( + isCritical: TreatsWarningsAsErrors, + $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]") + ); + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PartitionFilter.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PartitionFilter.cs new file mode 100644 index 00000000000..16ae22f3167 --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PartitionFilter.cs @@ -0,0 +1,27 @@ +using BenchmarkDotNet.Filters; +using System; +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Running; + + +public class PartitionFilter : IFilter +{ + private readonly int? _partitionsCount; + private readonly int? _partitionIndex; // indexed from 0 + private int _counter = 0; + + public PartitionFilter(int? partitionCount, int? partitionIndex) + { + _partitionsCount = partitionCount; + _partitionIndex = partitionIndex; + } + + public bool Predicate(BenchmarkCase benchmarkCase) + { + if (!_partitionsCount.HasValue || !_partitionIndex.HasValue) + return true; // the filter is not enabled so it does not filter anything out and can be added to RecommendedConfig + + return _counter++ % _partitionsCount.Value == _partitionIndex.Value; // will return true only for benchmarks that belong to it’s partition + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PerfLabExporter.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PerfLabExporter.cs new file mode 100644 index 00000000000..b50e408af0b --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/PerfLabExporter.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Loggers; +using BenchmarkDotNet.Reports; +using Reporting; +using System.Linq; + +namespace BenchmarkDotNet.Extensions +{ + internal class PerfLabExporter : ExporterBase + { + protected override string FileExtension => "json"; + protected override string FileCaption => "perf-lab-report"; + + public PerfLabExporter() + { + } + + public override void ExportToLog(Summary summary, ILogger logger) + { + var reporter = Reporter.CreateReporter(); + + DisassemblyDiagnoser disassemblyDiagnoser = summary.Reports + .FirstOrDefault()? // dissasembler was either enabled for all or none of them (so we use the first one) + .BenchmarkCase.Config.GetDiagnosers().OfType().FirstOrDefault(); + + foreach (var report in summary.Reports) + { + var test = new Test(); + test.Name = FullNameProvider.GetBenchmarkName(report.BenchmarkCase); + test.Categories = report.BenchmarkCase.Descriptor.Categories; + + var results = from result in report.AllMeasurements + where result.IterationMode == Engines.IterationMode.Workload && result.IterationStage == Engines.IterationStage.Result + orderby result.LaunchIndex, result.IterationIndex + select new { result.Nanoseconds, result.Operations}; + + var overheadResults = from result in report.AllMeasurements + where result.IsOverhead() && result.IterationStage != Engines.IterationStage.Jitting + orderby result.LaunchIndex, result.IterationIndex + select new { result.Nanoseconds, result.Operations }; + + test.Counters.Add(new Counter + { + Name = "Duration of single invocation", + TopCounter = true, + DefaultCounter = true, + HigherIsBetter = false, + MetricName = "ns", + Results = (from result in results + select result.Nanoseconds / result.Operations).ToList() + }); + test.Counters.Add(new Counter + { + Name = "Overhead invocation", + TopCounter = false, + DefaultCounter = false, + HigherIsBetter = false, + MetricName = "ns", + Results = (from result in overheadResults + select result.Nanoseconds / result.Operations).ToList() + }); + test.Counters.Add(new Counter + { + Name = "Duration", + TopCounter = false, + DefaultCounter = false, + HigherIsBetter = false, + MetricName = "ms", + Results = (from result in results + select result.Nanoseconds).ToList() + }); + + test.Counters.Add(new Counter + { + Name = "Operations", + TopCounter = false, + DefaultCounter = false, + HigherIsBetter = true, + MetricName = "Count", + Results = (from result in results + select (double)result.Operations).ToList() + }); + + foreach (var metric in report.Metrics.Keys) + { + var m = report.Metrics[metric]; + test.Counters.Add(new Counter + { + Name = m.Descriptor.DisplayName, + TopCounter = false, + DefaultCounter = false, + HigherIsBetter = m.Descriptor.TheGreaterTheBetter, + MetricName = m.Descriptor.Unit, + Results = new[] { m.Value } + }); + } + + if (disassemblyDiagnoser != null && disassemblyDiagnoser.Results.TryGetValue(report.BenchmarkCase, out var disassemblyResult)) + { + string disassembly = DiffableDisassemblyExporter.BuildDisassemblyString(disassemblyResult, disassemblyDiagnoser.Config); + test.AdditionalData["disasm"] = disassembly; + } + + reporter.AddTest(test); + } + + logger.WriteLine(reporter.GetJson()); + } + } +} diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/RecommendedConfig.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/RecommendedConfig.cs new file mode 100644 index 00000000000..40aa5f87fbe --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/RecommendedConfig.cs @@ -0,0 +1,86 @@ +using System.Collections.Immutable; +using System.IO; +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Exporters.Json; +using Perfolizer.Horology; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Reports; +using System.Collections.Generic; +using Reporting; +using BenchmarkDotNet.Loggers; +using System.Linq; +using BenchmarkDotNet.Exporters; + +namespace BenchmarkDotNet.Extensions +{ + public static class RecommendedConfig + { + public static IConfig Create( + DirectoryInfo artifactsPath, + ImmutableHashSet mandatoryCategories, + int? partitionCount = null, + int? partitionIndex = null, + List exclusionFilterValue = null, + List categoryExclusionFilterValue = null, + Job job = null, + bool getDiffableDisasm = false) + { + if (job is null) + { + job = Job.Default + .WithWarmupCount(1) // 1 warmup is enough for our purpose + .WithIterationTime(TimeInterval.FromMilliseconds(250)) // the default is 0.5s per iteration, which is slighlty too much for us + .WithMinIterationCount(15) + .WithMaxIterationCount(20) // we don't want to run more that 20 iterations + .DontEnforcePowerPlan(); // make sure BDN does not try to enforce High Performance power plan on Windows + + // See https://github.com/dotnet/roslyn/issues/42393 + job = job.WithArguments(new Argument[] { new MsBuildArgument("/p:DebugType=portable") }); + } + + var config = ManualConfig.CreateEmpty() + .AddLogger(ConsoleLogger.Default) // log output to console + .AddValidator(DefaultConfig.Instance.GetValidators().ToArray()) // copy default validators + .AddAnalyser(DefaultConfig.Instance.GetAnalysers().ToArray()) // copy default analysers + .AddExporter(MarkdownExporter.GitHub) // export to GitHub markdown + .AddColumnProvider(DefaultColumnProviders.Instance) // display default columns (method name, args etc) + .AddJob(job.AsDefault()) // tell BDN that this are our default settings + .WithArtifactsPath(artifactsPath.FullName) + .AddDiagnoser(MemoryDiagnoser.Default) // MemoryDiagnoser is enabled by default + .AddFilter(new PartitionFilter(partitionCount, partitionIndex)) + .AddFilter(new ExclusionFilter(exclusionFilterValue)) + .AddFilter(new CategoryExclusionFilter(categoryExclusionFilterValue)) + .AddExporter(JsonExporter.Full) // make sure we export to Json + .AddColumn(StatisticColumn.Median, StatisticColumn.Min, StatisticColumn.Max) + .AddValidator(TooManyTestCasesValidator.FailOnError) + .AddValidator(new UniqueArgumentsValidator()) // don't allow for duplicated arguments #404 + .AddValidator(new MandatoryCategoryValidator(mandatoryCategories)) + .WithSummaryStyle(SummaryStyle.Default.WithMaxParameterColumnWidth(36)); // the default is 20 and trims too aggressively some benchmark results + + if (Reporter.CreateReporter().InLab) + { + config = config.AddExporter(new PerfLabExporter()); + } + + if (getDiffableDisasm) + { + config = config.AddDiagnoser(CreateDisassembler()); + } + + return config; + } + + private static DisassemblyDiagnoser CreateDisassembler() + => new DisassemblyDiagnoser(new DisassemblyDiagnoserConfig( + maxDepth: 1, // TODO: is depth == 1 enough? + formatter: null, // TODO: enable diffable format + printSource: false, // we are not interested in getting C# + printInstructionAddresses: false, // would make the diffing hard, however could be useful to determine alignment + exportGithubMarkdown: false, + exportHtml: false, + exportCombinedDisassemblyReport: false, + exportDiff: false)); + } +} diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs new file mode 100644 index 00000000000..36c8b41f9c7 --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Validators; + +namespace BenchmarkDotNet.Extensions +{ + /// + /// we need to tell our users that having more than 16 test cases per benchmark is a VERY BAD idea + /// + public class TooManyTestCasesValidator : IValidator + { + private const int Limit = 16; + + public static readonly IValidator FailOnError = new TooManyTestCasesValidator(); + + public bool TreatsWarningsAsErrors => true; + + public IEnumerable Validate(ValidationParameters validationParameters) + { + var byDescriptor = validationParameters.Benchmarks.GroupBy(benchmark => (benchmark.Descriptor, benchmark.Job)); // descriptor = type + method + + return byDescriptor.Where(benchmarkCase => benchmarkCase.Count() > Limit).Select(group => + new ValidationError( + isCritical: true, + message: $"{group.Key.Descriptor.Type.Name}.{group.Key.Descriptor.WorkloadMethod.Name} has {group.Count()} test cases. It MUST NOT have more than {Limit} test cases. We don't have inifinite amount of time to run all the benchmarks!!", + benchmarkCase: group.First())); + } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs new file mode 100644 index 00000000000..7bfab8445cb --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using BenchmarkDotNet.Validators; +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Running; + +namespace BenchmarkDotNet.Extensions +{ + public class UniqueArgumentsValidator : IValidator + { + public bool TreatsWarningsAsErrors => true; + + public IEnumerable Validate(ValidationParameters validationParameters) + => validationParameters.Benchmarks + .Where(benchmark => benchmark.HasArguments || benchmark.HasParameters) + .GroupBy(benchmark => (benchmark.Descriptor.Type, benchmark.Descriptor.WorkloadMethod, benchmark.Job)) + .Where(sameBenchmark => + { + int numberOfUniqueTestCases = sameBenchmark.Distinct(new BenchmarkArgumentsComparer()).Count(); + int numberOfTestCases = sameBenchmark.Count(); + + return numberOfTestCases != numberOfUniqueTestCases; + }) + .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First())); + + private class BenchmarkArgumentsComparer : IEqualityComparer + { + public bool Equals(BenchmarkCase x, BenchmarkCase y) + => Enumerable.SequenceEqual( + x.Parameters.Items.Select(argument => argument.Value), + y.Parameters.Items.Select(argument => argument.Value)); + + public int GetHashCode(BenchmarkCase obj) + => obj.Parameters.Items + .Where(item => item.Value != null) + .Aggregate(seed: 0, (hashCode, argument) => hashCode ^= argument.Value.GetHashCode()); + } + } +} diff --git a/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ValuesGenerator.cs b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ValuesGenerator.cs new file mode 100644 index 00000000000..87bf6d82d8d --- /dev/null +++ b/test/perf/dotnet-tools/BenchmarkDotNet.Extensions/ValuesGenerator.cs @@ -0,0 +1,148 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; + +namespace BenchmarkDotNet.Extensions +{ + public static class ValuesGenerator + { + private const int Seed = 12345; // we always use the same seed to have repeatable results! + + public static T GetNonDefaultValue() + { + if (typeof(T) == typeof(byte)) // we can't use ArrayOfUniqueValues for byte + return Array(byte.MaxValue).First(value => !value.Equals(default)); + else + return ArrayOfUniqueValues(2).First(value => !value.Equals(default)); + } + + /// + /// does not support byte because there are only 256 unique byte values + /// + public static T[] ArrayOfUniqueValues(int count) + { + // allocate the array first to try to take advantage of memory randomization + // as it's usually the first thing called from GlobalSetup method + // which with MemoryRandomization enabled is the first method called right after allocation + // of random-sized memory by BDN engine + T[] result = new T[count]; + + var random = new Random(Seed); + + var uniqueValues = new HashSet(); + + while (uniqueValues.Count != count) + { + T value = GenerateValue(random); + + if (!uniqueValues.Contains(value)) + uniqueValues.Add(value); + } + + uniqueValues.CopyTo(result); + + return result; + } + + public static T[] Array(int count) + { + var result = new T[count]; + + var random = new Random(Seed); + + if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)) + { + random.NextBytes(Unsafe.As(result)); + } + else + { + for (int i = 0; i < result.Length; i++) + { + result[i] = GenerateValue(random); + } + } + + return result; + } + + public static Dictionary Dictionary(int count) + { + var dictionary = new Dictionary(); + + var random = new Random(Seed); + + while (dictionary.Count != count) + { + TKey key = GenerateValue(random); + + if (!dictionary.ContainsKey(key)) + dictionary.Add(key, GenerateValue(random)); + } + + return dictionary; + } + + private static T GenerateValue(Random random) + { + if (typeof(T) == typeof(char)) + return (T)(object)(char)random.Next(char.MinValue, char.MaxValue); + if (typeof(T) == typeof(short)) + return (T)(object)(short)random.Next(short.MaxValue); + if (typeof(T) == typeof(ushort)) + return (T)(object)(ushort)random.Next(short.MaxValue); + if (typeof(T) == typeof(int)) + return (T)(object)random.Next(); + if (typeof(T) == typeof(uint)) + return (T)(object)(uint)random.Next(); + if (typeof(T) == typeof(long)) + return (T)(object)(long)random.Next(); + if (typeof(T) == typeof(ulong)) + return (T)(object)(ulong)random.Next(); + if (typeof(T) == typeof(float)) + return (T)(object)(float)random.NextDouble(); + if (typeof(T) == typeof(double)) + return (T)(object)random.NextDouble(); + if (typeof(T) == typeof(bool)) + return (T)(object)(random.NextDouble() > 0.5); + if (typeof(T) == typeof(string)) + return (T)(object)GenerateRandomString(random, 1, 50); + if (typeof(T) == typeof(Guid)) + return (T)(object)GenerateRandomGuid(random); + + throw new NotImplementedException($"{typeof(T).Name} is not implemented"); + } + + private static string GenerateRandomString(Random random, int minLength, int maxLength) + { + var length = random.Next(minLength, maxLength); + + var builder = new StringBuilder(length); + for (int i = 0; i < length; i++) + { + var rangeSelector = random.Next(0, 3); + + if (rangeSelector == 0) + builder.Append((char) random.Next('a', 'z')); + else if (rangeSelector == 1) + builder.Append((char) random.Next('A', 'Z')); + else + builder.Append((char) random.Next('0', '9')); + } + + return builder.ToString(); + } + + private static Guid GenerateRandomGuid(Random random) + { + byte[] bytes = new byte[16]; + random.NextBytes(bytes); + return new Guid(bytes); + } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/README.md b/test/perf/dotnet-tools/README.md new file mode 100644 index 00000000000..745130f9d6c --- /dev/null +++ b/test/perf/dotnet-tools/README.md @@ -0,0 +1,14 @@ +## Tools + +The tools here are copied from [dotnet/performance](https://github.com/dotnet/performance), +the performance testing repository for the .NET runtime and framework libraries. + +- [BenchmarkDotNet.Extensions](https://github.com/dotnet/performance/tree/main/src/harness/BenchmarkDotNet.Extensions) + - It provides the needed extensions for running benckmarks, + such as the `RecommendedConfig` which defines the set of recommended configurations for running the dotnet benckmarks. +- [Reporting](https://github.com/dotnet/performance/tree/main/src/tools/Reporting) + - It provides additional result reporting support + which may be useful to us when running our benchmarks in lab. +- [ResultsComparer](https://github.com/dotnet/performance/tree/main/src/tools/ResultsComparer) + - It's a tool for comparing different benchmark results. + It's very useful to show the regression of new changes by comparing its benchmark results to the baseline results. diff --git a/test/perf/dotnet-tools/Reporting/Build.cs b/test/perf/dotnet-tools/Reporting/Build.cs new file mode 100644 index 00000000000..c98ac254f34 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Build.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace Reporting +{ + public sealed class Build + { + public string Repo { get; set; } + + public string Branch { get; set; } + + public string Architecture { get; set; } + + public string Locale { get; set; } + + public string GitHash { get; set; } + + public string BuildName { get; set; } + + public DateTime TimeStamp { get; set; } + + public Dictionary AdditionalData { get; set; } = new Dictionary(); + } +} diff --git a/test/perf/dotnet-tools/Reporting/Counter.cs b/test/perf/dotnet-tools/Reporting/Counter.cs new file mode 100644 index 00000000000..3952369c312 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Counter.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace Reporting +{ + public class Counter + { + public string Name { get; set; } + + public bool TopCounter { get; set; } + + public bool DefaultCounter { get; set; } + + public bool HigherIsBetter { get; set; } + + public string MetricName { get; set; } + + public IList Results { get; set; } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/Reporting/EnvironmentProvider.cs b/test/perf/dotnet-tools/Reporting/EnvironmentProvider.cs new file mode 100644 index 00000000000..90d28729284 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/EnvironmentProvider.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Reporting +{ + public class EnvironmentProvider : IEnvironment + { + public string GetEnvironmentVariable(string variable) => Environment.GetEnvironmentVariable(variable); + } +} diff --git a/test/perf/dotnet-tools/Reporting/IEnvironment.cs b/test/perf/dotnet-tools/Reporting/IEnvironment.cs new file mode 100644 index 00000000000..c7dbfb9b002 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/IEnvironment.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Reporting +{ + public interface IEnvironment + { + string GetEnvironmentVariable(string variable); + } +} diff --git a/test/perf/dotnet-tools/Reporting/Os.cs b/test/perf/dotnet-tools/Reporting/Os.cs new file mode 100644 index 00000000000..692a75ee7c5 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Os.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Reporting +{ + public class Os + { + public string Locale { get; set; } + + public string Architecture { get; set; } + + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/Reporting/Reporter.cs b/test/perf/dotnet-tools/Reporting/Reporter.cs new file mode 100644 index 00000000000..9291d6f36eb --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Reporter.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using RuntimeEnvironment = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment; + +namespace Reporting +{ + public class Reporter + { + private Run run; + private Os os; + private Build build; + private List tests = new List(); + protected IEnvironment environment; + + private Reporter() { } + + public void AddTest(Test test) + { + if (tests.Any(t => t.Name.Equals(test.Name))) + throw new Exception($"Duplicate test name, {test.Name}"); + tests.Add(test); + } + + /// + /// Get a Reporter. Relies on environment variables. + /// + /// Optional environment variable provider + /// A Reporter instance or null if the environment is incorrect. + public static Reporter CreateReporter(IEnvironment environment = null) + { + var ret = new Reporter(); + ret.environment = environment == null ? new EnvironmentProvider() : environment; + if (ret.InLab) + { + ret.Init(); + } + + return ret; + } + + private void Init() + { + run = new Run + { + CorrelationId = environment.GetEnvironmentVariable("HELIX_CORRELATION_ID"), + PerfRepoHash = environment.GetEnvironmentVariable("PERFLAB_PERFHASH"), + Name = environment.GetEnvironmentVariable("PERFLAB_RUNNAME"), + Queue = environment.GetEnvironmentVariable("PERFLAB_QUEUE"), + }; + Boolean.TryParse(environment.GetEnvironmentVariable("PERFLAB_HIDDEN"), out bool hidden); + run.Hidden = hidden; + var configs = environment.GetEnvironmentVariable("PERFLAB_CONFIGS"); + if (!String.IsNullOrEmpty(configs)) // configs should be optional. + { + foreach (var kvp in configs.Split(';')) + { + var split = kvp.Split('='); + run.Configurations.Add(split[0], split[1]); + } + } + + os = new Os() + { + Name = $"{RuntimeEnvironment.OperatingSystem} {RuntimeEnvironment.OperatingSystemVersion}", + Architecture = RuntimeInformation.OSArchitecture.ToString(), + Locale = CultureInfo.CurrentUICulture.ToString() + }; + + build = new Build + { + Repo = environment.GetEnvironmentVariable("PERFLAB_REPO"), + Branch = environment.GetEnvironmentVariable("PERFLAB_BRANCH"), + Architecture = environment.GetEnvironmentVariable("PERFLAB_BUILDARCH"), + Locale = environment.GetEnvironmentVariable("PERFLAB_LOCALE"), + GitHash = environment.GetEnvironmentVariable("PERFLAB_HASH"), + BuildName = environment.GetEnvironmentVariable("PERFLAB_BUILDNUM"), + TimeStamp = DateTime.Parse(environment.GetEnvironmentVariable("PERFLAB_BUILDTIMESTAMP")), + }; + build.AdditionalData["productVersion"] = environment.GetEnvironmentVariable("DOTNET_VERSION"); + } + public string GetJson() + { + if (!InLab) + { + return null; + } + var jsonobj = new + { + build, + os, + run, + tests + }; + var settings = new JsonSerializerSettings(); + var resolver = new DefaultContractResolver(); + resolver.NamingStrategy = new CamelCaseNamingStrategy() { ProcessDictionaryKeys = false }; + settings.ContractResolver = resolver; + return JsonConvert.SerializeObject(jsonobj, Formatting.Indented, settings); + } + + public string WriteResultTable() + { + StringBuilder ret = new StringBuilder(); + foreach (var test in tests) + { + var defaultCounter = test.Counters.Single(c => c.DefaultCounter); + var topCounters = test.Counters.Where(c => c.TopCounter && !c.DefaultCounter); + var restCounters = test.Counters.Where(c => !(c.TopCounter || c.DefaultCounter)); + var counterWidth = Math.Max(test.Counters.Max(c => c.Name.Length) + 1, 15); + var resultWidth = Math.Max(test.Counters.Max(c => c.Results.Max().ToString("F3").Length + c.MetricName.Length) + 2, 15); + ret.AppendLine(test.Name); + ret.AppendLine($"{LeftJustify("Metric", counterWidth)}|{LeftJustify("Average",resultWidth)}|{LeftJustify("Min", resultWidth)}|{LeftJustify("Max",resultWidth)}"); + ret.AppendLine($"{new String('-', counterWidth)}|{new String('-', resultWidth)}|{new String('-', resultWidth)}|{new String('-', resultWidth)}"); + + + ret.AppendLine(Print(defaultCounter, counterWidth, resultWidth)); + foreach(var counter in topCounters) + { + ret.AppendLine(Print(counter, counterWidth, resultWidth)); + } + foreach (var counter in restCounters) + { + ret.AppendLine(Print(counter, counterWidth, resultWidth)); + } + } + return ret.ToString(); + } + private string Print(Counter counter, int counterWidth, int resultWidth) + { + string average = $"{counter.Results.Average():F3} {counter.MetricName}"; + string max = $"{counter.Results.Max():F3} {counter.MetricName}"; + string min = $"{counter.Results.Min():F3} {counter.MetricName}"; + return $"{LeftJustify(counter.Name, counterWidth)}|{LeftJustify(average, resultWidth)}|{LeftJustify(min, resultWidth)}|{LeftJustify(max, resultWidth)}"; + } + + private string LeftJustify(string str, int width) + { + return String.Format("{0,-" + width + "}", str); + } + + public bool InLab => environment.GetEnvironmentVariable("PERFLAB_INLAB")?.Equals("1") ?? false; + } +} diff --git a/test/perf/dotnet-tools/Reporting/Reporting.csproj b/test/perf/dotnet-tools/Reporting/Reporting.csproj new file mode 100644 index 00000000000..e0d2f3b8249 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Reporting.csproj @@ -0,0 +1,13 @@ + + + + Library + netstandard2.0 + + + + + + + + diff --git a/test/perf/dotnet-tools/Reporting/Run.cs b/test/perf/dotnet-tools/Reporting/Run.cs new file mode 100644 index 00000000000..d39d30e5801 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Run.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Reporting +{ + public class Run + { + public bool Hidden { get; set; } + + public string CorrelationId { get; set; } + + public string PerfRepoHash { get; set; } + + public string Name { get; set; } + + public string Queue { get; set; } + public IDictionary Configurations { get; set; } = new Dictionary(); + } +} diff --git a/test/perf/dotnet-tools/Reporting/Test.cs b/test/perf/dotnet-tools/Reporting/Test.cs new file mode 100644 index 00000000000..e22529de2b1 --- /dev/null +++ b/test/perf/dotnet-tools/Reporting/Test.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Reporting +{ + public class Test + { + public IList Categories { get; set; } = new List(); + + public string Name { get; set; } + public Dictionary AdditionalData { get; set; } = new Dictionary(); + + public IList Counters { get; set; } = new List(); + + public void AddCounter(Counter counter) + { + if (counter.DefaultCounter && Counters.Any(c => c.DefaultCounter)) + { + throw new Exception($"Duplicate default counter, name: ${counter.Name}"); + } + + if (Counters.Any(c => c.Name.Equals(counter.Name))) + { + throw new Exception($"Duplicate counter name, name: ${counter.Name}"); + } + + Counters.Add(counter); + } + + public void AddCounter(IEnumerable counters) + { + foreach (var counter in counters) + AddCounter(counter); + } + } +} diff --git a/test/perf/dotnet-tools/ResultsComparer/CommandLineOptions.cs b/test/perf/dotnet-tools/ResultsComparer/CommandLineOptions.cs new file mode 100644 index 00000000000..d3ad01be95b --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/CommandLineOptions.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.IO; +using CommandLine; +using CommandLine.Text; + +namespace ResultsComparer +{ + public class CommandLineOptions + { + [Option("base", HelpText = "Path to the folder/file with base results.")] + public string BasePath { get; set; } + + [Option("diff", HelpText = "Path to the folder/file with diff results.")] + public string DiffPath { get; set; } + + [Option("threshold", Required = true, HelpText = "Threshold for Statistical Test. Examples: 5%, 10ms, 100ns, 1s.")] + public string StatisticalTestThreshold { get; set; } + + [Option("noise", HelpText = "Noise threshold for Statistical Test. The difference for 1.0ns and 1.1ns is 10%, but it's just a noise. Examples: 0.5ns 1ns.", Default = "0.3ns" )] + public string NoiseThreshold { get; set; } + + [Option("top", HelpText = "Filter the diff to top/bottom N results. Optional.")] + public int? TopCount { get; set; } + + [Option("csv", HelpText = "Path to exported CSV results. Optional.")] + public FileInfo CsvPath { get; set; } + + [Option("xml", HelpText = "Path to exported XML results. Optional.")] + public FileInfo XmlPath { get; set; } + + [Option('f', "filter", HelpText = "Filter the benchmarks by name using glob pattern(s). Optional.")] + public IEnumerable Filters { get; set; } + + [Usage(ApplicationAlias = "")] + public static IEnumerable Examples + { + get + { + yield return new Example(@"Compare the results stored in 'C:\results\win' (base) vs 'C:\results\unix' (diff) using 5% threshold.", + new CommandLineOptions { BasePath = @"C:\results\win", DiffPath = @"C:\results\unix", StatisticalTestThreshold = "5%" }); + yield return new Example(@"Compare the results stored in 'C:\results\win' (base) vs 'C:\results\unix' (diff) using 5% threshold and show only top/bottom 10 results.", + new CommandLineOptions { BasePath = @"C:\results\win", DiffPath = @"C:\results\unix", StatisticalTestThreshold = "5%", TopCount = 10 }); + yield return new Example(@"Compare the results stored in 'C:\results\win' (base) vs 'C:\results\unix' (diff) using 5% threshold and 0.5ns noise filter.", + new CommandLineOptions { BasePath = @"C:\results\win", DiffPath = @"C:\results\unix", StatisticalTestThreshold = "5%", NoiseThreshold = "0.5ns" }); + yield return new Example(@"Compare the System.Math benchmark results stored in 'C:\results\ubuntu16' (base) vs 'C:\results\ubuntu18' (diff) using 5% threshold.", + new CommandLineOptions { Filters = new[] { "System.Math*" }, BasePath = @"C:\results\win", DiffPath = @"C:\results\unix", StatisticalTestThreshold = "5%" }); + } + } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/ResultsComparer/DataTransferContracts.cs b/test/perf/dotnet-tools/ResultsComparer/DataTransferContracts.cs new file mode 100644 index 00000000000..c3399ea4333 --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/DataTransferContracts.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +using System.Collections.Generic; +using System.Linq; + +namespace DataTransferContracts // generated with http://json2csharp.com/# +{ + public class ChronometerFrequency + { + public int Hertz { get; set; } + } + + public class HostEnvironmentInfo + { + public string BenchmarkDotNetCaption { get; set; } + public string BenchmarkDotNetVersion { get; set; } + public string OsVersion { get; set; } + public string ProcessorName { get; set; } + public int? PhysicalProcessorCount { get; set; } + public int? PhysicalCoreCount { get; set; } + public int? LogicalCoreCount { get; set; } + public string RuntimeVersion { get; set; } + public string Architecture { get; set; } + public bool? HasAttachedDebugger { get; set; } + public bool? HasRyuJit { get; set; } + public string Configuration { get; set; } + public string JitModules { get; set; } + public string DotNetCliVersion { get; set; } + public ChronometerFrequency ChronometerFrequency { get; set; } + public string HardwareTimerKind { get; set; } + } + + public class ConfidenceInterval + { + public int N { get; set; } + public double Mean { get; set; } + public double StandardError { get; set; } + public int Level { get; set; } + public double Margin { get; set; } + public double Lower { get; set; } + public double Upper { get; set; } + } + + public class Percentiles + { + public double P0 { get; set; } + public double P25 { get; set; } + public double P50 { get; set; } + public double P67 { get; set; } + public double P80 { get; set; } + public double P85 { get; set; } + public double P90 { get; set; } + public double P95 { get; set; } + public double P100 { get; set; } + } + + public class Statistics + { + public int N { get; set; } + public double Min { get; set; } + public double LowerFence { get; set; } + public double Q1 { get; set; } + public double Median { get; set; } + public double Mean { get; set; } + public double Q3 { get; set; } + public double UpperFence { get; set; } + public double Max { get; set; } + public double InterquartileRange { get; set; } + public List LowerOutliers { get; set; } + public List UpperOutliers { get; set; } + public List AllOutliers { get; set; } + public double StandardError { get; set; } + public double Variance { get; set; } + public double StandardDeviation { get; set; } + public double Skewness { get; set; } + public double Kurtosis { get; set; } + public ConfidenceInterval ConfidenceInterval { get; set; } + public Percentiles Percentiles { get; set; } + } + + public class Memory + { + public int Gen0Collections { get; set; } + public int Gen1Collections { get; set; } + public int Gen2Collections { get; set; } + public long TotalOperations { get; set; } + public long BytesAllocatedPerOperation { get; set; } + } + + public class Measurement + { + public string IterationStage { get; set; } + public int LaunchIndex { get; set; } + public int IterationIndex { get; set; } + public long Operations { get; set; } + public double Nanoseconds { get; set; } + } + + public class Benchmark + { + public string DisplayInfo { get; set; } + public object Namespace { get; set; } + public string Type { get; set; } + public string Method { get; set; } + public string MethodTitle { get; set; } + public string Parameters { get; set; } + public string FullName { get; set; } + public Statistics Statistics { get; set; } + public Memory Memory { get; set; } + public List Measurements { get; set; } + + /// + /// this method was not auto-generated by a tool, it was added manually + /// + /// an array of the actual workload results (not warmup, not pilot) + internal double[] GetOriginalValues() + => Measurements + .Where(measurement => measurement.IterationStage == "Result") + .Select(measurement => measurement.Nanoseconds / measurement.Operations) + .ToArray(); + } + + public class BdnResult + { + public string Title { get; set; } + public HostEnvironmentInfo HostEnvironmentInfo { get; set; } + public List Benchmarks { get; set; } + } +} \ No newline at end of file diff --git a/test/perf/dotnet-tools/ResultsComparer/Program.cs b/test/perf/dotnet-tools/ResultsComparer/Program.cs new file mode 100644 index 00000000000..655c9f3458e --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/Program.cs @@ -0,0 +1,290 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Xml; +using Perfolizer.Mathematics.Multimodality; +using Perfolizer.Mathematics.SignificanceTesting; +using Perfolizer.Mathematics.Thresholds; +using CommandLine; +using DataTransferContracts; +using MarkdownLog; +using Newtonsoft.Json; + +namespace ResultsComparer +{ + public class Program + { + private const string FullBdnJsonFileExtension = "full.json"; + + public static void Main(string[] args) + { + // we print a lot of numbers here and we want to make it always in invariant way + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + + Parser.Default.ParseArguments(args).WithParsed(Compare); + } + + private static void Compare(CommandLineOptions args) + { + if (!Threshold.TryParse(args.StatisticalTestThreshold, out var testThreshold)) + { + Console.WriteLine($"Invalid Threshold {args.StatisticalTestThreshold}. Examples: 5%, 10ms, 100ns, 1s."); + return; + } + if (!Threshold.TryParse(args.NoiseThreshold, out var noiseThreshold)) + { + Console.WriteLine($"Invalid Noise Threshold {args.NoiseThreshold}. Examples: 0.3ns 1ns."); + return; + } + + var notSame = GetNotSameResults(args, testThreshold, noiseThreshold).ToArray(); + + if (!notSame.Any()) + { + Console.WriteLine($"No differences found between the benchmark results with threshold {testThreshold}."); + return; + } + + PrintSummary(notSame); + + PrintTable(notSame, EquivalenceTestConclusion.Slower, args); + PrintTable(notSame, EquivalenceTestConclusion.Faster, args); + + ExportToCsv(notSame, args.CsvPath); + ExportToXml(notSame, args.XmlPath); + } + + private static IEnumerable<(string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion)> GetNotSameResults(CommandLineOptions args, Threshold testThreshold, Threshold noiseThreshold) + { + foreach ((string id, Benchmark baseResult, Benchmark diffResult) in ReadResults(args) + .Where(result => result.baseResult.Statistics != null && result.diffResult.Statistics != null)) // failures + { + var baseValues = baseResult.GetOriginalValues(); + var diffValues = diffResult.GetOriginalValues(); + + var userTresholdResult = StatisticalTestHelper.CalculateTost(MannWhitneyTest.Instance, baseValues, diffValues, testThreshold); + if (userTresholdResult.Conclusion == EquivalenceTestConclusion.Same) + continue; + + var noiseResult = StatisticalTestHelper.CalculateTost(MannWhitneyTest.Instance, baseValues, diffValues, noiseThreshold); + if (noiseResult.Conclusion == EquivalenceTestConclusion.Same) + continue; + + yield return (id, baseResult, diffResult, userTresholdResult.Conclusion); + } + } + + private static void PrintSummary((string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion)[] notSame) + { + var better = notSame.Where(result => result.conclusion == EquivalenceTestConclusion.Faster); + var worse = notSame.Where(result => result.conclusion == EquivalenceTestConclusion.Slower); + var betterCount = better.Count(); + var worseCount = worse.Count(); + + // If the baseline doesn't have the same set of tests, you wind up with Infinity in the list of diffs. + // Exclude them for purposes of geomean. + worse = worse.Where(x => GetRatio(x) != double.PositiveInfinity); + better = better.Where(x => GetRatio(x) != double.PositiveInfinity); + + Console.WriteLine("summary:"); + + if (betterCount > 0) + { + var betterGeoMean = Math.Pow(10, better.Skip(1).Aggregate(Math.Log10(GetRatio(better.First())), (x, y) => x + Math.Log10(GetRatio(y))) / better.Count()); + Console.WriteLine($"better: {betterCount}, geomean: {betterGeoMean:F3}"); + } + + if (worseCount > 0) + { + var worseGeoMean = Math.Pow(10, worse.Skip(1).Aggregate(Math.Log10(GetRatio(worse.First())), (x, y) => x + Math.Log10(GetRatio(y))) / worse.Count()); + Console.WriteLine($"worse: {worseCount}, geomean: {worseGeoMean:F3}"); + } + + Console.WriteLine($"total diff: {notSame.Length}"); + Console.WriteLine(); + } + + private static void PrintTable((string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion)[] notSame, EquivalenceTestConclusion conclusion, CommandLineOptions args) + { + var data = notSame + .Where(result => result.conclusion == conclusion) + .OrderByDescending(result => GetRatio(conclusion, result.baseResult, result.diffResult)) + .Take(args.TopCount ?? int.MaxValue) + .Select(result => new + { + Id = result.id.Length > 80 ? result.id.Substring(0, 80) : result.id, + DisplayValue = GetRatio(conclusion, result.baseResult, result.diffResult), + BaseMedian = result.baseResult.Statistics.Median, + DiffMedian = result.diffResult.Statistics.Median, + Modality = GetModalInfo(result.baseResult) ?? GetModalInfo(result.diffResult) + }) + .ToArray(); + + if (!data.Any()) + { + Console.WriteLine($"No {conclusion} results for the provided threshold = {args.StatisticalTestThreshold} and noise filter = {args.NoiseThreshold}."); + Console.WriteLine(); + return; + } + + var table = data.ToMarkdownTable().WithHeaders(conclusion.ToString(), conclusion == EquivalenceTestConclusion.Faster ? "base/diff" : "diff/base", "Base Median (ns)", "Diff Median (ns)", "Modality"); + + foreach (var line in table.ToMarkdown().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)) + Console.WriteLine($"| {line.TrimStart()}|"); // the table starts with \t and does not end with '|' and it looks bad so we fix it + + Console.WriteLine(); + } + + private static IEnumerable<(string id, Benchmark baseResult, Benchmark diffResult)> ReadResults(CommandLineOptions args) + { + var baseFiles = GetFilesToParse(args.BasePath); + var diffFiles = GetFilesToParse(args.DiffPath); + + if (!baseFiles.Any() || !diffFiles.Any()) + throw new ArgumentException($"Provided paths contained no {FullBdnJsonFileExtension} files."); + + var baseResults = baseFiles.Select(ReadFromFile); + var diffResults = diffFiles.Select(ReadFromFile); + + var filters = args.Filters.Select(pattern => new Regex(WildcardToRegex(pattern), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); + + var benchmarkIdToDiffResults = diffResults + .SelectMany(result => result.Benchmarks) + .Where(benchmarkResult => !filters.Any() || filters.Any(filter => filter.IsMatch(benchmarkResult.FullName))) + .ToDictionary(benchmarkResult => benchmarkResult.FullName, benchmarkResult => benchmarkResult); + + return baseResults + .SelectMany(result => result.Benchmarks) + .ToDictionary(benchmarkResult => benchmarkResult.FullName, benchmarkResult => benchmarkResult) // we use ToDictionary to make sure the results have unique IDs + .Where(baseResult => benchmarkIdToDiffResults.ContainsKey(baseResult.Key)) + .Select(baseResult => (baseResult.Key, baseResult.Value, benchmarkIdToDiffResults[baseResult.Key])); + } + + private static void ExportToCsv((string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion)[] notSame, FileInfo csvPath) + { + if (csvPath == null) + return; + + if (csvPath.Exists) + csvPath.Delete(); + + using (var textWriter = csvPath.CreateText()) + { + foreach (var (id, baseResult, diffResult, conclusion) in notSame) + { + textWriter.WriteLine($"\"{id.Replace("\"", "\"\"")}\";base;{conclusion};{string.Join(';', baseResult.GetOriginalValues())}"); + textWriter.WriteLine($"\"{id.Replace("\"", "\"\"")}\";diff;{conclusion};{string.Join(';', diffResult.GetOriginalValues())}"); + } + } + + Console.WriteLine($"CSV results exported to {csvPath.FullName}"); + } + + private static void ExportToXml((string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion)[] notSame, FileInfo xmlPath) + { + if (xmlPath == null) + { + Console.WriteLine("No file given"); + return; + } + + if (xmlPath.Exists) + xmlPath.Delete(); + + using (XmlWriter writer = XmlWriter.Create(xmlPath.Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))) + { + writer.WriteStartElement("performance-tests"); + foreach (var (id, baseResult, diffResult, conclusion) in notSame.Where(x => x.conclusion == EquivalenceTestConclusion.Slower)) + { + writer.WriteStartElement("test"); + writer.WriteAttributeString("name", id); + writer.WriteAttributeString("type", baseResult.Type); + writer.WriteAttributeString("method", baseResult.Method); + writer.WriteAttributeString("time", "0"); + writer.WriteAttributeString("result", "Fail"); + writer.WriteStartElement("failure"); + writer.WriteAttributeString("exception-type", "Regression"); + writer.WriteElementString("message", $"{id} has regressed, was {baseResult.Statistics.Median} is {diffResult.Statistics.Median}."); + writer.WriteEndElement(); + } + + foreach (var (id, baseResult, diffResult, conclusion) in notSame.Where(x => x.conclusion == EquivalenceTestConclusion.Faster)) + { + writer.WriteStartElement("test"); + writer.WriteAttributeString("name", id); + writer.WriteAttributeString("type", baseResult.Type); + writer.WriteAttributeString("method", baseResult.Method); + writer.WriteAttributeString("time", "0"); + writer.WriteAttributeString("result", "Skip"); + writer.WriteElementString("reason", $"{id} has improved, was {baseResult.Statistics.Median} is {diffResult.Statistics.Median}."); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + writer.Flush(); + } + + Console.WriteLine($"XML results exported to {xmlPath.FullName}"); + } + + private static string[] GetFilesToParse(string path) + { + if (Directory.Exists(path)) + return Directory.GetFiles(path, $"*{FullBdnJsonFileExtension}", SearchOption.AllDirectories); + else if (File.Exists(path) || !path.EndsWith(FullBdnJsonFileExtension)) + return new[] { path }; + else + throw new FileNotFoundException($"Provided path does NOT exist or is not a {path} file", path); + } + + // code and magic values taken from BenchmarkDotNet.Analysers.MultimodalDistributionAnalyzer + // See http://www.brendangregg.com/FrequencyTrails/modes.html + private static string GetModalInfo(Benchmark benchmark) + { + if (benchmark.Statistics.N < 12) // not enough data to tell + return null; + + double mValue = MValueCalculator.Calculate(benchmark.GetOriginalValues()); + if (mValue > 4.2) + return "multimodal"; + else if (mValue > 3.2) + return "bimodal"; + else if (mValue > 2.8) + return "several?"; + + return null; + } + + private static double GetRatio((string id, Benchmark baseResult, Benchmark diffResult, EquivalenceTestConclusion conclusion) item) => GetRatio(item.conclusion, item.baseResult, item.diffResult); + + private static double GetRatio(EquivalenceTestConclusion conclusion, Benchmark baseResult, Benchmark diffResult) + => conclusion == EquivalenceTestConclusion.Faster + ? baseResult.Statistics.Median / diffResult.Statistics.Median + : diffResult.Statistics.Median / baseResult.Statistics.Median; + + private static BdnResult ReadFromFile(string resultFilePath) + { + try + { + return JsonConvert.DeserializeObject(File.ReadAllText(resultFilePath)); + } + catch (JsonSerializationException) + { + Console.WriteLine($"Exception while reading the {resultFilePath} file."); + + throw; + } + } + + // https://stackoverflow.com/a/6907849/5852046 not perfect but should work for all we need + private static string WildcardToRegex(string pattern) => $"^{Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".")}$"; + } +} diff --git a/test/perf/dotnet-tools/ResultsComparer/README.md b/test/perf/dotnet-tools/ResultsComparer/README.md new file mode 100644 index 00000000000..109ba901422 --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/README.md @@ -0,0 +1,41 @@ +# Results Comparer + +This simple tool allows for easy comparison of provided benchmark results. + +It can be used to compare: +* historical results (eg. before and after my changes) +* results for different OSes (eg. Windows vs Ubuntu) +* results for different CPU architectures (eg. x64 vs ARM64) +* results for different target frameworks (eg. .NET Core 3.1 vs 5.0) + +All you need to provide is: +* `--base` - path to folder/file with baseline results +* `--diff` - path to folder/file with diff results +* `--threshold` - threshold for Statistical Test. Examples: 5%, 10ms, 100ns, 1s + +Optional arguments: +* `--top` - filter the diff to top/bottom `N` results +* `--noise` - noise threshold for Statistical Test. The difference for 1.0ns and 1.1ns is 10%, but it's just a noise. Examples: 0.5ns 1ns. The default value is 0.3ns. +* `--csv` - path to exported CSV results. Optional. +* `-f|--filter` - filter the benchmarks by name using glob pattern(s). Optional. + +Sample: compare the results stored in `C:\results\windows` vs `C:\results\ubuntu` using `1%` threshold and print only TOP 10. + +```cmd +dotnet run --base "C:\results\windows" --diff "C:\results\ubuntu" --threshold 1% --top 10 +``` + +**Note**: the tool supports only `*full.json` results exported by BenchmarkDotNet. This exporter is enabled by default in this repository. + +## Sample results + +| Slower | diff/base | Base Median (ns) | Diff Median (ns) | Modality| +| --------------------------------------------------------------- | ---------:| ----------------:| ----------------:| -------:| +| PerfLabTests.BlockCopyPerf.CallBlockCopy(numElements: 100) | 1.60 | 9.22 | 14.76 | | +| System.Tests.Perf_String.Trim_CharArr(s: "Test", c: [' ', ' ']) | 1.41 | 6.18 | 8.72 | | + +| Faster | base/diff | Base Median (ns) | Diff Median (ns) | Modality| +| ----------------------------------- | ---------:| ----------------:| ----------------:| -------:| +| System.Tests.Perf_Array.ArrayCopy3D | 1.31 | 372.71 | 284.73 | | + +If there is no difference or if there is no match (we use full benchmark names to match the benchmarks), then the results are omitted. diff --git a/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj new file mode 100644 index 00000000000..838d6ccd673 --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj @@ -0,0 +1,15 @@ + + + Exe + $(PERFLAB_TARGET_FRAMEWORKS) + net5.0 + latest + + + + + + + + + diff --git a/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.sln b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.sln new file mode 100644 index 00000000000..951a4d0fb5d --- /dev/null +++ b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResultsComparer", "ResultsComparer.csproj", "{00859394-44F8-466B-8624-41578CA94009}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00859394-44F8-466B-8624-41578CA94009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00859394-44F8-466B-8624-41578CA94009}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00859394-44F8-466B-8624-41578CA94009}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00859394-44F8-466B-8624-41578CA94009}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/test/perf/nuget.config b/test/perf/nuget.config new file mode 100644 index 00000000000..e8b7ac6770f --- /dev/null +++ b/test/perf/nuget.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/perf/perf.psm1 b/test/perf/perf.psm1 new file mode 100644 index 00000000000..5b1ab239160 --- /dev/null +++ b/test/perf/perf.psm1 @@ -0,0 +1,207 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +$repoRoot = git rev-parse --show-toplevel +Import-Module "$repoRoot/build.psm1" + +function Start-Benchmarking +{ + <# + .SYNOPSIS + Start a benchmark run. + + .PARAMETER TargetPSVersion + The version of 'Microsoft.PowerShell.SDK' package that we want the benchmark to target. + The supported versions are 7.0.x and above, including preview versions. + + .PARAMETER TargetFramework + The target framework to run benchmarks against. + + .PARAMETER List + List the available benchmarks, in either 'flat' or 'tree' views. + + .PARAMETER Runtime + Run benchmarks against multiple .NET runtimes. + + .PARAMETER Filter + One or more wildcard patterns to filter the benchmarks to be executed or to be listed. + + .PARAMETER Artifacts + Path to the folder where you want to store the artifacts produced from running benchmarks. + + .PARAMETER KeepFiles + Indicates to keep all temporary files produced for running benchmarks. + #> + [CmdletBinding(DefaultParameterSetName = 'TargetFramework')] + param( + [Parameter(ParameterSetName = 'TargetPSVersion')] + [ValidatePattern( + '^7\.(0|1|2)\.\d+(-preview\.\d{1,2})?$', + ErrorMessage = 'The package version is invalid or not supported')] + [string] $TargetPSVersion, + + [Parameter(ParameterSetName = 'TargetFramework')] + [ValidateSet('netcoreapp3.1', 'net5.0', 'net6.0')] + [string] $TargetFramework = 'net6.0', + + [Parameter(ParameterSetName = 'TargetFramework')] + [ValidateSet('flat', 'tree')] + [string] $List, + + [Parameter(Mandatory, ParameterSetName = 'Runtimes')] + [ValidateSet('netcoreapp3.1', 'net5.0', 'net6.0')] + [string[]] $Runtime, + + [string[]] $Filter = '*', + [string] $Artifacts, + [switch] $KeepFiles + ) + + Begin { + Find-Dotnet + + if ($Artifacts) { + $Artifacts = $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Artifacts) + } else { + $Artifacts = Join-Path $PSScriptRoot 'BenchmarkDotNet.Artifacts' + } + + if (Test-Path -Path $Artifacts) { + Remove-Item -Path $Artifacts -Recurse -Force -ErrorAction Stop + } + + if ($Runtime) { + ## Remove duplicate values. + $hash = [ordered]@{} + foreach ($item in $Runtime) { + if (-not $hash.Contains($item)) { + $hash.Add($item, $null) + } + } + $Runtime = $hash.Keys + } + } + + End { + try { + Push-Location -Path "$PSScriptRoot/benchmarks" + $savedOFS = $OFS; $OFS = $null + + ## Aggregate BDN arguments. + $runArgs = @('--filter') + foreach ($entry in $Filter) { $runArgs += $entry } + $runArgs += '--artifacts', $Artifacts + $runArgs += '--envVars', 'POWERSHELL_TELEMETRY_OPTOUT:1' + + if ($List) { $runArgs += '--list', $List } + if ($KeepFiles) { $runArgs += "--keepFiles" } + + switch ($PSCmdlet.ParameterSetName) { + 'TargetPSVersion' { + Write-Log -message "Run benchmarks targeting '$TargetFramework' and the 'Microsoft.PowerShell.SDK' version '$TargetPSVersion' ..." + $env:PERF_TARGET_VERSION = $TargetPSVersion + + ## Use 'Release' instead of 'release' (note the capital case) because BDN uses 'Release' when building the auto-generated + ## project, and MSBuild somehow recognizes 'release' and 'Release' as two different configurations and thus will rebuild + ## all dependencies unnecessarily. + dotnet run -c Release -f $TargetFramework $runArgs + } + + 'TargetFramework' { + $message = if ($TargetFramework -eq 'net6.0') { 'the current PowerShell code base ...' } else { "the corresponding latest version of 'Microsoft.PowerShell.SDK' ..." } + Write-Log -message "Run benchmarks targeting '$TargetFramework' and $message" + + ## Use 'Release' instead of 'release' (note the capital case) because BDN uses 'Release' when building the auto-generated + ## project, and MSBuild somehow recognizes 'release' and 'Release' as two different configurations and thus will rebuild + ## all dependencies unnecessarily. + dotnet run -c Release -f $TargetFramework $runArgs + } + + 'Runtimes' { + Write-Log -message "Run benchmarks targeting multiple .NET runtimes: $Runtime ..." + + ## Use 'Release' instead of 'release' (note the capital case) because BDN uses 'Release' when building the auto-generated + ## project, and MSBuild somehow recognizes 'release' and 'Release' as two different configurations and thus will rebuild + ## all dependencies unnecessarily. + dotnet run -c Release -f net6.0 --runtimes $Runtime $runArgs + } + } + + if (Test-Path $Artifacts) { + Write-Log -message "`nBenchmark artifacts can be found at $Artifacts" + } + } + finally { + $OFS = $savedOFS + $env:PERF_TARGET_VERSION = $null + Pop-Location + } + } +} + +function Compare-BenchmarkResult +{ + <# + .SYNOPSIS + Compare two benchmark run results to find possible regressions. + + When running benchmarks with 'Start-Benchmarking', you can define the result folder + where to save the artifacts by specifying '-Artifacts'. + + To compare two benchmark run results, you need to specify the result folder paths + for both runs, one as the base and one as the diff. + + .PARAMETER BaseResultPath + Path to the benchmark result used as baseline. + + .PARAMETER DiffResultPath + Path to the benchmark result to be compared with the baseline. + + .PARAMETER Threshold + Threshold for Statistical Test. Examples: 5%, 10ms, 100ns, 1s + + .PARAMETER Noise + Noise threshold for Statistical Test. + The difference for 1.0ns and 1.1ns is 10%, but it's really just noise. Examples: 0.5ns 1ns. + The default value is 0.3ns. + + .PARAMETER Top + Filter the diff to top `N` results + #> + param( + [Parameter(Mandatory)] + [string] $BaseResultPath, + + [Parameter(Mandatory)] + [string] $DiffResultPath, + + [Parameter(Mandatory)] + [ValidatePattern('^\d{1,2}%$|^\d+(ms|ns|s)$')] + [string] $Threshold, + + [ValidatePattern('^(\d\.)?\d+(ms|ns|s)$')] + [string] $Noise, + + [ValidateRange(1, 100)] + [int] $Top + ) + + Find-Dotnet + + try { + Push-Location -Path "$PSScriptRoot/dotnet-tools/ResultsComparer" + $savedOFS = $OFS; $OFS = $null + + $runArgs = @() + if ($Noise) { $runArgs += "--noise $Noise" } + if ($Top -gt 0) { $runArgs += "--top $Top" } + + dotnet run -c Release --base $BaseResultPath --diff $DiffResultPath --threshold $Threshold "$runArgs" + } + finally { + $OFS = $savedOFS + Pop-Location + } +} + +Export-ModuleMember -Function 'Start-Benchmarking', 'Compare-BenchmarkResult' diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index 390b461fb90..5c903f53745 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -147,21 +147,32 @@ Describe "ConsoleHost unit tests" -tags "Feature" { } It "-File should be default parameter" { - Set-Content -Path $testdrive/test -Value "'hello'" - $observed = & $powershell -NoProfile $testdrive/test + Set-Content -Path $testdrive/test.ps1 -Value "'hello'" + $observed = & $powershell -NoProfile $testdrive/test.ps1 $observed | Should -Be "hello" } - It "-File accepts scripts with and without .ps1 extension: " -TestCases @( - @{Filename="test.ps1"}, - @{Filename="test"} - ) { - param($Filename) + It "-File accepts scripts with .ps1 extension" { + $Filename = 'test.ps1' + Set-Content -Path $testdrive/$Filename -Value "'hello'" + $observed = & $powershell -NoProfile -File $testdrive/$Filename + $observed | Should -Be "hello" + } + + It "-File accepts scripts without .ps1 extension to support shebang" -Skip:($IsWindows) { + $Filename = 'test.xxx' Set-Content -Path $testdrive/$Filename -Value "'hello'" $observed = & $powershell -NoProfile -File $testdrive/$Filename $observed | Should -Be "hello" } + It "-File should fail for script without .ps1 extension" -Skip:(!$IsWindows) { + $Filename = 'test.xxx' + Set-Content -Path $testdrive/$Filename -Value "'hello'" + & $powershell -NoProfile -File $testdrive/$Filename > $null + $LASTEXITCODE | Should -Be 64 + } + It "-File should pass additional arguments to script" { Set-Content -Path $testdrive/script.ps1 -Value 'foreach($arg in $args){$arg}' $observed = & $powershell -NoProfile $testdrive/script.ps1 foo bar @@ -208,11 +219,8 @@ Describe "ConsoleHost unit tests" -tags "Feature" { $observed | Should -Be $BoolValue } - It "-File '' should return exit code from script" -TestCases @( - @{Filename = "test.ps1"}, - @{Filename = "test"} - ) { - param($Filename) + It "-File should return exit code from script" { + $Filename = 'test.ps1' Set-Content -Path $testdrive/$Filename -Value 'exit 123' & $powershell $testdrive/$Filename $LASTEXITCODE | Should -Be 123 @@ -235,11 +243,16 @@ Describe "ConsoleHost unit tests" -tags "Feature" { $observed | Should -BeExactly "h-llo" } - It "Empty command should fail" { - & $powershell -noprofile -c '' + It "Missing command should fail" { + & $powershell -noprofile -c $LASTEXITCODE | Should -Be 64 } + It "Empty space command should succeed on non-Windows" -skip:$IsWindows { + & $powershell -noprofile -c '' | Should -BeNullOrEmpty + $LASTEXITCODE | Should -Be 0 + } + It "Whitespace command should succeed" { & $powershell -noprofile -c ' ' | Should -BeNullOrEmpty $LASTEXITCODE | Should -Be 0 @@ -270,7 +283,7 @@ export $envVarName='$guid' } It "Doesn't run the login profile when -Login not used" { - $result = & $powershell -Command "`$env:$envVarName" + $result = & $powershell -noprofile -Command "`$env:$envVarName" $result | Should -BeNullOrEmpty $LASTEXITCODE | Should -Be 0 } @@ -369,7 +382,20 @@ export $envVarName='$guid' } Context "Pipe to/from powershell" { - $p = [PSCustomObject]@{X=10;Y=20} + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + + $p = [PSCustomObject]@{X=10;Y=20} + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } It "xml input" { $p | & $powershell -noprofile { $input | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should -Be 30 @@ -646,7 +672,7 @@ namespace StackTest { } It "powershell starts if PATH is not set" -Skip:($IsWindows) { - bash -c "unset PATH;$powershell -c '1+1'" | Should -BeExactly 2 + bash -c "unset PATH;$powershell -nop -c '1+1'" | Should -BeExactly 2 } } @@ -1003,3 +1029,38 @@ Describe 'Console host name' -Tag CI { (Get-Process -Id $PID).Name | Should -BeExactly 'pwsh' } } + +Describe 'TERM env var' -Tag CI { + BeforeAll { + $oldTERM = $env:TERM + } + + AfterAll { + $env:TERM = $oldTERM + } + + It 'TERM = "dumb"' { + $env:TERM = 'dumb' + pwsh -noprofile -command '$Host.UI.SupportsVirtualTerminal' | Should -BeExactly 'False' + } + + It 'TERM = ""' -TestCases @( + @{ term = "xterm-mono" } + @{ term = "xtermm" } + ) { + param ($term) + + $env:TERM = $term + pwsh -noprofile -command '$PSStyle.OutputRendering' | Should -BeExactly 'PlainText' + } + + It 'NO_COLOR' { + try { + $env:NO_COLOR = 1 + pwsh -noprofile -command '$PSStyle.OutputRendering' | Should -BeExactly 'PlainText' + } + finally { + $env:NO_COLOR = $null + } + } +} diff --git a/test/powershell/Host/HostUtilities.Tests.ps1 b/test/powershell/Host/HostUtilities.Tests.ps1 index 6c791b5c446..b5c65af97e6 100644 --- a/test/powershell/Host/HostUtilities.Tests.ps1 +++ b/test/powershell/Host/HostUtilities.Tests.ps1 @@ -58,3 +58,23 @@ Describe "InvokeOnRunspace method on remote runspace" -tags "Feature","RequireAd $results[0] | Should -Be "Hello!" } } + +Describe 'PromptForCredential' -Tags "CI" { + BeforeAll { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('NoPromptForPassword', $true) + } + + AfterAll { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('NoPromptForPassword', $false) + } + + It 'Should accept no targetname' { + $out = $Host.UI.PromptForCredential('caption','message','myUser',$null) + $out.UserName | Should -BeExactly 'myUser' + } + + It 'Should accept targetname as domain' { + $out = $Host.UI.PromptForCredential('caption','message','myUser','myDomain') + $out.UserName | Should -BeExactly 'myDomain\myUser' + } +} diff --git a/test/powershell/Host/Logging.Tests.ps1 b/test/powershell/Host/Logging.Tests.ps1 index 5159d46551f..5250d2ef5ae 100644 --- a/test/powershell/Host/Logging.Tests.ps1 +++ b/test/powershell/Host/Logging.Tests.ps1 @@ -248,12 +248,15 @@ $PID It 'Verifies logging level filtering works' -Skip:(!$IsSupportedEnvironment) { $configFile = WriteLogSettings -LogId $logId -LogLevel Warning - & $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null' + $result = & $powershell -NoProfile -SettingsFile $configFile -Command '$PID' + $result | Should -Not -BeNullOrEmpty # by default, PowerShell only logs informational events on startup. With Level = Warning, nothing should - # have been logged. - $items = Get-PSSysLog -Path $SyslogFile -Id $logId -Tail 100 -TotalCount 1 - $items | Should -Be $null + # have been logged. We'll collect all the syslog entries and look for $PID (there should be none). + $items = Get-PSSysLog -Path $SyslogFile + @($items).Count | Should -BeGreaterThan 0 + $logs = $items | Where-Object { $_.ProcessId -eq $result } + $logs | Should -BeNullOrEmpty } } diff --git a/test/powershell/Host/PSVersionTable.Tests.ps1 b/test/powershell/Host/PSVersionTable.Tests.ps1 index 2ef9fb30a23..e691b7661be 100644 --- a/test/powershell/Host/PSVersionTable.Tests.ps1 +++ b/test/powershell/Host/PSVersionTable.Tests.ps1 @@ -23,7 +23,7 @@ Describe "PSVersionTable" -Tags "CI" { $unexpectectGitCommitIdPattern = $fullVersionPattern } - $powerShellVersions = "1.0", "2.0", "3.0", "4.0", "5.0", "5.1", "6.0", "6.1", "6.2", "7.0", "7.1" + $powerShellVersions = "1.0", "2.0", "3.0", "4.0", "5.0", "5.1", "6.0", "6.1", "6.2", "7.0", "7.1", "7.2" $powerShellCompatibleVersions = $PSVersionTable.PSCompatibleVersions | ForEach-Object {$_.ToString(2).SubString(0,3)} } diff --git a/test/powershell/Host/Startup.Tests.ps1 b/test/powershell/Host/Startup.Tests.ps1 index 05b2534bc9a..bb775d0ca2f 100644 --- a/test/powershell/Host/Startup.Tests.ps1 +++ b/test/powershell/Host/Startup.Tests.ps1 @@ -22,12 +22,10 @@ Describe "Validate start of console host" -Tag CI { 'System.ComponentModel.TypeConverter.dll' 'System.Console.dll' 'System.Data.Common.dll' - 'System.Diagnostics.FileVersionInfo.dll' 'System.Diagnostics.Process.dll' 'System.Diagnostics.TraceSource.dll' 'System.Diagnostics.Tracing.dll' 'System.IO.FileSystem.AccessControl.dll' - 'System.IO.FileSystem.dll' 'System.IO.FileSystem.DriveInfo.dll' 'System.IO.Pipes.dll' 'System.Linq.dll' @@ -53,6 +51,7 @@ Describe "Validate start of console host" -Tag CI { 'System.Runtime.Serialization.Primitives.dll' 'System.Security.AccessControl.dll' 'System.Security.Cryptography.Encoding.dll' + 'System.Security.Cryptography.Primitives.dll' 'System.Security.Cryptography.X509Certificates.dll' 'System.Security.Principal.Windows.dll' 'System.Text.Encoding.Extensions.dll' @@ -70,16 +69,12 @@ Describe "Validate start of console host" -Tag CI { 'System.DirectoryServices.dll' 'System.Management.dll' 'System.Security.Claims.dll' - 'System.Security.Cryptography.Primitives.dll' 'System.Threading.Overlapped.dll' ) } else { $allowedAssemblies += @( - 'System.Collections.Immutable.dll' - 'System.IO.MemoryMappedFiles.dll' 'System.Net.Sockets.dll' - 'System.Reflection.Metadata.dll' ) } @@ -93,7 +88,7 @@ Describe "Validate start of console host" -Tag CI { Remove-Item $profileDataFile -Force } - $loadedAssemblies = & "$PSHOME/pwsh" -noprofile -command '([System.AppDomain]::CurrentDomain.GetAssemblies()).manifestmodule | Where-Object { $_.Name -notlike ""<*>"" } | ForEach-Object { $_.Name }' + $loadedAssemblies = & "$PSHOME/pwsh" -noprofile -command '([System.AppDomain]::CurrentDomain.GetAssemblies()).manifestmodule | Where-Object { $_.Name -notlike "<*>" } | ForEach-Object { $_.Name }' } It "No new assemblies are loaded" { diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index c42f30e510a..2674a74a21a 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -301,6 +301,111 @@ Describe "TabCompletion" -Tags CI { $actual | Should -BeExactly $expected } + Context "Format cmdlet's View paramter completion" { + BeforeAll { + $viewDefinition = @' + + + + + R A M + + System.Diagnostics.Process + + + + + + 40 + Center + + + + 40 + Center + + + + 40 + Center + + + + + + + Center + Name + + + Center + PagedMemorySize + + + Center + PeakWorkingSet + + + + + + + + +'@ + + $tempViewFile = Join-Path -Path $TestDrive -ChildPath 'processViewDefinition.ps1xml' + Set-Content -LiteralPath $tempViewFile -Value $viewDefinition -Force + + $ps = [PowerShell]::Create() + $null = $ps.AddScript("Update-FormatData -AppendPath $tempViewFile") + $ps.Invoke() + $ps.HadErrors | Should -BeFalse + $ps.Commands.Clear() + + Remove-Item -LiteralPath $tempViewFile -Force -ErrorAction SilentlyContinue + } + + It 'Should complete Get-ChildItem | -View' -TestCases ( + @{ cmd = 'Format-Table'; expected = "children childrenWithHardlink$(if (!$IsWindows) { ' childrenWithUnixStat' })" }, + @{ cmd = 'Format-List'; expected = 'children' }, + @{ cmd = 'Format-Wide'; expected = 'children' }, + @{ cmd = 'Format-Custom'; expected = '' } + ) { + param($cmd, $expected) + + # The completion is based on OutputTypeAttribute() of the cmdlet. + $res = TabExpansion2 -inputScript "Get-ChildItem | $cmd -View " -cursorColumn "Get-ChildItem | $cmd -View ".Length + $completionText = $res.CompletionMatches.CompletionText | Sort-Object + $completionText -join ' ' | Should -BeExactly $expected + } + + It 'Should complete $processList = Get-Process; $processList | ' -TestCases ( + @{ cmd = 'Format-Table -View '; expected = "'R A M'", "Priority", "process", "ProcessModule", "ProcessWithUserName", "StartTime" }, + @{ cmd = 'Format-List -View '; expected = '' }, + @{ cmd = 'Format-Wide -View '; expected = 'process' }, + @{ cmd = 'Format-Custom -View '; expected = '' }, + @{ cmd = 'Format-Table -View S'; expected = "StartTime" }, + @{ cmd = "Format-Table -View 'S"; expected = "'StartTime'" }, + @{ cmd = "Format-Table -View R"; expected = "'R A M'" } + ) { + param($cmd, $expected) + + $null = $ps.AddScript({ + param ($cmd) + $processList = Get-Process + $res = TabExpansion2 -inputScript "`$processList | $cmd" -cursorColumn "`$processList | $cmd".Length + $completionText = $res.CompletionMatches.CompletionText | Sort-Object + $completionText + }).AddArgument($cmd) + + $result = $ps.Invoke() + $ps.Commands.Clear() + $expected = ($expected | Sort-Object) -join ' ' + $result -join ' ' | Should -BeExactly $expected + } + } + Context NativeCommand { BeforeAll { $nativeCommand = (Get-Command -CommandType Application -TotalCount 1).Name @@ -908,6 +1013,75 @@ Describe "TabCompletion" -Tags CI { $res.CompletionMatches[0].CompletionText | Should -BeExactly "Test history completion" } + It "Test #requires parameter completion" { + $res = TabExpansion2 -inputScript "#requires -" -cursorColumn 11 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches[0].CompletionText | Should -BeExactly "Modules" + } + + It "Test #requires parameter value completion" { + $res = TabExpansion2 -inputScript "#requires -PSEdition " -cursorColumn 21 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches[0].CompletionText | Should -BeExactly "Core" + } + + It "Test no completion after #requires -RunAsAdministrator" { + $res = TabExpansion2 -inputScript "#requires -RunAsAdministrator -" -cursorColumn 31 + $res.CompletionMatches | Should -HaveCount 0 + } + + It "Test no suggestions for already existing parameters in #requires" { + $res = TabExpansion2 -inputScript "#requires -Modules -" -cursorColumn 20 + $res.CompletionMatches.CompletionText | Should -Not -Contain "Modules" + } + + It "Test module completion in #requires without quotes" { + $res = TabExpansion2 -inputScript "#requires -Modules P" -cursorColumn 20 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Contain "Pester" + } + + It "Test module completion in #requires with quotes" { + $res = TabExpansion2 -inputScript '#requires -Modules "' -cursorColumn 20 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Contain "Pester" + } + + It "Test module completion in #requires with multiple modules" { + $res = TabExpansion2 -inputScript "#requires -Modules Pester," -cursorColumn 26 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Contain "Pester" + } + + It "Test hashtable key completion in #requires statement for modules" { + $res = TabExpansion2 -inputScript "#requires -Modules @{" -cursorColumn 21 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches[0].CompletionText | Should -BeExactly "GUID" + } + + It "Test no suggestions for already existing hashtable keys in #requires statement for modules" { + $res = TabExpansion2 -inputScript '#requires -Modules @{ModuleName="Pester";' -cursorColumn 41 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Not -Contain "ModuleName" + } + + It "Test no suggestions for mutually exclusive hashtable keys in #requires statement for modules" { + $res = TabExpansion2 -inputScript '#requires -Modules @{ModuleName="Pester";RequiredVersion="1.0";' -cursorColumn 63 + $res.CompletionMatches.CompletionText | Should -BeExactly "GUID" + } + + It "Test no suggestions for RequiredVersion key in #requires statement when ModuleVersion is specified" { + $res = TabExpansion2 -inputScript '#requires -Modules @{ModuleName="Pester";ModuleVersion="1.0";' -cursorColumn 61 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Not -Contain "RequiredVersion" + } + + It "Test module completion in #requires statement for hashtables" { + $res = TabExpansion2 -inputScript '#requires -Modules @{ModuleName="p' -cursorColumn 34 + $res.CompletionMatches.Count | Should -BeGreaterThan 0 + $res.CompletionMatches.CompletionText | Should -Contain "Pester" + } + It "Test Attribute member completion" { $inputStr = "function bar { [parameter(]param() }" $res = TabExpansion2 -inputScript $inputStr -cursorColumn ($inputStr.IndexOf('(') + 1) @@ -915,6 +1089,13 @@ Describe "TabCompletion" -Tags CI { $entry = $res.CompletionMatches | Where-Object CompletionText -EQ "Position" $entry.CompletionText | Should -BeExactly "Position" } + It "Test Attribute member completion multiple members" { + $inputStr = "function bar { [parameter(Position,]param() }" + $res = TabExpansion2 -inputScript $inputStr -cursorColumn ($inputStr.IndexOf(',') + 1) + $res.CompletionMatches | Should -HaveCount 10 + $entry = $res.CompletionMatches | Where-Object CompletionText -EQ "Mandatory" + $entry.CompletionText | Should -BeExactly "Mandatory" + } It "Test completion with line continuation" { $inputStr = @' @@ -946,6 +1127,13 @@ dir -Recurse ` $res.CompletionMatches | Should -HaveCount 4 [string]::Join(',', ($res.CompletionMatches.completiontext | Sort-Object)) | Should -BeExactly "-wa,-Wait,-WarningAction,-WarningVariable" } + + It "Test completion with splatted variable" { + $inputStr = 'Get-Content @Splat -P' + $res = TabExpansion2 -inputScript $inputStr -cursorColumn $inputStr.Length + $res.CompletionMatches | Should -HaveCount 4 + [string]::Join(',', ($res.CompletionMatches.completiontext | Sort-Object)) | Should -BeExactly "-Path,-PipelineVariable,-PSPath,-pv" + } } Context "Module completion for 'using module'" { @@ -1295,6 +1483,201 @@ dir -Recurse ` $res.CompletionMatches | Should -HaveCount $expectedCompletions $res.CompletionMatches[0].CompletionText | Should -BeExactly 'about_Splatting' } + It 'Should complete about help topic regardless of culture' { + try + { + ## Save original culture and temporarily set it to da-DK because there's no localized help for da-DK. + $OriginalCulture = [cultureinfo]::CurrentCulture + [cultureinfo]::CurrentCulture="da-DK" + + $res = TabExpansion2 -inputScript 'get-help about_spla' -cursorColumn 'get-help about_spla'.Length + $res.CompletionMatches | Should -HaveCount 1 + $res.CompletionMatches[0].CompletionText | Should -BeExactly 'about_Splatting' + } + finally + { + [cultureinfo]::CurrentCulture = $OriginalCulture + } + } + It '' -TestCases @( + @{ + Intent = 'Complete help keywords with minimum input' + Expected = @( + 'COMPONENT' + 'DESCRIPTION' + 'EXAMPLE' + 'EXTERNALHELP' + 'FORWARDHELPCATEGORY' + 'FORWARDHELPTARGETNAME' + 'FUNCTIONALITY' + 'INPUTS' + 'LINK' + 'NOTES' + 'OUTPUTS' + 'PARAMETER' + 'REMOTEHELPRUNSPACE' + 'ROLE' + 'SYNOPSIS' + ) + TestString = @' +<# +.^ +#> +'@ + } + @{ + Intent = 'Complete help keywords without duplicates' + Expected = $null + TestString = @' +<# +.SYNOPSIS +.S^ +#> +'@ + } + @{ + Intent = 'Complete help keywords with allowed duplicates' + Expected = 'PARAMETER' + TestString = @' +<# +.PARAMETER +.Paramet^ +#> +'@ + } + @{ + Intent = 'Complete help keyword FORWARDHELPTARGETNAME argument' + Expected = 'Get-ChildItem' + TestString = @' +<# +.FORWARDHELPTARGETNAME Get-Child^ +#> +'@ + } + @{ + Intent = 'Complete help keyword FORWARDHELPCATEGORY argument' + Expected = 'Cmdlet' + TestString = @' +<# +.FORWARDHELPCATEGORY C^ +#> +'@ + } + @{ + Intent = 'Complete help keyword REMOTEHELPRUNSPACE argument' + Expected = 'PSEdition' + TestString = @' +<# +.REMOTEHELPRUNSPACE PSEditi^ +#> +'@ + } + @{ + Intent = 'Complete help keyword EXTERNALHELP argument' + Expected = Join-Path $PSHOME "pwsh.xml" + TestString = @" +<# +.EXTERNALHELP $PSHOME\pwsh.^ +#> +"@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for script' + Expected = 'Param1' + TestString = @' +<# +.PARAMETER ^ +#> +param($Param1) +'@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for function with help inside' + Expected = 'param2' + TestString = @' +function MyFunction ($param1, $param2) +{ +<# +.PARAMETER param1 +.PARAMETER ^ +#> +} +'@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for function with help before it' + Expected = 'param1','param2' + TestString = @' +<# +.PARAMETER ^ +#> +function MyFunction ($param1, $param2) +{ +} +'@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for advanced function with help inside' + Expected = 'Param1' + TestString = @' +function Verb-Noun +{ +<# +.PARAMETER ^ +#> + [CmdletBinding()] + Param + ( + $Param1 + ) + + Begin + { + } + Process + { + } + End + { + } +} +'@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for nested function with help before it' + Expected = 'param3','param4' + TestString = @' +function MyFunction ($param1, $param2) +{ + <# + .PARAMETER ^ + #> + function MyFunction2 ($param3, $param4) + { + } +} +'@ + } + @{ + Intent = 'Not complete help keyword PARAMETER argument if following function is too far away' + Expected = $null + TestString = @' +<# +.PARAMETER ^ +#> + + +function MyFunction ($param1, $param2) +{ +} +'@ + } + ){ + param($Expected, $TestString) + $CursorIndex = $TestString.IndexOf('^') + $res = TabExpansion2 -cursorColumn $CursorIndex -inputScript $TestString.Remove($CursorIndex, 1) + $res.CompletionMatches.CompletionText | Should -BeExactly $Expected + } } } diff --git a/test/powershell/Installer/WindowsInstaller.Tests.ps1 b/test/powershell/Installer/WindowsInstaller.Tests.ps1 index 76cca8151de..66bd08e74f5 100644 --- a/test/powershell/Installer/WindowsInstaller.Tests.ps1 +++ b/test/powershell/Installer/WindowsInstaller.Tests.ps1 @@ -14,7 +14,7 @@ Describe "Windows Installer" -Tags "Scenario" { } It "WiX (Windows Installer XML) file contains pre-requisites link $preRequisitesLink" -Skip:$skipTest { - $wixProductFile = Join-Path -Path $PSScriptRoot -ChildPath "..\..\..\assets\Product.wxs" + $wixProductFile = Join-Path -Path $PSScriptRoot -ChildPath "..\..\..\assets\wix\Product.wxs" (Get-Content $wixProductFile -Raw).Contains($preRequisitesLink) | Should -BeTrue } diff --git a/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 b/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 index 9bef836e19b..4e5668071d7 100644 --- a/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 +++ b/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 @@ -682,6 +682,19 @@ Describe 'ScriptScopeAccessFromClassMethod' -Tags "CI" { } Describe 'Hidden Members Test ' -Tags "CI" { + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + class C1 { [int]$visibleX diff --git a/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 b/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 index 59d7039898a..074351d3414 100644 --- a/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 +++ b/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 @@ -11,6 +11,12 @@ Describe "Replace Operator" -Tags CI { $res | Should -BeExactly "image.jpg" } + It "Replace operator can convert an substitution object to string" { + $substitution = Get-Process -Id $pid + $res = "!3!" -replace "3",$substitution + $res | Should -BeExactly "!System.Diagnostics.Process (pwsh)!" + } + It "Replace operator can be case-insensitive and case-sensitive" { $res = "book" -replace "B","C" $res | Should -BeExactly "Cook" @@ -29,6 +35,18 @@ Describe "Replace Operator" -Tags CI { $res = "PowerPoint" -replace "Point" $res | Should -BeExactly "Power" } + + It "Replace operator can take an enumerable as first argument, a mandatory pattern, and an optional substitution" { + $res = "PowerPoint1","PowerPoint2" -replace "Point","Shell" + $res.Count | Should -Be 2 + $res[0] | Should -BeExactly "PowerShell1" + $res[1] | Should -BeExactly "PowerShell2" + + $res = "PowerPoint1","PowerPoint2" -replace "Point" + $res.Count | Should -Be 2 + $res[0] | Should -BeExactly "Power1" + $res[1] | Should -BeExactly "Power2" + } } Context "Replace operator substitutions" { @@ -67,24 +85,13 @@ Describe "Replace Operator" -Tags CI { Describe "Culture-invariance tests for -split and -replace" -Tags CI { BeforeAll { - $skipTest = -not [ExperimentalFeature]::IsEnabled("PSCultureInvariantReplaceOperator") - if ($skipTest) { - Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSCultureInvariantReplaceOperator' to be enabled." -Verbose - $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() - $PSDefaultParameterValues["it:skip"] = $true - } else { - $prevCulture = [cultureinfo]::CurrentCulture - # The French culture uses "," as the decimal mark. - [cultureinfo]::CurrentCulture = 'fr' - } + $prevCulture = [cultureinfo]::CurrentCulture + # The French culture uses "," as the decimal mark. + [cultureinfo]::CurrentCulture = 'fr' } AfterAll { - if ($skipTest) { - $global:PSDefaultParameterValues = $originalDefaultParameterValues - } else { - [cultureinfo]::CurrentCulture = $prevCulture - } + [cultureinfo]::CurrentCulture = $prevCulture } It "-split: LHS stringification is not culture-sensitive" { diff --git a/test/powershell/Language/Parser/ExtensibleCompletion.Tests.ps1 b/test/powershell/Language/Parser/ExtensibleCompletion.Tests.ps1 index 3c9edd43915..3514f389718 100644 --- a/test/powershell/Language/Parser/ExtensibleCompletion.Tests.ps1 +++ b/test/powershell/Language/Parser/ExtensibleCompletion.Tests.ps1 @@ -175,6 +175,77 @@ function TestFunction ) } + +class NumberCompleter : IArgumentCompleter +{ + + [int] $From + [int] $To + [int] $Step + + NumberCompleter([int] $from, [int] $to, [int] $step) + { + if ($from -gt $to) { + throw [ArgumentOutOfRangeException]::new("from") + } + $this.From = $from + $this.To = $to + $this.Step = if($step -lt 1) { 1 } else { $step } + } + + [IEnumerable[CompletionResult]] CompleteArgument( + [string] $CommandName, + [string] $parameterName, + [string] $wordToComplete, + [CommandAst] $commandAst, + [IDictionary] $fakeBoundParameters) + { + $resultList = [List[CompletionResult]]::new() + $local:to = $this.To + for ($i = $this.From; $i -le $to; $i += $this.Step) { + if ($i.ToString().StartsWith($wordToComplete, [System.StringComparison]::Ordinal)) { + $num = $i.ToString() + $resultList.Add([CompletionResult]::new($num, $num, "ParameterValue", $num)) + } + } + + return $resultList + } +} + +class NumberCompletionAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory +{ + [int] $From + [int] $To + [int] $Step + + NumberCompletionAttribute([int] $from, [int] $to) + { + $this.From = $from + $this.To = $to + $this.Step = 1 + } + + [IArgumentCompleter] Create() { return [NumberCompleter]::new($this.From, $this.To, $this.Step) } +} + +function FactoryCompletionAdd { + param( + [NumberCompletion(0, 50, Step = 5)] + [int] $Number + ) +} + +Describe "Factory based extensible completion" -Tags "CI" { + @{ + ExpectedResults = @( + @{CompletionText = "5"; ResultType = "ParameterValue" } + @{CompletionText = "50"; ResultType = "ParameterValue" } + ) + TestInput = 'FactoryCompletionAdd -Number 5' + } | Get-CompletionTestCaseData | Test-Completions +} + Describe "Script block based extensible completion" -Tags "CI" { @{ ExpectedResults = @( diff --git a/test/powershell/Language/Parser/ParameterBinding.Tests.ps1 b/test/powershell/Language/Parser/ParameterBinding.Tests.ps1 index 7fd26912ead..493ea9083a0 100644 --- a/test/powershell/Language/Parser/ParameterBinding.Tests.ps1 +++ b/test/powershell/Language/Parser/ParameterBinding.Tests.ps1 @@ -168,7 +168,13 @@ Describe "Custom type conversion in parameter binding" -Tags 'Feature' { } } '@ - $asmFile = [System.IO.Path]::GetTempFileName() + ".dll" + if ($IsWindows) { + $asmFile = [System.IO.Path]::GetTempFileName() + ".dll" + } + else { + $asmFile = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName() + ".dll")) + } + Add-Type -TypeDefinition $code -OutputAssembly $asmFile ## Helper function to execute script diff --git a/test/powershell/Language/Parser/Parser.Tests.ps1 b/test/powershell/Language/Parser/Parser.Tests.ps1 index b3163ba2f27..0f8a6c74726 100644 --- a/test/powershell/Language/Parser/Parser.Tests.ps1 +++ b/test/powershell/Language/Parser/Parser.Tests.ps1 @@ -864,7 +864,10 @@ foo``u{2195}abc @{ Script = "0x0"; ExpectedValue = "0"; ExpectedType = [int] } @{ Script = "0x12"; ExpectedValue = "18"; ExpectedType = [int] } @{ Script = "-0x12"; ExpectedValue = "-18"; ExpectedType = [int] } - @{ Script = "0x80000000"; ExpectedValue = $([int32]::MinValue); ExpectedType = [int] } + + # Disabling this because https://github.com/dotnet/runtime/issues/54251 + # @{ Script = "0x80000000"; ExpectedValue = $([int32]::MinValue); ExpectedType = [int] } + @{ Script = "0x7fffffff"; ExpectedValue = $([int32]::MaxValue); ExpectedType = [int] } @{ Script = "0x100000000"; ExpectedValue = [int64]0x100000000; ExpectedType = [long] } @{ Script = "0xFF"; ExpectedValue = "255"; ExpectedType = [int] } @@ -1047,7 +1050,10 @@ foo``u{2195}abc @{ Script = "0xFFu"; ExpectedValue = "255"; ExpectedType = [uint] } @{ Script = "0xFFFFu"; ExpectedValue = "65535"; ExpectedType = [uint] } @{ Script = "0xFFFFFFu"; ExpectedValue = "16777215"; ExpectedType = [uint] } - @{ Script = "0xFFFFFFFFu"; ExpectedValue = "$([uint]::MaxValue)"; ExpectedType = [uint] } + + # Disabling this because https://github.com/dotnet/runtime/issues/54251 + # @{ Script = "0xFFFFFFFFu"; ExpectedValue = "$([uint]::MaxValue)"; ExpectedType = [uint] } + @{ Script = "0xFFFFFFFFFFu"; ExpectedValue = "1099511627775"; ExpectedType = [ulong] } @{ Script = "0xFFFFFFFFFFFFu"; ExpectedValue = "281474976710655"; ExpectedType = [ulong] } @{ Script = "0xFFFFFFFFFFFFFFu"; ExpectedValue = "72057594037927935"; ExpectedType = [ulong] } @@ -1057,7 +1063,10 @@ foo``u{2195}abc @{ Script = "0b10u"; ExpectedValue = "2"; ExpectedType = [uint] } @{ Script = "0b11111111u"; ExpectedValue = "255"; ExpectedType = [uint] } @{ Script = "0b1111111111111111u"; ExpectedValue = "65535"; ExpectedType = [uint] } - @{ Script = "0b11111111111111111111111111111111u"; ExpectedValue = "4294967295"; ExpectedType = [uint] } + + # Disabling this because https://github.com/dotnet/runtime/issues/54251 + # @{ Script = "0b11111111111111111111111111111111u"; ExpectedValue = "4294967295"; ExpectedType = [uint] } + @{ Script = "0b1111111111111111111111111111111111111111111111111111111111111111u"; ExpectedValue = "18446744073709551615"; ExpectedType = [ulong] } #Multipliers @{ Script = "1ukb"; ExpectedValue = "1024"; ExpectedType = [uint] } diff --git a/test/powershell/Language/Scripting/Adapter.Tests.ps1 b/test/powershell/Language/Scripting/Adapter.Tests.ps1 new file mode 100644 index 00000000000..db681192c4e --- /dev/null +++ b/test/powershell/Language/Scripting/Adapter.Tests.ps1 @@ -0,0 +1,110 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe "Interface static members" -Tags "CI" { + BeforeAll { + $testType = "InterfaceStaticMemberTest.ITest" -as [Type] + if (-not $testType) { + Add-Type -TypeDefinition @' + using System; + + namespace InterfaceStaticMemberTest { + public interface ITest { + public const int MyConst = 17; + + public static string Type = "ITest-Type"; + public static string Name => "Joe"; + public static string GetPath() => "Path"; + public int GetAge(); + public int GetId(); + } + + public class Foo : ITest { + int ITest.GetId() { return 100; } + int ITest.GetAge() { return 2; } + } + + public class Zoo : Foo { + public static string Type = "Zoo-Type"; + } + } +'@ + } + } + + It "Access static/const members on the interface type" { + [InterfaceStaticMemberTest.ITest]::MyConst | Should -Be 17 + [InterfaceStaticMemberTest.ITest]::Type | Should -Be "ITest-Type" + [InterfaceStaticMemberTest.ITest]::Name | Should -Be "Joe" + [InterfaceStaticMemberTest.ITest]::GetPath() | Should -Be "Path" + + $type = [InterfaceStaticMemberTest.ITest] + $type::MyConst | Should -Be 17 + $type::Type | Should -Be "ITest-Type" + $type::Name | Should -Be "Joe" + $type::GetPath() | Should -Be "Path" + + { [InterfaceStaticMemberTest.ITest]::Name = 'Jane' } | Should -Throw -ErrorId 'PropertyAssignmentException' + { $type::Name = 'Jane' } | Should -Throw -ErrorId 'PropertyAssignmentException' + } + + It "Access interface static/const members on the implementation type" { + [InterfaceStaticMemberTest.Foo]::MyConst | Should -Be 17 + [InterfaceStaticMemberTest.Foo]::Type | Should -Be "ITest-Type" + [InterfaceStaticMemberTest.Foo]::Name | Should -Be "Joe" + [InterfaceStaticMemberTest.Foo]::GetPath() | Should -Be "Path" + [InterfaceStaticMemberTest.Foo]::get_Name() | Should -Be "Joe" + + $type = [InterfaceStaticMemberTest.Foo] + $type::MyConst | Should -Be 17 + $type::Type | Should -Be "ITest-Type" + $type::Name | Should -Be "Joe" + $type::GetPath() | Should -Be "Path" + $type::get_Name() | Should -Be "Joe" + + { [InterfaceStaticMemberTest.Foo]::Name = 'Jane' } | Should -Throw -ErrorId 'PropertyAssignmentException' + { $type::Name = 'Jane' } | Should -Throw -ErrorId 'PropertyAssignmentException' + } + + It "Static field with the same name on the implementation type overrides the one from the interface" { + [InterfaceStaticMemberTest.Zoo]::Type | Should -Be "Zoo-Type" + + $type = [InterfaceStaticMemberTest.Zoo] + $type::Type | Should -Be "Zoo-Type" + + $nameMember = $type | Get-Member -Static -Name Name + $nameMember | Should -Not -BeNullOrEmpty + $nameMember.Name | Should -Be "Name" + $nameMember.MemberType | Should -Be "Property" + + $getNameMember = $type | Get-Member -Static -Name 'get_Name' + $getNameMember | Should -BeNullOrEmpty + + $getNameMember = $type | Get-Member -Static -Name 'get_Name' -Force + $getNameMember | Should -Not -BeNullOrEmpty + $getNameMember.Name | Should -Be "get_Name" + $getNameMember.MemberType | Should -Be "Method" + + $type::Name | Should -Be "Joe" + $type::get_Name() | Should -Be "Joe" + } + + It "Explicitly implemented interface members are visible/accessible by default" { + $obj = [InterfaceStaticMemberTest.Zoo]::new() + + $ageMember = $obj | Get-Member -Name GetAge + $ageMember | Should -Not -BeNullOrEmpty + $ageMember.Name | Should -Be "GetAge" + $ageMember.MemberType | Should -Be "Method" + $ageMember.Definition | Should -Be "int ITest.GetAge()" + + $idMember = $obj | Get-Member -Name GetId + $idMember | Should -Not -BeNullOrEmpty + $idMember.Name | Should -Be "GetId" + $idMember.MemberType | Should -Be "Method" + $idMember.Definition | Should -Be "int ITest.GetId()" + + $obj.GetAge() | Should -Be 2 + $obj.GetId() | Should -Be 100 + } +} diff --git a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 new file mode 100644 index 00000000000..fe2ed803ecf --- /dev/null +++ b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 @@ -0,0 +1,470 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe 'Command error handling in general' -Tag 'CI' { + + BeforeAll { + $pwsh = [PowerShell]::Create() + $pwsh.AddScript(@' + + function ThrowTerminatingError { + [CmdletBinding()] + param() + + $ex = [System.ArgumentException]::new('terminating-exception') + $er = [System.Management.Automation.ErrorRecord]::new($ex, 'ThrowTerminatingError:error', 'InvalidArgument', $null) + $PSCmdlet.ThrowTerminatingError($er) + + Write-Verbose -Verbose "verbose-message" + } + + function ErrorActionStop { + [CmdletBinding()] + param() + + Get-Command NonExist -ErrorAction Stop + Write-Verbose -Verbose "verbose-message" + } + + function ThrowException { + [CmdletBinding()] + param() + + throw 'throw-exception' + Write-Verbose -Verbose "verbose-message" + } + + function WriteErrorAPI { + [CmdletBinding()] + param() + + $ex = [System.ArgumentException]::new('arg-exception') + $er = [System.Management.Automation.ErrorRecord]::new($ex, 'WriteErrorAPI:error', 'InvalidArgument', $null) + $PSCmdlet.WriteError($er) + + Write-Verbose -Verbose "verbose-message" + } + + function WriteErrorCmdlet { + [CmdletBinding()] + param() + + Write-Error 'write-error-cmdlet' + Write-Verbose -Verbose "verbose-message" + } + + function MethodInvocationThrowException { + [CmdletBinding()] + param() + + ## This method call throws exception. + $iss = [initialsessionstate]::Create() + $iss.ImportPSModule($null) + + Write-Verbose -Verbose "verbose-message" + } + + function ExpressionThrowException { + [CmdletBinding()] + param() + + 1/0 ## throw exception. + Write-Verbose -Verbose "verbose-message" + } + +'@).Invoke() + + function RunCommand { + param( + [string] $Command, + [ValidateSet('Continue', 'Ignore', 'SilentlyContinue', 'Stop')] + [string] $ErrorAction + ) + + $pwsh.Commands.Clear() + $pwsh.Streams.ClearStreams() + $pwsh.AddCommand($command).AddParameter('ErrorAction', $ErrorAction).Invoke() + } + + function RunScript { + param([string] $Script) + + $pwsh.Commands.Clear() + $pwsh.Streams.ClearStreams() + $pwsh.AddScript($Script).Invoke() + } + + function GetLastError { + $pwsh.Commands.Clear() + $pwsh.AddCommand('Get-Error').Invoke() + } + + function ClearDollarError { + $pwsh.Commands.Clear() + $pwsh.AddScript('$Error.Clear()').Invoke() + } + } + + AfterAll { + $pwsh.Dispose() + } + + Context 'Terminating error' { + + It "'ThrowTerminatingError' should always stop execution even when the error action is ''" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ThrowTerminatingError' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException | Should -BeOfType 'System.ArgumentException' + $failure.Exception.InnerException.InnerException.Message | Should -BeExactly 'terminating-exception' + + $pwsh.Streams.Verbose | Should -HaveCount 0 + } + + It "'-ErrorAction Stop' should always stop execution even when the error action is ''" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ErrorActionStop' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.ActionPreferenceStopException' + $failure.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly 'CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand' + + $pwsh.Streams.Verbose | Should -HaveCount 0 + } + + It "'throw' statement should stop execution when running with the default error action ('Continue')" { + $failure = $null + + try { + RunCommand -Command 'ThrowException' -ErrorAction 'Continue' + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.RuntimeException' + $failure.Exception.InnerException.Message | Should -BeExactly 'throw-exception' + + $pwsh.Streams.Verbose | Should -HaveCount 0 + } + + <# The 'throw' statement is special, in that it can be suppressed by '-ErrorAction SilentlyContinue/Ignore' #> + It "'throw' statement doesn't stop execution when the error action is ''" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ThrowException' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -BeNullOrEmpty + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed 'throw' exception is not written to the error stream, not sure why but it's the current behavior. + $pwsh.Streams.Error | Should -HaveCount 0 + + ## The suppressed 'throw' exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.FullyQualifiedErrorId | Should -BeExactly 'throw-exception' + } + + It "'throw' statement should stop execution with the error action '' when it's wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { ThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.FullyQualifiedErrorId }" + + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' + } + + It "'throw' statement should stop execution with the error action '' when it's accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.FullyQualifiedErrorId; continue } ThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' + } + } + + Context 'Non-terminating error' { + + It "'WriteErrorAPI' doesn't stop execution with the default error action ('Continue')" { + RunCommand -Command 'WriteErrorAPI' -ErrorAction Continue + + $pwsh.Streams.Error | Should -HaveCount 1 + $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'arg-exception' + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' + + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'WriteErrorAPI' doesn't stop execution with the error action 'Ignore' and the error doesn't get logged in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorAPI' -ErrorAction Ignore + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -BeNullOrEmpty + } + + It "'WriteErrorAPI' doesn't stop execution with the error action 'SilentlyContinue' and the error gets logged in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorAPI' -ErrorAction SilentlyContinue + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -Not -BeNullOrEmpty + $lastErr.Exception.Message | Should -BeExactly 'arg-exception' + $lastErr.FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' + } + + It "'WriteErrorCmdlet' doesn't stop execution with the default error action ('Continue')" { + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Continue + + $pwsh.Streams.Error | Should -HaveCount 1 + $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'write-error-cmdlet' + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' + + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'WriteErrorCmdlet' doesn't stop execution with the error action 'Ignore' and the error doesn't get logged in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Ignore + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -BeNullOrEmpty + } + + It "'WriteErrorCmdlet' doesn't stop execution with the error action 'SilentlyContinue' and the error gets logged in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction SilentlyContinue + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -Not -BeNullOrEmpty + $lastErr.Exception.Message | Should -BeExactly 'write-error-cmdlet' + $lastErr.FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' + } + } + + Context 'Exception thrown from the method invocation or expression' { + + #region MethodInvocationThrowException + + It "'MethodInvocationThrowException' emits non-terminating error with the default error action ('Continue')" { + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction 'Continue' + + $pwsh.Streams.Error | Should -HaveCount 1 + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' + + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'MethodInvocationThrowException' emits no error with the error action ''" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction $ErrorAction + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' + } + + It "'MethodInvocationThrowException' emits terminating error with the error action 'Stop'" { + $failure = $null + + try { + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction Stop + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.ArgumentNullException' + + $pwsh.Streams.Verbose | Should -HaveCount 0 + } + + It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { MethodInvocationThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' + } + + It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } MethodInvocationThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' + } + + #endregion + + #region ExpressionThrowException + + It "'ExpressionThrowException' emits non-terminating error with the default error action ('Continue')" { + RunCommand -Command 'ExpressionThrowException' -ErrorAction 'Continue' + + $pwsh.Streams.Error | Should -HaveCount 1 + $pwsh.Streams.Error[0].Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' + + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'ExpressionThrowException' emits no error with the error action ''" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunCommand -Command 'ExpressionThrowException' -ErrorAction $ErrorAction + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' + } + + It "'ExpressionThrowException' emits terminating error with the error action 'Stop'" { + $failure = $null + + try { + RunCommand -Command 'ExpressionThrowException' -ErrorAction Stop + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.DivideByZeroException' + + $pwsh.Streams.Verbose | Should -HaveCount 0 + } + + It "'ExpressionThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { ExpressionThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' + } + + It "'ExpressionThrowException' emits terminating error with the error action '' when it's accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } ExpressionThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' + } + + #endregion + } +} diff --git a/test/powershell/Language/Scripting/DollarHook.Tests.ps1 b/test/powershell/Language/Scripting/DollarHook.Tests.ps1 index 86fb70306d2..198b93a1de4 100644 --- a/test/powershell/Language/Scripting/DollarHook.Tests.ps1 +++ b/test/powershell/Language/Scripting/DollarHook.Tests.ps1 @@ -85,4 +85,84 @@ Describe 'Tests for setting $? for execution success' -Tag 'CI' { $script:hookValues | Should -Be $HookResults $output | Should -Be $PipelineResults } + + It 'Sets $? correctly for single expression with redirection ''''' -TestCases @( + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" > $null; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" >> $null; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" > TESTDRIVE:\out.txt; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" >> TESTDRIVE:\out.txt; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2> $null; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>> $null; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2> TESTDRIVE:\out.txt; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>> TESTDRIVE:\out.txt; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>&1; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>&1; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>&1 > $null; Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; "b" 2>&1 > TESTDRIVE:\out.txt; Hook $?'; HookResults = $($false, $true); } + + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" > $null); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" >> $null); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" > TESTDRIVE:\out.txt); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" >> TESTDRIVE:\out.txt); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2> $null); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2>> $null); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2> TESTDRIVE:\out.txt); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2>> TESTDRIVE:\out.txt); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2>&1); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2>&1 > $null); Hook $?'; HookResults = $($false, $true); } + @{ Expression = 'Write-Error "Bad"; Hook $?; ("b" 2>&1 > TESTDRIVE:\out.txt); Hook $?'; HookResults = $($false, $true); } + ) { + param([string]$Expression, [object[]]$HookResults) + + Invoke-Expression $Expression 2>&1 >$null + + $script:hookValues | Should -Be $HookResults + } + + Context 'Validate $? with potential terminating error' { + + ## Script execution directly in Pester tests will be enclosed in try/catch by the Pester, + ## and therefore, general exceptions thrown from an expression like "1/0" will be turned + ## into a terminating exception, which will stop the execution of remaining scripts. + ## + ## For those test cases, we have to use a PowerShell instance, so as to keep the default + ## error handling behavior for the general exceptions. + + BeforeAll { + $pwsh = [powershell]::Create() + + function Invoke([string] $script) + { + $pwsh.Commands.Clear() + $pwsh.Streams.ClearStreams() + $pwsh.AddScript($script).Invoke() + } + + $root = Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid().ToString()) + $null = Invoke "New-PSDrive -Name TESTDRIVE -PSProvider FileSystem -Root $root" + } + + Afterall { + $null = Invoke "Remove-PSDrive -Name TESTDRIVE -PSProvider FileSystem -Force" + $pwsh.Dispose() + } + + It 'Sets $? correctly for single expression with redirection ''''' -TestCases @( + @{ Expression = '1/0 > $null; $?'; Result = $false; } + @{ Expression = '1/0 >> $null; $?'; Result = $false; } + @{ Expression = '1/0 > TESTDRIVE:\out.txt; $?'; Result = $false; } + @{ Expression = '1/0 >> TESTDRIVE:\out.txt; $?'; Result = $false; } + @{ Expression = '1/0 2>&1; $?'; Result = $false; } + @{ Expression = '1/0 2>&1 > $null; $?'; Result = $false; } + @{ Expression = '1/0 2>&1 > TESTDRIVE:\out.txt; $?'; Result = $false; } + + @{ Expression = '"b" > NonExistDrive:\nowhere.txt; $?'; Result = $false; } + @{ Expression = '"b" >> NonExistDrive:\nowhere.txt; $?'; Result = $false; } + @{ Expression = '"b" 2>&1 > NonExistDrive:\nowhere.txt; $?'; Result = $false; } + ) { + param([string]$Expression, $Result) + + Invoke $Expression | Should -Be $Result + } + } } diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 index 4848cd34b95..0c7b7f9d512 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 @@ -1,72 +1,277 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -Describe "Native Command Arguments" -tags "CI" { - # When passing arguments to native commands, quoted segments that contain - # spaces need to be quoted with '"' characters when they are passed to the - # native command (or to bash or sh on Linux). - # - # This test checks that the proper quoting is occuring by passing arguments - # to the testexe native command and looking at how it got the arguments. - It "Should handle quoted spaces correctly" { +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")] +param() + +Describe "Behavior is specific for each platform" -tags "CI" { + BeforeAll { + $skipTests = $EnabledExperimentalFeatures -notcontains 'PSNativeCommandArgumentPassing' + } + It "PSNativeCommandArgumentPassing is set to 'Windows' on Windows systems" -skip:(-not $IsWindows) { + $PSNativeCommandArgumentPassing | Should -Be "Windows" + } + It "PSNativeCommandArgumentPassing is set to 'Standard' on non-Windows systems" -skip:($IsWindows) { + $PSNativeCommandArgumentPassing | Should -Be "Standard" + } + It "Has proper behavior on Windows" -skip:(-not $IsWindows) { + "@echo off`nSET V1=1" > "$TESTDRIVE\script 1.cmd" + "@echo off`nSET V2=a`necho %V1%" > "$TESTDRIVE\script 2.cmd" + "@echo off`necho %V1%`necho %V2%" > "$TESTDRIVE\script 3.cmd" + $result = cmd /c """${TESTDRIVE}\script 1.cmd"" && ""${TESTDRIVE}\script 2.cmd"" && ""${TESTDRIVE}\script 3.cmd""" + $result.Count | Should -Be 3 + $result[0] | Should -Be 1 + $result[1] | Should -Be 1 + $result[2] | Should Be "a" + } + +} + +Describe "tests for multiple languages and extensions" -tags "CI" { + AfterAll { + if (-not $IsWindows -or + $EnabledExperimentalFeatures -notcontains 'PSNativeCommandArgumentPassing') { + return + } + $PSNativeCommandArgumentPassing = $passingStyle + } + BeforeAll { + $testCases = @( + @{ + Command = "cscript.exe" + Filename = "test.wsf" + ExpectedResults = @( + "Argument 0 is: " + "Argument 1 is: " + "Argument 2 is: " + "Argument 3 is: " + ) + Script = @' + + + + +'@ + } + @{ + Command = "cscript.exe" + Filename = "test.vbs" + ExpectedResults = @( + "Argument 0 is: " + "Argument 1 is: " + "Argument 2 is: " + "Argument 3 is: " + ) + Script = @' +for i = 0 to wScript.arguments.count - 1 + wscript.echo "Argument " & i & " is: <" & (wScript.arguments(i)) & ">" +next +'@ + } + @{ + Command = "cscript" + Filename = "test.js" + ExpectedResults = @( + "Argument 0 is: " + "Argument 1 is: " + "Argument 2 is: " + "Argument 3 is: " + ) + Script = @' +for(i = 0; i < WScript.Arguments.Count(); i++) { + WScript.echo("Argument " + i + " is: <" + WScript.Arguments(i) + ">"); +} +'@ + } + @{ + Command = "" + Filename = "test.bat" + ExpectedResults = @( + "Argument 1 is: " + "Argument 2 is: " + "Argument 3 is: <""ab cd"">" + "Argument 4 is: <""a'b c'd"">" + ) + Script = @' +@echo off +echo Argument 1 is: ^<%1^> +echo Argument 2 is: ^<%2^> +echo Argument 3 is: ^<%3^> +echo Argument 4 is: ^<%4^> +'@ + } + @{ + Command = "" + Filename = "test.cmd" + ExpectedResults = @( + "Argument 1 is: " + "Argument 2 is: " + "Argument 3 is: <""ab cd"">" + "Argument 4 is: <""a'b c'd"">" + ) + Script = @' +@echo off +echo Argument 1 is: ^<%1^> +echo Argument 2 is: ^<%2^> +echo Argument 3 is: ^<%3^> +echo Argument 4 is: ^<%4^> +'@ + } + ) + + # determine whether we should skip the tests we just defined + # doing it in this order ensures that the test output will show each skipped test + $skipTests = -not $IsWindows -or $EnabledExperimentalFeatures -notcontains 'PSNativeCommandArgumentPassing' + if ($skipTests) { + return + } + + # save the passing style + $passingStyle = $PSNativeCommandArgumentPassing + # explicitely set the passing style to Windows + $PSNativeCommandArgumentPassing = "Windows" + } + + It "Invoking '' is compatible with PowerShell 5" -TestCases $testCases -Skip:$($skipTests) { + param ( $Command, $Arguments, $Filename, $Script, $ExpectedResults ) + cscript //h:cscript //nologo //s $a = 'a"b c"d' - $lines = testexe -echoargs $a 'a"b c"d' a"b c"d - $lines.Count | Should -Be 3 - $lines[0] | Should -BeExactly 'Arg 0 is ' - $lines[1] | Should -BeExactly 'Arg 1 is ' - $lines[2] | Should -BeExactly 'Arg 2 is ' - } - - # In order to pass '"' characters so they are actually part of command line - # arguments for native commands, they need to be escaped with a '\' (this - # is in addition to the '`' escaping needed inside '"' quoted strings in - # PowerShell). - # - # This functionality was broken in PowerShell 5.0 and 5.1, so this test - # will fail on those versions unless the fix is backported to them. - # - # This test checks that the proper quoting and escaping is occurring by - # passing arguments with escaped quotes to the testexe native command and - # looking at how it got the arguments. - It "Should handle spaces between escaped quotes" { - $lines = testexe -echoargs 'a\"b c\"d' "a\`"b c\`"d" - $lines.Count | Should -Be 2 - $lines[0] | Should -BeExactly 'Arg 0 is ' - $lines[1] | Should -BeExactly 'Arg 1 is ' - } - - It "Should correctly quote paths with spaces: " -TestCases @( - @{arguments = "'.\test 1\' `".\test 2\`"" ; expected = @(".\test 1\",".\test 2\")}, - @{arguments = "'.\test 1\\\' `".\test 2\\`""; expected = @(".\test 1\\\",".\test 2\\")} - ) { - param($arguments, $expected) - $lines = Invoke-Expression "testexe -echoargs $arguments" - $lines.Count | Should -Be $expected.Count - for ($i = 0; $i -lt $lines.Count; $i++) { - $lines[$i] | Should -BeExactly "Arg $i is <$($expected[$i])>" + $scriptPath = Join-Path $TESTDRIVE $Filename + $Script | out-file -encoding ASCII $scriptPath + if ($Command) { + $results = & $Command $scriptPath $a 'a"b c"d' a"b c"d "a'b c'd" 2> "${TESTDRIVE}/error.txt" + } + else { + $results = & $scriptPath $a 'a"b c"d' a"b c"d "a'b c'd" 2> "${TESTDRIVE}/error.txt" } + $errorContent = Get-Content "${TESTDRIVE}/error.txt" -ErrorAction Ignore + $errorContent | Should -BeNullOrEmpty + $results.Count | Should -Be 4 + $results[0] | Should -Be $ExpectedResults[0] + $results[1] | Should -Be $ExpectedResults[1] + $results[2] | Should -Be $ExpectedResults[2] + $results[3] | Should -Be $ExpectedResults[3] } +} + - It "Should handle PowerShell arrays with or without spaces correctly: " -TestCases @( - @{arguments = "1,2"; expected = @("1,2")} - @{arguments = "1,2,3"; expected = @("1,2,3")} - @{arguments = "1, 2"; expected = "1,", "2"} - @{arguments = "1 ,2"; expected = "1", ",2"} - @{arguments = "1 , 2"; expected = "1", ",", "2"} - @{arguments = "1, 2,3"; expected = "1,", "2,3"} - @{arguments = "1 ,2,3"; expected = "1", ",2,3"} - @{arguments = "1 , 2,3"; expected = "1", ",", "2,3"} - ) { - param($arguments, $expected) - $lines = @(Invoke-Expression "testexe -echoargs $arguments") - $lines.Count | Should -Be $expected.Count - for ($i = 0; $i -lt $expected.Count; $i++) { - $lines[$i] | Should -BeExactly "Arg $i is <$($expected[$i])>" +Describe "Will error correctly if an attempt to set variable to improper value" -tags "CI" { + It "will error when setting variable incorrectly" { + if ($EnabledExperimentalFeatures -contains 'PSNativeCommandArgumentPassing') { + { $global:PSNativeCommandArgumentPassing = "zzz" } | Should -Throw -ExceptionType System.Management.Automation.ArgumentTransformationMetadataException + } + else { + Set-Test -State skipped -Because "Experimental feature 'PSNativeCommandArgumentPassing' is not enabled" } } } -Describe 'PSPath to native commands' { +foreach ( $argumentListValue in "Standard","Legacy" ) { + $PSNativeCommandArgumentPassing = $argumentListValue + Describe "Native Command Arguments (${PSNativeCommandArgumentPassing})" -tags "CI" { + # When passing arguments to native commands, quoted segments that contain + # spaces need to be quoted with '"' characters when they are passed to the + # native command (or to bash or sh on Linux). + # + # This test checks that the proper quoting is occuring by passing arguments + # to the testexe native command and looking at how it got the arguments. + It "Should handle quoted spaces correctly (ArgumentList=${PSNativeCommandArgumentPassing})" { + $a = 'a"b c"d' + $lines = testexe -echoargs $a 'a"b c"d' a"b c"d "a'b c'd" + $lines.Count | Should -Be 4 + if (($EnabledExperimentalFeatures -contains 'PSNativeCommandArgumentPassing') -and $PSNativeCommandArgumentPassing -ne "Legacy") { + $lines[0] | Should -BeExactly 'Arg 0 is ' + $lines[1] | Should -BeExactly 'Arg 1 is ' + } + else { + $lines[0] | Should -BeExactly 'Arg 0 is ' + $lines[1] | Should -BeExactly 'Arg 1 is ' + } + $lines[2] | Should -BeExactly 'Arg 2 is ' + $lines[3] | Should -BeExactly 'Arg 3 is ' + } + + # In order to pass '"' characters so they are actually part of command line + # arguments for native commands, they need to be escaped with a '\' (this + # is in addition to the '`' escaping needed inside '"' quoted strings in + # PowerShell). + # + # This functionality was broken in PowerShell 5.0 and 5.1, so this test + # will fail on those versions unless the fix is backported to them. + # + # This test checks that the proper quoting and escaping is occurring by + # passing arguments with escaped quotes to the testexe native command and + # looking at how it got the arguments. + It "Should handle spaces between escaped quotes (ArgumentList=${PSNativeCommandArgumentPassing})" { + $lines = testexe -echoargs 'a\"b c\"d' "a\`"b c\`"d" + $lines.Count | Should -Be 2 + if (($EnabledExperimentalFeatures -contains 'PSNativeCommandArgumentPassing') -and $PSNativeCommandArgumentPassing -ne "Legacy") { + $lines[0] | Should -BeExactly 'Arg 0 is ' + $lines[1] | Should -BeExactly 'Arg 1 is ' + } + else { + $lines[0] | Should -BeExactly 'Arg 0 is ' + $lines[1] | Should -BeExactly 'Arg 1 is ' + } + } + + It "Should correctly quote paths with spaces (ArgumentList=${PSNativeCommandArgumentPassing}): " -TestCases @( + @{arguments = "'.\test 1\' `".\test 2\`"" ; expected = @(".\test 1\",".\test 2\")}, + @{arguments = "'.\test 1\\\' `".\test 2\\`""; expected = @(".\test 1\\\",".\test 2\\")} + ) { + param($arguments, $expected) + $lines = Invoke-Expression "testexe -echoargs $arguments" + $lines.Count | Should -Be $expected.Count + for ($i = 0; $i -lt $lines.Count; $i++) { + $lines[$i] | Should -BeExactly "Arg $i is <$($expected[$i])>" + } + } + + It "Should handle arguments that include commas without spaces (windbg example)" { + $lines = testexe -echoargs -k com:port=\\devbox\pipe\debug,pipe,resets=0,reconnect + $lines.Count | Should -Be 2 + $lines[0] | Should -BeExactly "Arg 0 is <-k>" + $lines[1] | Should -BeExactly "Arg 1 is " + } + + It "Should handle DOS style arguments" { + $lines = testexe -echoargs /arg1 /c:"a string" + $lines.Count | Should -Be 2 + $lines[0] | Should -BeExactly "Arg 0 is " + $lines[1] | Should -BeExactly "Arg 1 is " + } + + It "Should handle PowerShell arrays with or without spaces correctly (ArgumentList=${PSNativeCommandArgumentPassing}): " -TestCases @( + @{arguments = "1,2"; expected = @("1,2")} + @{arguments = "1,2,3"; expected = @("1,2,3")} + @{arguments = "1, 2"; expected = "1,", "2"} + @{arguments = "1 ,2"; expected = "1", ",2"} + @{arguments = "1 , 2"; expected = "1", ",", "2"} + @{arguments = "1, 2,3"; expected = "1,", "2,3"} + @{arguments = "1 ,2,3"; expected = "1", ",2,3"} + @{arguments = "1 , 2,3"; expected = "1", ",", "2,3"} + ) { + param($arguments, $expected) + $lines = @(Invoke-Expression "testexe -echoargs $arguments") + $lines.Count | Should -Be $expected.Count + for ($i = 0; $i -lt $expected.Count; $i++) { + $lines[$i] | Should -BeExactly "Arg $i is <$($expected[$i])>" + } + } + } +} +Describe 'PSPath to native commands' -tags "CI" { BeforeAll { + $featureEnabled = $EnabledExperimentalFeatures.Contains('PSNativePSPathResolution') + $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() + + $PSDefaultParameterValues["it:skip"] = (-not $featureEnabled) + if ($IsWindows) { $cmd = "cmd" $cmdArg1 = "/c" @@ -90,6 +295,8 @@ Describe 'PSPath to native commands' { } AfterAll { + $global:PSDefaultParameterValues = $originalDefaultParameterValues + Remove-Item -Path "env:/test var" Remove-Item -Path $filePath Remove-PSDrive -Name $complexDriveName diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 index 13724556036..b76cf67bfec 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 @@ -43,6 +43,12 @@ Describe 'native commands with pipeline' -tags 'Feature' { $result[0] | Should -Match "pwsh" } } + + It 'native command should be killed when pipeline is disposed' -Skip:($IsWindows) { + $yes = (Get-Process 'yes' -ErrorAction Ignore).Count + yes | Select-Object -First 2 + (Get-Process 'yes' -ErrorAction Ignore).Count | Should -Be $yes + } } Describe "Native Command Processor" -tags "Feature" { @@ -141,9 +147,18 @@ Describe "Native Command Processor" -tags "Feature" { } } - It '$ErrorActionPreference does not apply to redirected stderr output' -Skip:(!$EnabledExperimentalFeatures.Contains('PSNotApplyErrorActionToStderr')) { + It '$ErrorActionPreference does not apply to redirected stderr output' { pwsh -noprofile -command '$ErrorActionPreference = ''Stop''; testexe -stderr stop 2>$null; ''hello''; $error; $?' | Should -BeExactly 'hello','True' } + + It 'Can start an elevated associated process correctly' -Skip:( + !$IsWindows -or (!(Test-Path (Join-Path -Path $env:windir -ChildPath 'system32' -AdditionalChildPath 'diskmgmt.msc'))) + ) { + # test bug https://github.com/PowerShell/PowerShell/issues/13744 where console is blocked + diskmgmt.msc + Wait-UntilTrue -sb { (Get-Process mmc).Count -gt 0 } -TimeoutInMilliseconds 5000 -IntervalInMilliseconds 1000 | Should -BeTrue + Get-Process mmc | Stop-Process + } } Describe "Open a text file with NativeCommandProcessor" -tags @("Feature", "RequireAdminOnWindows") { @@ -237,3 +252,48 @@ Categories=Application; { $dllFile = "$PSHOME\System.Management.Automation.dll"; & $dllFile } | Should -Throw -ErrorId "NativeCommandFailed" } } + +Describe "Run native command from a mounted FAT-format VHD" -tags @("Feature", "RequireAdminOnWindows") { + BeforeAll { + if (-not $IsWindows) { + return; + } + + $vhdx = Join-Path -Path $TestDrive -ChildPath ncp.vhdx + + if (Test-Path -Path $vhdx) { + Remove-item -Path $vhdx -Force + } + + $create_vhdx = Join-Path -Path $TestDrive -ChildPath 'create_vhdx.txt' + + Set-Content -Path $create_vhdx -Force -Value @" + create vdisk file="$vhdx" maximum=20 type=fixed + select vdisk file="$vhdx" + attach vdisk + convert mbr + create partition primary + format fs=fat + assign letter="T" + detach vdisk +"@ + + diskpart.exe /s $create_vhdx + Mount-DiskImage -ImagePath $vhdx > $null + + Copy-Item "$env:WinDir\System32\whoami.exe" T:\whoami.exe + } + + AfterAll { + if ($IsWindows) { + Dismount-DiskImage -ImagePath $vhdx + Remove-Item $vhdx, $create_vhdx -Force + } + } + + It "Should run 'whoami.exe' from FAT file system without error" -Skip:(!$IsWindows) { + $expected = & "$env:WinDir\System32\whoami.exe" + $result = T:\whoami.exe + $result | Should -BeExactly $expected + } +} diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 index 59702938375..755ea27f794 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 @@ -12,9 +12,9 @@ Describe "Native streams behavior with PowerShell" -Tags 'CI' { $error.Clear() $command = [string]::Join('', @( - '[Console]::Error.Write(\"foo`n`nbar`n`nbaz\"); ', - '[Console]::Error.Write(\"middle\"); ', - '[Console]::Error.Write(\"foo`n`nbar`n`nbaz\")' + '[Console]::Error.Write("foo`n`nbar`n`nbaz"); ', + '[Console]::Error.Write("middle"); ', + '[Console]::Error.Write("foo`n`nbar`n`nbaz")' )) $out = & $powershell -noprofile -command $command 2>&1 diff --git a/test/powershell/Language/Scripting/Requires.Tests.ps1 b/test/powershell/Language/Scripting/Requires.Tests.ps1 index ed3180ffbc1..d635f05a14e 100644 --- a/test/powershell/Language/Scripting/Requires.Tests.ps1 +++ b/test/powershell/Language/Scripting/Requires.Tests.ps1 @@ -41,7 +41,7 @@ Describe "Requires tests" -Tags "CI" { BeforeAll { $currentVersion = $PSVersionTable.PSVersion - $powerShellVersions = "1.0", "2.0", "3.0", "4.0", "5.0", "5.1", "6.0", "6.1", "6.2", "7.0", "7.1" + $powerShellVersions = "1.0", "2.0", "3.0", "4.0", "5.0", "5.1", "6.0", "6.1", "6.2", "7.0", "7.1", "7.2" $latestVersion = [version]($powerShellVersions | Sort-Object -Descending -Top 1) $nonExistingMinor = "$($latestVersion.Major).$($latestVersion.Minor + 1)" $nonExistingMajor = "$($latestVersion.Major + 1).0" diff --git a/test/powershell/Language/Scripting/ScriptHelp.Tests.ps1 b/test/powershell/Language/Scripting/ScriptHelp.Tests.ps1 index 8824d962090..7553fc96207 100644 --- a/test/powershell/Language/Scripting/ScriptHelp.Tests.ps1 +++ b/test/powershell/Language/Scripting/ScriptHelp.Tests.ps1 @@ -180,7 +180,12 @@ Describe 'get-help HelpFunc1' -Tags "Feature" { Describe 'get-help file' -Tags "CI" { BeforeAll { try { - $tmpfile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), "ps1") + if ($IsWindows) { + $tmpfile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), "ps1") + } + else { + $tmpfile = Join-Path $env:HOME $([IO.Path]::ChangeExtension([IO.Path]::GetRandomFileName(), "ps1")) + } } catch { return } @@ -233,7 +238,12 @@ Describe 'get-help file' -Tags "CI" { Describe 'get-help other tests' -Tags "CI" { BeforeAll { try { - $tempFile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), "ps1") + if ($IsWindows) { + $tempFile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), "ps1") + } + else { + $tempFile = Join-Path $env:HOME $([IO.Path]::ChangeExtension([IO.Path]::GetRandomFileName(), "ps1")) + } } catch { return } diff --git a/test/powershell/Language/Scripting/SuppressAnsiEscapeSequence.Tests.ps1 b/test/powershell/Language/Scripting/SuppressAnsiEscapeSequence.Tests.ps1 index 568e56be904..30a82309a70 100644 --- a/test/powershell/Language/Scripting/SuppressAnsiEscapeSequence.Tests.ps1 +++ b/test/powershell/Language/Scripting/SuppressAnsiEscapeSequence.Tests.ps1 @@ -4,10 +4,13 @@ Describe '$env:__SuppressAnsiEscapeSequences tests' -Tag CI { BeforeAll { $originalSuppressPref = $env:__SuppressAnsiEscapeSequences + $originalRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'Ansi' } AfterAll { $env:__SuppressAnsiEscapeSequences = $originalSuppressPref + $PSStyle.OutputRendering = $originalRendering } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1 index c9809884fd6..72a7c9eddb1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1 @@ -473,8 +473,8 @@ Describe "Additional tests for Import-Module with WinCompat" -Tag "Feature" { It "Verify that Warning is generated with default WarningAction" { $LogPath = Join-Path $TestDrive (New-Guid).ToString() - & $pwsh -NoProfile -NonInteractive -c "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('TestWindowsPowerShellPSHomeLocation', `'$basePath`');Import-Module $ModuleName" *> $LogPath - $LogPath | Should -FileContentMatch 'loaded in Windows PowerShell' + & $pwsh -NoProfile -NonInteractive -c "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('TestWindowsPowerShellPSHomeLocation', `'$basePath`');Import-Module $ModuleName;Get-Error" *> $LogPath + $LogPath | Should -FileContentMatch 'loaded in Windows PowerShell' -Because (Get-Content $LogPath) } It "Verify that Error is Not generated with -ErrorAction Ignore" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 index 6841778af19..dc1b8b81b4d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 @@ -49,6 +49,58 @@ Describe "History cmdlet test cases" -Tags "CI" { } } + Context 'Conversions and Culture tests' { + + BeforeAll { + $cultureTestCases = @( + @{ + Culture = 'en-us' + StartTime = '08/18/2021 16:43:50' + EndTime = '08/18/2021 16:44:50' + } + @{ + Culture = 'en-au' + StartTime = '18/08/2021 16:43:50' + EndTime = '18/08/2021 16:44:50' + } + ) + + $oldCulture = [cultureinfo]::CurrentCulture + } + + AfterEach { + [cultureinfo]::CurrentCulture = $oldCulture + } + + It "respects current culture settings when handling datetime conversions" -TestCases $cultureTestCases { + param($Culture, $StartTime, $EndTime) + + [cultureinfo]::CurrentCulture = [cultureinfo]::GetCultureInfo($Culture) + + $history = [PSCustomObject] @{ + CommandLine = "test-command" + ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::Completed + StartExecutionTime = $StartTime + EndExecutionTime = $EndTime + } + + { $history | Add-History -ErrorAction Stop } | Should -Not -Throw -Because 'the datetime should be converted according to the current culture' + } + + It "throws an error when asked to convert a date format that doesn't match the current culture" { + [cultureinfo]::CurrentCulture = [cultureinfo]::GetCultureInfo('en-au') + $history = [PSCustomObject] @{ + CommandLine = "test-command" + ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::Completed + StartExecutionTime = '08/18/2021 16:43:50' + EndExecutionTime = '08/18/2021 16:44:50' + } + + $errorMessage = 'Cannot add history because the input object has a format that is not valid.' + { $history | Add-History -ErrorAction Stop } | Should -Throw -ExpectedMessage $errorMessage + } + } + It "Tests Invoke-History on a cmdlet that generates output on all streams" { $streamSpammer = ' function StreamSpammer diff --git a/src/System.Management.Automation/engine/Modules/ImportProvider.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/ImportProvider.Tests.ps1 similarity index 93% rename from src/System.Management.Automation/engine/Modules/ImportProvider.Tests.ps1 rename to test/powershell/Modules/Microsoft.PowerShell.Core/ImportProvider.Tests.ps1 index 1bfcb84d0ce..dba35c4ec59 100644 --- a/src/System.Management.Automation/engine/Modules/ImportProvider.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/ImportProvider.Tests.ps1 @@ -62,7 +62,7 @@ namespace module { } It "Import a PowerShell provider with correct name" { - $result = & $pwsh -NoProfile -Command "Import-Module -Name $testModulePath; Get-Item ReproModule\SamplePrv::test.txt" - $result.PSPath | Should -BeExactly "ReproModule\SamplePrv::test.txt" + $result = & $pwsh -NoProfile -Command "Import-Module -Name $testModulePath; (Get-Item ReproModule\SamplePrv::test.txt).PSPath" + $result | Should -BeExactly "ReproModule\SamplePrv::test.txt" } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index d4bd23a6fee..6d63206b709 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -5,6 +5,7 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { BeforeAll { $file1 = "file1.txt" Setup -File "$file1" + $streamContent = "ShouldWork" } Context "Add-Content should actually add content" { @@ -47,6 +48,29 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { { Add-Content -Path . -Value "WriteContainerContentException" -ErrorAction Stop } | Should -Throw -ErrorId "WriteContainerContentException,Microsoft.PowerShell.Commands.AddContentCommand" } + Context "Add-Content should work with alternate data streams on Windows" { + BeforeAll { + if (!$isWindows) { + return + } + $ADSTestDir = "addcontentadstest" + $ADSTestFile = "addcontentads.txt" + $streamContent = "This is a test stream." + Setup -Directory "$ADSTestDir" + Setup -File "$ADSTestFile" + } + + It "Should add an alternate data stream on a directory" -Skip:(!$IsWindows) { + Add-Content -Path TestDrive:\$ADSTestDir -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$ADSTestDir -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + } + + It "Should add an alternate data stream on a file" -Skip:(!$IsWindows) { + Add-Content -Path TestDrive:\$ADSTestFile -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$ADSTestFile -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + } + } + #[BugId(BugDatabase.WindowsOutOfBandReleases, 906022)] It "should throw 'NotSupportedException' when you add-content to an unsupported provider" -Skip:($IsLinux -Or $IsMacOS) { { Add-Content -Path HKLM:\\software\\microsoft -Value "ShouldNotWorkBecausePathIsUnsupported" -ErrorAction Stop } | Should -Throw -ErrorId "NotSupported,Microsoft.PowerShell.Commands.AddContentCommand" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index e2ab56fc809..ff9d0c8f39c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -51,6 +51,8 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Setup -File "$file3" -Content $content2 $streamContent = "content for alternate stream" $streamName = "altStream1" + $dirName = "clearcontent" + Setup -Directory "$dirName" } Context "Clear-Content should actually clear content" { @@ -75,32 +77,50 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $cci.SupportsShouldProcess | Should -BeTrue } - It "Alternate streams should be cleared with clear-content" -Skip:(!$IsWindows) { - # make sure that the content is correct - # this is here rather than BeforeAll because only windows can write to an alternate stream - Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent - Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 - Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeExactly $streamContent - Clear-Content -Path "TestDrive:/$file3" -Stream $streamName - Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 - Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeNullOrEmpty - } + Context "Clear-Content should work with alternate data streams on Windows" { + It "Alternate streams should be cleared with Clear-Content on a file" -Skip:(!$IsWindows) { + + Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent + Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeExactly $streamContent + + Clear-Content -Path "TestDrive:/$file3" -Stream $streamName -ErrorAction Stop + + $result = Get-Item -Path "TestDrive:/$file3" -Stream $streamName + $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData + $result.length | Should -Be 0 + } - It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { - try { - Push-Location -Path TestDrive: - (Get-Command Clear-Content -Stream foo).parameters.keys -eq "stream" | Should -Be "stream" + It "Alternate streams should be cleared with Clear-Content on a directory" -Skip:(!$IsWindows) { + Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent + + Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent + Clear-Content -Path "TestDrive:/$dirName" -Stream $streamName -ErrorAction Stop + + $result = Get-Item -Path "TestDrive:/$dirName" -Stream $streamName + $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData + $result.length | Should -Be 0 } - finally { - Pop-Location + + It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { + try { + Push-Location -Path TestDrive: + (Get-Command Clear-Content -Stream foo).parameters.keys -eq "Stream" | Should -BeExactly "Stream" + } + finally { + Pop-Location + } } - } - It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" { - Push-Location -Path function: - { Get-Command Clear-Content -Stream $streamName } | - Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" - Pop-Location + It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" -Skip:(!$IsWindows) { + try { + Push-Location -Path function: + { Get-Command Clear-Content -Stream $streamName } | + Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" + } + finally { + Pop-Location + } + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clipboard.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clipboard.Tests.ps1 index d28394c9f26..7cd4f492bfa 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clipboard.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clipboard.Tests.ps1 @@ -41,5 +41,46 @@ Describe 'Clipboard cmdlet tests' -Tag CI { 'world' | Set-Clipboard -Append Get-Clipboard -Raw | Should -BeExactly "hello$([Environment]::NewLine)world" } + + It 'Set-Clipboard accepts string' -TestCases @( + @{ value = 'empty'; text = "" } + @{ value = 'null' ; text = $null } + ){ + param ($text) + + $text | Set-Clipboard + Get-Clipboard -Raw | Should -BeNullOrEmpty + } + + It 'Set-Clipboard should not return object' { + $result = 'hello' | Set-Clipboard + $result | Should -BeNullOrEmpty + } + + It 'Set-Clipboard -PassThru returns single object with -Append = ' -TestCases @( + @{ Append = $false } + @{ Append = $true } + ){ + param ($append) + + $params = @{ PassThru = $true; Append = $append } + + Set-Clipboard -Value 'world' + $result = 'hello' | Set-Clipboard @params + $result | Should -BeExactly 'hello' + } + + It 'Set-Clipboard -PassThru returns multiple objects with -Append = ' -TestCases @( + @{ Append = $false } + @{ Append = $true } + ){ + param ($append) + + $params = @{ PassThru = $true; Append = $append } + + Set-Clipboard -Value 'world' + $result = 'hello', 'world' | Set-Clipboard @params + $result | Should -BeExactly @('hello', 'world') + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 index 0e4adaeec70..bec4ad83b80 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 @@ -92,6 +92,22 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { $existsAfter | Should -BeFalse } + It "Verify Remove-Item for file" { + $longDir = 'a' * 250 + $longSubDir = 'b' * 250 + $fileName = "file1.txt" + $topPath = Join-Path $TestDrive $longDir + $longDirPath = Join-Path $topPath $longSubDir + $longFilePath = Join-Path $longDirPath $fileName + $null = New-Item -itemtype file -path $longFilePath -force + + $longFilePath | Should -Exist + + Remove-Item -Path $longFilePath -Force + + $longFilePath | Should -Not -Exist + } + It "Verify Rename-Item for file" { Rename-Item -Path $testFile -NewName $newTestFile -ErrorAction Stop $testFile | Should -Not -Exist @@ -154,11 +170,37 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { } It "Verify Move-Item will not move to an existing file" { - { Move-Item -Path $testDir -Destination $testFile -ErrorAction Stop } | Should -Throw -ErrorId "MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand" - $error[0].Exception | Should -BeOfType System.IO.IOException + if ($IsWindows) { + $expectedError = 'MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand' + } + else { + $expectedError = 'DirectoryExist,Microsoft.PowerShell.Commands.MoveItemCommand' + } + + $e = { Move-Item -Path $testDir -Destination $testFile -ErrorAction Stop } | Should -Throw -ErrorId $expectedError -PassThru + $e.Exception | Should -BeOfType System.IO.IOException $testDir | Should -Exist } + It 'Verify Move-Item fails for non-existing destination path' { + $e = { Move-Item -Path $testDir -Destination TestDrive:/0/2/0 -ErrorAction Stop } | Should -Throw -ErrorId 'MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand' -PassThru + $e.Exception | Should -BeOfType System.IO.IOException + } + + It 'Verify Move-Item fails for destination that is subdir of source with trailing: ' -TestCases @( + @{ trailingChar = [System.IO.Path]::DirectorySeparatorChar } + @{ trailingChar = [System.IO.Path]::AltDirectorySeparatorChar } + @{ trailingChar = '' } + ) { + param($trailingChar) + + $dest = Join-Path -Path $TestDrive -ChildPath dest + $null = New-item -ItemType Directory -Path $dest -Force -ErrorAction Stop + $src = "$TestDrive$trailingChar" + + { Move-Item -Path $src -Destination $dest -ErrorAction Stop } | Should -Throw -ErrorId 'MoveItemArgumentError,Microsoft.PowerShell.Commands.MoveItemCommand' + } + It "Verify Move-Item throws correct error for non-existent source" { { Move-Item -Path /does/not/exist -Destination $testFile -ErrorAction Stop } | Should -Throw -ErrorId 'PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand' } @@ -287,6 +329,13 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { $newItemPath = Join-Path $protectedPath "foo" $shouldSkip = -not (Test-Path $protectedPath) } + + if ($IsWindows) { + $fqaccessdenied = "MoveDirectoryItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.MoveItemCommand" + } + else { + $fqaccessdenied = "MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand" + } } It "Access-denied test for " -Skip:(-not $IsWindows -or $shouldSkip) -TestCases @( @@ -296,7 +345,7 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { # @{cmdline = "New-Item -Type File -Path $newItemPath -ErrorAction Stop"; expectedError = "NewItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand"} @{cmdline = "Get-ChildItem $protectedPath -ErrorAction Stop"; expectedError = "DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand"} @{cmdline = "Rename-Item -Path $protectedPath -NewName bar -ErrorAction Stop"; expectedError = "RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand"}, - @{cmdline = "Move-Item -Path $protectedPath -Destination bar -ErrorAction Stop"; expectedError = "MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand"} + @{cmdline = "Move-Item -Path $protectedPath -Destination bar -ErrorAction Stop"; expectedError = $fqaccessdenied} ) { param ($cmdline, $expectedError) @@ -563,7 +612,7 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows" $omegaFile1 = Join-Path $omegaDir "OmegaFile1" $omegaFile2 = Join-Path $omegaDir "OmegaFile2" $betaDir = Join-Path $alphaDir "sub-Beta" - $betaLink = Join-Path $alphaDir "link-Beta" + $betaLink = Join-Path $alphaDir "link-Beta" # Don't change! The name is hard-coded in PowerShell for OneDrive tests. $betaFile1 = Join-Path $betaDir "BetaFile1.txt" $betaFile2 = Join-Path $betaDir "BetaFile2.txt" $betaFile3 = Join-Path $betaDir "BetaFile3.txt" @@ -738,6 +787,42 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows" $childB.Name | Should -BeExactly $childA.Name } } + + Context "Show immediate target" { + BeforeAll { + $testDir = Join-Path $TestDrive "immediate-target" + New-Item -ItemType Directory $testDir > $null + + $testFile = Join-Path $testDir "target" + Set-Content -Path $testFile -Value "Hello world" + + Push-Location $testDir + New-Item -ItemType SymbolicLink -Path 'firstLink' -Value 'target' > $null + New-Item -ItemType SymbolicLink -Path 'secondLink' -Value 'firstLink' > $null + Pop-Location + } + + AfterAll { + Remove-Item $testDir -Recurse -Force + } + + It "Property 'Target' should show the immediate target" { + $firstLink = Get-Item (Join-Path $testDir 'firstLink') + $firstLink.Target | Should -BeExactly 'target' + $str = [Microsoft.PowerShell.Commands.FileSystemProvider]::NameString($firstLink) + [System.Management.Automation.Internal.StringDecorated]::new($str).ToString([System.Management.Automation.OutputRendering]::PlainText) | Should -BeExactly 'firstLink -> target' + + $secondLink = Get-Item (Join-Path $testDir 'secondLink') + $secondLink.Target | Should -BeExactly 'firstLink' + $str = [Microsoft.PowerShell.Commands.FileSystemProvider]::NameString($secondLink) + [System.Management.Automation.Internal.StringDecorated]::new($str).ToString([System.Management.Automation.OutputRendering]::PlainText) | Should -BeExactly 'secondLink -> firstLink' + } + + It "Get-Content should be able to resolve the final target" { + Get-Content (Join-Path $testDir 'firstLink') | Should -BeExactly "Hello world" + Get-Content (Join-Path $testDir 'secondLink') | Should -BeExactly "Hello world" + } + } } Describe "Copy-Item can avoid copying an item onto itself" -Tags "CI", "RequireAdminOnWindows" { @@ -1493,3 +1578,148 @@ Describe "Verify sub-directory creation under root" -Tag 'CI','RequireSudoOnUnix $dirPath | Should -Exist } } + +Describe "Windows admin tests" -Tag 'RequireAdminOnWindows' { + It "Verify Move-Item for directory across drives on Windows" -Skip:(!$IsWindows) { + try { + # find first available drive letter, unfortunately need to use both function: and Win32_LogicalDisk to cover + # both subst drives and bitlocker drives + $drive = Get-ChildItem function:[h-z]: -Name | Where-Object { !(Test-Path -Path $_) -and !(Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$_'") } | Select-Object -First 1 + if ($null -eq $drive) { + throw "Test cannot continue as no drive letter available" + } + + $dest = (Resolve-Path -Path $TestDrive).ProviderPath + $null = New-Item -ItemType Directory -Path $dest -Name test + $out = subst $drive $dest 2>&1 + if ($LASTEXITCODE -ne 0) { + throw "subst failed with exit code ${LASTEXITCODE} for drive '$drive': $out" + } + + $testdir = New-Item -ItemType Directory -Path $drive -Name testmovedir -Force + 1 > $testdir\test.txt + Move-Item $drive\testmovedir $dest\test + "$drive\testmovedir" | Should -Not -Exist + "$dest\test\testmovedir\test.txt" | Should -FileContentMatchExactly 1 + } + finally { + subst $drive /d + } + } +} + +Describe "OneDrive filesystem manipulation" -Tags @('CI', 'RequireAdminOnWindows') { + BeforeAll { + # on macOS, the /tmp directory is a symlink, so we'll resolve it here + $TestPath = $TestDrive + if ($IsMacOS) + { + $item = Get-Item $TestPath + $dirName = $item.BaseName + $item = Get-Item $item.PSParentPath -Force + if ($item.LinkType -eq "SymbolicLink") + { + $TestPath = Join-Path $item.Target $dirName + } + } + + $realFile = Join-Path $TestPath "file.txt" + $nonFile = Join-Path $TestPath "not-a-file" + $fileContent = "some text" + $realDir = Join-Path $TestPath "subdir" + $nonDir = Join-Path $TestPath "not-a-dir" + $hardLinkToFile = Join-Path $TestPath "hard-to-file.txt" + $symLinkToFile = Join-Path $TestPath "sym-link-to-file.txt" + $symLinkToDir = Join-Path $TestPath "sym-link-to-dir" + $symLinkToNothing = Join-Path $TestPath "sym-link-to-nowhere" + $dirSymLinkToDir = Join-Path $TestPath "symd-link-to-dir" + $junctionToDir = Join-Path $TestPath "junction-to-dir" + + New-Item -ItemType File -Path $realFile -Value $fileContent > $null + New-Item -ItemType Directory -Path $realDir > $null + + $alphaDir = Join-Path $TestDrive "sub-alpha" + $alphaLink = Join-Path $TestDrive "link-alpha" + $alphaFile1 = Join-Path $alphaDir "AlphaFile1.txt" + $alphaFile2 = Join-Path $alphaDir "AlphaFile2.txt" + $omegaDir = Join-Path $TestDrive "sub-omega" + $omegaFile1 = Join-Path $omegaDir "OmegaFile1" + $omegaFile2 = Join-Path $omegaDir "OmegaFile2" + $betaDir = Join-Path $alphaDir "sub-Beta" + $betaLink = Join-Path $alphaDir "link-Beta" # Don't change! The name is hard-coded in PowerShell for OneDrive tests. + $betaFile1 = Join-Path $betaDir "BetaFile1.txt" + $betaFile2 = Join-Path $betaDir "BetaFile2.txt" + $betaFile3 = Join-Path $betaDir "BetaFile3.txt" + $gammaDir = Join-Path $betaDir "sub-gamma" + $uponeLink = Join-Path $gammaDir "upone-link" + $uptwoLink = Join-Path $gammaDir "uptwo-link" + $omegaLink = Join-Path $gammaDir "omegaLink" + + New-Item -ItemType Directory -Path $alphaDir + New-Item -ItemType File -Path $alphaFile1 + New-Item -ItemType File -Path $alphaFile2 + New-Item -ItemType Directory -Path $betaDir + New-Item -ItemType File -Path $betaFile1 + New-Item -ItemType File -Path $betaFile2 + New-Item -ItemType File -Path $betaFile3 + New-Item -ItemType Directory $omegaDir + New-Item -ItemType File -Path $omegaFile1 + New-Item -ItemType File -Path $omegaFile2 + } + + AfterAll { + Remove-Item -Path $alphaLink -Force -ErrorAction SilentlyContinue + Remove-Item -Path $betaLink -Force -ErrorAction SilentlyContinue + } + + BeforeEach { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $true) + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false) + } + + AfterEach { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false) + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $false) + } + + It "Get-ChildItem will recurse into emulated OneDrive directory" -Skip:(-not $IsWindows) { + New-Item -ItemType SymbolicLink -Path $alphaLink -Value $alphaDir -Force + New-Item -ItemType SymbolicLink -Path $betaLink -Value $betaDir -Force + + # '$betaDir' is a symlink - we don't follow symlinks + # This emulates PowerShell 6.2 and below behavior. + $ci = Get-ChildItem -Path $alphaDir -Recurse + $ci.Count | Should -BeExactly 7 + + # Now we follow the symlink like on OneDrive. + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $true) + $ci = Get-ChildItem -Path $alphaDir -Recurse + $ci.Count | Should -BeExactly 10 + } + + It "Remove-Item will recurse into emulated OneDrive directory" -Skip:(-not $IsWindows) { + $alphaDir = Join-Path $TestDrive "sub-alpha2" + $alphaLink = Join-Path $TestDrive "link-alpha2" + $alphaFile1 = Join-Path $alphaDir "AlphaFile1.txt" + $betaDir = Join-Path $alphaDir "sub-Beta" + $betaLink = Join-Path $alphaDir "link-Beta" + $betaFile1 = Join-Path $betaDir "BetaFile1.txt" + + New-Item -ItemType Directory -Path $alphaDir > $null + New-Item -ItemType File -Path $alphaFile1 > $null + New-Item -ItemType Directory -Path $betaDir > $null + New-Item -ItemType File -Path $betaFile1 > $null + + New-Item -ItemType SymbolicLink -Path $alphaLink -Value $alphaDir > $null + New-Item -ItemType SymbolicLink -Path $betaLink -Value $betaDir > $null + + # With the test hook turned on we don't remove '$betaDir' symlink. + # This emulates PowerShell 7.1 and below behavior. + { Remove-Item -Path $betaLink -Recurse -ErrorAction Stop } | Should -Throw -ErrorId "DeleteSymbolicLinkFailed,Microsoft.PowerShell.Commands.RemoveItemCommand" + + # Now we emulate OneDrive and follow the symlink like on OneDrive. + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $true) + Remove-Item -Path $betaLink -Recurse + Test-Path -Path $betaLink | Should -BeFalse + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 index 6c50cee5aa8..5fdc904580d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 @@ -221,25 +221,27 @@ Describe "Get-Content" -Tags "CI" { $expected = 'He', 'o,', '', 'Wor', "d${nl}He", 'o2,', '', 'Wor', "d2${nl}" for ($i = 0; $i -lt $result.Length ; $i++) { $result[$i] | Should -BeExactly $expected[$i]} } + + Context "Alternate Data Stream support on Windows" { + It "Should support NTFS streams using colon syntax" -Skip:(!$IsWindows) { + Set-Content "${testPath}:Stream" -Value "Foo" + { Test-Path "${testPath}:Stream" | Should -Throw -ErrorId "ItemExistsNotSupportedError,Microsoft.PowerShell.Commands,TestPathCommand" } + Get-Content "${testPath}:Stream" | Should -BeExactly "Foo" + Get-Content $testPath | Should -BeExactly $testString + } - It "Should support NTFS streams using colon syntax" -Skip:(!$IsWindows) { - Set-Content "${testPath}:Stream" -Value "Foo" - { Test-Path "${testPath}:Stream" | Should -Throw -ErrorId "ItemExistsNotSupportedError,Microsoft.PowerShell.Commands,TestPathCommand" } - Get-Content "${testPath}:Stream" | Should -BeExactly "Foo" - Get-Content $testPath | Should -BeExactly $testString - } - - It "Should support NTFS streams using -Stream" -Skip:(!$IsWindows) { - Set-Content -Path $testPath -Stream hello -Value World - Get-Content -Path $testPath | Should -BeExactly $testString - Get-Content -Path $testPath -Stream hello | Should -BeExactly "World" - $item = Get-Item -Path $testPath -Stream hello - $item | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData - $item.Stream | Should -BeExactly "hello" - Clear-Content -Path $testPath -Stream hello - Get-Content -Path $testPath -Stream hello | Should -BeNullOrEmpty - Remove-Item -Path $testPath -Stream hello - { Get-Content -Path $testPath -Stream hello | Should -Throw -ErrorId "GetContentReaderFileNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand" } + It "Should support NTFS streams using -Stream" -Skip:(!$IsWindows) { + Set-Content -Path $testPath -Stream hello -Value World + Get-Content -Path $testPath | Should -BeExactly $testString + Get-Content -Path $testPath -Stream hello | Should -BeExactly "World" + $item = Get-Item -Path $testPath -Stream hello + $item | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData + $item.Stream | Should -BeExactly "hello" + Clear-Content -Path $testPath -Stream hello + Get-Content -Path $testPath -Stream hello | Should -BeNullOrEmpty + Remove-Item -Path $testPath -Stream hello + { Get-Content -Path $testPath -Stream hello -ErrorAction stop} | Should -Throw -ErrorId "GetContentReaderFileNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand" + } } It "Should support colons in filename on Linux/Mac" -Skip:($IsWindows) { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 86b831ba8d0..35c05b1bb12 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -112,16 +112,38 @@ Describe "Get-Item" -Tags "CI" { return } $altStreamPath = "$TESTDRIVE/altStream.txt" + $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $noAltStreamDirectory = "$TESTDRIVE/noaltstreamdir" $stringData = "test data" $streamName = "test" - $item = New-Item -type file $altStreamPath + $absentStreamName = "noExist" + $null = New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData + $null = New-Item -type directory $altStreamDirectory + Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData + $null = New-Item -type directory $noAltStreamDirectory } - It "Should find an alternate stream if present" -Skip:$skipNotWindows { + It "Should find an alternate stream on a file if present" -Skip:$skipNotWindows { $result = Get-Item $altStreamPath -Stream $streamName $result.Length | Should -Be ($stringData.Length + [Environment]::NewLine.Length) $result.Stream | Should -Be $streamName } + It "Should error if it cannot find alternate stream on an existing file" -Skip:$skipNotWindows { + { Get-Item $altStreamPath -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } + It "Should find an alternate stream on a directory if present, and it should not be a container" -Skip:$skipNotWindows { + $result = Get-Item $altStreamDirectory -Stream $streamName + $result.Length | Should -Be ($stringData.Length + [Environment]::NewLine.Length ) + $result.Stream | Should -Be $streamName + $result.PSIsContainer | Should -BeExactly $false + } + It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { + { Get-Item $noAltStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } + It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { + $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop + $result | Should -BeExactly $null + } } Context "Registry Provider" { @@ -183,3 +205,62 @@ Describe "Get-Item environment provider on Windows with accidental case-variant } } } + +Describe 'Formatting for FileInfo objects' -Tags 'CI' { + BeforeAll { + $PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRenderingFileInfo'))) + $extensionTests = [System.Collections.Generic.List[HashTable]]::new() + foreach ($extension in @('.zip', '.tgz', '.tar', '.gz', '.nupkg', '.cab', '.7z', '.ps1', '.psd1', '.psm1', '.ps1xml')) { + $extensionTests.Add(@{extension = $extension}) + } + } + + AfterAll { + $PSDefaultParameterValues.Remove('It:Skip') + } + + It 'File type should have correct color' -TestCases $extensionTests { + param($extension) + + $testFile = Join-Path -Path $TestDrive -ChildPath "test$extension" + $file = New-Item -ItemType File -Path $testFile + $file.NameString | Should -BeExactly "$($PSStyle.FileInfo.Extension[$extension] + $file.Name + $PSStyle.Reset)" + } + + It 'Directory should have correct color' { + $dirPath = Join-Path -Path $TestDrive -ChildPath 'myDir' + $dir = New-Item -ItemType Directory -Path $dirPath + $dir.NameString | Should -BeExactly "$($PSStyle.FileInfo.Directory + $dir.Name + $PSStyle.Reset)" + } + + It 'Executable should have correct color' { + if ($IsWindows) { + $exePath = Join-Path -Path $TestDrive -ChildPath 'myExe.exe' + $exe = New-Item -ItemType File -Path $exePath + } + else { + $exePath = Join-Path -Path $TestDrive -ChildPath 'myExe' + $null = New-Item -ItemType File -Path $exePath + chmod +x $exePath + $exe = Get-Item -Path $exePath + } + + $exe.NameString | Should -BeExactly "$($PSStyle.FileInfo.Executable + $exe.Name + $PSStyle.Reset)" + } +} + +Describe 'Formatting for FileInfo requiring admin' -Tags 'CI','RequireAdminOnWindows' { + BeforeAll { + $PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRenderingFileInfo'))) + } + + AfterAll { + $PSDefaultParameterValues.Remove('It:Skip') + } + + It 'Symlink should have correct color' { + $linkPath = Join-Path -Path $TestDrive -ChildPath 'link' + $link = New-Item -ItemType SymbolicLink -Name 'link' -Value $TestDrive -Path $TestDrive + $link.NameString | Should -BeExactly "$($PSStyle.FileInfo.SymbolicLink + $link.Name + $PSStyle.Reset) -> $TestDrive" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 index 6143ddca0be..345b2affa2e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 @@ -70,8 +70,7 @@ Describe "Get-Process" -Tags "CI" { { (Get-Process -Id $idleProcessPid).Name } | Should -Not -Throw } - It "Test for process property = Name" -Pending { - # Bug in .Net 5.0 Preview4. See https://github.com/PowerShell/PowerShell/pull/12894 + It "Test for process property = Name" { (Get-Process -Id $PID).Name | Should -BeExactly "pwsh" } @@ -87,6 +86,11 @@ Describe "Get-Process" -Tags "CI" { { Get-Process -Module -ErrorAction Stop } | Should -Throw -ErrorId "CouldNotEnumerateModules,Microsoft.PowerShell.Commands.GetProcessCommand" } + It "Should not fail to stop Get-Process with -Module when piped to Select-Object" { + Get-Process -Module -Id $PID -ErrorVariable errs | Select-Object -First 1 + $errs | Should -HaveCount 0 + } + It "Should fail to run Get-Process with -FileVersionInfo without admin" -Skip:(!$IsWindows) { { Get-Process -FileVersionInfo -ErrorAction Stop } | Should -Throw -ErrorId "CouldNotEnumerateFileVer,Microsoft.PowerShell.Commands.GetProcessCommand" } @@ -124,8 +128,7 @@ Describe "Get-Process Formatting" -Tags "Feature" { } Describe "Process Parent property" -Tags "CI" { - It "Has Parent process property" -Pending { - # Bug in .Net 5.0 Preview4. See https://github.com/PowerShell/PowerShell/pull/12894 + It "Has Parent process property" { $powershellexe = (Get-Process -Id $PID).mainmodule.filename & $powershellexe -noprofile -command '(Get-Process -Id $PID).Parent' | Should -Not -BeNullOrEmpty } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index 769a8a34003..28c5ed6052d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -1,141 +1,195 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -Describe "Remove-Item" -Tags "CI" { - $testpath = $TestDrive - $testfile = "testfile.txt" - $testfilepath = Join-Path -Path $testpath -ChildPath $testfile - Context "File removal Tests" { - BeforeEach { - New-Item -Name $testfile -Path $testpath -ItemType "file" -Value "lorem ipsum" -Force - Test-Path $testfilepath | Should -BeTrue +Describe "Remove-Item" -Tags "CI" { + BeforeAll { + $testpath = $TestDrive + $testfile = "testfile.txt" + $testfilepath = Join-Path -Path $testpath -ChildPath $testfile + } - } + Context "File removal Tests" { + BeforeEach { + New-Item -Name $testfile -Path $testpath -ItemType "file" -Value "lorem ipsum" -Force + Test-Path $testfilepath | Should -BeTrue + } - It "Should be able to be called on a regular file without error using the Path parameter" { - { Remove-Item -Path $testfilepath } | Should -Not -Throw + It "Should be able to be called on a regular file without error using the Path parameter" { + { Remove-Item -Path $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to be called on a file without the Path parameter" { - { Remove-Item $testfilepath } | Should -Not -Throw + It "Should be able to be called on a file without the Path parameter" { + { Remove-Item $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to call the rm alias" { - { rm $testfilepath } | Should -Not -Throw + It "Should be able to call the rm alias" { + { rm $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to call the del alias" { - { del $testfilepath } | Should -Not -Throw + It "Should be able to call the del alias" { + { del $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to call the erase alias" { - { erase $testfilepath } | Should -Not -Throw + It "Should be able to call the erase alias" { + { erase $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to call the ri alias" { - { ri $testfilepath } | Should -Not -Throw + It "Should be able to call the ri alias" { + { ri $testfilepath } | Should -Not -Throw - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should not be able to remove a read-only document without using the force switch" { - # Set to read only - Set-ItemProperty -Path $testfilepath -Name IsReadOnly -Value $true + It "Should not be able to remove a read-only document without using the force switch" { + # Set to read only + Set-ItemProperty -Path $testfilepath -Name IsReadOnly -Value $true - # attempt to remove the file - { Remove-Item $testfilepath -ErrorAction SilentlyContinue } | Should -Not -Throw + # attempt to remove the file + { Remove-Item $testfilepath -ErrorAction SilentlyContinue } | Should -Not -Throw - # validate - Test-Path $testfilepath | Should -BeTrue + # validate + Test-Path $testfilepath | Should -BeTrue - # remove using the -force switch on the readonly object - Remove-Item $testfilepath -Force + # remove using the -force switch on the readonly object + Remove-Item $testfilepath -Force - # Validate - Test-Path $testfilepath | Should -BeFalse - } + # Validate + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to remove all files matching a regular expression with the include parameter" { - # Create multiple files with specific string - New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" - New-Item -Name file2.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" - New-Item -Name file3.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" - # Create a single file that does not match that string - already done in BeforeEach + It "Should be able to remove all files matching a regular expression with the include parameter" { + # Create multiple files with specific string + New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" + New-Item -Name file2.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" + New-Item -Name file3.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" + # Create a single file that does not match that string - already done in BeforeEach - # Delete the specific string - Remove-Item (Join-Path -Path $testpath -ChildPath "*") -Include file*.txt - # validate that the string under test was deleted, and the nonmatching strings still exist - Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse - Test-Path (Join-Path -Path $testpath -ChildPath file2.txt) | Should -BeFalse - Test-Path (Join-Path -Path $testpath -ChildPath file3.txt) | Should -BeFalse - Test-Path $testfilepath | Should -BeTrue + # Delete the specific string + Remove-Item (Join-Path -Path $testpath -ChildPath "*") -Include file*.txt + # validate that the string under test was deleted, and the nonmatching strings still exist + Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse + Test-Path (Join-Path -Path $testpath -ChildPath file2.txt) | Should -BeFalse + Test-Path (Join-Path -Path $testpath -ChildPath file3.txt) | Should -BeFalse + Test-Path $testfilepath | Should -BeTrue - # Delete the non-matching strings - Remove-Item $testfilepath + # Delete the non-matching strings + Remove-Item $testfilepath - Test-Path $testfilepath | Should -BeFalse - } + Test-Path $testfilepath | Should -BeFalse + } - It "Should be able to not remove any files matching a regular expression with the exclude parameter" { - # Create multiple files with specific string - New-Item -Name file1.wav -Path $testpath -ItemType "file" -Value "lorem ipsum" - New-Item -Name file2.wav -Path $testpath -ItemType "file" -Value "lorem ipsum" + It "Should be able to not remove any files matching a regular expression with the exclude parameter" { + # Create multiple files with specific string + New-Item -Name file1.wav -Path $testpath -ItemType "file" -Value "lorem ipsum" + New-Item -Name file2.wav -Path $testpath -ItemType "file" -Value "lorem ipsum" - # Create a single file that does not match that string - New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" + # Create a single file that does not match that string + New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum" - # Delete the specific string - Remove-Item (Join-Path -Path $testpath -ChildPath "file*") -Exclude *.wav -Include *.txt + # Delete the specific string + Remove-Item (Join-Path -Path $testpath -ChildPath "file*") -Exclude *.wav -Include *.txt - # validate that the string under test was deleted, and the nonmatching strings still exist - Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeTrue - Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeTrue - Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse + # validate that the string under test was deleted, and the nonmatching strings still exist + Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeTrue + Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeTrue + Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse - # Delete the non-matching strings - Remove-Item (Join-Path -Path $testpath -ChildPath file1.wav) - Remove-Item (Join-Path -Path $testpath -ChildPath file2.wav) + # Delete the non-matching strings + Remove-Item (Join-Path -Path $testpath -ChildPath file1.wav) + Remove-Item (Join-Path -Path $testpath -ChildPath file2.wav) - Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeFalse - Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeFalse - } + Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeFalse + Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeFalse + } } Context "Directory Removal Tests" { - $testdirectory = Join-Path -Path $testpath -ChildPath testdir - $testsubdirectory = Join-Path -Path $testdirectory -ChildPath subd - BeforeEach { - New-Item -Name "testdir" -Path $testpath -ItemType "directory" -Force + BeforeAll { + $testdirectory = Join-Path -Path $testpath -ChildPath testdir + $testsubdirectory = Join-Path -Path $testdirectory -ChildPath subd + } + + BeforeEach { + New-Item -Name "testdir" -Path $testpath -ItemType "directory" -Force + + Test-Path $testdirectory | Should -BeTrue + } - Test-Path $testdirectory | Should -BeTrue - } + It "Should be able to remove a directory" { + { Remove-Item $testdirectory -ErrorAction Stop } | Should -Not -Throw - It "Should be able to remove a directory" { - { Remove-Item $testdirectory } | Should -Not -Throw + Test-Path $testdirectory | Should -BeFalse + } - Test-Path $testdirectory | Should -BeFalse - } + It "Should be able to recursively delete subfolders" { + New-Item -Name "subd" -Path $testdirectory -ItemType "directory" + New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum" - It "Should be able to recursively delete subfolders" { - New-Item -Name "subd" -Path $testdirectory -ItemType "directory" - New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum" + $complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile + Test-Path $complexDirectory | Should -BeTrue - $complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile - Test-Path $complexDirectory | Should -BeTrue + { Remove-Item $testdirectory -Recurse -ErrorAction Stop } | Should -Not -Throw - { Remove-Item $testdirectory -Recurse} | Should -Not -Throw + Test-Path $testdirectory | Should -BeFalse + } + + It "Should be able to recursively delete a directory with a trailing backslash" { + New-Item -Name "subd" -Path $testdirectory -ItemType "directory" + New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum" + + $complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile + Test-Path $complexDirectory | Should -BeTrue + + $testdirectoryWithBackSlash = Join-Path -Path $testdirectory -ChildPath ([IO.Path]::DirectorySeparatorChar) + Test-Path $testdirectoryWithBackSlash | Should -BeTrue + + { Remove-Item $testdirectoryWithBackSlash -Recurse -ErrorAction Stop } | Should -Not -Throw + + Test-Path $testdirectoryWithBackSlash | Should -BeFalse + Test-Path $testdirectory | Should -BeFalse + } + } - Test-Path $testdirectory | Should -BeFalse - } + Context "Alternate Data Streams should be supported on Windows" { + BeforeAll { + if (!$IsWindows) { + return + } + $fileName = "ADStest.txt" + $streamName = "teststream" + $dirName = "ADStestdir" + $fileContent =" This is file content." + $streamContent = "datastream content here" + $streamfile = Join-Path -Path $testpath -ChildPath $fileName + $streamdir = Join-Path -Path $testpath -ChildPath $dirName + + $null = New-Item -Path $streamfile -ItemType "File" -force + Add-Content -Path $streamfile -Value $fileContent + Add-Content -Path $streamfile -Stream $streamName -Value $streamContent + $null = New-Item -Path $streamdir -ItemType "Directory" -Force + Add-Content -Path $streamdir -Stream $streamName -Value $streamContent + } + + It "Should completely remove a datastream from a file" -Skip:(!$IsWindows) { + Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty + Remove-Item -Path $streamfile -Stream $streamName + Get-Item -Path $streamfile -Stream $streamName -ErrorAction SilentlyContinue | Should -BeNullOrEmpty + } + + It "Should completely remove a datastream from a directory" -Skip:(!$IsWindows) { + Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty + Remove-Item -Path $streamdir -Stream $streamName + Get-Item -Path $streamdir -Stream $streamname -ErrorAction SilentlyContinue | Should -BeNullOrEmpty + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 index 6e8f8bde083..fefd73412df 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 @@ -72,6 +72,39 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { $result[1] | Should -BeExactly "world" } } + Context "Set-Content should work with alternate data streams on Windows" { + BeforeAll { + if ( -Not $IsWindows ) + { + return + } + $altStreamPath = "$TESTDRIVE/altStream.txt" + $altStreamPath2 = "$TESTDRIVE/altStream2.txt" + $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $altStreamDirectory2 = "$TESTDRIVE/altstream2dir" + $stringData = "test data" + $streamName = "test" + $absentStreamName = "noExist" + $item = New-Item -type file $altStreamPath + $altstreamdiritem = New-Item -type directory $altStreamDirectory + } + It "Should create a new data stream on a file" -Skip:(-Not $IsWindows) { + Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData + Get-Content -Path $altStreamPath -Stream $streamName | Should -BeExactly $stringData + } + It "Should create a new data stream on a file using colon syntax" -Skip:(-Not $IsWindows) { + Set-Content -Path ${altStreamPath2}:${streamName} -Value $stringData + Get-Content -Path ${altStreamPath2} -Stream $streamName | Should -BeExactly $stringData + } + It "Should create a new data stream on a directory" -Skip:(-Not $IsWindows) { + Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData + Get-Content -Path $altStreamDirectory -Stream $streamName | Should -BeExactly $stringData + } + It "Should create a new data stream on a directory using colon syntax" -Skip:(-Not $IsWindows) { + Set-Content -Path ${altStreamDirectory2}:${streamName} -Value $stringData + Get-Content -Path ${altStreamDirectory2} -Stream ${streamName} | Should -BeExactly $stringData + } + } } Describe "Set-Content should work for PSDrive with UNC path as root" -Tags @('CI', 'RequireAdminOnWindows') { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Test-Connection.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Test-Connection.Tests.ps1 index bcd0562af85..c41b60c3ecb 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Test-Connection.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Test-Connection.Tests.ps1 @@ -44,6 +44,7 @@ Describe "Test-Connection" -tags "CI" { $targetAddress = "127.0.0.1" $targetAddressIPv6 = "::1" $UnreachableAddress = "10.11.12.13" + # under some environments, we can't round trip this and retrieve the real name from the address # in this case we will simply use the hostname $jobContinues = Start-Job { Test-Connection $using:targetAddress -Repeat } @@ -95,7 +96,8 @@ Describe "Test-Connection" -tags "CI" { { Test-Connection "fakeHost" -Count 1 -ErrorAction Stop } | Should -Throw -ErrorId "TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand" # Error code = 11001 - Host not found. - if ((Get-PlatformInfo).Platform -match "raspbian") { + $platform = Get-PlatformInfo + if ($platform.Platform -match "raspbian" -or ( $platform.Platform -match 'ubuntu' -and $platform.Version -eq '20.04')) { $code = 11 } elseif (!$IsWindows) { $code = -131073 @@ -105,7 +107,7 @@ Describe "Test-Connection" -tags "CI" { $error[0].Exception.InnerException.ErrorCode | Should -Be $code } - It "Force IPv4 with implicit PingOptions" -Pending { + It "Force IPv4 with implicit PingOptions" { $result = Test-Connection $testAddress -Count 1 -IPv4 $result[0].Address | Should -BeExactly $testAddress @@ -116,6 +118,7 @@ Describe "Test-Connection" -tags "CI" { } # In VSTS, address is 0.0.0.0 + # This test is marked as PENDING as .NET Core does not return correct PingOptions from ping request It "Force IPv4 with explicit PingOptions" -Pending { $result1 = Test-Connection $testAddress -Count 1 -IPv4 -MaxHops 10 -DontFragment @@ -259,7 +262,8 @@ Describe "Test-Connection" -tags "CI" { Context "MTUSizeDetect" { # We skip the MtuSize detection tests when in containers, as the environments throw raw exceptions # instead of returning a PacketTooBig response cleanly. - It "MTUSizeDetect works" -Pending:($true -or $env:__INCONTAINER -eq 1) { + # Test disabled due to .NET runtime issue: https://github.com/dotnet/runtime/issues/55961 + It "MTUSizeDetect works" -Pending:(($env:__INCONTAINER -eq 1) -or $IsMacOS) { $result = Test-Connection $testAddress -MtuSize $result | Should -BeOfType Microsoft.PowerShell.Commands.TestConnectionCommand+PingMtuStatus @@ -268,7 +272,8 @@ Describe "Test-Connection" -tags "CI" { $result.MtuSize | Should -BeGreaterThan 0 } - It "Quiet works" -Pending:($env:__INCONTAINER -eq 1) { + # Test disabled due to .NET runtime issue: https://github.com/dotnet/runtime/issues/55961 + It "Quiet works" -Pending:(($env:__INCONTAINER -eq 1) -or $IsMacOS) { $result = Test-Connection $gatewayAddress -MtuSize -Quiet $result | Should -BeOfType Int32 @@ -282,7 +287,7 @@ Describe "Test-Connection" -tags "CI" { $result = Test-Connection $testAddress -TraceRoute -IPv4 $result[0] | Should -BeOfType Microsoft.PowerShell.Commands.TestConnectionCommand+TraceStatus - $result[0].Source | Should -BeExactly $hostName + $result[0].Source | Should -BeExactly $testAddress $result[0].TargetAddress | Should -BeExactly $testAddress $result[0].Target | Should -BeExactly $testAddress $result[0].Hop | Should -Be 1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/UnixStat.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/UnixStat.Tests.ps1 index 1fe6113c92b..b14df30e7e2 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/UnixStat.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/UnixStat.Tests.ps1 @@ -1,25 +1,13 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. Describe "UnixFileSystem additions" -Tag "CI" { - # if PSUnixFileStat is converted from an experimental feature, these tests will need to be changed - BeforeAll { - $experimentalFeatureName = "PSUnixFileStat" - $skipTest = -not $EnabledExperimentalFeatures.Contains($experimentalFeatureName) - $PSDefaultParameterValues.Add('It:Skip', $skipTest) - } - AfterAll { - $PSDefaultParameterValues.Remove('It:Skip') - } Context "Basic Validation" { + BeforeAll { + $PSDefaultParameterValues.Add('It:Skip', $IsWindows) + } - It "Should be an experimental feature on non-Windows systems" { - $feature = Get-ExperimentalFeature -Name $experimentalFeatureName - if ( $IsWindows ) { - $feature | Should -BeNullOrEmpty - } - else { - $feature.Name | Should -Be $experimentalFeatureName - } + AfterAll { + $PSDefaultParameterValues.Remove('It:Skip') } It "Should include a UnixStat property" { @@ -36,9 +24,7 @@ Describe "UnixFileSystem additions" -Tag "CI" { Context "Validation of additional properties on file system objects" { BeforeAll { - if ( $IsWindows ) { - return - } + $PSDefaultParameterValues.Add('It:Skip', $IsWindows) $testDir = "${TestDrive}/TestDir" $testFile = "${testDir}/TestFile" @@ -55,6 +41,10 @@ Describe "UnixFileSystem additions" -Tag "CI" { @{ Mode = '1777'; Perm = 'drwxrwxrwt'; Item = "${testDir}" } } + AfterAll { + $PSDefaultParameterValues.Remove('It:Skip') + } + BeforeEach { $null = New-Item -ItemType Directory -Path "${testDir}" $null = New-Item -ItemType File -Path "${testFile}" @@ -87,7 +77,8 @@ Describe "UnixFileSystem additions" -Tag "CI" { Context "Other properties of UnixStat object" { BeforeAll { - if ( $IsWindows ) { + $PSDefaultParameterValues.Add('It:Skip', $IsWindows) + if ($IsWindows) { return } @@ -115,6 +106,10 @@ Describe "UnixFileSystem additions" -Tag "CI" { @{ Expected = $expectedDirSize; Observed = $Dir.UnixStat.Size; Title = "DirSize" } } + AfterAll { + $PSDefaultParameterValues.Remove('It:Skip') + } + It "Should have correct values in UnixStat property for ''" -TestCases $testCases { param ( $Title, $expected, $observed ) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1 index 047fcf9582a..e9397f86ec9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1 @@ -672,6 +672,41 @@ try } } + Describe "Add-Type in no language mode on locked down system" -Tags 'Feature','RequireAdminOnWindows' { + + It "Verifies Add-Type fails in no language mode when in system lock down" { + + # Create No-Language session, that allows Add-Type cmdlet + $entry = [System.Management.Automation.Runspaces.SessionStateCmdletEntry]::new('Add-Type', [Microsoft.PowerShell.Commands.AddTypeCommand], $null) + $iss = [initialsessionstate]::CreateRestricted([System.Management.Automation.SessionCapabilities]::Language) + $iss.Commands.Add($entry) + $rs = [runspacefactory]::CreateRunspace($iss) + $rs.Open() + + # Try to use Add-Type in No-Language session + $ps = [powershell]::Create($rs) + $ps.AddCommand('Add-Type').AddParameter('TypeDefinition', 'public class C1 { }') + $expectedError = $null + try + { + Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode + $ps.Invoke() + } + catch + { + $expectedError = $_ + } + finally + { + Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode + $rs.Dispose() + $ps.Dispose() + } + + $expectedError.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly 'CannotDefineNewType,Microsoft.PowerShell.Commands.AddTypeCommand' + } + } + Describe "Import-LocalizedData additional commands in constrained language" -Tags 'Feature','RequireAdminOnWindows' { It "Verifies Import-LocalizedData disallows Add-Type in constrained language" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 index 1a0f7e00954..df1fa9294e1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 @@ -1,5 +1,9 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. + +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] +param() + Describe "SecureString conversion tests" -Tags "CI" { BeforeAll { $string = "ABCD" @@ -7,12 +11,12 @@ Describe "SecureString conversion tests" -Tags "CI" { $string.ToCharArray() | ForEach-Object { $securestring.AppendChar($_) } } - It "using null arguments to ConvertFrom-SecureString produces an exception" { + It "Using null arguments to ConvertFrom-SecureString produces an exception" { { ConvertFrom-SecureString -SecureString $null -Key $null } | Should -Throw -ErrorId "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand" } - It "using a bad key produces an exception" { + It "Using a bad key produces an exception" { $badkey = [byte[]]@(1,2) { ConvertFrom-SecureString -SecureString $secureString -Key $badkey } | Should -Throw -ErrorId "Argument,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand" @@ -23,10 +27,18 @@ Describe "SecureString conversion tests" -Tags "CI" { $ss | Should -BeOfType SecureString } - It "can convert back from a secure string" { - $secret = "abcd" - $ss1 = ConvertTo-SecureString -AsPlainText -Force $secret + It "Can convert back from a secure string" { + $ss1 = ConvertTo-SecureString -AsPlainText -Force $string $ss2 = ConvertFrom-SecureString $ss1 | ConvertTo-SecureString - $ss2 | ConvertFrom-SecureString -AsPlainText | Should -Be $secret + $ss2 | ConvertFrom-SecureString -AsPlainText | Should -Be $string + } + + It "Can encode secure string with key" { + $testString = '[8Chars][8Chars][Not8]' + $key = [System.Text.Encoding]::UTF8.GetBytes("1234"*8) + $ss1 = $testString | ConvertTo-SecureString -AsPlainText -Force + $encodedStr = $ss1 | ConvertFrom-SecureString -Key $key + $ss2 = $encodedStr | ConvertTo-SecureString -Key $key + $ss2 | ConvertFrom-SecureString -AsPlainText | Should -BeExactly $testString } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 index b818dc64012..72d42af1d12 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 @@ -155,7 +155,13 @@ public class SMAAttributeTest$guid : PSCmdlet ## The assembly files cannot be removed once they are loaded, unless the current PowerShell session exits. ## If we use $TestDrive here, then Pester will try to remove them afterward and result in errors. - $TempPath = [System.IO.Path]::GetTempFileName() + if ($IsWindows) { + $TempPath = [System.IO.Path]::GetTempFileName() + } + else { + $TempPath = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } + if (Test-Path $TempPath) { Remove-Item -Path $TempPath -Force -Recurse } New-Item -Path $TempPath -ItemType Directory -Force > $null diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 index 494051507f7..129da4a9fde 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 @@ -49,7 +49,7 @@ Describe "ConvertTo-Csv" -Tags "CI" { It "Should output an array of objects" { $result = $testObject | ConvertTo-Csv - ,$result | Should -BeOfType System.Array + $result.GetType() | Should -Be ([object[]]) } It "Should return the type of data in the first element of the output array" { @@ -59,16 +59,16 @@ Describe "ConvertTo-Csv" -Tags "CI" { } It "Should return the column info in the second element of the output array" { - $result = $testObject | ConvertTo-Csv -IncludeTypeInformation + $result = $testObject | ConvertTo-Csv -IncludeTypeInformation $result[1] | Should -Match "`"FirstColumn`"" - $result[1] | Should -Match "`"SecondColumn`"" + $result[1] | Should -Match "`"SecondColumn`"" } It "Should return the data as a comma-separated list in the third element of the output array" { $result = $testObject | ConvertTo-Csv -IncludeTypeInformation $result[2] | Should -Match "`"Hello`"" - $result[2] | Should -Match "`"World`"" + $result[2] | Should -Match "`"World`"" } It "Includes type information when -IncludeTypeInformation is supplied" { @@ -109,7 +109,7 @@ Describe "ConvertTo-Csv" -Tags "CI" { $result[0] | Should -BeExactly "`"FirstColumn`",SecondColumn" $result[1] | Should -BeExactly "`"Hello`",World" - $result = $testObject | ConvertTo-Csv -QuoteFields FiRstCoLumn,SeCondCoLumn -Delimiter ',' + $result = $testObject | ConvertTo-Csv -QuoteFields FiRstCoLumn, SeCondCoLumn -Delimiter ',' $result[0] | Should -BeExactly "`"FirstColumn`",`"SecondColumn`"" $result[1] | Should -BeExactly "`"Hello`",`"World`"" @@ -159,5 +159,76 @@ Describe "ConvertTo-Csv" -Tags "CI" { $result[0] | Should -BeExactly "`"FirstColumn`"rSecondColumn" $result[1] | Should -BeExactly "Hellor" } + + It "UseQuotes AsNeeded Escapes Delimiters" { + $testDelimitersObject = [pscustomobject]@{ "FirstColumn" = "Hello,"; "Second,Column" = "World" }; + + $result = $testDelimitersObject | ConvertTo-Csv -UseQuotes AsNeeded -Delimiter ',' + + $result[0] | Should -BeExactly "FirstColumn,`"Second,Column`"" + $result[1] | Should -BeExactly "`"Hello,`",World" + + $result = $testDelimitersObject | ConvertTo-Csv -UseQuotes AsNeeded -Delimiter "r" + + $result[0] | Should -BeExactly "`"FirstColumn`"rSecond,Column" + $result[1] | Should -BeExactly "Hello,r`"World`"" + } + + It "UseQuotes AsNeeded Escapes Newlines" { + $testCRLFObject = [pscustomobject]@{ "First`r`nColumn" = "Hello`r`nWorld" }; + $testLFObject = [pscustomobject]@{ "First`nColumn" = "Hello`nWorld" }; + + $result = $testCRLFObject | ConvertTo-Csv -UseQuotes AsNeeded + + $result[0] | Should -BeExactly "`"First`r`nColumn`"" + $result[1] | Should -BeExactly "`"Hello`r`nWorld`"" + + $result = $testLFObject | ConvertTo-Csv -UseQuotes AsNeeded + + $result[0] | Should -BeExactly "`"First`nColumn`"" + $result[1] | Should -BeExactly "`"Hello`nWorld`"" + } + + It "UseQuotes AsNeeded Escapes Quotes" { + $testQuotesObject = [pscustomobject]@{ "First`"Column" = "`"Hello`" World" }; + + $result = $testQuotesObject | ConvertTo-Csv -UseQuotes AsNeeded + + $result[0] | Should -BeExactly "`"First`"`"Column`"" + $result[1] | Should -BeExactly "`"`"`"Hello`"`" World`"" + } + + } + + Context 'Converting IDictionary Objects' { + BeforeAll { + $Letters = 'A', 'B', 'C', 'D', 'E', 'F' + $Items = 0..5 | ForEach-Object { + [ordered]@{ Number = $_; Letter = $Letters[$_] } + } + $CsvString = $Items | ConvertTo-Csv + } + + It 'should treat dictionary entries as properties' { + $CsvString[0] | Should -MatchExactly ($Items[0].Keys -join '","') + + for ($i = 0; $i -lt $Items.Count; $i++) { + # Index in the CSV strings will be +1 due to header line + $ValuesPattern = $Items[$i].Values -join '","' + $CsvString[$i + 1] | Should -MatchExactly $ValuesPattern + } + } + + It 'should ignore regular object properties' { + $PropertyPattern = $Items[0].PSObject.Properties.Name -join '|' + $CsvString[0] | Should -Not -Match $PropertyPattern + } + + It 'should account for extended properties added deliberately' { + $Items | Add-Member -MemberType NoteProperty -Name 'Extra' -Value 'Surprise!' + $NewCsvString = $Items | ConvertTo-Csv + $NewCsvString[0] | Should -MatchExactly 'Extra' + $NewCsvString | Select-Object -Skip 1 | Should -MatchExactly 'Surprise!' + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index 7f44a854438..c549975b32c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -40,6 +40,34 @@ Describe 'ConvertTo-Json' -tags "CI" { $ps.Dispose() } + It "Should accept minimum depth as 0." { + $ComplexObject = [PSCustomObject] @{ + FirstLevel1 = @{ + Child1_1 = 0 + Bool = $True + } + FirstLevel2 = @{ + Child2_1 = 'Child_2_1_Value' + Child2_2 = @{ + ChildOfChild2_2= @(1,2,3) + } + Float = 1.2 + } + Integer = 10 + Bool = $False + } + + $ExpectedOutput = '{ + "FirstLevel1": "System.Collections.Hashtable", + "FirstLevel2": "System.Collections.Hashtable", + "Integer": 10, + "Bool": false +}' + + $output = $ComplexObject | ConvertTo-Json -Depth 0 + $output | Should -Be $ExpectedOutput + } + It "The result string is packed in an array symbols when AsArray parameter is used." { $output = 1 | ConvertTo-Json -AsArray $output | Should -BeLike "``[*1*]" @@ -103,4 +131,19 @@ Describe 'ConvertTo-Json' -tags "CI" { $p2.psobject.Properties.Remove('nullstr') } } + + It 'Should not serialize ETS properties added to DateTime' { + $date = "2021-06-24T15:54:06.796999-07:00" + $d = [DateTime]::Parse($date) + + # need to use wildcard here due to some systems may be configured with different culture setting showing time in different format + $d | ConvertTo-Json -Compress | Should -BeLike '"2021-06-24T*' + $d | ConvertTo-Json | ConvertFrom-Json | Should -Be $d + } + + It 'Should not serialize ETS properties added to String' { + $text = "Hello there" + $t = Add-Member -InputObject $text -MemberType NoteProperty -Name text -Value $text -PassThru + $t | ConvertTo-Json -Compress | Should -BeExactly "`"$text`"" + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1 index 484454e3a85..994d71601a7 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1 @@ -26,6 +26,67 @@ Describe 'ForEach-Object -Parallel Basic Tests' -Tags 'CI' { $result[1] | Should -BeExactly $varArray[1] } + It 'Verifies in scope using variables in nested calls' { + + $Test = "Test1" + $results = 1..2 | ForEach-Object -Parallel { + $using:Test + $Test = "Test2" + 1..2 | ForEach-Object -Parallel { + $using:Test + $Test = "Test3" + 1..2 | ForEach-Object -Parallel { + $using:Test + } + } + } + $results.Count | Should -BeExactly 14 + $groups = $results | Group-Object -AsHashTable + $groups['Test1'].Count | Should -BeExactly 2 + $groups['Test2'].Count | Should -BeExactly 4 + $groups['Test3'].Count | Should -BeExactly 8 + } + + It 'Verifies in scope using variables with different names in nested calls' { + $Test1 = "TestA" + $results = 1..2 | ForEach-Object -parallel { + $using:Test1 + $Test2 = "TestB" + 1..2 | ForEach-Object -parallel { + $using:Test2 + } + } + $results.Count | Should -BeExactly 6 + $groups = $results | Group-Object -AsHashTable + $groups['TestA'].Count | Should -BeExactly 2 + $groups['TestB'].Count | Should -BeExactly 4 + } + + It 'Verifies using variable in nested scriptblock' { + + $test = 'testC' + $results = 1..2 | ForEach-Object -parallel { + & { $using:test } + } + $results.Count | Should -BeExactly 2 + $groups = $results | Group-Object -AsHashTable + $groups['TestC'].Count | Should -BeExactly 2 + } + + It 'Verifies expected error for out of scope using variable in nested calls' { + + $Test = "TestZ" + 1..1 | ForEach-Object -Parallel { + $using:Test + # Variable '$Test' is not defined in this scope. + 1..1 | ForEach-Object -Parallel { + $using:Test + } + } -ErrorVariable usingErrors 2>$null + + $usingErrors[0].FullyQualifiedErrorId | Should -BeExactly 'UsingVariableIsUndefined,Microsoft.PowerShell.Commands.ForEachObjectCommand' + } + It 'Verifies terminating error streaming' { $result = 1..1 | ForEach-Object -Parallel { throw 'Terminating Error!'; "Hello" } 2>&1 @@ -77,6 +138,19 @@ Describe 'ForEach-Object -Parallel Basic Tests' -Tags 'CI' { $actualDebug.Message | Should -BeExactly 'Debug!' } + It 'Verifies progress data streaming' { + + $ps = [Powershell]::Create([System.Management.Automation.RunspaceMode]::NewRunspace) + + $ps.Commands.AddScript("`$ProgressPreference='Continue'; 1..2 | ForEach-Object -Parallel { Write-Progress -Activity Progress -Status Running }") | Out-Null + $ps.Invoke() + $pr = $ps.Streams.Progress.ReadAll() + $pr.Count | Should -Be 2 + $pr[0].Activity | Should -Be Progress + $pr[0].StatusDescription | Should -Be Running + $ps.Dispose() + } + It 'Verifies information data streaming' { $actualInformation = 1..1 | ForEach-Object -Parallel { Write-Information "Information!" } 6>&1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 index 92f4c3ff213..80aad6ef5b9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 @@ -26,7 +26,20 @@ Describe "Format-Custom" -Tags "CI" { } Describe "Format-Custom DRT basic functionality" -Tags "CI" { - Add-Type -TypeDefinition @" + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + + Add-Type -TypeDefinition @" public abstract class NamedItem { public string name; @@ -310,6 +323,11 @@ class MyLeaf2 Describe "Format-Custom with expression based EntrySelectedBy in a CustomControl" -Tags "CI" { BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + $formatFilePath = Join-Path $TestDrive 'UpdateFormatDataTests.format.ps1xml' $xmlContent = @' <?xml version="1.0" encoding="UTF-8" ?> @@ -389,6 +407,10 @@ Describe "Format-Custom with expression based EntrySelectedBy in a CustomControl } AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + $rs.Close() $ps.Dispose() } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 index a562ac40d19..715503c3577 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 @@ -1,7 +1,21 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. Describe "Format-List" -Tags "CI" { - $nl = [Environment]::NewLine + BeforeAll { + $nl = [Environment]::NewLine + + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + BeforeEach { $in = New-Object PSObject Add-Member -InputObject $in -MemberType NoteProperty -Name testName -Value testValue @@ -70,6 +84,19 @@ Describe "Format-List" -Tags "CI" { } Describe "Format-List DRT basic functionality" -Tags "CI" { + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + It "Format-List with array should work" { $al = (0..255) $info = @{} @@ -183,3 +210,23 @@ dbda : KM $actual | Should -BeExactly $expected } } + +Describe 'Format-List color tests' { + BeforeAll { + $originalRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'Ansi' + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForceFormatListFixedLabelWidth', $true) + } + + AfterAll { + $PSStyle.OutputRendering = $originalRendering + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForceFormatListFixedLabelWidth', $false) + } + + It 'Property names should use FormatAccent' { + $out = ([pscustomobject]@{Short=1;LongLabelName=2} | fl | out-string).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) + $out.Count | Should -Be 2 + $out[0] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)Short : $($PSStyle.Reset)1" -Because ($out[0] | Format-Hex) + $out[1] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)LongLabelN : $($PSStyle.Reset)2" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 index 2887e833314..3d4111e89a5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 @@ -1,6 +1,19 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. Describe "Format-Table" -Tags "CI" { + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + It "Should call format table on piped input without error" { { Get-Date | Format-Table } | Should -Not -Throw } @@ -833,3 +846,22 @@ A Name B ($actual.Replace("`r`n", "`n")) | Should -BeExactly ($expected.Replace("`r`n", "`n")) } } + +Describe 'Table color tests' { + BeforeAll { + $originalRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'Ansi' + } + + AfterAll { + $PSStyle.OutputRendering = $originalRendering + } + + It 'Table header should use FormatAccent' { + ([pscustomobject]@{foo = 1} | Format-Table | Out-String).Trim() | Should -BeExactly @" +$($PSStyle.Formatting.FormatAccent)foo$($PSStyle.Reset) +$($PSStyle.Formatting.FormatAccent)---$($PSStyle.Reset) + 1 +"@ + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Command.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Command.Tests.ps1 index 2dbc01c38db..1292992b092 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Command.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Command.Tests.ps1 @@ -178,5 +178,14 @@ Describe "Get-Command" -Tag CI { $Result | Should -BeOfType [System.Management.Automation.CommandInfo] } + + It "Throws '<expected>' exception if '<Name>' name is used" -TestCases @( + @{ Name = 'space'; Value = ' '; expected = "CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand" } + @{ Name = 'empty'; Value = ''; expected = "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetCommandCommand" } + @{ Name = 'null'; Value = $null; expected = "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetCommandCommand" } + ) { + param($value, $expected) + { Get-Command $value -ErrorAction Stop } | Should -Throw -ErrorId $expected + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 index 87670b0529b..d3c2295fa11 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 @@ -97,6 +97,137 @@ Describe "Get-Date DRT Unit Tests" -Tags "CI" { Get-Date -Date $date -UFormat %V | Should -BeExactly $week } + # Using the same test cases as V for ISO week date component parity, plus some more esoteric ones + It "using -uformat 'G' produces the correct output" -TestCases @( + @{date="0055-12-31"; year = "0055"}, + @{date="0325-01-01"; year = "0325"}, + @{date="0777-01-01"; year = "0776"}, + @{date="1998-01-02"; year = "1998"}, + @{date="1998-01-03"; year = "1998"}, + @{date="2003-01-03"; year = "2003"}, + @{date="2004-01-02"; year = "2004"}, + @{date="2004-01-03"; year = "2004"}, + @{date="2005-01-01"; year = "2004"}, + @{date="2005-01-02"; year = "2004"}, + @{date="2005-12-31"; year = "2005"}, + @{date="2006-01-01"; year = "2005"}, + @{date="2006-01-02"; year = "2006"}, + @{date="2006-12-31"; year = "2006"}, + @{date="2007-01-01"; year = "2007"}, + @{date="2007-12-30"; year = "2007"}, + @{date="2007-12-31"; year = "2008"}, + @{date="2008-01-01"; year = "2008"}, + @{date="2008-12-28"; year = "2008"}, + @{date="2008-12-29"; year = "2009"}, + @{date="2008-12-30"; year = "2009"}, + @{date="2008-12-31"; year = "2009"}, + @{date="2009-01-01"; year = "2009"}, + @{date="2009-01-02"; year = "2009"}, + @{date="2009-01-03"; year = "2009"}, + @{date="2009-12-31"; year = "2009"}, + @{date="2010-01-01"; year = "2009"}, + @{date="2010-01-02"; year = "2009"}, + @{date="2010-01-03"; year = "2009"}, + @{date="2010-01-04"; year = "2010"}, + @{date="2014-01-03"; year = "2014"}, + @{date="2015-01-02"; year = "2015"}, + @{date="2015-01-03"; year = "2015"}, + @{date="2020-01-03"; year = "2020"}, + @{date="2025-01-03"; year = "2025"}, + @{date="2026-01-02"; year = "2026"}, + @{date="2026-01-03"; year = "2026"}, + @{date="2031-01-03"; year = "2031"} + ) { + param($date, $year) + Get-Date -Date $date -UFormat %G | Should -BeExactly $year + } + + # Using the same test cases as V for ISO week date component parity, plus some more esoteric ones + It "using -uformat 'g' produces the correct output" -TestCases @( + @{date="0055-12-31"; yy = "55"}, + @{date="0325-01-01"; yy = "25"}, + @{date="0777-01-01"; yy = "76"}, + @{date="1998-01-02"; yy = "98"}, + @{date="1998-01-03"; yy = "98"}, + @{date="2003-01-03"; yy = "03"}, + @{date="2004-01-02"; yy = "04"}, + @{date="2004-01-03"; yy = "04"}, + @{date="2005-01-01"; yy = "04"}, + @{date="2005-01-02"; yy = "04"}, + @{date="2005-12-31"; yy = "05"}, + @{date="2006-01-01"; yy = "05"}, + @{date="2006-01-02"; yy = "06"}, + @{date="2006-12-31"; yy = "06"}, + @{date="2007-01-01"; yy = "07"}, + @{date="2007-12-30"; yy = "07"}, + @{date="2007-12-31"; yy = "08"}, + @{date="2008-01-01"; yy = "08"}, + @{date="2008-12-28"; yy = "08"}, + @{date="2008-12-29"; yy = "09"}, + @{date="2008-12-30"; yy = "09"}, + @{date="2008-12-31"; yy = "09"}, + @{date="2009-01-01"; yy = "09"}, + @{date="2009-01-02"; yy = "09"}, + @{date="2009-01-03"; yy = "09"}, + @{date="2009-12-31"; yy = "09"}, + @{date="2010-01-01"; yy = "09"}, + @{date="2010-01-02"; yy = "09"}, + @{date="2010-01-03"; yy = "09"}, + @{date="2010-01-04"; yy = "10"}, + @{date="2014-01-03"; yy = "14"}, + @{date="2015-01-02"; yy = "15"}, + @{date="2015-01-03"; yy = "15"}, + @{date="2020-01-03"; yy = "20"}, + @{date="2025-01-03"; yy = "25"}, + @{date="2026-01-02"; yy = "26"}, + @{date="2026-01-03"; yy = "26"}, + @{date="2031-01-03"; yy = "31"} + ) { + param($date, $yy) + Get-Date -Date $date -UFormat %g | Should -BeExactly $yy + } + + # Using the same test cases as V for ISO week date component parity + It "using -uformat 'u' produces the correct output" -TestCases @( + @{date="1998-01-02"; dayOfWeek = "5"}, + @{date="1998-01-03"; dayOfWeek = "6"}, + @{date="2003-01-03"; dayOfWeek = "5"}, + @{date="2004-01-02"; dayOfWeek = "5"}, + @{date="2004-01-03"; dayOfWeek = "6"}, + @{date="2005-01-01"; dayOfWeek = "6"}, + @{date="2005-01-02"; dayOfWeek = "7"}, + @{date="2005-12-31"; dayOfWeek = "6"}, + @{date="2006-01-01"; dayOfWeek = "7"}, + @{date="2006-01-02"; dayOfWeek = "1"}, + @{date="2006-12-31"; dayOfWeek = "7"}, + @{date="2007-01-01"; dayOfWeek = "1"}, + @{date="2007-12-30"; dayOfWeek = "7"}, + @{date="2007-12-31"; dayOfWeek = "1"}, + @{date="2008-01-01"; dayOfWeek = "2"}, + @{date="2008-12-28"; dayOfWeek = "7"}, + @{date="2008-12-29"; dayOfWeek = "1"}, + @{date="2008-12-30"; dayOfWeek = "2"}, + @{date="2008-12-31"; dayOfWeek = "3"}, + @{date="2009-01-01"; dayOfWeek = "4"}, + @{date="2009-01-02"; dayOfWeek = "5"}, + @{date="2009-01-03"; dayOfWeek = "6"}, + @{date="2009-12-31"; dayOfWeek = "4"}, + @{date="2010-01-01"; dayOfWeek = "5"}, + @{date="2010-01-02"; dayOfWeek = "6"}, + @{date="2010-01-03"; dayOfWeek = "7"}, + @{date="2010-01-04"; dayOfWeek = "1"}, + @{date="2014-01-03"; dayOfWeek = "5"}, + @{date="2015-01-02"; dayOfWeek = "5"}, + @{date="2015-01-03"; dayOfWeek = "6"}, + @{date="2020-01-03"; dayOfWeek = "5"}, + @{date="2025-01-03"; dayOfWeek = "5"}, + @{date="2026-01-02"; dayOfWeek = "5"}, + @{date="2026-01-03"; dayOfWeek = "6"}, + @{date="2031-01-03"; dayOfWeek = "5"} + ) { + param($date, $dayOfWeek) + Get-Date -Date $date -UFormat %u | Should -BeExactly $dayOfWeek + } It "Passing '<name>' to -uformat produces a descriptive error" -TestCases @( @{ name = "`$null" ; value = $null; errorId = "ParameterArgumentValidationErrorNullNotAllowed" } @{ name = "empty string"; value = ""; errorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed" } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Error.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Error.Tests.ps1 index 88c3d898cf9..651eaa287dd 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Error.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Error.Tests.ps1 @@ -125,4 +125,32 @@ Describe 'Get-Error tests' -Tag CI { $out | Should -BeLikeExactly "*$expectedExceptionType*" } + + It 'Get-Error uses Error color for Message and PositionMessage members' { + $suppressVT = $false + if (Test-Path env:/__SuppressAnsiEscapeSequences) { + $suppressVT = $true + $env:__SuppressAnsiEscapeSequences = $null + } + + try { + $originalRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'Ansi' + $out = pwsh -noprofile -command '$PSStyle.OutputRendering = "ANSI"; [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("BypassOutputRedirectionCheck", $true); try { 1/0 } catch { }; Get-Error' | Out-String + + # need to escape the open square bracket so the regex works + $resetColor = $PSStyle.Reset.Replace('[','\[') + $errorColor = $PSStyle.Formatting.Error.Replace('[','\[') + $out | Should -Match "Message +: ${resetColor}${errorColor}[A-z]+" + # match the position message underline + $out | Should -Match ".*?${errorColor}~~~" + } + finally + { + $PSStyle.OutputRendering = $originalRendering + if ($suppressVT) { + $env:__SuppressAnsiEscapeSequences = 1 + } + } + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-FormatData.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-FormatData.Tests.ps1 index 04bffe8df82..d420e6ce085 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-FormatData.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-FormatData.Tests.ps1 @@ -21,13 +21,19 @@ Describe "Get-FormatData" -Tags "CI" { } It "Can get format data requiring v5.1+ with <cmd>" -TestCases $cmds { param([scriptblock] $cmd) + + if ($IsWindows) { + $expectedCount = 4 + } else { + # UnixStat addes extra one + $expectedCount = 5 + } + $format = & $cmd $format.TypeNames | Should -HaveCount 2 $format.TypeNames[0] | Should -BeExactly "System.IO.DirectoryInfo" $format.TypeNames[1] | Should -BeExactly "System.IO.FileInfo" - - $isUnixStatEnabled = $EnabledExperimentalFeatures -contains 'PSUnixFileStat' - $format.FormatViewDefinition | Should -HaveCount ($isUnixStatEnabled ? 5 : 4) + $format.FormatViewDefinition | Should -HaveCount $expectedCount } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Json.Tests.ps1 index acd3f095d8d..d3713963f96 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Json.Tests.ps1 @@ -345,6 +345,258 @@ Describe "Json Tests" -Tags "Feature" { ValidateSampleObject -result $result -hasEmbeddedSampleObject } + It "ConvertFrom-Json correctly processes datetimes vs strings using newtonsoft conventions" { + # Create all the various "standard" date formats from a source date 2008-09-22T14:01:54.9571247Z + # Then we deserialize them and verify which ones newtonsoft decides to make into datetimes and which ones newtonsoft keeps as strings + # For the ones that are datetimes, make sure they retain all of the various formats correctly + # for the ones that are strings just verify that they are actually strings. + + $json = @" +{ + "date-s-should-parse-as-datetime": "2008-09-22T14:01:54", + "date-upperO-should-parse-as-datetime": "2008-09-22T14:01:54.9571247Z", + + "date-o-should-parse-as-string": "2019-12-17T06:14:06 +06:00", + "date-upperD-should-parse-as-string": "Monday, September 22, 2008", + "date-f-should-parse-as-string": "Monday, September 22, 2008 2:01 PM", + "date-upperF-should-parse-as-string": "Monday, September 22, 2008 2:01:54 PM", + "date-g-should-parse-as-string": "9/22/2008 2:01 PM", + "date-upperG-should-parse-as-string": "9/22/2008 2:01:54 PM", + "date-m-should-parse-as-string": "September 22", + "date-upperM-should-parse-as-string": "September 22", + "date-upperR-should-parse-as-string": "Mon, 22 Sep 2008 14:01:54 GMT", + "date-t-should-parse-as-string": "2:01 PM", + "date-upperT-should-parse-as-string": "2:01:54 PM", + "date-u-should-parse-as-string": "2008-09-22 14:01:54Z", + "date-upperU-should-parse-as-string": "Monday, September 22, 2008 2:01:54 PM", + "date-upperY-should-parse-as-string": "September 2008", + "date-y-should-parse-as-string": "September 2008" +} +"@ + foreach ($asHashtableOption in @($True, $False)) { + $result = ConvertFrom-Json $json -AsHashtable:$asHashtableOption + + # If the timezone is not specified in the input string newtonsoft assumes the system timezone. + # this means that some tests will fail locally but work on the build farm and vice-versa. + # this is used to force the datetime into UTC without changing the value so 4PM Central becomes 4PM UTC instead of becoming 10PM UTC + $result."date-s-should-parse-as-datetime" = [datetime]::SpecifyKind($result."date-s-should-parse-as-datetime", [System.DateTimeKind]::Utc) + $result."date-s-should-parse-as-datetime".ToString("d") | Should -Be "9/22/2008" + $result."date-s-should-parse-as-datetime".ToString("D") | Should -Be "Monday, September 22, 2008" + $result."date-s-should-parse-as-datetime".ToString("f") | Should -Be "Monday, September 22, 2008 2:01 PM" + $result."date-s-should-parse-as-datetime".ToString("F") | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-s-should-parse-as-datetime".ToString("g") | Should -Be "9/22/2008 2:01 PM" + $result."date-s-should-parse-as-datetime".ToString("G") | Should -Be "9/22/2008 2:01:54 PM" + $result."date-s-should-parse-as-datetime".ToString("m") | Should -Be "September 22" + $result."date-s-should-parse-as-datetime".ToString("M") | Should -Be "September 22" + $result."date-s-should-parse-as-datetime".ToString("o") | Should -Be "2008-09-22T14:01:54.0000000Z" + $result."date-s-should-parse-as-datetime".ToString("O") | Should -Be "2008-09-22T14:01:54.0000000Z" + $result."date-s-should-parse-as-datetime".ToString("R") | Should -Be "Mon, 22 Sep 2008 14:01:54 GMT" + $result."date-s-should-parse-as-datetime".ToString("s") | Should -Be "2008-09-22T14:01:54" + $result."date-s-should-parse-as-datetime".ToString("t") | Should -Be "2:01 PM" + $result."date-s-should-parse-as-datetime".ToString("T") | Should -Be "2:01:54 PM" + $result."date-s-should-parse-as-datetime".ToString("u") | Should -Be "2008-09-22 14:01:54Z" + $result."date-s-should-parse-as-datetime".ToString("U") | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-s-should-parse-as-datetime".ToString("Y") | Should -Be "September 2008" + $result."date-s-should-parse-as-datetime".ToString("y") | Should -Be "September 2008" + $result."date-s-should-parse-as-datetime" | Should -BeOfType [DateTime] + + $result."date-upperO-should-parse-as-datetime" = [datetime]::SpecifyKind($result."date-upperO-should-parse-as-datetime", [System.DateTimeKind]::Utc) + $result."date-upperO-should-parse-as-datetime".ToString("d") | Should -Be "9/22/2008" + $result."date-upperO-should-parse-as-datetime".ToString("D") | Should -Be "Monday, September 22, 2008" + $result."date-upperO-should-parse-as-datetime".ToString("f") | Should -Be "Monday, September 22, 2008 2:01 PM" + $result."date-upperO-should-parse-as-datetime".ToString("F") | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-upperO-should-parse-as-datetime".ToString("g") | Should -Be "9/22/2008 2:01 PM" + $result."date-upperO-should-parse-as-datetime".ToString("G") | Should -Be "9/22/2008 2:01:54 PM" + $result."date-upperO-should-parse-as-datetime".ToString("m") | Should -Be "September 22" + $result."date-upperO-should-parse-as-datetime".ToString("M") | Should -Be "September 22" + $result."date-upperO-should-parse-as-datetime".ToString("o") | Should -Be "2008-09-22T14:01:54.9571247Z" + $result."date-upperO-should-parse-as-datetime".ToString("O") | Should -Be "2008-09-22T14:01:54.9571247Z" + $result."date-upperO-should-parse-as-datetime".ToString("R") | Should -Be "Mon, 22 Sep 2008 14:01:54 GMT" + $result."date-upperO-should-parse-as-datetime".ToString("s") | Should -Be "2008-09-22T14:01:54" + $result."date-upperO-should-parse-as-datetime".ToString("t") | Should -Be "2:01 PM" + $result."date-upperO-should-parse-as-datetime".ToString("T") | Should -Be "2:01:54 PM" + $result."date-upperO-should-parse-as-datetime".ToString("u") | Should -Be "2008-09-22 14:01:54Z" + $result."date-upperO-should-parse-as-datetime".ToString("U") | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-upperO-should-parse-as-datetime".ToString("Y") | Should -Be "September 2008" + $result."date-upperO-should-parse-as-datetime".ToString("y") | Should -Be "September 2008" + $result."date-upperO-should-parse-as-datetime" | Should -BeOfType [DateTime] + + $result."date-o-should-parse-as-string" | Should -Be "2019-12-17T06:14:06 +06:00" + $result."date-o-should-parse-as-string" | Should -BeOfType [String] + $result."date-f-should-parse-as-string" | Should -Be "Monday, September 22, 2008 2:01 PM" + $result."date-f-should-parse-as-string" | Should -BeOfType [String] + $result."date-g-should-parse-as-string" | Should -Be "9/22/2008 2:01 PM" + $result."date-g-should-parse-as-string" | Should -BeOfType [String] + $result."date-m-should-parse-as-string" | Should -Be "September 22" + $result."date-m-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperM-should-parse-as-string" | Should -Be "September 22" + $result."date-upperM-should-parse-as-string" | Should -BeOfType [String] + $result."date-t-should-parse-as-string" | Should -Be "2:01 PM" + $result."date-t-should-parse-as-string" | Should -BeOfType [String] + $result."date-u-should-parse-as-string" | Should -Be "2008-09-22 14:01:54Z" + $result."date-u-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperD-should-parse-as-string" | Should -Be "Monday, September 22, 2008" + $result."date-upperD-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperF-should-parse-as-string" | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-upperF-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperG-should-parse-as-string" | Should -Be "9/22/2008 2:01:54 PM" + $result."date-upperG-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperR-should-parse-as-string" | Should -Be "Mon, 22 Sep 2008 14:01:54 GMT" + $result."date-upperR-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperT-should-parse-as-string" | Should -Be "2:01:54 PM" + $result."date-upperT-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperU-should-parse-as-string" | Should -Be "Monday, September 22, 2008 2:01:54 PM" + $result."date-upperU-should-parse-as-string" | Should -BeOfType [String] + $result."date-upperY-should-parse-as-string" | Should -Be "September 2008" + $result."date-upperY-should-parse-as-string" | Should -BeOfType [String] + $result."date-y-should-parse-as-string" | Should -Be "September 2008" + $result."date-y-should-parse-as-string" | Should -BeOfType [String] + } + } + + It "ConvertFrom-Json properly parses complex objects" { + $json = @" +{ +"_id": "60dd3ea9253016932039a0a2", +"index": 0, +"guid": "429b96a7-24e3-47de-a93b-f44a346c5ac9", +"isActive": false, +"balance": "$2,039.72", +"picture": "http://placehold.it/32x32", +"age": 35, +"eyeColor": "green", +"name": "Rhodes Roberson", +"gender": "male", +"company": "INSECTUS", +"email": "rhodesroberson@insectus.com", +"phone": "+1 (883) 561-3999", +"address": "931 Kings Place, Hartsville/Hartley, Federated States Of Micronesia, 9344", +"about": "Ipsum pariatur nisi eiusmod aliquip in cupidatat. Deserunt non sit anim consectetur consectetur incididunt elit qui id proident nostrud. Consectetur pariatur et adipisicing aliquip fugiat fugiat Lorem reprehenderit laboris magna. Duis veniam irure amet ex minim eiusmod et laborum non elit. Dolor enim Lorem occaecat nisi consectetur mollit laborum anim velit et. Irure aliquip eiusmod anim proident ex ea duis deserunt aute amet adipisicing nisi nostrud. Minim ipsum fugiat consequat mollit fugiat tempor fugiat.", +"registered": "2019-12-17T06:14:06 +06:00", +"latitude": 51.890798, +"longitude": -47.522764, +"tags": [ + "laboris", + "voluptate", + "amet", + "ad", + "velit", + "ipsum", + "do" +], +"friends": [ + { + "id": 0, + "name": "Renee Holden" + }, + { + "id": 1, + "name": "Bennett Dixon" + }, + { + "id": 2, + "name": "Emilia Holder" + } +], +"greeting": "Hello, Rhodes Roberson! You have 9 unread messages.", +"favoriteFruit": "banana" +} +"@ + $result = ConvertFrom-Json $Json + $result."about"| Should -BeExactly "Ipsum pariatur nisi eiusmod aliquip in cupidatat. Deserunt non sit anim consectetur consectetur incididunt elit qui id proident nostrud. Consectetur pariatur et adipisicing aliquip fugiat fugiat Lorem reprehenderit laboris magna. Duis veniam irure amet ex minim eiusmod et laborum non elit. Dolor enim Lorem occaecat nisi consectetur mollit laborum anim velit et. Irure aliquip eiusmod anim proident ex ea duis deserunt aute amet adipisicing nisi nostrud. Minim ipsum fugiat consequat mollit fugiat tempor fugiat." + $result."about" | Should -BeOfType [String] + $result."address"| Should -BeExactly "931 Kings Place, Hartsville/Hartley, Federated States Of Micronesia, 9344" + $result."address" | Should -BeOfType [String] + $result."age" | Should -BeOfType [Int64] + $result."balance"| Should -BeExactly ",039.72" + $result."balance" | Should -BeOfType [String] + $result."company"| Should -BeExactly "INSECTUS" + $result."company" | Should -BeOfType [String] + $result."email"| Should -BeExactly "rhodesroberson@insectus.com" + $result."email" | Should -BeOfType [String] + $result."eyeColor"| Should -BeExactly "green" + $result."eyeColor" | Should -BeOfType [String] + $result."favoriteFruit"| Should -BeExactly "banana" + $result."favoriteFruit" | Should -BeOfType [String] + $result."gender"| Should -BeExactly "male" + $result."gender" | Should -BeOfType [String] + $result."greeting"| Should -BeExactly "Hello, Rhodes Roberson! You have 9 unread messages." + $result."greeting" | Should -BeOfType [String] + $result."guid"| Should -BeExactly "429b96a7-24e3-47de-a93b-f44a346c5ac9" + $result."guid" | Should -BeOfType [String] + $result."index" | Should -BeOfType [Int64] + $result."isActive"| Should -Be False + $result."isActive" | Should -BeOfType [Boolean] + $result."latitude"| Should -Be 51.890798 + $result."latitude" | Should -BeOfType [Double] + $result."longitude"| Should -Be -47.522764 + $result."longitude" | Should -BeOfType [Double] + $result."name"| Should -BeExactly "Rhodes Roberson" + $result."name" | Should -BeOfType [String] + $result."phone"| Should -BeExactly "+1 (883) 561-3999" + $result."phone" | Should -BeOfType [String] + $result."picture"| Should -BeExactly "http://placehold.it/32x32" + $result."picture" | Should -BeOfType [String] + $result."registered"| Should -BeExactly "2019-12-17T06:14:06 +06:00" + $result."registered" | Should -BeOfType [String] + $result."_id"| Should -BeExactly "60dd3ea9253016932039a0a2" + $result."_id" | Should -BeOfType [String] + + $result.Tags | Should -BeOfType [string] + + $result.Tags.count | Should -Be 7 + $result.Tags[0] | Should -BeExactly "laboris" + $result.Tags | Should -Be @("laboris", "voluptate", "amet", "ad", "velit", "ipsum", "do") + + $result.Friends | Should -BeOfType [pscustomobject] + $result.Friends[0].id | Should -Be 0 + $result.Friends[0].name | Should -BeExactly "Renee Holden" + $result.Friends[1].id | Should -Be 1 + $result.Friends[1].name | Should -BeExactly "Bennett Dixon" + $result.Friends[2].id | Should -Be 2 + $result.Friends[2].name | Should -BeExactly "Emilia Holder" + } + + It "ConvertFrom-Json chooses the appropriate number type" { + ConvertFrom-Json -InputObject "5" | should -Be 5 + ConvertFrom-Json -InputObject 5 | should -Be 5 + ConvertFrom-Json -InputObject "5" | should -BeOfType [int64] + ConvertFrom-Json -InputObject 5 | should -BeOfType [int64] + ConvertFrom-Json -InputObject 5000000000000 | should -Be 5000000000000 + ConvertFrom-Json -InputObject "5000000000000" | should -Be "5000000000000" + ConvertFrom-Json -InputObject "5000000000000" | should -BeOfType [int64] + ConvertFrom-Json -InputObject 5000000000000 | should -BeOfType [int64] + ConvertFrom-Json -InputObject "5.0" | should -Be 5.0 + ConvertFrom-Json -InputObject 5.0 | should -Be 5.0 + ConvertFrom-Json -InputObject "5.0" | should -BeOfType [double] + ConvertFrom-Json -InputObject 5.0 | should -BeOfType [double] + + # The decimal is lost but only when this is quoted + ConvertFrom-Json -InputObject "500000000000.0000000000000001" | should -Be "500000000000" + + # Counter intuitively all four of these tests pass because precision is lost on both sides of the test, likely due to powershell number handling + ConvertFrom-Json -InputObject 500000000000.0000000000000001 | should -Be 500000000000 + ConvertFrom-Json -InputObject 500000000000.0000000000000001 | should -Be 500000000000.0000000000000001 + ConvertFrom-Json -InputObject 500000000000 | should -Be 500000000000.0000000000000001 + ConvertFrom-Json -InputObject 500000000000 | should -Be 500000000000 + + ConvertFrom-Json -InputObject "500000000000.0000000000000001" | should -BeOfType [double] + ConvertFrom-Json -InputObject 500000000000.0000000000000001 | should -BeOfType [double] + + # these tests also pass because precision is lost during conversion/powershell handling + ConvertFrom-Json -InputObject "50000000000000000000000000000000000.0000000000000001" | should -Be "5E+34" + ConvertFrom-Json -InputObject 50000000000000000000000000000000000.0000000000000001 | should -Be "5E+34" + + ConvertFrom-Json -InputObject "50000000000000000000000000000000000.0000000000000001" | should -BeOfType [double] + ConvertFrom-Json -InputObject 50000000000000000000000000000000000.0000000000000001 | should -BeOfType [double] + + + ConvertFrom-Json -InputObject "50000000000000000000000000000000000" | should -Be 50000000000000000000000000000000000 + ConvertFrom-Json -InputObject 50000000000000000000000000000000000 | should -Be 50000000000000000000000000000000000 + ConvertFrom-Json -InputObject "50000000000000000000000000000000000" | should -BeOfType [BigInt] + ConvertFrom-Json -InputObject 50000000000000000000000000000000000 | should -BeOfType [BigInt] + } + It "ConvertFrom-Json with special characters" { $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' @@ -1463,4 +1715,11 @@ Describe "Json Bug fixes" -Tags "Feature" { $result = "[1,","2,","3]" | ConvertFrom-Json $result.Count | Should -Be 3 } + + It 'ConvertTo-Json will output warning if depth is exceeded.' { + $a = @{ a = @{ b = @{ c = @{ d = 1 } } } } + $json = $a | ConvertTo-Json -Depth 2 -WarningVariable warningMessage -WarningAction SilentlyContinue + $json | Should -Not -BeNullOrEmpty + $warningMessage | Should -Not -BeNullOrEmpty + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 index ea96741de3a..b1cf1b36d39 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 @@ -64,10 +64,13 @@ Describe "Measure-Object" -Tags "CI" { } It "Should be able to count using the Property switch" { - $expected = $(Get-ChildItem $TestDrive).Length - $actual = $(Get-ChildItem $TestDrive | Measure-Object -Property Length).Count + $items = @( + [pscustomobject]@{ X = 'a'; Y = 'b' } + [pscustomobject]@{ X = 'c' } + [pscustomobject]@{ X = 'e'; Y = 'f' } + ) - $actual | Should -Be $expected + ($items | Measure-Object -Property Y).Count | Should -Be 2 } It "Should be able to use wildcards for the Property argument" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 index 912db06f78a..6803ee8e132 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 @@ -21,11 +21,22 @@ Describe "Out-File DRT Unit Tests" -Tags "CI" { Describe "Out-File" -Tags "CI" { BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + $expectedContent = "some test text" $inObject = New-Object psobject -Property @{text=$expectedContent} $testfile = Join-Path -Path $TestDrive -ChildPath outfileTest.txt } + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + AfterEach { Remove-Item -Path $testfile -Force } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 index 6d13be5005b..cfba4a4cbed 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -1,6 +1,15 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "CI" { + BeforeAll { + $largePsd1Path = Join-Path -Path $TestDrive -ChildPath 'large.psd1' + $largePsd1Builder = [System.Text.StringBuilder]::new('@{') + 1..501 | ForEach-Object { + $largePsd1Builder.Append("key$_ = $_;") + } + $largePsd1Builder.Append('}') + Set-Content -Path $largePsd1Path -Value $largePsd1Builder.ToString() + } It "Validates error on a missing path" { { Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop } | @@ -32,4 +41,12 @@ Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "CI" { $result.Hello | Should -BeExactly "World" } + It 'Fails if psd1 file has more than 500 keys' { + { Import-PowerShellDataFile $largePsd1Path } | Should -Throw -ErrorId 'System.InvalidOperationException,Microsoft.PowerShell.Commands.ImportPowerShellDataFileCommand' + } + + It 'Succeeds if -NoLimit is used and has more than 500 keys' { + $result = Import-PowerShellDataFile $largePsd1Path -SkipLimitCheck + $result.Keys.Count | Should -Be 501 + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/RunspaceBreakpointManagement.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/RunspaceBreakpointManagement.Tests.ps1 index fe131f99117..75fb0d98358 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/RunspaceBreakpointManagement.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/RunspaceBreakpointManagement.Tests.ps1 @@ -1,18 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -$FeatureEnabled = $EnabledExperimentalFeatures.Contains('Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace') - Describe 'Runspace Breakpoint Unit Tests - Feature-Enabled' -Tags 'CI' { BeforeAll { - if (!$FeatureEnabled) { - Write-Verbose 'Test series skipped. This series of tests requires the experimental feature ''Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace'' to be enabled.' -Verbose - $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() - $PSDefaultParameterValues['it:skip'] = $true - return - } - # Start a job; this will create a runspace in which we can manage breakpoints $job = Start-Job -ScriptBlock { Set-PSBreakpoint -Command Start-Sleep @@ -37,11 +28,6 @@ Describe 'Runspace Breakpoint Unit Tests - Feature-Enabled' -Tags 'CI' { } AfterAll { - if (!$FeatureEnabled) { - $global:PSDefaultParameterValues = $originalDefaultParameterValues - return - } - # Remove the running job forcibly (whether it has finished or not) Remove-Job -Job $job -Force } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 index 68c238abb78..0351001cb99 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 @@ -5,9 +5,12 @@ Describe "Select-String" -Tags "CI" { BeforeAll { $nl = [Environment]::NewLine $currentDirectory = $PWD.Path + $originalRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'Ansi' } AfterAll { + $PSStyle.OutputRendering = $originalRendering Push-Location $currentDirectory } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-PSBreakpoint.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-PSBreakpoint.Tests.ps1 index 21c84fe4770..a5b809d8f15 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-PSBreakpoint.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-PSBreakpoint.Tests.ps1 @@ -154,7 +154,14 @@ set-psbreakpoint -command foo } It "Fail to set psbreakpoints when script is a file of wrong type" { - $tempFile = [System.IO.Path]::GetTempFileName() + + if ($IsWindows) { + $tempFile = [System.IO.Path]::GetTempFileName() + } + else { + $tempFile = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } + $ErrorActionPreference = "Stop" { Set-PSBreakpoint -Script $tempFile -Line 1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 index fe1b105ed04..0b6b9c59dfc 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 @@ -146,6 +146,23 @@ Describe "Set-Variable DRT Unit Tests" -Tags "CI" { } Describe "Set-Variable" -Tags "CI" { + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + + $expectedContent = "some test text" + $inObject = New-Object psobject -Property @{text=$expectedContent} + $testfile = Join-Path -Path $TestDrive -ChildPath outfileTest.txt + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } + It "Should create a new variable with no parameters" { { Set-Variable testVar } | Should -Not -Throw } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Tee-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Tee-Object.Tests.ps1 index 01527be8435..7483c4d8004 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Tee-Object.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Tee-Object.Tests.ps1 @@ -4,21 +4,39 @@ Describe "Tee-Object" -Tags "CI" { Context "Validate Tee-Object is correctly forking output" { - $testfile = Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath assets) -ChildPath testfile.txt + BeforeAll { + $testfile = Join-Path $TestDrive -ChildPath "testfile.txt" + $testvalue = "ф" + if ($IsWindows) { + # Expected bytes: 244 - 'ф', 13 - '`r', 10 - '`n'. + $expectedBytes = 244,13,10 -join "-" + } else { + $expectedBytes = 244,10 -join "-" + } + } + + BeforeEach { + Remove-Item -Path $testfile -ErrorAction SilentlyContinue -Force + } It "Should return the output to the screen and to the variable" { - $teefile = $testfile Write-Output teeobjecttest1 | Tee-Object -Variable teeresults - $teeresults | Should -BeExactly "teeobjecttest1" - Remove-Item $teefile -ErrorAction SilentlyContinue + $teeresults | Should -BeExactly "teeobjecttest1" } It "Should tee the output to a file" { $teefile = $testfile Write-Output teeobjecttest3 | Tee-Object $teefile Get-Content $teefile | Should -BeExactly "teeobjecttest3" - Remove-Item $teefile -ErrorAction SilentlyContinue - } + } + + It "Parameter 'Encoding' should accept encoding" { + $teefile = $testfile + $encoding = 1251 + $testvalue | Tee-Object -Encoding $encoding $teefile + Get-Content $teefile -Encoding $encoding | Should -BeExactly $testvalue + (Get-Content $teefile -AsByteStream) -join "-" | Should -BeExactly $expectedBytes + } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index f63f3be140f..5f4f5c7728e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -688,6 +688,13 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { ($result.Output.Content | ConvertFrom-Json).args.testparam | Should -Be "testvalue" } + It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET and -NoProxy" { + $uri = Get-WebListenerUrl -Test 'Get' + $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod GET -Body @{'testparam'='testvalue'} -NoProxy" + $result = ExecuteWebCommand -command $command + ($result.Output.Content | ConvertFrom-Json).query | Should -Be "?testparam=testvalue" + } + It "Validate Invoke-WebRequest returns HTTP errors in exception" { $query = @{ body = "I am a teapot!!!" @@ -2269,6 +2276,13 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $result.Output.args.testparam | Should -Be "testvalue" } + It "Validate Invoke-RestMethod body is converted to query params for CustomMethod GET and -NoProxy" { + $uri = Get-WebListenerUrl -Test 'Get' + $command = "Invoke-RestMethod -Uri '$uri' -CustomMethod GET -Body @{'testparam'='testvalue'} -NoProxy" + $result = ExecuteWebCommand -command $command + $result.Output.Query | Should -Be "?testparam=testvalue" + } + It "Validate Invoke-RestMethod returns HTTP errors in exception" { $query = @{ body = "I am a teapot!!!" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 index ce52a59285a..d243ec07988 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 @@ -105,4 +105,31 @@ Describe "Write-Error Tests" -Tags "CI" { $result.Count | Should -BeExactly 3 $result[0] | Should -Match $longtext } + + It "Should be able to pass ErrorRecord to parameter position 0." { + try { + [int]::parse('foo') + } catch { } + + (Write-Error $Error[0] 2>&1).Exception.GetType().FullName | + Should -Be System.Management.Automation.MethodInvocationException + } + + It "Should be able to pass Exception to parameter position 0." { + try { + [int]::parse('foo') + } catch { } + + (Write-Error $Error[0].Exception.InnerException 2>&1).Exception.GetType().FullName | + Should -Be System.FormatException + } + + It "Should be able to pass string to parameter position 0." { + try { + [int]::parse('foo') + } catch { } + + (Write-Error "$($Error[0])" 2>&1).Exception.GetType().FullName | + Should -Be Microsoft.PowerShell.Commands.WriteErrorException + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 index f346b61f079..6e6c9ee57c4 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 @@ -22,4 +22,8 @@ Describe "Write-Progress DRT Unit Tests" -Tags "CI" { It "all params works" -Pending { { Write-Progress -Activity 'myactivity' -Status 'mystatus' -Id 1 -ParentId 2 -Completed:$false -current 'current' -sec 1 -percent 1 } | Should -Not -Throw } + + It 'Activity longer than console width works' { + { Write-Progress -Activity ('a' * ([console]::WindowWidth + 1)) -Status ('b' * ([console]::WindowWidth + 1)) -Id 1 } | Should -Not -Throw + } } diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/MOF-Compilation.Tests.ps1 b/test/powershell/Modules/PSDesiredStateConfiguration/MOF-Compilation.Tests.ps1 deleted file mode 100644 index 01620ee9eeb..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/MOF-Compilation.Tests.ps1 +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -Describe "DSC MOF Compilation" -tags "CI" { - - AfterAll { - $env:PSModulePath = $_modulePath - } - - BeforeAll { - $platformInfo = Get-PlatformInfo - $SkipAdditionalPlatforms = - ($platformInfo.Platform -match "alpine|raspbian") -or - ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') - - Import-Module PSDesiredStateConfiguration - $dscModule = Get-Module PSDesiredStateConfiguration - $baseSchemaPath = Join-Path $dscModule.ModuleBase 'Configuration' - $testResourceSchemaPath = Join-Path -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath assets) -ChildPath dsc) schema - - # Copy test resources to PSDesiredStateConfiguration module - Copy-Item $testResourceSchemaPath $baseSchemaPath -Recurse -Force - - $_modulePath = $env:PSModulePath - $powershellexe = (Get-Process -pid $PID).MainModule.FileName - $env:PSModulePath = Join-Path ([io.path]::GetDirectoryName($powershellexe)) Modules - } - - It "Should be able to compile a MOF from a basic configuration" -Skip:($IsMacOS -or $IsWindows -or $SkipAdditionalPlatforms) { - [Scriptblock]::Create(@" - configuration DSCTestConfig - { - Import-DscResource -ModuleName PSDesiredStateConfiguration - Node "localhost" { - nxFile f1 - { - DestinationPath = "/tmp/file1"; - } - } - } - - DSCTestConfig -OutputPath TestDrive:\DscTestConfig1 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig1\localhost.mof" | Should -Exist - } - - It "Should be able to compile a MOF from another basic configuration" -Skip:($IsMacOS -or $IsWindows -or $SkipAdditionalPlatforms) { - [Scriptblock]::Create(@" - configuration DSCTestConfig - { - Import-DscResource -ModuleName PSDesiredStateConfiguration - Node "localhost" { - nxScript f1 - { - GetScript = ""; - SetScript = ""; - TestScript = ""; - User = "root"; - } - } - } - - DSCTestConfig -OutputPath TestDrive:\DscTestConfig2 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig2\localhost.mof" | Should -Exist - } - - It "Should be able to compile a MOF from a complex configuration" -Skip:($IsMacOS -or $IsWindows -or $SkipAdditionalPlatforms) { - [Scriptblock]::Create(@" - Configuration WordPressServer{ - - Import-DscResource -ModuleName PSDesiredStateConfiguration - - Node CentOS{ - - #Ensure Apache packages are installed - nxPackage httpd { - Ensure = "Present" - Name = "httpd" - PackageManager = "yum" - } - - #Include vhostdir - nxFile vHostDir{ - DestinationPath = "/etc/httpd/conf.d/vhosts.conf" - Ensure = "Present" - Contents = "IncludeOptional /etc/httpd/sites-enabled/*.conf`n" - Type = "File" - } - - nxFile vHostDirectory{ - DestinationPath = "/etc/httpd/sites-enabled" - Type = "Directory" - Ensure = "Present" - } - - #Ensure directory for Wordpress site - nxFile wpHttpDir{ - DestinationPath = "/var/www/wordpress" - Type = "Directory" - Ensure = "Present" - Mode = "755" - } - - #Ensure share directory - nxFile share{ - DestinationPath = "/mnt/share" - Type = "Directory" - Ensure = "Present" - Mode = "755" - } - - #Bind httpd to port 8080 - nxFile HttpdPort{ - DestinationPath = "/etc/httpd/conf.d/listen.conf" - Ensure = "Present" - Contents = "Listen 8080`n" - Type = "File" - } - - #nfs mounts - nxScript nfsMount{ - TestScript= "#!/bin/bash" - GetScript="#!/bin/bash" - SetScript="#!/bin/bash" - - } - - #Retrieve latest wordpress - nxFile WordPressTar{ - SourcePath = "/mnt/share/latest.zip" - DestinationPath = "/tmp/wordpress.zip" - Checksum = "md5" - Type = "file" - DependsOn = "[nxScript]nfsMount" - } - - #Extract wordpress if changed - nxArchive ExtractSite{ - SourcePath = "/tmp/wordpress.zip" - DestinationPath = "/var/www/wordpress" - Ensure = "Present" - DependsOn = "[nxFile]WordpressTar" - } - - #Set wp-config - - #Fixup SE Linux context - #nxScript SELinuxContext{ - #TestScript= "#!/bin/bash" - #GetScript = "#!/bin/bash" - #SetScript = "#!/bin/bash" - #} - - #Disable SELinux - nxFileLine SELinux { - Filepath = "/etc/selinux/config" - DoesNotContainPattern = "SELINUX=enforcing" - ContainsLine = "SELINUX=disabled" - } - - nxScript SELinuxHTTPNet{ - GetScript = "#!/bin/bash`ngetsebool httpd_can_network_connect" - setScript = "#!/bin/bash`nsetsebool -P httpd_can_network_connect=1" - TestScript = "#!/bin/bash`n exit 1" - } - - } - - } - WordPressServer -OutputPath TestDrive:\DscTestConfig3 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig3\CentOS.mof" | Should -Exist - } - - It "Should be able to compile a MOF from a basic configuration on Windows" -Skip:($IsMacOS -or $IsLinux -or $SkipAdditionalPlatforms) { - [Scriptblock]::Create(@" - configuration DSCTestConfig - { - Import-DscResource -ModuleName PSDesiredStateConfiguration - Node "localhost" { - File f1 - { - DestinationPath = "$env:SystemDrive\\Test.txt"; - Ensure = "Present" - } - } - } - - DSCTestConfig -OutputPath TestDrive:\DscTestConfig4 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig4\localhost.mof" | Should -Exist - } - - It "Should be able to compile a MOF from a configuration with multiple resources on Windows" -Skip:($IsMacOS -or $IsLinux -or $SkipAdditionalPlatforms) { - [Scriptblock]::Create(@" - configuration DSCTestConfig - { - Import-DscResource -ModuleName PSDesiredStateConfiguration - Node "localhost" { - File f1 - { - DestinationPath = "$env:SystemDrive\\Test.txt"; - Ensure = "Present" - } - Script s1 - { - GetScript = {return @{}} - SetScript = "Write-Verbose Hello" - TestScript = {return $false} - } - Log l1 - { - Message = "This is a log message" - } - } - } - - DSCTestConfig -OutputPath TestDrive:\DscTestConfig5 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig5\localhost.mof" | Should -Exist - } -} diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 b/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 deleted file mode 100644 index c2fc8cf1e55..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 +++ /dev/null @@ -1,589 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -Function Install-ModuleIfMissing { - param( - [parameter(Mandatory)] - [String] - $Name, - [version] - $MinimumVersion, - [switch] - $SkipPublisherCheck, - [switch] - $Force - ) - - $module = Get-Module -Name $Name -ListAvailable -ErrorAction Ignore | Sort-Object -Property Version -Descending | Select-Object -First 1 - - if (!$module -or $module.Version -lt $MinimumVersion) { - Write-Verbose "Installing module '$Name' ..." -Verbose - Install-Module -Name $Name -Force -SkipPublisherCheck:$SkipPublisherCheck.IsPresent - } -} - -Function Test-IsInvokeDscResourceEnable { - return [ExperimentalFeature]::IsEnabled("PSDesiredStateConfiguration.InvokeDscResource") -} - -Describe "Test PSDesiredStateConfiguration" -tags CI { - BeforeAll { - $MissingLibmi = $false - $platformInfo = Get-PlatformInfo - if ( - ($platformInfo.Platform -match "alpine|raspbian") -or - ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') - ) { - $MissingLibmi = $true - } - } - - Context "Module loading" { - BeforeAll { - Function BeCommand { - [CmdletBinding()] - Param( - [object[]] $ActualValue, - [string] $CommandName, - [string] $ModuleName, - [switch]$Negate - ) - - $failure = if ($Negate) { - "Expected: Command $CommandName should not exist in module $ModuleName" - } - else { - "Expected: Command $CommandName should exist in module $ModuleName" - } - - $succeeded = if ($Negate) { - ($ActualValue | Where-Object { $_.Name -eq $CommandName }).count -eq 0 - } - else { - ($ActualValue | Where-Object { $_.Name -eq $CommandName }).count -gt 0 - } - - return [PSCustomObject]@{ - Succeeded = $succeeded - FailureMessage = $failure - } - } - - Add-AssertionOperator -Name 'HaveCommand' -Test $Function:BeCommand -SupportsArrayInput - - $commands = Get-Command -Module PSDesiredStateConfiguration - } - - It "The module should have the Configuration Command" { - $commands | Should -HaveCommand -CommandName 'Configuration' -ModuleName PSDesiredStateConfiguration - } - - It "The module should have the Configuration Command" { - $commands | Should -HaveCommand -CommandName 'New-DscChecksum' -ModuleName PSDesiredStateConfiguration - } - - It "The module should have the Get-DscResource Command" { - $commands | Should -HaveCommand -CommandName 'Get-DscResource' -ModuleName PSDesiredStateConfiguration - } - - It "The module should have the Invoke-DscResource Command" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - $commands | Should -HaveCommand -CommandName 'Invoke-DscResource' -ModuleName PSDesiredStateConfiguration - } - } - Context "Get-DscResource - Composite Resources" { - BeforeAll { - $origProgress = $global:ProgressPreference - $global:ProgressPreference = 'SilentlyContinue' - Install-ModuleIfMissing -Name PSDscResources - $testCases = @( - @{ - TestCaseName = 'case mismatch in resource name' - Name = 'groupset' - ModuleName = 'PSDscResources' - } - @{ - TestCaseName = 'Both names have matching case' - Name = 'GroupSet' - ModuleName = 'PSDscResources' - } - @{ - TestCaseName = 'case mismatch in module name' - Name = 'GroupSet' - ModuleName = 'psdscResources' - } - ) - } - - AfterAll { - $Global:ProgressPreference = $origProgress - } - - It "should be able to get <Name> - <TestCaseName>" -TestCases $testCases { - param($Name) - - if ($IsWindows) { - Set-ItResult -Pending -Because "Will only find script from PSDesiredStateConfiguration without modulename" - } - - if ($IsLinux) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/26" - } - - $resource = Get-DscResource -Name $name - $resource | Should -Not -BeNullOrEmpty - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - - } - - It "should be able to get <Name> from <ModuleName> - <TestCaseName>" -TestCases $testCases { - param($Name, $ModuleName, $PendingBecause) - - if ($IsLinux) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/26" - } - - if ($PendingBecause) { - Set-ItResult -Pending -Because $PendingBecause - } - - $resource = Get-DscResource -Name $Name -Module $ModuleName - $resource | Should -Not -BeNullOrEmpty - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - } - } - - Context "Get-DscResource - ScriptResources" { - BeforeAll { - $origProgress = $global:ProgressPreference - $global:ProgressPreference = 'SilentlyContinue' - - Install-ModuleIfMissing -Name PSDscResources -Force - - # Install PowerShellGet only if PowerShellGet 2.2.1 or newer does not exist - Install-ModuleIfMissing -Name PowerShellGet -MinimumVersion '2.2.1' - $module = Get-Module PowerShellGet -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 - - $psGetModuleSpecification = @{ModuleName = $module.Name; ModuleVersion = $module.Version.ToString() } - $psGetModuleCount = @(Get-Module PowerShellGet -ListAvailable).Count - $testCases = @( - @{ - TestCaseName = 'case mismatch in resource name' - Name = 'script' - ModuleName = 'PSDscResources' - } - @{ - TestCaseName = 'Both names have matching case' - Name = 'Script' - ModuleName = 'PSDscResources' - } - @{ - TestCaseName = 'case mismatch in module name' - Name = 'Script' - ModuleName = 'psdscResources' - } - <# - Add these back when PowerShellGet is fixed https://github.com/PowerShell/PowerShellGet/pull/529 - @{ - TestCaseName = 'case mismatch in resource name' - Name = 'PsModule' - ModuleName = 'PowerShellGet' - } - @{ - TestCaseName = 'Both names have matching case' - Name = 'PSModule' - ModuleName = 'PowerShellGet' - } - @{ - TestCaseName = 'case mismatch in module name' - Name = 'PSModule' - ModuleName = 'powershellget' - } - #> - ) - } - - AfterAll { - $Global:ProgressPreference = $origProgress - } - - It "should be able to get <Name> - <TestCaseName>" -TestCases $testCases { - param($Name) - - if ($IsWindows) { - Set-ItResult -Pending -Because "Will only find script from PSDesiredStateConfiguration without modulename" - } - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - if ($PendingBecause) { - Set-ItResult -Pending -Because $PendingBecause - } - - $resources = @(Get-DscResource -Name $name) - $resources | Should -Not -BeNullOrEmpty - foreach ($resource in $resource) { - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -Be 'ScriptBased' - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - - } - } - - It "should be able to get <Name> from <ModuleName> - <TestCaseName>" -TestCases $testCases { - param($Name, $ModuleName, $PendingBecause) - - if ($IsLinux) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/12 and https://github.com/PowerShell/PowerShellGet/pull/529" - } - - if ($PendingBecause) { - Set-ItResult -Pending -Because $PendingBecause - } - - $resources = @(Get-DscResource -Name $name -Module $ModuleName) - $resources | Should -Not -BeNullOrEmpty - foreach ($resource in $resource) { - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -Be 'ScriptBased' - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - } - } - - It "should throw when resource is not found" { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/17" - { - Get-DscResource -Name antoehusatnoheusntahoesnuthao -Module tanshoeusnthaosnetuhasntoheusnathoseun - } | - Should -Throw -ErrorId 'Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound' - } - } - Context "Get-DscResource - Class base Resources" { - - BeforeAll { - $origProgress = $global:ProgressPreference - $global:ProgressPreference = 'SilentlyContinue' - Install-ModuleIfMissing -Name XmlContentDsc -Force - $classTestCases = @( - @{ - TestCaseName = 'Good case' - Name = 'XmlFileContentResource' - ModuleName = 'XmlContentDsc' - } - @{ - TestCaseName = 'Module Name case mismatch' - Name = 'XmlFileContentResource' - ModuleName = 'xmlcontentdsc' - } - @{ - TestCaseName = 'Resource name case mismatch' - Name = 'xmlfilecontentresource' - ModuleName = 'XmlContentDsc' - } - ) - } - - AfterAll { - $global:ProgressPreference = $origProgress - } - - It "should be able to get class resource - <Name> from <ModuleName> - <TestCaseName>" -TestCases $classTestCases { - param($Name, $ModuleName, $PendingBecause) - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - if ($PendingBecause) { - Set-ItResult -Pending -Because $PendingBecause - } - - $resource = Get-DscResource -Name $Name -Module $ModuleName - $resource | Should -Not -BeNullOrEmpty - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -Be 'ClassBased' - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - } - - It "should be able to get class resource - <Name> - <TestCaseName>" -TestCases $classTestCases { - param($Name, $ModuleName, $PendingBecause) - if ($IsWindows) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/19" - } - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - if ($PendingBecause) { - Set-ItResult -Pending -Because $PendingBecause - } - - $resource = Get-DscResource -Name $Name - $resource | Should -Not -BeNullOrEmpty - $resource.Name | Should -Be $Name - if (Test-IsInvokeDscResourceEnable) { - $resource.ImplementationDetail | Should -Be 'ClassBased' - } - else { - $resource.ImplementationDetail | Should -BeNullOrEmpty - } - } - } - Context "Invoke-DscResource" { - BeforeAll { - $origProgress = $global:ProgressPreference - $global:ProgressPreference = 'SilentlyContinue' - $module = Get-InstalledModule -Name PsDscResources -ErrorAction Ignore - if ($module) { - Write-Verbose "removing PSDscResources, tests will re-install..." -Verbose - Uninstall-Module -Name PsDscResources -AllVersions -Force - } - } - - AfterAll { - $Global:ProgressPreference = $origProgress - } - - Context "mof resources" { - BeforeAll { - $dscMachineStatusCases = @( - @{ - value = '1' - expectedResult = $true - } - @{ - value = '$true' - expectedResult = $true - } - @{ - value = '0' - expectedResult = $false - } - @{ - value = '$false' - expectedResult = $false - } - ) - - Install-ModuleIfMissing -Name PowerShellGet -Force -SkipPublisherCheck -MinimumVersion '2.2.1' - Install-ModuleIfMissing -Name xWebAdministration - $module = Get-Module PowerShellGet -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 - - $psGetModuleSpecification = @{ModuleName = $module.Name; ModuleVersion = $module.Version.ToString() } - } - It "Set method should work" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - if (!$IsLinux) { - $result = Invoke-DscResource -Name PSModule -ModuleName $psGetModuleSpecification -Method set -Property @{ - Name = 'PsDscResources' - InstallationPolicy = 'Trusted' - } - } - else { - # workraound because of https://github.com/PowerShell/PowerShellGet/pull/529 - Install-ModuleIfMissing -Name PsDscResources -Force - } - - $result.RebootRequired | Should -BeFalse - $module = Get-Module PsDscResources -ListAvailable - $module | Should -Not -BeNullOrEmpty -Because "Resource should have installed module" - } - It 'Set method should return RebootRequired=<expectedResult> when $global:DSCMachineStatus = <value>' -Skip:(!(Test-IsInvokeDscResourceEnable)) -TestCases $dscMachineStatusCases { - param( - $value, - $ExpectedResult - ) - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - # using create scriptBlock because $using:<variable> doesn't work with existing Invoke-DscResource - # Verified in Windows PowerShell on 20190814 - $result = Invoke-DscResource -Name Script -ModuleName PSDscResources -Method Set -Property @{TestScript = { Write-Output 'test'; return $false }; GetScript = { return @{ } }; SetScript = [scriptblock]::Create("`$global:DSCMachineStatus = $value;return") } - $result | Should -Not -BeNullOrEmpty - $result.RebootRequired | Should -BeExactly $expectedResult - } - - It "Test method should return false" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - $result = Invoke-DscResource -Name Script -ModuleName PSDscResources -Method Test -Property @{TestScript = { Write-Output 'test'; return $false }; GetScript = { return @{ } }; SetScript = { return } } - $result | Should -Not -BeNullOrEmpty - $result.InDesiredState | Should -BeFalse -Because "Test method return false" - } - - It "Test method should return true" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - $result = Invoke-DscResource -Name Script -ModuleName PSDscResources -Method Test -Property @{TestScript = { Write-Verbose 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } - $result | Should -BeTrue -Because "Test method return true" - } - - It "Test method should return true with moduleSpecification" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - $module = Get-Module PsDscResources -ListAvailable - $moduleSpecification = @{ModuleName = $module.Name; ModuleVersion = $module.Version.ToString() } - $result = Invoke-DscResource -Name Script -ModuleName $moduleSpecification -Method Test -Property @{TestScript = { Write-Verbose 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } - $result | Should -BeTrue -Because "Test method return true" - } - - It "Invalid moduleSpecification" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/17" - $moduleSpecification = @{ModuleName = 'PsDscResources'; ModuleVersion = '99.99.99.993' } - { - Invoke-DscResource -Name Script -ModuleName $moduleSpecification -Method Test -Property @{TestScript = { Write-Host 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } -ErrorAction Stop - } | - Should -Throw -ErrorId 'InvalidResourceSpecification,Invoke-DscResource' -ExpectedMessage 'Invalid Resource Name ''Script'' or module specification.' - } - - It "Resource with embedded resource not supported and a warning should be produced" { - - Set-ItResult -Pending -Because "Test is unreliable in release automation." - - if (!(Test-IsInvokeDscResourceEnable)) { - Set-ItResult -Skipped -Because "Feature not enabled" - } - - if (!$IsMacOS) { - Set-ItResult -Skipped -Because "Not applicable on Windows and xWebAdministration resources don't load on linux" - } - - try { - Invoke-DscResource -Name xWebSite -ModuleName 'xWebAdministration' -Method Test -Property @{TestScript = 'foodbar' } -ErrorAction Stop -WarningVariable warnings - } - catch{ - #this will fail too, but that is nat what we are testing... - } - - $warnings.Count | Should -Be 1 -Because "There should be 1 warning on macOS and Linux" - $warnings[0] | Should -Match 'embedded resources.*not support' - } - - It "Using PsDscRunAsCredential should say not supported" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - { - Invoke-DscResource -Name Script -ModuleName PSDscResources -Method Set -Property @{TestScript = { Write-Output 'test'; return $false }; GetScript = { return @{ } }; SetScript = {return}; PsDscRunAsCredential='natoheu'} -ErrorAction Stop - } | - Should -Throw -ErrorId 'PsDscRunAsCredentialNotSupport,Invoke-DscResource' - } - - # waiting on Get-DscResource to be fixed - It "Invalid module name" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/17" - { - Invoke-DscResource -Name Script -ModuleName santoheusnaasonteuhsantoheu -Method Test -Property @{TestScript = { Write-Host 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } -ErrorAction Stop - } | - Should -Throw -ErrorId 'Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound' - } - - It "Invalid resource name" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($IsWindows) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/17" - } - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - { - Invoke-DscResource -Name santoheusnaasonteuhsantoheu -Method Test -Property @{TestScript = { Write-Host 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } -ErrorAction Stop - } | - Should -Throw -ErrorId 'Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound' - } - - It "Get method should work" -Skip:(!(Test-IsInvokeDscResourceEnable)) { - if ($IsLinux) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/12 and https://github.com/PowerShell/PowerShellGet/pull/529" - } - - $result = Invoke-DscResource -Name PSModule -ModuleName $psGetModuleSpecification -Method Get -Property @{ Name = 'PsDscResources' } - $result | Should -Not -BeNullOrEmpty - $result.Author | Should -BeLike 'Microsoft*' - $result.InstallationPolicy | Should -BeOfType string - $result.Guid | Should -BeOfType Guid - $result.Ensure | Should -Be 'Present' - $result.Name | Should -Be 'PsDscResources' - $result.Description | Should -BeLike 'This*DSC*' - $result.InstalledVersion | Should -BeOfType Version - $result.ModuleBase | Should -BeLike '*PSDscResources*' - $result.Repository | Should -BeOfType string - $result.ModuleType | Should -Be 'Manifest' - } - } - - Context "Class Based Resources" { - BeforeAll { - Install-ModuleIfMissing -Name XmlContentDsc -Force - } - - AfterAll { - $Global:ProgressPreference = $origProgress - } - - BeforeEach { - $testXmlPath = 'TestDrive:\test.xml' - @' -<configuration> -<appSetting> - <Test1/> -</appSetting> -</configuration> -'@ | Out-File -FilePath $testXmlPath -Encoding utf8NoBOM - $resolvedXmlPath = (Resolve-Path -Path $testXmlPath).ProviderPath - } - - It 'Set method should work' -Skip:(!(Test-IsInvokeDscResourceEnable)) { - param( - $value, - $ExpectedResult - ) - - if ($MissingLibmi) { - Set-ItResult -Pending -Because "Libmi not available for this platform" - } - - $testString = '890574209347509120348' - $result = Invoke-DscResource -Name XmlFileContentResource -ModuleName XmlContentDsc -Property @{Path = $resolvedXmlPath; XPath = '/configuration/appSetting/Test1'; Ensure = 'Present'; Attributes = @{ TestValue2 = $testString; Name = $testString } } -Method Set - $result | Should -Not -BeNullOrEmpty - $result.RebootRequired | Should -BeFalse - $testXmlPath | Should -FileContentMatch $testString - } - } - } -} diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/BaseResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/BaseResource.schema.mof deleted file mode 100755 index d7682145140..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/BaseResource.schema.mof +++ /dev/null @@ -1,207 +0,0 @@ - -[Abstract, ClassVersion("1.0.0")] -class OMI_BaseResource -{ - [required] string ResourceId; - [write] string SourceInfo; - [write] string DependsOn[]; - [required] string ModuleName; - [required] string ModuleVersion; - [write] string ConfigurationName; -}; - -[Abstract, ClassVersion("1.0.0")] -class MSFT_KeyValuePair -{ - [Key] - string Key; - - [write] - string Value; -}; - -[Abstract, ClassVersion("1.0.0")] -class MSFT_BaseConfigurationProviderRegistration -{ - [key] String ClassName; - String DSCEngineCompatVersion; - String DSCModuleVersion; -}; - -[ClassVersion("1.0.0")] -class MSFT_CimConfigurationProviderRegistration : MSFT_BaseConfigurationProviderRegistration -{ - String Namespace; -}; - -[ClassVersion("1.0.0")] -class MSFT_PSConfigurationProviderRegistration : MSFT_BaseConfigurationProviderRegistration -{ - String ModuleName; -}; - -[ClassVersion("1.0.0")] -class OMI_ConfigurationDocument -{ - String Version; - String Author; - String Copyright; - String HelpInfoUri; - String ContentType; - String GenerationDate; - String GenerationHost; - String Name; - String MinimumCompatibleVersion; - String CompatibleVersionAdditionalProperties[]; - String DocumentType; -}; - -[ClassVersion("1.0.0")] -class MSFT_Credential -{ - [MaxLen ( 256 )] - string UserName; - string Password; -}; - -// =============================================================== -// OMI_MetaConfigurationResource -// =============================================================== -[ClassVersion("1.0.0"), - Description ( - "Base schema for all Metaconfiguration resources." )] -class OMI_MetaConfigurationResource -{ - - [required] - string ResourceId; - - [write] - string SourceInfo; -}; - - -// =============================================================== -// Configuration Download Manager -// =============================================================== -[ClassVersion("1.0.0"), - Description("Class defining the configuration download manager" ) ] -class OMI_ConfigurationDownloadManager : OMI_MetaConfigurationResource -{ -}; - -[ClassVersion("1.0.0"), - Description("Web download manager class inheriting from OMI_ConfigurationDownloadManager" )] -class MSFT_WebDownloadManager : OMI_ConfigurationDownloadManager -{ - [Description ("String URL of the download manager location" ) , Key] - string ServerURL; - - - [Description ("The certificate ID used to locate the certificate." ) ] - string CertificateID; - - - [Description ("Boolean variable to allow unsecure connections" ) ] - boolean AllowUnsecureConnection; - - [Description ("Registration Key with which to register with the Pull Server" ) ] - string RegistrationKey; - - [Description ("The set of configuration names with which to register with the Pull Server.")] - string ConfigurationNames[]; -}; - - -// =============================================================== -// Report Managers -// =============================================================== - -[ClassVersion("1.0.0"), - Description("Class defining a report manager") ] -class OMI_ReportManager : OMI_MetaConfigurationResource -{ -}; - -[ClassVersion("1.0.0"), - Description("Web report manager class inheriting from OMI_ReportManager class") ] -class MSFT_WebReportManager : OMI_ReportManager -{ - [Description ("URL of the server used by report manager." ) , Key] - string ServerURL; - - [Description ("The certificate ID used to locate the certificate for secure connections." ) ] - string CertificateID; - - [Description("Specifies whether report manager can use unsecure connection over http.")] - boolean AllowUnsecureConnection; - - [Description ("Registration Key with which to register with the Reporting Server" ) ] - string RegistrationKey; -}; - - -// =============================================================== -// ResourceModule Managers -// =============================================================== - - -[ClassVersion("1.0.0"), Description("Class defining the structure of resource module managers") ] -class OMI_ResourceModuleManager : OMI_MetaConfigurationResource -{ -}; - - -[ClassVersion("1.0.0"), - Description("Web resource module manager class inheriting from OMI_ResourceModuleManager") ] -class MSFT_WebResourceManager : OMI_ResourceModuleManager -{ - [Description ("String URL of the resource module manager location" ) , Key] - string ServerURL; - - [Description ("The certificate ID used to locate the certificate." ) ] - string CertificateID; - - - [Description ("Boolean variable to allow unsecure connections" ) ] - boolean AllowUnsecureConnection; - - [Description ("Registration Key with which to register with the Resource Repository Web" ) ] - string RegistrationKey; - -}; - -[ClassVersion("1.0.0"), - Description("File resource module manager class inheriting from OMI_ResourceModuleManager class") ] -class MSFT_FileResourceManager : OMI_ResourceModuleManager -{ - [Description ("String UNC path of the File resource manager" ) , Key] - string SourcePath; - - [EmbeddedInstance("MSFT_Credential"), - Description ("Default credential to access resources." ) ] - string Credential; - -}; - - - -[Description( - "This represents a Partial Configuration class."), - ClassVersion("1.0.0")] -class MSFT_PartialConfiguration : OMI_MetaConfigurationResource -{ - [Description ("Description of the partial configuration" ) , Write] - String Description ; - - [Description ("Defines the resources that are exclusive to this particular partial configuration" ) , Write] - String ExclusiveResources[]; - - [Description ("The configuration repository source that this partial configuration will use" ) , Write] - String ConfigurationSource; - - [Description ("A dependency variable indicating which partial configuration must be applied prior to this" ) , Write] - String DependsOn[]; -}; - - diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/MSFT_DSCMetaConfiguration.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/MSFT_DSCMetaConfiguration.mof deleted file mode 100755 index f0c45707580..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/BaseRegistration/MSFT_DSCMetaConfiguration.mof +++ /dev/null @@ -1,100 +0,0 @@ -// =============================================================== -// MetaConfiguration -// =============================================================== -[ClassVersion("1.0.0"),Description("Local Configuration Manager settings.")] -class MSFT_DSCMetaConfiguration -{ - [Description ("The time interval between consecutive runs for reapplying the configuration to get to the desired state." )] - uint32 ConfigurationModeFrequencyMins; - - [Description ("Reboot node if needed.")] - boolean RebootNodeIfNeeded; - - [Description ("The configuration apply mode for the server."), - ValueMap {"ApplyOnly","ApplyAndMonitor","ApplyAndAutoCorrect"}, - Values {"ApplyOnly","ApplyAndMonitor","ApplyAndAutoCorrect"}] - string ConfigurationMode; - - [EmbeddedInstance("MSFT_Credential"), - Description ("Default credential to access resources." )] - string Credential; - - [Description ("The refresh mode for the server. Valid values are Pull and Push." ), - ValueMap {"Push","Pull"}, - Values {"Push","Pull"}] - string RefreshMode; - - [Description ("The certificate ID used to locate the certificate." )] - string CertificateID; - - [Description ("The configuration ID used to get the configuration from the pull server." )] - string ConfigurationID; - - [Description ("Name of the configuration and module Download Manager." )] - string DownloadManagerName; - - [Description ("Custom data that is specific to Download Manager." ), - EmbeddedInstance("MSFT_KeyValuePair")] - string DownloadManagerCustomData[]; - - [Description ("The time interval between consecutive runs to get the action from the server." )] - uint32 RefreshFrequencyMins; - - [Description ("Overwrite modules when downloading from Pull Server." )] - boolean AllowModuleOverwrite; - - [Read, Description("Current state of local configuration manager."), - ValueMap{"Ready","Busy","PendingReboot"}, - Values{"Ready","Busy","PendingReboot"}] - string LocalConfigurationManagerState; - - [Description ("Array of configuration download manager objects that contain location information to download configurations" ) , - EmbeddedInstance("OMI_ConfigurationDownloadManager")] - string ConfigurationDownloadManagers[]; - - [Description ("Array of resource module managers pointing to a location to download missing DSCResources" ) , - EmbeddedInstance("OMI_ResourceModuleManager")] - string ResourceModuleManagers[]; - - [Description ("Array of report managers pointing to a location that would help generate reports for DSC" ) , - EmbeddedInstance("OMI_ReportManager")] - string ReportManagers[]; - - [EmbeddedInstance("MSFT_PartialConfiguration")] string PartialConfigurations[]; - - - [Description ("The action after reboot the server."), - ValueMap {"ContinueConfiguration","StopConfiguration"}, - Values {"ContinueConfiguration","StopConfiguration"}] - string ActionAfterReboot; - - [Description ("The enumeration for DebugMode."), - ValueMap {"None","ForceModuleImport", "All", "ResourceScriptBreakAll"}, - Values {"None","ForceModuleImport", "All", "ResourceScriptBreakAll"}] - string DebugMode[]; - - [Read, Description("Current version of local configuration manager.")] - string LCMVersion; - - [Read, Description("Compatible versions of current local configuration manager.")] - string LCMCompatibleVersions[]; - - [Read, Description("Current state of local configuration manager."), - ValueMap{"Idle","Busy","PendingReboot","PendingConfiguration"}, - Values{"Idle","Busy","PendingReboot","PendingConfiguration"}] - string LCMState; - - [Read, Description("State detail of local configuration manager.")] - string LCMStateDetail; - - [Description ("Number of days to retain configuration status history.")] - uint32 StatusRetentionTimeInDays; - - [Read, Description("AgentId of the current Dsc Agent.")] - string AgentId; - - - boolean EnableSignatureValidation; - boolean DisableModuleSignatureValidation; - -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_LogResource/MSFT_LogResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_LogResource/MSFT_LogResource.schema.mof deleted file mode 100755 index 9216888fee5..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_LogResource/MSFT_LogResource.schema.mof +++ /dev/null @@ -1,7 +0,0 @@ -#pragma namespace("\\\\.\\root\\microsoft\\windows\\DesiredstateConfiguration") - -[ClassVersion("1.0.0"),FriendlyName("Log")] -class MSFT_LogResource : OMI_BaseResource -{ - [required] string Message; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxArchiveResource/MSFT_nxArchiveResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxArchiveResource/MSFT_nxArchiveResource.schema.mof deleted file mode 100755 index 53dcdbac143..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxArchiveResource/MSFT_nxArchiveResource.schema.mof +++ /dev/null @@ -1,10 +0,0 @@ -[ClassVersion("1.0.0"), FriendlyName("nxArchive")] -class MSFT_nxArchiveResource : OMI_BaseResource -{ - [Key] string SourcePath; - [Key] string DestinationPath; - [write,ValueMap{"ctime", "mtime", "md5"},Values{"ctime", "mtime","md5"}] string Checksum; - [write] boolean Force; - [Write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; -}; - diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxEnvironmentResource/MSFT_nxEnvironmentResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxEnvironmentResource/MSFT_nxEnvironmentResource.schema.mof deleted file mode 100755 index bdfa934a15f..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxEnvironmentResource/MSFT_nxEnvironmentResource.schema.mof +++ /dev/null @@ -1,8 +0,0 @@ -[ClassVersion("1.0.0"), Description("The configuration provider for environment variable control."), FriendlyName("nxEnvironment")] -class MSFT_nxEnvironmentResource:OMI_BaseResource -{ - [Key] string Name; - [write] string Value; - [Write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [Write] boolean Path; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileLineResource/MSFT_nxFileLineResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileLineResource/MSFT_nxFileLineResource.schema.mof deleted file mode 100755 index 85cc45dc6f9..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileLineResource/MSFT_nxFileLineResource.schema.mof +++ /dev/null @@ -1,8 +0,0 @@ -[ClassVersion("1.0.0"), FriendlyName("nxFileLine")] -class MSFT_nxFileLineResource : OMI_BaseResource -{ -[key,required] string FilePath; -[write] string DoesNotContainPattern; -[key,write] string ContainsLine; -}; - diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileResource/MSFT_nxFileResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileResource/MSFT_nxFileResource.schema.mof deleted file mode 100755 index 003e4e2d53a..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxFileResource/MSFT_nxFileResource.schema.mof +++ /dev/null @@ -1,17 +0,0 @@ -[ClassVersion("1.0.0"), Description("The configuration provider for files and directories."), FriendlyName("nxFile")] -class MSFT_nxFileResource:OMI_BaseResource -{ - [Key] string DestinationPath; - [Write] string SourcePath; - [Write,ValueMap{"present", "absent"},Values{"present", "absent"}] string Ensure; - [Write,ValueMap{"file", "directory", "link"},Values{"file", "directory","link"}] string Type; - [Write] boolean Force; - [Write] string Contents; - [Write, ValueMap{"md5", "mtime", "ctime"}] string Checksum; - [Write] boolean Recurse; - [Write, ValueMap{"follow", "manage", "ignore" }] string Links; - [Write] string Group; - [Write] string Mode; - [Write] string Owner; - [Read] datetime ModifiedDate; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxGroupResource/MSFT_nxGroupResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxGroupResource/MSFT_nxGroupResource.schema.mof deleted file mode 100755 index 76680de5c57..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxGroupResource/MSFT_nxGroupResource.schema.mof +++ /dev/null @@ -1,12 +0,0 @@ -[ClassVersion("1.0.0"), FriendlyName("nxGroup")] -class MSFT_nxGroupResource:OMI_BaseResource -{ - [Key] string GroupName; - [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [write] string Members[]; - [write] string MembersToInclude[]; - [write] string MembersToExclude[]; - [write] string PreferredGroupID; - [read] string GroupID; - -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxPackageResource/MSFT_nxPackageResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxPackageResource/MSFT_nxPackageResource.schema.mof deleted file mode 100755 index d51aedf9107..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxPackageResource/MSFT_nxPackageResource.schema.mof +++ /dev/null @@ -1,19 +0,0 @@ -[ClassVersion("1.0.0"), FriendlyName("nxPackage")] -class MSFT_nxPackageResource : OMI_BaseResource -{ - [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [write,ValueMap{"Yum", "Apt", "Zypper", "*"},Values{"Yum", "Apt", "Zypper", "*"}] string PackageManager; - [Key] string Name; - [write] string FilePath; - [write] Boolean PackageGroup; - [write] string Arguments; - [write] uint32 ReturnCode; - [read] string PackageDescription; - [read] string Publisher; - [read] string InstalledOn; - [read] uint32 Size; - [read] string Version; - [read] boolean Installed; - [read] string Architecture; - -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxScriptResource/MSFT_nxScriptResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxScriptResource/MSFT_nxScriptResource.schema.mof deleted file mode 100755 index 509747abb5f..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxScriptResource/MSFT_nxScriptResource.schema.mof +++ /dev/null @@ -1,10 +0,0 @@ -[ClassVersion("1.0.0"),FriendlyName("nxScript")] -class MSFT_nxScriptResource : OMI_BaseResource -{ - [Key] string GetScript; - [Key] string SetScript; - [Key] string TestScript; - [write] string User; - [write] string Group; - [Read] string Result; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxServiceResource/MSFT_nxServiceResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxServiceResource/MSFT_nxServiceResource.schema.mof deleted file mode 100755 index 2995aba53ba..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxServiceResource/MSFT_nxServiceResource.schema.mof +++ /dev/null @@ -1,12 +0,0 @@ -/* I am really new */ -[ClassVersion("1.0.0"), FriendlyName("nxService")] -class MSFT_nxServiceResource : OMI_BaseResource -{ - [key] string Name; - [write,required,ValueMap{"init", "upstart", "systemd", "*"},Values{"init","upstart","systemd", "*"}] string Controller; - [write] boolean Enabled; - [write,ValueMap{"Running", "Stopped"},Values{"Running", "Stopped"}] string State; - [read] string Path; - [read] string Description; - [read] string Runlevels; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxSshAuthorizedKeysResource/MSFT_nxSshAuthorizedKeysResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxSshAuthorizedKeysResource/MSFT_nxSshAuthorizedKeysResource.schema.mof deleted file mode 100755 index 71bb190b992..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxSshAuthorizedKeysResource/MSFT_nxSshAuthorizedKeysResource.schema.mof +++ /dev/null @@ -1,8 +0,0 @@ -[ClassVersion("1.0.0"), Description("The configuration provider for ssh authorized key control."), FriendlyName("nxSshAuthorizedKeys")] -class MSFT_nxSshAuthorizedKeysResource:OMI_BaseResource -{ - [Key] string KeyComment; - [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [write] string UserName; - [write] string Key; -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxUserResource/MSFT_nxUserResource.schema.mof b/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxUserResource/MSFT_nxUserResource.schema.mof deleted file mode 100755 index 9360ab2030d..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/assets/dsc/schema/MSFT_nxUserResource/MSFT_nxUserResource.schema.mof +++ /dev/null @@ -1,15 +0,0 @@ -[ClassVersion("1.0.0"), FriendlyName("nxUser")] -class MSFT_nxUserResource : OMI_BaseResource -{ - [Key] string UserName; - [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [write] string FullName; - [write] string Description; - [write] string Password; - [write] boolean Disabled; - [write] boolean PasswordChangeRequired; - [write] string HomeDirectory; - [write] string GroupID; - [read] string UserID; - -}; diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 b/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 deleted file mode 100644 index 7b621578e4d..00000000000 --- a/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -Describe "DSC MOF Compilation" -tags "CI" { - BeforeAll { - $module = Get-Module PowerShellGet -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 - - $psGetModuleVersion = $module.Version.ToString() - if (!$env:DSC_HOME) - { - Import-Module PSDesiredStateConfiguration - } - } - - It "Should be able to compile a MOF using PSModule resource" { - if ($IsLinux) { - Set-ItResult -Pending -Because "https://github.com/PowerShell/PowerShellGet/pull/529" - } - - Write-Verbose "DSC_HOME: ${env:DSC_HOME}" -Verbose - [Scriptblock]::Create(@" - configuration DSCTestConfig - { - Import-DscResource -ModuleName PowerShellGet -ModuleVersion $psGetModuleVersion - Node "localhost" { - PSModule f1 - { - Name = 'PsDscResources' - InstallationPolicy = 'Trusted' - } - } - } - - DSCTestConfig -OutputPath TestDrive:\DscTestConfig2 -"@) | Should -Not -Throw - - "TestDrive:\DscTestConfig2\localhost.mof" | Should -Exist - } -} diff --git a/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 b/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 index 9c579b7e1b8..62c27c87a12 100644 --- a/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 +++ b/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 @@ -12,13 +12,13 @@ Describe "PSReadLine" -tags "CI" { Import-Module PSReadLine $module = Get-Module PSReadLine $module.Name | Should -BeExactly 'PSReadLine' - $module.Version | Should -Match '^2.0.\d$' + $module.Version | Should -Match '^2.1.\d$' } It "Should be installed to `$PSHOME" { $module = Get-Module (Join-Path -Path $PSHOME -ChildPath "Modules" -AdditionalChildPath "PSReadLine") -ListAvailable $module.Name | Should -BeExactly 'PSReadLine' - $module.Version | Should -Match '^2.0.\d$' + $module.Version | Should -Match '^2.1.\d$' $module.Path | Should -Be (Join-Path -Path $PSHOME -ChildPath "Modules/PSReadLine/PSReadLine.psd1") } diff --git a/test/powershell/engine/Api/TypeInference.Tests.ps1 b/test/powershell/engine/Api/TypeInference.Tests.ps1 index 9ce41f54e29..1d65047c34c 100644 --- a/test/powershell/engine/Api/TypeInference.Tests.ps1 +++ b/test/powershell/engine/Api/TypeInference.Tests.ps1 @@ -504,7 +504,7 @@ Describe "Type inference Tests" -tags "CI" { It "Infers typeof Select-Object when Parameter is ExcludeProperty" { $res = [AstTypeInference]::InferTypeOf( { [io.fileinfo]::new("file") | Select-Object -ExcludeProperty *Time*, E* }.Ast) $res.Count | Should -Be 1 - $res[0].Name | Should -BeExactly "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LengthString:LinkType:Mode:ModeWithoutHardLink:Name:NameString:Target:VersionInfo" + $res[0].Name | Should -BeExactly "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LengthString:LinkTarget:LinkType:Mode:ModeWithoutHardLink:Name:NameString:Target:VersionInfo" $names = $res[0].Members.Name $names -contains "BaseName" | Should -BeTrue $names -contains "Name" | Should -BeTrue diff --git a/test/powershell/engine/Basic/Assembly.LoadFrom.Tests.ps1 b/test/powershell/engine/Basic/Assembly.LoadFrom.Tests.ps1 index 67ee0677c51..383f20bfb10 100644 --- a/test/powershell/engine/Basic/Assembly.LoadFrom.Tests.ps1 +++ b/test/powershell/engine/Basic/Assembly.LoadFrom.Tests.ps1 @@ -35,7 +35,14 @@ Describe "Assembly.LoadFrom Validation Test" -Tags "CI" { ## The assembly files cannot be removed once they are loaded, unless the current PowerShell session exits. ## If we use $TestDrive here, then Pester will try to remove them afterward and result in errors. - $TempPath = [System.IO.Path]::GetTempFileName() + + if ($IsWindows) { + $TempPath = [System.IO.Path]::GetTempFileName() + } + else { + $TempPath = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } + if (Test-Path $TempPath) { Remove-Item -Path $TempPath -Force -Recurse } New-Item -Path $TempPath -ItemType Directory -Force > $null diff --git a/test/powershell/engine/Basic/Assembly.LoadNative.Tests.ps1 b/test/powershell/engine/Basic/Assembly.LoadNative.Tests.ps1 index bb383573672..9196ccc0e13 100644 --- a/test/powershell/engine/Basic/Assembly.LoadNative.Tests.ps1 +++ b/test/powershell/engine/Basic/Assembly.LoadNative.Tests.ps1 @@ -6,7 +6,13 @@ Describe "Can load a native assembly" -Tags "CI" { BeforeAll { ## The assembly files cannot be removed once they are loaded, unless the current PowerShell session exits. ## If we use $TestDrive here, then Pester will try to remove them afterward and result in errors. - $TempPath = [System.IO.Path]::GetTempFileName() + if ($IsWindows) { + $TempPath = [System.IO.Path]::GetTempFileName() + } + else { + $TempPath = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + } + if (Test-Path $TempPath) { Remove-Item -Path $TempPath -Force -Recurse } New-Item -Path $TempPath -ItemType Directory -Force > $null diff --git a/test/powershell/engine/Basic/assets/standardtypes.csv b/test/powershell/engine/Basic/assets/standardtypes.csv index dfae58ea321..d372000dcb5 100644 --- a/test/powershell/engine/Basic/assets/standardtypes.csv +++ b/test/powershell/engine/Basic/assets/standardtypes.csv @@ -250,7 +250,7 @@ "System.Management.Automation.PSScriptMethod","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" "System.Management.Automation.PSScriptProperty","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" "System.Management.Automation.PSSecurityException","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","True","True" -"System.Management.Automation.PSSerializer","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" +"System.Management.Automation.PSSerializer","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","True","False","True","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" "System.Management.Automation.PSSessionTypeOption","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","True","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" "System.Management.Automation.PSTraceSource","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","False","False","False","False","False","False","True" "System.Management.Automation.PSTraceSourceOptions","False","False","False","False","False","False","False","True","True","False","False","False","False","False","False","False","False","False","False","False","False","True","False","False","False","False","False","False","False","False","False","True","True","False","False","True","False","False","False","False","True","False","False","True","False","True","True" diff --git a/test/powershell/engine/ETS/TypeTable.Tests.ps1 b/test/powershell/engine/ETS/TypeTable.Tests.ps1 index 37e8f08686d..55b909145a8 100644 --- a/test/powershell/engine/ETS/TypeTable.Tests.ps1 +++ b/test/powershell/engine/ETS/TypeTable.Tests.ps1 @@ -18,13 +18,10 @@ Describe "Built-in type information tests" -Tag "CI" { } It "Should have correct number of built-in type items in type table" { - $isUnixStatEnabled = $EnabledExperimentalFeatures -contains 'PSUnixFileStat' $expected = if ($IsWindows) { 273 - } elseif ($isUnixStatEnabled) { - 272 } else { - 271 + 272 } $types.Count | Should -BeExactly $expected } diff --git a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 index bcc358bcccd..af18672cf27 100644 --- a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 +++ b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 @@ -165,16 +165,34 @@ Describe "Default enablement of Experimental Features" -Tags CI { } It "On stable builds, Experimental Features are not enabled" -Skip:($isPreview) { - foreach ($expFeature in Get-ExperimentalFeature) { - $expFeature.Enabled | Should -Not -BeEnabled -Name $expFeature.Name + foreach ($expFeature in Get-ExperimentalFeature) + { + # In CI, pwsh that is running tests (with $PSHOME like D:\a\1\s\src\powershell-win-core\bin\release\net6.0\win7-x64\publish) + # is launched from another pwsh (with $PSHOME like C:\program files\powershell\7) + # resulting in combined PSModulePath which is used by Get-ExperimentalFeature to enum module-scoped exp.features from both pwsh locations. + # So we need to exclude parent's modules' exp.features from verification using filtering on $PSHOME. + if (($expFeature.Source -eq 'PSEngine') -or ($expFeature.Source.StartsWith($PSHOME, "InvariantCultureIgnoreCase"))) + { + "Checking $($expFeature.Name) experimental feature" | Write-Verbose -Verbose + $expFeature.Enabled | Should -Not -BeEnabled -Name $expFeature.Name + } } } It "On preview builds, Experimental Features are enabled" -Skip:(!$isPreview) { (Join-Path -Path $PSHOME -ChildPath 'powershell.config.json') | Should -Exist - foreach ($expFeature in Get-ExperimentalFeature) { - $expFeature.Enabled | Should -BeEnabled -Name $expFeature.Name + foreach ($expFeature in Get-ExperimentalFeature) + { + # In CI, pwsh that is running tests (with $PSHOME like D:\a\1\s\src\powershell-win-core\bin\release\net6.0\win7-x64\publish) + # is launched from another pwsh (with $PSHOME like C:\program files\powershell\7) + # resulting in combined PSModulePath which is used by Get-ExperimentalFeature to enum module-scoped exp.features from both pwsh locations. + # So we need to exclude parent's modules' exp.features from verification using filtering on $PSHOME. + if (($expFeature.Source -eq 'PSEngine') -or ($expFeature.Source.StartsWith($PSHOME, "InvariantCultureIgnoreCase"))) + { + "Checking $($expFeature.Name) experimental feature" | Write-Verbose -Verbose + $expFeature.Enabled | Should -BeEnabled -Name $expFeature.Name + } } } } diff --git a/test/powershell/engine/Formatting/BugFix.Tests.ps1 b/test/powershell/engine/Formatting/BugFix.Tests.ps1 index 20f9d538aec..5be7797134c 100644 --- a/test/powershell/engine/Formatting/BugFix.Tests.ps1 +++ b/test/powershell/engine/Formatting/BugFix.Tests.ps1 @@ -2,6 +2,18 @@ # Licensed under the MIT License. Describe "Hidden properties should not be returned by the 'FirstOrDefault' primitive" -Tag CI { + BeforeAll { + if ($null -ne $PSStyle) { + $outputRendering = $PSStyle.OutputRendering + $PSStyle.OutputRendering = 'plaintext' + } + } + + AfterAll { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $outputRendering + } + } It "Formatting for an object with no property/field should use 'ToString'" { class Empty { diff --git a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 index d77f9eb45f7..7de4f9d431d 100644 --- a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 +++ b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 @@ -15,12 +15,13 @@ Describe 'Tests for $ErrorView' -Tag CI { It 'Exceptions not thrown do not get formatted as ErrorRecord' { $exp = [System.Exception]::new('test') | Out-String - $exp | Should -BeLike "*Message : test*" + $exp | Should -BeLike "*Message : *test*" } Context 'ConciseView tests' { BeforeEach { $testScriptPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $testModulePath = Join-Path -Path $TestDrive -ChildPath 'test.psm1' } AfterEach { @@ -136,6 +137,19 @@ Describe 'Tests for $ErrorView' -Tag CI { $e = & "$PSHOME/pwsh" -noprofile -file $testScriptPath 2>&1 | Out-String $e.Split("o${newline}t").Count | Should -Be 1 -Because "Error message should not contain newline" } + + It "Script module error should not show line information" { + $testModule = @' + function Invoke-Error() { + throw 'oops' + } +'@ + + Set-Content -Path $testModulePath -Value $testModule + $e = & "$PSHOME/pwsh" -noprofile -command "Import-Module '$testModulePath'; Invoke-Error" 2>&1 | Out-String + $e | Should -Not -BeNullOrEmpty + $e | Should -Not -BeLike "*Line*" + } } Context 'NormalView tests' { @@ -156,4 +170,20 @@ Describe 'Tests for $ErrorView' -Tag CI { $e | Should -BeLike '*Oops!*' } } + + Context 'DetailedView tests' { + + It 'Detailed error is rendered' { + try { + $ErrorView = 'DetailedView' + throw 'Oops!' + } + catch { + # an extra newline gets added by the formatting system so we remove them + $e = ($_ | Out-String).Trim([Environment]::NewLine.ToCharArray()) + } + + $e | Should -BeExactly (Get-Error | Out-String).Trim([Environment]::NewLine.ToCharArray()) + } + } } diff --git a/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 b/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 new file mode 100644 index 00000000000..14085cc23ba --- /dev/null +++ b/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 @@ -0,0 +1,79 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe 'OutputRendering tests' { + BeforeEach { + if ($null -ne $PSStyle) { + $oldOutputRendering = $PSStyle.OutputRendering + } + } + + AfterEach { + if ($null -ne $PSStyle) { + $PSStyle.OutputRendering = $oldOutputRendering + } + } + + It 'OutputRendering works for "<outputRendering>" to the host' -TestCases @( + @{ outputRendering = 'host' ; ansi = $true } + @{ outputRendering = 'ansi' ; ansi = $true } + @{ outputRendering = 'plaintext'; ansi = $false } + ) { + param($outputRendering, $ansi) + + $out = pwsh -noprofile -command "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassOutputRedirectionCheck', `$true); `$PSStyle.OutputRendering = '$outputRendering'; write-host '$($PSStyle.Foreground.Green)hello'" + + if ($ansi) { + $out | Should -BeLike "*`e*" -Because ($out | Format-Hex | Out-String) + } + else { + $out | Should -Not -BeLike "*`e*" -Because ($out | Format-Hex | Out-String) + } + } + + It 'OutputRendering works for "<outputRendering>" to the pipeline' -TestCases @( + @{ outputRendering = 'host' ; ansi = $false } + @{ outputRendering = 'ansi' ; ansi = $true } + @{ outputRendering = 'plaintext'; ansi = $false } + ) { + param($outputRendering, $ansi) + + $PSStyle.OutputRendering = $outputRendering + $out = "$($PSStyle.Foreground.Green)hello" | Out-String + + if ($ansi) { + $out | Should -BeLike "*`e*" -Because ($out | Format-Hex | Out-String) + } + else { + $out | Should -Not -BeLike "*`e*" -Because ($out | Format-Hex | Out-String) + } + } + + # Error isn't covered here because it has custom formatting + It 'OutputRendering is correct for <stream>' -TestCases @( + @{ stream = 'Verbose' } + @{ stream = 'Debug' } + @{ stream = 'Warning' } + ) { + param($stream) + + if ($stream -ne 'Warning') + { + $switch = "-$stream" + } + + $out = pwsh -noprofile -command "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassOutputRedirectionCheck', `$true); write-$stream $switch 'hello';'bye'" + $out.Count | Should -Be 2 + $out[0] | Should -BeExactly "$($PSStyle.Formatting.$stream)$($stream.ToUpper()): hello$($PSStyle.Reset)" -Because ($out[0] | Out-String | Format-hex) + $out[1] | Should -BeExactly "bye" + } + + It 'ToString(OutputRendering) works correctly' { + $s = [System.Management.Automation.Internal.StringDecorated]::new($PSStyle.Foreground.Red + 'Hello') + $s.IsDecorated | Should -BeTrue + $s.ToString() | Should -BeExactly "$($PSStyle.Foreground.Red)Hello" + $s.ToString([System.Management.Automation.OutputRendering]::ANSI) | Should -BeExactly "$($PSStyle.Foreground.Red)Hello" + $s.ToString([System.Management.Automation.OutputRendering]::PlainText) | Should -BeExactly 'Hello' + { $s.ToString([System.Management.Automation.OutputRendering]::Host) } | Should -Throw -ErrorId 'ArgumentException' + } +} diff --git a/test/powershell/engine/Formatting/PSStyle.Tests.ps1 b/test/powershell/engine/Formatting/PSStyle.Tests.ps1 new file mode 100644 index 00000000000..04c13c5e04e --- /dev/null +++ b/test/powershell/engine/Formatting/PSStyle.Tests.ps1 @@ -0,0 +1,240 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe 'Tests for $PSStyle automatic variable' { + BeforeAll { + $styleDefaults = @{ + Reset = "`e[0m" + BlinkOff = "`e[25m" + Blink = "`e[5m" + BoldOff = "`e[22m" + Bold = "`e[1m" + HiddenOff = "`e[28m" + Hidden = "`e[8m" + ReverseOff = "`e[27m" + Reverse = "`e[7m" + ItalicOff = "`e[23m" + Italic = "`e[3m" + UnderlineOff = "`e[24m" + Underline = "`e[4m" + StrikethroughOff = "`e[29m" + Strikethrough = "`e[9m" + } + + $formattingDefaults = @{ + FormatAccent = "`e[32;1m" + TableHeader = "`e[32;1m" + ErrorAccent = "`e[36;1m" + Error = "`e[31;1m" + Debug = "`e[33;1m" + Verbose = "`e[33;1m" + Warning = "`e[33;1m" + } + + $foregroundDefaults = @{ + Black = "`e[30m" + White = "`e[37m" + BrightBlack = "`e[90m" + BrightWhite = "`e[97m" + Red = "`e[31m" + BrightRed = "`e[91m" + Magenta = "`e[35m" + BrightMagenta = "`e[95m" + Blue = "`e[34m" + BrightBlue = "`e[94m" + Cyan = "`e[36m" + BrightCyan = "`e[96m" + Green = "`e[32m" + BrightGreen = "`e[92m" + Yellow = "`e[33m" + BrightYellow = "`e[93m" + } + + $backgroundDefaults = @{ + Black = "`e[40m" + White = "`e[47m" + BrightBlack = "`e[100m" + BrightWhite = "`e[107m" + Red = "`e[41m" + BrightRed = "`e[101m" + Magenta = "`e[45m" + BrightMagenta = "`e[105m" + Blue = "`e[44m" + BrightBlue = "`e[104m" + Cyan = "`e[46m" + BrightCyan = "`e[106m" + Green = "`e[42m" + BrightGreen = "`e[102m" + Yellow = "`e[43m" + BrightYellow = "`e[103m" + } + + function Get-TestCases($hashtable) { + $testcases = [System.Collections.Generic.List[hashtable]]::new() + foreach ($key in $hashtable.Keys) { + $testcases.Add( + @{ Key = $key; Value = $hashtable[$key] } + ) + } + + return $testcases + } + } + + It '$PSStyle has correct default for OutputRendering' { + $PSStyle | Should -Not -BeNullOrEmpty + $PSStyle.OutputRendering | Should -BeExactly 'Host' + } + + It '$PSStyle has correct defaults for style <key>' -TestCases (Get-TestCases $styleDefaults) { + param($key, $value) + + $PSStyle.$key | Should -BeExactly $value + } + + It '$PSStyle.Formatting has correct default for <key>' -TestCases (Get-TestCases $formattingDefaults) { + param($key, $value) + + $PSStyle.Formatting.$key | Should -BeExactly $value + } + + It '$PSStyle.Foreground has correct default for <key>' -TestCases (Get-TestCases $foregroundDefaults) { + param($key, $value) + + $PSStyle.Foreground.$key | Should -BeExactly $value + } + + It '$PSStyle.Background has correct default for <key>' -TestCases (Get-TestCases $backgroundDefaults) { + param($key, $value) + + $PSStyle.Background.$key | Should -BeExactly $value + } + + It '$PSStyle.Foreground.FromRGB(r, g, b) works' { + $o = $PSStyle.Foreground.FromRGB(11,22,33) + $o | Should -BeExactly "`e[38;2;11;22;33m" -Because ($o | Format-Hex | Out-String) + } + + It '$PSStyle.Foreground.FromRGB(rgb) works' { + $o = $PSStyle.Foreground.FromRGB(0x223344) + $o | Should -BeExactly "`e[38;2;34;51;68m" -Because ($o | Format-Hex | Out-String) + } + + It '$PSStyle.Background.FromRGB(r, g, b) works' { + $o = $PSStyle.Background.FromRGB(33,44,55) + $o | Should -BeExactly "`e[48;2;33;44;55m" -Because ($o | Format-Hex | Out-String) + } + + It '$PSStyle.Background.FromRGB(rgb) works' { + $o = $PSStyle.Background.FromRGB(0x445566) + $o | Should -BeExactly "`e[48;2;68;85;102m" -Because ($o | Format-Hex | Out-String) + } + + It '$PSStyle.FormatHyperlink() works' { + $o = $PSStyle.FormatHyperlink('PSBlog','https://aka.ms/psblog') + $o | Should -BeExactly "`e]8;;https://aka.ms/psblog`e\PSBlog`e]8;;`e\" -Because ($o | Format-Hex | Out-String) + } + + It '$PSStyle.Formatting.FormatAccent is applied to Format-List' { + $old = $PSStyle.Formatting.FormatAccent + $oldRender = $PSStyle.OutputRendering + + try { + $PSStyle.OutputRendering = 'Ansi' + $PSStyle.Formatting.FormatAccent = $PSStyle.Foreground.Yellow + $PSStyle.Background.Red + $PSStyle.Italic + $out = $PSVersionTable | Format-List | Out-String + $out | Should -BeLike "*$($PSStyle.Formatting.FormatAccent.Replace('[',"``["))*" + } + finally { + $PSStyle.OutputRendering = $oldRender + $PSStyle.Formatting.FormatAccent = $old + } + } + + It '$PSStyle.Formatting.TableHeader is applied to Format-Table' { + $old = $PSStyle.Formatting.TableHeader + $oldRender = $PSStyle.OutputRendering + + try { + $PSStyle.OutputRendering = 'Ansi' + $PSStyle.Formatting.TableHeader = $PSStyle.Foreground.Blue + $PSStyle.Background.White + $PSStyle.Bold + $out = $PSVersionTable | Format-Table | Out-String + $out | Should -BeLike "*$($PSStyle.Formatting.TableHeader.Replace('[',"``["))*" + } + finally { + $PSStyle.OutputRendering = $oldRender + $PSStyle.Formatting.TableHeader = $old + } + } + + It 'Should fail if setting formatting contains printable characters: <member>.<submember>' -TestCases @( + @{ Submember = 'Reset' } + @{ Submember = 'BlinkOff' } + @{ Submember = 'Blink' } + @{ Submember = 'BoldOff' } + @{ Submember = 'Bold' } + @{ Submember = 'HiddenOff' } + @{ Submember = 'Hidden' } + @{ Submember = 'ItalicOff' } + @{ Submember = 'Italic' } + @{ Submember = 'UnderlineOff' } + @{ Submember = 'Underline' } + @{ Submember = 'StrikethroughOff' } + @{ Submember = 'Strikethrough' } + @{ Member = 'Formatting'; Submember = 'FormatAccent' } + @{ Member = 'Formatting'; Submember = 'TableHeader' } + @{ Member = 'Formatting'; Submember = 'ErrorAccent' } + @{ Member = 'Formatting'; Submember = 'Error' } + @{ Member = 'Formatting'; Submember = 'Warning' } + @{ Member = 'Formatting'; Submember = 'Verbose' } + @{ Member = 'Formatting'; Submember = 'Debug' } + @{ Member = 'Progress'; Submember = 'Style' } + @{ Member = 'FileInfo'; Submember = 'Directory' } + @{ Member = 'FileInfo'; Submember = 'SymbolicLink' } + @{ Member = 'FileInfo'; Submember = 'Executable' } + @{ Member = 'FileInfo'; Submember = 'Hidden' } + ) { + param ($member, $submember) + + if ($null -ne $member) { + { $PSStyle.$member.$submember = $PSStyle.Foreground.Red + 'hello' } | Should -Throw + } + else { + { $PSStyle.$submember = $PSStyle.Foreground.Red + 'hello' } | Should -Throw + } + } + + It 'Should fail adding extension formatting with printable characters' { + { $PSStyle.FileInfo.Extension.Add('.md', 'hello') } | Should -Throw -ErrorId 'ArgumentException' + } + + It 'Should add and remove extension' { + $extension = '.mytest' + $PSStyle.FileInfo.Extension.Keys | Should -Not -Contain $extension + $PSStyle.FileInfo.Extension.Add($extension, $PSStyle.Foreground.Blue) + + $PSStyle.FileInfo.Extension[$extension] | Should -Be $PSStyle.Foreground.Blue + $PSStyle.FileInfo.Extension.Remove($extension) + $PSStyle.FileInfo.Extension.Keys | Should -Not -Contain $extension + } + + It 'Should fail to add extension does not start with a period' { + { $PSStyle.FileInfo.Extension.Add('mytest', $PSStyle.Foreground.Blue) } | Should -Throw -ErrorId 'ArgumentException' + } + + It 'Should fail to remove extension does not start with a period' { + { $PSStyle.FileInfo.Extension.Remove('zip') } | Should -Throw -ErrorId 'ArgumentException' + } + + It 'Should fail if MaxWidth is less than 18' { + $maxWidth = $PSStyle.Progress.MaxWidth + + # minimum allowed width is 18 as less than that doesn't render correctly + try { + { $PSStyle.Progress.MaxWidth = 17 } | Should -Throw -ErrorId 'ExceptionWhenSetting' + } + finally { + $PSStyle.Progress.MaxWidth = $maxWidth + } + } +} diff --git a/test/powershell/engine/Help/HelpSystem.Tests.ps1 b/test/powershell/engine/Help/HelpSystem.Tests.ps1 index d3c508fe40a..3fbd0822352 100644 --- a/test/powershell/engine/Help/HelpSystem.Tests.ps1 +++ b/test/powershell/engine/Help/HelpSystem.Tests.ps1 @@ -16,7 +16,7 @@ $script:cmdletsToSkip = @( "Get-ExperimentalFeature", "Enable-ExperimentalFeature", "Disable-ExperimentalFeature", - "Get-Subsystem" + "Get-PSSubsystem" ) function UpdateHelpFromLocalContentPath { diff --git a/test/powershell/engine/Help/assets/HelpURI/V2Cmdlets.csv b/test/powershell/engine/Help/assets/HelpURI/V2Cmdlets.csv index a88e715c347..465574bca58 100644 --- a/test/powershell/engine/Help/assets/HelpURI/V2Cmdlets.csv +++ b/test/powershell/engine/Help/assets/HelpURI/V2Cmdlets.csv @@ -159,6 +159,7 @@ Register-EngineEvent,https://go.microsoft.com/fwlink/?linkid=2097128 Register-ObjectEvent,https://go.microsoft.com/fwlink/?linkid=2096714 Register-PSSessionConfiguration,https://go.microsoft.com/fwlink/?linkid=2096793 Register-WmiEvent,https://go.microsoft.com/fwlink/?LinkID=135245 +Remove-Alias,https://go.microsoft.com/fwlink/?linkid=2097127 Remove-Computer,https://go.microsoft.com/fwlink/?LinkID=135246 Remove-Event,https://go.microsoft.com/fwlink/?linkid=2096715 Remove-EventLog,https://go.microsoft.com/fwlink/?LinkID=135248 diff --git a/test/powershell/engine/ParameterBinding/ParameterBinding.Tests.ps1 b/test/powershell/engine/ParameterBinding/ParameterBinding.Tests.ps1 index 07d132012a0..5bacbae7b2d 100644 --- a/test/powershell/engine/ParameterBinding/ParameterBinding.Tests.ps1 +++ b/test/powershell/engine/ParameterBinding/ParameterBinding.Tests.ps1 @@ -256,6 +256,70 @@ Describe "Parameter Binding Tests" -Tags "CI" { DynamicParamTest -PipelineVariable bar | ForEach-Object { $bar } | Should -Be "hi" } + It 'Dynamic parameter is found even if globbed path does not exist' { + $guid = New-Guid + + # This test verifies that the ErrorRecord is coming from parameter validation on a dynamic parameter + # instead of an error indicating that the dynamic parameter is not found + { Copy-Item "~\$guid*" -Destination ~ -ToSession $null } | Should -Throw -ErrorId 'ParameterArgumentValidationError' + } + + Context "PipelineVariable Behaviour" { + + BeforeAll { + function Write-PipelineVariable { + [CmdletBinding()] + [OutputType([int])] + param( + [Parameter(ValueFromPipeline)] + $a + ) + begin { 1 } + process { 2 } + end { 3 } + } + + $testScripts = @( + @{ + CmdletType = 'Script Cmdlet' + Script = { + 1..3 | + Write-PipelineVariable -PipelineVariable pipe | + Select-Object -Property @( + @{ Name = "PipelineVariableSet"; Expression = { $null -ne $pipe ? $true : $false } } + @{ Name = "PipelineVariable"; Expression = { $pipe } } + ) + } + } + @{ + CmdletType = 'Compiled Cmdlet' + Script = { + 1..3 | + Write-PipelineVariable | + ForEach-Object { $_ } -PipelineVariable pipe | + Select-Object -Property @( + @{ Name = "PipelineVariableSet"; Expression = { $null -ne $pipe ? $true : $false } } + @{ Name = "PipelineVariable"; Expression = { $pipe } } + ) + } + } + ) + } + + AfterAll { + Remove-Item -Path 'function:Write-PipelineVariable' + } + + It 'should set the pipeline variable every time for a <CmdletType>' -TestCases $testScripts { + param($Script, $CmdletType) + + $result = & $Script + $result.Count | Should -Be 5 + $result.PipelineVariableSet | Should -Not -Contain $false + $result.PipelineVariable | Should -Be 1, 2, 2, 2, 3 + } + } + Context "Use automatic variables as default value for parameters" { BeforeAll { ## Explicit use of 'CmdletBinding' make it a script cmdlet diff --git a/test/powershell/engine/Remoting/ImplicitRemotingBatching.Tests.ps1 b/test/powershell/engine/Remoting/ImplicitRemotingBatching.Tests.ps1 deleted file mode 100644 index 62c72790622..00000000000 --- a/test/powershell/engine/Remoting/ImplicitRemotingBatching.Tests.ps1 +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -Describe "TestImplicitRemotingBatching hook should correctly batch simple remote command pipelines" -Tag 'Feature','RequireAdminOnWindows' { - - BeforeAll { - - if (! $IsWindows) { return } - - function ThrowSetupError - { - param ( - [string] $errorMessage, - [System.Management.Automation.ErrorRecord[]] $eRecords - ) - - $msg = @() - foreach ($err in $powerShell.Streams.Error) - { - $msg += $err.ToString() + "`n" - } - - throw "$errorMessage : '$msg'" - } - - # Make sure we can create a remote session - $remotePSSession = New-RemoteSession - if ($remotePSSession -eq $null) - { - Write-Verbose "Unable to create a remote session in test." - } - else - { - Remove-PSSession $remotePSSession - } - - [powershell] $powerShell = [powershell]::Create([System.Management.Automation.RunspaceMode]::NewRunspace) - - # Create remote session in new PowerShell session - $powerShell.AddScript('Import-Module -Name HelpersRemoting; $remoteSession = New-RemoteSession').Invoke() - if ($powerShell.Streams.Error.Count -gt 0) - { - ThrowSetupError -errorMessage "Unable to create remote session for test with error" -eRecords $powerShell.Streams.Error - } - - # Import implicit commands from remote session - $powerShell.Commands.Clear() - $powerShell.AddScript('Import-PSSession -Session $remoteSession -CommandName Get-Process,Write-Output -AllowClobber').Invoke() - if ($powerShell.Streams.Error.Count -gt 0) - { - ThrowSetupError -errorMessage "Unable to import pssession for test" -eRecords $powerShell.Streams.Error - } - - # Define $filter variable in local session - $powerShell.Commands.Clear() - $powerShell.AddScript('$filter = "pwsh","powershell"').Invoke() - $localRunspace = $powerShell.Runspace - - [powershell] $psInvoke = [powershell]::Create([System.Management.Automation.RunspaceMode]::NewRunspace) - - $testCases = @( - @{ - Name = 'Two implicit commands should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | Write-Output' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Where-Object should be successfully batched' - CommandLine = 'Get-Process | Write-Output | Where-Object { $_.Name -like "*pwsh*" }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Where-Object alias (?) should be successfully batched' - CommandLine = 'Get-Process | Write-Output | ? { $_.Name -like "*pwsh*" }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Where-Object alias (where) should be successfully batched' - CommandLine = 'Get-Process | Write-Output | where { $_.Name -like "*pwsh*" }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Sort-Object should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | Sort-Object -Property Name | Write-Output' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Sort-Object alias (sort) should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | sort -Property Name | Write-Output' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with ForEach-Object should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | Write-Output | ForEach-Object { $_ }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with ForEach-Object alias (%) should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | Write-Output | % { $_ }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with ForEach-Object alias (foreach) should be successfully batched' - CommandLine = 'Get-Process -Name "pwsh" | Write-Output | foreach { $_ }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Measure-Command should be successfully batched' - CommandLine = 'Measure-Command { Get-Process | Write-Output }' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Measure-Object should be successfully batched' - CommandLine = 'Get-Process | Write-Output | Measure-Object' - ExpectedOutput = $true - }, - @{ - Name = 'Two implicit commands with Measure-Object alias (measure) should be successfully batched' - CommandLine = 'Get-Process | Write-Output | measure' - ExpectedOutput = $true - }, - @{ - Name = 'Implicit commands with variable arguments should be successfully batched' - CommandLine = 'Get-Process -Name $filter | Write-Output' - ExpectedOutput = $true - }, - @{ - Name = 'Pipeline with non-implicit command should not be batched' - CommandLine = 'Get-Process | Write-Output | Select-Object -Property Name' - ExpectedOutput = $false - }, - @{ - Name = 'Non-simple pipeline should not be batched' - CommandLine = '1..2 | % { Get-Process pwsh | Write-Output }' - ExpectedOutput = $false - } - @{ - Name = 'Pipeline with single command should not be batched' - CommandLine = 'Get-Process pwsh' - ExpectedOutput = $false - }, - @{ - Name = 'Pipeline without any implicit commands should not be batched' - CommandLine = 'Get-PSSession | Out-Default' - ExpectedOutput = $false - } - ) - } - - AfterAll { - - if (! $IsWindows) { return } - - if ($remoteSession -ne $null) { Remove-PSSession $remoteSession -ErrorAction Ignore } - if ($powershell -ne $null) { $powershell.Dispose() } - if ($psInvoke -ne $null) { $psInvoke.Dispose() } - } - - It "<Name>" -TestCases $testCases -Skip:(! $IsWindows) { - param ($CommandLine, $ExpectedOutput) - - $psInvoke.Commands.Clear() - $psInvoke.Commands.AddScript('param ($cmdLine, $runspace) [System.Management.Automation.Internal.InternalTestHooks]::TestImplicitRemotingBatching($cmdLine, $runspace)').AddArgument($CommandLine).AddArgument($localRunspace) - - $result = $psInvoke.Invoke() - $result | Should -Be $ExpectedOutput - } -} diff --git a/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 b/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 index 7829aa38770..fef7da0e75e 100644 --- a/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 +++ b/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 @@ -174,7 +174,7 @@ Describe "Invoke-Command remote debugging tests" -Tags 'Feature','RequireAdminOn $ps.Commands.Clear() $ps2.Commands.Clear() - Remove-PSSession $remoteSession -ErrorAction SilentlyContinue + if ($null -ne $remoteSession) { Remove-PSSession $remoteSession -ErrorAction SilentlyContinue } $remoteSession = $null } diff --git a/test/powershell/engine/Remoting/PSSession.Tests.ps1 b/test/powershell/engine/Remoting/PSSession.Tests.ps1 index e985ff6ab36..25c7ab9c582 100644 --- a/test/powershell/engine/Remoting/PSSession.Tests.ps1 +++ b/test/powershell/engine/Remoting/PSSession.Tests.ps1 @@ -5,6 +5,11 @@ # PSSession tests for non-Windows platforms # +function GetRandomString() +{ + return [System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetRandomFileName()) +} + Describe "New-PSSessionOption parameters for non-Windows platforms" -Tag "CI" { BeforeAll { @@ -36,12 +41,13 @@ Describe "SkipCACheck and SkipCNCheck PSSession options are required for New-PSS BeforeAll { $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() - if ($IsWindows) { + # Skip this test for macOS because the latest OS release is incompatible with our shipped libmi for WinRM/OMI. + if ($IsWindows -or $IsMacOS) { $PSDefaultParameterValues['it:skip'] = $true } else { $userName = "User_$(Get-Random -Maximum 99999)" - $userPassword = "Password_$(Get-Random -Maximum 99999)" + $userPassword = GetRandomString $cred = [pscredential]::new($userName, (ConvertTo-SecureString -String $userPassword -AsPlainText -Force)) $soSkipCA = New-PSSessionOption -SkipCACheck $soSkipCN = New-PSSessionOption -SkipCNCheck @@ -54,7 +60,7 @@ Describe "SkipCACheck and SkipCNCheck PSSession options are required for New-PSS $testCases = @( @{ - Name = 'Verifies expected error when session options is missing' + Name = 'Verifies expected error when session option is missing' ScriptBlock = { New-PSSession -cn localhost -Credential $cred -Authentication Basic -UseSSL } ExpectedErrorCode = 825 }, @@ -77,7 +83,8 @@ Describe "SkipCACheck and SkipCNCheck PSSession options are required for New-PSS if ( ($platformInfo.Platform -match "alpine|raspbian") -or ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') + ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') -or + ($platformInfo.Platform -eq 'ubuntu' -and $platformInfo.Version -eq '20.04') ) { Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, and CentOS 8" return diff --git a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 index e48eaecb526..d56ed1999ac 100644 --- a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 +++ b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 @@ -3,19 +3,26 @@ Import-Module HelpersCommon +function GetRandomString() +{ + return [System.IO.Path]::GetFileNameWithoutExtension([System.IO.Path]::GetRandomFileName()) +} + Describe "New-PSSession basic test" -Tag @("CI") { It "New-PSSession should not crash powershell" { $platformInfo = Get-PlatformInfo if ( ($platformInfo.Platform -match "alpine|raspbian") -or ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') + ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') -or + ($platformInfo.Platform -eq 'ubuntu' -and $platformInfo.Version -eq '20.04') -or + ($IsMacOS) ) { - Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, and CentOS 8" + Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, CentOS 8, and not compatible with macOS" return } - { New-PSSession -ComputerName nonexistcomputer -Authentication Basic } | + { New-PSSession -ComputerName (GetRandomString) -Authentication Basic } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.NewPSSessionCommand" } } @@ -26,13 +33,15 @@ Describe "Basic Auth over HTTP not allowed on Unix" -Tag @("CI") { if ( ($platformInfo.Platform -match "alpine|raspbian") -or ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') + ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') -or + ($platformInfo.Platform -eq 'ubuntu' -and $platformInfo.Version -eq '20.04') -or + ($IsMacOS) ) { - Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, and CentOS 8" + Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, CentOS 8, and not compatible with macOS" return } - $password = ConvertTo-SecureString -String "password" -AsPlainText -Force + $password = ConvertTo-SecureString -String (GetRandomString) -AsPlainText -Force $credential = [PSCredential]::new('username', $password) $err = ({New-PSSession -ComputerName 'localhost' -Credential $credential -Authentication Basic} | Should -Throw -PassThru -ErrorId 'System.Management.Automation.Remoting.PSRemotingDataStructureException,Microsoft.PowerShell.Commands.NewPSSessionCommand') @@ -42,18 +51,21 @@ Describe "Basic Auth over HTTP not allowed on Unix" -Tag @("CI") { $err.Exception.ErrorCode | Should -Be 801 } + # Skip this test for macOS because the latest OS release is incompatible with our shipped libmi for WinRM/OMI. It "New-PSSession should NOT throw a ConnectFailed exception when specifying Basic Auth over HTTPS on Unix" -Skip:($IsWindows) { $platformInfo = Get-PlatformInfo if ( ($platformInfo.Platform -match "alpine|raspbian") -or ($platformInfo.Platform -eq "debian" -and ($platformInfo.Version -eq '10' -or $platformInfo.Version -eq '')) -or # debian 11 has empty Version ID - ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') + ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '8') -or + ($platformInfo.Platform -eq 'ubuntu' -and $platformInfo.Version -eq '20.04') -or + ($IsMacOS) ) { - Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, and CentOS 8" + Set-ItResult -Skipped -Because "MI library not available for Alpine, Raspberry Pi, Debian 10 and 11, CentOS 8, and not compatible with macOS" return } - $password = ConvertTo-SecureString -String "password" -AsPlainText -Force + $password = ConvertTo-SecureString -String (GetRandomString) -AsPlainText -Force $credential = [PSCredential]::new('username', $password) # use a Uri that specifies HTTPS to test Basic Auth logic. @@ -336,5 +348,16 @@ Describe "Remoting loopback tests" -Tags @('CI', 'RequireAdminOnWindows') { $result = Invoke-Command -Session $openSession -ScriptBlock { $using:number } $result | Should -Be 100 } + + It '$Host.Version should be PSVersion' { + $session = New-RemoteSession -ConfigurationName $endPoint + try { + $result = Invoke-Command -Session $session -ScriptBlock { $Host.Version } + $result | Should -Be $PSVersionTable.PSVersion + } + finally { + $session | Remove-PSSession -ErrorAction Ignore + } + } } diff --git a/test/powershell/engine/Remoting/RemoteSession.Disconnect.Tests.ps1 b/test/powershell/engine/Remoting/RemoteSession.Disconnect.Tests.ps1 index a26769ad2ba..c98e3045e7e 100644 --- a/test/powershell/engine/Remoting/RemoteSession.Disconnect.Tests.ps1 +++ b/test/powershell/engine/Remoting/RemoteSession.Disconnect.Tests.ps1 @@ -72,7 +72,7 @@ Describe "WinRM based remoting session abrupt disconnect" -Tags 'Feature','Requi } -ErrorAction SilentlyContinue # Session should be disconnected. - $session.State | Should -BeExactly 'Disconnected' + $session.State | Should -BeLikeExactly 'Disconnect*' # A disconnected job should have been created for reconnect. $script:job = Get-Job | Where-Object { $_.ChildJobs[0].Runspace.Id -eq $session.Runspace.Id } diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 index 0071f16fcdc..894a85ff14d 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 @@ -219,22 +219,21 @@ function Send-VstsLogFile { } } + $newName = ([System.Io.Path]::GetRandomFileName() + "-$LogName.txt") if($Contents) { - $logFile = Join-Path -Path $logFolder -ChildPath ([System.Io.Path]::GetRandomFileName() + "-$LogName.txt") - $name = Split-Path -Leaf -Path $logFile + $logFile = Join-Path -Path $logFolder -ChildPath $newName $Contents | Out-File -path $logFile -Encoding ascii } else { - $name = Split-Path -Leaf -Path $path - $logFile = Join-Path -Path $logFolder -ChildPath ([System.Io.Path]::GetRandomFileName() + '-' + $name) + $logFile = Join-Path -Path $logFolder -ChildPath $newName Copy-Item -Path $Path -Destination $logFile } - Write-Host "##vso[artifact.upload containerfolder=$name;artifactname=$name]$logFile" - Write-Verbose "Log file captured as $name" -Verbose + Write-Host "##vso[artifact.upload containerfolder=$newName;artifactname=$newName]$logFile" + Write-Verbose "Log file captured as $newName" -Verbose } # Tests if the Linux or macOS user is root diff --git a/test/tools/Modules/HelpersRemoting/HelpersRemoting.psm1 b/test/tools/Modules/HelpersRemoting/HelpersRemoting.psm1 index 96461bd5fb0..b5544364260 100644 --- a/test/tools/Modules/HelpersRemoting/HelpersRemoting.psm1 +++ b/test/tools/Modules/HelpersRemoting/HelpersRemoting.psm1 @@ -18,7 +18,7 @@ function Get-DefaultEndPointName if ($endPoint -eq $null) { - Enable-PSRemoting -SkipNetworkProfileCheck + $null = Enable-PSRemoting -SkipNetworkProfileCheck $endPoint = Get-PSSessionConfiguration -Name $endPointName -ErrorAction SilentlyContinue if ($endPoint -eq $null) @@ -30,7 +30,7 @@ function Get-DefaultEndPointName if ($endPoint.Permission -like "*NT AUTHORITY\NETWORK AccessDenied*") { - Enable-PSRemoting -SkipNetworkProfileCheck + $null = Enable-PSRemoting -SkipNetworkProfileCheck $endPoint = Get-PSSessionConfiguration -Name $endPointName -ErrorAction SilentlyContinue if ($endPoint.Permission -like "*NT AUTHORITY\NETWORK AccessDenied*") diff --git a/test/tools/Modules/PSSysLog/PSSysLog.psm1 b/test/tools/Modules/PSSysLog/PSSysLog.psm1 index 660e98226b2..00dd74be5af 100644 --- a/test/tools/Modules/PSSysLog/PSSysLog.psm1 +++ b/test/tools/Modules/PSSysLog/PSSysLog.psm1 @@ -302,7 +302,7 @@ class PSLogItem } else { - Write-Warning -Message "Could not split EventId $($item.EventId) on '[] ' Count:$($subparts.Count)" + Write-Warning -Message "Could not split EventId $($item.EventId) on '[] ' Count:$($subparts.Count) -> $content" } # (commitid:TID:ChannelID) @@ -317,7 +317,7 @@ class PSLogItem } else { - Write-Warning -Message "Could not split CommitId $($item.CommitId) on '(): ' Count:$($subparts.Count)" + Write-Warning -Message "Could not split CommitId $($item.CommitId) on '(): ' Count:$($subparts.Count) -> $content" } # nameid[PID] @@ -331,7 +331,7 @@ class PSLogItem } else { - Write-Warning -Message "Could not split LogId $($item.LogId) on '[]:' Count:$($subparts.Count)" + Write-Warning -Message "Could not split LogId $($item.LogId) on '[]:' Count:$($subparts.Count) -> $content" } return $item @@ -497,11 +497,18 @@ function ConvertFrom-SysLog { foreach ($line in $Content) { - [PSLogItem] $item = [PSLogItem]::ConvertSysLog($line, $id, $after) - if ($item -ne $null) + try { - $totalWritten++ - Write-Output $item + [PSLogItem] $item = [PSLogItem]::ConvertSysLog($line, $id, $after) + if ($item -ne $null) + { + $totalWritten++ + Write-Output $item + } + } + catch + { + Write-Warning -Message "Could not convert '$line' to PSLogItem" } } } diff --git a/test/tools/Modules/WebListener/WebListener.psm1 b/test/tools/Modules/WebListener/WebListener.psm1 index 6436da97d1c..655b4cdd638 100644 --- a/test/tools/Modules/WebListener/WebListener.psm1 +++ b/test/tools/Modules/WebListener/WebListener.psm1 @@ -102,7 +102,7 @@ function Start-WebListener [int]$HttpPort = 8083, [ValidateRange(1,65535)] - [int]$HttpsPort = 8084, + [int]$HttpsPort = 9084, [ValidateRange(1,65535)] [int]$Tls11Port = 8085, diff --git a/test/tools/Modules/nuget.config b/test/tools/Modules/nuget.config new file mode 100644 index 00000000000..b0fc73009da --- /dev/null +++ b/test/tools/Modules/nuget.config @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <packageSources> + <clear /> + <add key="PSGallery" value="https://www.powershellgallery.com/api/v2/" /> + </packageSources> + <disabledPackageSources> + <clear /> + </disabledPackageSources> +</configuration> diff --git a/test/tools/OpenCover/OpenCover.psm1 b/test/tools/OpenCover/OpenCover.psm1 index 45d5c682a19..d0def0abf6c 100644 --- a/test/tools/OpenCover/OpenCover.psm1 +++ b/test/tools/OpenCover/OpenCover.psm1 @@ -615,7 +615,7 @@ function Install-OpenCover .Description Invoke-OpenCover runs tests under OpenCover by executing tests on PowerShell located at $PowerShellExeDirectory. .EXAMPLE - Invoke-OpenCover -TestPath $PWD/test/powershell -PowerShellExeDirectory $PWD/src/powershell-win-core/bin/CodeCoverage/net5.0/win7-x64 + Invoke-OpenCover -TestPath $PWD/test/powershell -PowerShellExeDirectory $PWD/src/powershell-win-core/bin/CodeCoverage/net6.0/win7-x64 #> function Invoke-OpenCover { @@ -624,7 +624,7 @@ function Invoke-OpenCover [parameter()]$OutputLog = "$HOME/Documents/OpenCover.xml", [parameter()]$TestPath = "${script:psRepoPath}/test/powershell", [parameter()]$OpenCoverPath = "$HOME/OpenCover", - [parameter()]$PowerShellExeDirectory = "${script:psRepoPath}/src/powershell-win-core/bin/CodeCoverage/net5.0/win7-x64/publish", + [parameter()]$PowerShellExeDirectory = "${script:psRepoPath}/src/powershell-win-core/bin/CodeCoverage/net6.0/win7-x64/publish", [parameter()]$PesterLogElevated = "$HOME/Documents/TestResultsElevated.xml", [parameter()]$PesterLogUnelevated = "$HOME/Documents/TestResultsUnelevated.xml", [parameter()]$PesterLogFormat = "NUnitXml", diff --git a/test/tools/TestExe/TestExe.cs b/test/tools/TestExe/TestExe.cs index 1293a4acaee..fa57fb57215 100644 --- a/test/tools/TestExe/TestExe.cs +++ b/test/tools/TestExe/TestExe.cs @@ -7,13 +7,13 @@ namespace TestExe { - class TestExe + internal class TestExe { - static int Main(string[] args) + private static int Main(string[] args) { if (args.Length > 0) { - switch(args[0].ToLowerInvariant()) + switch (args[0].ToLowerInvariant()) { case "-echoargs": EchoArgs(args); @@ -44,11 +44,11 @@ static int Main(string[] args) // <Summary> // Echos back to stdout the arguments passed in // </Summary> - static void EchoArgs(string[] args) + private static void EchoArgs(string[] args) { for (int i = 1; i < args.Length; i++) { - Console.WriteLine("Arg {0} is <{1}>", i-1, args[i]); + Console.WriteLine("Arg {0} is <{1}>", i - 1, args[i]); } } @@ -56,7 +56,7 @@ static void EchoArgs(string[] args) // First argument is the number of child processes to create which are instances of itself // Processes automatically exit after 100 seconds // </Summary> - static void CreateChildProcess(string[] args) + private static void CreateChildProcess(string[] args) { if (args.Length > 1) { @@ -64,7 +64,7 @@ static void CreateChildProcess(string[] args) for (uint i = 0; i < num; i++) { Process child = new Process(); - child.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName; + child.StartInfo.FileName = Environment.ProcessPath; child.StartInfo.Arguments = "-createchildprocess"; child.Start(); } diff --git a/test/tools/TestService/Program.cs b/test/tools/TestService/Program.cs index 2e7a2ae1b42..83305624582 100644 --- a/test/tools/TestService/Program.cs +++ b/test/tools/TestService/Program.cs @@ -5,9 +5,9 @@ namespace TestService { - static class Program + internal static class Program { - static void Main() + private static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] diff --git a/test/tools/TestService/TestService.csproj b/test/tools/TestService/TestService.csproj index 9e5f96b310a..491a77f0c80 100644 --- a/test/tools/TestService/TestService.csproj +++ b/test/tools/TestService/TestService.csproj @@ -13,7 +13,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.0-rc.1.20451.14" /> + <PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" /> </ItemGroup> </Project> diff --git a/test/tools/WebListener/Controllers/AuthController.cs b/test/tools/WebListener/Controllers/AuthController.cs index 10ade84f2ed..6e8349ebe97 100644 --- a/test/tools/WebListener/Controllers/AuthController.cs +++ b/test/tools/WebListener/Controllers/AuthController.cs @@ -28,7 +28,7 @@ public JsonResult Basic() } else { - Response.Headers.Add("WWW-Authenticate","Basic realm=\"WebListener\""); + Response.Headers.Add("WWW-Authenticate", "Basic realm=\"WebListener\""); Response.StatusCode = 401; return Json("401 Unauthorized"); } @@ -45,7 +45,7 @@ public JsonResult Negotiate() } else { - Response.Headers.Add("WWW-Authenticate","Negotiate"); + Response.Headers.Add("WWW-Authenticate", "Negotiate"); Response.StatusCode = 401; return Json("401 Unauthorized"); } @@ -62,7 +62,7 @@ public JsonResult Ntlm() } else { - Response.Headers.Add("WWW-Authenticate","NTLM"); + Response.Headers.Add("WWW-Authenticate", "NTLM"); Response.StatusCode = 401; return Json("401 Unauthorized"); } diff --git a/test/tools/WebListener/Controllers/CertController.cs b/test/tools/WebListener/Controllers/CertController.cs index 077708c41fc..0de2dd3632d 100644 --- a/test/tools/WebListener/Controllers/CertController.cs +++ b/test/tools/WebListener/Controllers/CertController.cs @@ -25,14 +25,14 @@ public JsonResult Index() { output = new Hashtable { - {"Status" , "OK"}, - {"Thumbprint" , HttpContext.Connection.ClientCertificate.Thumbprint}, - {"Subject" , HttpContext.Connection.ClientCertificate.Subject}, - {"SubjectName" , HttpContext.Connection.ClientCertificate.SubjectName.Name}, - {"Issuer" , HttpContext.Connection.ClientCertificate.Issuer}, - {"IssuerName" , HttpContext.Connection.ClientCertificate.IssuerName.Name}, - {"NotAfter" , HttpContext.Connection.ClientCertificate.NotAfter}, - {"NotBefore" , HttpContext.Connection.ClientCertificate.NotBefore} + {"Status", "OK"}, + {"Thumbprint", HttpContext.Connection.ClientCertificate.Thumbprint}, + {"Subject", HttpContext.Connection.ClientCertificate.Subject}, + {"SubjectName", HttpContext.Connection.ClientCertificate.SubjectName.Name}, + {"Issuer", HttpContext.Connection.ClientCertificate.Issuer}, + {"IssuerName", HttpContext.Connection.ClientCertificate.IssuerName.Name}, + {"NotAfter", HttpContext.Connection.ClientCertificate.NotAfter}, + {"NotBefore", HttpContext.Connection.ClientCertificate.NotBefore} }; } diff --git a/test/tools/WebListener/Controllers/DosController.cs b/test/tools/WebListener/Controllers/DosController.cs index 6024430095e..7fc138e0e81 100644 --- a/test/tools/WebListener/Controllers/DosController.cs +++ b/test/tools/WebListener/Controllers/DosController.cs @@ -22,7 +22,6 @@ public string Index() Response.StatusCode = 200; - StringValues dosType; if (Request.Query.TryGetValue("dosType", out dosType)) { diff --git a/test/tools/WebListener/Controllers/GetController.cs b/test/tools/WebListener/Controllers/GetController.cs index cadb34725a8..03f733f5049 100644 --- a/test/tools/WebListener/Controllers/GetController.cs +++ b/test/tools/WebListener/Controllers/GetController.cs @@ -32,11 +32,12 @@ public JsonResult Index() Hashtable output = new Hashtable { - {"args" , args}, + {"args", args}, {"headers", headers}, - {"origin" , Request.HttpContext.Connection.RemoteIpAddress.ToString()}, - {"url" , UriHelper.GetDisplayUrl(Request)}, - {"method" , Request.Method} + {"origin", Request.HttpContext.Connection.RemoteIpAddress.ToString()}, + {"url", UriHelper.GetDisplayUrl(Request)}, + {"query", Request.QueryString.ToUriComponent()}, + {"method", Request.Method} }; if (Request.HasFormContentType) @@ -44,7 +45,7 @@ public JsonResult Index() Hashtable form = new Hashtable(); foreach (var key in Request.Form.Keys) { - form.Add(key,Request.Form[key]); + form.Add(key, Request.Form[key]); } output["form"] = form; diff --git a/test/tools/WebListener/Controllers/LinkController.cs b/test/tools/WebListener/Controllers/LinkController.cs index 3aa7541f4ee..e15607d6b9b 100644 --- a/test/tools/WebListener/Controllers/LinkController.cs +++ b/test/tools/WebListener/Controllers/LinkController.cs @@ -109,7 +109,7 @@ public IActionResult Error() return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } - private string GetLink(string baseUri, int maxLinks, int linkNumber, string whitespace, string type, string rel) + private static string GetLink(string baseUri, int maxLinks, int linkNumber, string whitespace, string type, string rel) { return string.Format(Constants.LinkUriTemplate, baseUri, maxLinks, linkNumber, type, whitespace, rel); } diff --git a/test/tools/WebListener/Controllers/MultipartController.cs b/test/tools/WebListener/Controllers/MultipartController.cs index 0d5a9efba27..56e8c2003d4 100644 --- a/test/tools/WebListener/Controllers/MultipartController.cs +++ b/test/tools/WebListener/Controllers/MultipartController.cs @@ -18,7 +18,7 @@ namespace mvc.Controllers { public class MultipartController : Controller { - private IWebHostEnvironment _environment; + private readonly IWebHostEnvironment _environment; public MultipartController(IWebHostEnvironment environment) { @@ -36,7 +36,7 @@ public JsonResult Index(IFormCollection collection) if (!Request.HasFormContentType) { Response.StatusCode = 415; - Hashtable error = new Hashtable {{"error","Unsupported media type"}}; + Hashtable error = new Hashtable { { "error", "Unsupported media type" } }; return Json(error); } @@ -54,13 +54,13 @@ public JsonResult Index(IFormCollection collection) Hashtable fileHash = new Hashtable { - {"ContentDisposition" , file.ContentDisposition}, - {"ContentType" , file.ContentType}, - {"FileName" , file.FileName}, - {"Length" , file.Length}, - {"Name" , file.Name}, - {"Content" , result}, - {"Headers" , file.Headers} + {"ContentDisposition", file.ContentDisposition}, + {"ContentType", file.ContentType}, + {"FileName", file.FileName}, + {"Length", file.Length}, + {"Name", file.Name}, + {"Content", result}, + {"Headers", file.Headers} }; fileList.Add(fileHash); } @@ -68,7 +68,7 @@ public JsonResult Index(IFormCollection collection) Hashtable itemsHash = new Hashtable(); foreach (var key in collection.Keys) { - itemsHash.Add(key,collection[key]); + itemsHash.Add(key, collection[key]); } MediaTypeHeaderValue mediaContentType = MediaTypeHeaderValue.Parse(Request.ContentType); @@ -80,10 +80,10 @@ public JsonResult Index(IFormCollection collection) Hashtable output = new Hashtable { - {"Files" , fileList}, - {"Items" , itemsHash}, + {"Files", fileList}, + {"Items", itemsHash}, {"Boundary", HeaderUtilities.RemoveQuotes(mediaContentType.Boundary).Value}, - {"Headers" , headers} + {"Headers", headers} }; return Json(output); } diff --git a/test/tools/WebListener/Controllers/ResponseController.cs b/test/tools/WebListener/Controllers/ResponseController.cs index 70e4659b3a4..cb014029b36 100644 --- a/test/tools/WebListener/Controllers/ResponseController.cs +++ b/test/tools/WebListener/Controllers/ResponseController.cs @@ -41,7 +41,7 @@ public string Index() } StringValues responsePhrase; - if ( Request.Query.TryGetValue("responsephrase", out responsePhrase)) + if (Request.Query.TryGetValue("responsephrase", out responsePhrase)) { Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = responsePhrase.FirstOrDefault(); } @@ -69,7 +69,7 @@ public string Index() foreach (string entry in GetSingleOrArray<string>(property.Value)) { - Response.Headers.Append(property.Name,entry); + Response.Headers.Append(property.Name, entry); } } } @@ -84,7 +84,7 @@ public string Index() // Content-Type must be applied right before it is sent to the client or MVC will overwrite. Response.OnStarting(state => { - var httpContext = (HttpContext) state; + var httpContext = (HttpContext)state; httpContext.Response.ContentType = contentType; return Task.FromResult(0); }, HttpContext); @@ -99,7 +99,7 @@ public IActionResult Error() return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } - private List<T> GetSingleOrArray<T>(JToken token) + private static List<T> GetSingleOrArray<T>(JToken token) { if (token.HasValues) { diff --git a/test/tools/WebListener/Controllers/ResponseHeadersController.cs b/test/tools/WebListener/Controllers/ResponseHeadersController.cs index ab6c7547571..d5bffaefb70 100644 --- a/test/tools/WebListener/Controllers/ResponseHeadersController.cs +++ b/test/tools/WebListener/Controllers/ResponseHeadersController.cs @@ -31,7 +31,7 @@ public string Index() string contentType = Request.Query[key]; Response.OnStarting(state => { - var httpContext = (HttpContext) state; + var httpContext = (HttpContext)state; httpContext.Response.ContentType = contentType; return Task.FromResult(0); }, HttpContext); diff --git a/test/tools/WebListener/Controllers/ResumeController.cs b/test/tools/WebListener/Controllers/ResumeController.cs index ebcfad40d78..55341894e12 100644 --- a/test/tools/WebListener/Controllers/ResumeController.cs +++ b/test/tools/WebListener/Controllers/ResumeController.cs @@ -19,7 +19,7 @@ namespace mvc.Controllers { public class ResumeController : Controller { - private static byte[] FileBytes = new byte[] { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 }; + private static readonly byte[] FileBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; public async void Index() { @@ -30,12 +30,12 @@ public async void Index() if (TryGetRangeHeader(out rangeHeader)) { var range = GetRange(rangeHeader); - if(range.From != null) + if (range.From != null) { from = (int)range.From; } - if(range.To != null) + if (range.To != null) { to = (int)range.To; } @@ -49,7 +49,7 @@ public async void Index() return; } - if(to >= FileBytes.Length || from >= FileBytes.Length) + if (to >= FileBytes.Length || from >= FileBytes.Length) { Response.StatusCode = StatusCodes.Status416RequestedRangeNotSatisfiable; Response.Headers[HeaderNames.ContentRange] = $"bytes */{FileBytes.Length}"; @@ -91,7 +91,7 @@ public IActionResult Error() return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } - private RangeItemHeaderValue GetRange(string rangeHeader) + private static RangeItemHeaderValue GetRange(string rangeHeader) { return RangeHeaderValue.Parse(rangeHeader).Ranges.FirstOrDefault(); } @@ -113,7 +113,7 @@ private void SetResumeResponseHeaders() private bool TryGetRangeHeader(out string rangeHeader) { var rangeHeaderSv = new StringValues(); - if(Request.Headers.TryGetValue("Range", out rangeHeaderSv)) + if (Request.Headers.TryGetValue("Range", out rangeHeaderSv)) { rangeHeader = rangeHeaderSv.FirstOrDefault(); return true; diff --git a/test/tools/WebListener/DeflateFilter.cs b/test/tools/WebListener/DeflateFilter.cs index 7af94b23920..60d39c39d18 100644 --- a/test/tools/WebListener/DeflateFilter.cs +++ b/test/tools/WebListener/DeflateFilter.cs @@ -11,7 +11,7 @@ namespace mvc.Controllers { internal sealed class DeflateFilter : ResultFilterAttribute { - public override async Task OnResultExecutionAsync( ResultExecutingContext context, ResultExecutionDelegate next) + public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { var httpContext = context.HttpContext; using (var memoryStream = new MemoryStream()) diff --git a/test/tools/WebListener/GzipFilter.cs b/test/tools/WebListener/GzipFilter.cs index e015e0f682d..9eab3627b5c 100644 --- a/test/tools/WebListener/GzipFilter.cs +++ b/test/tools/WebListener/GzipFilter.cs @@ -11,7 +11,7 @@ namespace mvc.Controllers { internal sealed class GzipFilter : ResultFilterAttribute { - public override async Task OnResultExecutionAsync( ResultExecutingContext context, ResultExecutionDelegate next) + public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { var httpContext = context.HttpContext; using (var memoryStream = new MemoryStream()) diff --git a/test/tools/WebListener/Program.cs b/test/tools/WebListener/Program.cs index c13fb54e5de..a4b575121d2 100644 --- a/test/tools/WebListener/Program.cs +++ b/test/tools/WebListener/Program.cs @@ -17,11 +17,11 @@ namespace mvc { - public class Program + public static class Program { public static void Main(string[] args) { - if (args.Count() != 7) + if (args.Length != 7) { System.Console.WriteLine("Required: <CertificatePath> <CertificatePassword> <HTTPPortNumber> <HTTPSPortNumberTls12> <HTTPSPortNumberTls11> <HTTPSPortNumberTls> <HTTPSPortNumberTls12>"); Environment.Exit(1); @@ -42,7 +42,7 @@ public static IWebHost BuildWebHost(string[] args) => HttpsConnectionAdapterOptions httpsOption = new HttpsConnectionAdapterOptions(); httpsOption.SslProtocols = SslProtocols.Tls12; httpsOption.ClientCertificateMode = ClientCertificateMode.AllowCertificate; - httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => {return true;}; + httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => { return true; }; httpsOption.CheckCertificateRevocation = false; httpsOption.ServerCertificate = certificate; listenOptions.UseHttps(httpsOption); @@ -53,7 +53,7 @@ public static IWebHost BuildWebHost(string[] args) => HttpsConnectionAdapterOptions httpsOption = new HttpsConnectionAdapterOptions(); httpsOption.SslProtocols = SslProtocols.Tls11; httpsOption.ClientCertificateMode = ClientCertificateMode.AllowCertificate; - httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => {return true;}; + httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => { return true; }; httpsOption.CheckCertificateRevocation = false; httpsOption.ServerCertificate = certificate; listenOptions.UseHttps(httpsOption); @@ -64,7 +64,7 @@ public static IWebHost BuildWebHost(string[] args) => HttpsConnectionAdapterOptions httpsOption = new HttpsConnectionAdapterOptions(); httpsOption.SslProtocols = SslProtocols.Tls; httpsOption.ClientCertificateMode = ClientCertificateMode.AllowCertificate; - httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => {return true;}; + httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => { return true; }; httpsOption.CheckCertificateRevocation = false; httpsOption.ServerCertificate = certificate; listenOptions.UseHttps(httpsOption); @@ -75,7 +75,7 @@ public static IWebHost BuildWebHost(string[] args) => HttpsConnectionAdapterOptions httpsOption = new HttpsConnectionAdapterOptions(); httpsOption.SslProtocols = SslProtocols.Tls13; httpsOption.ClientCertificateMode = ClientCertificateMode.AllowCertificate; - httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => {return true;}; + httpsOption.ClientCertificateValidation = (inCertificate, inChain, inPolicy) => { return true; }; httpsOption.CheckCertificateRevocation = false; httpsOption.ServerCertificate = certificate; listenOptions.UseHttps(httpsOption); diff --git a/test/tools/WebListener/WebListener.csproj b/test/tools/WebListener/WebListener.csproj index 45ce62fa73f..bbc07be5259 100644 --- a/test/tools/WebListener/WebListener.csproj +++ b/test/tools/WebListener/WebListener.csproj @@ -7,8 +7,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0-rc.1.20451.17" /> - <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0-rc.1.20451.14" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" /> + <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" /> </ItemGroup> <ItemGroup> diff --git a/test/xUnit/Asserts/PriorityAttribute.cs b/test/xUnit/Asserts/PriorityAttribute.cs index 9214bdd3dd5..7441dcf1143 100644 --- a/test/xUnit/Asserts/PriorityAttribute.cs +++ b/test/xUnit/Asserts/PriorityAttribute.cs @@ -3,13 +3,16 @@ using System; -[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] -public class TestPriorityAttribute : Attribute +namespace PSTests.Internal { - public TestPriorityAttribute(int priority) + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class PriorityAttribute : Attribute { - Priority = priority; - } + public PriorityAttribute(int priority) + { + Priority = priority; + } - public int Priority { get; } + public int Priority { get; } + } } diff --git a/test/xUnit/Asserts/PriorityOrderer.cs b/test/xUnit/Asserts/PriorityOrderer.cs index f8801f314c7..d1e133f92d3 100644 --- a/test/xUnit/Asserts/PriorityOrderer.cs +++ b/test/xUnit/Asserts/PriorityOrderer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using PSTests.Internal; using Xunit.Abstractions; using Xunit.Sdk; @@ -19,7 +20,7 @@ public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> t { int priority = 0; - foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes(typeof(TestPriorityAttribute).AssemblyQualifiedName)) + foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes(typeof(PriorityAttribute).AssemblyQualifiedName)) { priority = attr.GetNamedArgument<int>("Priority"); } diff --git a/test/xUnit/csharp/test_AstDefaultVisit.cs b/test/xUnit/csharp/test_AstDefaultVisit.cs index 925f2c6be53..283c1f73071 100644 --- a/test/xUnit/csharp/test_AstDefaultVisit.cs +++ b/test/xUnit/csharp/test_AstDefaultVisit.cs @@ -44,7 +44,7 @@ public static class AstDefaultVisitTests public static void TestCustomAstVisitor() { var ast = Parser.ParseInput("a | b", out _, out _); - var expected = typeof(NamedBlockAst).Name; + var expected = nameof(NamedBlockAst); var myVisitor1 = new MyICustomAstVisitor2(); var result1 = ast.EndBlock.Accept(myVisitor1); diff --git a/test/xUnit/csharp/test_CommandLineParser.cs b/test/xUnit/csharp/test_CommandLineParser.cs index 6644b5daef8..cf2a1281219 100644 --- a/test/xUnit/csharp/test_CommandLineParser.cs +++ b/test/xUnit/csharp/test_CommandLineParser.cs @@ -19,7 +19,7 @@ public static void TestDefaults() { var cpp = new CommandLineParameterParser(); - cpp.Parse(new string[0]); + cpp.Parse(System.Array.Empty<string>()); Assert.False(cpp.AbortStartup); Assert.Empty(cpp.Args); @@ -48,7 +48,15 @@ public static void TestDefaults() Assert.False(cpp.SkipProfiles); Assert.False(cpp.SocketServerMode); Assert.False(cpp.SSHServerMode); - Assert.True(cpp.StaMode); + if (Platform.IsWindows) + { + Assert.True(cpp.StaMode); + } + else + { + Assert.False(cpp.StaMode); + } + Assert.False(cpp.ThrowOnReadAndPrompt); Assert.False(cpp.WasInitialCommandEncoded); Assert.Null(cpp.WorkingDirectory); @@ -60,9 +68,9 @@ public static void Test_Throws_On_Reuse() { var cpp = new CommandLineParameterParser(); - cpp.Parse(new string[0]); + cpp.Parse(System.Array.Empty<string>()); - Assert.Throws<System.InvalidOperationException>(() => cpp.Parse(new string[0])); + Assert.Throws<System.InvalidOperationException>(() => cpp.Parse(System.Array.Empty<string>())); } [Theory] @@ -95,18 +103,27 @@ public static void TestDefaultParameterIsFileName_Not_Exist(params string[] comm [Fact] public static void TestDefaultParameterIsFileName_Exist() { - var fileName = System.IO.Path.GetTempFileName(); + var tempFile = System.IO.Path.GetTempFileName(); + var tempPs1 = tempFile + ".ps1"; + File.Move(tempFile, tempPs1); var cpp = new CommandLineParameterParser(); - cpp.Parse(new string[] { fileName }); + cpp.Parse(new string[] { tempPs1 }); - Assert.False(cpp.AbortStartup); - Assert.False(cpp.NoExit); - Assert.False(cpp.ShowShortHelp); - Assert.False(cpp.ShowBanner); - Assert.Equal(CommandLineParameterParser.NormalizeFilePath(fileName), cpp.File); - Assert.Null(cpp.ErrorMessage); + try + { + Assert.False(cpp.AbortStartup); + Assert.False(cpp.NoExit); + Assert.False(cpp.ShowShortHelp); + Assert.False(cpp.ShowBanner); + Assert.Equal(CommandLineParameterParser.NormalizeFilePath(tempPs1), cpp.File); + Assert.Null(cpp.ErrorMessage); + } + finally + { + File.Delete(tempPs1); + } } [Theory] @@ -143,6 +160,47 @@ public static void TestParameterIs_Wrong_Value(params string[] commandLine) Assert.Contains("-noprofile", cpp.ErrorMessage); } + [Theory] + [InlineData("-Version")] + [InlineData("--Version")] + [InlineData("/Version")] + public static void TestParameter_Dash_Or_Slash(params string[] commandLine) + { + var cpp = new CommandLineParameterParser(); + + cpp.Parse(commandLine); + + Assert.False(cpp.AbortStartup); + Assert.False(cpp.NoExit); + Assert.True(cpp.NonInteractive); + Assert.False(cpp.ShowBanner); + Assert.False(cpp.ShowShortHelp); + Assert.False(cpp.NoPrompt); + Assert.True(cpp.ShowVersion); + Assert.True(cpp.SkipProfiles); + Assert.Null(cpp.ErrorMessage); + } + + [Theory] + [InlineData("/-Version")] + [InlineData("-/Version")] + public static void TestParameter_Wrong_Dash_And_Slash(params string[] commandLine) + { + var cpp = new CommandLineParameterParser(); + + cpp.Parse(commandLine); + + Assert.True(cpp.AbortStartup); + Assert.False(cpp.NoExit); + Assert.False(cpp.NonInteractive); + Assert.False(cpp.ShowBanner); + Assert.True(cpp.ShowShortHelp); + Assert.False(cpp.NoPrompt); + Assert.False(cpp.ShowVersion); + Assert.False(cpp.SkipProfiles); + Assert.Contains(commandLine[0], cpp.ErrorMessage); + } + [Theory] [InlineData("-Version")] [InlineData("-V")] @@ -969,13 +1027,14 @@ public static void TestParameter_SettingsFile_Not_Exists(params string[] command public class TestDataSettingsFile : IEnumerable<object[]> { - private string _fileName = Path.GetTempFileName(); + private readonly string _fileName = Path.GetTempFileName(); public IEnumerator<object[]> GetEnumerator() { yield return new object[] { "-settingsfile", _fileName }; yield return new object[] { "-settings", _fileName }; } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } @@ -1162,7 +1221,16 @@ public static void TestParameter_WorkingDirectory_RemoveTrailingCharacter(params public class TestDataLastFile : IEnumerable<object[]> { - private string _fileName = Path.GetTempFileName(); + private static string _fileName + { + get + { + var tempFile = Path.GetTempFileName(); + var tempPs1 = tempFile + ".ps1"; + File.Move(tempFile, tempPs1); + return tempPs1; + } + } public IEnumerator<object[]> GetEnumerator() { @@ -1180,13 +1248,28 @@ public static void TestParameter_LastParameterIsFileName_Exist(params string[] c cpp.Parse(commandLine); - Assert.False(cpp.AbortStartup); - Assert.False(cpp.NoExit); - Assert.False(cpp.ShowShortHelp); - Assert.False(cpp.ShowBanner); - Assert.True(cpp.StaMode); - Assert.Equal(CommandLineParameterParser.NormalizeFilePath(commandLine[commandLine.Length - 1]), cpp.File); - Assert.Null(cpp.ErrorMessage); + try + { + Assert.False(cpp.AbortStartup); + Assert.False(cpp.NoExit); + Assert.False(cpp.ShowShortHelp); + Assert.False(cpp.ShowBanner); + if (Platform.IsWindows) + { + Assert.True(cpp.StaMode); + } + else + { + Assert.False(cpp.StaMode); + } + + Assert.Equal(CommandLineParameterParser.NormalizeFilePath(commandLine[commandLine.Length - 1]), cpp.File); + Assert.Null(cpp.ErrorMessage); + } + finally + { + File.Delete(cpp.File); + } } } } diff --git a/test/xUnit/csharp/test_FileSystemProvider.cs b/test/xUnit/csharp/test_FileSystemProvider.cs index 268dbddef42..85ab0b2eedd 100644 --- a/test/xUnit/csharp/test_FileSystemProvider.cs +++ b/test/xUnit/csharp/test_FileSystemProvider.cs @@ -24,8 +24,8 @@ namespace PSTests.Parallel { public class FileSystemProviderTests : IDisposable { - private string testPath; - private string testContent; + private readonly string testPath; + private readonly string testContent; public FileSystemProviderTests() { @@ -39,12 +39,21 @@ public FileSystemProviderTests() File.AppendAllText(testPath, testContent); } - void IDisposable.Dispose() + public void Dispose() { - File.Delete(testPath); + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + File.Delete(testPath); + } } - private ExecutionContext GetExecutionContext() + private static ExecutionContext GetExecutionContext() { CultureInfo currentCulture = CultureInfo.CurrentCulture; PSHost hostInterface = new DefaultHost(currentCulture, currentCulture); @@ -54,7 +63,7 @@ private ExecutionContext GetExecutionContext() return executionContext; } - private ProviderInfo GetProvider() + private static ProviderInfo GetProvider() { ExecutionContext executionContext = GetExecutionContext(); SessionStateInternal sessionState = new SessionStateInternal(executionContext); @@ -106,7 +115,7 @@ public void TestMode() { directoryObject = new DirectoryInfo(System.Environment.CurrentDirectory); fileObject = new FileInfo(System.Reflection.Assembly.GetEntryAssembly().Location); - executableObject = new FileInfo(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); + executableObject = new FileInfo(Environment.ProcessPath); } Assert.Equal("d----", FileSystemProvider.Mode(PSObject.AsPSObject(directoryObject)).Replace("r", "-")); diff --git a/test/xUnit/csharp/test_NamedPipe.cs b/test/xUnit/csharp/test_NamedPipe.cs index 1ee50036fc0..1174799fd95 100644 --- a/test/xUnit/csharp/test_NamedPipe.cs +++ b/test/xUnit/csharp/test_NamedPipe.cs @@ -31,7 +31,7 @@ public void TestCustomPipeNameCreation() [Fact] public void TestCustomPipeNameCreationTooLongOnNonWindows() { - var longPipeName = "DoggoipsumwaggywagssmolborkingdoggowithalongsnootforpatsdoingmeafrightenporgoYapperporgolongwatershoobcloudsbigolpupperlengthboy"; + const string longPipeName = "DoggoipsumwaggywagssmolborkingdoggowithalongsnootforpatsdoingmeafrightenporgoYapperporgolongwatershoobcloudsbigolpupperlengthboy"; if (!Platform.IsWindows) { diff --git a/test/xUnit/csharp/test_NativeInterop.cs b/test/xUnit/csharp/test_NativeInterop.cs new file mode 100644 index 00000000000..685e8a23ce4 --- /dev/null +++ b/test/xUnit/csharp/test_NativeInterop.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Management.Automation; +using Xunit; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.Text; + +namespace PSTests.Sequential +{ + public static class NativeInterop + { + [Fact] + public static void TestLoadNativeInMemoryAssembly() + { + string tempDir = Path.Combine(Path.GetTempPath(), "TestLoadNativeInMemoryAssembly"); + string testDll = Path.Combine(tempDir, "test.dll"); + + if (!File.Exists(testDll)) + { + Directory.CreateDirectory(tempDir); + bool result = CreateTestDll(testDll); + Assert.True(result, "The call to 'CreateTestDll' should be successful and return true."); + Assert.True(File.Exists(testDll), "The test assembly should be created."); + } + + var asmName = AssemblyName.GetAssemblyName(testDll); + string asmFullName = SearchAssembly(asmName.Name); + Assert.Null(asmFullName); + + unsafe + { + int ret = LoadAssemblyTest(testDll); + Assert.Equal(0, ret); + } + + asmFullName = SearchAssembly(asmName.Name); + Assert.Equal(asmName.FullName, asmFullName); + } + + private static unsafe int LoadAssemblyTest(string assemblyPath) + { + // The 'LoadAssemblyFromNativeMemory' method is annotated with 'UnmanagedCallersOnly' attribute, + // so we have to use the 'unmanaged' function pointer to invoke it. + delegate* unmanaged<IntPtr, int, int> funcPtr = &PowerShellUnsafeAssemblyLoad.LoadAssemblyFromNativeMemory; + + int length = 0; + IntPtr nativeMem = IntPtr.Zero; + + try + { + using (var fileStream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read)) + { + length = (int)fileStream.Length; + nativeMem = Marshal.AllocHGlobal(length); + + using var unmanagedStream = new UnmanagedMemoryStream((byte*)nativeMem, length, length, FileAccess.Write); + fileStream.CopyTo(unmanagedStream); + } + + // Call the function pointer. + return funcPtr(nativeMem, length); + } + finally + { + // Free the native memory + Marshal.FreeHGlobal(nativeMem); + } + } + + private static string SearchAssembly(string assemblyName) + { + Assembly asm = AssemblyLoadContext.Default.Assemblies.FirstOrDefault( + assembly => assembly.FullName.StartsWith(assemblyName, StringComparison.OrdinalIgnoreCase)); + + return asm?.FullName; + } + + private static bool CreateTestDll(string dllPath) + { + var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest); + var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + + List<SyntaxTree> syntaxTrees = new(); + SourceText sourceText = SourceText.From("public class Utt { }"); + syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, parseOptions)); + + var refs = new List<PortableExecutableReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + Compilation compilation = CSharpCompilation.Create( + Path.GetRandomFileName(), + syntaxTrees: syntaxTrees, + references: refs, + options: compilationOptions); + + using var fs = new FileStream(dllPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); + EmitResult emitResult = compilation.Emit(peStream: fs, options: null); + return emitResult.Success; + } + } +} diff --git a/test/xUnit/csharp/test_PSConfiguration.cs b/test/xUnit/csharp/test_PSConfiguration.cs index 45e057bea75..54e69da68f0 100644 --- a/test/xUnit/csharp/test_PSConfiguration.cs +++ b/test/xUnit/csharp/test_PSConfiguration.cs @@ -10,6 +10,7 @@ using System.Threading; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PSTests.Internal; using Xunit; namespace PSTests.Sequential @@ -96,18 +97,27 @@ public PowerShellPolicyFixture() public void Dispose() { - CleanupConfigFiles(); - if (systemWideConfigBackupFile != null) - { - File.Move(systemWideConfigBackupFile, systemWideConfigFile); - } + Dispose(true); + GC.SuppressFinalize(this); + } - if (currentUserConfigBackupFile != null) + protected virtual void Dispose(bool disposing) + { + if (disposing) { - File.Move(currentUserConfigBackupFile, currentUserConfigFile); - } + CleanupConfigFiles(); + if (systemWideConfigBackupFile != null) + { + File.Move(systemWideConfigBackupFile, systemWideConfigFile); + } - InternalTestHooks.BypassGroupPolicyCaching = originalTestHookValue; + if (currentUserConfigBackupFile != null) + { + File.Move(currentUserConfigBackupFile, currentUserConfigFile); + } + + InternalTestHooks.BypassGroupPolicyCaching = originalTestHookValue; + } } internal PowerShellPolicies SystemWidePolicies @@ -356,11 +366,27 @@ public void SetupConfigFile4() CreateEmptyFile(currentUserConfigFile); } - private void CreateEmptyFile(string fileName) + private static void CreateEmptyFile(string fileName) { File.Create(fileName).Dispose(); } + public void SetupConfigFile5() + { + CleanupConfigFiles(); + + // System wide config file is broken + CreateBrokenConfigFile(systemWideConfigFile); + + // Current user config file is broken + CreateBrokenConfigFile(currentUserConfigFile); + } + + private static void CreateBrokenConfigFile(string fileName) + { + File.WriteAllText(fileName, "[abbra"); + } + internal void ForceReadingFromFile() { // Reset the cached roots. @@ -375,14 +401,14 @@ internal void ForceReadingFromFile() public class PowerShellPolicyTests : IClassFixture<PowerShellPolicyFixture> { - private PowerShellPolicyFixture fixture; + private readonly PowerShellPolicyFixture fixture; public PowerShellPolicyTests(PowerShellPolicyFixture fixture) { this.fixture = fixture; } - [Fact, TestPriority(1)] + [Fact, Priority(1)] public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotEmpty() { fixture.SetupConfigFile1(); @@ -398,7 +424,7 @@ public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotEmpty() fixture.CompareTwoPolicies(userPolicies, fixture.CurrentUserPolicies); } - [Fact, TestPriority(2)] + [Fact, Priority(2)] public void PowerShellConfig_GetPowerShellPolicies_EmptyUserConfig() { fixture.SetupConfigFile2(); @@ -413,7 +439,7 @@ public void PowerShellConfig_GetPowerShellPolicies_EmptyUserConfig() fixture.CompareTwoPolicies(sysPolicies, fixture.SystemWidePolicies); } - [Fact, TestPriority(3)] + [Fact, Priority(3)] public void PowerShellConfig_GetPowerShellPolicies_EmptySystemConfig() { fixture.SetupConfigFile3(); @@ -428,7 +454,7 @@ public void PowerShellConfig_GetPowerShellPolicies_EmptySystemConfig() fixture.CompareTwoPolicies(userPolicies, fixture.CurrentUserPolicies); } - [Fact, TestPriority(4)] + [Fact, Priority(4)] public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesEmpty() { fixture.SetupConfigFile4(); @@ -441,7 +467,7 @@ public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesEmpty() Assert.Null(userPolicies); } - [Fact, TestPriority(5)] + [Fact, Priority(5)] public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotExist() { fixture.CleanupConfigFiles(); @@ -454,7 +480,7 @@ public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotExist() Assert.Null(userPolicies); } - [Fact, TestPriority(6)] + [Fact, Priority(6)] public void Utils_GetPolicySetting_BothConfigFilesNotEmpty() { fixture.SetupConfigFile1(); @@ -553,7 +579,7 @@ public void Utils_GetPolicySetting_BothConfigFilesNotEmpty() fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration); } - [Fact, TestPriority(7)] + [Fact, Priority(7)] public void Utils_GetPolicySetting_EmptyUserConfig() { fixture.SetupConfigFile2(); @@ -652,7 +678,7 @@ public void Utils_GetPolicySetting_EmptyUserConfig() fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration); } - [Fact, TestPriority(8)] + [Fact, Priority(8)] public void Utils_GetPolicySetting_EmptySystemConfig() { fixture.SetupConfigFile3(); @@ -752,7 +778,7 @@ public void Utils_GetPolicySetting_EmptySystemConfig() fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null); } - [Fact, TestPriority(9)] + [Fact, Priority(9)] public void Utils_GetPolicySetting_BothConfigFilesEmpty() { fixture.SetupConfigFile4(); @@ -852,7 +878,7 @@ public void Utils_GetPolicySetting_BothConfigFilesEmpty() fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null); } - [Fact, TestPriority(10)] + [Fact, Priority(10)] public void Utils_GetPolicySetting_BothConfigFilesNotExist() { fixture.CleanupConfigFiles(); @@ -951,5 +977,15 @@ public void Utils_GetPolicySetting_BothConfigFilesNotExist() consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig); fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null); } + + [Fact, Priority(11)] + public void PowerShellConfig_GetPowerShellPolicies_BrokenSystemConfig() + { + fixture.SetupConfigFile5(); + fixture.ForceReadingFromFile(); + + Assert.Throws<System.Management.Automation.PSInvalidOperationException>(() => PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.AllUsers)); + Assert.Throws<System.Management.Automation.PSInvalidOperationException>(() => PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser)); + } } } diff --git a/test/xUnit/csharp/test_Prediction.cs b/test/xUnit/csharp/test_Prediction.cs index 4d67c850f6d..a2c38db1359 100644 --- a/test/xUnit/csharp/test_Prediction.cs +++ b/test/xUnit/csharp/test_Prediction.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Management.Automation.Language; using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.Prediction; using System.Threading; using Xunit; @@ -18,11 +19,13 @@ public class MyPredictor : ICommandPredictor public List<string> History { get; } + public List<string> Results { get; } + public List<string> AcceptedSuggestions { get; } - public static readonly MyPredictor SlowPredictor; + public List<string> DisplayedSuggestions { get; } - public static readonly MyPredictor FastPredictor; + public static readonly MyPredictor SlowPredictor, FastPredictor; static MyPredictor() { @@ -47,30 +50,30 @@ private MyPredictor(Guid id, string name, string description, bool delay) _delay = delay; History = new List<string>(); + Results = new List<string>(); AcceptedSuggestions = new List<string>(); + DisplayedSuggestions = new List<string>(); } + public void Clear() + { + History.Clear(); + Results.Clear(); + AcceptedSuggestions.Clear(); + DisplayedSuggestions.Clear(); + } + + #region "Interface implementation" + public Guid Id => _id; public string Name => _name; public string Description => _description; - bool ICommandPredictor.SupportEarlyProcessing => true; - - bool ICommandPredictor.AcceptFeedback => true; - - public void StartEarlyProcessing(IReadOnlyList<string> history) - { - History.AddRange(history); - } - - public void OnSuggestionAccepted(string acceptedSuggestion) - { - AcceptedSuggestions.Add(acceptedSuggestion); - } + bool ICommandPredictor.CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback) => true; - public List<PredictiveSuggestion> GetSuggestion(PredictionContext context, CancellationToken cancellationToken) + public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken) { if (_delay) { @@ -81,24 +84,57 @@ public List<PredictiveSuggestion> GetSuggestion(PredictionContext context, Cance // You can get the user input from the AST. var userInput = context.InputAst.Extent.Text; - return new List<PredictiveSuggestion> { - new PredictiveSuggestion($"{userInput} TEST-1 from {Name}"), - new PredictiveSuggestion($"{userInput} TeSt-2 from {Name}"), + var entries = new List<PredictiveSuggestion> + { + new PredictiveSuggestion($"'{userInput}' from '{client.Name}' - TEST-1 from {Name}"), + new PredictiveSuggestion($"'{userInput}' from '{client.Name}' - TeSt-2 from {Name}"), }; + + return new SuggestionPackage(56, entries); + } + + public void OnSuggestionDisplayed(PredictionClient client, uint session, int countOrIndex) + { + DisplayedSuggestions.Add($"{client.Name}-{session}-{countOrIndex}"); + } + + public void OnSuggestionAccepted(PredictionClient client, uint session, string acceptedSuggestion) + { + AcceptedSuggestions.Add($"{client.Name}-{session}-{acceptedSuggestion}"); + } + + public void OnCommandLineAccepted(PredictionClient client, IReadOnlyList<string> history) + { + foreach (string item in history) + { + History.Add($"{client.Name}-{item}"); + } + } + + public void OnCommandLineExecuted(PredictionClient client, string commandLine, bool success) + { + Results.Add($"{client.Name}-{commandLine}-{success}"); } + + #endregion } public static class CommandPredictionTests { + private const string Client = "PredictionTest"; + private const uint Session = 56; + private static readonly PredictionClient predClient = new(Client, PredictionClientKind.Terminal); + [Fact] public static void PredictInput() { + const string Input = "Hello world"; MyPredictor slow = MyPredictor.SlowPredictor; MyPredictor fast = MyPredictor.FastPredictor; - Ast ast = Parser.ParseInput("Hello world", out Token[] tokens, out _); + Ast ast = Parser.ParseInput(Input, out Token[] tokens, out _); // Returns null when no predictor implementation registered - List<PredictionResult> results = CommandPrediction.PredictInput(ast, tokens).Result; + List<PredictionResult> results = CommandPrediction.PredictInputAsync(predClient, ast, tokens).Result; Assert.Null(results); try @@ -111,32 +147,35 @@ public static void PredictInput() // cannot finish before the specified timeout. // The specified timeout is exaggerated to make the test reliable. // xUnit must spin up a lot tasks, which makes the test unreliable when the time difference between 'delay' and 'timeout' is small. - results = CommandPrediction.PredictInput(ast, tokens, millisecondsTimeout: 1000).Result; + results = CommandPrediction.PredictInputAsync(predClient, ast, tokens, millisecondsTimeout: 1000).Result; Assert.Single(results); PredictionResult res = results[0]; Assert.Equal(fast.Id, res.Id); + Assert.Equal(Session, res.Session); Assert.Equal(2, res.Suggestions.Count); - Assert.Equal($"Hello world TEST-1 from {fast.Name}", res.Suggestions[0].SuggestionText); - Assert.Equal($"Hello world TeSt-2 from {fast.Name}", res.Suggestions[1].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TEST-1 from {fast.Name}", res.Suggestions[0].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TeSt-2 from {fast.Name}", res.Suggestions[1].SuggestionText); // Expect the results from both 'slow' and 'fast' predictors // Same here -- the specified timeout is exaggerated to make the test reliable. // xUnit must spin up a lot tasks, which makes the test unreliable when the time difference between 'delay' and 'timeout' is small. - results = CommandPrediction.PredictInput(ast, tokens, millisecondsTimeout: 4000).Result; + results = CommandPrediction.PredictInputAsync(predClient, ast, tokens, millisecondsTimeout: 4000).Result; Assert.Equal(2, results.Count); PredictionResult res1 = results[0]; Assert.Equal(slow.Id, res1.Id); + Assert.Equal(Session, res1.Session); Assert.Equal(2, res1.Suggestions.Count); - Assert.Equal($"Hello world TEST-1 from {slow.Name}", res1.Suggestions[0].SuggestionText); - Assert.Equal($"Hello world TeSt-2 from {slow.Name}", res1.Suggestions[1].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TEST-1 from {slow.Name}", res1.Suggestions[0].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TeSt-2 from {slow.Name}", res1.Suggestions[1].SuggestionText); PredictionResult res2 = results[1]; Assert.Equal(fast.Id, res2.Id); + Assert.Equal(Session, res2.Session); Assert.Equal(2, res2.Suggestions.Count); - Assert.Equal($"Hello world TEST-1 from {fast.Name}", res2.Suggestions[0].SuggestionText); - Assert.Equal($"Hello world TeSt-2 from {fast.Name}", res2.Suggestions[1].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TEST-1 from {fast.Name}", res2.Suggestions[0].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TeSt-2 from {fast.Name}", res2.Suggestions[1].SuggestionText); } finally { @@ -151,6 +190,9 @@ public static void Feedback() MyPredictor slow = MyPredictor.SlowPredictor; MyPredictor fast = MyPredictor.FastPredictor; + slow.Clear(); + fast.Clear(); + try { // Register 2 predictor implementations @@ -160,26 +202,43 @@ public static void Feedback() var history = new[] { "hello", "world" }; var ids = new HashSet<Guid> { slow.Id, fast.Id }; - CommandPrediction.OnCommandLineAccepted(history); - CommandPrediction.OnSuggestionAccepted(slow.Id, "Yeah"); - - // The calls to 'StartEarlyProcessing' and 'OnSuggestionAccepted' are queued in thread pool, - // so we wait a bit to make sure the calls are done. - while (slow.History.Count == 0 || slow.AcceptedSuggestions.Count == 0) + CommandPrediction.OnCommandLineAccepted(predClient, history); + CommandPrediction.OnCommandLineExecuted(predClient, "last_input", true); + CommandPrediction.OnSuggestionDisplayed(predClient, slow.Id, Session, 2); + CommandPrediction.OnSuggestionDisplayed(predClient, fast.Id, Session, -1); + CommandPrediction.OnSuggestionAccepted(predClient, slow.Id, Session, "Yeah"); + + // The feedback calls are queued in thread pool, so let's wait a bit to make sure the calls are done. + while (slow.History.Count == 0 || fast.History.Count == 0 || + slow.Results.Count == 0 || fast.Results.Count == 0 || + slow.DisplayedSuggestions.Count == 0 || fast.DisplayedSuggestions.Count == 0 || + slow.AcceptedSuggestions.Count == 0) { - Thread.Sleep(10); + Thread.Sleep(100); } Assert.Equal(2, slow.History.Count); - Assert.Equal(history[0], slow.History[0]); - Assert.Equal(history[1], slow.History[1]); + Assert.Equal($"{Client}-{history[0]}", slow.History[0]); + Assert.Equal($"{Client}-{history[1]}", slow.History[1]); Assert.Equal(2, fast.History.Count); - Assert.Equal(history[0], fast.History[0]); - Assert.Equal(history[1], fast.History[1]); + Assert.Equal($"{Client}-{history[0]}", fast.History[0]); + Assert.Equal($"{Client}-{history[1]}", fast.History[1]); + + Assert.Single(slow.Results); + Assert.Equal($"{Client}-last_input-True", slow.Results[0]); + + Assert.Single(fast.Results); + Assert.Equal($"{Client}-last_input-True", fast.Results[0]); + + Assert.Single(slow.DisplayedSuggestions); + Assert.Equal($"{Client}-{Session}-2", slow.DisplayedSuggestions[0]); + + Assert.Single(fast.DisplayedSuggestions); + Assert.Equal($"{Client}-{Session}--1", fast.DisplayedSuggestions[0]); Assert.Single(slow.AcceptedSuggestions); - Assert.Equal("Yeah", slow.AcceptedSuggestions[0]); + Assert.Equal($"{Client}-{Session}-Yeah", slow.AcceptedSuggestions[0]); Assert.Empty(fast.AcceptedSuggestions); } diff --git a/test/xUnit/csharp/test_Runspace.cs b/test/xUnit/csharp/test_Runspace.cs index 3a7a6278bf6..bd8afb5746f 100644 --- a/test/xUnit/csharp/test_Runspace.cs +++ b/test/xUnit/csharp/test_Runspace.cs @@ -13,8 +13,8 @@ namespace PSTests.Sequential // otherwise Invoke will not return any objects public class RunspaceTests { - private static int count = 1; - private static string script = string.Format($"get-command get-command"); + private static readonly int count = 1; + private static readonly string script = string.Format($"get-command get-command"); [Fact] public void TestRunspaceWithPipeline() diff --git a/test/xUnit/csharp/test_Subsystem.cs b/test/xUnit/csharp/test_Subsystem.cs index a45ebc116b5..d5bc3b9c728 100644 --- a/test/xUnit/csharp/test_Subsystem.cs +++ b/test/xUnit/csharp/test_Subsystem.cs @@ -4,6 +4,8 @@ using System; using System.Collections.ObjectModel; using System.Management.Automation.Subsystem; +using System.Management.Automation.Subsystem.DSC; +using System.Management.Automation.Subsystem.Prediction; using System.Threading; using Xunit; @@ -19,8 +21,7 @@ static SubsystemTests() predictor2 = MyPredictor.SlowPredictor; } - // This method needs to be updated when there are more than 1 subsystem defined. - private static void VerifySubsystemMetadata(SubsystemInfo ssInfo) + private static void VerifyCommandPredictorMetadata(SubsystemInfo ssInfo) { Assert.Equal(SubsystemKind.CommandPredictor, ssInfo.Kind); Assert.Equal(typeof(ICommandPredictor), ssInfo.SubsystemType); @@ -30,26 +31,51 @@ private static void VerifySubsystemMetadata(SubsystemInfo ssInfo) Assert.Empty(ssInfo.RequiredFunctions); } + private static void VerifyCrossPlatformDscMetadata(SubsystemInfo ssInfo) + { + Assert.Equal(SubsystemKind.CrossPlatformDsc, ssInfo.Kind); + Assert.Equal(typeof(ICrossPlatformDsc), ssInfo.SubsystemType); + Assert.True(ssInfo.AllowUnregistration); + Assert.False(ssInfo.AllowMultipleRegistration); + Assert.Empty(ssInfo.RequiredCmdlets); + Assert.Empty(ssInfo.RequiredFunctions); + } + [Fact] public static void GetSubsystemInfo() { - SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor)); + SubsystemInfo predictorInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor)); - VerifySubsystemMetadata(ssInfo); - Assert.False(ssInfo.IsRegistered); - Assert.Empty(ssInfo.Implementations); + VerifyCommandPredictorMetadata(predictorInfo); + Assert.False(predictorInfo.IsRegistered); + Assert.Empty(predictorInfo.Implementations); - SubsystemInfo ssInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor); - Assert.Same(ssInfo2, ssInfo); + SubsystemInfo predictorInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor); + Assert.Same(predictorInfo2, predictorInfo); - ReadOnlyCollection<SubsystemInfo> ssInfos = SubsystemManager.GetAllSubsystemInfo(); - Assert.Single(ssInfos); - Assert.Same(ssInfos[0], ssInfo); + SubsystemInfo crossPlatformDscInfo = SubsystemManager.GetSubsystemInfo(typeof(ICrossPlatformDsc)); - ICommandPredictor impl = SubsystemManager.GetSubsystem<ICommandPredictor>(); - Assert.Null(impl); - ReadOnlyCollection<ICommandPredictor> impls = SubsystemManager.GetSubsystems<ICommandPredictor>(); - Assert.Empty(impls); + VerifyCrossPlatformDscMetadata(crossPlatformDscInfo); + Assert.False(crossPlatformDscInfo.IsRegistered); + Assert.Empty(crossPlatformDscInfo.Implementations); + + SubsystemInfo crossPlatformDscInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CrossPlatformDsc); + Assert.Same(crossPlatformDscInfo2, crossPlatformDscInfo); + + ReadOnlyCollection<SubsystemInfo> ssInfos = SubsystemManager.GetAllSubsystemInfo(); + Assert.Equal(2, ssInfos.Count); + Assert.Same(ssInfos[0], predictorInfo); + Assert.Same(ssInfos[1], crossPlatformDscInfo); + + ICommandPredictor predictorImpl = SubsystemManager.GetSubsystem<ICommandPredictor>(); + Assert.Null(predictorImpl); + ReadOnlyCollection<ICommandPredictor> predictorImpls = SubsystemManager.GetSubsystems<ICommandPredictor>(); + Assert.Empty(predictorImpls); + + ICrossPlatformDsc crossPlatformDscImpl = SubsystemManager.GetSubsystem<ICrossPlatformDsc>(); + Assert.Null(crossPlatformDscImpl); + ReadOnlyCollection<ICrossPlatformDsc> crossPlatformDscImpls = SubsystemManager.GetSubsystems<ICrossPlatformDsc>(); + Assert.Empty(crossPlatformDscImpls); } [Fact] @@ -72,7 +98,8 @@ public static void RegisterSubsystem() // Now validate the SubsystemInfo of the 'ICommandPredictor' subsystem SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor)); - VerifySubsystemMetadata(ssInfo); + SubsystemInfo crossPlatformDscInfo = SubsystemManager.GetSubsystemInfo(typeof(ICrossPlatformDsc)); + VerifyCommandPredictorMetadata(ssInfo); Assert.True(ssInfo.IsRegistered); Assert.Single(ssInfo.Implementations); @@ -84,21 +111,19 @@ public static void RegisterSubsystem() Assert.Equal(SubsystemKind.CommandPredictor, implInfo.Kind); Assert.Same(typeof(MyPredictor), implInfo.ImplementationType); - // Now validate the all-subsystem-info collection. - ReadOnlyCollection<SubsystemInfo> ssInfos = SubsystemManager.GetAllSubsystemInfo(); - Assert.Single(ssInfos); - Assert.Same(ssInfos[0], ssInfo); - // Now validate the subsystem implementation itself. ICommandPredictor impl = SubsystemManager.GetSubsystem<ICommandPredictor>(); Assert.Same(impl, predictor1); Assert.Null(impl.FunctionsToDefine); Assert.Equal(SubsystemKind.CommandPredictor, impl.Kind); - var predCxt = PredictionContext.Create("Hello world"); - var results = impl.GetSuggestion(predCxt, CancellationToken.None); - Assert.Equal($"Hello world TEST-1 from {impl.Name}", results[0].SuggestionText); - Assert.Equal($"Hello world TeSt-2 from {impl.Name}", results[1].SuggestionText); + const string Client = "SubsystemTest"; + const string Input = "Hello world"; + var predClient = new PredictionClient(Client, PredictionClientKind.Terminal); + var predCxt = PredictionContext.Create(Input); + var results = impl.GetSuggestion(predClient, predCxt, CancellationToken.None); + Assert.Equal($"'{Input}' from '{Client}' - TEST-1 from {impl.Name}", results.SuggestionEntries[0].SuggestionText); + Assert.Equal($"'{Input}' from '{Client}' - TeSt-2 from {impl.Name}", results.SuggestionEntries[1].SuggestionText); // Now validate the all-subsystem-implementation collection. ReadOnlyCollection<ICommandPredictor> impls = SubsystemManager.GetSubsystems<ICommandPredictor>(); @@ -109,7 +134,7 @@ public static void RegisterSubsystem() SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, predictor2); // Now validate the SubsystemInfo of the 'ICommandPredictor' subsystem - VerifySubsystemMetadata(ssInfo); + VerifyCommandPredictorMetadata(ssInfo); Assert.True(ssInfo.IsRegistered); Assert.Equal(2, ssInfo.Implementations.Count); @@ -154,7 +179,7 @@ public static void UnregisterSubsystem() SubsystemManager.UnregisterSubsystem<ICommandPredictor>(predictor1.Id); SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor); - VerifySubsystemMetadata(ssInfo); + VerifyCommandPredictorMetadata(ssInfo); Assert.True(ssInfo.IsRegistered); Assert.Single(ssInfo.Implementations); @@ -175,7 +200,7 @@ public static void UnregisterSubsystem() // Unregister 'predictor2' SubsystemManager.UnregisterSubsystem(SubsystemKind.CommandPredictor, predictor2.Id); - VerifySubsystemMetadata(ssInfo); + VerifyCommandPredictorMetadata(ssInfo); Assert.False(ssInfo.IsRegistered); Assert.Empty(ssInfo.Implementations); diff --git a/test/xUnit/csharp/test_Utils.cs b/test/xUnit/csharp/test_Utils.cs index cda3d5741f4..ea45ce533d6 100644 --- a/test/xUnit/csharp/test_Utils.cs +++ b/test/xUnit/csharp/test_Utils.cs @@ -59,7 +59,7 @@ public static void TestHistoryStack() [Fact] public static void TestBoundedStack() { - int capacity = 20; + const int capacity = 20; var boundedStack = new BoundedStack<string>(capacity); Assert.Throws<InvalidOperationException>(() => boundedStack.Pop()); @@ -116,7 +116,7 @@ public static void TestConvertToJsonWithEnum() public static void TestConvertToJsonWithoutCompress() { var context = new JsonObject.ConvertToJsonContext(maxDepth: 1, enumsAsStrings: true, compressOutput: false); - string expected = @"{ + const string expected = @"{ ""type"": ""Alias"" }"; Hashtable hash = new Hashtable { @@ -134,9 +134,9 @@ public static void TestConvertToJsonCancellation() maxDepth: 1, enumsAsStrings: true, compressOutput: false, - source.Token, Newtonsoft.Json.StringEscapeHandling.Default, - targetCmdlet: null); + targetCmdlet: null, + source.Token); source.Cancel(); Hashtable hash = new Hashtable { diff --git a/test/xUnit/xUnit.tests.csproj b/test/xUnit/xUnit.tests.csproj index 1dd68b6ae8e..967f1cce627 100644 --- a/test/xUnit/xUnit.tests.csproj +++ b/test/xUnit/xUnit.tests.csproj @@ -26,8 +26,8 @@ <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="Xunit.SkippableFact" Version="1.4.13" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="XunitXml.TestLogger" Version="2.1.26" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> + <PackageReference Include="XunitXml.TestLogger" Version="3.0.66" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> </ItemGroup> <ItemGroup> diff --git a/tools/UpdateDotnetRuntime.ps1 b/tools/UpdateDotnetRuntime.ps1 index 93f3a1cbb49..46593297b9d 100644 --- a/tools/UpdateDotnetRuntime.ps1 +++ b/tools/UpdateDotnetRuntime.ps1 @@ -19,7 +19,10 @@ param ( [string]$RuntimeSourceFeedKey, [Parameter()] - [switch]$InteractiveAuth + [switch]$InteractiveAuth, + + [Parameter()] + [switch]$UseInternalFeed ) <# @@ -65,6 +68,7 @@ function Update-PackageVersion { "Microsoft.Management.Infrastructure" "Microsoft.PowerShell.Native" "Microsoft.NETCore.Windows.ApiSets" + "Microsoft.PowerShell.MarkdownRender" ) $packages = [System.Collections.Generic.Dictionary[[string], [PkgVer[]] ]]::new() @@ -72,6 +76,7 @@ function Update-PackageVersion { $paths = @( "$PSScriptRoot/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj" "$PSScriptRoot/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj" + "$PSScriptRoot/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj" "$PSScriptRoot/../src/" "$PSScriptRoot/../test/tools/" ) @@ -94,15 +99,34 @@ function Update-PackageVersion { $versionPattern = (Get-Content "$PSScriptRoot/../DotnetRuntimeMetadata.json" | ConvertFrom-Json).sdk.packageVersionPattern - $source = if ($UseNuGetOrg) { 'nuget.org' } else { 'dotnet5' } + $source = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseInternalFeed) { 'dotnet-internal' } else { 'dotnet' } + + # Always add nuget.org as some packages are only found there. + $source = if ($source -ne 'nuget.org') { + @($source, "nuget.org") + } + $packages.GetEnumerator() | ForEach-Object { - $pkgs = Find-Package -Name $_.Key -AllVersions -AllowPrereleaseVersions -Source $source + $pkgName = $_.Key + + $pkgs = [System.Collections.Generic.Dictionary[string, Microsoft.PackageManagement.Packaging.SoftwareIdentity]]::new() + + # We have to find packages for all sources separately as Find-Package does not return all packages when both sources are provided at the same time. + # Since there will be a lot of duplicates we add the package to a dictionary so we only get a unique set by version. + $source | ForEach-Object { + Find-Package -Name $pkgName -AllVersions -AllowPrereleaseVersions -Source $_ -ErrorAction SilentlyContinue | ForEach-Object { + if (-not $pkgs.ContainsKey($_.Version)) { + $pkgs.Add($_.Version, $_) + } + } + } foreach ($v in $_.Value) { $version = $v.Version - foreach ($p in $pkgs) { - if ($p.Version -like "$versionPattern*") { + foreach ($p in $pkgs.Values) { + # some packages are directly updated on nuget.org so need to check that too. + if ($p.Version -like "$versionPattern*" -or $p.Source -eq 'nuget.org') { if ([System.Management.Automation.SemanticVersion] ($version) -lt [System.Management.Automation.SemanticVersion] ($p.Version)) { $v.NewVersion = $p.Version break @@ -143,18 +167,49 @@ function Update-CsprojFile([string] $path, $values) { } function Get-DotnetUpdate { + param ( + $channel, + $quality, + $qualityFallback, + $feedUrl, + $sdkImageVersion + ) + if ($SDKVersionOverride) { return @{ ShouldUpdate = $true NewVersion = $SDKVersionOverride Message = $null + FeedUrl = $feedUrl + Quality = $quality } } try { - $dotnetMetadataPath = "$PSScriptRoot/../DotnetRuntimeMetadata.json" - $nextChannel = (Get-Content $dotnetMetadataPath -Raw | ConvertFrom-Json).sdk.nextChannel - $latestSDKversion = [System.Management.Automation.SemanticVersion] (Invoke-RestMethod -Uri "http://aka.ms/dotnet/$nextChannel/Sdk/productVersion.txt" -ErrorAction Stop | ForEach-Object { $_.Trim() }) + + try { + $latestSDKVersionString = Invoke-RestMethod -Uri "http://aka.ms/dotnet/$channel/$quality/productVersion.txt" -ErrorAction Stop | ForEach-Object { $_.Trim() } + $selectedQuality = $quality + } catch { + if ($_.exception.Response.StatusCode -eq 'NotFound') { + Write-Verbose "Build not found for Channel: $Channel and Quality: $Quality" -Verbose + } else { + throw $_ + } + } + + if (-not $latestSDKVersionString -or -not $latestSDKVersionString.StartsWith($sdkImageVersion)) { + # we did not get a version number so fall back to daily + $latestSDKVersionString = Invoke-RestMethod -Uri "http://aka.ms/dotnet/$channel/$qualityFallback/productVersion.txt" -ErrorAction Stop | ForEach-Object { $_.Trim() } + $selectedQuality = $qualityFallback + + if (-not $latestSDKVersionString.StartsWith($sdkImageVersion)) { + throw "No build found!" + } + } + + $latestSDKversion = [System.Management.Automation.SemanticVersion] $latestSDKVersionString + $currentVersion = [System.Management.Automation.SemanticVersion] (( Get-Content -Path "$PSScriptRoot/../global.json" -Raw | ConvertFrom-Json).sdk.version) if ($latestSDKversion -gt $currentVersion) { @@ -175,6 +230,8 @@ function Get-DotnetUpdate { ShouldUpdate = $shouldUpdate NewVersion = $newVersion Message = $Message + FeedUrl = $feedUrl + Quality = $selectedQuality } } @@ -187,51 +244,64 @@ function Update-DevContainer { $devContainerDocker | Out-File -FilePath $dockerFilePath -Force } -$dotnetUpdate = Get-DotnetUpdate - -if ($dotnetUpdate.ShouldUpdate) { +$dotnetMetadataPath = "$PSScriptRoot/../DotnetRuntimeMetadata.json" +$dotnetMetadataJson = Get-Content $dotnetMetadataPath -Raw | ConvertFrom-Json +$channel = $dotnetMetadataJson.sdk.channel +$nextChannel = $dotnetMetadataJson.sdk.nextChannel +$quality = $dotnetMetadataJson.sdk.quality +$qualityFallback = $dotnetMetadataJson.sdk.qualityFallback +$sdkImageVersion = $dotnetMetadataJson.sdk.sdkImageVersion +$internalfeed = $dotnetMetadataJson.internalfeed.url - $dotnetMetadataPath = "$PSScriptRoot/../DotnetRuntimeMetadata.json" - $dotnetMetadataJson = Get-Content $dotnetMetadataPath -Raw | ConvertFrom-Json +$dotnetUpdate = Get-DotnetUpdate -channel $nextChannel -quality $quality -feedUrl $internalfeed -qualityFallback $qualityFallback -sdkImageVersion $sdkImageVersion - # Channel is like: $Channel = "5.0.1xx-preview2" - $Channel = $dotnetMetadataJson.sdk.channel +if ($dotnetUpdate.ShouldUpdate) { Import-Module "$PSScriptRoot/../build.psm1" -Force Find-Dotnet - $addDotnet5Source = (-not (Get-PackageSource -Name 'dotnet5' -ErrorAction SilentlyContinue)) - $addDotnet5InternalSource = (-not (Get-PackageSource -Name 'dotnet5-internal' -ErrorAction SilentlyContinue)) + $feedname = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseInternalFeed) { 'dotnet-internal' } else { 'dotnet' } + + $addDotnetSource = (-not (Get-PackageSource -Name $feedname -ErrorAction SilentlyContinue)) - if (!$UseNuGetOrg -and ($addDotnet5Source -or $addDotnet5InternalSource)) { - $nugetFileSources = ([xml](Get-Content .\nuget.config -Raw)).Configuration.packagesources.add + if (!$UseNuGetOrg -and $addDotnetSource) { + $nugetFileContent = Get-Content "$PSScriptRoot/../nuget.config" -Raw + $nugetFileSources = ([xml]($nugetFileContent)).Configuration.packagesources.add - if ($addDotnet5Source) { - $dotnet5Feed = $nugetFileSources | Where-Object { $_.Key -eq 'dotnet5' } | Select-Object -ExpandProperty Value - Register-PackageSource -Name 'dotnet5' -Location $dotnet5Feed -ProviderName NuGet - Write-Verbose -Message "Register new package source 'dotnet5'" -verbose + if ($feedname -ne 'dotnet-internal') { + $dotnetFeed = $nugetFileSources | Where-Object { $_.Key -eq $feedname } | Select-Object -ExpandProperty Value + Register-PackageSource -Name $feedname -Location $dotnetFeed -ProviderName NuGet + Write-Verbose -Message "Register new package source $feedname" -verbose } - if ($addDotnet5InternalSource -and $InteractiveAuth) { + if ($feedname -eq 'dotnet-internal') { # This NuGet feed is for internal to Microsoft use only. - $dotnet5InternalFeed = 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json' - $updatedNugetFile = (Get-Content .\nuget.config -Raw) -replace "</packageSources>", " <add key=`"dotnet5-internal`" value=`"$dotnet5InternalFeed`" />`r`n </packageSources>" - $updatedNugetFile | Out-File .\nuget.config -Force - Register-PackageSource -Name 'dotnet5-internal' -Location $dotnet5InternalFeed -ProviderName NuGet - Write-Verbose -Message "Register new package source 'dotnet5-internal'" -verbose + $dotnetInternalFeed = $dotnetMetadataJson.internalfeed.url + + $updatedNugetFile = if ($nugetFileContent.Contains('dotnet-internal')) { + $nugetFileContent -replace ".<add key=`"dotnet-internal?.*', ' <add key=`"dotnet-internal`" value=`"$dotnetInternalFeed`" />`r`n </packageSources>" + } else { + $nugetFileContent -replace "</packageSources>", " <add key=`"dotnet-internal`" value=`"$dotnetInternalFeed`" />`r`n </packageSources>" + } + + $updatedNugetFile | Out-File "$PSScriptRoot/../nuget.config" -Force + + Register-PackageSource -Name 'dotnet-internal' -Location $dotnetInternalFeed -ProviderName NuGet + Write-Verbose -Message "Register new package source 'dotnet-internal'" -verbose } } ## Install latest version from the channel + $sdkQuality = $dotnetUpdate.Quality $sdkVersion = if ($SDKVersionOverride) { $SDKVersionOverride } else { $dotnetUpdate.NewVersion } if (-not $RuntimeSourceFeed) { - Install-Dotnet -Channel "$Channel" -Version $sdkVersion + Install-Dotnet -Version $sdkVersion -Quality $sdkQuality -Channel $null } else { - Install-Dotnet -Channel "$Channel" -Version $sdkVersion -AzureFeed $RuntimeSourceFeed -FeedCredential $RuntimeSourceFeedKey + Install-Dotnet -Version $sdkVersion -Quality $sdkQuality -AzureFeed $RuntimeSourceFeed -FeedCredential $RuntimeSourceFeedKey -Channel $null } Write-Verbose -Message "Installing .NET SDK completed." -Verbose @@ -268,6 +338,9 @@ if ($dotnetUpdate.ShouldUpdate) { Start-PSBootstrap -Package Start-PSBuild -Clean -Configuration Release -CrossGen -InteractiveAuth:$InteractiveAuth + $publishPath = Split-Path (Get-PSOutput) + Remove-Item -Path "$publishPath\*.pdb" + try { Start-PSPackage -Type msi -SkipReleaseChecks -InformationVariable wxsData } catch { diff --git a/tools/WindowsCI.psm1 b/tools/WindowsCI.psm1 index 37b866cebd0..57d506bda8b 100644 --- a/tools/WindowsCI.psm1 +++ b/tools/WindowsCI.psm1 @@ -1,11 +1,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -if($PSVersionTable.PSEdition -ne 'Desktop') -{ - throw 'Must be run from Windows PowerShell' -} - function New-LocalUser { <# diff --git a/tools/ci.psm1 b/tools/ci.psm1 index 2329b56db99..f4ed3c78945 100644 --- a/tools/ci.psm1 +++ b/tools/ci.psm1 @@ -16,8 +16,8 @@ if(Test-Path $dotNetPath) } # import build into the global scope so it can be used by packaging -Import-Module (Join-Path $repoRoot 'build.psm1') -Scope Global -Import-Module (Join-Path $repoRoot 'tools\packaging') -Scope Global +Import-Module (Join-Path $repoRoot 'build.psm1') -Verbose -Scope Global +Import-Module (Join-Path $repoRoot 'tools\packaging') -Verbose -Scope Global # import the windows specific functcion only in Windows PowerShell or on Windows if($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) @@ -99,7 +99,7 @@ function Invoke-CIBuild Start-PSBuild -Configuration 'CodeCoverage' -PSModuleRestore -CI -ReleaseTag $releaseTag } - Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -CI -ReleaseTag $releaseTag + Start-PSBuild -PSModuleRestore -Configuration 'Release' -CI -ReleaseTag $releaseTag Save-PSOptions $options = (Get-PSOptions) @@ -171,7 +171,8 @@ function Invoke-CIInstall } Set-BuildVariable -Name TestPassed -Value False - Start-PSBootstrap -Confirm:$false + Write-Verbose -Verbose -Message "Calling Start-PSBootstrap from Invoke-CIInstall" + Start-PSBootstrap } function Invoke-CIxUnit @@ -215,6 +216,9 @@ function Invoke-CITest [string] $TagSet ) + # Set locale correctly for Linux CIs + Set-CorrectLocale + # Pester doesn't allow Invoke-Pester -TagAll@('CI', 'RequireAdminOnWindows') currently # https://github.com/pester/Pester/issues/608 # To work-around it, we exlude all categories, but 'CI' from the list @@ -438,123 +442,150 @@ function Get-ReleaseTag function Invoke-CIFinish { param( - [string] $NuGetKey + [string] $Runtime = 'win7-x64', + [string] $Channel = 'preview', + [Validateset('Build','Package')] + [string[]] $Stage = ('Build','Package') ) - if($PSEdition -eq 'Core' -and ($IsLinux -or $IsMacOS)) - { - return New-LinuxPackage -NugetKey $NugetKey + if ($PSEdition -eq 'Core' -and ($IsLinux -or $IsMacOS) -and $Stage -contains 'Build') { + return New-LinuxPackage } + $artifacts = New-Object System.Collections.ArrayList try { - $releaseTag = Get-ReleaseTag - - $previewVersion = $releaseTag.Split('-') - $previewPrefix = $previewVersion[0] - $previewLabel = $previewVersion[1].replace('.','') + $buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/mainBuild" + + if ($Stage -contains "Build") { + if ($Channel -eq 'preview') { + $releaseTag = Get-ReleaseTag + + $previewVersion = $releaseTag.Split('-') + $previewPrefix = $previewVersion[0] + $previewLabel = $previewVersion[1].replace('.','') + + if (Test-DailyBuild) { + $previewLabel = "daily{0}" -f $previewLabel + } + + $prereleaseIteration = (get-date).Day + $preReleaseVersion = "$previewPrefix-$previewLabel.$prereleaseIteration" + # Build clean before backing to remove files from testing + Start-PSBuild -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime -output $buildFolder -PSOptionsPath "${buildFolder}/psoptions.json" + $options = Get-PSOptions + # Remove symbol files. + $filter = Join-Path -Path (Split-Path $options.Output) -ChildPath '*.pdb' + Write-Verbose "Removing symbol files from $filter" -Verbose + Remove-Item $filter -Force -Recurse + } else { + $releaseTag = Get-ReleaseTag + $releaseTagParts = $releaseTag.split('.') + $preReleaseVersion = $releaseTagParts[0]+ ".9.9" + Write-Verbose "newPSReleaseTag: $preReleaseVersion" -Verbose + Start-PSBuild -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime -output $buildFolder -PSOptionsPath "${buildFolder}/psoptions.json" + $options = Get-PSOptions + # Remove symbol files. + $filter = Join-Path -Path (Split-Path $options.Output) -ChildPath '*.pdb' + Write-Verbose "Removing symbol files from $filter" -Verbose + Remove-Item $filter -Force -Recurse + } - if(Test-DailyBuild) - { - $previewLabel= "daily{0}" -f $previewLabel + # Set a variable, both in the current process and in AzDevOps for the packaging stage to get the release tag + $env:CI_FINISH_RELASETAG=$preReleaseVersion + $vstsCommandString = "vso[task.setvariable variable=CI_FINISH_RELASETAG]$preReleaseVersion" + Write-Verbose -Message "$vstsCommandString" -Verbose + Write-Host -Object "##$vstsCommandString" } - $preReleaseVersion = "$previewPrefix-$previewLabel.$env:BUILD_BUILDID" - - # Build clean before backing to remove files from testing - Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean - - # Build packages - $packages = Start-PSPackage -Type msi,nupkg,zip,zip-pdb -ReleaseTag $preReleaseVersion -SkipReleaseChecks - - $artifacts = New-Object System.Collections.ArrayList - foreach ($package in $packages) { - if (Test-Path $package -ErrorAction Ignore) - { - Write-Log "Package found: $package" + if ($Stage -contains "Package") { + Restore-PSOptions -PSOptionsPath "${buildFolder}/psoptions.json" + $preReleaseVersion = $env:CI_FINISH_RELASETAG + + # Build packages $preReleaseVersion = "$previewPrefix-$previewLabel.$prereleaseIteration" + switch -regex ($Runtime){ + default { + $runPackageTest = $true + $packageTypes = 'msi', 'nupkg', 'zip', 'zip-pdb', 'msix' + } + 'win-arm.*' { + $runPackageTest = $false + $packageTypes = 'zip', 'zip-pdb', 'msix' + } } - else - { - Write-Warning -Message "Package NOT found: $package" + $packages = Start-PSPackage -Type $packageTypes -ReleaseTag $preReleaseVersion -SkipReleaseChecks -WindowsRuntime $Runtime + + foreach ($package in $packages) { + if (Test-Path $package -ErrorAction Ignore) { + Write-Log "Package found: $package" + } else { + Write-Warning -Message "Package NOT found: $package" + } + + if ($package -is [string]) { + $null = $artifacts.Add($package) + } elseif ($package -is [pscustomobject] -and $package.psobject.Properties['msi']) { + $null = $artifacts.Add($package.msi) + $null = $artifacts.Add($package.wixpdb) + } } - if($package -is [string]) - { - $null = $artifacts.Add($package) + if ($runPackageTest) { + # the packaging tests find the MSI package using env:PSMsiX64Path + $env:PSMsiX64Path = $artifacts | Where-Object { $_.EndsWith(".msi")} + $architechture = $Runtime.Split('-')[1] + $exePath = New-ExePackage -ProductVersion ($preReleaseVersion -replace '^v') -ProductTargetArchitecture $architechture -MsiLocationPath $env:PSMsiX64Path + Write-Verbose "exe Path: $exePath" -Verbose + $artifacts.Add($exePath) + $env:PSExePath = $exePath + $env:PSMsiChannel = $Channel + $env:PSMsiRuntime = $Runtime + + # Install the latest Pester and import it + $maximumPesterVersion = '4.99' + Install-Module Pester -Force -SkipPublisherCheck -MaximumVersion $maximumPesterVersion + Import-Module Pester -Force -MaximumVersion $maximumPesterVersion + + $testResultPath = Join-Path -Path $env:TEMP -ChildPath "win-package-$channel-$runtime.xml" + + # start the packaging tests and get the results + $packagingTestResult = Invoke-Pester -Script (Join-Path $repoRoot '.\test\packaging\windows\') -PassThru -OutputFormat NUnitXml -OutputFile $testResultPath + + Publish-TestResults -Title "win-package-$channel-$runtime" -Path $testResultPath + + # fail the CI job if the tests failed, or nothing passed + if (-not $packagingTestResult -is [pscustomobject] -or $packagingTestResult.FailedCount -ne 0 -or $packagingTestResult.PassedCount -eq 0) { + throw "Packaging tests failed ($($packagingTestResult.FailedCount) failed/$($packagingTestResult.PassedCount) passed)" + } } - elseif($package -is [pscustomobject] -and $package.psobject.Properties['msi']) - { - $null = $artifacts.Add($package.msi) - $null = $artifacts.Add($package.wixpdb) - } - } - - # the packaging tests find the MSI package using env:PSMsiX64Path - $env:PSMsiX64Path = $artifacts | Where-Object { $_.EndsWith(".msi")} - # Install the latest Pester and import it - $maximumPesterVersion = '4.99' - Install-Module Pester -Force -SkipPublisherCheck -MaximumVersion $maximumPesterVersion - Import-Module Pester -Force -MaximumVersion $maximumPesterVersion - - # start the packaging tests and get the results - $packagingTestResult = Invoke-Pester -Script (Join-Path $repoRoot '.\test\packaging\windows\') -PassThru - - # fail the CI job if the tests failed, or nothing passed - if(-not $packagingTestResult -is [pscustomobject] -or $packagingTestResult.FailedCount -ne 0 -or $packagingTestResult.PassedCount -eq 0) - { - 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)) + # 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)) + } } } - - # produce win-arm and win-arm64 packages if it is a daily build - Start-PSBuild -Restore -Runtime win-arm -PSModuleRestore -Configuration 'Release' -ReleaseTag $releaseTag - $arm32Package = Start-PSPackage -Type zip -WindowsRuntime win-arm -ReleaseTag $releaseTag -SkipReleaseChecks - $artifacts.Add($arm32Package) - - Start-PSBuild -Restore -Runtime win-arm64 -PSModuleRestore -Configuration 'Release' -ReleaseTag $releaseTag - $arm64Package = Start-PSPackage -Type zip -WindowsRuntime win-arm64 -ReleaseTag $releaseTag -SkipReleaseChecks - $artifacts.Add($arm64Package) - + } catch { + Get-Error -InputObject $_ + throw + } finally { $pushedAllArtifacts = $true $artifacts | ForEach-Object { Write-Log -Message "Pushing $_ as CI artifact" - if(Test-Path $_) - { + if (Test-Path $_) { Push-Artifact -Path $_ -Name 'artifacts' - } - else - { + } else { $pushedAllArtifacts = $false Write-Warning "Artifact $_ does not exist." } - - if($NuGetKey -and $env:NUGET_URL -and [system.io.path]::GetExtension($_) -ieq '.nupkg') - { - Write-Log "pushing $_ to $env:NUGET_URL" - Start-NativeExecution -sb {dotnet nuget push $_ --api-key $NuGetKey --source "$env:NUGET_URL/api/v2/package"} -IgnoreExitcode - } } - if(!$pushedAllArtifacts) - { + + if (!$pushedAllArtifacts) { throw "Some artifacts did not exist!" } } - catch - { - Write-Host -Foreground Red $_ - Write-Host -Foreground Red $_.ScriptStackTrace - throw $_ - } } # Bootstrap script for Linux and macOS @@ -692,10 +723,6 @@ function Invoke-LinuxTestsCore function New-LinuxPackage { - param( - [string] - $NugetKey - ) $isFullBuild = Test-DailyBuild $releaseTag = Get-ReleaseTag @@ -704,7 +731,7 @@ function New-LinuxPackage # Only build packages for PowerShell/PowerShell repository # branches, not pull requests - $packages = @(Start-PSPackage @packageParams -SkipReleaseChecks) + $packages = @(Start-PSPackage @packageParams -SkipReleaseChecks -Type deb, rpm, tar) foreach($package in $packages) { if (Test-Path $package) @@ -716,31 +743,18 @@ function New-LinuxPackage Write-Error -Message "Package NOT found: $package" } - # Publish the packages to the nuget feed if: - # 1 - It's a Daily build (already checked, for not a PR) - # 2 - We have the info to publish (NUGET_KEY and NUGET_URL) - # 3 - it's a nupkg file - if($isFullBuild -and $NugetKey -and $env:NUGET_URL -and [system.io.path]::GetExtension($package) -ieq '.nupkg') + if ($package -isnot [System.IO.FileInfo]) { - Write-Log "pushing $package to $env:NUGET_URL" - Start-NativeExecution -sb {dotnet nuget push $package --api-key $NugetKey --source "$env:NUGET_URL/api/v2/package"} -IgnoreExitcode + $packageObj = Get-Item $package + Write-Error -Message "The PACKAGE is not a FileInfo object" } - - if($isFullBuild) + else { - if ($package -isnot [System.IO.FileInfo]) - { - $packageObj = Get-Item $package - Write-Error -Message "The PACKAGE is not a FileInfo object" - } - else - { - $packageObj = $package - } - - Write-Log -message "Artifacts directory: ${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" - Copy-Item $packageObj.FullName -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force + $packageObj = $package } + + Write-Log -message "Artifacts directory: ${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" + Copy-Item $packageObj.FullName -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force } if ($IsLinux) diff --git a/tools/findMissingNotices.ps1 b/tools/findMissingNotices.ps1 new file mode 100644 index 00000000000..7e802e4238a --- /dev/null +++ b/tools/findMissingNotices.ps1 @@ -0,0 +1,136 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# Requires the module dotnet.project.assets from the PowerShell Gallery authored by @TravisEz13 + +import-module dotnet.project.assets +Class Registration { + [Component]$Component + [bool]$DevelopmentDependency +} + +Class Component { + [ValidateSet("nuget")] + [String] $Type + [Nuget]$Nuget + + [string]ToString() { + $message = "Type: $($this.Type)" + if ($this.Type -eq "nuget") { + $message += "; $($this.Nuget)" + } + return $message + } + + [string]Name() { + switch ($this.Type) { + "nuget" { + return $($this.Nuget.Name) + } + default { + throw "Unknown component type: $($this.Type)" + } + } + throw "How did we get here?!?" + } + + [string]Version() { + switch ($this.Type) { + "nuget" { + return $($this.Nuget.Version) + } + default { + throw "Unknown component type: $($this.Type)" + } + } + throw "How did we get here?!?" + } +} + +Class Nuget { + [string]$Name + [string]$Version + + [string]ToString() { + return "$($this.Name) - $($this.Version)" + } +} + +function New-NugetComponent { + param( + [string]$name, + [string]$version + ) + + $nuget = [Nuget]@{ + Name = $name + Version = $version + } + $Component = [Component]@{ + Type = "nuget" + Nuget = $nuget + } + + $registration = [Registration]@{ + Component = $Component + DevelopmentDependency = $false + } + + return $registration +} + +$existingRegistrationTable = @{} +$newRegistrations = @() +$existingRegistrationsJson = Get-Content $PSScriptRoot\..\cgmanifest.json | ConvertFrom-Json -AsHashtable +$existingRegistrationsJson.Registrations | ForEach-Object { + $registration = [Registration]$_ + $existingRegistrationTable.Add($registration.Component.Name(), $registration) + $newRegistrations += $registration +} + +Get-PSDrive -Name pwsh-win-core -ErrorAction Ignore | Remove-PSDrive +Push-Location $PSScriptRoot\..\src\powershell-win-core +$null = dotnet restore +$null = New-PADrive -Path $PSScriptRoot\..\src\powershell-win-core\obj\project.assets.json -Name pwsh-win-core +$targets = Get-ChildItem -Path 'pwsh-win-core:/targets/net6.0-windows7.0|win7-x64' | Where-Object { + $_.Type -eq 'package' -and + $_.Name -notlike 'DotNetAnalyzers.DocumentationAnalyzers*' -and + $_.Name -notlike 'StyleCop*' -and + $_.Name -notlike 'Microsoft.CodeAnalysis.Analyzers*' -and + $_.Name -notlike 'Microsoft.CodeAnalysis.NetAnalyzers*' +} | select-object -ExpandProperty name +Pop-Location +Get-PSDrive -Name pwsh-win-core | Remove-PSDrive + +$updateRegistrations = @() +$targets | ForEach-Object { + $target = $_ + $parts = ($target -split '\|') + $name = $parts[0] + $targetVersion = $parts[1] + $pattern = [regex]::Escape($name) + " " + $tpnMatch = select-string -Path $PSScriptRoot\..\ThirdPartyNotices.txt -Pattern $pattern + if (!$tpnMatch) { + if ($existingRegistrationTable.ContainsKey($name)) { + $registrationVersion = $existingRegistrationTable.$name.Component.Version() + if ($registrationVersion -ne $targetVersion) { + $registration = New-NugetComponent -Name $name -Version $targetVersion + $updateRegistrations += $registration + } else { + Write-Verbose "$target already registered: $registrationVersion" -Verbose + } + } else { + $registration = New-NugetComponent -Name $name -Version $targetVersion + $newRegistrations += $registration + } + } +} + +if ($updateRegistrations.count -gt 0) { + #TODO delete existing and add new registration + throw "updating registrations is not implemented" +} + +$newCount = $newRegistrations.count - $existingRegistrationTable.count +@{Registrations = $newRegistrations } | ConvertTo-Json -depth 99 | Set-Content $PSScriptRoot\..\cgmanifest.json +Write-Verbose "$newCount registrations added" -Verbose diff --git a/tools/installpsh-debian.sh b/tools/installpsh-debian.sh index 0314bc05260..2c70f0a7cec 100755 --- a/tools/installpsh-debian.sh +++ b/tools/installpsh-debian.sh @@ -19,7 +19,7 @@ #gitrepo paths are overrideable to run from your own fork or branch for testing or private distribution -VERSION="1.2.0" +VERSION="1.2.1" gitreposubpath="PowerShell/PowerShell/master" gitreposcriptroot="https://raw.githubusercontent.com/$gitreposubpath/tools" thisinstallerdistro=debian @@ -176,12 +176,12 @@ fi case $DISTRIB_ID in ubuntu|linuxmint) case $DISTRIB_RELEASE in - 18.04|16.10|16.04|15.10|14.04) + 20.04|18.04|16.10|16.04|15.10|14.04) curl https://packages.microsoft.com/config/ubuntu/$DISTRIB_RELEASE/prod.list | $SUDO tee /etc/apt/sources.list.d/microsoft.list ;; *) echo "ERROR: unsupported Ubuntu version ($DISTRIB_RELEASE)." >&2 - echo "Supported versions: 14.04, 15.10, 16.04, 16.10, 18.04." >&2 + echo "Supported versions: 14.04, 15.10, 16.04, 16.10, 18.04, 20.04." >&2 echo "For additional versions open an issue or pull request at: https://github.com/powershell/powershell" >&2 exit 1 ;; diff --git a/tools/metadata.json b/tools/metadata.json index 690a4fd143e..1a0de37657f 100644 --- a/tools/metadata.json +++ b/tools/metadata.json @@ -1,9 +1,10 @@ { - "StableReleaseTag": "v7.0.3", - "PreviewReleaseTag": "v7.1.0-preview.7", - "ServicingReleaseTag": "v6.2.7", - "ReleaseTag": "v7.0.3", - "LTSReleaseTag" : ["v7.0.3"], - "NextReleaseTag": "v7.1.0-preview.8", - "LTSRelease": false + "StableReleaseTag": "v7.2.0", + "PreviewReleaseTag": "v7.2.0-preview.10", + "ServicingReleaseTag": "v7.1.5", + "ReleaseTag": "v7.2.0", + "LTSReleaseTag" : ["v7.0.8", "7.2.0"], + "NextReleaseTag": "v7.2.0-preview.11", + "LTSRelease": { "Latest": true, "Package": true }, + "StableRelease": { "Latest": true, "Package": true } } diff --git a/tools/packaging/packaging.psd1 b/tools/packaging/packaging.psd1 index 2a1df399f13..8de303ef45c 100644 --- a/tools/packaging/packaging.psd1 +++ b/tools/packaging/packaging.psd1 @@ -1,12 +1,29 @@ @{ -GUID="41857994-4283-4757-a932-0b0edb104913" -Author="PowerShell" -CompanyName="Microsoft Corporation" -Copyright="Copyright (c) Microsoft Corporation." -ModuleVersion="1.0.0" -PowerShellVersion="5.0" -CmdletsToExport=@() -FunctionsToExport=@('Start-PSPackage','New-PSSignedBuildZip', 'New-PSBuildZip', 'New-MSIPatch', 'Expand-PSSignedBuild', 'Publish-NugetToMyGet', 'New-DotnetSdkContainerFxdPackage', 'New-GlobalToolNupkg', 'New-ILNugetPackage', 'Update-PSSignedBuildFolder') -RootModule="packaging.psm1" -RequiredModules = @("build") + GUID = "41857994-4283-4757-a932-0b0edb104913" + Author = "PowerShell" + CompanyName = "Microsoft Corporation" + Copyright = "Copyright (c) Microsoft Corporation." + ModuleVersion = "1.0.0" + PowerShellVersion = "5.0" + CmdletsToExport = @() + FunctionsToExport = @( + 'Compress-ExePackageEngine' + 'Expand-ExePackageEngine' + 'Expand-PSSignedBuild' + 'Invoke-AzDevOpsLinuxPackageBuild' + 'Invoke-AzDevOpsLinuxPackageCreation' + 'New-DotnetSdkContainerFxdPackage' + 'New-ExePackage' + 'New-GlobalToolNupkg' + 'New-ILNugetPackage' + 'New-MSIPatch' + 'New-PSBuildZip' + 'New-PSSignedBuildZip' + 'Publish-NugetToMyGet' + 'Start-PSPackage' + 'Test-PackageManifest' + 'Update-PSSignedBuildFolder' + ) + RootModule = "packaging.psm1" + RequiredModules = @("build") } diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 664f5455553..70cf08fc79d 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -6,9 +6,9 @@ $RepoRoot = (Resolve-Path -Path "$PSScriptRoot/../..").Path $packagingStrings = Import-PowerShellDataFile "$PSScriptRoot\packaging.strings.psd1" Import-Module "$PSScriptRoot\..\Xml" -ErrorAction Stop -Force -$DebianDistributions = @("ubuntu.16.04", "ubuntu.18.04", "debian.9", "debian.10", "debian.11") -$RedhatDistributions = @("rhel.7","centos.8") -$script:netCoreRuntime = 'net5.0' +$DebianDistributions = @("deb") +$RedhatDistributions = @("rh") +$script:netCoreRuntime = 'net6.0' $script:iconFileName = "Powershell_black_64.png" $script:iconPath = Join-Path -path $PSScriptRoot -ChildPath "../../assets/$iconFileName" -Resolve @@ -20,7 +20,7 @@ function Start-PSPackage { [string]$Version, [Parameter(ParameterSetName = "ReleaseTag")] - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [ValidateNotNullOrEmpty()] [string]$ReleaseTag, @@ -29,7 +29,7 @@ function Start-PSPackage { [string]$Name = "powershell", # Ubuntu, CentOS, Fedora, macOS, and Windows packages are supported - [ValidateSet("msix", "deb", "osxpkg", "rpm", "msi", "zip", "zip-pdb", "nupkg", "tar", "tar-arm", "tar-arm64", "tar-alpine", "fxdependent", "fxdependent-win-desktop")] + [ValidateSet("msix", "deb", "osxpkg", "rpm", "msi", "zip", "zip-pdb", "nupkg", "tar", "tar-arm", "tar-arm64", "tar-alpine", "fxdependent", "fxdependent-win-desktop", "min-size")] [string[]]$Type, # Generate windows downlevel package @@ -37,6 +37,10 @@ function Start-PSPackage { [ValidateScript({$Environment.IsWindows})] [string] $WindowsRuntime, + [ValidateSet('osx-x64', 'osx-arm64')] + [ValidateScript({$Environment.IsMacOS})] + [string] $MacOSRuntime, + [Switch] $Force, [Switch] $SkipReleaseChecks, @@ -47,7 +51,7 @@ function Start-PSPackage { ) DynamicParam { - if ("zip" -eq $Type -or "fxdependent" -eq $Type -or "fxdependent-win-desktop" -eq $Type) { + if ($Type -in ('zip', 'min-size') -or $Type -like 'fxdependent*') { # Add a dynamic parameter '-IncludeSymbols' when the specified package type is 'zip' only. # The '-IncludeSymbols' parameter can be used to indicate that the package should only contain powershell binaries and symbols. $ParameterAttr = New-Object "System.Management.Automation.ParameterAttribute" @@ -71,12 +75,18 @@ function Start-PSPackage { # Runtime and Configuration settings required by the package ($Runtime, $Configuration) = if ($WindowsRuntime) { $WindowsRuntime, "Release" - } elseif ($Type -eq "tar-alpine") { + } elseif ($MacOSRuntime) { + $MacOSRuntime, "Release" + } elseif ($Type.Count -eq 1 -and $Type[0] -eq "tar-alpine") { New-PSOptions -Configuration "Release" -Runtime "alpine-x64" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } - } elseif ($Type -eq "tar-arm") { + } elseif ($Type.Count -eq 1 -and $Type[0] -eq "tar-arm") { New-PSOptions -Configuration "Release" -Runtime "Linux-ARM" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } - } elseif ($Type -eq "tar-arm64") { - New-PSOptions -Configuration "Release" -Runtime "Linux-ARM64" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } + } elseif ($Type.Count -eq 1 -and $Type[0] -eq "tar-arm64") { + if ($IsMacOS) { + New-PSOptions -Configuration "Release" -Runtime "osx-arm64" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } + } else { + New-PSOptions -Configuration "Release" -Runtime "Linux-ARM64" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } + } } else { New-PSOptions -Configuration "Release" -WarningAction SilentlyContinue | ForEach-Object { $_.Runtime, $_.Configuration } } @@ -93,10 +103,13 @@ function Start-PSPackage { if ($Type -eq 'fxdependent') { $NameSuffix = "win-fxdependent" - Write-Log "Packaging : '$Type'; Packaging Configuration: '$Configuration'" + Write-Log "Packaging : '$Type'; Packaging Configuration: '$Configuration', Runtime: '$Runtime'" } elseif ($Type -eq 'fxdependent-win-desktop') { $NameSuffix = "win-fxdependentWinDesktop" - Write-Log "Packaging : '$Type'; Packaging Configuration: '$Configuration'" + Write-Log "Packaging : '$Type'; Packaging Configuration: '$Configuration', Runtime: '$Runtime'" + } elseif ($MacOSRuntime) { + $NameSuffix = $MacOSRuntime + Write-Log "Packaging : '$Type'; Packaging Configuration: '$Configuration', Runtime: '$Runtime'" } else { Write-Log "Packaging RID: '$Runtime'; Packaging Configuration: '$Configuration'" } @@ -104,16 +117,6 @@ function Start-PSPackage { $Script:Options = Get-PSOptions $actualParams = @() - $crossGenCorrect = $false - if ($Runtime -match "arm") { - # crossgen doesn't support arm32/64 - $crossGenCorrect = $true - } - elseif ($Script:Options.CrossGen) { - $actualParams += '-CrossGen' - $crossGenCorrect = $true - } - $PSModuleRestoreCorrect = $false # Require PSModuleRestore for packaging without symbols @@ -130,14 +133,13 @@ function Start-PSPackage { } $precheckFailed = if ($Type -like 'fxdependent*' -or $Type -eq 'tar-alpine') { - ## We do not check for runtime and crossgen for framework dependent package. + ## We do not check on runtime for framework dependent package. -not $Script:Options -or ## Start-PSBuild hasn't been executed yet -not $PSModuleRestoreCorrect -or ## Last build didn't specify '-PSModuleRestore' correctly $Script:Options.Configuration -ne $Configuration -or ## Last build was with configuration other than 'Release' $Script:Options.Framework -ne $script:netCoreRuntime ## Last build wasn't for CoreCLR } else { -not $Script:Options -or ## Start-PSBuild hasn't been executed yet - -not $crossGenCorrect -or ## Last build didn't specify '-CrossGen' correctly -not $PSModuleRestoreCorrect -or ## Last build didn't specify '-PSModuleRestore' correctly $Script:Options.Runtime -ne $Runtime -or ## Last build wasn't for the required RID $Script:Options.Configuration -ne $Configuration -or ## Last build was with configuration other than 'Release' @@ -157,14 +159,8 @@ function Start-PSPackage { # also ensure `Start-PSPackage` does what the user asks/expects, because once packages # are generated, it'll be hard to verify if they were built from the correct content. - $params = @('-Clean') - # CrossGen cannot be done for framework dependent package as it is runtime agnostic. - if ($Type -notlike 'fxdependent*') { - $params += '-CrossGen' - } - if (!$IncludeSymbols.IsPresent) { $params += '-PSModuleRestore' } @@ -211,6 +207,22 @@ function Start-PSPackage { # Copy the default.help.txt so it's part of the package Copy-Item "$RepoRoot/assets/default.help.txt" -Destination "$Source/en-US" -Force + if (-not $SkipGenerateReleaseFiles -and -not $env:TF_BUILD) { + # Make sure psoptions.json file exists so appropriate files.wsx is generated + $psOptionsPath = (Join-Path -Path $Source "psoptions.json") + if (-not (Test-Path -Path $psOptionsPath)) { + $createdOptionsFile = New-Item -Path $psOptionsPath -Force + Write-Verbose -Verbose "Created psoptions file: $createdOptionsFile" + } + + # Make sure _manifest\spdx_2.2\manifest.spdx.json file exists so appropriate files.wxs is generated + $manifestSpdxPath = (Join-Path -Path $Source "_manifest\spdx_2.2\manifest.spdx.json") + if (-not (Test-Path -Path $manifestSpdxPath)) { + $createdSpdxPath = New-Item -Path $manifestSpdxPath -Force + Write-Verbose -Verbose "Created manifest.spdx.json file: $createdSpdxPath" + } + } + # If building a symbols package, we add a zip of the parent to publish if ($IncludeSymbols.IsPresent) { @@ -299,13 +311,35 @@ function Start-PSPackage { New-PdbZipPackage @Arguments } } + "min-size" { + # Add suffix '-gc' because this package is for the Guest Config team. + if ($Environment.IsWindows) { + $Arguments = @{ + PackageNameSuffix = "$NameSuffix-gc" + PackageSourcePath = $Source + PackageVersion = $Version + Force = $Force + } - { $_ -like "fxdependent*" } { - ## Remove PDBs from package to reduce size. - if(-not $IncludeSymbols.IsPresent) { - Get-ChildItem $Source -Filter *.pdb | Remove-Item -Force + if ($PSCmdlet.ShouldProcess("Create Zip Package")) { + New-ZipPackage @Arguments + } } + elseif ($Environment.IsLinux) { + $Arguments = @{ + PackageSourcePath = $Source + Name = $Name + PackageNameSuffix = 'gc' + Version = $Version + Force = $Force + } + if ($PSCmdlet.ShouldProcess("Create tar.gz Package")) { + New-TarballPackage @Arguments + } + } + } + { $_ -like "fxdependent*" } { if ($Environment.IsWindows) { $Arguments = @{ PackageNameSuffix = $NameSuffix @@ -317,7 +351,7 @@ function Start-PSPackage { if ($PSCmdlet.ShouldProcess("Create Zip Package")) { New-ZipPackage @Arguments } - } elseif ($IsLinux) { + } elseif ($Environment.IsLinux) { $Arguments = @{ PackageSourcePath = $Source Name = $Name @@ -336,6 +370,7 @@ function Start-PSPackage { if ($Runtime -match "-x86") { $TargetArchitecture = "x86" } + Write-Verbose "TargetArchitecture = $TargetArchitecture" -Verbose $Arguments = @{ ProductNameSuffix = $NameSuffix @@ -385,6 +420,10 @@ function Start-PSPackage { Force = $Force } + if ($MacOSRuntime) { + $Arguments['Architecture'] = $MacOSRuntime.Split('-')[1] + } + if ($PSCmdlet.ShouldProcess("Create tar.gz Package")) { New-TarballPackage @Arguments } @@ -512,7 +551,9 @@ function New-TarballPackage { [switch] $Force, - [switch] $ExcludeSymbolicLinks + [switch] $ExcludeSymbolicLinks, + + [string] $CurrentLocation = (Get-Location) ) if ($PackageNameSuffix) { @@ -529,7 +570,7 @@ function New-TarballPackage { $packageName = $packageName -f "osx" } - $packagePath = Join-Path -Path $PWD -ChildPath $packageName + $packagePath = Join-Path -Path $CurrentLocation -ChildPath $packageName Write-Verbose "Create package $packageName" Write-Verbose "Package destination path: $packagePath" @@ -543,10 +584,6 @@ function New-TarballPackage { $Staging = "$PSScriptRoot/staging" New-StagingFolder -StagingPath $Staging -PackageSourcePath $PackageSourcePath - if (-not $ExcludeSymbolicLinks.IsPresent) { - New-PSSymbolicLinks -Distribution 'ubuntu.16.04' -Staging $Staging - } - if (Get-Command -Name tar -CommandType Application -ErrorAction Ignore) { if ($Force -or $PSCmdlet.ShouldProcess("Create tarball package")) { $options = "-czf" @@ -644,7 +681,8 @@ function Update-PSSignedBuildFolder [Parameter(Mandatory)] [string]$BuildPath, [Parameter(Mandatory)] - [string]$SignedFilesPath + [string]$SignedFilesPath, + [string[]] $RemoveFilter = ('*.pdb', '*.zip') ) # Replace unsigned binaries with signed @@ -655,6 +693,11 @@ function Update-PSSignedBuildFolder Write-Log "replacing $destination with $_" Copy-Item -Path $_ -Destination $destination -Force } + + foreach($filter in $RemoveFilter) { + $removePath = Join-Path -Path $BuildPath -ChildPath $filter + Remove-Item -Path $removePath -Recurse -Force + } } @@ -689,7 +732,7 @@ function Expand-PSSignedBuild Restore-PSModuleToBuild -PublishPath $buildPath $psOptionsPath = Join-Path $buildPath -ChildPath 'psoptions.json' - Restore-PSOptions -PSOptionsPath $psOptionsPath -Remove + Restore-PSOptions -PSOptionsPath $psOptionsPath $options = Get-PSOptions @@ -733,7 +776,10 @@ function New-UnixPackage { $NoSudo, [switch] - $LTS + $LTS, + + [string] + $CurrentLocation = (Get-Location) ) DynamicParam { @@ -780,6 +826,8 @@ function New-UnixPackage { $DebDistro = "ubuntu.16.04" } elseif ($Environment.IsUbuntu18) { $DebDistro = "ubuntu.18.04" + } elseif ($Environment.IsUbuntu20) { + $DebDistro = "ubuntu.20.04" } elseif ($Environment.IsDebian9) { $DebDistro = "debian.9" } else { @@ -801,9 +849,6 @@ function New-UnixPackage { } $packageVersion = Get-LinuxPackageSemanticVersion -Version $Version - if (!$Environment.IsRedHatFamily -and !$Environment.IsSUSEFamily) { - throw ($ErrorMessage -f "Redhat or SUSE Family") - } } "osxpkg" { $packageVersion = $Version @@ -865,8 +910,7 @@ function New-UnixPackage { if ($PSCmdlet.ShouldProcess("Create package file system")) { # Generate After Install and After Remove scripts - $AfterScriptInfo = New-AfterScripts -Link $Link -Distribution $DebDistro - New-PSSymbolicLinks -Distribution $DebDistro -Staging $Staging + $AfterScriptInfo = New-AfterScripts -Link $Link -Distribution $DebDistro -Destination $Destination # there is a weird bug in fpm # if the target of the powershell symlink exists, `fpm` aborts @@ -964,7 +1008,7 @@ function New-UnixPackage { } # Magic to get path output - $createdPackage = Get-Item (Join-Path $PWD (($Output[-1] -split ":path=>")[-1] -replace '["{}]')) + $createdPackage = Get-Item (Join-Path $CurrentLocation (($Output[-1] -split ":path=>")[-1] -replace '["{}]')) if ($Environment.IsMacOS) { if ($PSCmdlet.ShouldProcess("Add distribution information and Fix PackageName")) @@ -1068,7 +1112,7 @@ function New-MacOsDistributionPackage # 2 - package path # 3 - minimum os version # 4 - Package Identifier - $PackagingStrings.OsxDistributionTemplate -f "PowerShell - $packageVersion", $packageVersion, $packageName, '10.13', $packageId | Out-File -Encoding ascii -FilePath $distributionXmlPath -Force + $PackagingStrings.OsxDistributionTemplate -f "PowerShell - $packageVersion", $packageVersion, $packageName, '10.14', $packageId | Out-File -Encoding ascii -FilePath $distributionXmlPath -Force Write-Log "Applying distribution.xml to package..." Push-Location $tempDir @@ -1180,15 +1224,17 @@ function Get-FpmArguments "--maintainer", "PowerShell Team <PowerShellTeam@hotmail.com>", "--vendor", "Microsoft Corporation", "--url", "https://microsoft.com/powershell", - "--license", "MIT License", "--description", $Description, "--category", "shells", "-t", $Type, "-s", "dir" ) - if ($Environment.IsRedHatFamily) { + if ($Distribution -eq 'rh') { $Arguments += @("--rpm-dist", $Distribution) $Arguments += @("--rpm-os", "linux") + $Arguments += @("--license", "MIT") + } else { + $Arguments += @("--license", "MIT License") } if ($Environment.IsMacOS) { @@ -1226,68 +1272,33 @@ function Get-FpmArguments return $Arguments } -function Test-Distribution -{ - param( - [String] - $Distribution - ) - - if ( $Environment.IsDebianFamily -and !$Distribution ) - { - throw "$Distribution is required for a Debian based distribution." - } - - if ( $Environment.IsDebianFamily -and $Script:DebianDistributions -notcontains $Distribution) - { - throw "$Distribution should be one of the following: $Script:DebianDistributions" - } - - if ( $Environment.IsRedHatFamily -and $Script:RedHatDistributions -notcontains $Distribution) - { - throw "$Distribution should be one of the following: $Script:RedHatDistributions" - } - - return $true -} function Get-PackageDependencies { param( [String] - [ValidateScript({Test-Distribution -Distribution $_})] + [ValidateSet('rh','deb','macOS')] $Distribution ) End { # These should match those in the Dockerfiles, but exclude tools like Git, which, and curl $Dependencies = @() - if ($Environment.IsDebianFamily) { + if ($Distribution -eq 'deb') { $Dependencies = @( "libc6", "libgcc1", "libgssapi-krb5-2", - "liblttng-ust0", "libstdc++6", - "zlib1g" + "zlib1g", + "libicu72|libicu71|libicu70|libicu69|libicu68|libicu67|libicu66|libicu65|libicu63|libicu60|libicu57|libicu55|libicu52", + "libssl1.1|libssl1.0.2|libssl1.0.0" ) - switch -regex ($Distribution) { - "ubuntu\.16\.04" { $Dependencies += @("libssl1.0.0", "libicu55") } - "ubuntu\.18\.04" { $Dependencies += @("libssl1.0.0", "libicu60") } - "debian\.9" { $Dependencies += @("libssl1.0.2", "libicu57") } - "debian\.(10|11)" { $Dependencies += @("libssl1.1", "libicu63") } - default { throw "Debian distro '$Distribution' is not supported." } - } - } elseif ($Environment.IsRedHatFamily) { + } elseif ($Distribution -eq 'rh') { $Dependencies = @( "openssl-libs", "libicu" ) - } elseif ($Environment.IsSUSEFamily) { - $Dependencies = @( - "libopenssl1_0_0", - "libicu" - ) } return $Dependencies @@ -1329,27 +1340,31 @@ function New-AfterScripts [Parameter(Mandatory)] [string] - $Distribution + $Distribution, + + [Parameter(Mandatory)] + [string] + $Destination ) Write-Verbose -Message "AfterScript Distribution: $Distribution" -Verbose - if ($Environment.IsRedHatFamily) { - $AfterInstallScript = [io.path]::GetTempFileName() - $AfterRemoveScript = [io.path]::GetTempFileName() - $packagingStrings.RedHatAfterInstallScript -f "$Link" | Out-File -FilePath $AfterInstallScript -Encoding ascii - $packagingStrings.RedHatAfterRemoveScript -f "$Link" | Out-File -FilePath $AfterRemoveScript -Encoding ascii + if ($Distribution -eq 'rh') { + $AfterInstallScript = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + $AfterRemoveScript = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + $packagingStrings.RedHatAfterInstallScript -f "$Link", $Destination | Out-File -FilePath $AfterInstallScript -Encoding ascii + $packagingStrings.RedHatAfterRemoveScript -f "$Link", $Destination | Out-File -FilePath $AfterRemoveScript -Encoding ascii } elseif ($Environment.IsDebianFamily -or $Environment.IsSUSEFamily) { - $AfterInstallScript = [io.path]::GetTempFileName() - $AfterRemoveScript = [io.path]::GetTempFileName() - $packagingStrings.UbuntuAfterInstallScript -f "$Link" | Out-File -FilePath $AfterInstallScript -Encoding ascii - $packagingStrings.UbuntuAfterRemoveScript -f "$Link" | Out-File -FilePath $AfterRemoveScript -Encoding ascii + $AfterInstallScript = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + $AfterRemoveScript = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) + $packagingStrings.UbuntuAfterInstallScript -f "$Link", $Destination | Out-File -FilePath $AfterInstallScript -Encoding ascii + $packagingStrings.UbuntuAfterRemoveScript -f "$Link", $Destination | Out-File -FilePath $AfterRemoveScript -Encoding ascii } elseif ($Environment.IsMacOS) { # NOTE: The macos pkgutil doesn't support uninstall actions so we did not implement it. # Handling uninstall can be done in Homebrew so we'll take advantage of that in the brew formula. - $AfterInstallScript = [io.path]::GetTempFileName() + $AfterInstallScript = (Join-Path $env:HOME $([System.IO.Path]::GetRandomFileName())) $packagingStrings.MacOSAfterInstallScript -f "$Link" | Out-File -FilePath $AfterInstallScript -Encoding ascii } @@ -1359,60 +1374,6 @@ function New-AfterScripts } } -function New-PSSymbolicLinks -{ - param( - [Parameter(Mandatory)] - [string] - $Distribution, - - [Parameter(Mandatory)] - [string] - $Staging - ) - - Write-Verbose -Message "PSSymLinks-Distribution: $Distribution" -Verbose - - if ($Environment.IsRedHatFamily) { - switch -regex ($Distribution) - { - # add two symbolic links to system shared libraries that libmi.so is dependent on to handle - # platform specific changes. This is the only set of platforms needed for this currently - # as Ubuntu has these specific library files in the platform and macOS builds for itself - # against the correct versions. - 'centos\.8' { - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libssl.so.1.1" -Path "$Staging/libssl.so.1.0.0" > $null - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libcrypto.so.1.1.1" -Path "$Staging/libcrypto.so.1.0.0" > $null - } - default { - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libssl.so.10" -Path "$Staging/libssl.so.1.0.0" > $null - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libcrypto.so.10" -Path "$Staging/libcrypto.so.1.0.0" > $null - } - } - } - elseif ($Environment.IsDebianFamily -or $Environment.IsSUSEFamily) { - switch -regex ($Distribution) - { - # add two symbolic links to system shared libraries that libmi.so is dependent on to handle - # platform specific changes. This appears to be a change in Debian 9; Debian 8 did not need these - # symlinks. - 'debian\.9' { - New-Item -Force -ItemType SymbolicLink -Target "/usr/lib/x86_64-linux-gnu/libssl.so.1.0.2" -Path "$Staging/libssl.so.1.0.0" > $null - New-Item -Force -ItemType SymbolicLink -Target "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.2" -Path "$Staging/libcrypto.so.1.0.0" > $null - } - 'debian\.(10|11)' { - New-Item -Force -ItemType SymbolicLink -Target "/usr/lib/x86_64-linux-gnu/libssl.so.1.1" -Path "$Staging/libssl.so.1.0.0" > $null - New-Item -Force -ItemType SymbolicLink -Target "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1" -Path "$Staging/libcrypto.so.1.0.0" > $null - } - default { - # Default to old behavior before this change - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libssl.so.10" -Path "$Staging/libssl.so.1.0.0" > $null - New-Item -Force -ItemType SymbolicLink -Target "/lib64/libcrypto.so.10" -Path "$Staging/libcrypto.so.1.0.0" > $null - } - } - } -} - function New-ManGzip { param( @@ -1613,7 +1574,9 @@ function New-ZipPackage [ValidateNotNullOrEmpty()] [string] $PackageSourcePath, - [switch] $Force + [switch] $Force, + + [string] $CurrentLocation = (Get-Location) ) $ProductSemanticVersion = Get-PackageSemanticVersion -Version $PackageVersion @@ -1625,7 +1588,7 @@ function New-ZipPackage Write-Verbose "Create Zip for Product $zipPackageName" - $zipLocationPath = Join-Path $PWD "$zipPackageName.zip" + $zipLocationPath = Join-Path $CurrentLocation "$zipPackageName.zip" if ($Force.IsPresent) { @@ -1642,8 +1605,6 @@ function New-ZipPackage $staging = "$PSScriptRoot/staging" New-StagingFolder -StagingPath $staging -PackageSourcePath $PackageSourcePath - Get-ChildItem $staging -Filter *.pdb -Recurse | Remove-Item -Force - Compress-Archive -Path $staging\* -DestinationPath $zipLocationPath } @@ -1657,7 +1618,6 @@ function New-ZipPackage throw "Failed to create $zipLocationPath" } } - #TODO: Use .NET Api to do compresss-archive equivalent if the pscmdlet is not present else { Write-Error -Message "Compress-Archive cmdlet is missing in this PowerShell version" @@ -1685,7 +1645,9 @@ function New-PdbZipPackage [Parameter(Mandatory = $true)] [string] $PackageSourcePath, - [switch] $Force + [switch] $Force, + + [string] $CurrentLocation = (Get-Location) ) $ProductSemanticVersion = Get-PackageSemanticVersion -Version $PackageVersion @@ -1697,7 +1659,7 @@ function New-PdbZipPackage Write-Verbose "Create Symbols Zip for Product $zipPackageName" - $zipLocationPath = Join-Path $PWD "$zipPackageName.zip" + $zipLocationPath = Join-Path $CurrentLocation "$zipPackageName.zip" if ($Force.IsPresent) { @@ -1727,7 +1689,6 @@ function New-PdbZipPackage throw "Failed to create $zipLocationPath" } } - #TODO: Use .NET Api to do compresss-archive equivalent if the pscmdlet is not present else { Write-Error -Message "Compress-Archive cmdlet is missing in this PowerShell version" @@ -1822,8 +1783,7 @@ function New-ILNugetPackage "Microsoft.PowerShell.SDK.dll", "Microsoft.WSMan.Management.dll", "Microsoft.WSMan.Runtime.dll", - "System.Management.Automation.dll", - "Microsoft.PowerShell.MarkdownRender.dll") + "System.Management.Automation.dll") $linuxExceptionList = @( "Microsoft.Management.Infrastructure.CimCmdlets.dll", @@ -1931,7 +1891,6 @@ function New-ILNugetPackage 'Microsoft.PowerShell.Commands.Utility' { $deps.Add([tuple]::Create([tuple]::Create('id', 'System.Management.Automation'), [tuple]::Create('version', $PackageVersion))) > $null - $deps.Add([tuple]::Create([tuple]::Create('id', 'Microsoft.PowerShell.MarkdownRender'), [tuple]::Create('version', $PackageVersion))) > $null foreach($packageInfo in (Get-ProjectPackageInformation -ProjectName $fileBaseName)) { @@ -1993,14 +1952,6 @@ function New-ILNugetPackage $deps.Add([tuple]::Create([tuple]::Create('id', $packageInfo.Name), [tuple]::Create('version', $packageInfo.Version))) > $null } } - - 'Microsoft.PowerShell.MarkdownRender' { - $deps.Add([tuple]::Create([tuple]::Create('id', 'System.Management.Automation'), [tuple]::Create('version', $PackageVersion))) > $null - foreach($packageInfo in (Get-ProjectPackageInformation -ProjectName $fileBaseName)) - { - $deps.Add([tuple]::Create([tuple]::Create('id', $packageInfo.Name), [tuple]::Create('version', $packageInfo.Version))) > $null - } - } } New-NuSpec -PackageId $fileBaseName -PackageVersion $PackageVersion -Dependency $deps -FilePath (Join-Path $filePackageFolder.FullName "$fileBaseName.nuspec") @@ -2024,7 +1975,7 @@ function New-ILNugetPackage } <# - Copy the generated reference assemblies to the 'ref/net5.0' folder properly. + Copy the generated reference assemblies to the 'ref/net6.0' folder properly. This is a helper function used by 'New-ILNugetPackage' #> function CopyReferenceAssemblies @@ -2043,24 +1994,27 @@ function CopyReferenceAssemblies switch ($assemblyName) { { $_ -in $supportedRefList } { $refDll = Join-Path -Path $refBinPath -ChildPath "$assemblyName.dll" - Copy-Item $refDll -Destination $refNugetPath -Force - Write-Log "Copied file $refDll to $refNugetPath" + $refDoc = Join-Path -Path $refBinPath -ChildPath "$assemblyName.xml" + Copy-Item $refDll, $refDoc -Destination $refNugetPath -Force + Write-Log "Copied file '$refDll' and '$refDoc' to '$refNugetPath'" } "Microsoft.PowerShell.SDK" { foreach ($asmFileName in $assemblyFileList) { $refFile = Join-Path -Path $refBinPath -ChildPath $asmFileName if (Test-Path -Path $refFile) { - Copy-Item $refFile -Destination $refNugetPath -Force - Write-Log "Copied file $refFile to $refNugetPath" + $refDoc = Join-Path -Path $refBinPath -ChildPath ([System.IO.Path]::ChangeExtension($asmFileName, "xml")) + Copy-Item $refFile, $refDoc -Destination $refNugetPath -Force + Write-Log "Copied file '$refFile' and '$refDoc' to '$refNugetPath'" } } } default { $ref_SMA = Join-Path -Path $refBinPath -ChildPath System.Management.Automation.dll - Copy-Item $ref_SMA -Destination $refNugetPath -Force - Write-Log "Copied file $ref_SMA to $refNugetPath" + $ref_doc = Join-Path -Path $refBinPath -ChildPath System.Management.Automation.xml + Copy-Item $ref_SMA, $ref_doc -Destination $refNugetPath -Force + Write-Log "Copied file '$ref_SMA' and '$ref_doc' to '$refNugetPath'" } } } @@ -2242,8 +2196,13 @@ function New-ReferenceAssembly throw "$assemblyName.dll was not found at: $Linux64BinPath" } + $dllXmlDoc = Join-Path $Linux64BinPath "$assemblyName.xml" + if (-not (Test-Path $dllXmlDoc)) { + throw "$assemblyName.xml was not found at: $Linux64BinPath" + } + $genAPIArgs = "$linuxDllPath","-libPath:$Linux64BinPath,$Linux64BinPath\ref" - Write-Log "GenAPI cmd: $genAPIExe $genAPIArgsString" + Write-Log "GenAPI cmd: $genAPIExe $genAPIArgs" Start-NativeExecution { & $genAPIExe $genAPIArgs } | Out-File $generatedSource -Force Write-Log "Reference assembly file generated at: $generatedSource" @@ -2256,10 +2215,14 @@ function New-ReferenceAssembly $sourceProjectRoot = Join-Path $PSScriptRoot "projects/reference/$assemblyName" $sourceProjectFile = Join-Path $sourceProjectRoot "$assemblyName.csproj" - Copy-Item -Path $sourceProjectFile -Destination "$projectFolder/$assemblyName.csproj" -Force - Copy-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath "../../nuget.config") -Destination $projectFolder - Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$projectFolder/$assemblyName.csproj" + $destProjectFile = Join-Path $projectFolder "$assemblyName.csproj" + $nugetConfigFile = Join-Path $PSScriptRoot "../../nuget.config" + + Copy-Item -Path $sourceProjectFile -Destination $destProjectFile -Force -Verbose + Copy-Item -Path $nugetConfigFile -Destination $projectFolder -Verbose + + Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$destProjectFile" Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$generatedSource" $arguments = GenerateBuildArguments -AssemblyName $assemblyName -RefAssemblyVersion $RefAssemblyVersion -SnkFilePath $SnkFilePath -SMAReferencePath $SMAReferenceAssembly @@ -2275,6 +2238,9 @@ function New-ReferenceAssembly Copy-Item $refBinPath $RefAssemblyDestinationPath -Force Write-Log "Reference assembly '$assemblyName.dll' built and copied to $RefAssemblyDestinationPath" + Copy-Item $dllXmlDoc $RefAssemblyDestinationPath -Force + Write-Log "Xml document '$assemblyName.xml' copied to $RefAssemblyDestinationPath" + if ($assemblyName -eq "System.Management.Automation") { $SMAReferenceAssembly = $refBinPath } @@ -2318,7 +2284,6 @@ function CleanupGeneratedSourceCode '[Microsoft.PowerShell.Commands.AddMemberCommand' '[System.Management.Automation.ArgumentCompleterAttribute(typeof(Microsoft.PowerShell.Commands.Utility.JoinItemCompleter))]' '[System.Management.Automation.ArgumentCompleterAttribute(typeof(System.Management.Automation.PropertyNameCompleter))]' - '[System.Management.Automation.OutputTypeAttribute(typeof(Microsoft.PowerShell.MarkdownRender' '[Microsoft.PowerShell.Commands.ArgumentToTypeNameTransformationAttribute]' '[System.Management.Automation.Internal.ArchitectureSensitiveAttribute]' '[Microsoft.PowerShell.Commands.SelectStringCommand.FileinfoToStringAttribute]' @@ -2375,6 +2340,11 @@ function CleanupGeneratedSourceCode Pattern = "[System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Runtime.CompilerServices.NullableContextAttribute((byte)2)]" Replacement = "/* [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Runtime.CompilerServices.NullableContextAttribute((byte)2)] */ " }, + @{ + ApplyTo = @("System.Management.Automation") + Pattern = "[System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Runtime.CompilerServices.IsReadOnlyAttribute]" + Replacement = "/* [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Runtime.CompilerServices.IsReadOnlyAttribute] */ " + }, @{ ApplyTo = @("System.Management.Automation", "Microsoft.PowerShell.ConsoleHost") Pattern = "[System.Runtime.CompilerServices.NullableAttribute((byte)2)]" @@ -2398,7 +2368,6 @@ function CleanupGeneratedSourceCode if ($assemblyName -in $patternToReplace.ApplyTo -and $line.Contains($patternToReplace.Pattern)) { $line = $line.Replace($patternToReplace.Pattern, $patternToReplace.Replacement) $lineWasProcessed = $true - break } } @@ -2603,7 +2572,6 @@ function New-NugetContentPackage $arguments = @('pack') $arguments += @('--output',$nugetFolder) $arguments += @('--configuration',$PackageConfiguration) - $arguments += @('--runtime',$PackageRuntime) $arguments += "/p:StagingPath=$stagingRoot" $arguments += "/p:RID=$PackageRuntime" $arguments += "/p:SemVer=$nugetSemanticVersion" @@ -2792,14 +2760,16 @@ function Get-WixPath $wixPyroExePath = Join-Path $wixToolsetBinPath "pyro.exe" $wixCandleExePath = Join-Path $wixToolsetBinPath "Candle.exe" $wixLightExePath = Join-Path $wixToolsetBinPath "Light.exe" + $wixInsigniaExePath = Join-Path $wixToolsetBinPath "Insignia.exe" return [PSCustomObject] @{ - WixHeatExePath = $wixHeatExePath - WixMeltExePath = $wixMeltExePath - WixTorchExePath = $wixTorchExePath - WixPyroExePath = $wixPyroExePath - WixCandleExePath = $wixCandleExePath - WixLightExePath = $wixLightExePath + WixHeatExePath = $wixHeatExePath + WixMeltExePath = $wixMeltExePath + WixTorchExePath = $wixTorchExePath + WixPyroExePath = $wixPyroExePath + WixCandleExePath = $wixCandleExePath + WixLightExePath = $wixLightExePath + WixInsigniaExePath = $wixInsigniaExePath } } @@ -2844,7 +2814,7 @@ function New-MSIPatch [Parameter(HelpMessage='Path to the patch template WXS. Usually you do not need to specify this')] [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $PatchWxsPath = "$RepoRoot\assets\patch-template.wxs", + [string] $PatchWxsPath = "$RepoRoot\assets\wix\patch-template.wxs", [Parameter(HelpMessage='Produce a delta patch instead of a full patch. Usually not worth it.')] [switch] $Delta @@ -2884,7 +2854,7 @@ function New-MSIPatch Copy-Item -Path $BaselineWixPdbPath -Destination $wixBaselineOriginalPdbPath -Force Copy-Item -Path $PatchWixPdbPath -Destination $wixPatchOriginalPdbPath -Force - [xml] $filesAssetXml = Get-Content -Raw -Path "$RepoRoot\assets\files.wxs" + [xml] $filesAssetXml = Get-Content -Raw -Path "$RepoRoot\assets\wix\files.wxs" [xml] $patchTemplateXml = Get-Content -Raw -Path $PatchWxsPath # Update the patch version @@ -2948,7 +2918,7 @@ function New-MSIPatch # This example shows how to produce a Debug-x64 installer for development purposes. cd $RootPathOfPowerShellRepo Import-Module .\build.psm1; Import-Module .\tools\packaging\packaging.psm1 - New-MSIPackage -Verbose -ProductSourcePath '.\src\powershell-win-core\bin\Debug\net5.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' + New-MSIPackage -Verbose -ProductSourcePath '.\src\powershell-win-core\bin\Debug\net6.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' #> function New-MSIPackage { @@ -2975,12 +2945,17 @@ function New-MSIPackage # File describing the MSI Package creation semantics [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $ProductWxsPath = "$RepoRoot\assets\Product.wxs", + [string] $ProductWxsPath = "$RepoRoot\assets\wix\Product.wxs", # File describing the MSI file components [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $FilesWxsPath = "$RepoRoot\assets\Files.wxs", + [string] $FilesWxsPath = "$RepoRoot\assets\wix\Files.wxs", + + # File describing the MSI Package creation semantics + [ValidateNotNullOrEmpty()] + [ValidateScript({Test-Path $_})] + [string] $BundleWxsPath = "$RepoRoot\assets\wix\bundle.wxs", # Path to Assets folder containing artifacts such as icons, images [ValidateNotNullOrEmpty()] @@ -2994,13 +2969,22 @@ function New-MSIPackage [string] $ProductTargetArchitecture, # Force overwrite of package - [Switch] $Force + [Switch] $Force, + + [string] $CurrentLocation = (Get-Location) ) $wixPaths = Get-WixPath - $ProductSemanticVersion = Get-PackageSemanticVersion -Version $ProductVersion - $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion + $windowsNames = Get-WindowsNames -ProductName $ProductName -ProductNameSuffix $ProductNameSuffix -ProductVersion $ProductVersion + $productSemanticVersionWithName = $windowsNames.ProductSemanticVersionWithName + $ProductSemanticVersion = $windowsNames.ProductSemanticVersion + $packageName = $windowsNames.PackageName + $ProductVersion = $windowsNames.ProductVersion + Write-Verbose "Create MSI for Product $productSemanticVersionWithName" -Verbose + Write-Verbose "ProductSemanticVersion = $productSemanticVersion" -Verbose + Write-Verbose "packageName = $packageName" -Verbose + Write-Verbose "ProductVersion = $ProductVersion" -Verbose $simpleProductVersion = [string]([Version]$ProductVersion).Major $isPreview = Test-IsPreview -Version $ProductSemanticVersion @@ -3012,8 +2996,6 @@ function New-MSIPackage $staging = "$PSScriptRoot/staging" New-StagingFolder -StagingPath $staging -PackageSourcePath $ProductSourcePath - Get-ChildItem $staging -Filter *.pdb -Recurse | Remove-Item -Force - $assetsInSourcePath = Join-Path $staging 'assets' New-Item $assetsInSourcePath -type directory -Force | Write-Verbose @@ -3021,10 +3003,7 @@ function New-MSIPackage Write-Verbose "Place dependencies such as icons to $assetsInSourcePath" Copy-Item "$AssetsPath\*.ico" $assetsInSourcePath -Force - $productVersionWithName = $ProductName + '_' + $ProductVersion - $productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion - Write-Verbose "Create MSI for Product $productSemanticVersionWithName" $fileArchitecture = 'amd64' $ProductProgFilesDir = "ProgramFiles64Folder" @@ -3039,15 +3018,10 @@ function New-MSIPackage # cleanup any garbage on the system Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force - $packageName = $productSemanticVersionWithName - if ($ProductNameSuffix) { - $packageName += "-$ProductNameSuffix" - } - $msiLocationPath = Join-Path $PWD "$packageName.msi" - $msiPdbLocationPath = Join-Path $PWD "$packageName.wixpdb" + $msiLocationPath = Join-Path $CurrentLocation "$packageName.msi" + $msiPdbLocationPath = Join-Path $CurrentLocation "$packageName.wixpdb" - if (!$Force.IsPresent -and (Test-Path -Path $msiLocationPath)) - { + if (!$Force.IsPresent -and (Test-Path -Path $msiLocationPath)) { Write-Error -Message "Package already exists, use -Force to overwrite, path: $msiLocationPath" -ErrorAction Stop } @@ -3105,6 +3079,158 @@ function New-MSIPackage } } +function Get-WindowsNames { + param( + # Name of the Product + [ValidateNotNullOrEmpty()] + [string] $ProductName = 'PowerShell', + + # Suffix of the Name + [string] $ProductNameSuffix, + + # Version of the Product + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $ProductVersion + ) + + Write-Verbose -Message "Getting Windows Names for ProductName: $ProductName; ProductNameSuffix: $ProductNameSuffix; ProductVersion: $ProductVersion" -Verbose + + $ProductSemanticVersion = Get-PackageSemanticVersion -Version $ProductVersion + $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion + + $productVersionWithName = $ProductName + '_' + $ProductVersion + $productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion + + $packageName = $productSemanticVersionWithName + if ($ProductNameSuffix) { + $packageName += "-$ProductNameSuffix" + } + + return [PSCustomObject]@{ + PackageName = $packageName + ProductVersionWithName = $productVersionWithName + ProductSemanticVersion = $ProductSemanticVersion + ProductSemanticVersionWithName = $productSemanticVersionWithName + ProductVersion = $ProductVersion + } +} + +function New-ExePackage { + param( + # Name of the Product + [ValidateNotNullOrEmpty()] + [string] $ProductName = 'PowerShell', + + # Version of the Product + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + + [string] $ProductVersion, + + # File describing the MSI Package creation semantics + [ValidateNotNullOrEmpty()] + [ValidateScript({Test-Path $_})] + [string] $BundleWxsPath = "$RepoRoot\assets\wix\bundle.wxs", + + # Architecture to use when creating the MSI + [Parameter(Mandatory = $true)] + [ValidateSet("x86", "x64")] + [ValidateNotNullOrEmpty()] + [string] $ProductTargetArchitecture, + + # Location of the signed MSI + [Parameter(Mandatory = $true)] + [string] + $MsiLocationPath, + + [string] $CurrentLocation = (Get-Location) + ) + + $productNameSuffix = "win-$ProductTargetArchitecture" + + $windowsNames = Get-WindowsNames -ProductName $ProductName -ProductNameSuffix $productNameSuffix -ProductVersion $ProductVersion + $productSemanticVersionWithName = $windowsNames.ProductSemanticVersionWithName + $packageName = $windowsNames.PackageName + $isPreview = Test-IsPreview -Version $windowsNames.ProductSemanticVersion + + Write-Verbose "Create EXE for Product $productSemanticVersionWithName" -verbose + Write-Verbose "packageName = $packageName" -Verbose + + $exeLocationPath = Join-Path $CurrentLocation "$packageName.exe" + $exePdbLocationPath = Join-Path $CurrentLocation "$packageName.exe.wixpdb" + $windowsVersion = Get-WindowsVersion -packageName $packageName + + Start-MsiBuild -WxsFile $BundleWxsPath -ProductTargetArchitecture $ProductTargetArchitecture -Argument @{ + IsPreview = $isPreview + TargetPath = $MsiLocationPath + WindowsVersion = $windowsVersion + } -MsiLocationPath $exeLocationPath -MsiPdbLocationPath $exePdbLocationPath + + return $exeLocationPath +} + +<# +Allows you to extract the engine of exe package, mainly for signing +Any existing signature will be removed. + #> +function Expand-ExePackageEngine { + param( + # Location of the unsigned EXE + [Parameter(Mandatory = $true)] + [string] + $ExePath, + + # Location to put the expanded engine. + [Parameter(Mandatory = $true)] + [string] + $EnginePath + ) + + <# + 2. detach the engine from TestInstaller.exe: + insignia -ib TestInstaller.exe -o engine.exe + #> + + $wixPaths = Get-WixPath + + $resolvedExePath = (Resolve-Path -Path $ExePath).ProviderPath + $resolvedEnginePath = [System.IO.Path]::GetFullPath($EnginePath) + + Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixInsigniaExePath -ib $resolvedExePath -o $resolvedEnginePath} +} + +<# +Allows you to replace the engine (installer) in the exe package. +Used to replace the engine with a signed version +#> +function Compress-ExePackageEngine { + param( + # Location of the unsigned EXE + [Parameter(Mandatory = $true)] + [string] + $ExePath, + + # Location of the signed engine + [Parameter(Mandatory = $true)] + [string] + $EnginePath + ) + + + <# + 4. re-attach the signed engine.exe to the bundle: + insignia -ab engine.exe TestInstaller.exe -o TestInstaller.exe + #> + + $wixPaths = Get-WixPath + + $resolvedEnginePath = (Resolve-Path -Path $EnginePath).ProviderPath + $resolvedExePath = (Resolve-Path -Path $ExePath).ProviderPath + + Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixInsigniaExePath -ab $resolvedEnginePath $resolvedExePath -o $resolvedExePath} +} + function New-MsiArgsArray { param( [Parameter(Mandatory)] @@ -3165,7 +3291,8 @@ function Start-MsiBuild { Write-Log "running light..." # suppress ICE61, because we allow same version upgrades # suppress ICE57, this suppresses an error caused by our shortcut not being installed per user - Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixLightExePath -sice:ICE61 -sice:ICE57 -out $msiLocationPath -pdbout $msiPdbLocationPath $objectPaths $extensionArgs } + # suppress ICE40, REINSTALLMODE is defined in the Property table. + Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixLightExePath -sice:ICE61 -sice:ICE40 -sice:ICE57 -out $msiLocationPath -pdbout $msiPdbLocationPath $objectPaths $extensionArgs } foreach($file in $objectPaths) { @@ -3182,7 +3309,7 @@ function Start-MsiBuild { # This example shows how to produce a Debug-x64 installer for development purposes. cd $RootPathOfPowerShellRepo Import-Module .\build.psm1; Import-Module .\tools\packaging\packaging.psm1 - New-MSIXPackage -Verbose -ProductSourcePath '.\src\powershell-win-core\bin\Debug\net5.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' + New-MSIXPackage -Verbose -ProductSourcePath '.\src\powershell-win-core\bin\Debug\net6.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' #> function New-MSIXPackage { @@ -3212,7 +3339,9 @@ function New-MSIXPackage [string] $Architecture, # Force overwrite of package - [Switch] $Force + [Switch] $Force, + + [string] $CurrentLocation = (Get-Location) ) $makeappx = Get-Command makeappx -CommandType Application -ErrorAction Ignore @@ -3251,27 +3380,7 @@ function New-MSIXPackage Write-Verbose -Verbose "ProductName: $productName" Write-Verbose -Verbose "DisplayName: $displayName" - $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion - if (([Version]$ProductVersion).Revision -eq -1) { - $ProductVersion += ".0" - } - - # The Store requires the last digit of the version to be 0 so we swap the build and revision - # This only affects Preview versions where the last digit is the preview number - # For stable versions, the last digit is already zero so no changes - $pversion = [version]$ProductVersion - if ($pversion.Revision -ne 0) { - $revision = $pversion.Revision - if ($packageName.Contains('-rc')) { - # For Release Candidates, we use numbers in the 100 range - $revision += 100 - } - - $pversion = [version]::new($pversion.Major, $pversion.Minor, $revision, 0) - $ProductVersion = $pversion.ToString() - } - - Write-Verbose "Version: $productversion" -Verbose + $ProductVersion = Get-WindowsVersion -PackageName $packageName $isPreview = Test-IsPreview -Version $ProductSemanticVersion if ($isPreview) { @@ -3317,7 +3426,7 @@ function New-MSIXPackage Start-NativeExecution -VerboseOutputOnError { & $makepri new /v /o /pr $ProductSourcePath /cf (Join-Path $ProductSourcePath "priconfig.xml") } Pop-Location Write-Verbose "Creating msix package" -Verbose - Start-NativeExecution -VerboseOutputOnError { & $makeappx pack /o /v /h SHA256 /d $ProductSourcePath /p (Join-Path -Path $PWD -ChildPath "$packageName.msix") } + Start-NativeExecution -VerboseOutputOnError { & $makeappx pack /o /v /h SHA256 /d $ProductSourcePath /p (Join-Path -Path $CurrentLocation -ChildPath "$packageName.msix") } Write-Verbose "Created $packageName.msix" -Verbose } } @@ -3331,7 +3440,7 @@ function Test-FileWxs # File describing the MSI file components from the asset folder [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $FilesWxsPath = "$RepoRoot\assets\Files.wxs", + [string] $FilesWxsPath = "$RepoRoot\assets\wix\Files.wxs", # File describing the MSI file components generated by heat [ValidateNotNullOrEmpty()] @@ -3601,6 +3710,36 @@ function New-WixId "$Prefix$guidPortion" } +function Get-WindowsVersion { + param ( + [parameter(Mandatory)] + [string]$PackageName + ) + + $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion + if (([Version]$ProductVersion).Revision -eq -1) { + $ProductVersion += ".0" + } + + # The Store requires the last digit of the version to be 0 so we swap the build and revision + # This only affects Preview versions where the last digit is the preview number + # For stable versions, the last digit is already zero so no changes + $pversion = [version]$ProductVersion + if ($pversion.Revision -ne 0) { + $revision = $pversion.Revision + if ($packageName.Contains('-rc')) { + # For Release Candidates, we use numbers in the 100 range + $revision += 100 + } + + $pversion = [version]::new($pversion.Major, $pversion.Minor, $revision, 0) + $ProductVersion = $pversion.ToString() + } + + Write-Verbose "Version: $productversion" -Verbose + return $productversion +} + # Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f' # This function converts the above version into major.minor[.build[.revision]] format function Get-PackageVersionAsMajorMinorBuildRevision @@ -3617,7 +3756,7 @@ function Get-PackageVersionAsMajorMinorBuildRevision $packageVersionTokens = $Version.Split('-') $packageVersion = ([regex]::matches($Version, "\d+(\.\d+)+"))[0].value - if (1 -eq $packageVersionTokens.Count) { + if (1 -eq $packageVersionTokens.Count -and ([Version]$packageVersion).Revision -eq -1) { # In case the input is of the form a.b.c, add a '0' at the end for revision field $packageVersion = $packageVersion + '.0' } elseif (1 -lt $packageVersionTokens.Count) { @@ -3744,8 +3883,16 @@ function New-GlobalToolNupkg $packageInfo = @() - Remove-Item -Path (Join-Path $LinuxBinPath 'libcrypto.so.1.0.0') -Verbose -Force -Recurse - Remove-Item -Path (Join-Path $LinuxBinPath 'libssl.so.1.0.0') -Verbose -Force -Recurse + $libCryptoPath = Join-Path $LinuxBinPath 'libcrypto.so.1.0.0' + $libSSLPath = Join-Path $LinuxBinPath 'libssl.so.1.0.0' + + if (Test-Path $libCryptoPath) { + Remove-Item -Path $libCryptoPath -Verbose -Force + } + + if (Test-Path $libSSLPath) { + Remove-Item -Path $libSSLPath -Verbose -Force + } ## Remove unnecessary xml files Get-ChildItem -Path $LinuxBinPath, $WindowsBinPath, $WindowsDesktopBinPath -Filter *.xml | Remove-Item -Verbose @@ -3877,3 +4024,237 @@ function New-GlobalToolNupkg New-NugetPackage -NuSpecPath $_.RootFolder -PackageDestinationPath $DestinationPath } } + +${mainLinuxBuildFolder} = 'pwshLinuxBuild' +${minSizeLinuxBuildFolder} = 'pwshLinuxBuildMinSize' +${arm32LinuxBuildFolder} = 'pwshLinuxBuildArm32' +${arm64LinuxBuildFolder} = 'pwshLinuxBuildArm64' + +<# + Used in Azure DevOps Yaml to package all the linux packages for a channel. +#> +function Invoke-AzDevOpsLinuxPackageCreation { + param( + [switch] + $LTS, + + [Parameter(Mandatory)] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] + [ValidateNotNullOrEmpty()] + [string]$ReleaseTag, + + [Parameter(Mandatory)] + [ValidateSet('fxdependent', 'alpine', 'deb', 'rpm')] + [String]$BuildType + ) + + if (!${env:SYSTEM_ARTIFACTSDIRECTORY}) { + throw "Must be run in Azure DevOps" + } + + try { + Write-Verbose "Packaging '$BuildType'-LTS:$LTS for $ReleaseTag ..." -Verbose + + Restore-PSOptions -PSOptionsPath "${env:SYSTEM_ARTIFACTSDIRECTORY}\${mainLinuxBuildFolder}-meta\psoptions.json" + + $releaseTagParam = @{ 'ReleaseTag' = $ReleaseTag } + + switch ($BuildType) { + 'fxdependent' { + Start-PSPackage -Type 'fxdependent' @releaseTagParam -LTS:$LTS + } + 'alpine' { + Start-PSPackage -Type 'tar-alpine' @releaseTagParam -LTS:$LTS + } + 'rpm' { + Start-PSPackage -Type 'rpm' @releaseTagParam -LTS:$LTS + } + default { + Start-PSPackage @releaseTagParam -LTS:$LTS -Type 'deb', 'tar' + } + } + + if ($BuildType -eq 'deb') { + Start-PSPackage -Type tar @releaseTagParam -LTS:$LTS + + Restore-PSOptions -PSOptionsPath "${env:SYSTEM_ARTIFACTSDIRECTORY}\${minSizeLinuxBuildFolder}-meta\psoptions.json" + + Write-Verbose -Verbose "---- Min-Size ----" + Write-Verbose -Verbose "options.Output: $($options.Output)" + Write-Verbose -Verbose "options.Top $($options.Top)" + + Start-PSPackage -Type min-size @releaseTagParam -LTS:$LTS + + ## Create 'linux-arm' 'tar.gz' package. + ## Note that 'linux-arm' can only be built on Ubuntu environment. + Restore-PSOptions -PSOptionsPath "${env:SYSTEM_ARTIFACTSDIRECTORY}\${arm32LinuxBuildFolder}-meta\psoptions.json" + Start-PSPackage -Type tar-arm @releaseTagParam -LTS:$LTS + + ## Create 'linux-arm64' 'tar.gz' package. + ## Note that 'linux-arm64' can only be built on Ubuntu environment. + Restore-PSOptions -PSOptionsPath "${env:SYSTEM_ARTIFACTSDIRECTORY}\${arm64LinuxBuildFolder}-meta\psoptions.json" + Start-PSPackage -Type tar-arm64 @releaseTagParam -LTS:$LTS + } + } + catch { + Get-Error + throw + } +} + +<# + Used in Azure DevOps Yaml to do all the builds needed for all Linux packages for a channel. +#> +function Invoke-AzDevOpsLinuxPackageBuild { + param ( + [Parameter(Mandatory)] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] + [ValidateNotNullOrEmpty()] + [string]$ReleaseTag, + + [Parameter(Mandatory)] + [ValidateSet('fxdependent', 'alpine', 'deb', 'rpm')] + [String]$BuildType + ) + + if (!${env:SYSTEM_ARTIFACTSDIRECTORY}) { + throw "Must be run in Azure DevOps" + } + + try { + + Write-Verbose "Building '$BuildType' for $ReleaseTag ..." -Verbose + + $releaseTagParam = @{ 'ReleaseTag' = $ReleaseTag } + + $buildParams = @{ Configuration = 'Release'; PSModuleRestore = $true; Restore = $true } + + switch ($BuildType) { + 'fxdependent' { + $buildParams.Add("Runtime", "fxdependent") + } + 'alpine' { + $buildParams.Add("Runtime", 'alpine-x64') + # We are cross compiling, so we can't generate experimental features + $buildParams.Add("SkipExperimentalFeatureGeneration", $true) + } + } + + $buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/${mainLinuxBuildFolder}" + Start-PSBuild @buildParams @releaseTagParam -Output $buildFolder -PSOptionsPath "${buildFolder}-meta/psoptions.json" + # Remove symbol files. + Remove-Item "${buildFolder}\*.pdb" -Force + + if ($BuildType -eq 'deb') { + ## Build 'min-size' + $options = Get-PSOptions + Write-Verbose -Verbose "---- Min-Size ----" + Write-Verbose -Verbose "options.Output: $($options.Output)" + Write-Verbose -Verbose "options.Top $($options.Top)" + $binDir = Join-Path -Path $options.Top -ChildPath 'bin' + if (Test-Path -Path $binDir) { + Write-Verbose -Verbose "Remove $binDir, to get a clean build for min-size package" + Remove-Item -Path $binDir -Recurse -Force + } + + $buildParams['ForMinimalSize'] = $true + $buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/${minSizeLinuxBuildFolder}" + Start-PSBuild -Clean @buildParams @releaseTagParam -Output $buildFolder -PSOptionsPath "${buildFolder}-meta/psoptions.json" + # Remove symbol files, xml document files. + Remove-Item "${buildFolder}\*.pdb", "${buildFolder}\*.xml" -Force + + + ## Build 'linux-arm' and create 'tar.gz' package for it. + ## Note that 'linux-arm' can only be built on Ubuntu environment. + $buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/${arm32LinuxBuildFolder}" + Start-PSBuild -Configuration Release -Restore -Runtime linux-arm -PSModuleRestore @releaseTagParam -Output $buildFolder -PSOptionsPath "${buildFolder}-meta/psoptions.json" + # Remove symbol files. + Remove-Item "${buildFolder}\*.pdb" -Force + + $buildFolder = "${env:SYSTEM_ARTIFACTSDIRECTORY}/${arm64LinuxBuildFolder}" + Start-PSBuild -Configuration Release -Restore -Runtime linux-arm64 -PSModuleRestore @releaseTagParam -Output $buildFolder -PSOptionsPath "${buildFolder}-meta/psoptions.json" + # Remove symbol files. + Remove-Item "${buildFolder}\*.pdb" -Force + } + } + catch { + Get-Error + throw + } +} + +enum PackageManifestResultStatus { + Mismatch + Match + MissingFromManifest + MissingFromPackage +} + +class PackageManifestResult { + [string] $File + [string] $ExpectedHash + [string] $ActualHash + [PackageManifestResultStatus] $Status +} + +function Test-PackageManifest { + param ( + [Parameter(Mandatory)] + [string] + $PackagePath + ) + + Begin { + $spdxManifestPath = Join-Path $PackagePath -ChildPath "/_manifest/spdx_2.2/manifest.spdx.json" + $man = Get-Content $spdxManifestPath -ErrorAction Stop | convertfrom-json + $inManifest = @() + } + + Process { + Write-Verbose "Processing $($man.files) files..." -verbose + $man.files | ForEach-Object { + $filePath = Join-Path $PackagePath -childPath $_.fileName + $checksumObj = $_.checksums | Where-Object {$_.algorithm -eq 'sha256'} + $sha256 = $checksumObj.checksumValue + $actualHash = $null + $actualHash = (Get-FileHash -Path $filePath -Algorithm sha256 -ErrorAction SilentlyContinue).Hash + $inManifest += $filePath + if($actualHash -ne $sha256) { + $status = [PackageManifestResultStatus]::Mismatch + if (!$actualHash) { + $status = [PackageManifestResultStatus]::MissingFromPackage + } + [PackageManifestResult] $result = @{ + File = $filePath + ExpectedHash = $sha256 + ActualHash = $actualHash + Status = $status + } + Write-Output $result + } + else { + [PackageManifestResult] $result = @{ + File = $filePath + ExpectedHash = $sha256 + ActualHash = $actualHash + Status = [PackageManifestResultStatus]::Match + } + Write-Output $result + } + } + + + Get-ChildItem $PackagePath -recurse | Select-Object -ExpandProperty FullName | foreach-object { + if(!$inManifest -contains $_) { + $actualHash = (get-filehash -Path $_ -algorithm sha256 -erroraction silentlycontinue).Hash + [PackageManifestResult] $result = @{ + File = $_ + ExpectedHash = $null + ActualHash = $actualHash + Status = [PackageManifestResultStatus]::MissingFromManifest + } + Write-Output $result + } + } + } +} diff --git a/tools/packaging/packaging.strings.psd1 b/tools/packaging/packaging.strings.psd1 index 444bfa7f3a0..7a06855442d 100644 --- a/tools/packaging/packaging.strings.psd1 +++ b/tools/packaging/packaging.strings.psd1 @@ -11,6 +11,14 @@ if [ ! -f /etc/shells ] ; then else grep -q "^{0}$" /etc/shells || echo "{0}" >> /etc/shells fi +if [ -f /lib64/libssl.so.1.1 ] ; then + ln -f -s /lib64/libssl.so.1.1 {1}/libssl.so.1.0.0 + ln -f -s /lib64/libcrypto.so.1.1.1 {1}/libcrypto.so.1.0.0 +else + ln -f -s /lib64/libssl.so.10 {1}/libssl.so.1.0.0 + ln -f -s /lib64/libcrypto.so.10 {1}/libcrypto.so.1.0.0 +fi + '@ RedHatAfterRemoveScript = @' @@ -20,6 +28,8 @@ if [ "$1" = 0 ] ; then grep -v '^{0}$' /etc/shells > $TmpFile cp -f $TmpFile /etc/shells rm -f $TmpFile + rm -f {1}/libssl.so.1.0.0 + rm -f {1}/libcrypto.so.1.0.0 fi fi '@ @@ -38,6 +48,18 @@ case "$1" in exit 0 ;; esac + +if [ -f /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ] ; then + ln -f -s /usr/lib/x86_64-linux-gnu/libssl.so.1.1 {1}/libssl.so.1.0.0 + ln -f -s /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 {1}/libcrypto.so.1.0.0 +elif [ -f /usr/lib/x86_64-linux-gnu/libssl.so.1.0.2 ] ; then + ln -f -s /usr/lib/x86_64-linux-gnu/libssl.so.1.0.2 {1}/libssl.so.1.0.0 + ln -f -s /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.2 {1}/libcrypto.so.1.0.0 +else + ln -f -s /lib64/libssl.so.10 {1}/libssl.so.1.0.0 + ln -f -s /lib64/libcrypto.so.10 {1}/libcrypto.so.1.0.0 +fi + '@ UbuntuAfterRemoveScript = @' @@ -46,6 +68,8 @@ set -e case "$1" in (remove) remove-shell "{0}" + rm -f {1}/libssl.so.1.0.0 + rm -f {1}/libcrypto.so.1.0.0 ;; esac '@ @@ -142,7 +166,7 @@ open {0} <files include="**/*" buildAction="None" copyToOutput="true" flatten="false" /> </contentFiles> <dependencies> - <group targetFramework="net5.0"></group> + <group targetFramework="net6.0"></group> </dependencies> </metadata> </package> diff --git a/tools/packaging/projects/nuget/package.csproj b/tools/packaging/projects/nuget/package.csproj index e20f5a13523..cee634e2ffa 100644 --- a/tools/packaging/projects/nuget/package.csproj +++ b/tools/packaging/projects/nuget/package.csproj @@ -11,6 +11,6 @@ <NuspecProperties>runtime=$(RID);version=$(SemVer);PackageName=$(PackageName)</NuspecProperties> <NuspecBasePath>$(StagingPath)</NuspecBasePath> <IsTool>True</IsTool> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> </PropertyGroup> </Project> diff --git a/tools/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj b/tools/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj index 0dc3e0f6720..53eee6e16db 100644 --- a/tools/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/tools/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <Version>$(RefAsmVersion)</Version> <DelaySign>true</DelaySign> <AssemblyOriginatorKeyFile>$(SnkFile)</AssemblyOriginatorKeyFile> @@ -13,7 +13,8 @@ </Reference> </ItemGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> - <PackageReference Include="System.Security.AccessControl" Version="5.0.0-rc.1.20451.14" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> + <PackageReference Include="System.Security.AccessControl" Version="6.0.0" /> + <PackageReference Include="Microsoft.PowerShell.MarkdownRender" Version="7.2.0" /> </ItemGroup> </Project> diff --git a/tools/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj b/tools/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj index b393fe1cd2b..a95a2a47cac 100644 --- a/tools/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj +++ b/tools/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <Version>$(RefAsmVersion)</Version> <DelaySign>true</DelaySign> <AssemblyOriginatorKeyFile>$(SnkFile)</AssemblyOriginatorKeyFile> diff --git a/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj b/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj index 3651a22939e..e382b8cbb33 100644 --- a/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj +++ b/tools/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <Version>$(RefAsmVersion)</Version> <DelaySign>true</DelaySign> <AssemblyOriginatorKeyFile>$(SnkFile)</AssemblyOriginatorKeyFile> @@ -9,7 +9,6 @@ </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Management.Infrastructure" Version="2.0.0" /> - <PackageReference Include="System.Security.AccessControl" Version="5.0.0-rc.1.20451.14" /> - <PackageReference Include="System.Security.Principal.Windows" Version="5.0.0-rc.1.20451.14" /> + <PackageReference Include="System.Security.AccessControl" Version="6.0.0" /> </ItemGroup> </Project> diff --git a/tools/packaging/releaseTests/sbom.tests.ps1 b/tools/packaging/releaseTests/sbom.tests.ps1 new file mode 100644 index 00000000000..0e64e6c5042 --- /dev/null +++ b/tools/packaging/releaseTests/sbom.tests.ps1 @@ -0,0 +1,110 @@ +Describe "Verify SBOMs" { + BeforeAll { + Write-Verbose "In Describe BeforeAll" -Verbose + Import-Module $PSScriptRoot/../../../build.psm1 + Import-Module $PSScriptRoot/../packaging.psd1 -Force + $matchCases = @() + $testCases = @() + $missingFromPackageCases = @() + $missingFromManifestCases = @() + Write-Verbose "${env:PACKAGE_FOLDER}" -Verbose + Get-ChildItem $env:PACKAGE_FOLDER -Filter *.zip | ForEach-Object { + Write-Verbose "Found $($_.Name)..." -Verbose + $testCases += @{ + FilePath = $_.FullName + Name = $_.Name + } + } + + foreach($case in $testCases) { + $name = $case.Name + Write-Verbose "Testing $name..." -Verbose + $extractedPath = Join-Path Testdrive:\ -ChildPath ([System.io.path]::GetRandomFileName()) + $null = New-Item -Path $extractedPath -ItemType Directory -Force + Expand-Archive -Path $case.FilePath -DestinationPath $extractedPath + $manifestPath = Join-Path $extractedPath -ChildPath '/_manifest/spdx_2.2/manifest.spdx.json' + It "$name has a BOM" { + $manifestPath | Should -Exist + } + Test-PackageManifest -PackagePath $extractedPath | ForEach-Object { + $status = $_.Status + $expectedHash = $_.ExpectedHash + $actual = $_.ActualHash + $file = $_.File + + switch($status) { + # cover match and mismatch + default { + $matchCases += @{ + Name = $name + File = $file + ActualHash = $actual + ExpectedHash = $ExpectedHash + Status = $status + } + } + "MissingFromPackage" { + $missingFromPackageCases = @{ + Name = $name + File = $file + ActualHash = $actual + ExpectedHash = $ExpectedHash + Status = $status + } + } + "MissingFromManifest" { + $missingFromManifestCases = @{ + Name = $name + File = $file + ActualHash = $actual + ExpectedHash = $ExpectedHash + Status = $status + } + } + } + } + } + } + + Context "Zip files" { + BeforeAll { + Write-Verbose "In Context BeforeAll" -Verbose + } + + It "<name> should have <file> with matching hash" -TestCases $matchCases { + param( + $Name, + $File, + $ActualHash, + $ExpectedHash, + $Status + ) + + $status | Should -Be "Match" -Because "$actualHash should be $expectedHash" + } + + It "<name> should have <file> with matching hash" -TestCases $missingFromPackageCases -Skip:($missingFromPackageCases.Count -eq 0) { + param( + $Name, + $File, + $ActualHash, + $ExpectedHash, + $Status + ) + + $status | Should -Be "Match" -Because "All files in manifest should exist in package" + } + + It "Manifest for <name> should have <file>" -TestCases $missingFromManifestCases -Skip:($missingFromManifestCases.Count -eq 0) { + param( + $Name, + $File, + $ActualHash, + $ExpectedHash, + $Status + ) + + $status | Should -Be "Match" -Because "All files in package should exist in manifest" + } + } +} diff --git a/tools/releaseBuild/Images/GenericLinuxFiles/PowerShellPackage.ps1 b/tools/releaseBuild/Images/GenericLinuxFiles/PowerShellPackage.ps1 index 9ace6f720aa..f96263ea6e8 100644 --- a/tools/releaseBuild/Images/GenericLinuxFiles/PowerShellPackage.ps1 +++ b/tools/releaseBuild/Images/GenericLinuxFiles/PowerShellPackage.ps1 @@ -11,13 +11,14 @@ param ( # Destination location of the package on docker host [string] $destination = '/mnt', - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [ValidateNotNullOrEmpty()] [string]$ReleaseTag, [switch]$TarX64, [switch]$TarArm, [switch]$TarArm64, + [switch]$TarMinSize, [switch]$FxDependent, [switch]$Alpine ) @@ -34,7 +35,7 @@ $semVersion = [System.Management.Automation.SemanticVersion] $version $metadata = Get-Content "$location/tools/metadata.json" -Raw | ConvertFrom-Json -$LTS = $metadata.LTSRelease +$LTS = $metadata.LTSRelease.Package Write-Verbose -Verbose -Message "LTS is set to: $LTS" @@ -62,10 +63,10 @@ function BuildPackages { } else { # make the artifact name unique $projectAssetsZipName = "linuxProjectAssets-$((Get-Date).Ticks)-symbols.zip" - $buildParams.Add("Crossgen", $true) } Start-PSBuild @buildParams @releaseTagParam + $options = Get-PSOptions if ($FxDependent) { Start-PSPackage -Type 'fxdependent' @releaseTagParam -LTS:$LTS @@ -77,6 +78,21 @@ function BuildPackages { if ($TarX64) { Start-PSPackage -Type tar @releaseTagParam -LTS:$LTS } + if ($TarMinSize) { + Write-Verbose -Verbose "---- Min-Size ----" + Write-Verbose -Verbose "options.Output: $($options.Output)" + Write-Verbose -Verbose "options.Top $($options.Top)" + + $binDir = Join-Path -Path $options.Top -ChildPath 'bin' + Write-Verbose -Verbose "Remove $binDir, to get a clean build for min-size package" + Remove-Item -Path $binDir -Recurse -Force + + ## Build 'min-size' and create 'tar.gz' package for it. + $buildParams['ForMinimalSize'] = $true + Start-PSBuild @buildParams @releaseTagParam + Start-PSPackage -Type min-size @releaseTagParam -LTS:$LTS + } + if ($TarArm) { ## Build 'linux-arm' and create 'tar.gz' package for it. ## Note that 'linux-arm' can only be built on Ubuntu environment. diff --git a/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile b/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile index c0541b7bbd8..fb1070fcd52 100644 --- a/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile +++ b/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile @@ -1,6 +1,6 @@ # Docker image file that describes an Centos7 image with PowerShell installed from Microsoft YUM Repo -FROM mcr.microsoft.com/powershell:alpine-3.8 +FROM mcr.microsoft.com/powershell:alpine-3.12 LABEL maintainer="PowerShell Team <powershellteam@hotmail.com>" # Install dependencies and clean up diff --git a/tools/releaseBuild/Images/microsoft_powershell_centos7/Dockerfile b/tools/releaseBuild/Images/microsoft_powershell_centos7/Dockerfile index 25a225dd67f..e0a3946c3c4 100644 --- a/tools/releaseBuild/Images/microsoft_powershell_centos7/Dockerfile +++ b/tools/releaseBuild/Images/microsoft_powershell_centos7/Dockerfile @@ -19,6 +19,7 @@ RUN yum install -y \ which \ curl \ git \ + wget \ && yum clean all COPY PowerShellPackage.ps1 / diff --git a/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 b/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 index e90e4220ffc..40fe755cd68 100644 --- a/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 +++ b/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 @@ -12,20 +12,22 @@ param ( [string] $destination = "$env:WORKSPACE", [ValidateSet("win7-x64", "win7-x86", "win-arm", "win-arm64", "fxdependent", "fxdependent-win-desktop")] - [string]$Runtime = 'win7-x64', + [string] $Runtime = 'win7-x64', + + [switch] $ForMinimalSize, [switch] $Wait, - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [ValidateNotNullOrEmpty()] - [string]$ReleaseTag, + [string] $ReleaseTag, [Parameter(Mandatory,ParameterSetName='IncludeSymbols')] [switch] $Symbols, [Parameter(Mandatory,ParameterSetName='packageSigned')] [ValidatePattern("-signed.zip$")] - [string]$BuildZip, + [string] $BuildZip, [Parameter(Mandatory,ParameterSetName='ComponentRegistration')] [switch] $ComponentRegistration @@ -63,7 +65,8 @@ if ($memoryMB -lt $requiredMemoryMB) } Write-Verbose "Running with $memoryMB MB memory." -Verbose -try{ +try +{ Set-Location $location Import-Module "$location\build.psm1" -Force @@ -93,9 +96,11 @@ try{ else { Write-Verbose "Starting powershell build for RID: $Runtime and ReleaseTag: $ReleaseTag ..." -Verbose - $buildParams = @{'CrossGen'= $Runtime -notmatch "arm" -and $Runtime -notlike "fxdependent*"} + $buildParams = @{ + ForMinimalSize = $ForMinimalSize + } - if($Symbols.IsPresent) + if($Symbols) { $buildParams['NoPSModuleRestore'] = $true } @@ -107,58 +112,62 @@ try{ Start-PSBuild -Clean -Runtime $Runtime -Configuration Release @releaseTagParam @buildParams } - if ($Runtime -eq 'fxdependent') + if ($ComponentRegistration) { - $pspackageParams = @{'Type'='fxdependent'} + Write-Verbose "Exporting project.assets files ..." -Verbose + + $projectAssetsCounter = 1 + $projectAssetsFolder = Join-Path -Path $destination -ChildPath 'projectAssets' + $projectAssetsZip = Join-Path -Path $destination -ChildPath 'windowsProjectAssetssymbols.zip' + Get-ChildItem $location\project.assets.json -Recurse | ForEach-Object { + $subfolder = $_.FullName.Replace($location,'') + $subfolder.Replace('project.assets.json','') + $itemDestination = Join-Path -Path $projectAssetsFolder -ChildPath $subfolder + New-Item -Path $itemDestination -ItemType Directory -Force > $null + $file = $_.FullName + Write-Verbose "Copying $file to $itemDestination" -Verbose + Copy-Item -Path $file -Destination "$itemDestination\" -Force + $projectAssetsCounter++ + } + + Compress-Archive -Path $projectAssetsFolder -DestinationPath $projectAssetsZip + Remove-Item -Path $projectAssetsFolder -Recurse -Force -ErrorAction SilentlyContinue + + return } - elseif ($Runtime -eq 'fxdependent-win-desktop') + + if ($Runtime -like 'fxdependent*') { - $pspackageParams = @{'Type'='fxdependent-win-desktop'} + $pspackageParams = @{'Type' = $Runtime} } else { - $pspackageParams = @{'Type'='msi'; 'WindowsRuntime'=$Runtime} + ## Set the default package type. + $pspackageParams = @{'Type' = 'msi'; 'WindowsRuntime' = $Runtime} + if ($ForMinimalSize) + { + ## Special case for the minimal size self-contained package. + $pspackageParams['Type'] = 'min-size' + } } - if (!$ComponentRegistration.IsPresent -and !$Symbols.IsPresent -and $Runtime -notmatch 'arm' -and $Runtime -notlike 'fxdependent*') + if (!$Symbols -and $Runtime -notlike 'fxdependent*' -and !$ForMinimalSize) { - Write-Verbose "Starting powershell packaging(msi)..." -Verbose - Start-PSPackage @pspackageParams @releaseTagParam - } + if ($Runtime -notmatch 'arm') + { + Write-Verbose "Starting powershell packaging(msi)..." -Verbose + Start-PSPackage @pspackageParams @releaseTagParam + } - if (!$ComponentRegistration.IsPresent -and !$Symbols.IsPresent -and $Runtime -notin 'fxdependent', 'fxdependent-win-desktop') - { $pspackageParams['Type']='msix' - $pspackageParams['WindowsRuntime']=$Runtime Write-Verbose "Starting powershell packaging(msix)..." -Verbose Start-PSPackage @pspackageParams @releaseTagParam } - if (!$ComponentRegistration.IsPresent -and $Runtime -notlike 'fxdependent*') - { - if (!$Symbols.IsPresent) { - $pspackageParams['Type'] = 'zip-pdb' - Write-Verbose "Starting powershell symbols packaging(zip)..." -Verbose - Start-PSPackage @pspackageParams @releaseTagParam - } - - $pspackageParams['Type']='zip' - $pspackageParams['IncludeSymbols']=$Symbols.IsPresent - Write-Verbose "Starting powershell packaging(zip)..." -Verbose - Start-PSPackage @pspackageParams @releaseTagParam - - Write-Verbose "Exporting packages ..." -Verbose - - Get-ChildItem $location\*.msi,$location\*.zip,$location\*.wixpdb,$location\*.msix | ForEach-Object { - $file = $_.FullName - Write-Verbose "Copying $file to $destination" -Verbose - Copy-Item -Path $file -Destination "$destination\" -Force - } - } - elseif (!$ComponentRegistration.IsPresent -and $Runtime -like 'fxdependent*') + if ($Runtime -like 'fxdependent*' -or $ForMinimalSize) { ## Add symbols for just like zip package. - $pspackageParams['IncludeSymbols']=$Symbols.IsPresent + $pspackageParams['IncludeSymbols']=$Symbols Start-PSPackage @pspackageParams @releaseTagParam ## Copy the fxdependent Zip package to destination. @@ -170,31 +179,30 @@ try{ } else { - Write-Verbose "Exporting project.assets files ..." -Verbose + if (!$Symbols) { + $pspackageParams['Type'] = 'zip-pdb' + Write-Verbose "Starting powershell symbols packaging(zip)..." -Verbose + Start-PSPackage @pspackageParams @releaseTagParam + } - $projectAssetsCounter = 1 - $projectAssetsFolder = Join-Path -Path $destination -ChildPath 'projectAssets' - $projectAssetsZip = Join-Path -Path $destination -ChildPath 'windowsProjectAssetssymbols.zip' - Get-ChildItem $location\project.assets.json -Recurse | ForEach-Object { - $subfolder = $_.FullName.Replace($location,'') - $subfolder.Replace('project.assets.json','') - $itemDestination = Join-Path -Path $projectAssetsFolder -ChildPath $subfolder - New-Item -Path $itemDestination -ItemType Directory -Force + $pspackageParams['Type']='zip' + $pspackageParams['IncludeSymbols']=$Symbols + Write-Verbose "Starting powershell packaging(zip)..." -Verbose + Start-PSPackage @pspackageParams @releaseTagParam + + Write-Verbose "Exporting packages ..." -Verbose + + Get-ChildItem $location\*.msi,$location\*.zip,$location\*.wixpdb,$location\*.msix,$location\*.exe | ForEach-Object { $file = $_.FullName - Write-Verbose "Copying $file to $itemDestination" -Verbose - Copy-Item -Path $file -Destination "$itemDestination\" -Force - $projectAssetsCounter++ + Write-Verbose "Copying $file to $destination" -Verbose + Copy-Item -Path $file -Destination "$destination\" -Force } - - Compress-Archive -Path $projectAssetsFolder -DestinationPath $projectAssetsZip - Remove-Item -Path $projectAssetsFolder -Recurse -Force -ErrorAction SilentlyContinue } - } finally { Write-Verbose "Beginning build clean-up..." -Verbose - if ($Wait.IsPresent) + if ($Wait) { $path = Join-Path $PSScriptRoot -ChildPath 'delete-to-continue.txt' $null = New-Item -Path $path -ItemType File diff --git a/tools/releaseBuild/azureDevOps/AzArtifactFeed/PSGalleryToAzArtifacts.yml b/tools/releaseBuild/azureDevOps/AzArtifactFeed/PSGalleryToAzArtifacts.yml index fab28643168..221a385b8b8 100644 --- a/tools/releaseBuild/azureDevOps/AzArtifactFeed/PSGalleryToAzArtifacts.yml +++ b/tools/releaseBuild/azureDevOps/AzArtifactFeed/PSGalleryToAzArtifacts.yml @@ -18,7 +18,7 @@ steps: - pwsh: | Import-Module -Force "$(Build.SourcesDirectory)/tools/releaseBuild/azureDevOps/AzArtifactFeed/SyncGalleryToAzArtifacts.psm1" - SyncGalleryToAzArtifacts -AzDevOpsFeedUserName $(AzDevOpsFeedUserName) -AzDevOpsPAT $(AzDevOpsFeedPAT) -Destination $(Build.ArtifactStagingDirectory) + SyncGalleryToAzArtifacts -AzDevOpsFeedUserName $(AzDevOpsFeedUserName) -AzDevOpsPAT $(AzDevOpsFeedPAT2) -Destination $(Build.ArtifactStagingDirectory) displayName: Download packages from PSGallery that need to be updated condition: succeededOrFailed() diff --git a/tools/releaseBuild/azureDevOps/WindowsBuild.yml b/tools/releaseBuild/azureDevOps/WindowsBuild.yml deleted file mode 100644 index 61e3041e338..00000000000 --- a/tools/releaseBuild/azureDevOps/WindowsBuild.yml +++ /dev/null @@ -1,464 +0,0 @@ -jobs: - -- job: BuildJob - displayName: Build - condition: succeeded() - pool: - name: Package ES Standard Build - strategy: - matrix: - Build (x64,release): - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: x64 - Build (x86,release): - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: x86 - Build (arm,release): - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: arm - Build (arm64,release): - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: arm64 - Build (fxdependent,release): - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: fxdependent - - steps: - - - checkout: self - clean: true - persistCredentials: true - - - task: PkgESSetupBuild@10 - displayName: 'Initialize build' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - useDfs: false - productName: PowerShellCore - branchVersion: true - disableWorkspace: true - disableBuildTools: true - disableNugetPack: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - tools/releaseBuild/setReleaseTag.ps1 -ReleaseTag $(ReleaseTag) - displayName: 'Set ReleaseTag Variable' - - - powershell: | - Write-Verbose -Verbose "$(Architecture)" - - if ('$(Architecture)' -eq 'fxdependent' -and '$(ReleaseTag)' -match '6.0.*') - { - $vstsCommandString = "vso[task.setvariable variable=SkipFxDependent]true" - } - else - { - $vstsCommandString = "vso[task.setvariable variable=SkipFxDependent]false" - } - - Write-Verbose -Message "$vstsCommandString " -Verbose - Write-Host -Object "##$vstsCommandString" - displayName: 'Skip FxDependent for PS v6.0.*' - - - powershell: | - Import-Module $(Build.SourcesDirectory)/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT) -FeedName AzDevOpsFeed -Destination $(Build.SourcesDirectory)/src/Modules - - if(-not (Test-Path "$(Build.SourcesDirectory)/src/Modules/nuget.config")) - { - throw "nuget.config is not created" - } - displayName: 'Add nuget.config for AzDevOps feed for PSGallery modules ' - condition: ne(Variables['SkipFxDependent'], 'true') - - - powershell: | - $version = $env:ReleaseTag.Substring(1) - $vstsCommandString = "vso[task.setvariable variable=Version]$version" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - displayName: 'Set Version Varibale' - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - docker container prune --force - docker container ls --all --format '{{ json .ID }}' | ConvertFrom-Json | ForEach-Object {docker container rm --force --volumes $_} - displayName: 'remove all containers [Port to PSRelease]' - continueOnError: true - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - docker image ls --format '{{ json .}}'|ConvertFrom-Json| ForEach-Object { - if($_.tag -eq '<none>') - { - $formatString = 'yyyy-MM-dd HH:mm:ss zz00' - $createdAtString = $_.CreatedAt.substring(0,$_.CreatedAt.Length -4) - $createdAt = [DateTime]::ParseExact($createdAtString, $formatString,[System.Globalization.CultureInfo]::InvariantCulture) - if($createdAt -lt (Get-Date).adddays(-1)) - { - docker image rm $_.ID - } - } - } - exit 0 - displayName: 'remove old images [Port to PSRelease]' - continueOnError: true - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - Write-verbose "--docker info---" -verbose - docker info - Write-verbose "--docker image ls---" -verbose - docker image ls - Write-verbose "--docker container ls --all---" -verbose - docker container ls --all - Write-verbose "--git branch ---" -verbose - git branch - exit 0 - displayName: 'Get Environment' - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTag) -Name win-$(Architecture)-symbols - displayName: 'Build Windows Universal - $(Architecture) Symbols zip' - continueOnError: true - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - if ("$env:Architecture" -eq 'fxdependent') - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 -SkipPwshExe - } - else - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 - } - displayName: 'Update Signing Xml' - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - $vstsCommandString = "vso[task.setvariable variable=Symbols]${env:Symbols_$(Architecture)}" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - displayName: 'Get Symbols path [Update build.json]' - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(Architecture)' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(Build.SourcesDirectory)\tools\releaseBuild\signing.xml' - inPathRoot: '$(Symbols)' - outPathRoot: '$(Symbols)\signed' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual'), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - New-Item -ItemType Directory -Path $(Symbols)\signed -Force - displayName: 'Create empty signed folder' - condition: and(succeeded(), ne(variables['Build.Reason'], 'Manual'), ne(variables['SkipFxDependent'], 'true')) - - - powershell: | - tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTag) -Name win-$(Architecture)-package -BuildPath $(Symbols) -SignedFilesPath $(Symbols)\signed - displayName: 'Build Windows Universal - $(Architecture) Package' - continueOnError: true - condition: and(succeeded(), ne(variables['SkipFxDependent'], 'true')) - -- job: ComponentRegistrationJob - displayName: Component Registration - dependsOn: BuildJob - condition: succeeded() - pool: - name: Package ES Standard Build - strategy: - matrix: - release-anycpu: - BuildConfiguration: release - BuildPlatform: any cpu - - steps: - - - powershell: | - ./tools/releaseBuild/setReleaseTag.ps1 -ReleaseTag $(ReleaseTag) - displayName: 'Set ReleaseTag Variable' - - - powershell: | - $version = $env:ReleaseTag.Substring(1) - $vstsCommandString = "vso[task.setvariable variable=Version]$version" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - displayName: 'Set Version Variable' - - - powershell: | - docker container prune --force - docker container ls --all --format '{{ json .ID }}' | ConvertFrom-Json | ForEach-Object {docker container rm --force --volumes $_} - displayName: 'Remove all containers' - continueOnError: true - - - powershell: | - docker image ls --format '{{ json .}}'|ConvertFrom-Json| ForEach-Object { - if($_.tag -eq '<none>') - { - $formatString = 'yyyy-MM-dd HH:mm:ss zz00' - $createdAtString = $_.CreatedAt.substring(0,$_.CreatedAt.Length -4) - $createdAt = [DateTime]::ParseExact($createdAtString, $formatString,[System.Globalization.CultureInfo]::InvariantCulture) - if($createdAt -lt (Get-Date).adddays(-1)) - { - docker image rm $_.ID - } - } - } - exit 0 - displayName: 'Remove old images' - continueOnError: true - - - powershell: | - Write-verbose "--docker info---" -verbose - docker info - Write-verbose "--docker image ls---" -verbose - docker image ls - Write-verbose "--docker container ls --all---" -verbose - docker container ls --all - Write-verbose "--git branch ---" -verbose - git branch - exit 0 - displayName: 'Get Environment' - - - powershell: | - ./tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTag) -Name win-x64-component-registration - displayName: 'Build Windows Universal - Component Registration' - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - inputs: - sourceScanPath: '$(componentregistration)' - snapshotForceEnabled: true - -- job: PackageSigningJob - displayName: Package signing - dependsOn: BuildJob - condition: succeeded() - pool: - name: Package ES Standard Build - strategy: - matrix: - release-anycpu: - BuildConfiguration: release - BuildPlatform: any cpu - - steps: - - - powershell: | - tools/releaseBuild/setReleaseTag.ps1 -ReleaseTag $(ReleaseTag) - displayName: 'Set ReleaseTag Variable' - continueOnError: true - - - powershell: | - $version = $env:ReleaseTag.Substring(1) - $vstsCommandString = "vso[task.setvariable variable=Version]$version" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - - $azureVersion = $env:ReleaseTag.ToLowerInvariant() -replace '\.', '-' - $vstsCommandString = "vso[task.setvariable variable=AzureVersion]$azureVersion" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - - displayName: 'Set Version Variable' - continueOnError: true - - - task: DownloadBuildArtifacts@0 - displayName: 'Download artifacts' - inputs: - downloadType: specific - continueOnError: true - - - powershell: | - dir "$(System.ArtifactsDirectory)\*" -Recurse - displayName: 'dir artifacts directory' - continueOnError: true - - - powershell: | - Expand-Archive -Path "$(System.ArtifactsDirectory)\results\PowerShell-$(Version)-symbols-win-x86.zip" -Destination "$(Build.StagingDirectory)\symbols\x86" - displayName: 'Expand symbols zip - x86' - continueOnError: true - - - powershell: | - Expand-Archive -Path "$(System.ArtifactsDirectory)\results\PowerShell-$(Version)-symbols-win-x64.zip" -Destination "$(Build.StagingDirectory)\symbols\x64" - displayName: 'Expand symbols zip - x64' - continueOnError: true - - - powershell: | - Expand-Archive -Path "$(System.ArtifactsDirectory)\results\PowerShell-$(Version)-symbols-win-fxdependent.zip" -Destination "$(Build.StagingDirectory)\symbols\fxdependent" - displayName: 'Expand symbols zip - fxdependent' - continueOnError: true - - - powershell: | - tools/releaseBuild/generatePackgeSigning.ps1 -AuthenticodeFiles "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x64.msi","$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x86.msi" -path "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Generate Package Signing Xml' - - - powershell: | - Get-Content "$(System.ArtifactsDirectory)\package.xml" - displayName: 'print signing xml' - continueOnError: true - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(System.ArtifactsDirectory)\package.xml' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\package.xml' - outPathRoot: '$(Build.StagingDirectory)\signedPackages' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(Build.StagingDirectory)\signedPackages\PowerShell-$(Version)-win-x64.msi" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[Create script] upload signed msi - x64' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - task: AzureFileCopy@4 - displayName: 'upload signed msi to Azure - x64' - inputs: - SourcePath: '$(Build.StagingDirectory)\signedPackages\PowerShell-$(Version)-win-x64.msi' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(Build.StagingDirectory)\signedPackages\PowerShell-$(Version)-win-x86.msi" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[create script] upload signed msi - x86' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed msi to Azure - x86' - inputs: - SourcePath: '$(Build.StagingDirectory)\signedPackages\PowerShell-$(Version)-win-x86.msi' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x64.zip" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[Create script] upload signed zip - x64' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - x64' - inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x64.zip' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x86.zip" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[create script] upload signed zip - x86' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - x86' - inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x86.zip' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm32.zip" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[create script] upload signed zip - arm' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - arm' - inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm32.zip' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm64.zip" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[create script] upload signed zip - arm64' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - arm64' - inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm64.zip' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) - - - powershell: | - $packagePath = "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-fxdependent.zip" - if(Test-Path -Path $packagePath) - { - Write-Host "##vso[artifact.upload containerfolder=signedResults;artifactname=signedResults]$packagePath" - } - displayName: '[create script] upload signed zip - fxdependent' - continueOnError: true - - - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - fxdependent' - inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-fxdependent.zip' - azureSubscription: '$(AzureFileCopySubscription)' - Destination: AzureBlob - storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' - continueOnError: true - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) diff --git a/tools/releaseBuild/azureDevOps/releaseBuild.yml b/tools/releaseBuild/azureDevOps/releaseBuild.yml index 2f38adc5367..4616f734b25 100644 --- a/tools/releaseBuild/azureDevOps/releaseBuild.yml +++ b/tools/releaseBuild/azureDevOps/releaseBuild.yml @@ -10,14 +10,40 @@ pr: - master - release* -variables: - DOTNET_CLI_TELEMETRY_OPTOUT: 1 - POWERSHELL_TELEMETRY_OPTOUT: 1 +parameters: + - name: ForceAzureBlobDelete + displayName: Delete Azure Blob + type: string + values: + - true + - false + default: false -# Set AzDevOps Agent to clean the machine after the end of the build resources: -- repo: self - clean: true + repositories: + - repository: ComplianceRepo + type: github + endpoint: ComplianceGHRepo + name: PowerShell/compliance + ref: master + +variables: + - name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 + - name: POWERSHELL_TELEMETRY_OPTOUT + value: 1 + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: branchCounterKey + value: $[format('{0:yyyyMMdd}-{1}', pipeline.startTime,variables['Build.SourceBranch'])] + - name: branchCounter + value: $[counter(variables['branchCounterKey'], 1)] + - name: ForceAzureBlobDelete + value: ${{ parameters.ForceAzureBlobDelete }} + - name: Github_Build_Repository_Uri + value: https://github.com/powershell/powershell + - name: SBOMGenerator_Formats + value: spdx:2.2 stages: - stage: prep @@ -28,18 +54,36 @@ stages: dependsOn: ['prep'] jobs: - template: templates/mac.yml + parameters: + buildArchitecture: x64 + + - template: templates/mac.yml + parameters: + buildArchitecture: arm64 + + - template: templates/mac-file-signing.yml + parameters: + buildArchitecture: x64 - template: templates/mac-file-signing.yml parameters: - parentJob: build_macOS + buildArchitecture: arm64 + + - template: templates/mac-package-build.yml + parameters: + buildArchitecture: x64 - template: templates/mac-package-build.yml parameters: - parentJob: MacFileSigningJob + buildArchitecture: arm64 + + - template: templates/mac-package-signing.yml + parameters: + buildArchitecture: x64 - template: templates/mac-package-signing.yml parameters: - parentJob: package_macOS + buildArchitecture: arm64 - stage: linux dependsOn: ['prep'] @@ -69,6 +113,11 @@ stages: parameters: Architecture: x64 + - template: templates/windows-hosted-build.yml + parameters: + Architecture: x64 + BuildConfiguration: minSize + - template: templates/windows-hosted-build.yml parameters: Architecture: x86 @@ -92,42 +141,49 @@ stages: - template: templates/windows-packaging.yml parameters: Architecture: x64 - parentJob: build_windows_x64 + parentJob: build_windows_x64_release + + - template: templates/windows-packaging.yml + parameters: + Architecture: x64 + BuildConfiguration: minSize + parentJob: build_windows_x64_minSize - template: templates/windows-packaging.yml parameters: Architecture: x86 - parentJob: build_windows_x86 + parentJob: build_windows_x86_release - template: templates/windows-packaging.yml parameters: Architecture: arm - parentJob: build_windows_arm + parentJob: build_windows_arm_release - template: templates/windows-packaging.yml parameters: Architecture: arm64 - parentJob: build_windows_arm64 + parentJob: build_windows_arm64_release - template: templates/windows-packaging.yml parameters: Architecture: fxdependent - parentJob: build_windows_fxdependent + parentJob: build_windows_fxdependent_release - template: templates/windows-packaging.yml parameters: Architecture: fxdependentWinDesktop - parentJob: build_windows_fxdependentWinDesktop + parentJob: build_windows_fxdependentWinDesktop_release - template: templates/windows-package-signing.yml parameters: parentJobs: - - sign_windows_x64 - - sign_windows_x86 - - sign_windows_arm - - sign_windows_arm64 - - sign_windows_fxdependent - - sign_windows_fxdependentWinDesktop + - sign_windows_x64_release + - sign_windows_x64_minSize + - sign_windows_x86_release + - sign_windows_arm_release + - sign_windows_arm64_release + - sign_windows_fxdependent_release + - sign_windows_fxdependentWinDesktop_release - stage: compliance dependsOn: ['windows'] @@ -149,15 +205,19 @@ stages: - job: release_json displayName: Create and Upload release.json pool: - vmImage: 'windows-latest' + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 steps: + - checkout: self + clean: true - template: templates/SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) - powershell: | $metadata = Get-Content '$(Build.SourcesDirectory)/tools/metadata.json' -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease + $LTS = $metadata.LTSRelease.Latest @{ ReleaseVersion = "$(Version)"; LTSRelease = $LTS } | ConvertTo-Json | Out-File "$(Build.StagingDirectory)\release.json" Get-Content "$(Build.StagingDirectory)\release.json" Write-Host "##vso[artifact.upload containerfolder=metadata;artifactname=metadata]$(Build.StagingDirectory)\release.json" diff --git a/tools/releaseBuild/azureDevOps/releasePipeline.yml b/tools/releaseBuild/azureDevOps/releasePipeline.yml index 9c752a179d9..7abb9792fe6 100644 --- a/tools/releaseBuild/azureDevOps/releasePipeline.yml +++ b/tools/releaseBuild/azureDevOps/releasePipeline.yml @@ -13,9 +13,20 @@ resources: - release/* variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value : false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: skipComponentGovernanceDetection + value: true stages: +- stage: MSIXBundle + displayName: Create MSIX Bundle package + dependsOn: [] + jobs: + - template: templates/release-MsixBundle.yml + - stage: ValidateSDK displayName: Validate SDK dependsOn: [] @@ -67,17 +78,26 @@ stages: globalToolExeName: 'pwsh' globalToolPackageName: 'PowerShell.Linux.x64' -- stage: ValidatePkgNames +- stage: StaticPkgValidation dependsOn: [] - displayName: Package Names validation + displayName: Static package validation jobs: - job: ValidatePkgNames + displayName: Validate Package Names pool: vmImage: windows-latest variables: - group: 'Azure Blob variable group' steps: - template: templates/release-ValidatePackageNames.yml + - job: ValidatePkgBOM + displayName: Validate Package BOM + pool: + vmImage: windows-latest + variables: + - group: 'Azure Blob variable group' + steps: + - template: templates/release-ValidatePackageBOM.yml - stage: StartDocker dependsOn: [] @@ -115,9 +135,10 @@ stages: displayName: Create GitHub draft release # do not include stages that are likely to fail in dependency as there is no way to force deploy. dependsOn: + - MSIXBundle - ValidateSDK - PRCreation - - ValidatePkgNames + - StaticPkgValidation - StartDocker - ManualValidation - ReleaseAutomation @@ -225,17 +246,40 @@ stages: pool: server environment: PSReleaseUpdateDotnetDocker +- stage: UpdateWinGet + dependsOn: GitHubManualTasks + displayName: Add manifest entry to winget + jobs: + - deployment: UpdateWinGet + displayName: Add manifest entry to winget + pool: server + environment: PSReleaseUpdateWinGet + +- stage: PublishMsix + dependsOn: GitHubManualTasks + displayName: Publish MSIX to store + jobs: + - deployment: PublishMsix + displayName: Publish the MSIX Bundle package to store + pool: server + environment: PSReleasePublishMsix + - stage: BuildInfoJson dependsOn: GitHubManualTasks displayName: Upload BuildInfoJson jobs: - - job: UploadJson + - deployment: UploadJson + displayName: Upload BuildInfoJson pool: vmImage: windows-latest variables: - group: 'Azure Blob variable group' - steps: - - template: templates/release-BuildJson.yml + environment: PSReleaseBuildInfoJson + strategy: + runOnce: + deploy: + steps: + - template: templates/release-BuildJson.yml - stage: ReleaseVPack dependsOn: GitHubManualTasks diff --git a/tools/releaseBuild/azureDevOps/templates/SetVersionVariables.yml b/tools/releaseBuild/azureDevOps/templates/SetVersionVariables.yml index ec688f8a91c..4376c4a1e58 100644 --- a/tools/releaseBuild/azureDevOps/templates/SetVersionVariables.yml +++ b/tools/releaseBuild/azureDevOps/templates/SetVersionVariables.yml @@ -2,11 +2,40 @@ parameters: ReleaseTagVar: v6.2.0 ReleaseTagVarName: ReleaseTagVar CreateJson: 'no' + UseJson: 'yes' steps: +- ${{ if eq(parameters['UseJson'],'yes') }}: + - task: DownloadBuildArtifacts@0 + inputs: + artifactName: 'BuildInfoJson' + itemPattern: '**/*.json' + downloadPath: '$(System.ArtifactsDirectory)' + displayName: Download Build Info Json + +- powershell: | + $path = "./build.psm1" + + if(Test-Path -Path $path) + { + $vstsCommandString = "vso[task.setvariable variable=repoRoot]." + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + } + else{ + $path = "./PowerShell/build.psm1" + if(Test-Path -Path $path) + { + $vstsCommandString = "vso[task.setvariable variable=repoRoot]./PowerShell" + Write-Host ("sending " + $vstsCommandString) + Write-Host "##$vstsCommandString" + } + } + displayName: 'Set repo Root' + - powershell: | - $createJson = ("${{ parameters.ReleaseTagVarName }}" -ne "no") - $releaseTag = tools/releaseBuild/setReleaseTag.ps1 -ReleaseTag ${{ parameters.ReleaseTagVar }} -Variable "${{ parameters.ReleaseTagVarName }}" -CreateJson:$createJson + $createJson = ("${{ parameters.CreateJson }}" -ne "no") + $releaseTag = & "$env:REPOROOT/tools/releaseBuild/setReleaseTag.ps1" -ReleaseTag ${{ parameters.ReleaseTagVar }} -Variable "${{ parameters.ReleaseTagVarName }}" -CreateJson:$createJson $version = $releaseTag.Substring(1) $vstsCommandString = "vso[task.setvariable variable=Version]$version" Write-Host ("sending " + $vstsCommandString) diff --git a/tools/releaseBuild/azureDevOps/templates/checkAzureContainer.yml b/tools/releaseBuild/azureDevOps/templates/checkAzureContainer.yml index c320727cc13..8019a5de3b9 100644 --- a/tools/releaseBuild/azureDevOps/templates/checkAzureContainer.yml +++ b/tools/releaseBuild/azureDevOps/templates/checkAzureContainer.yml @@ -1,14 +1,25 @@ jobs: - job: DeleteBlob variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value : false + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: Azure Blob variable group displayName: Delete blob is exists pool: - vmImage: windows-latest + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 steps: + - checkout: self + clean: true + - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + CreateJson: yes + UseJson: no - task: AzurePowerShell@4 inputs: diff --git a/tools/releaseBuild/azureDevOps/templates/cloneToOfficialPath.yml b/tools/releaseBuild/azureDevOps/templates/cloneToOfficialPath.yml new file mode 100644 index 00000000000..0a52f887671 --- /dev/null +++ b/tools/releaseBuild/azureDevOps/templates/cloneToOfficialPath.yml @@ -0,0 +1,16 @@ +steps: + - powershell: | + $dirSeparatorChar = [system.io.path]::DirectorySeparatorChar + $nativePath = "${dirSeparatorChar}PowerShell" + Write-Host "##vso[task.setvariable variable=PowerShellRoot]$nativePath" + + if ((Test-Path "$nativePath")) { + Remove-Item -Path "$nativePath" -Force -Recurse -Verbose -ErrorAction ignore + } + else { + Write-Verbose -Verbose -Message "No cleanup required." + } + + git clone --quiet $env:REPOROOT $nativePath + displayName: Clone PowerShell Repo to /PowerShell + errorActionPreference: silentlycontinue diff --git a/tools/releaseBuild/azureDevOps/templates/compliance.yml b/tools/releaseBuild/azureDevOps/templates/compliance.yml index b4b5a04dfb3..befe1728cd6 100644 --- a/tools/releaseBuild/azureDevOps/templates/compliance.yml +++ b/tools/releaseBuild/azureDevOps/templates/compliance.yml @@ -4,17 +4,29 @@ parameters: jobs: - job: compliance variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value : false + - name: NugetSecurityAnalysisWarningLevel + value: none + + # Defines the variables APIScanClient, APIScanTenant and APIScanSecret + - group: PS-PS-APIScan + displayName: Compliance dependsOn: ${{ parameters.parentJobs }} pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 # APIScan can take a long time timeoutInMinutes: 180 steps: + - checkout: self + clean: true + - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) @@ -73,12 +85,11 @@ jobs: inputs: targetType: F optionsFC: 0 - optionsXS: 0 + optionsXS: 1 optionsPE: '1|2|3|4' optionsHMENABLE: 0 optionsRulesDBPath: '$(Build.SourcesDirectory)\tools\terms\PowerShell-Terms-Rules.mdb' - optionsFTPATH: '$(Build.SourcesDirectory)\tools\terms\FileTypeSet.xml' - toolVersion: 5.8.2.1 + optionsUEPath: $(Build.SourcesDirectory)\tools\terms\TermsExclusion.xml continueOnError: true # add RoslynAnalyzers @@ -109,6 +120,8 @@ jobs: softwareVersionNum: '$(ReleaseTagVar)' isLargeApp: false preserveTempFiles: true + env: + AzureServicesAuthConnectionString: RunAs=App;AppId=$(APIScanClient);TenantId=$(APIScanTenant);AppKey=$(APIScanSecret) continueOnError: true - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 @@ -120,9 +133,13 @@ jobs: inputs: tsaVersion: TsaV2 codeBaseName: 'PowerShellCore_201906' + uploadAPIScan: false + uploadBinSkim: true + uploadCredScan: false uploadFortifySCA: false uploadFxCop: false uploadModernCop: false + uploadPoliCheck: false uploadPREfast: false uploadRoslyn: false uploadTSLint: false diff --git a/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml b/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml index ae697e70e33..9cf3d8dbc8d 100644 --- a/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml +++ b/tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml @@ -1,11 +1,25 @@ +parameters: + - name: "repoRoot" + default: $(REPOROOT) + steps: -- powershell: | - Import-Module $(Build.SourcesDirectory)/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT) -FeedName AzDevOpsFeed -Destination $(Build.SourcesDirectory)/src/Modules +- pwsh: | + Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force + New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT2) -FeedName AzDevOpsFeed -Destination '${{ parameters.repoRoot }}/src/Modules' - if(-not (Test-Path "$(Build.SourcesDirectory)/src/Modules/nuget.config")) + if(-not (Test-Path "${{ parameters.repoRoot }}/src/Modules/nuget.config")) { throw "nuget.config is not created" } displayName: 'Add nuget.config for Azure DevOps feed for PSGallery modules' condition: and(succeededOrFailed(), ne(variables['AzDevOpsFeed'], '')) +- pwsh: | + Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force + New-NugetConfigFile -NugetFeedUrl $(PSInternalNugetFeed) -UserName $(PSInternalNugetFeedUserName) -ClearTextPAT $(PSInternalNugetFeedPAT) -FeedName AzDevOpsFeed -Destination '${{ parameters.repoRoot }}' + + if(-not (Test-Path "${{ parameters.repoRoot }}/nuget.config")) + { + throw "nuget.config is not created" + } + displayName: 'Add nuget.config for Azure DevOps feed for packages' + condition: and(succeededOrFailed(), ne(variables['PSInternalNugetFeed'], '')) diff --git a/tools/releaseBuild/azureDevOps/templates/json.yml b/tools/releaseBuild/azureDevOps/templates/json.yml index 1a0bfba950d..570a658756a 100644 --- a/tools/releaseBuild/azureDevOps/templates/json.yml +++ b/tools/releaseBuild/azureDevOps/templates/json.yml @@ -4,19 +4,27 @@ parameters: jobs: - job: json variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value : false + - name: NugetSecurityAnalysisWarningLevel + value: none displayName: Create Json for Blob dependsOn: ${{ parameters.parentJobs }} condition: succeeded() pool: - vmImage: windows-latest + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 steps: #- task: <task type name>@<version> # inputs: # <task specific inputs> # displayName: '<display name of task>' + - checkout: self + clean: true + - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) diff --git a/tools/releaseBuild/azureDevOps/templates/linux.yml b/tools/releaseBuild/azureDevOps/templates/linux.yml index be372a6b982..353f6e2431c 100644 --- a/tools/releaseBuild/azureDevOps/templates/linux.yml +++ b/tools/releaseBuild/azureDevOps/templates/linux.yml @@ -7,59 +7,159 @@ jobs: - job: build_${{ parameters.buildName }} displayName: Build ${{ parameters.buildName }} condition: succeeded() - pool: Hosted Ubuntu 1604 + pool: + name: PowerShell1ES + demands: + - ImageOverride -equals MMSUbuntu20.04 dependsOn: ${{ parameters.parentJob }} variables: - build: ${{ parameters.buildName }} - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value: false + - name: build + value: ${{ parameters.buildName }} + - name: NugetSecurityAnalysisWarningLevel + value: none + - group: ESRP + steps: + - checkout: self + clean: true + + - checkout: ComplianceRepo + clean: true - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) - - powershell: | - Write-Verbose -Verbose "$(build)" + - pwsh: | + # create folder + sudo mkdir /PowerShell - if ('$(build)' -in 'alpine', 'fxdependent' -and '$(ReleaseTagVar)' -match '6.0.*') - { - $vstsCommandString = "vso[task.setvariable variable=SkipBuild]true" - } - else - { - $vstsCommandString = "vso[task.setvariable variable=SkipBuild]false" - } - displayName: 'Skip Alpine or fxdependent for PS v6.0.*' + # make the current user the owner + sudo chown $env:USER /PowerShell + displayName: 'Create /PowerShell' - - template: insert-nuget-config-azfeed.yml + - template: cloneToOfficialPath.yml + - template: insert-nuget-config-azfeed.yml + parameters: + repoRoot: $(PowerShellRoot) - powershell: | - import-module ./build.psm1 + import-module "$env:POWERSHELLROOT/build.psm1" Sync-PSTags -AddRemoteIfMissing displayName: SyncTags condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) + workingDirectory: $(PowerShellRoot) + + - powershell: | + Import-Module "$env:POWERSHELLROOT/build.psm1" + + Start-PSBootstrap -Package + displayName: 'Bootstrap' + condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) + workingDirectory: $(PowerShellRoot) - powershell: | - tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTagVar) -Name '$(build)' - displayName: 'Build and package' + Import-Module "$env:POWERSHELLROOT/build.psm1" + Import-Module "$env:POWERSHELLROOT/tools/packaging" + + Invoke-AzDevOpsLinuxPackageBuild -ReleaseTag '$(ReleaseTagVar)' -BuildType '$(build)' + displayName: 'Build' condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) + workingDirectory: $(PowerShellRoot) + + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/pwshLinuxBuild' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + displayName: ${{ parameters.buildName }} SBOM + + - ${{ if eq(variables.build,'deb') }} : + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/pwshLinuxBuildMinSize' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + displayName: MinSize SBOM + + - ${{ if eq(variables.build,'deb') }} : + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/pwshLinuxBuildArm32' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + displayName: Arm32 SBOM + + - ${{ if eq(variables.build,'deb') }} : + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/pwshLinuxBuildArm64' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + displayName: Arm64 SBOM + + - powershell: | + Import-Module "$env:POWERSHELLROOT/build.psm1" + Import-Module "$env:POWERSHELLROOT/tools/packaging" + + $metadata = Get-Content "$env:POWERSHELLROOT/tools/metadata.json" -Raw | ConvertFrom-Json + + # LTSRelease.Package indicates that the release should be packaged as an LTS + $LTS = $metadata.LTSRelease.Package + Write-Verbose -Verbose -Message "LTS is set to: $LTS" + + Invoke-AzDevOpsLinuxPackageCreation -ReleaseTag '$(ReleaseTagVar)' -BuildType '$(build)' + + if ($LTS) { + Write-Verbose -Verbose "Packaging LTS" + Invoke-AzDevOpsLinuxPackageCreation -LTS -ReleaseTag '$(ReleaseTagVar)' -BuildType '$(build)' + } + displayName: 'Package' + condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) + workingDirectory: $(PowerShellRoot) + + - powershell: | + $linuxPackages = Get-ChildItem "$env:POWERSHELLROOT/powershell*" -Include *.deb,*.rpm,*.tar.gz + + $bucket = 'release' + foreach ($linuxPackage in $linuxPackages) + { + $filePath = $linuxPackage.FullName + Write-Verbose "Publishing $filePath to $bucket" -Verbose + Write-Host "##vso[artifact.upload containerfolder=$bucket;artifactname=$bucket]$filePath" + } + displayName: Publish artifacts + condition: and(succeeded(), ne(variables['SkipBuild'], 'true')) + workingDirectory: $(PowerShellRoot) - job: upload_${{ parameters.buildName }} displayName: ${{ parameters.uploadDisplayName }} ${{ parameters.buildName }} dependsOn: build_${{ parameters.buildName }} condition: succeeded() - pool: Package ES Standard Build + pool: + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - buildName: ${{ parameters.buildName }} + - name: buildName + value: ${{ parameters.buildName }} + - group: ESRP + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + steps: + - checkout: self + clean: true - - template: shouldSign.yml + - checkout: ComplianceRepo + clean: true - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: shouldSign.yml - task: DownloadBuildArtifacts@0 displayName: 'Download Deb Artifacts' @@ -67,7 +167,7 @@ jobs: downloadType: specific itemPattern: '**/*.deb' downloadPath: '$(System.ArtifactsDirectory)\finished' - condition: and(eq(variables['buildName'], 'DEB'),succeeded()) + condition: and(eq(variables['buildName'], 'DEB'), succeeded()) - task: DownloadBuildArtifacts@0 displayName: 'Download tar.gz Artifacts copy' @@ -76,53 +176,97 @@ jobs: itemPattern: '**/*.tar.gz' downloadPath: '$(System.ArtifactsDirectory)\finished' + - powershell: | + Write-Host 'We handle the min-size package only when uploading for deb build.' + Write-Host '- For deb build, the min-size package is moved to a separate folder "finished\minSize",' + Write-Host ' so that the min-size package can be uploaded to a different Az Blob container.' + Write-Host '- For other builds, the min-size package is removed after being downloaded, so that it' + Write-Host ' does not get accidentally uploaded to the wrong Az Blob container.' + + $minSizePkg = '$(System.ArtifactsDirectory)\finished\release\*-gc.tar.gz' + if (Test-Path -Path $minSizePkg) + { + if ('$(buildName)' -eq 'DEB') + { + $minSizeDir = '$(System.ArtifactsDirectory)\finished\minSize' + New-Item -Path $minSizeDir -Type Directory -Force > $null + Move-Item -Path $minSizePkg -Destination $minSizeDir + + Write-Host "`nCapture the min-size package moved to the target folder." + Get-ChildItem -Path $minSizeDir + } + else + { + Write-Host '$(buildName): Remove the min-size package.' + Remove-Item -Path $minSizePkg -Force + } + } + else + { + Write-Host 'min-size package not found, so skip this step.' + } + displayName: 'Move minSize package to separate folder' + - task: DownloadBuildArtifacts@0 displayName: 'Download rpm Artifacts copy' inputs: downloadType: specific itemPattern: '**/*.rpm' downloadPath: '$(System.ArtifactsDirectory)\rpm' - condition: and(eq(variables['buildName'], 'RPM'),succeeded()) + condition: and(eq(variables['buildName'], 'RPM'), succeeded()) - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'Run Defender Scan' + - template: EsrpScan.yml@ComplianceRepo + parameters: + scanPath: $(System.ArtifactsDirectory) + pattern: | + **\*.rpm + **\*.deb + **\*.tar.gz - - powershell: | - $authenticodefiles = @() - Get-ChildItem -Path '$(System.ArtifactsDirectory)\rpm\*.rpm' -recurse | ForEach-Object { $authenticodefiles += $_.FullName} - tools/releaseBuild/generatePackgeSigning.ps1 -LinuxFiles $authenticodeFiles -path "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Generate RPM Signing Xml' - condition: and(and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')),eq(variables['buildName'], 'RPM')) + - ${{ if eq(variables['buildName'], 'RPM') }}: + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\rpm + signOutputPath: $(Build.StagingDirectory)\signedPackages + certificateId: "CP-450779-Pgp" + pattern: | + **\*.rpm + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign RPM - - powershell: | - Get-Content "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Capture RPM signing xml' - condition: and(and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')),eq(variables['buildName'], 'RPM')) + # requires windows + - ${{ if ne(variables['buildName'], 'RPM') }}: + - task: AzureFileCopy@4 + displayName: 'Upload to Azure - DEB and tar.gz' + inputs: + SourcePath: '$(System.ArtifactsDirectory)\finished\release\*' + azureSubscription: '$(AzureFileCopySubscription)' + Destination: AzureBlob + storage: '$(StorageAccount)' + ContainerName: '$(AzureVersion)' - - task: PkgESCodeSign@10 - displayName: 'CodeSign RPM $(System.ArtifactsDirectory)\package.xml' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\package.xml' - outPathRoot: '$(Build.StagingDirectory)\signedPackages' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')),eq(variables['buildName'], 'RPM')) + - template: upload-final-results.yml + parameters: + artifactPath: $(System.ArtifactsDirectory)\finished\release + # requires windows - task: AzureFileCopy@4 - displayName: 'Upload to Azure - DEB and tar.gz' + displayName: 'Upload to Azure - min-size package for Guest Config' inputs: - SourcePath: '$(System.ArtifactsDirectory)\finished\release\*' + SourcePath: '$(System.ArtifactsDirectory)\finished\minSize\*' azureSubscription: '$(AzureFileCopySubscription)' Destination: AzureBlob storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' + ContainerName: '$(AzureVersion)-gc' + condition: and(eq(variables['buildName'], 'DEB'), succeeded()) - template: upload-final-results.yml parameters: - artifactPath: $(System.ArtifactsDirectory)\finished\release + artifactPath: $(System.ArtifactsDirectory)\finished\minSize + condition: and(eq(variables['buildName'], 'DEB'), succeeded()) + # requires windows - task: AzureFileCopy@4 displayName: 'Upload to Azure - RPM - Unsigned' inputs: @@ -133,10 +277,11 @@ jobs: ContainerName: '$(AzureVersion)' condition: and(and(succeeded(), ne(variables['SHOULD_SIGN'], 'true')),eq(variables['buildName'], 'RPM')) + # requires windows - task: AzureFileCopy@4 displayName: 'Upload to Azure - RPM - Signed' inputs: - SourcePath: '$(Build.StagingDirectory)\signedPackages\*' + SourcePath: '$(Build.StagingDirectory)\signedPackages\release\*' azureSubscription: '$(AzureFileCopySubscription)' Destination: AzureBlob storage: '$(StorageAccount)' @@ -150,7 +295,7 @@ jobs: - template: upload-final-results.yml parameters: - artifactPath: '$(Build.StagingDirectory)\signedPackages' + artifactPath: '$(Build.StagingDirectory)\signedPackages\release' condition: and(and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')),eq(variables['buildName'], 'RPM')) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/releaseBuild/azureDevOps/templates/mac-file-signing.yml b/tools/releaseBuild/azureDevOps/templates/mac-file-signing.yml index 0d188be03b9..1f43d39ab61 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac-file-signing.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac-file-signing.yml @@ -1,25 +1,35 @@ parameters: - parentJob: '' + buildArchitecture: 'x64' jobs: - - job: MacFileSigningJob - displayName: macOS File signing - dependsOn: ${{ parameters.parentJob }} + - job: MacFileSigningJob_${{ parameters.buildArchitecture }} + displayName: macOS File signing ${{ parameters.buildArchitecture }} + dependsOn: build_macOS_${{ parameters.buildArchitecture }} condition: succeeded() pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - BuildConfiguration: release - BuildPlatform: any cpu + - group: ESRP + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none steps: + - checkout: self + clean: true - - template: shouldSign.yml + - checkout: ComplianceRepo + clean: true - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: shouldSign.yml + - task: DownloadBuildArtifacts@0 inputs: artifactName: 'macosBinResults' @@ -33,7 +43,7 @@ jobs: continueOnError: true - pwsh: | - $zipPath = Get-Item '$(System.ArtifactsDirectory)\Symbols\macosBinResults\*symbol*.zip' + $zipPath = Get-Item '$(System.ArtifactsDirectory)\Symbols\macosBinResults\*symbol*${{ parameters.buildArchitecture }}*.zip' Write-Verbose -Verbose "Zip Path: $zipPath" $expandedFolder = $zipPath.BaseName @@ -55,36 +65,25 @@ jobs: - pwsh: | $null = new-item -type directory -path "$(Build.StagingDirectory)\macos" - $zipFile = "$(Build.StagingDirectory)\macos\powershell-files-$(Version)-osx-x64.zip" + $zipFile = "$(Build.StagingDirectory)\macos\powershell-files-$(Version)-osx-${{ parameters.buildArchitecture }}.zip" Get-ChildItem "$(System.ArtifactsDirectory)\$(SymbolsFolder)" -Recurse -Include pwsh, *.dylib | Compress-Archive -Destination $zipFile Write-Host $zipFile displayName: 'Compress macOS binary files' - - pwsh: | - $pkgFiles = "$(Build.StagingDirectory)\macos\powershell-files-$(Version)-osx-x64.zip", "$(Build.StagingDirectory)\macos\powershell-lts-$(Version)-osx-x64.zip" - tools/releaseBuild/generatePackgeSigning.ps1 -MacDeveloperFiles $pkgFiles -path "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Generate macOS binary Signing Xml' - - - pwsh: | - Get-Content "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Capture macOS signing xml' - # Diagnostics is not critical it passes every time it runs - continueOnError: true - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(System.ArtifactsDirectory)\package.xml' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\package.xml' - outPathRoot: '$(Build.StagingDirectory)\signedMacOSPackages' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(Build.StagingDirectory)\macos + signOutputPath: $(Build.StagingDirectory)\signedMacOSPackages + certificateId: "CP-401337-Apple" + pattern: | + **\*.zip + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign macOS Binaries - pwsh: | - $destination = "$(System.ArtifactsDirectory)\azureMacOs" + $destination = "$(System.ArtifactsDirectory)\azureMacOs_${{ parameters.buildArchitecture }}" New-Item -Path $destination -Type Directory $zipPath = Get-ChildItem "$(Build.StagingDirectory)\signedMacOSPackages\powershell-*.zip" -Recurse | select-object -expandproperty fullname foreach ($z in $zipPath) { Expand-Archive -Path $z -DestinationPath $destination } @@ -93,13 +92,17 @@ jobs: - template: upload-final-results.yml parameters: - artifactPath: $(System.ArtifactsDirectory)\azureMacOs + artifactPath: $(System.ArtifactsDirectory)\azureMacOs_${{ parameters.buildArchitecture }} artifactFilter: "*" - artifactName: signedMacOsBins + artifactName: signedMacOsBins_${{ parameters.buildArchitecture }} condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'Run Defender Scan' + - ${{ if eq(variables['SHOULD_SIGN'], 'true') }}: + - template: EsrpScan.yml@ComplianceRepo + parameters: + scanPath: $(System.ArtifactsDirectory)\azureMacOs_${{ parameters.buildArchitecture }} + pattern: | + **\* - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' diff --git a/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml b/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml index 57208f26ce9..989cdbda039 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac-package-build.yml @@ -1,18 +1,26 @@ parameters: parentJob: '' - jobName: 'package_macOS' + buildArchitecture: x64 jobs: -- job: ${{ parameters.jobName }} - displayName: Package macOS - dependsOn: ${{ parameters.parentJob }} +- job: package_macOS_${{ parameters.buildArchitecture }} + displayName: Package macOS ${{ parameters.buildArchitecture }} + dependsOn: MacFileSigningJob_${{ parameters.buildArchitecture }} condition: succeeded() - pool: Hosted Mac Internal + pool: + vmImage: internal-macos-10.14 variables: # Turn off Homebrew analytics - HOMEBREW_NO_ANALYTICS: 1 - runCodesignValidationInjection: false + - name: HOMEBREW_NO_ANALYTICS + value: 1 + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none steps: + - checkout: self + clean: true + - pwsh: | # create folder sudo mkdir /PowerShell @@ -21,33 +29,25 @@ jobs: sudo chown $env:USER /PowerShell displayName: 'Create /PowerShell' - - pwsh: | - Write-Host "##vso[task.setvariable variable=PowerShellRoot]/PowerShell" - git clone $env:BUILD_REPOSITORY_LOCALPATH /PowerShell - displayName: Clone PowerShell Repo to /PowerShell - - - template: shouldSign.yml - - #- task: <task type name>@<version> - # inputs: - # <task specific inputs> - # displayName: '<display name of task>' - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: shouldSign.yml + + - template: cloneToOfficialPath.yml - task: DownloadBuildArtifacts@0 displayName: Download macosBinResults inputs: artifactName: 'macosBinResults' - itemPattern: '**/*.zip' + itemPattern: '**/*${{ parameters.buildArchitecture }}.zip' downloadPath: '$(System.ArtifactsDirectory)/Symbols' - task: DownloadBuildArtifacts@0 displayName: Download signedMacOsBins inputs: - artifactName: 'signedMacOsBins' + artifactName: 'signedMacOsBins_${{ parameters.buildArchitecture }}' itemPattern: '**/*' downloadPath: '$(System.ArtifactsDirectory)/macOsBins' condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) @@ -59,7 +59,7 @@ jobs: continueOnError: true - pwsh: | - $zipPath = Get-Item '$(System.ArtifactsDirectory)\Symbols\macosBinResults\*symbol*.zip' + $zipPath = Get-Item '$(System.ArtifactsDirectory)\Symbols\macosBinResults\*symbol*${{ parameters.buildArchitecture }}.zip' Write-Verbose -Verbose "Zip Path: $zipPath" $expandedFolder = $zipPath.BaseName @@ -72,13 +72,18 @@ jobs: - pwsh: | Import-Module $(PowerShellRoot)/build.psm1 -Force Import-Module $(PowerShellRoot)/tools/packaging -Force - $signedFilesPath = '$(System.ArtifactsDirectory)/macOsBins/signedMacOsBins/' + $signedFilesPath = '$(System.ArtifactsDirectory)/macOsBins/signedMacOsBins_${{ parameters.buildArchitecture }}/' $BuildPath = '$(System.ArtifactsDirectory)\$(SymbolsFolder)' Update-PSSignedBuildFolder -BuildPath $BuildPath -SignedFilesPath $SignedFilesPath displayName: Merge signed files with Build condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)/$(SymbolsFolder)' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + - pwsh: | Import-Module $(PowerShellRoot)/build.psm1 -Force Import-Module $(PowerShellRoot)/tools/packaging -Force @@ -103,7 +108,7 @@ jobs: displayName: 'Bootstrap VM' - pwsh: | - $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -location $(PowerShellRoot) -ArtifactName macosPkgResults -BuildZip $(BuildPackagePath) -ExtraPackage "tar" + $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -location $(PowerShellRoot) -ArtifactName macosPkgResults -BuildZip $(BuildPackagePath) -ExtraPackage "tar" -Runtime 'osx-${{ parameters.buildArchitecture }}' displayName: 'Package' - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/releaseBuild/azureDevOps/templates/mac-package-signing.yml b/tools/releaseBuild/azureDevOps/templates/mac-package-signing.yml index db3a8ba3dbc..cba0ed6f9c3 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac-package-signing.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac-package-signing.yml @@ -1,18 +1,27 @@ parameters: - parentJob: '' + buildArchitecture: x64 jobs: -- job: MacPackageSigningJob - displayName: macOS Package signing - dependsOn: ${{ parameters.parentJob }} +- job: MacPackageSigningJob_${{ parameters.buildArchitecture }} + displayName: macOS Package signing ${{ parameters.buildArchitecture }} + dependsOn: package_macOS_${{ parameters.buildArchitecture }} condition: succeeded() pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - BuildConfiguration: release - BuildPlatform: any cpu - + - group: ESRP + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none steps: + - checkout: self + clean: true + + - checkout: ComplianceRepo + clean: true - template: shouldSign.yml @@ -34,46 +43,35 @@ jobs: - pwsh: | $null = new-item -type directory -path "$(Build.StagingDirectory)\macos" - $zipFile = "$(Build.StagingDirectory)\macos\powershell-$(Version)-osx-x64.zip" - Compress-Archive -Path "$(System.ArtifactsDirectory)\macosPkgResults\powershell-$(Version)-osx-x64.pkg" -Destination $zipFile + $zipFile = "$(Build.StagingDirectory)\macos\powershell-$(Version)-osx-${{ parameters.buildArchitecture }}.zip" + Compress-Archive -Path "$(System.ArtifactsDirectory)\macosPkgResults\powershell-$(Version)-osx-${{ parameters.buildArchitecture }}.pkg" -Destination $zipFile Write-Host $zipFile - $ltsPkgPath = "$(System.ArtifactsDirectory)\macosPkgResults\powershell-lts-$(Version)-osx-x64.pkg" + $ltsPkgPath = "$(System.ArtifactsDirectory)\macosPkgResults\powershell-lts-$(Version)-osx-${{ parameters.buildArchitecture }}.pkg" if(Test-Path $ltsPkgPath) { - $ltsZipFile = "$(Build.StagingDirectory)\macos\powershell-lts-$(Version)-osx-x64.zip" + $ltsZipFile = "$(Build.StagingDirectory)\macos\powershell-lts-$(Version)-osx-${{ parameters.buildArchitecture }}.zip" Compress-Archive -Path $ltsPkgPath -Destination $ltsZipFile Write-Host $ltsZipFile } displayName: 'Compress macOS Package' - - pwsh: | - $pkgFiles = "$(Build.StagingDirectory)\macos\powershell-$(Version)-osx-x64.zip", "$(Build.StagingDirectory)\macos\powershell-lts-$(Version)-osx-x64.zip" - tools/releaseBuild/generatePackgeSigning.ps1 -MacDeveloperFiles $pkgFiles -path "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Generate macOS Package Signing Xml' - - - pwsh: | - Get-Content "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Capture macOS signing xml' - # Diagnostics is not critical it passes every time it runs - continueOnError: true - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(System.ArtifactsDirectory)\package.xml' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\package.xml' - outPathRoot: '$(Build.StagingDirectory)\signedMacOSPackages' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(Build.StagingDirectory)\macos + signOutputPath: $(Build.StagingDirectory)\signedMacOSPackages + certificateId: "CP-401337-Apple" + pattern: | + **\*.zip + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign pkg - template: upload-final-results.yml parameters: artifactPath: $(System.ArtifactsDirectory)\macosPkgResults - artifactFilter: "*.tar.gz" + artifactFilter: "*${{ parameters.buildArchitecture }}.tar.gz" - pwsh: | $destination = "$(System.ArtifactsDirectory)\azureMacOs" @@ -118,9 +116,6 @@ jobs: ContainerName: '$(AzureVersion)' condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'Run Defender Scan' - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' inputs: diff --git a/tools/releaseBuild/azureDevOps/templates/mac.yml b/tools/releaseBuild/azureDevOps/templates/mac.yml index 4526c8d1267..6bf7814d93b 100644 --- a/tools/releaseBuild/azureDevOps/templates/mac.yml +++ b/tools/releaseBuild/azureDevOps/templates/mac.yml @@ -1,20 +1,27 @@ parameters: - jobName: 'build_macOS' + buildArchitecture: 'x64' jobs: -- job: ${{ parameters.jobName }} - displayName: Build macOS +- job: build_macOS_${{ parameters.buildArchitecture }} + displayName: Build macOS ${{ parameters.buildArchitecture }} condition: succeeded() - pool: Hosted Mac Internal + pool: + vmImage: internal-macos-10.14 variables: # Turn off Homebrew analytics - HOMEBREW_NO_ANALYTICS: 1 - runCodesignValidationInjection: false + - name: HOMEBREW_NO_ANALYTICS + value: 1 + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none steps: #- task: <task type name>@<version> # inputs: # <task specific inputs> # displayName: '<display name of task>' + - checkout: self + clean: true - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) @@ -27,29 +34,20 @@ jobs: sudo chown $env:USER /PowerShell displayName: 'Create /PowerShell' - - pwsh: | - Write-Host "##vso[task.setvariable variable=PowerShellRoot]/PowerShell" - git clone $env:BUILD_REPOSITORY_LOCALPATH /PowerShell - displayName: Clone PowerShell Repo to /PowerShell + - template: cloneToOfficialPath.yml - pwsh: | tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -location $(PowerShellRoot) -BootStrap displayName: 'Bootstrap VM' - - pwsh: | - Import-Module $(Build.SourcesDirectory)/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT) -FeedName AzDevOpsFeed -Destination "$(PowerShellRoot)/src/Modules" - - if(-not (Test-Path "$(PowerShellRoot)/src/Modules/nuget.config")) - { - throw "nuget.config is not created" - } - displayName: 'Add nuget.config for AzDevOps feed for PSGallery modules ' + - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml + parameters: + repoRoot: $(PowerShellRoot) - pwsh: | - $env:AZDEVOPSFEEDPAT = '$(AzDevOpsFeedPAT)' - $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -Symbols -location $(PowerShellRoot) -Build -ArtifactName macosBinResults - $env:AZDEVOPSFEEDPAT = $null + $env:AzDevOpsFeedPAT2 = '$(AzDevOpsFeedPAT2)' + $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -Symbols -location $(PowerShellRoot) -Build -ArtifactName macosBinResults -Runtime 'osx-${{ parameters.buildArchitecture }}' + $env:AzDevOpsFeedPAT2 = $null displayName: 'Build' - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/releaseBuild/azureDevOps/templates/nuget.yml b/tools/releaseBuild/azureDevOps/templates/nuget.yml index 138050f5c60..467968b5a3a 100644 --- a/tools/releaseBuild/azureDevOps/templates/nuget.yml +++ b/tools/releaseBuild/azureDevOps/templates/nuget.yml @@ -7,22 +7,45 @@ jobs: ${{ parameters.parentJobs }} displayName: Build NuGet packages condition: succeeded() - pool: Package ES Standard Build + pool: + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 timeoutInMinutes: 90 variables: - runCodesignValidationInjection: false - GenAPIToolPath: '$(System.ArtifactsDirectory)/GenAPI' - PackagePath: '$(System.ArtifactsDirectory)/UnifiedPackagePath' - winFxdPath: '$(System.ArtifactsDirectory)/winFxd' - winFxdWinDesktopPath: '$(System.ArtifactsDirectory)/winFxdWinDesktop' - linuxFxdPath: '$(System.ArtifactsDirectory)/linuxFxd' + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: build + value: ${{ parameters.buildName }} + - group: ESRP + - name: GenAPIToolPath + value: '$(System.ArtifactsDirectory)/GenAPI' + - name: PackagePath + value: '$(System.ArtifactsDirectory)/UnifiedPackagePath' + - name: winFxdPath + value: '$(System.ArtifactsDirectory)/winFxd' + - name: winFxdWinDesktopPath + value: '$(System.ArtifactsDirectory)/winFxdWinDesktop' + - name: linuxFxdPath + value: '$(System.ArtifactsDirectory)/linuxFxd' steps: + - checkout: self + clean: true + + - checkout: ComplianceRepo + clean: true + + - template: SetVersionVariables.yml + parameters: + ReleaseTagVar: $(ReleaseTagVar) - powershell: | - $content = Get-Content "$(Build.SourcesDirectory)/global.json" -Raw | ConvertFrom-Json + $content = Get-Content "$env:REPOROOT/global.json" -Raw | ConvertFrom-Json $vstsCommandString = "vso[task.setvariable variable=SDKVersion]$($content.sdk.version)" Write-Host "sending " + $vstsCommandString Write-Host "##$vstsCommandString" @@ -34,13 +57,21 @@ jobs: version: '$(SDKVersion)' - task: DownloadBuildArtifacts@0 - displayName: 'Download PowerShell build artifacts' + displayName: 'Download PowerShell build artifacts - finalResults' inputs: buildType: current downloadType: single artifactName: finalResults downloadPath: '$(System.ArtifactsDirectory)' + - task: DownloadBuildArtifacts@0 + displayName: 'Download PowerShell build artifacts - macosPkgResults' + inputs: + buildType: current + downloadType: single + artifactName: macosPkgResults + downloadPath: '$(System.ArtifactsDirectory)' + - powershell: 'Get-ChildItem $(System.ArtifactsDirectory) -recurse' displayName: 'Capture downloaded artifacts' @@ -78,31 +109,32 @@ jobs: packageSources: 'https://nuget.org/api/v2' installRoot: '$(GenAPIToolPath)' - - template: shouldSign.yml - - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: shouldSign.yml + - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' - - powershell: | - Import-Module $env:BUILD_SOURCESDIRECTORY\build.psm1 - Import-Module $env:BUILD_SOURCESDIRECTORY\tools\packaging + - pwsh: | + Import-Module $env:REPOROOT\build.psm1 + Import-Module $env:REPOROOT\tools\packaging + Find-Dotnet New-ILNugetPackage -PackagePath "$(PackagePath)" -PackageVersion "$(Version)" -WinFxdBinPath '$(winFxdPath)' -LinuxFxdBinPath '$(linuxFxdPath)' -GenAPIToolPath "$(GenAPIToolPath)" displayName: 'Create Nuget Package Folders' - - powershell: | + - pwsh: | Get-ChildItem $(linuxFxdPath) Get-ChildItem $(winFxdPath) Get-ChildItem $(winFxdWinDesktopPath) displayName: Capture fxd folders - - powershell: | - Import-Module $env:BUILD_SOURCESDIRECTORY\build.psm1 - Import-Module $env:BUILD_SOURCESDIRECTORY\tools\packaging - + - pwsh: | + Import-Module $env:REPOROOT\build.psm1 + Import-Module $env:REPOROOT\tools\packaging + Find-Dotnet # Create unified package first New-GlobalToolNupkg -UnifiedPackage -LinuxBinPath "$(linuxFxdPath)" -WindowsBinPath "$(winFxdPath)" -WindowsDesktopBinPath "$(winFxdWinDesktopPath)" -PackageVersion "$(Version)" -DestinationPath "$(PackagePath)\globaltool" @@ -110,32 +142,20 @@ jobs: New-GlobalToolNupkg -LinuxBinPath "$(linuxFxdPath)" -WindowsBinPath "$(winFxdPath)" -WindowsDesktopBinPath "$(winFxdWinDesktopPath)" -PackageVersion "$(Version)" -DestinationPath "$(PackagePath)\globaltool" displayName: 'Create Global tool packages' - - powershell: | + - pwsh: | Get-ChildItem "$(PackagePath)" -Recurse displayName: Capture generated packages - - powershell: | - $packages = Get-ChildItem "$(PackagePath)\*.nupkg", "$(PackagePath)\globaltool\*.nupkg" | Select-Object -ExpandProperty FullName - - if($packages.Count -lt 1) - { - throw "No packages created" - } - - $(Build.SourcesDirectory)\tools\releaseBuild\generatePackgeSigning.ps1 -Path $(PackagePath)\NugetSigning.xml -NuPkgFiles $packages - displayName: Create signing file - - - task: PkgESCodeSign@10 - displayName: 'CodeSign Nuget Packages' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(PackagePath)\NugetSigning.xml' - inPathRoot: '$(PackagePath)' - outPathRoot: '$(System.ArtifactsDirectory)\signed' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(PackagePath) + signOutputPath: $(System.ArtifactsDirectory)\signed + certificateId: "CP-401405" + pattern: | + **\*.nupkg + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign NuPkg - pwsh: | if (-not (Test-Path '$(System.ArtifactsDirectory)\signed\')) { $null = New-Item -ItemType Directory -Path '$(System.ArtifactsDirectory)\signed\' } @@ -144,8 +164,8 @@ jobs: displayName: Fake copy when not signing condition: eq(variables['SHOULD_SIGN'], 'false') - - powershell: | - Import-Module $(Build.SourcesDirectory)\build.psm1 -Force + - pwsh: | + Import-Module "${env:REPOROOT}\build.psm1" -Force Get-ChildItem -Recurse "$(System.ArtifactsDirectory)\signed\*.nupkg" -Verbose | ForEach-Object { Start-NativeExecution -sb { nuget.exe verify -All $_.FullName } } displayName: Verify all packages are signed condition: eq(variables['SHOULD_SIGN'], 'true') @@ -163,7 +183,7 @@ jobs: parameters: artifactPath: '$(System.ArtifactsDirectory)\signed' - - powershell: | + - pwsh: | if (-not (Test-Path "$(System.ArtifactsDirectory)\signed\globaltool")) { $null = New-Item -Path "$(System.ArtifactsDirectory)\signed\globaltool" -ItemType Directory -Force @@ -173,6 +193,42 @@ jobs: Get-ChildItem "$(System.ArtifactsDirectory)\signed\globaltool" -Recurse displayName: Move global tool packages to subfolder and capture + - pwsh: | + $packagePath = (Join-Path $(System.ArtifactsDirectory) checksum) + New-Item $packagePath -ItemType Directory -Force > $null + $srcPaths = @("$(System.ArtifactsDirectory)\finalResults", "$(System.ArtifactsDirectory)\macosPkgResults", "$(System.ArtifactsDirectory)\signed") + + $packages = Get-ChildItem -Path $srcPaths -Include *.zip, *.tar.gz, *.msi*, *.pkg, *.deb, *.rpm -Exclude "PowerShell-Symbols*" -Recurse + $packages | ForEach-Object { Copy-Item $_.FullName -Destination $packagePath -Verbose } + + $packagePathList = Get-ChildItem $packagePath -Recurse | Select-Object -ExpandProperty FullName | Out-String + Write-Verbose -Verbose $packagePathList + + $checksums = Get-ChildItem -Path $packagePath | + ForEach-Object { + Write-Verbose -Verbose "Generating checksum file for $($_.FullName)" + $packageName = $_.Name + $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA512).Hash.ToLower() + + # the '*' before the packagename signifies it is a binary + "$hash *$packageName" + } + + $checksums | Out-File -FilePath "$packagePath\SHA512SUMS" -Force + + + $fileContent = Get-Content -Path "$packagePath\SHA512SUMS" -Raw | Out-String + Write-Verbose -Verbose -Message $fileContent + + Copy-Item -Path "$packagePath\SHA512SUMS" -Destination '$(System.ArtifactsDirectory)\signed\' -verbose + Copy-Item -Path "$packagePath\SHA512SUMS" -Destination '$(System.ArtifactsDirectory)\signed\globaltool\' -verbose + displayName: Generate checksum file + + - template: upload-final-results.yml + parameters: + artifactPath: '$(System.ArtifactsDirectory)\checksum' + artifactFilter: SHA512SUMS + - task: AzureFileCopy@4 displayName: 'Upload NuGet packages to Azure' inputs: diff --git a/tools/releaseBuild/azureDevOps/templates/release-BuildJson.yml b/tools/releaseBuild/azureDevOps/templates/release-BuildJson.yml index 8def847dce2..95e09b66642 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-BuildJson.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-BuildJson.yml @@ -1,51 +1,63 @@ steps: -- download: releasePipeline - artifact: BuildInfoJson +- task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: BuildInfoJson + path: '$(Pipeline.Workspace)/releasePipeline/BuildInfoJson' - pwsh: | + Import-Module '$(Build.SourcesDirectory)/tools/ci.psm1' $jsonFile = Get-Item "$ENV:PIPELINE_WORKSPACE/releasePipeline/BuildInfoJson/*.json" $fileName = Split-Path $jsonFile -Leaf $dateTime = [datetime]::UtcNow $dateTime = [datetime]::new($dateTime.Ticks - ($dateTime.Ticks % [timespan]::TicksPerSecond), $dateTime.Kind) + $metadata = Get-Content ./tools/metadata.json | ConvertFrom-Json + $stableRelease = $metadata.StableRelease.Latest + $ltsRelease = $metadata.LTSRelease.Latest + $buildInfo = Get-Content $jsonFile | ConvertFrom-Json $buildInfo.ReleaseDate = $dateTime $targetFile = "$ENV:PIPELINE_WORKSPACE/$fileName" ConvertTo-Json -InputObject $buildInfo | Out-File $targetFile -Encoding ascii - $vstsCommandString = "vso[task.setvariable variable=BuildInfoJsonFile]$targetFile" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" + if ($stableRelease -or $fileName -eq "preview.json") { + Set-BuildVariable -Name CopyMainBuildInfo -Value YES + } else { + Set-BuildVariable -Name CopyMainBuildInfo -Value NO + } + Set-BuildVariable -Name BuildInfoJsonFile -Value $targetFile ## Create 'lts.json' if it's the latest stable and also a LTS release. - $vstsCommandCopyLTSBuildInfo = "vso[task.setvariable variable=CopyLTSBuildInfo]NO" + if ($fileName -eq "stable.json") { + if ($ltsRelease) { + $ltsFile = "$ENV:PIPELINE_WORKSPACE/lts.json" + Copy-Item -Path $targetFile -Destination $ltsFile -Force + Set-BuildVariable -Name LtsBuildInfoJsonFile -Value $ltsFile + Set-BuildVariable -Name CopyLTSBuildInfo -Value YES + } else { + Set-BuildVariable -Name CopyLTSBuildInfo -Value NO + } - if ($fileName -eq "stable.json") - { - $releaseTag = $buildInfo.ReleaseTag - $version = $releaseTag -replace '^v' - $semVersion = [System.Management.Automation.SemanticVersion] $version + $releaseTag = $buildInfo.ReleaseTag + $version = $releaseTag -replace '^v' + $semVersion = [System.Management.Automation.SemanticVersion] $version - if ($semVersion.PreReleaseLabel -eq $null -and $semVersion.Minor % 2 -eq 0 -and $semVersion.Major -ge 7) - { - $ltsFile = "$ENV:PIPELINE_WORKSPACE/lts.json" - Copy-Item -Path $targetFile -Destination $ltsFile -Force - $vstsCommandLtsJsonFile = "vso[task.setvariable variable=LtsBuildInfoJsonFile]$ltsFile" - $vstsCommandCopyLTSBuildInfo = "vso[task.setvariable variable=CopyLTSBuildInfo]YES" - } - } - - Write-Host "sending " + $vstsCommandCopyLTSBuildInfo - Write-Host "##$vstsCommandCopyLTSBuildInfo" - - if ($vstsCommandLtsJsonFile) - { - Write-Host "sending " + $vstsCommandLtsJsonFile - Write-Host "##$vstsCommandLtsJsonFile" + $versionFile = "$ENV:PIPELINE_WORKSPACE/$($semVersion.Major)-$($semVersion.Minor).json" + Copy-Item -Path $targetFile -Destination $versionFile -Force + Set-BuildVariable -Name VersionBuildInfoJsonFile -Value $versionFile + Set-BuildVariable -Name CopyVersionBuildInfo -Value YES + } else { + Set-BuildVariable -Name CopyVersionBuildInfo -Value NO } displayName: Download and Capture NuPkgs @@ -57,6 +69,7 @@ steps: Destination: AzureBlob storage: '$(StorageAccount)' ContainerName: BuildInfo + condition: and(succeeded(), eq(variables['CopyMainBuildInfo'], 'YES')) - task: AzureFileCopy@2 displayName: 'AzureBlob build info ''lts.json'' Copy when needed' @@ -67,3 +80,13 @@ steps: storage: '$(StorageAccount)' ContainerName: BuildInfo condition: and(succeeded(), eq(variables['CopyLTSBuildInfo'], 'YES')) + +- task: AzureFileCopy@2 + displayName: 'AzureBlob build info ''Major-Minor.json'' Copy when needed' + inputs: + SourcePath: '$(VersionBuildInfoJsonFile)' + azureSubscription: '$(AzureFileCopySubscription)' + Destination: AzureBlob + storage: '$(StorageAccount)' + ContainerName: BuildInfo + condition: and(succeeded(), eq(variables['CopyVersionBuildInfo'], 'YES')) diff --git a/tools/releaseBuild/azureDevOps/templates/release-CreateGitHubDraft.yml b/tools/releaseBuild/azureDevOps/templates/release-CreateGitHubDraft.yml index 3b316e84cbf..6e968cca572 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-CreateGitHubDraft.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-CreateGitHubDraft.yml @@ -16,6 +16,24 @@ steps: git clone https://$(AzureDevOpsPat)@mscodehub.visualstudio.com/PowerShellCore/_git/Internal-PowerShellTeam-Tools '$(Pipeline.Workspace)/tools' displayName: Clone Internal-Tools repository +- pwsh: | + $Path = "$(System.ArtifactsDirectory)" + $OutputPath = Join-Path $Path ‘hashes.sha256’ + $srcPaths = @($Path) + $packages = Get-ChildItem -Path $srcPaths -Include * -Recurse + $checksums = $packages | + ForEach-Object { + Write-Verbose -Verbose "Generating checksum file for $($_.FullName)" + $packageName = $_.Name + $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash.ToLower() + # the '*' before the packagename signifies it is a binary + "$hash *$packageName" + } + $checksums | Out-File -FilePath $OutputPath -Force + $fileContent = Get-Content -Path $OutputPath -Raw | Out-String + Write-Verbose -Verbose -Message $fileContent + displayName: Add sha256 hashes + - pwsh: | Import-module '$(Pipeline.Workspace)/tools/Scripts/GitHubRelease.psm1' Publish-ReleaseDraft -Tag '$(ReleaseTag)' -Name '$(ReleaseTag) Release of PowerShell' -Description '<-- Update Me -->' -User PowerShell -Repository PowerShell -PackageFolder $(System.ArtifactsDirectory) -Token $(GitHubReleasePat) diff --git a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml index 7d9a49189bd..34ea848ca7e 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml @@ -12,21 +12,20 @@ jobs: pool: vmImage: ${{ parameters.imageName }} steps: - - download: releasePipeline - artifact: finalResults - patterns: '**/*.nupkg' + - checkout: self + clean: true - - task: DownloadBuildArtifacts@0 + - task: DownloadPipelineArtifact@2 inputs: - buildType: specific + source: specific project: PowerShellCore - pipeline: Co-ordinated Build Test - specificBuildWithTriggering: true - buildVersionToDownload: latest - downloadType: single - artifactName: finalResults - downloadPath: '$(Pipeline.Workspace)' - itemPattern: '*.nupkg' + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: finalResults + patterns: '**/*.nupkg' + path: '$(Pipeline.Workspace)/releasePipeline/finalResults' - pwsh: | $dotnetMetadataPath = "$(Build.SourcesDirectory)/DotnetRuntimeMetadata.json" @@ -40,23 +39,24 @@ jobs: Find-Dotnet - if(-not (Get-PackageSource -Name 'dotnet5' -ErrorAction SilentlyContinue)) + if(-not (Get-PackageSource -Name 'dotnet' -ErrorAction SilentlyContinue)) { - $nugetFeed = ([xml](Get-Content $(Build.SourcesDirectory)/nuget.config -Raw)).Configuration.packagesources.add | Where-Object { $_.Key -eq 'dotnet5' } | Select-Object -ExpandProperty Value - Register-PackageSource -Name 'dotnet5' -Location $nugetFeed -ProviderName NuGet - Write-Verbose -Message "Register new package source 'dotnet5'" -verbose + $nugetFeed = ([xml](Get-Content $(Build.SourcesDirectory)/nuget.config -Raw)).Configuration.packagesources.add | Where-Object { $_.Key -eq 'dotnet' } | Select-Object -ExpandProperty Value + Register-PackageSource -Name 'dotnet' -Location $nugetFeed -ProviderName NuGet + Write-Verbose -Message "Register new package source 'dotnet'" -verbose } ## Install latest version from the channel - Install-Dotnet -Channel "$Channel" -Version $sdkVersion + #Install-Dotnet -Channel "$Channel" -Version $sdkVersion + Start-PSBootstrap Write-Verbose -Message "Installing .NET SDK completed." -Verbose displayName: Install .NET - pwsh: | - $branch = $ENV:RESOURCES_PIPELINE_RELEASEPIPELINE_SOURCEBRANCH + $branch = $ENV:BUILD_SOURCEBRANCH $version = $branch -replace '^.*(release[-/])v' $vstsCommandString = "vso[task.setvariable variable=PowerShellVersion]$version" Write-Verbose -Message "Version is $version" -Verbose @@ -97,6 +97,11 @@ jobs: $toolPath = "$(System.DefaultWorkingDirectory)/toolPath/${{ parameters.globalToolExeName }}" + $env:DOTNET_ROOT = if ($IsWindows) { "$env:LOCALAPPDATA\Microsoft\dotnet" } else { "$env:HOME/.dotnet" } + + Write-Verbose -Verbose "DOTNET_ROOT: $env:DOTNET_ROOT" + Get-ChildItem $env:DOTNET_ROOT + $versionFound = & $toolPath -c '$PSVersionTable.PSVersion.ToString()' if ( '$(PowerShellVersion)' -ne $versionFound) diff --git a/tools/releaseBuild/azureDevOps/templates/release-MsixBundle.yml b/tools/releaseBuild/azureDevOps/templates/release-MsixBundle.yml new file mode 100644 index 00000000000..93bbbcc06d1 --- /dev/null +++ b/tools/releaseBuild/azureDevOps/templates/release-MsixBundle.yml @@ -0,0 +1,70 @@ +jobs: +- job: CreateMSIXBundle + displayName: Create .msixbundle file + pool: + vmImage: windows-latest + variables: + - group: msixTools + - group: 'Azure Blob variable group' + + steps: + - template: release-SetReleaseTagAndContainerName.yml + + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: finalResults + patterns: '**/*.msix' + path: '$(Pipeline.Workspace)\releasePipeline\msix' + + - pwsh: | + $cmd = Get-Command makeappx.exe -ErrorAction Ignore + if ($cmd) { + Write-Verbose -Verbose 'makeappx available in PATH' + $exePath = $cmd.Source + } else { + $toolsDir = '$(Pipeline.Workspace)\releasePipeline\tools' + New-Item $toolsDir -Type Directory -Force > $null + Invoke-RestMethod -Uri '$(makeappUrl)' -OutFile "$toolsDir\makeappx.zip" + Expand-Archive "$toolsDir\makeappx.zip" -DestinationPath "$toolsDir\makeappx" -Force + $exePath = "$toolsDir\makeappx\makeappx.exe" + + Write-Verbose -Verbose 'makeappx was installed:' + Get-ChildItem -Path $toolsDir -Recurse + } + + $vstsCommandString = "vso[task.setvariable variable=MakeAppxPath]$exePath" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + displayName: Install makeappx tool + + - pwsh: | + $sourceDir = '$(Pipeline.Workspace)\releasePipeline\msix' + $file = Get-ChildItem $sourceDir | Select-Object -First 1 + $prefix = ($file.BaseName -split "-win")[0] + $pkgName = "$prefix.msixbundle" + Write-Verbose -Verbose "Creating $pkgName" + + $makeappx = '$(MakeAppxPath)' + $outputDir = "$sourceDir\output" + New-Item $outputDir -Type Directory -Force > $null + & $makeappx bundle /d $sourceDir /p "$outputDir\$pkgName" + + Get-ChildItem -Path $sourceDir -Recurse + $vstsCommandString = "vso[task.setvariable variable=BundleDir]$outputDir" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + displayName: Create MsixBundle + + - pwsh: | + ## We use AzCopy v8.1 in our release pipeline, see the documentation at: + ## https://docs.microsoft.com/en-us/previous-versions/azure/storage/storage-use-azcopy + + $azcopy = "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy\AzCopy.exe" + & $azcopy /Source:$(BundleDir) /Dest:https://$(StorageAccount).blob.core.windows.net/$(AzureVersion)-private /DestKey:$(StorageAccountKey) /Pattern:*.msixbundle /Y + displayName: Upload MSIX Bundle package to Az Blob diff --git a/tools/releaseBuild/azureDevOps/templates/release-PublishPackageMsftCom.yml b/tools/releaseBuild/azureDevOps/templates/release-PublishPackageMsftCom.yml index 27d76a11fed..5257fa2d9ab 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-PublishPackageMsftCom.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-PublishPackageMsftCom.yml @@ -12,11 +12,27 @@ steps: git clone https://$(AzureDevOpsPat)@mscodehub.visualstudio.com/PowerShellCore/_git/Internal-PowerShellTeam-Tools '$(Pipeline.Workspace)/tools' displayName: Clone Internal-PowerShellTeam-Tools from MSCodeHub -- download: releasePipeline - artifact: metadata +- task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: metadata + path: '$(Pipeline.Workspace)/releasePipeline/metadata' - pwsh: | $metadata = Get-Content -Path "$ENV:PIPELINE_WORKSPACE/releasePipeline/metadata/release.json" -Raw | ConvertFrom-Json - Write-Verbose -Verbose "$(releaseTag) $(PackagesRepoPassword) $(AzureVersion) $($metadata.LTSRelease)" - & '$(Pipeline.Workspace)/tools/packages.microsoft.com/upload.ps1' -ReleaseTag "$(releaseTag)" -Secret "$(PackagesRepoPassword)" -BlobFolderName "$(AzureVersion)" -LTS:($metadata.LTSRelease) + Write-Verbose -Verbose "$(ReleaseTag) $(RepoClientCliClientID) $(RepoClientCliSecret) $(AzureVersion) $($metadata.LTSRelease.Latest)" + $params = @{ + ReleaseTag = "$(ReleaseTag)" + AadClientId = "$(RepoClientCliClientID)" + AadClientSecret = "$(RepoClientCliSecret)" + BlobFolderName = "$(AzureVersion)" + LTS = $metadata.LTSRelease.Latest + ForProduction = $true + } + & '$(Pipeline.Workspace)/tools/packages.microsoft.com/releaseLinuxPackages.ps1' @params displayName: Run release script diff --git a/tools/releaseBuild/azureDevOps/templates/release-ReleaseToNuGet.yml b/tools/releaseBuild/azureDevOps/templates/release-ReleaseToNuGet.yml index a77b0203b4f..e134e4ccc7b 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-ReleaseToNuGet.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-ReleaseToNuGet.yml @@ -1,10 +1,26 @@ steps: -- download: releasePipeline - artifact: finalResults - patterns: "**/*.nupkg" +- task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: finalResults + patterns: '**/*.nupkg' + path: '$(Pipeline.Workspace)/releasePipeline/finalResults' -- download: releasePipeline - artifact: metadata +- task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: metadata + path: '$(Pipeline.Workspace)/releasePipeline/metadata' - pwsh: | #Exclude all global tool packages. Their names start with 'PowerShell.' diff --git a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml index df2ea6085d7..8b7663f1c37 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml @@ -8,13 +8,61 @@ jobs: displayName: ${{ parameters.displayName }} pool: vmImage: ${{ parameters.imageName }} + variables: + - group: AzDevOpsArtifacts steps: - - download: releasePipeline - artifact: finalResults - patterns: '**/*.nupkg' + - checkout: self + clean: true - - download: releasePipeline - artifact: metadata + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: finalResults + patterns: '**/*.nupkg' + path: '$(Pipeline.Workspace)/releasePipeline/finalResults' + + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: metadata + path: '$(Pipeline.Workspace)/releasePipeline/metadata' + + - pwsh: | + Import-Module "$(Build.SourcesDirectory)/build.psm1" -Force + New-NugetConfigFile -NugetFeedUrl $(PSInternalNugetFeed) -UserName $(PSInternalNugetFeedUserName) -ClearTextPAT $(PSInternalNugetFeedPAT) -FeedName AzDevOpsFeed -Destination '$(Build.SourcesDirectory)/test/hosting' + + Write-Verbose -Verbose "Capture hosting folder files" + Get-ChildItem '$(Build.SourcesDirectory)/test/hosting' + + # The above cmdlet creates a lower-case nuget.config. There also exists a NuGet.config which we needed to replace. + # Hence the following workaround + + if (-not $IsWindows) { + Move-Item -Path '$(Build.SourcesDirectory)/test/hosting/nuget.config' -Destination '$(Build.SourcesDirectory)/test/hosting/NuGet.Config' -Force -ErrorAction Continue + Write-Verbose -Verbose "Capture hosting folder files after Move-Item" + Get-ChildItem '$(Build.SourcesDirectory)/test/hosting' + } + + if(-not (Test-Path "$(Build.SourcesDirectory)/test/hosting/NuGet.Config")) + { + throw "NuGet.Config is not created" + } + else + { + Write-Verbose -Verbose "Capture NuGet.Config contents" + Get-Content "$(Build.SourcesDirectory)/test/hosting/NuGet.Config" -Raw + } + displayName: Insert internal nuget feed - pwsh: | $dotnetMetadataPath = "$(Build.SourcesDirectory)/DotnetRuntimeMetadata.json" @@ -28,16 +76,17 @@ jobs: Find-Dotnet - if(-not (Get-PackageSource -Name 'dotnet5' -ErrorAction SilentlyContinue)) + if(-not (Get-PackageSource -Name 'dotnet' -ErrorAction SilentlyContinue)) { - $nugetFeed = ([xml](Get-Content $(Build.SourcesDirectory)/nuget.config -Raw)).Configuration.packagesources.add | Where-Object { $_.Key -eq 'dotnet5' } | Select-Object -ExpandProperty Value - Register-PackageSource -Name 'dotnet5' -Location $nugetFeed -ProviderName NuGet - Write-Verbose -Message "Register new package source 'dotnet5'" -verbose + $nugetFeed = ([xml](Get-Content $(Build.SourcesDirectory)/nuget.config -Raw)).Configuration.packagesources.add | Where-Object { $_.Key -eq 'dotnet' } | Select-Object -ExpandProperty Value + Register-PackageSource -Name 'dotnet' -Location $nugetFeed -ProviderName NuGet + Write-Verbose -Message "Register new package source 'dotnet'" -verbose } ## Install latest version from the channel + #Install-Dotnet -Channel "$Channel" -Version $sdkVersion - Install-Dotnet -Channel "$Channel" -Version $sdkVersion + Start-PSBootstrap Write-Verbose -Message "Installing .NET SDK completed." -Verbose @@ -51,7 +100,7 @@ jobs: $localLocation = "$(Pipeline.Workspace)/releasePipeline/finalResults" $xmlElement = @" <add key=`"local`" value=`"$localLocation`" /> - <add key="dotnet5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json" /> + <add key="dotnet" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v2" /> </packageSources> "@ diff --git a/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml b/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml index a1af9a4acdf..26229325b82 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-SetReleaseTagAndContainerName.yml @@ -1,13 +1,13 @@ steps: - pwsh: | $variable = 'releaseTag' - $branch = $ENV:RESOURCES_PIPELINE_RELEASEPIPELINE_SOURCEBRANCH - if($branch -notmatch '^.*(release[-/])') + $branch = $ENV:BUILD_SOURCEBRANCH + if($branch -notmatch '^.*((release/|rebuild/.*rebuild))') { throw "Branch name is not in release format: '$branch'" } - $releaseTag = $Branch -replace '^.*(release[-/])' + $releaseTag = $Branch -replace '^.*((release|rebuild)/)' $vstsCommandString = "vso[task.setvariable variable=$Variable]$releaseTag" Write-Verbose -Message "setting $Variable to $releaseTag" -Verbose Write-Host -Object "##$vstsCommandString" diff --git a/tools/releaseBuild/azureDevOps/templates/release-UpdateDepsJson.yml b/tools/releaseBuild/azureDevOps/templates/release-UpdateDepsJson.yml index 0d2f0df315e..55bf592c339 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-UpdateDepsJson.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-UpdateDepsJson.yml @@ -6,12 +6,31 @@ jobs: variables: - group: 'Azure Blob variable group' steps: - - download: releasePipeline - artifact: finalResults - patterns: '**/PowerShell*-win-x64.zip' + - checkout: self + clean: true - - download: releasePipeline - artifact: BuildInfoJson + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: finalResults + patterns: '**/PowerShell*-win-x64.zip' + path: '$(Pipeline.Workspace)/releasePipeline/finalResults' + + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: PowerShellCore + pipeline: '696' + preferTriggeringPipeline: true + runVersion: latestFromBranch + runBranch: '$(Build.SourceBranch)' + artifact: BuildInfoJson + path: '$(Pipeline.Workspace)/releasePipeline/BuildInfoJson' - pwsh: | $fileName = (Get-Item "$ENV:PIPELINE_WORKSPACE/releasePipeline/BuildInfoJson/*.json").BaseName @@ -26,7 +45,8 @@ jobs: displayName: Determine container name - pwsh: | - $zipFile = (Get-Item "$ENV:PIPELINE_WORKSPACE/releasePipeline/finalResults/PowerShell*-win-x64.zip") + $zipFile = Get-Item "$ENV:PIPELINE_WORKSPACE/releasePipeline/finalResults/PowerShell*-win-x64.zip" -Exclude *-symbols-* + Write-Verbose -Verbose "zipFile: $zipFile" Expand-Archive -Path $zipFile -Destination "$ENV:PIPELINE_WORKSPACE/expanded" $pwshDepsFile = Get-Item "$ENV:PIPELINE_WORKSPACE/expanded/pwsh.deps.json" diff --git a/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageBOM.yml b/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageBOM.yml new file mode 100644 index 00000000000..65eed1ef9e0 --- /dev/null +++ b/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageBOM.yml @@ -0,0 +1,43 @@ +steps: +- checkout: self + clean: true + +- pwsh: | + Get-ChildItem ENV: + displayName: Capture environment + +- template: release-SetReleaseTagAndContainerName.yml + +- pwsh: | + $name = "{0}_{1:x}" -f '$(releaseTag)', (Get-Date).Ticks + Write-Host $name + Write-Host "##vso[build.updatebuildnumber]$name" + displayName: Set Release Name + +- pwsh: | + $azcopy = "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy\AzCopy.exe" + + & $azcopy /Source:https://$(StorageAccount).blob.core.windows.net/$(AzureVersion) /Dest:$(System.ArtifactsDirectory) /S /SourceKey:$(StorageAccountKey) + displayName: Download Azure Artifacts + +- pwsh: | + Get-ChildItem $(System.ArtifactsDirectory)\* -recurse | Select-Object -ExpandProperty Name + displayName: Capture Artifact Listing + +- pwsh: | + Install-module Pester -Scope CurrentUser -Force -MaximumVersion 4.99 + displayName: Install Pester + condition: succeededOrFailed() + +- pwsh: | + Import-module './build.psm1' + Import-module './tools/packaging' + $env:PACKAGE_FOLDER = '$(System.ArtifactsDirectory)' + $path = Join-Path -Path $pwd -ChildPath './packageReleaseTests.xml' + $results = invoke-pester -Script './tools/packaging/releaseTests' -OutputFile $path -OutputFormat NUnitXml -PassThru + Write-Host "##vso[results.publish type=NUnit;mergeResults=true;runTitle=Package Release Tests;publishRunAttachments=true;resultFiles=$path;]" + if($results.TotalCount -eq 0 -or $results.FailedCount -gt 0) + { + throw "Package Release Tests failed" + } + displayName: Run packaging release tests diff --git a/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageNames.yml b/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageNames.yml index d0276ab11fe..44040f9ebb0 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageNames.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-ValidatePackageNames.yml @@ -24,7 +24,7 @@ steps: - pwsh: | $message = @() Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.rpm | ForEach-Object { - if($_.Name -notmatch 'powershell\-(preview-|lts-)?\d\.\d\.\d(_[a-z]*\.\d+)?-1.(rhel|centos).\d+\.x86_64\.rpm') + if($_.Name -notmatch 'powershell\-(preview-|lts-)?\d\.\d\.\d(_[a-z]*\.\d+)?-1.rh.x86_64\.rpm') { $messageInstance = "$($_.Name) is not a valid package name" $message += $messageInstance @@ -50,7 +50,7 @@ steps: - pwsh: | $message = @() Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.pkg | ForEach-Object { - if($_.Name -notmatch 'powershell-(lts-)?\d\.\d\.\d\-([a-z]*.\d+\-)?osx(\.10\.12)?\-x64\.pkg') + if($_.Name -notmatch 'powershell-(lts-)?\d\.\d\.\d\-([a-z]*.\d+\-)?osx(\.10\.12)?\-(x64|arm64)\.pkg') { $messageInstance = "$($_.Name) is not a valid package name" $message += $messageInstance @@ -77,7 +77,7 @@ steps: - pwsh: | $message = @() Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.deb | ForEach-Object { - if($_.Name -notmatch 'powershell(-preview|-lts)?_\d\.\d\.\d([\-~][a-z]*.\d+)?-\d\.(debian|ubuntu){1}\.\d+(\.\d+)?_amd64\.deb') + if($_.Name -notmatch 'powershell(-preview|-lts)?_\d\.\d\.\d([\-~][a-z]*.\d+)?-\d\.deb_amd64\.deb') { $messageInstance = "$($_.Name) is not a valid package name" $message += $messageInstance diff --git a/tools/releaseBuild/azureDevOps/templates/shouldSign.yml b/tools/releaseBuild/azureDevOps/templates/shouldSign.yml index affc523be6b..e3c38cb29d5 100644 --- a/tools/releaseBuild/azureDevOps/templates/shouldSign.yml +++ b/tools/releaseBuild/azureDevOps/templates/shouldSign.yml @@ -1,9 +1,12 @@ steps: - powershell: | $shouldSign = $true - if($env:BUILD_REASON -ne 'Manual') + $authenticodeCert = 'CP-230012' + $msixCert = 'CP-230012' + + if($env:IS_DAILY -eq 'true') { - $shouldSign = $false + $authenticodeCert = 'CP-460906' } if($env:SKIP_SIGNING -eq 'Yes') @@ -14,4 +17,13 @@ steps: $vstsCommandString = "vso[task.setvariable variable=SHOULD_SIGN]$($shouldSign.ToString().ToLowerInvariant())" Write-Host "sending " + $vstsCommandString Write-Host "##$vstsCommandString" + + $vstsCommandString = "vso[task.setvariable variable=MSIX_CERT]$($msixCert)" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + + $vstsCommandString = "vso[task.setvariable variable=AUTHENTICODE_CERT]$($authenticodeCert)" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + displayName: 'Set SHOULD_SIGN Variable' diff --git a/tools/releaseBuild/azureDevOps/templates/testartifacts.yml b/tools/releaseBuild/azureDevOps/templates/testartifacts.yml index dd51a95f57c..1bd715f1a46 100644 --- a/tools/releaseBuild/azureDevOps/templates/testartifacts.yml +++ b/tools/releaseBuild/azureDevOps/templates/testartifacts.yml @@ -1,11 +1,17 @@ jobs: - job: build_testartifacts variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none displayName: Build test artifacts condition: succeeded() - pool: 'Hosted Ubuntu 1604' + pool: + vmImage: ubuntu-latest steps: + - checkout: self + clean: true - pwsh: | Import-Module ./build.psm1 @@ -28,7 +34,8 @@ jobs: switch ($runtime) { - win7-x64 { $packageName = "TestPackage-win.zip" } + win7-x64 { $packageName = "TestPackage-win-x64.zip" } + win7-x86 { $packageName = "TestPackage-win-x86.zip" } linux-x64 { $packageName = "TestPackage-linux-x64.zip" } linux-arm { $packageName = "TestPackage-linux-arm.zip" } linux-arm64 { $packageName = "TestPackage-linux-arm64.zip" } @@ -41,6 +48,7 @@ jobs: } BuildTestPackage -runtime win7-x64 + BuildTestPackage -runtime win7-x86 BuildTestPackage -runtime linux-x64 BuildTestPackage -runtime linux-arm BuildTestPackage -runtime linux-arm64 diff --git a/tools/releaseBuild/azureDevOps/templates/upload-final-results.yml b/tools/releaseBuild/azureDevOps/templates/upload-final-results.yml index 341a44d02b9..07db5c6b3b8 100644 --- a/tools/releaseBuild/azureDevOps/templates/upload-final-results.yml +++ b/tools/releaseBuild/azureDevOps/templates/upload-final-results.yml @@ -6,7 +6,7 @@ parameters: steps: - powershell: | - Get-ChildItem -Path '${{ parameters.artifactPath }}' -File -filter '${{ parameters.artifactFilter }}' -ErrorAction SilentlyContinue | + Get-ChildItem -Path '${{ parameters.artifactPath }}' -Recurse -File -filter '${{ parameters.artifactFilter }}' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | ForEach-Object { Write-Host "##vso[artifact.upload containerfolder=${{ parameters.artifactName }};artifactname=${{ parameters.artifactName }}]$_" diff --git a/tools/releaseBuild/azureDevOps/templates/upload.yml b/tools/releaseBuild/azureDevOps/templates/upload.yml index a8f32b19679..3f121e2f51f 100644 --- a/tools/releaseBuild/azureDevOps/templates/upload.yml +++ b/tools/releaseBuild/azureDevOps/templates/upload.yml @@ -8,36 +8,47 @@ parameters: steps: - template: upload-final-results.yml parameters: - artifactPath: $(Build.StagingDirectory)\signedPackages - artifactFilter: PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.msi - condition: and(succeeded(), eq('${{ parameters.msi }}', 'yes')) + artifactPath: $(System.ArtifactsDirectory)\signed + artifactFilter: PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}*.zip - task: AzureFileCopy@4 - displayName: 'upload signed msi to Azure - ${{ parameters.architecture }}' + displayName: 'upload signed zip to Azure - ${{ parameters.architecture }}' inputs: - SourcePath: '$(Build.StagingDirectory)\signedPackages\PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.msi' + SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.zip' azureSubscription: '$(AzureFileCopySubscription)' Destination: AzureBlob storage: '$(StorageAccount)' ContainerName: '$(AzureVersion)' resourceGroup: '$(StorageResourceGroup)' - condition: and(succeeded(), eq('${{ parameters.msi }}', 'yes')) + condition: succeeded() + +- task: AzureFileCopy@4 + displayName: 'upload signed min-size package (for Guest Config) to Azure - ${{ parameters.architecture }}' + inputs: + SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}-gc.zip' + azureSubscription: '$(AzureFileCopySubscription)' + Destination: AzureBlob + storage: '$(StorageAccount)' + ContainerName: '$(AzureVersion)-gc' + resourceGroup: '$(StorageResourceGroup)' + condition: and(eq('${{ parameters.architecture }}', 'x64'), succeeded()) - template: upload-final-results.yml parameters: - artifactPath: $(System.ArtifactsDirectory)\signed - artifactFilter: PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.zip + artifactPath: $(System.ArtifactsDirectory)\signedPackages + artifactFilter: PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.exe + condition: and(succeeded(), eq('${{ parameters.msi }}', 'yes')) - task: AzureFileCopy@4 - displayName: 'upload signed zip to Azure - ${{ parameters.architecture }}' + displayName: 'upload signed exe to Azure - ${{ parameters.architecture }}' inputs: - SourcePath: '$(System.ArtifactsDirectory)\signed\PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.zip' + SourcePath: '$(System.ArtifactsDirectory)\signedPackages\PowerShell-${{ parameters.version }}-win-${{ parameters.architecture }}.exe' azureSubscription: '$(AzureFileCopySubscription)' Destination: AzureBlob storage: '$(StorageAccount)' - ContainerName: '$(AzureVersion)' + ContainerName: '$(AzureVersion)-private' resourceGroup: '$(StorageResourceGroup)' - condition: succeeded() + condition: and(succeeded(), eq('${{ parameters.msi }}', 'yes')) # Disable upload task as the symbols package is not currently used and we want to avoid publishing this in releases #- task: AzureFileCopy@4 diff --git a/tools/releaseBuild/azureDevOps/templates/vpackReleaseJob.yml b/tools/releaseBuild/azureDevOps/templates/vpackReleaseJob.yml index 97d3bea8d1d..e6f07d55ce5 100644 --- a/tools/releaseBuild/azureDevOps/templates/vpackReleaseJob.yml +++ b/tools/releaseBuild/azureDevOps/templates/vpackReleaseJob.yml @@ -3,10 +3,15 @@ parameters: jobs: - job: vpack_${{ parameters.architecture }} + variables: + - group: vPack + displayName: Build and Publish VPack - ${{ parameters.architecture }} condition: succeeded() - pool: Package ES Standard Build + pool: PowerShell1ES steps: + - checkout: self + clean: true - template: ./SetVersionVariables.yml parameters: @@ -69,10 +74,8 @@ jobs: displayName: Capture Environment condition: succeededOrFailed() - - task: PkgESVPack@10 + - task: PkgESVPack@12 displayName: 'Package ES - VPack ' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: sourceDirectory: '$(vpackDir)' description: PowerShell ${{ parameters.architecture }} $(version) @@ -83,4 +86,5 @@ jobs: owner: tplunk provData: false version: '$(vpackVersion)' + vpackToken: $(vPackPat) condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual')) diff --git a/tools/releaseBuild/azureDevOps/templates/windows-build.yml b/tools/releaseBuild/azureDevOps/templates/windows-build.yml deleted file mode 100644 index 8aab17585f3..00000000000 --- a/tools/releaseBuild/azureDevOps/templates/windows-build.yml +++ /dev/null @@ -1,126 +0,0 @@ -parameters: - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: x64 - -jobs: -- job: build_windows_${{ parameters.Architecture }} - displayName: Build Windows - ${{ parameters.Architecture }} - condition: succeeded() - pool: - name: Package ES Standard Build - variables: - BuildConfiguration: ${{ parameters.BuildConfiguration }} - BuildPlatform: ${{ parameters.BuildPlatform }} - Architecture: ${{ parameters.Architecture }} - - steps: - - - checkout: self - clean: true - persistCredentials: true - - - template: shouldSign.yml - - template: SetVersionVariables.yml - parameters: - ReleaseTagVar: $(ReleaseTagVar) - - - task: PkgESSetupBuild@10 - displayName: 'Initialize build' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - useDfs: false - productName: PowerShellCore - branchVersion: true - disableWorkspace: true - disableBuildTools: true - disableNugetPack: true - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - - - template: insert-nuget-config-azfeed.yml - - - powershell: | - docker container prune --force - docker container ls --all --format '{{ json .ID }}' | ConvertFrom-Json | ForEach-Object {docker container rm --force --volumes $_} - displayName: 'Remove all containers [Port to PSRelease]' - # Cleanup is not critical it passes every time it runs - continueOnError: true - - - powershell: | - docker image ls --format '{{ json .}}'|ConvertFrom-Json| ForEach-Object { - if($_.tag -eq '<none>') - { - $formatString = 'yyyy-MM-dd HH:mm:ss zz00' - $createdAtString = $_.CreatedAt.substring(0,$_.CreatedAt.Length -4) - $createdAt = [DateTime]::ParseExact($createdAtString, $formatString,[System.Globalization.CultureInfo]::InvariantCulture) - if($createdAt -lt (Get-Date).adddays(-1)) - { - docker image rm $_.ID - } - } - } - exit 0 - displayName: 'Remove old images [Port to PSRelease]' - # Cleanup is not critical it passes every time it runs - continueOnError: true - - - powershell: | - Write-verbose "--docker info---" -verbose - docker info - Write-verbose "--docker image ls---" -verbose - docker image ls - Write-verbose "--docker container ls --all---" -verbose - docker container ls --all - exit 0 - displayName: 'Capture docker info' - # Diagnostics is not critical it passes every time it runs - continueOnError: true - - - powershell: | - tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTagVar) -Name win-$(Architecture)-symbols - displayName: 'Build Windows Universal - $(Architecture) Symbols zip' - - - powershell: | - if ("$env:Architecture" -like 'fxdependent*') - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 -SkipPwshExe - } - else - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 - } - displayName: 'Update Signing Xml' - - - powershell: | - $vstsCommandString = "vso[task.setvariable variable=Symbols]${env:Symbols_$(Architecture)}" - Write-Host "sending " + $vstsCommandString - Write-Host "##$vstsCommandString" - displayName: 'Get Symbols path [Update build.json]' - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(Architecture)' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(Build.SourcesDirectory)\tools\releaseBuild\signing.xml' - inPathRoot: '$(Symbols)' - outPathRoot: '$(Symbols)\signed' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - - - powershell: | - New-Item -ItemType Directory -Path $(Symbols)\signed -Force - displayName: 'Create empty signed folder' - condition: and(succeeded(), ne(variables['SHOULD_SIGN'], 'true')) - - - powershell: | - tools/releaseBuild/vstsbuild.ps1 -ReleaseTag $(ReleaseTagVar) -Name win-$(Architecture)-package -BuildPath $(Symbols) -SignedFilesPath $(Symbols)\signed - displayName: 'Build Windows Universal - $(Architecture) Package' - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - inputs: - sourceScanPath: '$(Build.SourcesDirectory)' - snapshotForceEnabled: true diff --git a/tools/releaseBuild/azureDevOps/templates/windows-component-governance.yml b/tools/releaseBuild/azureDevOps/templates/windows-component-governance.yml index c02d5d4170d..b21ab208f1b 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-component-governance.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-component-governance.yml @@ -2,14 +2,21 @@ jobs: - job: ComponentRegistrationJob variables: - runCodesignValidationInjection: false + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none displayName: Component Registration condition: succeeded() pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 steps: + - checkout: self + clean: true - template: SetVersionVariables.yml parameters: diff --git a/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml b/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml index 39fbfe7a745..de08cb25824 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-hosted-build.yml @@ -1,41 +1,52 @@ parameters: - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: x64 - parentJob: '' + - name: BuildConfiguration + default: release + - name: BuildPlatform + default: any cpu + - name: Architecture + default: x64 + - name: parentJob + default: '' + jobs: -- job: build_windows_${{ parameters.Architecture }} - displayName: Build Windows - ${{ parameters.Architecture }} +- job: build_windows_${{ parameters.Architecture }}_${{ parameters.BuildConfiguration }} + displayName: Build Windows - ${{ parameters.Architecture }} ${{ parameters.BuildConfiguration }} condition: succeeded() dependsOn: ${{ parameters.parentJob }} pool: - vmImage: windows-latest + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - runCodesignValidationInjection: false - BuildConfiguration: ${{ parameters.BuildConfiguration }} - BuildPlatform: ${{ parameters.BuildPlatform }} - Architecture: ${{ parameters.Architecture }} - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + - name: runCodesignValidationInjection + value: false + - name: NugetSecurityAnalysisWarningLevel + value: none + - name: BuildConfiguration + value: ${{ parameters.BuildConfiguration }} + - name: BuildPlatform + value: ${{ parameters.BuildPlatform }} + - name: Architecture + value: ${{ parameters.Architecture }} + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 steps: - checkout: self clean: true - persistCredentials: true - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) - - template: insert-nuget-config-azfeed.yml + - template: cloneToOfficialPath.yml - - powershell: | - Write-Host "##vso[task.setvariable variable=PowerShellRoot]/PowerShell" - $null = New-Item -ItemType Directory -Path /Powershell -Force - git clone $env:BUILD_REPOSITORY_LOCALPATH /PowerShell - displayName: Clone PowerShell Repo to /PowerShell + - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml + parameters: + repoRoot: $(PowerShellRoot) - - powershell: | + - pwsh: | $runtime = switch ($env:Architecture) { @@ -47,10 +58,15 @@ jobs: "fxdependentWinDesktop" { "fxdependent-win-desktop" } } - tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -location '$(PowerShellRoot)' -destination '$(Build.ArtifactStagingDirectory)/Symbols_$(Architecture)' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' -Symbols - displayName: 'Build Windows Universal - $(Architecture) Symbols zip' + $params = @{} + if ($env:BuildConfiguration -eq 'minSize') { + $params['ForMinimalSize'] = $true + } + + tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -location '$(PowerShellRoot)' -destination '$(Build.ArtifactStagingDirectory)/Symbols_$(Architecture)' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' -Symbols @params + displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols zip' - - powershell: | + - pwsh: | $packageName = (Get-ChildItem '$(Build.ArtifactStagingDirectory)\Symbols_$(Architecture)').FullName $vstsCommandString = "vso[artifact.upload containerfolder=results;artifactname=results]$packageName" Write-Host ("sending " + $vstsCommandString) @@ -60,5 +76,5 @@ jobs: - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' inputs: - sourceScanPath: '$(Build.SourcesDirectory)' + sourceScanPath: '$(PowerShellRoot)' snapshotForceEnabled: true diff --git a/tools/releaseBuild/azureDevOps/templates/windows-package-signing.yml b/tools/releaseBuild/azureDevOps/templates/windows-package-signing.yml index c13008fe2b3..dd547da6a60 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-package-signing.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-package-signing.yml @@ -8,18 +8,27 @@ jobs: ${{ parameters.parentJobs }} condition: succeeded() pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - BuildConfiguration: release - BuildPlatform: any cpu + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - group: ESRP steps: + - checkout: self + clean: true + + - checkout: ComplianceRepo + clean: true - - template: shouldSign.yml - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) + - template: shouldSign.yml + - task: DownloadBuildArtifacts@0 displayName: 'Download artifacts' inputs: @@ -34,41 +43,37 @@ jobs: # Diagnostics is not critical it passes every time it runs continueOnError: true - - powershell: | - $authenticodefiles = @( - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x64.msi" - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x86.msi" - ) - - $msixFiles = @( - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x86.msix" - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-x64.msix" - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm32.msix" - "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-arm64.msix" - ) - - tools/releaseBuild/generatePackgeSigning.ps1 -AuthenticodeFiles $authenticodeFiles -path "$(System.ArtifactsDirectory)\package.xml" -MsixCertType $env:MSIX_TYPE -MsixFiles $msixFiles - displayName: 'Generate Package Signing Xml' - - - powershell: | - Get-Content "$(System.ArtifactsDirectory)\package.xml" - displayName: 'Capture signing xml' - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(System.ArtifactsDirectory)\package.xml' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\package.xml' - outPathRoot: '$(Build.StagingDirectory)\signedPackages' - binVersion: $(SigingVersion) - binVersionOverride: $(SigningVersionOverride) - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\signed + signOutputPath: $(Build.StagingDirectory)\signedPackages + certificateId: $(MSIX_CERT) + pattern: | + **\*.msix + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign msix + + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\signed + signOutputPath: $(Build.StagingDirectory)\signedPackages + certificateId: $(AUTHENTICODE_CERT) + pattern: | + **\*.exe + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign exe - powershell: | new-item -itemtype Directory -path '$(Build.StagingDirectory)\signedPackages' Get-ChildItem "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-*.msi*" | copy-item -Destination '$(Build.StagingDirectory)\signedPackages' - displayName: 'Fake Signing' + displayName: 'Fake msi* Signing' + condition: and(succeeded(), ne(variables['SHOULD_SIGN'], 'true')) + + - pwsh: | + Get-ChildItem "$(System.ArtifactsDirectory)\signed\PowerShell-$(Version)-win-*.exe" | copy-item -Destination '$(Build.StagingDirectory)\signedPackages' + displayName: 'Fake exe Signing' condition: and(succeeded(), ne(variables['SHOULD_SIGN'], 'true')) - template: upload.yml @@ -108,8 +113,13 @@ jobs: msi: no msix: no - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 - displayName: 'Run Defender Scan' + - template: EsrpScan.yml@ComplianceRepo + parameters: + scanPath: $(Build.StagingDirectory) + pattern: | + **\*.msix + **\*.msi + **\*.zip - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' diff --git a/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml index 7c1a6adadd2..03ecebaf0c0 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml @@ -1,53 +1,50 @@ parameters: - BuildConfiguration: release - BuildPlatform: any cpu - Architecture: x64 - parentJob: '' + - name: BuildConfiguration + default: release + - name: BuildPlatform + default: any cpu + - name: Architecture + default: x64 + - name: parentJob + default: '' jobs: -- job: sign_windows_${{ parameters.Architecture }} - displayName: Package Windows - ${{ parameters.Architecture }} +- job: sign_windows_${{ parameters.Architecture }}_${{ parameters.BuildConfiguration }} + displayName: Package Windows - ${{ parameters.Architecture }} ${{ parameters.BuildConfiguration }} condition: succeeded() dependsOn: ${{ parameters.parentJob }} pool: - name: Package ES Standard Build + name: PowerShell1ES + demands: + - ImageOverride -equals MMS2019 variables: - BuildConfiguration: ${{ parameters.BuildConfiguration }} - BuildPlatform: ${{ parameters.BuildPlatform }} - Architecture: ${{ parameters.Architecture }} - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + - name: BuildConfiguration + value: ${{ parameters.BuildConfiguration }} + - name: BuildPlatform + value: ${{ parameters.BuildPlatform }} + - name: Architecture + value: ${{ parameters.Architecture }} + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - group: ESRP steps: - checkout: self clean: true - persistCredentials: true - - template: shouldSign.yml + - checkout: ComplianceRepo + clean: true + - template: SetVersionVariables.yml parameters: ReleaseTagVar: $(ReleaseTagVar) - - task: PkgESSetupBuild@10 - displayName: 'Initialize build' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - useDfs: false - productName: PowerShellCore - branchVersion: true - disableWorkspace: true - disableBuildTools: true - disableNugetPack: true - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: shouldSign.yml - powershell: | - $pkgFilter = if ( '$(Architecture)' -eq 'arm' ) { - "arm32" - } - else { - '$(Architecture)' - } + $pkgFilter = if ( '$(Architecture)' -eq 'arm' ) { "arm32" } else { '$(Architecture)' } + if ($env:BuildConfiguration -eq 'minSize') { $pkgFilter += '-gc' } $vstsCommandString = "vso[task.setvariable variable=PkgFilter]$pkgFilter" Write-Host ("sending " + $vstsCommandString) @@ -60,30 +57,17 @@ jobs: itemPattern: '**/*$(PkgFilter).zip' downloadPath: '$(System.ArtifactsDirectory)\Symbols' - - powershell: | - Write-Host "##vso[task.setvariable variable=PowerShellRoot]/PowerShell" + - template: cloneToOfficialPath.yml - if ((Test-Path "\PowerShell")) { - Remove-Item -Path "\PowerShell" -Force -Recurse -Verbose - } - else { - Write-Verbose -Verbose -Message "No cleanup required." - } - - git clone --quiet $env:BUILD_REPOSITORY_LOCALPATH '\PowerShell' - - displayName: Clone PowerShell Repo to /PowerShell - errorActionPreference: silentlycontinue - - - powershell: | + - pwsh: | # cleanup previous install if((Test-Path "${env:ProgramFiles(x86)}\WiX Toolset xcopy")) { Remove-Item "${env:ProgramFiles(x86)}\WiX Toolset xcopy" -Recurse -Force } $toolsDir = New-Item -ItemType Directory -Path '$(Build.ArtifactStagingDirectory)\tools' - $wixUri = 'https://github.com/wixtoolset/wix3/releases/download/wix311rtm/wix311-binaries.zip' - Invoke-RestMethod -Uri $wixUri -OutFile '$(Build.ArtifactStagingDirectory)\tools\wix.zip' + $wixUri = 'https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip' + Invoke-RestMethod -Uri $wixUri -OutFile '$(Build.ArtifactStagingDirectory)\tools\wix.zip' -MaximumRetryCount 5 -RetryIntervalSec 10 Import-Module '$(PowerShellRoot)/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/wix.psm1' Install-WixZip -zipPath '$(Build.ArtifactStagingDirectory)\tools\wix.zip' @@ -95,8 +79,16 @@ jobs: displayName: Install packaging tools - powershell: | - $zipPath = Get-Item '$(System.ArtifactsDirectory)\Symbols\results\*$(PkgFilter).zip' - Write-Verbose -Verbose "Zip Path: $zipPath" + $zipPathString = '$(System.ArtifactsDirectory)\Symbols\results\*$(PkgFilter).zip' + Write-Verbose -Verbose "Zip Path: $zipPathString" + $zipPath = Get-Item $zipPathString + if(@($zipPath).Count -eq 0) { + throw "No files found at '$zipPathString'" + } + elseif(@($zipPath).Count -ne 1) { + $names = $zipPath.Name -join "', '" + throw "multiple files '${names}' found with '${zipPathString}'" + } $expandedFolder = $zipPath.BaseName Write-Host "sending.. vso[task.setvariable variable=SymbolsFolder]$expandedFolder" @@ -105,71 +97,141 @@ jobs: Expand-Archive -Path $zipPath -Destination "$(System.ArtifactsDirectory)\$expandedFolder" -Force displayName: Expand symbols zip - - powershell: | - if ("$env:Architecture" -like 'fxdependent*') - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 -SkipPwshExe - } - else - { - $(Build.SourcesDirectory)\tools\releaseBuild\updateSigning.ps1 - } - displayName: 'Update Signing Xml' - - - task: PkgESCodeSign@10 - displayName: 'CodeSign $(Architecture)' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(Build.SourcesDirectory)\tools\releaseBuild\signing.xml' - inPathRoot: '$(System.ArtifactsDirectory)\$(SymbolsFolder)' - outPathRoot: '$(System.ArtifactsDirectory)\signed' - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - - pwsh: | - New-Item -ItemType Directory -Path $(System.ArtifactsDirectory)\signed -Force - displayName: 'Create empty signed folder' - condition: and(succeeded(), ne(variables['SHOULD_SIGN'], 'true')) + $fullSymbolsFolder = "$(System.ArtifactsDirectory)\$($env:SYMBOLSFOLDER)" + + $filesToSignDirectory = "$(System.ArtifactsDirectory)\toBeSigned" + $null = New-Item -ItemType Directory -Path $filesToSignDirectory -Force + + $signedFilesDirectory = "$(System.ArtifactsDirectory)\signed" + $null = New-Item -ItemType Directory -Path $signedFilesDirectory -Force + + $itemsToCopyWithRecurse = @( + "$($fullSymbolsFolder)\*.ps1" + "$($fullSymbolsFolder)\Microsoft.PowerShell*.dll" + ) + + $itemsToCopy = @{ + "$($fullSymbolsFolder)\*.ps1" = "" + "$($fullSymbolsFolder)\Microsoft.Management.Infrastructure.CimCmdlets.dll" = "" + "$($fullSymbolsFolder)\Microsoft.WSMan.*.dll" = "" + "$($fullSymbolsFolder)\Modules\CimCmdlets\CimCmdlets.psd1" = "Modules\CimCmdlets" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Diagnostics\Diagnostics.format.ps1xml" = "Modules\Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Diagnostics\Event.format.ps1xml" = "Modules\Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Diagnostics\GetEvent.types.ps1xml" = "Modules\Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Diagnostics\Microsoft.PowerShell.Diagnostics.psd1" = "Modules\Microsoft.PowerShell.Diagnostics" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Host\Microsoft.PowerShell.Host.psd1" = "Modules\Microsoft.PowerShell.Host" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1" = "Modules\Microsoft.PowerShell.Management" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Security\Microsoft.PowerShell.Security.psd1" = "Modules\Microsoft.PowerShell.Security" + "$($fullSymbolsFolder)\Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1" = "Modules\Microsoft.PowerShell.Utility" + "$($fullSymbolsFolder)\Modules\Microsoft.WSMan.Management\Microsoft.WSMan.Management.psd1" = "Modules\Microsoft.WSMan.Management" + "$($fullSymbolsFolder)\Modules\Microsoft.WSMan.Management\WSMan.format.ps1xml" = "Modules\Microsoft.WSMan.Management" + "$($fullSymbolsFolder)\Modules\PSDiagnostics\PSDiagnostics.ps?1" = "Modules\PSDiagnostics" + "$($fullSymbolsFolder)\pwsh.dll" = "" + "$($fullSymbolsFolder)\System.Management.Automation.dll" = "" + } - - powershell: | + $itemsToExclude = @( + # This package is retrieved from https://www.github.com/powershell/MarkdownRender + "$($fullSymbolsFolder)\Microsoft.PowerShell.MarkdownRender.dll" + ) + + if ("$env:Architecture" -notlike 'fxdependent*') + { + $itemsToCopy += @{"$($fullSymbolsFolder)\pwsh.exe" = ""} + } + + Write-Verbose -verbose "recusively copying $($itemsToCopyWithRecurse | out-string) to $filesToSignDirectory" + Copy-Item -Path $itemsToCopyWithRecurse -Destination $filesToSignDirectory -Recurse -verbose -exclude $itemsToExclude + + foreach($pattern in $itemsToCopy.Keys) { + $destinationFolder = Join-Path $filesToSignDirectory -ChildPath $itemsToCopy.$pattern + $null = New-Item -ItemType Directory -Path $destinationFolder -Force + Write-Verbose -verbose "copying $pattern to $destinationFolder" + Copy-Item -Path $pattern -Destination $destinationFolder -Recurse -verbose + } + displayName: 'Prepare files to be signed' + + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\toBeSigned + signOutputPath: $(System.ArtifactsDirectory)\signed + certificateId: "$(AUTHENTICODE_CERT)" + pattern: | + **\*.dll + **\*.psd1 + **\*.psm1 + **\*.ps1xml + **\*.ps1 + **\*.exe + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign our binaries + + - pwsh: | Import-Module $(PowerShellRoot)/build.psm1 -Force Import-Module $(PowerShellRoot)/tools/packaging -Force $signedFilesPath = '$(System.ArtifactsDirectory)\signed\' $BuildPath = '$(System.ArtifactsDirectory)\$(SymbolsFolder)' Update-PSSignedBuildFolder -BuildPath $BuildPath -SignedFilesPath $SignedFilesPath - $dlls = Get-ChildItem $BuildPath\*.dll -Recurse + $dlls = Get-ChildItem $BuildPath\*.dll, $BuildPath\*.exe -Recurse $signatures = $dlls | Get-AuthenticodeSignature - $missingSignatures = $signatures | Where-Object { $_.status -eq 'notsigned'}| select-object -ExpandProperty Path - tools/releaseBuild/generatePackgeSigning.ps1 -ThirdPartyFiles $missingSignatures -path "$(System.ArtifactsDirectory)\thirtdparty.xml" - displayName: Create ThirdParty Signing Xml - condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + $missingSignatures = $signatures | Where-Object { $_.status -eq 'notsigned' -or $_.SignerCertificate.Issuer -notmatch '^CN=Microsoft.*'}| select-object -ExpandProperty Path - - task: PkgESCodeSign@10 - displayName: 'CodeSign ThirdParty $(Architecture)' - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - signConfigXml: '$(System.ArtifactsDirectory)\thirtdparty.xml' - inPathRoot: '$(System.ArtifactsDirectory)\$(SymbolsFolder)' - outPathRoot: '$(System.ArtifactsDirectory)\signedThirdParty' + Write-Verbose -verbose "to be signed:`r`n $($missingSignatures | Out-String)" + + $filesToSignDirectory = "$(System.ArtifactsDirectory)\thirdPartyToBeSigned" + $null = New-Item -ItemType Directory -Path $filesToSignDirectory -Force + + $signedFilesDirectory = "$(System.ArtifactsDirectory)\thirdPartySigned" + $null = New-Item -ItemType Directory -Path $signedFilesDirectory -Force + + $missingSignatures | ForEach-Object { + $pathWithoutLeaf = Split-Path $_ + $relativePath = $pathWithoutLeaf.replace($BuildPath,'') + $targetDirectory = Join-Path -Path $filesToSignDirectory -ChildPath $relativePath + if(!(Test-Path $targetDirectory)) + { + $null = New-Item -ItemType Directory -Path $targetDirectory -Force + } + Copy-Item -Path $_ -Destination $targetDirectory + } + + displayName: Create ThirdParty Signing Folder condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\thirdPartyToBeSigned + signOutputPath: $(System.ArtifactsDirectory)\thirdPartySigned + certificateId: "CP-231522" + pattern: | + **\*.dll + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign ThirdParty binaries + - powershell: | - Get-ChildItem '$(System.ArtifactsDirectory)\signedThirdParty\*' - displayName: Captrue ThirdParty Signed files + Get-ChildItem '$(System.ArtifactsDirectory)\thirdPartySigned\*' + displayName: Capture ThirdParty Signed files condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) - powershell: | Import-Module $(PowerShellRoot)/build.psm1 -Force Import-Module $(PowerShellRoot)/tools/packaging -Force - $signedFilesPath = '$(System.ArtifactsDirectory)\signedThirdParty\' + $signedFilesPath = '$(System.ArtifactsDirectory)\thirdPartySigned' $BuildPath = '$(System.ArtifactsDirectory)\$(SymbolsFolder)' Update-PSSignedBuildFolder -BuildPath $BuildPath -SignedFilesPath $SignedFilesPath displayName: Merge ThirdParty signed files with Build condition: and(succeeded(), eq(variables['SHOULD_SIGN'], 'true')) + - template: Sbom.yml@ComplianceRepo + parameters: + BuildDropPath: '$(System.ArtifactsDirectory)\$(SymbolsFolder)' + Build_Repository_Uri: $(Github_Build_Repository_Uri) + - powershell: | Import-Module $(PowerShellRoot)/build.psm1 -Force Import-Module $(PowerShellRoot)/tools/packaging -Force @@ -189,7 +251,7 @@ jobs: Write-Host "##$vstsCommandString" displayName: Compress signed files - - powershell: | + - pwsh: | $runtime = switch ($env:Architecture) { "x64" { "win7-x64" } @@ -201,10 +263,14 @@ jobs: } $signedPkg = "$(BuildPackagePath)" - Write-Verbose -Verbose -Message "signedPkg = $signedPkg" - $(PowerShellRoot)/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -BuildZip $signedPkg -location '$(PowerShellRoot)' -destination '$(System.ArtifactsDirectory)\pkgSigned' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' + $params = @{} + if ($env:BuildConfiguration -eq 'minSize') { + $params['ForMinimalSize'] = $true + } + + $(PowerShellRoot)/tools/releaseBuild/Images/microsoft_powershell_windowsservercore/PowerShellPackage.ps1 -BuildZip $signedPkg -location '$(PowerShellRoot)' -destination '$(System.ArtifactsDirectory)\pkgSigned' -Runtime $runtime -ReleaseTag '$(ReleaseTagVar)' @params displayName: 'Build Windows Universal - $(Architecture) Package' - powershell: | @@ -213,7 +279,84 @@ jobs: Write-Host "Uploading $packagePath" Write-Host "##vso[artifact.upload containerfolder=signed;artifactname=signed]$packagePath" } - displayName: Upload packages + displayName: Upload unsigned packages + + - ${{ if and(ne(variables['BuildConfiguration'],'minSize'), in(variables['Architecture'], 'x64', 'x86')) }}: + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\pkgSigned + signOutputPath: $(Build.StagingDirectory)\signedPackages + certificateId: "$(AUTHENTICODE_CERT)" + pattern: | + **\*.msi + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign MSI + alwaysCopy: true + + - pwsh: | + Get-ChildItem '$(System.ArtifactsDirectory)\signedPackages' | ForEach-Object { + $packagePath = $_.FullName + Write-Host "Uploading $packagePath" + Write-Host "##vso[artifact.upload containerfolder=finalResults;artifactname=finalResults]$packagePath" + } + displayName: Upload signed MSI to finalResults + + - task: AzureFileCopy@4 + displayName: 'upload signed msi to Azure - ${{ parameters.architecture }}' + inputs: + SourcePath: '$(Build.StagingDirectory)\signedPackages\PowerShell-$(version)-win-${{ parameters.architecture }}.msi' + azureSubscription: '$(AzureFileCopySubscription)' + Destination: AzureBlob + storage: '$(StorageAccount)' + ContainerName: '$(AzureVersion)' + resourceGroup: '$(StorageResourceGroup)' + + - pwsh: | + cd $(PowerShellRoot) + Import-Module $(PowerShellRoot)/build.psm1 -Force + Import-Module $(PowerShellRoot)/tools/packaging -Force + + $msiPath = '$(Build.StagingDirectory)\signedPackages\PowerShell-$(version)-win-${{ parameters.architecture }}.msi' + + New-ExePackage -ProductVersion '$(version)' -MsiLocationPath $msiPath -ProductTargetArchitecture ${{ parameters.architecture }} + $exePath = Get-ChildItem '.\PowerShell-*.exe' | Select-Object -First 1 -ExpandProperty fullname + $enginePath = Join-Path -Path '$(System.ArtifactsDirectory)\unsignedEngine' -ChildPath engine.exe + # Expand Burn Engine so we can sign it. + Expand-ExePackageEngine -ExePath $exePath -EnginePath $enginePath + displayName: Create exe wrapper + + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: $(System.ArtifactsDirectory)\unsignedEngine + signOutputPath: $(System.ArtifactsDirectory)\signedEngine + certificateId: "$(AUTHENTICODE_CERT)" + pattern: | + **\*.exe + useMinimatch: true + shouldSign: $(SHOULD_SIGN) + displayName: Sign Burn Engine + alwaysCopy: true + + - pwsh: | + cd '$(PowerShellRoot)' + Import-Module '$(PowerShellRoot)/build.psm1' -Force + Import-Module '$(PowerShellRoot)/tools/packaging' -Force + + $exePath = Get-ChildItem '.\PowerShell-*.exe' | Select-Object -First 1 -ExpandProperty fullname + $enginePath = Join-Path -Path '$(System.ArtifactsDirectory)\signedEngine' -ChildPath engine.exe + $enginePath | Get-AuthenticodeSignature | out-string | Write-Verbose -verbose + Compress-ExePackageEngine -ExePath $exePath -EnginePath $enginePath + displayName: Re-attach the signed Burn engine in exe wrapper + + - pwsh: | + cd '$(PowerShellRoot)' + Get-ChildItem '.\PowerShell-*.exe' | ForEach-Object { + $packagePath = $_.FullName + Write-Host "Uploading $packagePath" + Write-Host "##vso[artifact.upload containerfolder=signed;artifactname=signed]$packagePath" + } + displayName: Upload unsigned exe - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' diff --git a/tools/releaseBuild/azureDevOps/vpackRelease.yml b/tools/releaseBuild/azureDevOps/vpackRelease.yml index 48b9e833844..70091eac8b5 100644 --- a/tools/releaseBuild/azureDevOps/vpackRelease.yml +++ b/tools/releaseBuild/azureDevOps/vpackRelease.yml @@ -17,11 +17,6 @@ variables: value: 1 - group: Azure Blob variable group -# Set AzDevOps Agent to clean the machine after the end of the build -resources: -- repo: self - clean: true - jobs: - job: rename displayName: Name the build @@ -29,6 +24,8 @@ jobs: pool: vmImage: 'windows-latest' steps: + - checkout: self + clean: true - template: ./templates/SetVersionVariables.yml parameters: diff --git a/tools/releaseBuild/build.json b/tools/releaseBuild/build.json index 87d6753bcac..fe2f9d96f17 100644 --- a/tools/releaseBuild/build.json +++ b/tools/releaseBuild/build.json @@ -295,7 +295,7 @@ { "Name": "deb", "RepoDestinationPath": "/PowerShell", - "BuildCommand": "/PowerShellPackage.ps1 -location _RepoDestinationPath_ -destination _DockerVolume_ -ReleaseTag _ReleaseTag_ -TarX64 -TarArm -TarArm64", + "BuildCommand": "/PowerShellPackage.ps1 -location _RepoDestinationPath_ -destination _DockerVolume_ -ReleaseTag _ReleaseTag_ -TarX64 -TarArm -TarArm64 -TarMinSize", "DockerFile": "./tools/releaseBuild/Images/microsoft_powershell_ubuntu18.04/Dockerfile", "AdditionalContextFiles" :[ "./tools/releaseBuild/Images/GenericLinuxFiles/PowerShellPackage.ps1"], "DockerImageName": "ps-ubunutu-18-04", diff --git a/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 b/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 index e2d6735bd4d..acedbdd3388 100644 --- a/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 +++ b/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 @@ -18,7 +18,7 @@ param ( [Parameter(Mandatory, ParameterSetName = 'packageSigned')] [Parameter(Mandatory, ParameterSetName = 'IncludeSymbols')] [Parameter(Mandatory, ParameterSetName = 'Build')] - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [ValidateNotNullOrEmpty()] [string]$ReleaseTag, @@ -42,22 +42,31 @@ param ( [ValidatePattern("-signed.zip$")] [string]$BuildZip, - [string]$ArtifactName = 'result' + [Parameter(Mandatory, ParameterSetName = 'packageSigned')] + [Parameter(Mandatory, ParameterSetName = 'IncludeSymbols')] + [Parameter(Mandatory, ParameterSetName = 'Build')] + [ValidateSet('osx-x64', 'osx-arm64')] + [string]$Runtime, + + [string]$ArtifactName = 'result', + + [switch]$SkipReleaseChecks ) $repoRoot = $location -if ($Build.IsPresent -or $PSCmdlet.ParameterSetName -eq 'packageSigned') { - $releaseTagParam = @{ } +if ($Build -or $PSCmdlet.ParameterSetName -eq 'packageSigned') { + $releaseTagParam = @{} if ($ReleaseTag) { - $releaseTagParam = @{ 'ReleaseTag' = $ReleaseTag } + $releaseTagParam['ReleaseTag'] = $ReleaseTag #Remove the initial 'v' from the ReleaseTag $version = $ReleaseTag -replace '^v' $semVersion = [System.Management.Automation.SemanticVersion] $version $metadata = Get-Content "$location/tools/metadata.json" -Raw | ConvertFrom-Json - $LTS = $metadata.LTSRelease + + $LTS = $metadata.LTSRelease.Package Write-Verbose -Verbose -Message "LTS is set to: $LTS" } @@ -65,13 +74,14 @@ if ($Build.IsPresent -or $PSCmdlet.ParameterSetName -eq 'packageSigned') { Push-Location try { + $pspackageParams = @{ SkipReleaseChecks = $SkipReleaseChecks; MacOSRuntime = $Runtime } Write-Verbose -Message "Init..." -Verbose Set-Location $repoRoot Import-Module "$repoRoot/build.psm1" Import-Module "$repoRoot/tools/packaging" Sync-PSTags -AddRemoteIfMissing - if ($BootStrap.IsPresent) { + if ($BootStrap) { Start-PSBootstrap -Package } @@ -81,38 +91,37 @@ try { Remove-Item -Path $BuildZip - Start-PSPackage @releaseTagParam + Start-PSPackage @pspackageParams @releaseTagParam switch ($ExtraPackage) { - "tar" { Start-PSPackage -Type tar @releaseTagParam } + "tar" { Start-PSPackage -Type tar @pspackageParams @releaseTagParam } } if ($LTS) { - Start-PSPackage @releaseTagParam -LTS + Start-PSPackage @pspackageParams @releaseTagParam -LTS switch ($ExtraPackage) { - "tar" { Start-PSPackage -Type tar @releaseTagParam -LTS } + "tar" { Start-PSPackage -Type tar @pspackageParams @releaseTagParam -LTS } } } } - if ($Build.IsPresent) { - if ($Symbols.IsPresent) { - Start-PSBuild -Configuration 'Release' -Crossgen -NoPSModuleRestore @releaseTagParam - $pspackageParams = @{} + if ($Build) { + if ($Symbols) { + Start-PSBuild -Clean -Configuration 'Release' -NoPSModuleRestore @releaseTagParam -Runtime $Runtime $pspackageParams['Type']='zip' $pspackageParams['IncludeSymbols']=$Symbols.IsPresent Write-Verbose "Starting powershell packaging(zip)..." -Verbose Start-PSPackage @pspackageParams @releaseTagParam } else { - Start-PSBuild -Configuration 'Release' -Crossgen -PSModuleRestore @releaseTagParam - Start-PSPackage @releaseTagParam + Start-PSBuild -Configuration 'Release' -PSModuleRestore @releaseTagParam -Runtime $Runtime + Start-PSPackage @pspackageParams @releaseTagParam switch ($ExtraPackage) { - "tar" { Start-PSPackage -Type tar @releaseTagParam } + "tar" { Start-PSPackage -Type tar @pspackageParams @releaseTagParam } } if ($LTS) { Start-PSPackage @releaseTagParam -LTS switch ($ExtraPackage) { - "tar" { Start-PSPackage -Type tar @releaseTagParam -LTS } + "tar" { Start-PSPackage -Type tar @pspackageParams @releaseTagParam -LTS } } } } @@ -121,7 +130,7 @@ try { Pop-Location } -if ($Build.IsPresent -or $PSCmdlet.ParameterSetName -eq 'packageSigned') { +if ($Build -or $PSCmdlet.ParameterSetName -eq 'packageSigned') { $macPackages = Get-ChildItem "$repoRoot/powershell*" -Include *.pkg, *.tar.gz, *.zip foreach ($macPackage in $macPackages) { $filePath = $macPackage.FullName diff --git a/tools/releaseBuild/macOS/vsts.yml b/tools/releaseBuild/macOS/vsts.yml deleted file mode 100644 index b00fc9ae0b0..00000000000 --- a/tools/releaseBuild/macOS/vsts.yml +++ /dev/null @@ -1,47 +0,0 @@ -resources: -- repo: self - clean: true -queue: - name: Hosted Mac Internal -name: macOS_$(Build.SourceBranchName)_$(Build.BuildId) -steps: -#- task: <task type name>@<version> -# inputs: -# <task specific inputs> -# displayName: '<display name of task>' -- task: ShellScript@2 - inputs: - scriptPath: 'tools/releaseBuild/setReleaseTag.sh' - args: '-ReleaseTag $(ReleaseTagVar) -Variable "ReleaseTagVar"' - displayName: 'Calculate Release Tag' -- task: ShellScript@2 - inputs: - scriptPath: 'tools/installpsh-osx.sh' - displayName: 'Install pwsh' -- task: ShellScript@2 - inputs: - scriptPath: 'tools/releaseBuild/macOS/createPowerShell.sh' - displayName: 'Create /PowerShell' -- powershell: | - Write-Host "##vso[task.setvariable variable=PowerShellRoot]/PowerShell" - git clone $env:BUILD_REPOSITORY_LOCALPATH /PowerShell - displayName: Clone PowerShell Repo to /PowerShell -- task: ShellScript@2 - inputs: - scriptPath: 'tools/releaseBuild/macOS/PowerShellPackageVsts.sh' - args: '-location $(PowerShellRoot) -BootStrap' - displayName: 'Bootstrap VM' -- powershell: | - Import-Module $(Build.SourcesDirectory)/build.psm1 -Force - New-NugetConfigFile -NugetFeedUrl $(AzDevOpsFeed) -UserName $(AzDevOpsFeedUserName) -ClearTextPAT $(AzDevOpsFeedPAT) -FeedName AzDevOpsFeed -Destination "$(PowerShellRoot)/src/Modules" - - if(-not (Test-Path "$(PowerShellRoot)/src/Modules/nuget.config")) - { - throw "nuget.config is not created" - } - displayName: 'Add nuget.config for AzDevOps feed for PSGallery modules ' -- powershell: | - $env:AZDEVOPSFEEDPAT = '$(AzDevOpsFeedPAT)' - $(Build.SourcesDirectory)/tools/releaseBuild/macOS/PowerShellPackageVsts.ps1 -ReleaseTag $(ReleaseTagVar) -Destination $(System.ArtifactsDirectory) -ExtraPackage "tar" -location $(PowerShellRoot) -Build - $env:AZDEVOPSFEEDPAT = $null - displayName: 'Build and Package' diff --git a/tools/releaseBuild/setReleaseTag.ps1 b/tools/releaseBuild/setReleaseTag.ps1 index 1927eb7ae60..8d6a8c3eefe 100644 --- a/tools/releaseBuild/setReleaseTag.ps1 +++ b/tools/releaseBuild/setReleaseTag.ps1 @@ -65,11 +65,12 @@ $isDaily = $false if($ReleaseTag -eq 'fromBranch' -or !$ReleaseTag) { # Branch is named release-<semver> - if($Branch -match '^.*(release[-/])') + $releaseBranchRegex = '^.*((release/|rebuild/.*rebuild))' + if($Branch -match $releaseBranchRegex) { $msixType = 'release' Write-Verbose "release branch:" -Verbose - $releaseTag = $Branch -replace '^.*(release[-/])' + $releaseTag = $Branch -replace '^.*((release|rebuild)/)' $vstsCommandString = "vso[task.setvariable variable=$Variable]$releaseTag" Write-Verbose -Message "setting $Variable to $releaseTag" -Verbose Write-Host -Object "##$vstsCommandString" @@ -79,19 +80,27 @@ if($ReleaseTag -eq 'fromBranch' -or !$ReleaseTag) New-BuildInfoJson -ReleaseTag $releaseTag } } - elseif($branchOnly -eq 'master' -or $branchOnly -like '*dailytest*') + elseif(($branchOnly -eq 'master' -and $env:BUILD_REASON -ne 'Manual') -or $branchOnly -like '*dailytest*') { $isDaily = $true Write-Verbose "daily build" -Verbose - $metaDataJsonPath = Join-Path $PSScriptRoot -ChildPath '..\metadata.json' - $metadata = Get-Content $metaDataJsonPath | ConvertFrom-Json - $versionPart = $metadata.PreviewReleaseTag - if($versionPart -match '-.*$') - { - $versionPart = $versionPart -replace '-.*$' + $jsonPath = "${env:SYSTEM_ARTIFACTSDIRECTORY}\BuildInfoJson\daily.json" + if (test-path -Path $jsonPath) { + Write-Verbose "restoring from buildinfo json..." -Verbose + $buildInfo = Get-Content -Path $jsonPath | ConvertFrom-Json + $releaseTag = $buildInfo.ReleaseTag + } else { + Write-Verbose "creating from branch counter and metadata.json..." -Verbose + $metaDataJsonPath = Join-Path $PSScriptRoot -ChildPath '..\metadata.json' + $metadata = Get-Content $metaDataJsonPath | ConvertFrom-Json + $versionPart = $metadata.PreviewReleaseTag + if ($versionPart -match '-.*$') { + $versionPart = $versionPart -replace '-.*$' + } + + $releaseTag = "$versionPart-daily$((Get-Date).ToString('yyyyMMdd')).$($env:BRANCHCOUNTER)" } - $releaseTag = "$versionPart-daily.$((Get-Date).ToString('yyyyMMdd'))" $vstsCommandString = "vso[task.setvariable variable=$Variable]$releaseTag" Write-Verbose -Message "setting $Variable to $releaseTag" -Verbose Write-Host -Object "##$vstsCommandString" diff --git a/tools/releaseBuild/signing.xml b/tools/releaseBuild/signing.xml index 017dc425e0a..11f63fe69cc 100644 --- a/tools/releaseBuild/signing.xml +++ b/tools/releaseBuild/signing.xml @@ -8,7 +8,6 @@ <file src="__INPATHROOT__\Microsoft.PowerShell.Commands.Utility.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.Commands.Utility.dll" /> <file src="__INPATHROOT__\Microsoft.PowerShell.ConsoleHost.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.ConsoleHost.dll" /> <file src="__INPATHROOT__\Microsoft.PowerShell.CoreCLR.Eventing.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.CoreCLR.Eventing.dll" /> - <file src="__INPATHROOT__\Microsoft.PowerShell.MarkdownRender.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.MarkdownRender.dll" /> <file src="__INPATHROOT__\Microsoft.PowerShell.GlobalTool.Shim.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.GlobalTool.Shim.dll" /> <file src="__INPATHROOT__\Microsoft.PowerShell.Security.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.PowerShell.Security.dll" /> <file src="__INPATHROOT__\Microsoft.WSMan.Management.dll" signType="AuthenticodeFormer" dest="__OUTPATHROOT__\Microsoft.WSMan.Management.dll" /> diff --git a/tools/releaseBuild/vstsbuild.ps1 b/tools/releaseBuild/vstsbuild.ps1 index 4e7c4086b01..1c2d740c418 100644 --- a/tools/releaseBuild/vstsbuild.ps1 +++ b/tools/releaseBuild/vstsbuild.ps1 @@ -4,7 +4,7 @@ param( [Parameter(ParameterSetName='packageSigned')] [Parameter(ParameterSetName='Build')] - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [string]$ReleaseTag, # full paths to files to add to container to run the build diff --git a/tools/releaseToWinget.ps1 b/tools/releaseToWinget.ps1 new file mode 100644 index 00000000000..e3c1af080e3 --- /dev/null +++ b/tools/releaseToWinget.ps1 @@ -0,0 +1,166 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +param( + [Parameter(Mandatory)] + [semver] + $ReleaseVersion, + + [Parameter()] + [string] + $WingetRepoPath = "$PSScriptRoot/../../winget-pkgs", + + [Parameter()] + [string] + $FromRepository = 'rjmholt', + + [Parameter()] + [string] + $GitHubToken +) + +function GetMsiHash +{ + param( + [Parameter(Mandatory)] + [string] + $ReleaseVersion, + + [Parameter(Mandatory)] + $MsiName + ) + + $releaseParams = @{ + Tag = "v$ReleaseVersion" + OwnerName = 'PowerShell' + RepositoryName = 'PowerShell' + } + + if ($GitHubToken) { $releaseParams.AccessToken = $GitHubToken } + + $releaseDescription = (Get-GitHubRelease @releaseParams).body + + $regex = [regex]::new("powershell-$ReleaseVersion-win-x64.msi.*?([0-9A-F]{64})", 'SingleLine,IgnoreCase') + + return $regex.Match($releaseDescription).Groups[1].Value +} + +function GetThisScriptRepoUrl +{ + # Find the root of the repo + $prefix = $PSScriptRoot + while ($prefix) + { + if (Test-Path "$prefix/LICENSE.txt") + { + break + } + + $prefix = Split-Path $prefix + } + + $stem = $PSCommandPath.Substring($prefix.Length + 1).Replace('\', '/') + + return "https://github.com/PowerShell/PowerShell/blob/master/$stem" +} + +function Exec +{ + param([scriptblock]$sb) + + & $sb + + if ($LASTEXITCODE -ne 0) + { + throw "Invocation failed for '$sb'. See above errors for details" + } +} + +$ErrorActionPreference = 'Stop' + +$wingetPath = (Resolve-Path $WingetRepoPath).Path + +# Ensure we have git and PowerShellForGitHub installed +Import-Module -Name PowerShellForGitHub +$null = Get-Command git + +# Get the MSI hash from the release body +$msiName = "PowerShell-$ReleaseVersion-win-x64.msi" +$msiHash = GetMsiHash -ReleaseVersion $ReleaseVersion -MsiName $msiName + +$publisherName = 'Microsoft' + +# Create the manifest +$productName = if ($ReleaseVersion.PreReleaseLabel) +{ + 'PowerShell-Preview' +} +else +{ + 'PowerShell' +} + +$manifestDir = Join-Path $wingetPath 'manifests' 'm' $publisherName $productName $ReleaseVersion +$manifestPath = Join-Path $manifestDir "$publisherName.$productName.yaml" + +$manifestContent = @" +PackageIdentifier: $publisherName.$productName +PackageVersion: $ReleaseVersion +PackageName: $productName +Publisher: $publisherName +PackageUrl: https://microsoft.com/PowerShell +License: MIT +LicenseUrl: https://github.com/PowerShell/PowerShell/blob/master/LICENSE.txt +Moniker: $($productName.ToLower()) +ShortDescription: $publisherName.$productName +Description: PowerShell is a cross-platform (Windows, Linux, and macOS) automation and configuration tool/framework that works well with your existing tools and is optimized for dealing with structured data (e.g. JSON, CSV, XML, etc.), REST APIs, and object models. It includes a command-line shell, an associated scripting language and a framework for processing cmdlets. +Tags: +- powershell +- pwsh +Homepage: https://github.com/PowerShell/PowerShell +Installers: +- Architecture: x64 + InstallerUrl: https://github.com/PowerShell/PowerShell/releases/download/v$ReleaseVersion/$msiName + InstallerSha256: $msiHash + InstallerType: msi +PackageLocale: en-US +ManifestType: singleton +ManifestVersion: 1.0.0 + +"@ + +Push-Location $wingetPath +try +{ + $branch = "pwsh-$ReleaseVersion" + + Exec { git checkout master } + Exec { git checkout -b $branch } + + New-Item -Path $manifestDir -ItemType Directory + Set-Content -Path $manifestPath -Value $manifestContent -Encoding utf8NoBOM + + Exec { git add $manifestPath } + Exec { git commit -m "Add $productName $ReleaseVersion" } + Exec { git push origin $branch } + + $prParams = @{ + Title = "Add $productName $ReleaseVersion" + Body = "This pull request is automatically generated. See $(GetThisScriptRepoUrl)." + Head = $branch + HeadOwner = $FromRepository + Base = 'master' + Owner = 'Microsoft' + RepositoryName = 'winget-pkgs' + MaintainerCanModify = $true + } + + if ($GitHubToken) { $prParams.AccessToken = $GitHubToken } + + New-GitHubPullRequest @prParams +} +finally +{ + git checkout master + Pop-Location +} diff --git a/tools/releaseTools.psm1 b/tools/releaseTools.psm1 index 7f181c3f522..c900135aaee 100644 --- a/tools/releaseTools.psm1 +++ b/tools/releaseTools.psm1 @@ -24,7 +24,7 @@ class CommitNode { $this.Body = $body $this.IsBreakingChange = $body -match "\[breaking change\]" - if ($subject -match "\(#(\d+)\)") { + if ($subject -match "\(#(\d+)\)$") { $this.PullRequest = $Matches[1] } } @@ -36,8 +36,12 @@ $Script:powershell_team = @( "Robert Holt" "Travis Plunk" "dependabot-preview[bot]" + "dependabot[bot]" "Joey Aiello" "Tyler James Leonhardt" + "Anam Navied" + "Andrew Schwartzmeyer" + "Jason Helmick" ) # They are very active contributors, so we keep their email-login mappings here to save a few queries to Github. @@ -352,7 +356,7 @@ function Get-ChangeLog PrintChangeLog -clSection $clBuildPackage -sectionTitle 'Build and Packaging Improvements' -Compress PrintChangeLog -clSection $clDocs -sectionTitle 'Documentation and Help Content' - Write-Output "[${version}]: https://github.com/PowerShell/PowerShell/compare/${$LastReleaseTag}...${ThisReleaseTag}`n" + Write-Output "[${version}]: https://github.com/PowerShell/PowerShell/compare/${LastReleaseTag}...${ThisReleaseTag}`n" } function PrintChangeLog($clSection, $sectionTitle, [switch] $Compress) { @@ -593,12 +597,12 @@ function Update-PsVersionInCode { param( [Parameter(Mandatory)] - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [String] $NewReleaseTag, [Parameter(Mandatory)] - [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d+)?)?$")] + [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")] [String] $NextReleaseTag, diff --git a/tools/terms/FileTypeSet.xml b/tools/terms/FileTypeSet.xml deleted file mode 100644 index 2b0821d6777..00000000000 --- a/tools/terms/FileTypeSet.xml +++ /dev/null @@ -1,379 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<xmldata> -<PckFileTypes TotalTypes="35" TotalExts="198" UnsupportedFilesOnly="False"> -<Type ID="0" Check="1"> -<Name>Pure Text Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.txt</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.des</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pwd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.asm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cmd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ini</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.poc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pwt</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hpj</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.sql</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.inf</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.log</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.def</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.url</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.bat</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.aspx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.idl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.sys</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.resources</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.strings</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.md</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.yml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.yaml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.spelling</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.gitignore</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.gitattributes</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.gitmodules</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.csv</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.tsv</Ext> -</Extensions> -</Type> -<Type ID="1" Check="1"> -<Name>CodeFiles</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.frm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.inc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cpp</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cls</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.c</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hpp</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vbs</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.java</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cs</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cxx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.h</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.jav</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.bas</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.js</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.rc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.json</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.resjson</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.fs</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.fsi</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.fsx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.m</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.psm1</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.config</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ps1</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.psd1</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cmake</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.sh</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cshtml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.plist</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mof</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mc</Ext> -</Extensions> -</Type> -<Type ID="2" Check="1"> -<Name>XML Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxa</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxk</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xsl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxt</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.resx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxe</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxf</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxv</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.acctb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.accfl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xaml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ttml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ddue</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.sln</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.props</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ps1xml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.csproj</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xsd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.svg</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.clixml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.nuspec</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cdxml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.manifest</Ext> -</Extensions> -</Type> -<Type ID="3" Check="1"> -<Name>Microsoft Word Documents</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.doc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.dot</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.wiz</Ext> -</Extensions> -</Type> -<Type ID="4" Check="1"> -<Name>Microsoft Access Database Compatible</Name> -<Extensions> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.mdb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mda</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mde</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mpd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mdt</Ext> -</Extensions> -</Type> -<Type ID="5" Check="1"> -<Name>Microsoft PowerPoint Presentation</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ppt</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pot</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pps</Ext> -</Extensions> -</Type> -<Type ID="6" Check="1"> -<Name>Microsoft Publisher Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pub</Ext> -</Extensions> -</Type> -<Type ID="7" Check="1"> -<Name>Microsoft Excel Workbooks</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xls</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlt</Ext> -</Extensions> -</Type> -<Type ID="8" Check="1"> -<Name>Pure Binary Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.com</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.bin</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.tlb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.drv</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.fon</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.blg</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.gif</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.png</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.icns</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.ico</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.bmp</Ext> -<Ext Check="0" UseCustomParser="0" DllPath="" ClassName="">.pfx</Ext> -</Extensions> -</Type> -<Type ID="9" Check="1"> -<Name>Localization resource databases</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.edb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.lcl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlf</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xliff</Ext> -</Extensions> -</Type> -<Type ID="10" Check="1"> -<Name>Microsoft Project Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mpp</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mpt</Ext> -</Extensions> -</Type> -<Type ID="11" Check="1"> -<Name>Microsoft Visio Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vsd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vdx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vss</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vst</Ext> -</Extensions> -</Type> -<Type ID="12" Check="1"> -<Name>Windows Installer databases</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.msi</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.msm</Ext> -</Extensions> -</Type> -<Type ID="13" Check="1"> -<Name>Zip Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.zip</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.accdt</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.axtr</Ext> -</Extensions> -</Type> -<Type ID="14" Check="1"> -<Name>Cabinet / MS Compression Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cab</Ext> -</Extensions> -</Type> -<Type ID="15" Check="1"> -<Name>Table driven IME lexicons</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mb</Ext> -</Extensions> -</Type> -<Type ID="16" Check="1"> -<Name>IME ( IMD ) Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.imd</Ext> -</Extensions> -</Type> -<Type ID="17" Check="1"> -<Name>TrueType Font Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ttf</Ext> -</Extensions> -</Type> -<Type ID="18" Check="1"> -<Name>Microsoft Outlook Mail Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.msg</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.oft</Ext> -</Extensions> -</Type> -<Type ID="19" Check="1"> -<Name>HTML Help 2.0 Files / InfoTech5.x Storage System Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.its</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxh</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxr</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxw</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxi</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxs</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hxq</Ext> -</Extensions> -</Type> -<Type ID="20" Check="1"> -<Name>Adobe Acrobat PDF Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pdf</Ext> -</Extensions> -</Type> -<Type ID="21" Check="1"> -<Name>HTML Files / Web Page</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.htm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.dtd</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hhk</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.htw</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.asp</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.htc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.htx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.html</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.hhc</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.css</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.stm</Ext> -</Extensions> -</Type> -<Type ID="22" Check="1"> -<Name>Rich Text Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.rtf</Ext> -</Extensions> -</Type> -<Type ID="23" Check="1"> -<Name>Windows 3.x Write Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.wri</Ext> -</Extensions> -</Type> -<Type ID="24" Check="1"> -<Name>MHTML Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.eml</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.nws</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mht</Ext> -</Extensions> -</Type> -<Type ID="25" Check="1"> -<Name>Word 2007 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.docx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.docm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.dotx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.dotm</Ext> -</Extensions> -</Type> -<Type ID="26" Check="1"> -<Name>Excel 2007 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlsx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlsm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xltx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xltm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlsb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.xlam</Ext> -</Extensions> -</Type> -<Type ID="27" Check="1"> -<Name>Power Point 2007 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pptx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.pptm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.potx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.potm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ppsx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ppsm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ppam</Ext> -</Extensions> -</Type> -<Type ID="28" Check="1"> -<Name>Access 2007 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.accdb</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.accde</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.accdr</Ext> -</Extensions> -</Type> -<Type ID="29" Check="1"> -<Name>Win32/64-based executable (image) Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.exe</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.dll</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ocx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.scr</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.acm</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.rll</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.cpl</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.mui</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ax</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.ime</Ext> -</Extensions> -</Type> -<Type ID="30" Check="1"> -<Name>HTML Help 1.0 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.chm</Ext> -</Extensions> -</Type> -<Type ID="31" Check="1"> -<Name>LocStudio lsg</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.lsg</Ext> -</Extensions> -</Type> -<Type ID="32" Check="1"> -<Name>Microsoft Office OneNote Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.one</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.onepkg</Ext> -</Extensions> -</Type> -<Type ID="33" Check="1"> -<Name>Custom Parsers</Name> -<Extensions> -</Extensions> -</Type> -<Type ID="34" Check="1"> -<Name>Visio 2011 Files</Name> -<Extensions> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vstx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vsdx</Ext> -<Ext Check="1" UseCustomParser="0" DllPath="" ClassName="">.vssx</Ext> -</Extensions> -</Type> - -</PckFileTypes> -</xmldata> diff --git a/tools/terms/TermsExclusion.xml b/tools/terms/TermsExclusion.xml new file mode 100644 index 00000000000..e314fc1b7a2 --- /dev/null +++ b/tools/terms/TermsExclusion.xml @@ -0,0 +1,11 @@ +<PoliCheckExclusions> + <!-- All strings must be UPPER CASE --> + <!--Each of these exclusions is a folder name -if \[name]\exists in the file path, it will be skipped --> + <Exclusion Type="FolderPathFull">.GIT</Exclusion> + <!--Each of these exclusions is a folder name -if any folder or file starts with "\[name]", it will be skipped --> + <!--<Exclusion Type="FolderPathStart">ABC|XYZ</Exclusion>--> + <!--Each of these file types will be completely skipped for the entire scan --> + <!--<Exclusion Type="FileType">.ABC|.XYZ</Exclusion>--> + <!--The specified file names will be skipped during the scan regardless which folder they are in --> + <!--<Exclusion Type="FileName">ABC.TXT|XYZ.CS</Exclusion>--> +</PoliCheckExclusions> diff --git a/tools/windows/Reset-PWSHSystemPath.ps1 b/tools/windows/Reset-PWSHSystemPath.ps1 index 7a6a6d9e451..4b98e714525 100644 --- a/tools/windows/Reset-PWSHSystemPath.ps1 +++ b/tools/windows/Reset-PWSHSystemPath.ps1 @@ -32,11 +32,13 @@ Removes ALL PowerShell paths from the Machine level path. Good for running right before upgrading PowerShell. + .EXAMPLE .\Reset-PWSHSystemPath.ps1 -PathScope Machine, User, Process Removes all paths but the very last one when sorted in ascending order. Processes all path scopes including current process. + .EXAMPLE .\Reset-PWSHSystemPath.ps1 -PathScope Machine, User, Process -RemoveAllOccurencs @@ -53,7 +55,7 @@ ForEach ($PathScopeItem in $PathScope) { $AssembledNewPath = $NewPath = '' #From the current path scope. retrieve the array of paths that match the pathspec of PowerShell (to use as a filter) - $pathstoremove = @([Environment]::GetEnvironmentVariable("PATH","$PathScopeItem").split(';') | where { $_ -ilike "*\Program Files\Powershell\6*"}) + $pathstoremove = @([Environment]::GetEnvironmentVariable("PATH","$PathScopeItem").split(';') | Where-Object { $_ -ilike "*\Program Files\Powershell\6*"}) If (!$RemoveAllOccurences) { #If we are not removing all occurances of PowerShell paths, then remove the highest sorted path from the filter