diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 7c940b0211b..b765445ef97 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 +FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100 # Avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8548101590f..d6d78e52fb7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -82,7 +82,7 @@ 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` @@ -96,9 +96,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 index 2c51890e890..b8c8dabe08a 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ b/.github/ISSUE_TEMPLATE/Bug_Report.md @@ -2,7 +2,7 @@ name: Bug report 🐛 about: Report errors or unexpected behavior 🤔 title: "My bug report" -labels: Issue-Question +labels: Needs-Triage assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/Distribution_Request.md b/.github/ISSUE_TEMPLATE/Distribution_Request.md index ff089662700..b104df6a1be 100644 --- a/.github/ISSUE_TEMPLATE/Distribution_Request.md +++ b/.github/ISSUE_TEMPLATE/Distribution_Request.md @@ -2,7 +2,7 @@ name: Distribution Support Request about: Requests support for a new distribution title: "Distribution Support Request" -labels: Distribution-Request +labels: Distribution-Request, Needs-Triage assignees: '' --- @@ -17,16 +17,19 @@ assignees: '' - [ ] 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 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). - 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** +## Progress + +- [ ] An issues has been filed to create a Docker image in https://github.com/powershell/powershell-docker + +### For PowerShell Team **ONLY** - [ ] Docker image created - [ ] Docker image published diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.md b/.github/ISSUE_TEMPLATE/Feature_Request.md index cf91c6e3dc3..4ae10eb6e40 100644 --- a/.github/ISSUE_TEMPLATE/Feature_Request.md +++ b/.github/ISSUE_TEMPLATE/Feature_Request.md @@ -2,7 +2,7 @@ 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 +labels: Issue-Enhancement, Needs-Triage assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/Release_Process.md b/.github/ISSUE_TEMPLATE/Release_Process.md index 1932bff5c6d..0f93a4bbb70 100644 --- a/.github/ISSUE_TEMPLATE/Release_Process.md +++ b/.github/ISSUE_TEMPLATE/Release_Process.md @@ -2,7 +2,7 @@ name: Release Process about: Maintainers Only - Release Process title: "Release Process for v6.x.x" -labels: Issue-Meta +labels: Issue-Meta, Needs-Triage assignees: '' --- 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/workflows/daily.yml b/.github/workflows/daily.yml index 3447bf1803d..1535fced837 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,17 +31,17 @@ 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 $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: Create Pull Request uses: peter-evans/create-pull-request@v2 diff --git a/.globalconfig b/.globalconfig index f0cc41c388e..e5cb35160fb 100644 --- a/.globalconfig +++ b/.globalconfig @@ -100,7 +100,8 @@ dotnet_diagnostic.CA1050.severity = warning dotnet_diagnostic.CA1051.severity = silent # CA1052: Static holder types should be Static or NotInheritable -dotnet_diagnostic.CA1052.severity = none +dotnet_diagnostic.CA1052.severity = warning +dotnet_code_quality.ca1052.api_surface = private, internal # CA1054: URI-like parameters should not be strings dotnet_diagnostic.CA1054.severity = none @@ -467,7 +468,7 @@ dotnet_diagnostic.CA2247.severity = warning dotnet_diagnostic.CA2248.severity = suggestion # CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' -dotnet_diagnostic.CA2249.severity = suggestion +dotnet_diagnostic.CA2249.severity = warning # CA2300: Do not use insecure deserializer BinaryFormatter dotnet_diagnostic.CA2300.severity = none @@ -956,10 +957,10 @@ dotnet_diagnostic.IDE0074.severity = warning dotnet_diagnostic.IDE0075.severity = warning # IDE0076: InvalidSuppressMessageAttribute -dotnet_diagnostic.IDE0076.severity = silent +dotnet_diagnostic.IDE0076.severity = warning # IDE0077: LegacyFormatSuppressMessageAttribute -dotnet_diagnostic.IDE0077.severity = silent +dotnet_diagnostic.IDE0077.severity = warning # IDE0078: UsePatternCombinators dotnet_diagnostic.IDE0078.severity = silent @@ -1022,7 +1023,7 @@ dotnet_diagnostic.SA1001.severity = none dotnet_diagnostic.SA1002.severity = warning # SA1003: Symbols should be spaced correctly -dotnet_diagnostic.SA1003.severity = none +dotnet_diagnostic.SA1003.severity = warning # SA1004: Documentation lines should begin with single space dotnet_diagnostic.SA1004.severity = none @@ -1232,7 +1233,7 @@ dotnet_diagnostic.SA1203.severity = none dotnet_diagnostic.SA1204.severity = none # SA1205: Partial elements should declare access -dotnet_diagnostic.SA1205.severity = none +dotnet_diagnostic.SA1205.severity = warning # SA1206: Declaration keywords should follow order dotnet_diagnostic.SA1206.severity = none @@ -1256,16 +1257,16 @@ dotnet_diagnostic.SA1211.severity = none dotnet_diagnostic.SA1212.severity = warning # SA1213: Event accessors should follow order -dotnet_diagnostic.SA1213.severity = none +dotnet_diagnostic.SA1213.severity = warning # SA1214: Readonly fields should appear before non-readonly fields dotnet_diagnostic.SA1214.severity = none # SA1216: Using static directives should be placed at the correct location -dotnet_diagnostic.SA1216.severity = none +dotnet_diagnostic.SA1216.severity = warning # SA1217: Using static directives should be ordered alphabetically -dotnet_diagnostic.SA1217.severity = none +dotnet_diagnostic.SA1217.severity = warning # SA1300: Element should begin with upper-case letter dotnet_diagnostic.SA1300.severity = none @@ -1307,7 +1308,7 @@ dotnet_diagnostic.SA1312.severity = none dotnet_diagnostic.SA1313.severity = none # SA1314: Type parameter names should begin with T -dotnet_diagnostic.SA1314.severity = none +dotnet_diagnostic.SA1314.severity = warning # SA1316: Tuple element names should use correct casing dotnet_diagnostic.SA1316.severity = none @@ -1367,7 +1368,7 @@ dotnet_diagnostic.SA1502.severity = none dotnet_diagnostic.SA1503.severity = none # SA1504: All accessors should be single-line or multi-line -dotnet_diagnostic.SA1504.severity = none +dotnet_diagnostic.SA1504.severity = warning # SA1505: Opening braces should not be followed by blank line dotnet_diagnostic.SA1505.severity = none diff --git a/.spelling b/.spelling index 89f6593204d..49f92230d7a 100644 --- a/.spelling +++ b/.spelling @@ -443,6 +443,7 @@ launch.json ldspits lee303 Leonhardt +libicu libpsl libpsl-native libunwind8 @@ -953,6 +954,7 @@ v6.2.3 v6.2.4 v7.0.0 v7.0.3 +v7.0.4 v7.1.0 validatenotnullorempty versioned @@ -1009,6 +1011,48 @@ 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 - CHANGELOG.md aavdberg asrosent @@ -1148,6 +1192,7 @@ PkgES Microsoft.PowerShell.Native rtm.20526.5 jcotton42 +RPMs - CHANGELOG/preview.md Gimly jborean93 @@ -1168,3 +1213,70 @@ 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 + diff --git a/.vsts-ci/linux.yml b/.vsts-ci/linux.yml index 04451cba405..be7de6d8fc5 100644 --- a/.vsts-ci/linux.yml +++ b/.vsts-ci/linux.yml @@ -30,6 +30,8 @@ pr: - .vsts-ci/misc-analysis.yml - .github/ISSUE_TEMPLATE/* - .dependabot/config.yml + - .vsts-ci/windows.yml + - .vsts-ci/windows/* variables: DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/.vsts-ci/mac.yml b/.vsts-ci/mac.yml index 55666e05d03..5f487275bf2 100644 --- a/.vsts-ci/mac.yml +++ b/.vsts-ci/mac.yml @@ -31,6 +31,8 @@ pr: - .dependabot/config.yml - tools/releaseBuild/* - tools/releaseBuild/azureDevOps/templates/* + - /.vsts-ci/windows.yml + - /.vsts-ci/windows/* variables: DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -92,6 +94,10 @@ stages: vmImage: macOS-latest steps: - pwsh: | + # Remove old .NET SDKs + if (Test-Path -Path $HOME/.dotnet) { + Remove-Item $HOME/.dotnet -Recurse -Force + } Import-Module .\tools\ci.psm1 New-CodeCoverageAndTestPackage displayName: CodeCoverage and Test Package diff --git a/.vsts-ci/templates/ci-build.yml b/.vsts-ci/templates/ci-build.yml index 1838d99b060..9dc43bc8ebf 100644 --- a/.vsts-ci/templates/ci-build.yml +++ b/.vsts-ci/templates/ci-build.yml @@ -22,11 +22,18 @@ jobs: - template: /tools/releaseBuild/azureDevOps/templates/insert-nuget-config-azfeed.yml + - pwsh: | + if (Test-Path -Path $HOME/.dotnet) { + Remove-Item $HOME/.dotnet -Recurse -Force + } + displayName: Remove Old .NET SDKs + condition: succeededOrFailed() + - pwsh: | Import-Module .\tools\ci.psm1 Invoke-CIInstall -SkipUser displayName: Bootstrap - condition: succeededOrFailed() + condition: succeeded() - powershell: | Import-Module .\tools\ci.psm1 diff --git a/.vsts-ci/templates/nix-test.yml b/.vsts-ci/templates/nix-test.yml index 0938a93bcf9..6a1b6e6f9de 100644 --- a/.vsts-ci/templates/nix-test.yml +++ b/.vsts-ci/templates/nix-test.yml @@ -33,11 +33,17 @@ jobs: displayName: 'Capture Artifacts Directory' continueOnError: true + - pwsh: | + if (Test-Path -Path $HOME/.dotnet) { + Remove-Item $HOME/.dotnet -Recurse -Force + } + displayName: Remove Old .NET SDKs + condition: succeededOrFailed() + - pwsh: | 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-test.yml b/.vsts-ci/templates/windows-test.yml index a153b563e3f..b021e45f000 100644 --- a/.vsts-ci/templates/windows-test.yml +++ b/.vsts-ci/templates/windows-test.yml @@ -34,10 +34,21 @@ 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 .\tools\ci.psm1 diff --git a/.vsts-ci/windows-daily.yml b/.vsts-ci/windows-daily.yml index a13714782d0..dd3ad6ef2f8 100644 --- a/.vsts-ci/windows-daily.yml +++ b/.vsts-ci/windows-daily.yml @@ -165,9 +165,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 6554e3f38e5..bdaa015832e 100644 --- a/.vsts-ci/windows.yml +++ b/.vsts-ci/windows.yml @@ -73,11 +73,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/templates/windows-packaging.yml b/.vsts-ci/windows/templates/windows-packaging.yml similarity index 59% rename from .vsts-ci/templates/windows-packaging.yml rename to .vsts-ci/windows/templates/windows-packaging.yml index 455efbb9fec..19d2be32618 100644 --- a/.vsts-ci/templates/windows-packaging.yml +++ b/.vsts-ci/windows/templates/windows-packaging.yml @@ -1,16 +1,18 @@ parameters: pool: 'Hosted VS2017' jobName: 'win_packaging' + architecture: 'x64' + channel: 'preview' parentJobs: [] jobs: -- job: ${{ parameters.jobName }} +- job: ${{ parameters.jobName }}_${{ parameters.channel }}_${{ parameters.architecture }} dependsOn: ${{ parameters.parentJobs }} pool: name: ${{ parameters.pool }} - displayName: Windows Packaging + displayName: Windows Packaging - ${{ parameters.architecture }} - ${{ parameters.channel }} steps: - powershell: | @@ -20,15 +22,14 @@ jobs: - 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 + Invoke-CIInstall -SkipUser displayName: Bootstrap - condition: succeededOrFailed() + condition: succeeded() - pwsh: | Import-Module .\tools\ci.psm1 New-CodeCoverageAndTestPackage - Invoke-CIFinish -NuGetKey $(NUGET_KEY) + Invoke-CIFinish -Runtime win7-${{ parameters.architecture }} -channel ${{ parameters.channel }} displayName: Build and Test Package diff --git a/.vsts-ci/windows/windows-packaging.yml b/.vsts-ci/windows/windows-packaging.yml new file mode 100644 index 00000000000..e3edb42d4c4 --- /dev/null +++ b/.vsts-ci/windows/windows-packaging.yml @@ -0,0 +1,85 @@ +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: + include: + - /.vsts-ci/templates/windows-packaging.yml + - /.vsts-ci/windows-packaging.yml + - /global.json + - /src/* + - /tools/ci.psm1 + - /tools/packaging/* + - /assets/* + +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/templates/windows-packaging.yml + - /.vsts-ci/windows-packaging.yml + - /global.json + - /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.LocalAccounts/Microsoft.PowerShell.LocalAccounts.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/* + - /assets/files.wxs + - /assets/Product.wxs + +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 + +resources: +- repo: self + clean: true +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 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 index d0b16622b8c..14b63bff789 100644 --- a/Analyzers.props +++ b/Analyzers.props @@ -1,5 +1,5 @@ - + diff --git a/CHANGELOG/7.0.md b/CHANGELOG/7.0.md index e80c0b179fc..6949601fc5d 100644 --- a/CHANGELOG/7.0.md +++ b/CHANGELOG/7.0.md @@ -1,5 +1,48 @@ # 7.0 Changelog +## [7.0.4] - 2021-01-19 + +### Build and Packaging Improvements + +
+ + +Bump .NET SDK to version 3.1.405 + + + + +
+ +[7.0.4]: https://github.com/PowerShell/PowerShell/compare/v7.0.3...v7.0.4 + ## [7.0.3] - 2020-07-16 ### Tests diff --git a/CHANGELOG/7.1.md b/CHANGELOG/7.1.md index a51cfcb7a41..6f92dd03b54 100644 --- a/CHANGELOG/7.1.md +++ b/CHANGELOG/7.1.md @@ -1,5 +1,37 @@ # 7.1 Changelog +## [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 + +
+ + + +
+ +[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 diff --git a/CHANGELOG/preview.md b/CHANGELOG/preview.md index afc36040313..7f33e7a2d3b 100644 --- a/CHANGELOG/preview.md +++ b/CHANGELOG/preview.md @@ -1,5 +1,111 @@ # Current preview release +## [7.2.0-preview.3] - 2021-02-11 + +### Breaking Changes + +- Fix `Get-Date -UFormat %u` behavior to comply with ISO 8601 (#14549) (Thanks @brianary!) + +### Engine Updates and Fixes + +- 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

+ +
+ + + +
+ +### 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 + +
+ + + +
+ +### 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 diff --git a/DotnetRuntimeMetadata.json b/DotnetRuntimeMetadata.json index 84cdf2ce88f..418291f1a39 100644 --- a/DotnetRuntimeMetadata.json +++ b/DotnetRuntimeMetadata.json @@ -1,8 +1,11 @@ { "sdk": { - "channel": "release/5.0.1xx", - "packageVersionPattern": "5.0.0", - "sdkImageVersion": "5.0.100", - "nextChannel": "net5/rc2" + "channel": "release/6.0.1xx-preview1", + "packageVersionPattern": "6.0.0-preview.1", + "sdkImageVersion": "6.0.100", + "nextChannel": "net6/preview1" + }, + "internalfeed" : { + "url": null } } diff --git a/PowerShell.Common.props b/PowerShell.Common.props index 2e9f8e6f63b..73110a79695 100644 --- a/PowerShell.Common.props +++ b/PowerShell.Common.props @@ -97,7 +97,7 @@ Microsoft Corporation (c) Microsoft Corporation. - net5.0 + net6.0 9.0 true diff --git a/README.md b/README.md index bddb85540ac..e59e1576b64 100644 --- a/README.md +++ b/README.md @@ -62,54 +62,54 @@ You can also download the PowerShell binary archives for Windows, macOS and Linu | 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-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x86.msi -[lts-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/PowerShell-7.0.3-win-x64.msi -[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.1.0/PowerShell-7.1.0-win-x64.msi -[rl-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/PowerShell-7.1.0-win-x86.msi -[rl-ubuntu20]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.ubuntu.20.04_amd64.deb -[rl-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.ubuntu.18.04_amd64.deb -[rl-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.ubuntu.16.04_amd64.deb -[rl-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.debian.9_amd64.deb -[rl-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.debian.10_amd64.deb -[rl-debian11]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell_7.1.0-1.debian.11_amd64.deb -[rl-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-1.rhel.7.x86_64.rpm -[rl-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-1.centos.8.x86_64.rpm -[rl-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-osx-x64.pkg -[rl-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/PowerShell-7.1.0-win-arm64.zip -[rl-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/PowerShell-7.1.0-win-x86.zip -[rl-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/PowerShell-7.1.0-win-x64.zip -[rl-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-osx-x64.tar.gz -[rl-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-linux-x64.tar.gz -[rl-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-linux-arm32.tar.gz -[rl-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.0/powershell-7.1.0-linux-arm64.tar.gz +[lts-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/PowerShell-7.0.4-win-x86.msi +[lts-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/PowerShell-7.0.4-win-x64.msi +[lts-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts_7.0.4-1.ubuntu.18.04_amd64.deb +[lts-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts_7.0.4-1.ubuntu.16.04_amd64.deb +[lts-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts_7.0.4-1.debian.9_amd64.deb +[lts-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts_7.0.4-1.debian.10_amd64.deb +[lts-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts-7.0.4-1.rhel.7.x86_64.rpm +[lts-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts-7.0.4-1.centos.8.x86_64.rpm +[lts-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.0.4/powershell-lts-7.0.4-osx-x64.pkg + +[rl-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/PowerShell-7.1.1-win-x64.msi +[rl-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/PowerShell-7.1.1-win-x86.msi +[rl-ubuntu20]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.ubuntu.20.04_amd64.deb +[rl-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.ubuntu.18.04_amd64.deb +[rl-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.ubuntu.16.04_amd64.deb +[rl-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.debian.9_amd64.deb +[rl-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.debian.10_amd64.deb +[rl-debian11]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell_7.1.1-1.debian.11_amd64.deb +[rl-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-1.rhel.7.x86_64.rpm +[rl-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-1.centos.8.x86_64.rpm +[rl-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-osx-x64.pkg +[rl-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/PowerShell-7.1.1-win-arm64.zip +[rl-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/PowerShell-7.1.1-win-x86.zip +[rl-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/PowerShell-7.1.1-win-x64.zip +[rl-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-osx-x64.tar.gz +[rl-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-linux-x64.tar.gz +[rl-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-linux-arm32.tar.gz +[rl-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.1.1/powershell-7.1.1-linux-arm64.tar.gz [rl-snap]: https://snapcraft.io/powershell -[pv-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/PowerShell-7.2.0-preview.1-win-x64.msi -[pv-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/PowerShell-7.2.0-preview.1-win-x86.msi -[pv-ubuntu20]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.ubuntu.20.04_amd64.deb -[pv-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.ubuntu.18.04_amd64.deb -[pv-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.ubuntu.16.04_amd64.deb -[pv-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.debian.9_amd64.deb -[pv-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.debian.10_amd64.deb -[pv-debian11]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview_7.2.0-preview.1-1.debian.11_amd64.deb -[pv-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview-7.2.0_preview.1-1.rhel.7.x86_64.rpm -[pv-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-preview-7.2.0_preview.1-1.centos.8.x86_64.rpm -[pv-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-7.2.0-preview.1-osx-x64.pkg -[pv-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/PowerShell-7.2.0-preview.1-win-arm64.zip -[pv-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/PowerShell-7.2.0-preview.1-win-x86.zip -[pv-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/PowerShell-7.2.0-preview.1-win-x64.zip -[pv-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-7.2.0-preview.1-osx-x64.tar.gz -[pv-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-7.2.0-preview.1-linux-x64.tar.gz -[pv-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-7.2.0-preview.1-linux-arm32.tar.gz -[pv-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.1/powershell-7.2.0-preview.1-linux-arm64.tar.gz +[pv-windows-64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/PowerShell-7.2.0-preview.2-win-x64.msi +[pv-windows-86]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/PowerShell-7.2.0-preview.2-win-x86.msi +[pv-ubuntu20]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.ubuntu.20.04_amd64.deb +[pv-ubuntu18]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.ubuntu.18.04_amd64.deb +[pv-ubuntu16]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.ubuntu.16.04_amd64.deb +[pv-debian9]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.debian.9_amd64.deb +[pv-debian10]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.debian.10_amd64.deb +[pv-debian11]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview_7.2.0-preview.2-1.debian.11_amd64.deb +[pv-centos]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview-7.2.0_preview.2-1.rhel.7.x86_64.rpm +[pv-centos8]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-preview-7.2.0_preview.2-1.centos.8.x86_64.rpm +[pv-macos]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-7.2.0-preview.2-osx-x64.pkg +[pv-winarm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/PowerShell-7.2.0-preview.2-win-arm64.zip +[pv-winx86-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/PowerShell-7.2.0-preview.2-win-x86.zip +[pv-winx64-zip]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/PowerShell-7.2.0-preview.2-win-x64.zip +[pv-macos-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-7.2.0-preview.2-osx-x64.tar.gz +[pv-linux-tar]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-7.2.0-preview.2-linux-x64.tar.gz +[pv-arm32]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-7.2.0-preview.2-linux-arm32.tar.gz +[pv-arm64]: https://github.com/PowerShell/PowerShell/releases/download/v7.2.0-preview.2/powershell-7.2.0-preview.2-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 @@ -143,6 +143,18 @@ 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/). +## Discussions + +[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. + +Create or join a [discussion](https://github.com/PowerShell/PowerShell/discussions). + ## Chat Want to chat with other members of the PowerShell community? diff --git a/assets/files.wxs b/assets/files.wxs index 199e964fe17..05a7446573a 100644 --- a/assets/files.wxs +++ b/assets/files.wxs @@ -104,9 +104,6 @@ - - - @@ -1599,18 +1596,9 @@ - - - - - - - - - @@ -1620,6 +1608,18 @@ + + + + + + + + + + + + @@ -3054,8 +3054,17 @@ - - + + + + + + + + + + + @@ -3095,7 +3104,6 @@ - @@ -3593,10 +3601,7 @@ - - - @@ -4041,7 +4046,14 @@ - + + + + + + + + diff --git a/build.psm1 b/build.psm1 index c6eb8624a41..76f14041536 100644 --- a/build.psm1 +++ b/build.psm1 @@ -397,7 +397,8 @@ 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 + $Arguments = @("publish","--no-restore","/property:GenerateFullPaths=true", "/property:ErrorOnDuplicatePublishOutputFiles=false") if ($Output -or $SMAOnly) { $Arguments += "--output", (Split-Path $Options.Output) } @@ -587,8 +588,12 @@ 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 @@ -598,7 +603,7 @@ Fix steps: } } - ConvertTo-Json $expFeatures.ToArray() + ConvertTo-Json $expFeatures } $config += @{ ExperimentalFeatures = ([string[]] ($json | ConvertFrom-Json)) } @@ -748,8 +753,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 diff --git a/docs/community/governance.md b/docs/community/governance.md index 5b93ddeec51..d32cceb393f 100644 --- a/docs/community/governance.md +++ b/docs/community/governance.md @@ -94,7 +94,7 @@ For more information on Repository Maintainers--their responsibilities, who they Area Experts are people with knowledge of specific components or technologies in the PowerShell domain. They are responsible for code reviews, issue triage, and providing their expertise to others. -They have [write access](https://help.github.com/articles/permission-levels-for-an-organization-repository/) to the PowerShell repository 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 repository which gives them the power to: 1. `git push` to all branches *except* `master`. 1. Merge pull requests to all branches *except* `master` (though this should not be common given that [`master`is the only long-living branch](../git/README.md#understand-branches)). 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/global.json b/global.json index ee8f712f95d..a6b7a831364 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "5.0.100" + "version": "6.0.100-preview.1.21104.4" } } diff --git a/nuget.config b/nuget.config index 760e780c8ec..a8ed27bf99e 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,7 @@ - + diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs index 184a3537fec..25400514401 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs @@ -83,7 +83,7 @@ protected void GetCimInstanceInternal(CimBaseCommand cmdlet) GetComputerName(cmdlet)); string nameSpace; List proxys = new(); - bool isGetCimInstanceCommand = (cmdlet is GetCimInstanceCommand); + bool isGetCimInstanceCommand = cmdlet is GetCimInstanceCommand; CimInstance targetCimInstance = null; switch (cmdlet.ParameterSetName) { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs index 5e548a405ac..c27c7493ddb 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs @@ -115,8 +115,8 @@ internal class AsyncResultCompleteEventArgs : AsyncResultEventArgsBase /// public AsyncResultCompleteEventArgs( CimSession session, - IObservable observable) : - base(session, observable, AsyncResultType.Completion) + IObservable observable) + : base(session, observable, AsyncResultType.Completion) { } } @@ -137,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; } @@ -162,8 +162,8 @@ 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; } @@ -179,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; } diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs index f03f76c09dd..28d530ed6a3 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs @@ -604,7 +604,7 @@ internal IEnumerable QuerySession(IEnumerable nameArray, 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)) @@ -644,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)) diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs index 40a1f390b0d..dfbfe090ddc 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs @@ -344,7 +344,7 @@ public CimSessionProxy(CimSessionProxy proxy) public CimSessionProxy(string computerName) { CreateSetSession(computerName, null, null, null, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// @@ -360,7 +360,7 @@ public CimSessionProxy(string computerName) public CimSessionProxy(string computerName, CimSessionOptions sessionOptions) { CreateSetSession(computerName, null, sessionOptions, null, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// @@ -403,7 +403,7 @@ 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); } @@ -421,7 +421,7 @@ public CimSessionProxy(string computerName, CimInstance cimInstance) public CimSessionProxy(string computerName, CimSessionOptions sessionOptions, CimOperationOptions operOptions) { CreateSetSession(computerName, null, sessionOptions, operOptions, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// @@ -436,7 +436,7 @@ public CimSessionProxy(string computerName, CimSessionOptions sessionOptions, Ci public CimSessionProxy(string computerName, CimOperationOptions operOptions) { CreateSetSession(computerName, null, null, operOptions, false); - this.isDefaultSession = (computerName == ConstValue.NullComputerName); + this.isDefaultSession = computerName == ConstValue.NullComputerName; } /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs index 306bb57e288..ea592b40b90 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs @@ -76,7 +76,10 @@ public GetCimAssociatedInstanceCommand() [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return CimInstance; } + get + { + return CimInstance; + } set { @@ -118,7 +121,10 @@ public CimInstance InputObject [Parameter] public Uri ResourceUri { - get { return resourceUri; } + get + { + return resourceUri; + } set { @@ -146,7 +152,10 @@ public Uri ResourceUri [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -168,7 +177,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public Microsoft.Management.Infrastructure.CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs index 0d9de236f05..d4ab679f0a7 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs @@ -92,7 +92,10 @@ public GetCimClassCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -118,7 +121,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -208,7 +214,7 @@ protected override void EndProcessing() /// private CimGetCimClass GetOperationAgent() { - return (this.AsyncOperation as CimGetCimClass); + return this.AsyncOperation as CimGetCimClass; } /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs index b2f00a0e624..cc4de5e84e9 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs @@ -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 { @@ -270,7 +288,10 @@ public string Namespace [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return CimInstance; } + get + { + return CimInstance; + } set { @@ -297,7 +318,10 @@ public CimInstance InputObject ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -326,7 +350,10 @@ public string Query public string QueryDialect { - get { return queryDialect; } + get + { + return queryDialect; + } set { @@ -354,7 +381,10 @@ public string QueryDialect [Parameter(ParameterSetName = CimBaseCommand.QuerySessionSet)] public SwitchParameter Shallow { - get { return shallow; } + get + { + return shallow; + } set { @@ -381,7 +411,10 @@ public SwitchParameter Shallow ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] public string Filter { - get { return filter; } + get + { + return filter; + } set { @@ -410,7 +443,10 @@ public string Filter [Alias("SelectProperties")] public string[] Property { - get { return SelectProperties; } + get + { + return SelectProperties; + } set { @@ -474,7 +510,7 @@ protected override void EndProcessing() /// private CimGetInstance GetOperationAgent() { - return (this.AsyncOperation as CimGetInstance); + return this.AsyncOperation as CimGetInstance; } /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs index 0be1b643f79..a402d58d0d3 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs @@ -58,7 +58,10 @@ public GetCimSessionCommand() [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -80,7 +83,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public UInt32[] Id { - get { return id; } + get + { + return id; + } set { @@ -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 { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs index 4377aeacfa4..f920094ae15 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs @@ -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,7 +197,10 @@ public string QueryDialect [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return CimInstance; } + get + { + return CimInstance; + } set { @@ -224,7 +242,10 @@ public CimInstance InputObject [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -264,7 +285,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -294,7 +318,10 @@ public CimSession[] CimSession [Alias("Name")] public string MethodName { - get { return methodName; } + get + { + return methodName; + } set { @@ -325,7 +352,10 @@ public string MethodName ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs index e3daf3e0ede..b43b1e275d7 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs @@ -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 { @@ -190,7 +202,10 @@ public CimClass CimClass ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] public string Namespace { - get { return nameSpace; } + get + { + return nameSpace; + } set { @@ -231,7 +246,10 @@ public string Namespace [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public CimSession[] CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -263,7 +281,10 @@ public CimSession[] CimSession [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] ComputerName { - get { return computerName; } + get + { + return computerName; + } set { @@ -291,7 +312,10 @@ public string[] ComputerName ParameterSetName = CimBaseCommand.CimClassSessionSet)] public SwitchParameter ClientOnly { - get { return clientOnly; } + get + { + return clientOnly; + } set { @@ -371,7 +395,7 @@ protected override void EndProcessing() /// private CimNewCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimNewCimInstance); + return this.AsyncOperation as CimNewCimInstance; } /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs index a4a93419e70..2d1a91f5c0e 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs @@ -33,7 +33,10 @@ public sealed class NewCimSessionCommand : CimBaseCommand ParameterSetName = CredentialParameterSet)] public PasswordAuthenticationMechanism Authentication { - get { return authentication; } + get + { + return authentication; + } set { @@ -103,7 +106,10 @@ public PasswordAuthenticationMechanism Authentication [Parameter(ValueFromPipelineByPropertyName = true)] public UInt32 OperationTimeoutSec { - get { return operationTimeout; } + get + { + return operationTimeout; + } set { @@ -132,7 +138,10 @@ public UInt32 OperationTimeoutSec [Parameter(ValueFromPipelineByPropertyName = true)] public UInt32 Port { - get { return port; } + get + { + return port; + } set { @@ -225,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; diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs index 7fb8f91b9dc..0b62b79d96c 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs @@ -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 { @@ -212,7 +233,10 @@ public Uri HttpPrefix ParameterSetName = WSManParameterSet)] public UInt32 MaxEnvelopeSizeKB { - get { return maxenvelopesizekb; } + get + { + return maxenvelopesizekb; + } set { @@ -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 { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs index 159a75ed3ef..246a95f37e3 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs @@ -50,7 +50,10 @@ public class RegisterCimIndicationCommand : ObjectEventRegistrationBase ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ClassName { - get { return className; } + get + { + return className; + } set { @@ -75,7 +78,10 @@ public string ClassName ParameterSetName = CimBaseCommand.QueryExpressionComputerSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -97,7 +103,10 @@ public string Query [Parameter(ParameterSetName = CimBaseCommand.QueryExpressionSessionSet)] public string QueryDialect { - get { return queryDialect; } + get + { + return queryDialect; + } set { @@ -129,7 +138,10 @@ public string QueryDialect ParameterSetName = CimBaseCommand.ClassNameSessionSet)] public CimSession CimSession { - get { return cimSession; } + get + { + return cimSession; + } set { @@ -150,7 +162,10 @@ public CimSession CimSession [Parameter(ParameterSetName = CimBaseCommand.ClassNameComputerSet)] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs index dcdcbd405f7..c3f1230020c 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs @@ -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 { @@ -161,7 +173,10 @@ public string Namespace [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return CimInstance; } + get + { + return CimInstance; + } set { @@ -190,7 +205,10 @@ public CimInstance InputObject ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -212,7 +230,10 @@ public string Query ParameterSetName = CimBaseCommand.QueryComputerSet)] public string QueryDialect { - get { return querydialect; } + get + { + return querydialect; + } set { @@ -273,7 +294,7 @@ protected override void EndProcessing() /// private CimRemoveCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimRemoveCimInstance); + return this.AsyncOperation as CimRemoveCimInstance; } /// diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs index 00f575c41c8..53937e57354 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs @@ -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 { @@ -104,7 +110,10 @@ public string[] ComputerName [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public UInt32[] Id { - get { return id; } + get + { + return id; + } set { @@ -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 { diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs index 03c01785f1c..25b3113e452 100644 --- a/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs @@ -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 { @@ -158,7 +170,10 @@ public string Namespace [Alias(CimBaseCommand.AliasCimInstance)] public CimInstance InputObject { - get { return CimInstance; } + get + { + return CimInstance; + } set { @@ -187,7 +202,10 @@ public CimInstance InputObject ParameterSetName = CimBaseCommand.QuerySessionSet)] public string Query { - get { return query; } + get + { + return query; + } set { @@ -209,7 +227,10 @@ public string Query ParameterSetName = CimBaseCommand.QueryComputerSet)] public string QueryDialect { - get { return querydialect; } + get + { + return querydialect; + } set { @@ -244,7 +265,10 @@ public string QueryDialect [Alias("Arguments")] public IDictionary Property { - get { return property; } + get + { + return property; + } set { @@ -319,7 +343,7 @@ protected override void EndProcessing() /// private CimSetCimInstance GetOperationAgent() { - return (this.AsyncOperation as CimSetCimInstance); + return this.AsyncOperation as CimSetCimInstance; } /// diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs index 0717be5ff33..9089216a485 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSample.cs @@ -27,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; } - - set { _path = value; } - } - - private string _path = string.Empty; - - public string InstanceName - { - get { return _instanceName; } - - set { _instanceName = value; } - } - - private string _instanceName = string.Empty; - - public double CookedValue - { - get { return _cookedValue; } - - set { _cookedValue = value; } - } - - private double _cookedValue = 0; - - public UInt64 RawValue - { - get { return _rawValue; } - - set { _rawValue = value; } - } - - private UInt64 _rawValue = 0; - - public UInt64 SecondValue - { - get { return _secondValue; } - - set { _secondValue = value; } - } - - private UInt64 _secondValue = 0; - - public uint MultipleCount - { - get { return _multiCount; } - - set { _multiCount = value; } - } + public string Path { get; set; } = string.Empty; - private uint _multiCount = 0; + public string InstanceName { get; set; } = string.Empty; - public PerformanceCounterType CounterType - { - get { return _counterType; } - - set { _counterType = value; } - } - - private PerformanceCounterType _counterType = 0; - - public DateTime Timestamp - { - get { return _timeStamp; } - - set { _timeStamp = value; } - } - - private DateTime _timeStamp = DateTime.MinValue; - - public UInt64 Timestamp100NSec - { - get { return _timeStamp100nSec; } - - set { _timeStamp100nSec = value; } - } - - private UInt64 _timeStamp100nSec = 0; + public double CookedValue { get; set; } - public UInt32 Status - { - get { return _status; } + public UInt64 RawValue { get; set; } - set { _status = value; } - } + public UInt64 SecondValue { get; set; } - private UInt32 _status = 0; + public uint MultipleCount { get; set; } - public UInt32 DefaultScale - { - get { return _defaultScale; } + public PerformanceCounterType CounterType { get; set; } - set { _defaultScale = value; } - } + public DateTime Timestamp { get; set; } = DateTime.MinValue; - private UInt32 _defaultScale = 0; + public UInt64 Timestamp100NSec { get; set; } - public UInt64 TimeBase - { - get { return _timeBase; } + public UInt32 Status { get; set; } - set { _timeBase = value; } - } + public UInt32 DefaultScale { get; set; } - private UInt64 _timeBase = 0; + public UInt64 TimeBase { get; set; } } public class PerformanceCounterSampleSet @@ -161,31 +77,17 @@ 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 readonly ResourceManager _resourceMgr = null; } diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs index 2eb6b1dd7ce..dfc175b604c 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/CounterSet.cs @@ -16,74 +16,34 @@ 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 readonly string _counterSetName = string.Empty; - - public string MachineName - { - get - { - return _machineName; - } - } - - private readonly string _machineName = "."; - - public PerformanceCounterCategoryType CounterSetType - { - get - { - return _counterSetType; - } - } + public string CounterSetName { get; } = string.Empty; - private readonly PerformanceCounterCategoryType _counterSetType; + public string MachineName { get; } = "."; - public string Description - { - get - { - return _description; - } - } - - private readonly string _description = string.Empty; + public PerformanceCounterCategoryType CounterSetType { get; } - internal Dictionary CounterInstanceMapping - { - get - { - return _counterInstanceMapping; - } - } + public string Description { get; } = string.Empty; - private readonly Dictionary _counterInstanceMapping; + internal Dictionary CounterInstanceMapping { get; } public StringCollection Paths { @@ -95,15 +55,15 @@ public StringCollection Paths 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); @@ -122,9 +82,9 @@ public StringCollection PathsWithInstances { 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 b3f98a9364e..4a6941cc13f 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/GetCounterCommand.cs @@ -16,9 +16,9 @@ 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 { @@ -37,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 @@ -63,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,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 @@ -115,7 +103,10 @@ public int SampleInterval [ValidateRange((Int64)1, Int64.MaxValue)] public Int64 MaxSamples { - get { return _maxSamples; } + get + { + return _maxSamples; + } set { @@ -155,14 +146,7 @@ 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; @@ -186,11 +170,11 @@ public string[] ComputerName 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), } } }; @@ -288,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); } @@ -322,7 +306,7 @@ private void ProcessListSetPerMachine(string machine) _cultureAndSpecialCharacterMap.TryGetValue(culture.Name, out characterReplacementList); - foreach (string pattern in _listSet) + foreach (string pattern in ListSet) { bool bMatched = false; string normalizedPattern = pattern; @@ -550,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; @@ -587,7 +571,7 @@ private List CombineMachinesAndCounterPaths() { List retColl = new(); - if (_computerName.Length == 0) + if (ComputerName.Length == 0) { retColl.AddRange(_accumulatedCounters); return retColl; @@ -601,7 +585,7 @@ private List CombineMachinesAndCounterPaths() } else { - foreach (string machine in _computerName) + foreach (string machine in ComputerName) { if (machine.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) { diff --git a/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs b/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs index ae362bcfb0e..1a74da73d1c 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/GetEventCommand.cs @@ -20,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 { @@ -42,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. @@ -66,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. @@ -87,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. @@ -112,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. @@ -137,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,14 +145,7 @@ public string[] Path HelpMessageBaseName = "GetEventResources", HelpMessageResourceId = "MaxEventsParamHelp")] [ValidateRange((Int64)1, Int64.MaxValue)] - public Int64 MaxEvents - { - get { return _maxEvents; } - - set { _maxEvents = value; } - } - - private Int64 _maxEvents = -1; + public Int64 MaxEvents { get; set; } = -1; /// /// ComputerName parameter. @@ -222,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. @@ -245,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. @@ -273,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. @@ -292,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. @@ -317,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. @@ -338,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. @@ -355,7 +259,6 @@ public SwitchParameter Force [Parameter(ParameterSetName = "FileSet")] [Parameter(ParameterSetName = "GetProviderSet")] [Parameter(ParameterSetName = "GetLogSet")] - [Parameter(ParameterSetName = "HashQuerySet")] [Parameter(ParameterSetName = "XmlQuerySet")] public SwitchParameter Oldest @@ -501,7 +404,7 @@ protected override void ProcessRecord() // private void AccumulatePipelineLogNames() { - _accumulatedLogNames.AddRange(_logName); + _accumulatedLogNames.AddRange(LogName); } // @@ -510,7 +413,7 @@ private void AccumulatePipelineLogNames() // private void AccumulatePipelineProviderNames() { - _accumulatedProviderNames.AddRange(_logName); + _accumulatedProviderNames.AddRange(LogName); } // @@ -519,7 +422,7 @@ private void AccumulatePipelineProviderNames() // private void AccumulatePipelineFileNames() { - _accumulatedFileNames.AddRange(_logName); + _accumulatedFileNames.AddRange(LogName); } // @@ -544,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; @@ -561,7 +464,7 @@ private void ProcessGetProvider() { using (EventLogSession eventLogSession = CreateSession()) { - FindProvidersByLogForWildcardPatterns(eventLogSession, _providerName); + FindProvidersByLogForWildcardPatterns(eventLogSession, ProviderName); if (_providersByLogMap.Count == 0) { @@ -604,7 +507,7 @@ private void ProcessListLog() { using (EventLogSession eventLogSession = CreateSession()) { - foreach (string logPattern in _listLog) + foreach (string logPattern in ListLog) { bool bMatchFound = false; WildcardPattern wildLogPattern = new(logPattern, WildcardOptions.IgnoreCase); @@ -660,7 +563,7 @@ private void ProcessListLog() if (!bMatchFound) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new(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)); } } @@ -674,7 +577,7 @@ private void ProcessListProvider() { using (EventLogSession eventLogSession = CreateSession()) { - foreach (string provPattern in _listProvider) + foreach (string provPattern in ListProvider) { bool bMatchFound = false; WildcardPattern wildProvPattern = new(provPattern, WildcardOptions.IgnoreCase); @@ -707,7 +610,7 @@ private void ProcessListProvider() if (!bMatchFound) { string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoMatchingProvidersFound"), - _computerName, provPattern); + ComputerName, provPattern); Exception exc = new(msg); WriteError(new ErrorRecord(exc, "NoMatchingProvidersFound", ErrorCategory.ObjectNotFound, null)); } @@ -727,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) { @@ -749,7 +652,7 @@ private void ProcessFilterXml() } } - EventLogQuery logQuery = new(null, PathType.LogName, _xmlQuery.InnerXml); + EventLogQuery logQuery = new(null, PathType.LogName, FilterXml.InnerXml); logQuery.Session = eventLogSession; logQuery.ReverseDirection = !_oldest; @@ -768,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); @@ -791,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; @@ -833,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 ); // @@ -894,7 +797,7 @@ private void ReadEvents(EventLogQuery logQuery) break; } - if (_maxEvents != -1 && numEvents >= _maxEvents) + if (MaxEvents != -1 && numEvents >= MaxEvents) { break; } @@ -974,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); @@ -989,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); @@ -1111,7 +1014,7 @@ private string BuildStructuredQueryFromHashTable(EventLogSession eventLogSession uint queryId = 0; - foreach (Hashtable hash in _selector) + foreach (Hashtable hash in FilterHashtable) { string xpathString = string.Empty; string xpathStringSuppress = string.Empty; @@ -1674,7 +1577,7 @@ private bool ValidateLogName(string logName, EventLogSession eventLogSession) catch (EventLogNotFoundException) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new(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; } @@ -1833,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) { @@ -1875,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 + "]"; } @@ -1890,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 + "]"; @@ -2113,7 +2016,7 @@ private void FindLogNamesMatchingWildcards(EventLogSession eventLogSession, IEnu if (!bMatched) { string msg = _resourceMgr.GetString("NoMatchingLogsFound"); - Exception exc = new(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)); } } @@ -2150,7 +2053,7 @@ private void FindProvidersByLogForWildcardPatterns(EventLogSession eventLogSessi if (!bMatched) { string msg = _resourceMgr.GetString("NoMatchingProvidersFound"); - Exception exc = new(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 5fceca05b47..cb74c292a3e 100644 --- a/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs @@ -14,10 +14,10 @@ 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 { @@ -36,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) @@ -109,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. @@ -137,7 +111,7 @@ 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"); } @@ -146,7 +120,7 @@ private void LoadProvider() { foreach (string providerName in session.GetProviderNames()) { - if (string.Equals(providerName, _providerName, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(providerName, ProviderName, StringComparison.OrdinalIgnoreCase)) { try { @@ -165,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); } } @@ -188,7 +162,7 @@ private void LoadEventDescriptor() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("IncorrectEventId"), _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -216,7 +190,7 @@ private void LoadEventDescriptor() _resourceMgr.GetString("IncorrectEventVersion"), _version, _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -226,7 +200,7 @@ private void LoadEventDescriptor() string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("VersionNotSpecified"), _id, - _providerName); + ProviderName); throw new EventWriteException(msg); } @@ -269,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); @@ -317,17 +291,17 @@ protected override void ProcessRecord() { 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(in ed, _payload); + provider.WriteEvent(in ed, Payload); } else { 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 e17bceaa9b5..16cdf5f48d4 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 79fc1dd0461..fb6b638b9df 100644 --- a/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs +++ b/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/SessionBasedWrapper.cs @@ -75,7 +75,10 @@ protected virtual void Dispose(bool disposing) [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] protected TSession[] Session { - get { return _session ??= new TSession[] { this.DefaultSession }; } + get + { + return _session ??= new TSession[] { this.DefaultSession }; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs index 9d30f5b3a08..61b5fe4487d 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs @@ -233,7 +233,10 @@ public class RestartComputerCommand : PSCmdlet, IDisposable [ValidateRange(-1, int.MaxValue)] public int Timeout { - get { return _timeout; } + get + { + return _timeout; + } set { @@ -252,7 +255,10 @@ public int Timeout [Parameter(ParameterSetName = DefaultParameterSet)] public WaitForServiceTypes For { - get { return _waitFor; } + get + { + return _waitFor; + } set { @@ -272,7 +278,10 @@ public WaitForServiceTypes For [ValidateRange(1, Int16.MaxValue)] public Int16 Delay { - get { return (Int16)_delay; } + get + { + return (Int16)_delay; + } set { @@ -1793,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; } diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ContentCommandBase.cs index b591e05f7de..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 { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs index 10f7a28a8a7..ff13448bc09 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/CopyPropertyCommand.cs @@ -34,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/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/GetContentCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs index f01645544bb..f689695fc38 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetContentCommand.cs @@ -59,7 +59,10 @@ public long TotalCount [Alias("Last")] public int Tail { - get { return _backCount; } + get + { + return _backCount; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs index 94204269010..fb90ec1c502 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/MovePropertyCommand.cs @@ -35,7 +35,10 @@ public string[] Path [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return paths; } + get + { + return paths; + } set { @@ -51,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 6528e8394c2..23aa621266d 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs @@ -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) { @@ -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); @@ -2637,8 +2636,7 @@ protected override void ProcessRecord() if (isCurrentLocationOrAncestor) { PSInvalidOperationException invalidOperation = - (PSInvalidOperationException) - PSTraceSource.NewInvalidOperationException( + (PSInvalidOperationException)PSTraceSource.NewInvalidOperationException( NavigationResources.RemoveItemInUse, resolvedPath.Path); @@ -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/PingPathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs index 197ffa694bd..9bebcd076ca 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/PingPathCommand.cs @@ -62,7 +62,10 @@ public string[] Path [AllowEmptyString] public string[] LiteralPath { - get { return _paths; } + get + { + return _paths; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index c6eb4327471..3451fd96ac2 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -476,7 +476,10 @@ public sealed class GetProcessCommand : ProcessBaseCommand [ValidateNotNullOrEmpty] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -878,7 +881,10 @@ public int[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -1472,7 +1478,10 @@ public int[] Id [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Name { - get { return processNames; } + get + { + return processNames; + } set { @@ -1635,7 +1644,10 @@ public sealed class StartProcessCommand : PSCmdlet, IDisposable [Credential] public PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -1660,7 +1672,10 @@ public PSCredential Credential [Alias("Lup")] public SwitchParameter LoadUserProfile { - get { return _loaduserprofile; } + get + { + return _loaduserprofile; + } set { @@ -1678,7 +1693,10 @@ public SwitchParameter LoadUserProfile [Alias("nnw")] public SwitchParameter NoNewWindow { - get { return _nonewwindow; } + get + { + return _nonewwindow; + } set { @@ -1703,7 +1721,10 @@ public SwitchParameter NoNewWindow [ValidateNotNullOrEmpty] public string RedirectStandardError { - get { return _redirectstandarderror; } + get + { + return _redirectstandarderror; + } set { @@ -1722,7 +1743,10 @@ public string RedirectStandardError [ValidateNotNullOrEmpty] public string RedirectStandardInput { - get { return _redirectstandardinput; } + get + { + return _redirectstandardinput; + } set { @@ -1741,7 +1765,10 @@ public string RedirectStandardInput [ValidateNotNullOrEmpty] public string RedirectStandardOutput { - get { return _redirectstandardoutput; } + get + { + return _redirectstandardoutput; + } set { @@ -1769,7 +1796,10 @@ public string RedirectStandardOutput [ValidateNotNullOrEmpty] public ProcessWindowStyle WindowStyle { - get { return _windowstyle; } + get + { + return _windowstyle; + } set { @@ -1793,7 +1823,10 @@ public ProcessWindowStyle WindowStyle [Parameter(ParameterSetName = "Default")] public SwitchParameter UseNewEnvironment { - get { return _UseNewEnvironment; } + get + { + return _UseNewEnvironment; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs index a4471699922..1d793857c1a 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs @@ -1495,7 +1495,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [Alias("ServiceName", "SN")] public new string Name { - get { return serviceName; } + get + { + return serviceName; + } set { @@ -1523,7 +1526,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [Alias("DN")] public new string DisplayName { - get { return displayName; } + get + { + return displayName; + } set { @@ -1552,7 +1558,10 @@ public class SetServiceCommand : ServiceOperationBaseCommand [ValidateNotNullOrEmpty] public string Description { - get { return description; } + get + { + return description; + } set { @@ -1575,7 +1584,10 @@ public string Description [ValidateNotNullOrEmpty] public ServiceStartupType StartupType { - get { return startupType; } + get + { + return startupType; + } set { @@ -1611,7 +1623,10 @@ public string SecurityDescriptorSddl [ValidateSetAttribute(new string[] { "Running", "Stopped", "Paused" })] public string Status { - get { return serviceStatus; } + get + { + return serviceStatus; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs index e2c01168256..7c5f43aad2b 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetPropertyCommand.cs @@ -43,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/TimeZoneCommands.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs index 0289e885e65..69e8860f3ab 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/TimeZoneCommands.cs @@ -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"; 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 b6f1bbaf636..3acd57c6505 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs index a54094ea464..b86cadc1eff 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs @@ -292,7 +292,10 @@ private void ProcessPaths(List resolvedPaths) [Alias("RA")] public string[] ReferencedAssemblies { - get { return _referencedAssemblies; } + get + { + return _referencedAssemblies; + } set { 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 714054275d0..83f78ce77a2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Compare-Object.cs @@ -72,7 +72,10 @@ public SwitchParameter ExcludeDifferent [Parameter] public SwitchParameter IncludeEqual { - get { return _includeEqual; } + get + { + return _includeEqual; + } set { 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 013f9079d63..22c1e5ef46b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFrom-SddlString.cs @@ -31,7 +31,10 @@ public sealed class ConvertFromSddlStringCommand : PSCmdlet [Parameter] public AccessRightTypeNames Type { - get { return _type; } + get + { + return _type; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ExportAliasCommand.cs index 7260bc51d95..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 { 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 7a8613ac032..8d80462c12f 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 @@ -54,7 +54,10 @@ public SwitchParameter AutoSize return false; } - set { _autosize = value; } + set + { + _autosize = value; + } } private bool? _autosize = null; @@ -74,7 +77,10 @@ public int Column return -1; } - set { _column = value; } + set + { + _column = value; + } } private int? _column = null; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs index 241c49a989f..aecb011cab1 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetDateCommand.cs @@ -516,7 +516,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/ImplicitRemotingCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs index d5d283062b9..d772258227b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs @@ -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 = (PSObject pso) => ConvertTo(commandName, pso); + valueRehydrator = (PSObject pso) => ConvertTo(commandName, pso); } - Dictionary result = new(); + 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); } @@ -1128,7 +1132,7 @@ private static bool IsSafeNameOrIdentifier(string name) /// if the name is safe; otherwise. private static bool IsSafeParameterName(string parameterName) { - return IsSafeNameOrIdentifier(parameterName) && !parameterName.Contains(":"); + return IsSafeNameOrIdentifier(parameterName) && !parameterName.Contains(':'); } /// @@ -1985,9 +1989,9 @@ private static string EscapeFunctionNameForRemoteHelp(string name) 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); } 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 4bc6a3b42e0..452e8bfe09c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -159,12 +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 class MeasureObjectDictionary : Dictionary + where TValue : new() { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// Default ctor. /// internal MeasureObjectDictionary() : base(StringComparer.OrdinalIgnoreCase) @@ -181,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; } 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 54e323dfac8..90ef2ca4376 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/New-Object.cs @@ -519,12 +519,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/OrderObjectBase.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/OrderObjectBase.cs index 7a6bcc6bc1b..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?.ToString(); } + get + { + return _cultureInfo?.ToString(); + } set { 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 7ada7d4b947..d137524629d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Update-TypeData.cs @@ -50,7 +50,10 @@ private static bool HasBeenSpecified(object obj) System.Management.Automation.Runspaces.TypeData.CodeMethod, IgnoreCase = true)] public PSMemberTypes MemberType { - get { return _memberType; } + get + { + return _memberType; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs index 0658c7014c4..69b89e928ce 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs @@ -7,7 +7,7 @@ using System.Management.Automation; 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 { 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 13f7ea6f999..841f6a60c72 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 @@ -815,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() @@ -1837,7 +1837,7 @@ internal void ParseLinkHeader(HttpResponseMessage response, System.Uri requestUr { 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) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs index cfd216edc41..8db56196a68 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs @@ -836,7 +836,10 @@ public class SelectXmlCommand : PSCmdlet [Alias("PSPath", "LP")] public string[] LiteralPath { - get { return Path; } + get + { + return Path; + } set { 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/TraceExpressionCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs index 8179b9179d1..412f4a2d150 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceExpressionCommand.cs @@ -46,7 +46,10 @@ public string[] Name [Parameter(Position = 2)] public PSTraceSourceOptions Option { - get { return base.OptionsInternal; } + get + { + return base.OptionsInternal; + } set { @@ -82,7 +85,10 @@ public PSTraceSourceOptions Option [Parameter] public TraceOptions ListenerOption { - get { return base.ListenerOptionsInternal; } + get + { + return base.ListenerOptionsInternal; + } set { 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 abdb6ae17bc..f1e4fe2dfa0 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/trace/TraceListenerCommandBase.cs @@ -32,7 +32,10 @@ public class TraceListenerCommandBase : TraceCommandBase /// internal PSTraceSourceOptions OptionsInternal { - get { return _options; } + get + { + return _options; + } set { @@ -53,7 +56,10 @@ internal PSTraceSourceOptions OptionsInternal /// internal TraceOptions ListenerOptionsInternal { - get { return _traceOptions; } + get + { + return _traceOptions; + } set { diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index bb9b3002d60..fc1d25ac42f 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}) diff --git a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs index 90148ca7e25..10db7912b4a 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/WindowsTaskbarJumpList/PropVariant.cs @@ -58,7 +58,7 @@ public void Dispose() 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/host/msh/ConsoleControl.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs index c2458fabb5e..a157964c637 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs @@ -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, @@ -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, diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index d12f4385eaa..9de877ba46c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -124,7 +124,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); @@ -2870,15 +2870,13 @@ private class ConsoleHostStartupException : Exception { internal ConsoleHostStartupException() - : - base() + : base() { } internal ConsoleHostStartupException(string message) - : - base(message) + : base(message) { } @@ -2886,15 +2884,13 @@ private class ConsoleHostStartupException : Exception 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) { } } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs index a189481ce98..2a6ea89176d 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs @@ -1369,7 +1369,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); + } } /// @@ -1377,7 +1380,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 { @@ -1475,7 +1481,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/ConsoleHostUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs index 7485306c14e..142d514c491 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs @@ -1182,7 +1182,7 @@ public override void WriteDebugLine(string message) { if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering")) { - WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Debug) + StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message)); + WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Debug) + StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message) + PSStyle.Instance.Reset); } else { @@ -1243,7 +1243,7 @@ public override void WriteVerboseLine(string message) { if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering")) { - WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Verbose) + StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message)); + WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Verbose) + StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message) + PSStyle.Instance.Reset); } else { @@ -1287,7 +1287,7 @@ public override void WriteWarningLine(string message) { if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering")) { - WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Warning) + StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message)); + WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Warning) + StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message) + PSStyle.Instance.Reset); } else { @@ -1304,33 +1304,34 @@ public override void WriteWarningLine(string message) /// public override void WriteProgress(Int64 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); } } } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs index da9d5689105..872aaa19a9c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfacePromptForChoice.cs @@ -252,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) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs index 7313a40e139..97a02cb7123 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleTextWriter.cs @@ -13,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"); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index 89901b18126..0c38f35960f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -516,7 +516,11 @@ internal override 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; } } @@ -582,6 +586,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); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 165d1993bef..ca2694bcabc 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,6 +43,11 @@ 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, } /// @@ -47,8 +55,7 @@ namespace Microsoft.PowerShell /// internal ProgressNode(Int64 sourceId, ProgressRecord record) - : - base(record.ActivityId, record.Activity, record.StatusDescription) + : 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,88 @@ private static void RenderFullDescription(string description, string indent, int maxWidth)); } + internal static bool IsMinimalProgressRenderingEnabled() + { + return ExperimentalFeature.IsEnabled(ExperimentalFeature.PSAnsiProgressFeatureName) && 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; + } + + // 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); + + if (StatusDescription.Length > barWidth - secRemainLength) + { + sb.Append(StatusDescription.Substring(0, barWidth - secRemainLength - 1)); + sb.Append(PSObjectHelper.Ellipsis); + } + else + { + sb.Append(StatusDescription); + } + + sb.Append(string.Empty.PadRight(barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength)); + sb.Append(secRemain); + + if (PercentComplete > 0 && PercentComplete < 100) + { + int barLength = PercentComplete * barWidth / 100; + if (barLength >= barWidth) + { + barLength = barWidth - 1; + } + + 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. /// @@ -397,6 +493,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; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 65f0267d0ed..f0cdadc73eb 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 (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSAnsiProgressFeatureName) && 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) @@ -223,8 +285,41 @@ 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; } } @@ -233,6 +328,7 @@ class ProgressPane private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; + private string[] _content; private readonly PSHostRawUserInterface _rawui; private readonly ConsoleHostUserInterface _ui; } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Serialization.cs index 0c97ba3c095..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"); @@ -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"); 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 c9cd4d255eb..007cf74891e 100644 --- a/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs +++ b/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs @@ -22,7 +22,7 @@ namespace System.Diagnostics.Eventing.Reader { - internal class NativeWrapper + internal static class NativeWrapper { public class SystemProperties { 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 e7445b07d21..8be5faddce8 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.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index f89ec614d82..654ed9ef9c0 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.Security/security/AclCommands.cs b/src/Microsoft.PowerShell.Security/security/AclCommands.cs index beda593b70b..c0994a57a53 100644 --- a/src/Microsoft.PowerShell.Security/security/AclCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/AclCommands.cs @@ -87,8 +87,7 @@ internal CmdletProviderContext CmdletProviderContext { get { - CmdletProviderContext coreCommandContext = - new CmdletProviderContext(this); + CmdletProviderContext coreCommandContext = new(this); Collection includeFilter = SessionStateUtilities.ConvertArrayToCollection(Include); @@ -351,7 +350,7 @@ 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 pSd = IntPtr.Zero; @@ -801,7 +800,7 @@ protected override void ProcessRecord() { foreach (string p in Path) { - List pathsToProcess = new List(); + List pathsToProcess = new(); string currentPath = null; try @@ -824,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)) @@ -1264,7 +1263,7 @@ private static IntPtr GetTokenWithEnabledPrivilege( } // Get the LUID of the specified privilege. - NativeMethods.LUID luid = new NativeMethods.LUID(); + NativeMethods.LUID luid = new(); ret = NativeMethods.LookupPrivilegeValue( null, privilege, @@ -1275,7 +1274,7 @@ private static 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; @@ -1419,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) @@ -1427,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, @@ -1441,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, @@ -1453,7 +1450,7 @@ protected override void ProcessRecord() foreach (string p in Path) { - Collection pathsToProcess = new Collection(); + Collection pathsToProcess = new(); CmdletProviderContext context = this.CmdletProviderContext; context.PassThru = Passthru; @@ -1496,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, @@ -1518,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, diff --git a/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs b/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs index 5b542da92c2..a86bf657853 100644 --- a/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CatalogCommands.cs @@ -86,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) { @@ -182,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 46ab49ee0ab..4723aa7fbf0 100644 --- a/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/CertificateCommands.cs @@ -77,7 +77,7 @@ public string[] LiteralPath // // list of files that were not found // - private readonly List _filesNotFound = new List(); + private readonly List _filesNotFound = new(); /// /// Initializes a new instance of the GetPfxCertificateCommand @@ -105,7 +105,7 @@ protected override void ProcessRecord() foreach (string p in FilePath) { - List paths = new List(); + List paths = new(); // Expand wildcard characters if (_isLiteralPath) @@ -160,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; } diff --git a/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs b/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs index 79e3eac1971..d0c71e82260 100644 --- a/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs +++ b/src/Microsoft.PowerShell.Security/security/CertificateProvider.cs @@ -51,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 @@ -250,7 +250,7 @@ public SwitchParameter DeleteKey } } - private SwitchParameter _deleteKey = new SwitchParameter(); + private SwitchParameter _deleteKey = new(); } /// @@ -447,7 +447,7 @@ public IntPtr GetCertByName(string Name) break; } - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); if (string.Equals( cert.Thumbprint, Name, @@ -582,7 +582,7 @@ public sealed class CertificateProvider : NavigationCmdletProvider, ICmdletProvi /// -- storeLocations /// -- pathCache. /// - private static readonly object s_staticLock = new object(); + private static readonly object s_staticLock = new(); /// /// List of store locations. They do not change once initialized. @@ -664,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); @@ -673,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); @@ -997,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); } @@ -1016,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; @@ -1274,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); } } @@ -1349,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); @@ -1482,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 @@ -1506,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; @@ -1526,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, @@ -1542,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); @@ -1585,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) { @@ -1766,7 +1759,7 @@ private void RemoveCertStore(string storeName, bool fDeleteKey, string sourcePat IntPtr certContext = store.GetFirstCert(); while (certContext != IntPtr.Zero) { - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); string certPath = sourcePath + cert.Thumbprint; RemoveCertItem(cert, fDeleteKey, true, certPath); @@ -1986,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); @@ -2017,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) { @@ -2452,7 +2443,7 @@ private void GetCertificatesOrNames(string path, while (certContext != IntPtr.Zero) { - X509Certificate2 cert = new X509Certificate2(certContext); + X509Certificate2 cert = new(certContext); if (MatchesFilter(cert, filter)) { @@ -2465,7 +2456,7 @@ private void GetCertificatesOrNames(string path, } else { - PSObject myPsObj = new PSObject(cert); + PSObject myPsObj = new(cert); thingToReturn = (object)myPsObj; } @@ -2595,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; } @@ -2920,7 +2909,7 @@ string ICmdletProviderSupportsHelp.GetHelpMaml(string helpItemName, string path) // // Load the help file from the current UI culture subfolder of the module's root folder // - XmlDocument document = new XmlDocument(); + XmlDocument document = new(); CultureInfo currentUICulture = CultureInfo.CurrentUICulture; @@ -2928,7 +2917,7 @@ string ICmdletProviderSupportsHelp.GetHelpMaml(string helpItemName, string path) this.ProviderInfo.ApplicationBase, currentUICulture.ToString(), this.ProviderInfo.HelpFile); - XmlReaderSettings settings = new XmlReaderSettings(); + XmlReaderSettings settings = new(); settings.XmlResolver = null; using (XmlReader reader = XmlReader.Create(fullHelpPath, settings)) { @@ -2936,7 +2925,7 @@ string ICmdletProviderSupportsHelp.GetHelpMaml(string helpItemName, string path) } // Add "msh" and "command" namespaces from the MAML schema - XmlNamespaceManager nsMgr = new XmlNamespaceManager(document.NameTable); + XmlNamespaceManager nsMgr = new(document.NameTable); nsMgr.AddNamespace("msh", HelpCommentsParser.mshURI); nsMgr.AddNamespace("command", HelpCommentsParser.commandURI); @@ -3194,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; @@ -3217,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; @@ -3271,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) { @@ -3303,7 +3292,7 @@ private static string[] GetPathElements(string path) /// public sealed class EnhancedKeyUsageProperty { - private readonly List _ekuList = new List(); + private readonly List _ekuList = new(); /// /// Get property of EKUList. @@ -3332,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); } } @@ -3346,8 +3335,8 @@ public EnhancedKeyUsageProperty(X509Certificate2 cert) /// public sealed class DnsNameProperty { - private readonly List _dnsList = new List(); - private readonly 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="; @@ -3553,9 +3542,9 @@ internal static class Crypt32Helpers /// Lock that guards access to the following static members /// -- storeNames. /// - private static readonly 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. @@ -3581,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 baa7a847dd6..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 readonly 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 readonly 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 readonly 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)) { 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/SignatureCommands.cs b/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs index 49a37d06c78..5d5bb06b667 100644 --- a/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs +++ b/src/Microsoft.PowerShell.Security/security/SignatureCommands.cs @@ -104,7 +104,10 @@ public string[] SourcePathOrExtension [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public byte[] Content { - get { return _content; } + get + { + return _content; + } set { @@ -155,7 +158,7 @@ protected override void ProcessRecord() foreach (string p in FilePath) { - Collection paths = new Collection(); + Collection paths = new(); // Expand wildcard characters if (_isLiteralPath) @@ -464,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.. @@ -480,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; } @@ -548,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 208303d9b88..9e3d9bd05b1 100644 --- a/src/Microsoft.WSMan.Management/ConfigProvider.cs +++ b/src/Microsoft.WSMan.Management/ConfigProvider.cs @@ -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; diff --git a/src/Microsoft.WSMan.Management/InvokeWSManAction.cs b/src/Microsoft.WSMan.Management/InvokeWSManAction.cs index 9420dd4a77f..36f65e52705 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 { diff --git a/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj b/src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj index d012eeafc6f..45d4d4b2bad 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..30959f3ced5 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 { @@ -158,7 +173,10 @@ public SwitchParameter SkipRevocationCheck [ValidateRange(0, Int32.MaxValue)] public Int32 SPNPort { - get { return spnport; } + get + { + return spnport; + } set { @@ -177,7 +195,10 @@ public Int32 SPNPort [ValidateRange(0, Int32.MaxValue)] public Int32 OperationTimeout { - get { return operationtimeout; } + get + { + return operationtimeout; + } set { @@ -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..a04167a0f1b 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 { diff --git a/src/Microsoft.WSMan.Management/WSManConnections.cs b/src/Microsoft.WSMan.Management/WSManConnections.cs index 6d6c5f6bc0e..85c5d1ba0ae 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 { @@ -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 b4fb9ed955c..733316c785f 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 { @@ -222,7 +249,10 @@ public Hashtable OptionSet [Parameter(ParameterSetName = "GetInstance")] public Int32 Port { - get { return port; } + get + { + return port; + } set { @@ -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 { @@ -662,7 +713,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -1032,7 +1086,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { @@ -1294,7 +1351,10 @@ public string ApplicationName [Alias("cn")] public string ComputerName { - get { return computername; } + get + { + return computername; + } set { diff --git a/src/Microsoft.WSMan.Management/WsManHelper.cs b/src/Microsoft.WSMan.Management/WsManHelper.cs index 2c423fd2b13..000cb871abb 100644 --- a/src/Microsoft.WSMan.Management/WsManHelper.cs +++ b/src/Microsoft.WSMan.Management/WsManHelper.cs @@ -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())) diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 63807dc1e50..ae838f27601 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -5,7 +5,7 @@ Microsoft Corporation (c) Microsoft Corporation. - net5.0 + net6.0 true 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..1963b331ef1 100644 --- a/src/System.Management.Automation/AssemblyInfo.cs +++ b/src/System.Management.Automation/AssemblyInfo.cs @@ -27,7 +27,7 @@ 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/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 78f778b944b..2901148813b 100644 --- a/src/System.Management.Automation/DscSupport/CimDSCParser.cs +++ b/src/System.Management.Automation/DscSupport/CimDSCParser.cs @@ -41,9 +41,7 @@ public static object ConvertCimInstanceToObject(Type targetType, CimInstance ins using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) { - const 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); @@ -945,6 +943,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. /// @@ -2148,7 +2160,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); } @@ -2170,7 +2182,7 @@ public static void LoadResourcesFromModule(IScriptExtent scriptExtent, { foreach (var resourceNameToImport in resourcesToImport) { - if (!resourceNameToImport.Contains("*")) + if (!resourceNameToImport.Contains('*')) { errorList.Add(new ParseError(scriptExtent, "DscResourcesNotFoundDuringParsing", diff --git a/src/System.Management.Automation/DscSupport/JsonCimDSCParser.cs b/src/System.Management.Automation/DscSupport/JsonCimDSCParser.cs new file mode 100755 index 00000000000..c2221cb3f33 --- /dev/null +++ b/src/System.Management.Automation/DscSupport/JsonCimDSCParser.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Management.Automation; +using System.Security; + +namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform +{ + /// + /// Class that does high level Cim schema parsing. + /// + internal class CimDSCParser + { + private readonly JsonDeserializer _jsonDeserializer; + + internal CimDSCParser() + { + _jsonDeserializer = JsonDeserializer.Create(); + } + + internal IEnumerable ParseSchemaJson(string filePath, bool useNewRunspace = false) + { + try + { + string json = File.ReadAllText(filePath); + string fileNameDefiningClass = Path.GetFileNameWithoutExtension(filePath); + int dotIndex = fileNameDefiningClass.IndexOf(".schema", StringComparison.InvariantCultureIgnoreCase); + if (dotIndex != -1) + { + fileNameDefiningClass = fileNameDefiningClass.Substring(0, dotIndex); + } + + IEnumerable result = _jsonDeserializer.DeserializeClasses(json, useNewRunspace); + foreach (dynamic classObject in result) + { + string superClassName = classObject.SuperClassName; + string className = classObject.ClassName; + if (string.Equals(superClassName, "OMI_BaseResource", StringComparison.OrdinalIgnoreCase)) + { + // Get the name of the file without schema.mof/json extension + if (!className.Equals(fileNameDefiningClass, StringComparison.OrdinalIgnoreCase)) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException( + ParserStrings.ClassNameNotSameAsDefiningFile, className, fileNameDefiningClass); + throw e; + } + } + } + + return result; + } + catch (Exception exception) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException( + exception, ParserStrings.CimDeserializationError, filePath); + + e.SetErrorId("CimDeserializationError"); + throw e; + } + } + } +} diff --git a/src/System.Management.Automation/DscSupport/JsonDeserializer.cs b/src/System.Management.Automation/DscSupport/JsonDeserializer.cs new file mode 100755 index 00000000000..319560f0a09 --- /dev/null +++ b/src/System.Management.Automation/DscSupport/JsonDeserializer.cs @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Management.Automation; +using System.Management.Automation.Runspaces; + +namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform +{ + internal class JsonDeserializer + { + #region Constructors + + /// + /// Instantiates a default deserializer. + /// + /// Default deserializer. + public static JsonDeserializer Create() + { + return new JsonDeserializer(); + } + + #endregion Constructors + + #region Methods + + /// + /// Returns schema of Cim classes from specified json file. + /// + /// Json text to deserialize. + /// If a new runspace should be used. + /// Deserialized PSObjects. + public IEnumerable DeserializeClasses(string json, bool useNewRunspace = false) + { + if (string.IsNullOrEmpty(json)) + { + throw new ArgumentNullException(nameof(json)); + } + + System.Management.Automation.PowerShell powerShell = null; + + if (useNewRunspace) + { + // currently using RunspaceMode.NewRunspace will reset PSModulePath env var for the entire process + // this is something we want to avoid in DSC GuestConfigAgent scenario, so we use following workaround + var s_iss = InitialSessionState.CreateDefault(); + s_iss.EnvironmentVariables.Add( + new SessionStateVariableEntry( + "PSModulePath", + Environment.GetEnvironmentVariable("PSModulePath"), + description: null)); + powerShell = System.Management.Automation.PowerShell.Create(s_iss); + } + else + { + powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace); + } + + using (powerShell) + { + return powerShell.AddCommand("Microsoft.PowerShell.Utility\\ConvertFrom-Json") + .AddParameter("InputObject", json) + .AddParameter("Depth", 100) // maximum supported by cmdlet + .Invoke(); + } + } + + #endregion Methods + } +} diff --git a/src/System.Management.Automation/DscSupport/JsonDscClassCache.cs b/src/System.Management.Automation/DscSupport/JsonDscClassCache.cs new file mode 100755 index 00000000000..2fe4f7c2606 --- /dev/null +++ b/src/System.Management.Automation/DscSupport/JsonDscClassCache.cs @@ -0,0 +1,2498 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +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.Linq; +using System.Management.Automation; +using System.Management.Automation.Language; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using System.Text.RegularExpressions; + +using Microsoft.PowerShell.Commands; + +namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform +{ + /// + /// Class that defines Dsc cache entries. + /// + internal class DscClassCacheEntry + { + /// + /// Initializes a new instance of the class. + /// + public DscClassCacheEntry() + : this(DSCResourceRunAsCredential.Default, isImportedImplicitly: false, cimClassInstance: null, modulePath: string.Empty) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Run as credential value. + /// Resource is imported implicitly. + /// Class definition. + /// Path of module defining the class. + public DscClassCacheEntry(DSCResourceRunAsCredential dscResourceRunAsCredential, bool isImportedImplicitly, PSObject cimClassInstance, string modulePath) + { + DscResRunAsCred = dscResourceRunAsCredential; + IsImportedImplicitly = isImportedImplicitly; + CimClassInstance = cimClassInstance; + ModulePath = modulePath; + } + + /// + /// Gets or sets the RunAs Credentials that this DSC resource will use. + /// + public DSCResourceRunAsCredential DscResRunAsCred { get; set; } + + /// + /// Gets or sets a value indicating if we have implicitly imported this resource. + /// + public bool IsImportedImplicitly { get; set; } + + /// + /// Gets or sets CimClass instance for this resource. + /// + public PSObject CimClassInstance { get; set; } + + /// + /// Gets or sets path of the implementing module for this resource. + /// + public string ModulePath { get; set; } + } + + /// + /// DSC class cache for this runspace. + /// + [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes", + Justification = "Needed Internal use only")] + public static class DscClassCache + { + private static readonly HashSet s_reservedDynamicKeywords = new HashSet(new[] { "Synchronization", "Certificate", "IIS", "SQL" }, StringComparer.OrdinalIgnoreCase); + + private static readonly HashSet s_reservedProperties = new HashSet(new[] { "Require", "Trigger", "Notify", "Before", "After", "Subscribe" }, StringComparer.OrdinalIgnoreCase); + + /// + /// Experimental feature name for DSC v3. + /// + public const string DscExperimentalFeatureName = "PS7DscSupport"; + + 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 ModuleNameIndex = 0; + private const int ModuleVersionIndex = 1; + private const int ClassNameIndex = 2; + private const int FriendlyNameIndex = 3; + + // 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(StringComparer.OrdinalIgnoreCase) { "MSFT_BaseConfigurationProviderRegistration", "MSFT_CimConfigurationProviderRegistration", "MSFT_PSConfigurationProviderRegistration" }; + + // A collection to prevent circular importing case when Import-DscResource does not have a module specified + [ThreadStatic] + private static readonly HashSet t_currentImportDscResourceInvocations = new(StringComparer.OrdinalIgnoreCase); + + /// + /// Gets DSC class cache for this runspace. + /// Cache stores the DSCRunAsBehavior, cim class and boolean to indicate if an Inbox resource has been implicitly imported. + /// + private static Dictionary ClassCache + { + get => t_classCache ??= new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + [ThreadStatic] + private static Dictionary t_classCache; + + /// + /// Gets DSC class cache for GuestConfig; it is similar to ClassCache, but maintains values between operations. + /// + private static Dictionary GuestConfigClassCache + { + get => t_guestConfigClassCache ??= new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + [ThreadStatic] + private static Dictionary t_guestConfigClassCache; + + /// + /// DSC classname to source module mapper. + /// + private static Dictionary> ByClassModuleCache + => t_byClassModuleCache ??= new Dictionary>(StringComparer.OrdinalIgnoreCase); + + [ThreadStatic] + private static Dictionary> t_byClassModuleCache; + + /// + /// Default ModuleName and ModuleVersion to use. + /// + private static readonly Tuple s_defaultModuleInfoForResource = new Tuple("PSDesiredStateConfiguration", new Version(3, 0)); + + /// + /// When this property is set to true, DSC Cache will cache multiple versions of a resource. + /// That means it will cache duplicate resource classes (class names for a resource in two different module versions are same). + /// NOTE: This property should be set to false for DSC compiler related methods/functionality, such as Import-DscResource, + /// because the Mof serializer does not support deserialization of classes with different versions. + /// + [ThreadStatic] + private static bool t_cacheResourcesFromMultipleModuleVersions; + + private static bool CacheResourcesFromMultipleModuleVersions + { + get + { + return t_cacheResourcesFromMultipleModuleVersions; + } + + set + { + t_cacheResourcesFromMultipleModuleVersions = value; + } + } + + [ThreadStatic] + private static bool t_newApiIsUsed = false; + + /// + /// Flag shows if PS7 DSC APIs were used. + /// + public static bool NewApiIsUsed + { + get + { + return t_newApiIsUsed; + } + + set + { + t_newApiIsUsed = value; + } + } + + /// + /// Initialize the class cache with the default classes in $ENV:SystemDirectory\Configuration. + /// + public static void Initialize() + { + Initialize(errors: null, modulePathList: null); + } + + /// + /// Initialize the class cache with default classes that come with PSDesiredStateConfiguration module. + /// + /// Collection of any errors encountered during initialization. + /// List of module path from where DSC PS modules will be loaded. + public static void Initialize(Collection errors, List modulePathList) + { + s_tracer.WriteLine("Initializing DSC class cache"); + + // Load the base schema files. + ClearCache(); + var dscConfigurationDirectory = Environment.GetEnvironmentVariable("DSC_HOME"); + if (string.IsNullOrEmpty(dscConfigurationDirectory)) + { + var moduleInfos = ModuleCmdletBase.GetModuleIfAvailable(new Microsoft.PowerShell.Commands.ModuleSpecification() + { + Name = "PSDesiredStateConfiguration", + + // Version in the next line is actually MinimumVersion + Version = new Version(3, 0, 0) + }); + + if (moduleInfos.Count > 0) + { + // to be consistent with Import-Module behavior, we use the first occurrence that we find in PSModulePath + var moduleDirectory = Path.GetDirectoryName(moduleInfos[0].Path); + dscConfigurationDirectory = Path.Join(moduleDirectory, "Configuration"); + } + else + { + // when all else has failed use location of system-wide PS module directory (i.e. /usr/local/share/powershell/Modules) as backup + dscConfigurationDirectory = Path.Join(ModuleIntrinsics.GetSharedModulePath(), "PSDesiredStateConfiguration", "Configuration"); + } + } + + if (!Directory.Exists(dscConfigurationDirectory)) + { + throw new DirectoryNotFoundException(string.Format(ParserStrings.PsDscMissingSchemaStore, dscConfigurationDirectory)); + } + + var resourceBaseFile = Path.Join(dscConfigurationDirectory, "BaseRegistration", "BaseResource.schema.json"); + ImportBaseClasses(resourceBaseFile, s_defaultModuleInfoForResource, errors, false); + var metaConfigFile = Path.Join(dscConfigurationDirectory, "BaseRegistration", "MSFT_DSCMetaConfiguration.json"); + ImportBaseClasses(metaConfigFile, s_defaultModuleInfoForResource, errors, false); + } + + /// + /// Import base classes from the given file. + /// + /// Path to schema file. + /// Module information. + /// Error collection that will be shown to the user. + /// Flag for implicitly imported resource. + /// Class objects from schema file. + public static IEnumerable ImportBaseClasses(string path, Tuple moduleInfo, Collection errors, bool importInBoxResourcesImplicitly) + { + if (string.IsNullOrEmpty(path)) + { + throw PSTraceSource.NewArgumentNullException(nameof(path)); + } + + s_tracer.WriteLine("DSC ClassCache: importing file: {0}", path); + + var parser = new CimDSCParser(); + + IEnumerable classes = null; + try + { + classes = parser.ParseSchemaJson(path); + } + catch (PSInvalidOperationException e) + { + // Ignore modules with invalid schemas. + s_tracer.WriteLine("DSC ClassCache: Error importing file '{0}', with error '{1}'. Skipping file.", path, e); + if (errors != null) + { + errors.Add(e); + } + } + + if (classes != null) + { + foreach (dynamic c in classes) + { + var className = c.ClassName; + + if (string.IsNullOrEmpty(className)) + { + // ClassName is empty - skipping class import + continue; + } + + string alias = GetFriendlyName(c); + var friendlyName = string.IsNullOrEmpty(alias) ? className : alias; + string moduleQualifiedResourceName = GetModuleQualifiedResourceName(moduleInfo.Item1, moduleInfo.Item2.ToString(), className, friendlyName); + DscClassCacheEntry cimClassInfo; + + if (ClassCache.TryGetValue(moduleQualifiedResourceName, out cimClassInfo)) + { + if (errors != null) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException( + ParserStrings.DuplicateCimClassDefinition, className, path, cimClassInfo.ModulePath); + + e.SetErrorId("DuplicateCimClassDefinition"); + errors.Add(e); + } + + continue; + } + + if (s_hiddenResourceCache.Contains(className)) + { + continue; + } + + var classCacheEntry = new DscClassCacheEntry(DSCResourceRunAsCredential.NotSupported, importInBoxResourcesImplicitly, c, path); + ClassCache[moduleQualifiedResourceName] = classCacheEntry; + GuestConfigClassCache[moduleQualifiedResourceName] = classCacheEntry; + ByClassModuleCache[className] = moduleInfo; + } + + var sb = new System.Text.StringBuilder(); + foreach (dynamic c in classes) + { + sb.Append(c.ClassName); + sb.Append(','); + } + + s_tracer.WriteLine("DSC ClassCache: loading file '{0}' added the following classes to the cache: {1}", path, sb.ToString()); + } + else + { + s_tracer.WriteLine("DSC ClassCache: loading file '{0}' added no classes to the cache."); + } + + return classes; + } + + /// + /// Get text from SecureString. + /// + /// Value of SecureString. + /// Decoded string. + public static string GetStringFromSecureString(SecureString value) + { + string passwordValueToAdd = string.Empty; + + if (value != null) + { + IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(value); + passwordValueToAdd = Marshal.PtrToStringUni(ptr); + Marshal.ZeroFreeCoTaskMemUnicode(ptr); + } + + return passwordValueToAdd; + } + + /// + /// Clear out the existing collection of CIM classes and associated keywords. + /// + public static void ClearCache() + { + if (!ExperimentalFeature.IsEnabled(DscExperimentalFeatureName)) + { + throw new InvalidOperationException(ParserStrings.PS7DscSupportDisabled); + } + + s_tracer.WriteLine("DSC class: clearing the cache and associated keywords."); + ClassCache.Clear(); + ByClassModuleCache.Clear(); + CacheResourcesFromMultipleModuleVersions = false; + t_currentImportDscResourceInvocations.Clear(); + } + + private static string GetModuleQualifiedResourceName(string moduleName, string moduleVersion, string className, string resourceName) + { + return string.Format(CultureInfo.InvariantCulture, "{0}\\{1}\\{2}\\{3}", moduleName, moduleVersion, className, resourceName); + } + + private static List> FindResourceInCache(string moduleName, string className, string resourceName) + { + return (from cacheEntry in ClassCache + let splittedName = cacheEntry.Key.Split(Utils.Separators.Backslash) + let cachedClassName = splittedName[ClassNameIndex] + let cachedModuleName = splittedName[ModuleNameIndex] + let cachedResourceName = splittedName[FriendlyNameIndex] + where (string.Equals(cachedResourceName, resourceName, StringComparison.OrdinalIgnoreCase) + || (string.Equals(cachedClassName, className, StringComparison.OrdinalIgnoreCase) + && string.Equals(cachedModuleName, moduleName, StringComparison.OrdinalIgnoreCase))) + select cacheEntry).ToList(); + } + + /// + /// Returns class declaration from GuestConfigClassCache. + /// + /// Module name. + /// Module version. + /// Name of the class. + /// Friendly name of the resource. + /// Class declaration from cache. + public static PSObject GetGuestConfigCachedClass(string moduleName, string moduleVersion, string className, string resourceName) + { + if (!ExperimentalFeature.IsEnabled(DscExperimentalFeatureName)) + { + throw new InvalidOperationException(ParserStrings.PS7DscSupportDisabled); + } + + var moduleQualifiedResourceName = GetModuleQualifiedResourceName(moduleName, moduleVersion, className, string.IsNullOrEmpty(resourceName) ? className : resourceName); + DscClassCacheEntry classCacheEntry = null; + if (GuestConfigClassCache.TryGetValue(moduleQualifiedResourceName, out classCacheEntry)) + { + return classCacheEntry.CimClassInstance; + } + else + { + // if class was not found with current ResourceName then it may be a class with non-empty FriendlyName that caller does not know, so perform a broad search + string partialClassPath = string.Join('\\', moduleName, moduleVersion, className, string.Empty); + foreach (string key in GuestConfigClassCache.Keys) + { + if (key.StartsWith(partialClassPath)) + { + return GuestConfigClassCache[key].CimClassInstance; + } + } + + return null; + } + } + + /// + /// Clears GuestConfigClassCache. + /// + public static void ClearGuestConfigClassCache() + { + GuestConfigClassCache.Clear(); + } + + private static bool IsMagicProperty(string propertyName) + { + return System.Text.RegularExpressions.Regex.Match(propertyName, "^(ResourceId|SourceInfo|ModuleName|ModuleVersion|ConfigurationName)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Success; + } + + private static string GetFriendlyName(dynamic cimClass) + { + return cimClass.FriendlyName; + } + + /// + /// Method to get the cached classes in the form of DynamicKeyword. + /// + /// Dynamic keyword collection. + public static Collection GetKeywordsFromCachedClasses() + { + if (!ExperimentalFeature.IsEnabled(DscExperimentalFeatureName)) + { + throw new InvalidOperationException(ParserStrings.PS7DscSupportDisabled); + } + + Collection keywords = new Collection(); + + foreach (KeyValuePair cachedClass in ClassCache) + { + string[] splittedName = cachedClass.Key.Split(Utils.Separators.Backslash); + string moduleName = splittedName[ModuleNameIndex]; + string moduleVersion = splittedName[ModuleVersionIndex]; + + var keyword = CreateKeywordFromCimClass(moduleName, Version.Parse(moduleVersion), cachedClass.Value.CimClassInstance, cachedClass.Value.DscResRunAsCred); + if (keyword is not null) + { + keywords.Add(keyword); + } + } + + return keywords; + } + + private static void CreateAndRegisterKeywordFromCimClass(string moduleName, Version moduleVersion, PSObject cimClass, Dictionary functionsToDefine, DSCResourceRunAsCredential runAsBehavior) + { + var keyword = CreateKeywordFromCimClass(moduleName, moduleVersion, cimClass, runAsBehavior); + if (keyword is null) + { + return; + } + + // keyword is already defined and we don't allow redefine it + if (!CacheResourcesFromMultipleModuleVersions && DynamicKeyword.ContainsKeyword(keyword.Keyword)) + { + var oldKeyword = DynamicKeyword.GetKeyword(keyword.Keyword); + if (oldKeyword.ImplementingModule is null || + !oldKeyword.ImplementingModule.Equals(moduleName, StringComparison.OrdinalIgnoreCase) || oldKeyword.ImplementingModuleVersion != moduleVersion) + { + var e = PSTraceSource.NewInvalidOperationException(ParserStrings.DuplicateKeywordDefinition, keyword.Keyword); + e.SetErrorId("DuplicateKeywordDefinition"); + throw e; + } + } + + // Add the dynamic keyword to the table + DynamicKeyword.AddKeyword(keyword); + + // And now define the driver functions in the current scope... + if (functionsToDefine != null) + { + functionsToDefine[moduleName + "\\" + keyword.Keyword] = CimKeywordImplementationFunction; + } + } + + private static DynamicKeyword CreateKeywordFromCimClass(string moduleName, Version moduleVersion, dynamic cimClass, DSCResourceRunAsCredential runAsBehavior) + { + var resourceName = cimClass.ClassName; + string alias = GetFriendlyName(cimClass); + var keywordString = string.IsNullOrEmpty(alias) ? resourceName : alias; + + // Skip all of the base, meta, registration and other classes that are not intended to be used directly by a script author + if (System.Text.RegularExpressions.Regex.Match(keywordString, "^OMI_Base|^OMI_.*Registration", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Success) + { + return null; + } + + var keyword = new DynamicKeyword() + { + BodyMode = DynamicKeywordBodyMode.Hashtable, + Keyword = keywordString, + ResourceName = resourceName, + ImplementingModule = moduleName, + ImplementingModuleVersion = moduleVersion, + SemanticCheck = CheckMandatoryPropertiesPresent + }; + + // If it's one of reserved dynamic keyword, mark it + if (s_reservedDynamicKeywords.Contains(keywordString)) + { + keyword.IsReservedKeyword = true; + } + + // see if it's a resource type i.e. it inherits from OMI_BaseResource + bool isResourceType = false; + + // previous version of this code was the only place that referenced CimSuperClass + // so to simplify things we just check superclass to be OMI_BaseResource + // with assumption that current code will not work for multi-level class inheritance (which is never used in practice according to DSC team) + // this simplification allows us to avoid linking objects together using CimSuperClass field during deserialization + if ((!string.IsNullOrEmpty(cimClass.SuperClassName)) && string.Equals("OMI_BaseResource", cimClass.SuperClassName, StringComparison.OrdinalIgnoreCase)) + { + isResourceType = true; + } + + // If it's a resource type, then a resource name is required. + keyword.NameMode = isResourceType ? DynamicKeywordNameMode.NameRequired : DynamicKeywordNameMode.NoName; + + // Add the settable properties to the keyword object + if (cimClass.ClassProperties != null) + { + foreach (var prop in cimClass.ClassProperties) + { + // If the property has the Read qualifier, skip it. + if (string.Equals(prop.Qualifiers?.Read?.ToString(), "True", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + // If it's one of our magic properties, skip it + if (IsMagicProperty(prop.Name)) + { + continue; + } + + if (runAsBehavior == DSCResourceRunAsCredential.NotSupported) + { + if (string.Equals(prop.Name, "PsDscRunAsCredential", StringComparison.OrdinalIgnoreCase)) + { + // skip adding PsDscRunAsCredential to the dynamic word for the dsc resource. + continue; + } + } + + // If it's one of our reserved properties, save it for error reporting + if (s_reservedProperties.Contains(prop.Name)) + { + keyword.HasReservedProperties = true; + continue; + } + + // Otherwise, add it to the Keyword List. + var keyProp = new System.Management.Automation.Language.DynamicKeywordProperty(); + keyProp.Name = prop.Name; + + // Copy the type name string. If it's an embedded instance, need to grab it from the ReferenceClassName + bool referenceClassNameIsNullOrEmpty = string.IsNullOrEmpty(prop.ReferenceClassName); + if (prop.CimType == "Instance" && !referenceClassNameIsNullOrEmpty) + { + keyProp.TypeConstraint = prop.ReferenceClassName; + } + else if (prop.CimType == "InstanceArray" && !referenceClassNameIsNullOrEmpty) + { + keyProp.TypeConstraint = prop.ReferenceClassName + "[]"; + } + else + { + keyProp.TypeConstraint = prop.CimType.ToString(); + } + + // Check to see if there is a Values attribute and save the list of allowed values if so. + var values = prop.Qualifiers?.Values; + if (values is not null) + { + foreach (var val in values) + { + keyProp.Values.Add(val.ToString()); + } + } + + // Check to see if there is a ValueMap attribute and save the list of allowed values if so. + var nativeValueMap = prop.Qualifiers?.ValueMap; + List valueMap = null; + if (nativeValueMap is not null) + { + valueMap = new List(); + foreach (var val in nativeValueMap) + { + valueMap.Add(val.ToString()); + } + } + + // Check to see if this property has the Required qualifier associated with it. + if (string.Equals(prop.Qualifiers?.Required?.ToString(), "True", StringComparison.OrdinalIgnoreCase)) + { + keyProp.Mandatory = true; + } + + // Check to see if this property has the Key qualifier associated with it. + if (string.Equals(prop.Qualifiers?.Key?.ToString(), "True", StringComparison.OrdinalIgnoreCase)) + { + keyProp.Mandatory = true; + keyProp.IsKey = true; + } + + // set the property to mandatory is specified for the resource. + if (runAsBehavior == DSCResourceRunAsCredential.Mandatory) + { + if (string.Equals(prop.Name, "PsDscRunAsCredential", StringComparison.OrdinalIgnoreCase)) + { + keyProp.Mandatory = true; + } + } + + if (valueMap is not null && keyProp.Values.Count > 0) + { + if (valueMap.Count != keyProp.Values.Count) + { + s_tracer.WriteLine( + "DSC CreateDynamicKeywordFromClass: the count of values for qualifier 'Values' and 'ValueMap' doesn't match. count of 'Values': {0}, count of 'ValueMap': {1}. Skip the keyword '{2}'.", + keyProp.Values.Count, + valueMap.Count, + keyword.Keyword); + return null; + } + + for (int index = 0; index < valueMap.Count; index++) + { + string key = keyProp.Values[index]; + string value = valueMap[index]; + + if (keyProp.ValueMap.ContainsKey(key)) + { + s_tracer.WriteLine( + "DSC CreateDynamicKeywordFromClass: same string value '{0}' appears more than once in qualifier 'Values'. Skip the keyword '{1}'.", + key, + keyword.Keyword); + return null; + } + + keyProp.ValueMap.Add(key, value); + } + } + + keyword.Properties.Add(prop.Name, keyProp); + } + } + + // update specific keyword with range constraints + UpdateKnownRestriction(keyword); + + return keyword; + } + + private static void UpdateKnownRestriction(DynamicKeyword keyword) + { + const int RefreshFrequencyMin = 30; + const int RefreshFrequencyMax = 44640; + + const int ConfigurationModeFrequencyMin = 15; + const int ConfigurationModeFrequencyMax = 44640; + + if ( + string.Equals( + keyword.ResourceName, + "MSFT_DSCMetaConfigurationV2", + StringComparison.OrdinalIgnoreCase) + || + string.Equals( + keyword.ResourceName, + "MSFT_DSCMetaConfiguration", + StringComparison.OrdinalIgnoreCase)) + { + if (keyword.Properties["RefreshFrequencyMins"] is not null) + { + keyword.Properties["RefreshFrequencyMins"].Range = new Tuple(RefreshFrequencyMin, RefreshFrequencyMax); + } + + if (keyword.Properties["ConfigurationModeFrequencyMins"] != null) + { + keyword.Properties["ConfigurationModeFrequencyMins"].Range = new Tuple(ConfigurationModeFrequencyMin, ConfigurationModeFrequencyMax); + } + + if (keyword.Properties["DebugMode"] is not null) + { + keyword.Properties["DebugMode"].Values.Remove("ResourceScriptBreakAll"); + keyword.Properties["DebugMode"].ValueMap.Remove("ResourceScriptBreakAll"); + } + } + } + + /// + /// Load the default system CIM classes and create the corresponding keywords. + /// + /// Collection of any errors encountered while loading keywords. + public static void LoadDefaultCimKeywords(Collection errors) + { + LoadDefaultCimKeywords(functionsToDefine: null, errors, modulePathList: null, cacheResourcesFromMultipleModuleVersions: false); + } + + /// + /// Load the default system CIM classes and create the corresponding keywords. + /// + /// A dictionary to add the defined functions to, may be null. + public static void LoadDefaultCimKeywords(Dictionary functionsToDefine) + { + LoadDefaultCimKeywords(functionsToDefine, errors: null, modulePathList: null, cacheResourcesFromMultipleModuleVersions: false); + } + + /// + /// Load the default system CIM classes and create the corresponding keywords. + /// + /// Collection of any errors encountered while loading keywords. + /// Allow caching the resources from multiple versions of modules. + public static void LoadDefaultCimKeywords(Collection errors, bool cacheResourcesFromMultipleModuleVersions) + { + LoadDefaultCimKeywords(functionsToDefine: null, errors, modulePathList: null, cacheResourcesFromMultipleModuleVersions); + } + + /// + /// Load the default system CIM classes and create the corresponding keywords. + /// + /// A dictionary to add the defined functions to, may be null. + /// Collection of any errors encountered while loading keywords. + /// List of module path from where DSC PS modules will be loaded. + /// Allow caching the resources from multiple versions of modules. + private static void LoadDefaultCimKeywords( + Dictionary functionsToDefine, + Collection errors, + List modulePathList, + bool cacheResourcesFromMultipleModuleVersions) + { + if (!ExperimentalFeature.IsEnabled(DscExperimentalFeatureName)) + { + Exception exception = new InvalidOperationException(ParserStrings.PS7DscSupportDisabled); + errors.Add(exception); + return; + } + + NewApiIsUsed = true; + DynamicKeyword.Reset(); + Initialize(errors, modulePathList); + + // Initialize->ClearCache resets CacheResourcesFromMultipleModuleVersions to false, + // workaround is to set it after Initialize method call. + // Initialize method imports all the Inbox resources and internal classes which belongs to only one version + // of the module, so it is ok if this property is not set during cache initialization. + CacheResourcesFromMultipleModuleVersions = cacheResourcesFromMultipleModuleVersions; + + foreach (dynamic cimClass in ClassCache.Values) + { + var className = cimClass.CimClassInstance.ClassName; + var moduleInfo = ByClassModuleCache[className]; + CreateAndRegisterKeywordFromCimClass(moduleInfo.Item1, moduleInfo.Item2, cimClass.CimClassInstance, functionsToDefine, cimClass.DscResRunAsCred); + } + + // And add the Node keyword definitions + if (!DynamicKeyword.ContainsKeyword("Node")) + { + // Implement dispatch to the Node keyword. + var nodeKeyword = new DynamicKeyword() + { + BodyMode = DynamicKeywordBodyMode.ScriptBlock, + ImplementingModule = s_defaultModuleInfoForResource.Item1, + ImplementingModuleVersion = s_defaultModuleInfoForResource.Item2, + NameMode = DynamicKeywordNameMode.NameRequired, + Keyword = "Node", + }; + DynamicKeyword.AddKeyword(nodeKeyword); + } + + // And add the Import-DscResource keyword definitions + if (!DynamicKeyword.ContainsKeyword("Import-DscResource")) + { + // Implement dispatch to the Node keyword. + var nodeKeyword = new DynamicKeyword() + { + BodyMode = DynamicKeywordBodyMode.Command, + ImplementingModule = s_defaultModuleInfoForResource.Item1, + ImplementingModuleVersion = s_defaultModuleInfoForResource.Item2, + NameMode = DynamicKeywordNameMode.NoName, + Keyword = "Import-DscResource", + MetaStatement = true, + PostParse = ImportResourcePostParse, + SemanticCheck = ImportResourceCheckSemantics + }; + DynamicKeyword.AddKeyword(nodeKeyword); + } + } + + // This function is called after parsing the Import-DscResource keyword and it's arguments, but before parsing anything else. + private static ParseError[] ImportResourcePostParse(DynamicKeywordStatementAst ast) + { + var elements = Ast.CopyElements(ast.CommandElements); + var commandAst = new CommandAst(ast.Extent, elements, TokenKind.Unknown, null); + + const string NameParam = "Name"; + const string ModuleNameParam = "ModuleName"; + const string ModuleVersionParam = "ModuleVersion"; + + StaticBindingResult bindingResult = StaticParameterBinder.BindCommand(commandAst, false); + + var errorList = new List(); + foreach (var bindingException in bindingResult.BindingExceptions.Values) + { + errorList.Add(new ParseError(bindingException.CommandElement.Extent, "ParameterBindingException", bindingException.BindingException.Message)); + } + + ParameterBindingResult moduleNameBindingResult = null; + ParameterBindingResult resourceNameBindingResult = null; + ParameterBindingResult moduleVersionBindingResult = null; + + foreach (var binding in bindingResult.BoundParameters) + { + // Error case when positional parameter values are specified + var boundParameterName = binding.Key; + var parameterBindingResult = binding.Value; + if (boundParameterName.All(char.IsDigit)) + { + errorList.Add(new ParseError(parameterBindingResult.Value.Extent, "ImportDscResourcePositionalParamsNotSupported", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourcePositionalParamsNotSupported))); + continue; + } + + if (NameParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) + { + resourceNameBindingResult = parameterBindingResult; + } + else if (ModuleNameParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) + { + moduleNameBindingResult = parameterBindingResult; + } + else if (ModuleVersionParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) + { + moduleVersionBindingResult = parameterBindingResult; + } + else + { + errorList.Add(new ParseError(parameterBindingResult.Value.Extent, "ImportDscResourceNeedParams", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); + } + } + + if (errorList.Count == 0 && moduleNameBindingResult == null && resourceNameBindingResult == null) + { + errorList.Add(new ParseError(ast.Extent, "ImportDscResourceNeedParams", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); + } + + // Check here if Version is specified but modulename is not specified + if (moduleVersionBindingResult != null && moduleNameBindingResult == null) + { + // only add this error again to the error list if resources is not null + // if resources and modules are both null we have already added this error in collection + // we do not want to do this twice. since we are giving same error ImportDscResourceNeedParams in both cases + // once we have different error messages for 2 scenarios we can remove this check + if (resourceNameBindingResult is not null) + { + errorList.Add(new ParseError(ast.Extent, "ImportDscResourceNeedModuleNameWithModuleVersion", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); + } + } + + string[] resourceNames = null; + if (resourceNameBindingResult is not null) + { + object resourceName = null; + if (!IsConstantValueVisitor.IsConstant(resourceNameBindingResult.Value, out resourceName, true, true) || + !LanguagePrimitives.TryConvertTo(resourceName, out resourceNames)) + { + errorList.Add(new ParseError(resourceNameBindingResult.Value.Extent, "RequiresInvalidStringArgument", string.Format(CultureInfo.CurrentCulture, ParserStrings.RequiresInvalidStringArgument, NameParam))); + } + } + + System.Version moduleVersion = null; + if (moduleVersionBindingResult is not null) + { + object moduleVer = null; + if (!IsConstantValueVisitor.IsConstant(moduleVersionBindingResult.Value, out moduleVer, true, true)) + { + errorList.Add(new ParseError(moduleVersionBindingResult.Value.Extent, "RequiresArgumentMustBeConstant", ParserStrings.RequiresArgumentMustBeConstant)); + } + + if (moduleVer is double) + { + // this happens in case -ModuleVersion 1.0, then use extent text for that. + // The better way to do it would be define static binding API against CommandInfo, that holds information about parameter types. + // This way, we can avoid this ugly special-casing and say that -ModuleVersion has type [System.Version]. + moduleVer = moduleVersionBindingResult.Value.Extent.Text; + } + + if (!LanguagePrimitives.TryConvertTo(moduleVer, out moduleVersion)) + { + errorList.Add(new ParseError(moduleVersionBindingResult.Value.Extent, "RequiresVersionInvalid", ParserStrings.RequiresVersionInvalid)); + } + } + + ModuleSpecification[] moduleSpecifications = null; + if (moduleNameBindingResult is not null) + { + object moduleName = null; + if (!IsConstantValueVisitor.IsConstant(moduleNameBindingResult.Value, out moduleName, true, true)) + { + errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "RequiresArgumentMustBeConstant", ParserStrings.RequiresArgumentMustBeConstant)); + } + + if (LanguagePrimitives.TryConvertTo(moduleName, out moduleSpecifications)) + { + // if resourceNames are specified then we can not specify multiple modules name + if (moduleSpecifications is not null && moduleSpecifications.Length > 1 && resourceNames is not null) + { + errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModulesNotSupportedWithName", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceMultipleModulesNotSupportedWithName))); + } + + // if moduleversion is specified then we can not specify multiple modules name + if (moduleSpecifications is not null && moduleSpecifications.Length > 1 && moduleVersion is not null) + { + errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModulesNotSupportedWithVersion", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); + } + + // if moduleversion is specified then we can not specify another version in modulespecification object of ModuleName + if (moduleSpecifications is not null && (moduleSpecifications[0].Version is not null || moduleSpecifications[0].MaximumVersion is not null) && moduleVersion is not null) + { + errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModuleVersionsNotSupported", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); + } + + // If moduleVersion is specified we have only one module Name in valid scenario + // So update it's version property in module specification object that will be used to load modules + if (moduleSpecifications is not null && moduleSpecifications[0].Version is null && moduleSpecifications[0].MaximumVersion is null && moduleVersion is not null) + { + moduleSpecifications[0].Version = moduleVersion; + } + } + else + { + errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "RequiresInvalidStringArgument", string.Format(CultureInfo.CurrentCulture, ParserStrings.RequiresInvalidStringArgument, ModuleNameParam))); + } + } + + if (errorList.Count == 0) + { + // No errors, try to load the resources + LoadResourcesFromModuleInImportResourcePostParse(ast.Extent, moduleSpecifications, resourceNames, errorList); + } + + return errorList.ToArray(); + } + + // This function performs semantic checks for Import-DscResource + private static ParseError[] ImportResourceCheckSemantics(DynamicKeywordStatementAst ast) + { + List errorList = null; + + var keywordAst = Ast.GetAncestorAst(ast.Parent); + while (keywordAst is not null) + { + if (keywordAst.Keyword.Keyword.Equals("Node")) + { + if (errorList is null) + { + errorList = new List(); + } + + errorList.Add(new ParseError(ast.Extent, "ImportDscResourceInsideNode", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceInsideNode))); + break; + } + + keywordAst = Ast.GetAncestorAst(keywordAst.Parent); + } + + if (errorList is not null) + { + return errorList.ToArray(); + } + else + { + return null; + } + } + + // This function performs semantic checks for all DSC Resources keywords. + private static ParseError[] CheckMandatoryPropertiesPresent(DynamicKeywordStatementAst ast) + { + HashSet mandatoryPropertiesNames = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var pair in ast.Keyword.Properties) + { + if (pair.Value.Mandatory) + { + mandatoryPropertiesNames.Add(pair.Key); + } + } + + // by design mandatoryPropertiesNames are not empty at this point: + // every resource must have at least one Key property. + HashtableAst hashtableAst = null; + foreach (var commandElementsAst in ast.CommandElements) + { + hashtableAst = commandElementsAst as HashtableAst; + if (hashtableAst != null) + { + break; + } + } + + if (hashtableAst is null) + { + // nothing to validate + return null; + } + + foreach (var pair in hashtableAst.KeyValuePairs) + { + object evalResultObject; + if (IsConstantValueVisitor.IsConstant(pair.Item1, out evalResultObject, forAttribute: false, forRequires: false)) + { + var presentName = evalResultObject as string; + if (presentName is not null) + { + if (mandatoryPropertiesNames.Remove(presentName) && mandatoryPropertiesNames.Count == 0) + { + // optimization, once all mandatory properties are specified, we can safely exit. + return null; + } + } + } + } + + if (mandatoryPropertiesNames.Count > 0) + { + ParseError[] errors = new ParseError[mandatoryPropertiesNames.Count]; + var extent = ast.CommandElements[0].Extent; + int i = 0; + foreach (string name in mandatoryPropertiesNames) + { + errors[i] = new ParseError( + extent, + "MissingValueForMandatoryProperty", + string.Format( + CultureInfo.CurrentCulture, + ParserStrings.MissingValueForMandatoryProperty, + ast.Keyword.Keyword, + ast.Keyword.Properties.First(p => StringComparer.OrdinalIgnoreCase.Equals(p.Value.Name, name)).Value.TypeConstraint, + name)); + i++; + } + + return errors; + } + + return null; + } + + /// + /// Load DSC resources from specified module. + /// + /// Script statement loading the module, can be null. + /// Module information, can be null. + /// Name of the resource to be loaded from module. + /// List of errors reported by the method. + internal static void LoadResourcesFromModuleInImportResourcePostParse( + IScriptExtent scriptExtent, + ModuleSpecification[] moduleSpecifications, + string[] resourceNames, + List errorList) + { + // get all required modules + var modules = new Collection(); + if (moduleSpecifications is not null) + { + foreach (var moduleToImport in moduleSpecifications) + { + bool foundModule = false; + var moduleInfos = ModuleCmdletBase.GetModuleIfAvailable(moduleToImport); + + if (moduleInfos.Count >= 1 && (moduleToImport.Version is not null || moduleToImport.Guid is not null)) + { + foreach (var psModuleInfo in moduleInfos) + { + if ((moduleToImport.Guid.HasValue && moduleToImport.Guid.Equals(psModuleInfo.Guid)) || + (moduleToImport.Version is not null && + moduleToImport.Version.Equals(psModuleInfo.Version))) + { + modules.Add(psModuleInfo); + foundModule = true; + break; + } + } + } + else if (moduleInfos.Count == 1) + { + modules.Add(moduleInfos[0]); + foundModule = true; + } + + if (!foundModule) + { + if (moduleInfos.Count > 1) + { + errorList.Add( + new ParseError( + scriptExtent, + "MultipleModuleEntriesFoundDuringParse", + string.Format(CultureInfo.CurrentCulture, ParserStrings.MultipleModuleEntriesFoundDuringParse, moduleToImport.Name))); + } + else + { + string moduleString = moduleToImport.Version == null + ? moduleToImport.Name + : string.Format(CultureInfo.CurrentCulture, "<{0}, {1}>", moduleToImport.Name, moduleToImport.Version); + + errorList.Add(new ParseError(scriptExtent, "ModuleNotFoundDuringParse", string.Format(CultureInfo.CurrentCulture, ParserStrings.ModuleNotFoundDuringParse, moduleString))); + } + + return; + } + } + } + else if (resourceNames is not null) + { + // Lookup the required resources under available PowerShell modules when modulename is not specified + // Make sure that this is not a circular import/parsing + var callLocation = string.Join(':', scriptExtent.File, scriptExtent.StartLineNumber, scriptExtent.StartColumnNumber, scriptExtent.Text); + if (!t_currentImportDscResourceInvocations.Contains(callLocation)) + { + t_currentImportDscResourceInvocations.Add(callLocation); + using (var powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) + { + powerShell.AddCommand("Get-Module"); + powerShell.AddParameter("ListAvailable"); + modules = powerShell.Invoke(); + } + } + } + + // When ModuleName only specified, we need to import all resources from that module + var resourcesToImport = new List(); + if (resourceNames is null || resourceNames.Length == 0) + { + resourcesToImport.Add("*"); + } + else + { + resourcesToImport.AddRange(resourceNames); + } + + foreach (var moduleInfo in modules) + { + var resourcesFound = new List(); + var exceptionList = new System.Collections.ObjectModel.Collection(); + LoadPowerShellClassResourcesFromModule(primaryModuleInfo: moduleInfo, moduleInfo: moduleInfo, resourcesToImport: resourcesToImport, resourcesFound: resourcesFound, errorList: exceptionList, functionsToDefine: null, recurse: true, extent: scriptExtent); + foreach (Exception ex in exceptionList) + { + errorList.Add(new ParseError(scriptExtent, "ClassResourcesLoadingFailed", ex.Message)); + } + + foreach (var resource in resourcesFound) + { + resourcesToImport.Remove(resource); + } + + if (resourcesToImport.Count == 0) + { + break; + } + } + + if (resourcesToImport.Count > 0) + { + foreach (var resourceNameToImport in resourcesToImport) + { + if (!resourceNameToImport.Contains('*')) + { + errorList.Add(new ParseError(scriptExtent, "DscResourcesNotFoundDuringParsing", string.Format(CultureInfo.CurrentCulture, ParserStrings.DscResourcesNotFoundDuringParsing, resourceNameToImport))); + } + } + } + } + + private static void LoadPowerShellClassResourcesFromModule( + PSModuleInfo primaryModuleInfo, + PSModuleInfo moduleInfo, + ICollection resourcesToImport, + ICollection resourcesFound, + Collection errorList, + Dictionary functionsToDefine = null, + bool recurse = true, + IScriptExtent extent = null) + { + if (primaryModuleInfo._declaredDscResourceExports is null || primaryModuleInfo._declaredDscResourceExports.Count == 0) + { + return; + } + + if (moduleInfo.ModuleType == ModuleType.Binary) + { + throw PSTraceSource.NewArgumentException("isConfiguration", ParserStrings.ConfigurationNotSupportedInPowerShellCore); + } + else + { + string scriptPath = null; + if (moduleInfo.RootModule is not null) + { + scriptPath = Path.Join(moduleInfo.ModuleBase, moduleInfo.RootModule); + } + else if (moduleInfo.Path is not null) + { + scriptPath = moduleInfo.Path; + } + + LoadPowerShellClassResourcesFromModule(scriptPath, primaryModuleInfo, resourcesToImport, resourcesFound, functionsToDefine, errorList, extent); + } + + if (moduleInfo.NestedModules is not null && recurse) + { + foreach (var nestedModule in moduleInfo.NestedModules) + { + LoadPowerShellClassResourcesFromModule(primaryModuleInfo, nestedModule, resourcesToImport, resourcesFound, errorList, functionsToDefine, recurse: false, extent: extent); + } + } + } + + /// + /// Import class resources from module. + /// + /// Module information. + /// Collection of resources to import. + /// Functions to define. + /// List of errors to return. + /// The list of resources imported from this module. + public static List ImportClassResourcesFromModule(PSModuleInfo moduleInfo, ICollection resourcesToImport, Dictionary functionsToDefine, Collection errors) + { + if (!ExperimentalFeature.IsEnabled(DscExperimentalFeatureName)) + { + throw new InvalidOperationException(ParserStrings.PS7DscSupportDisabled); + } + + var resourcesImported = new List(); + LoadPowerShellClassResourcesFromModule(moduleInfo, moduleInfo, resourcesToImport, resourcesImported, errors, functionsToDefine); + return resourcesImported; + } + + internal static PSObject[] GenerateJsonClassesForAst(TypeDefinitionAst typeAst, PSModuleInfo module, DSCResourceRunAsCredential runAsBehavior) + { + var embeddedInstanceTypes = new List(); + + var result = GenerateJsonClassesForAst(typeAst, embeddedInstanceTypes); + var visitedInstances = new List(); + visitedInstances.Add(typeAst); + var classes = ProcessEmbeddedInstanceTypes(embeddedInstanceTypes, visitedInstances); + AddEmbeddedInstanceTypesToCaches(classes, module, runAsBehavior); + + return result; + } + + private static List ProcessEmbeddedInstanceTypes(List embeddedInstanceTypes, List visitedInstances) + { + var result = new List(); + while (embeddedInstanceTypes.Count > 0) + { + var batchedTypes = embeddedInstanceTypes.Where(x => !visitedInstances.Contains(x)).ToArray(); + embeddedInstanceTypes.Clear(); + + for (int i = batchedTypes.Length - 1; i >= 0; i--) + { + visitedInstances.Add(batchedTypes[i]); + var typeAst = batchedTypes[i] as TypeDefinitionAst; + if (typeAst is not null) + { + var classes = GenerateJsonClassesForAst(typeAst, embeddedInstanceTypes); + result.AddRange(classes); + } + } + } + + return result; + } + + private static void AddEmbeddedInstanceTypesToCaches(IEnumerable classes, PSModuleInfo module, DSCResourceRunAsCredential runAsBehavior) + { + foreach (dynamic c in classes) + { + var className = c.ClassName; + string alias = GetFriendlyName(c); + var friendlyName = string.IsNullOrEmpty(alias) ? className : alias; + var moduleQualifiedResourceName = GetModuleQualifiedResourceName(module.Name, module.Version.ToString(), className, friendlyName); + var classCacheEntry = new DscClassCacheEntry(runAsBehavior, false, c, module.Path); + ClassCache[moduleQualifiedResourceName] = classCacheEntry; + GuestConfigClassCache[moduleQualifiedResourceName] = classCacheEntry; + ByClassModuleCache[className] = new Tuple(module.Name, module.Version); + } + } + + internal static string MapTypeNameToMofType(ITypeName typeName, string memberName, string className, out bool isArrayType, out string embeddedInstanceType, List embeddedInstanceTypes, ref string[] enumNames) + { + TypeName propTypeName; + var arrayTypeName = typeName as ArrayTypeName; + if (arrayTypeName is not null) + { + isArrayType = true; + propTypeName = arrayTypeName.ElementType as TypeName; + } + else + { + isArrayType = false; + propTypeName = typeName as TypeName; + } + + if (propTypeName is null || propTypeName._typeDefinitionAst is null) + { + throw new NotSupportedException(string.Format( + CultureInfo.InvariantCulture, + ParserStrings.UnsupportedPropertyTypeOfDSCResourceClass, + memberName, + typeName.FullName, + typeName)); + } + + if (propTypeName._typeDefinitionAst.IsEnum) + { + enumNames = propTypeName._typeDefinitionAst.Members.Select(m => m.Name).ToArray(); + isArrayType = false; + embeddedInstanceType = null; + return "string"; + } + + if (!embeddedInstanceTypes.Contains(propTypeName._typeDefinitionAst)) + { + embeddedInstanceTypes.Add(propTypeName._typeDefinitionAst); + } + + embeddedInstanceType = propTypeName.Name.Replace('.', '_'); + return "Instance"; + } + + private static PSObject[] GenerateJsonClassesForAst(TypeDefinitionAst typeAst, List embeddedInstanceTypes) + { + // MOF-based implementation of this used to generate MOF string representing classes/typeAst and pass it to MMI/MOF deserializer to get CimClass array + // Here we are avoiding that roundtrip by constructing the resulting PSObjects directly + var className = typeAst.Name; + + string cimSuperClassName = null; + if (typeAst.Attributes.Any(a => a.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute))) + { + cimSuperClassName = "OMI_BaseResource"; + } + + var cimClassProperties = ProcessMembers(embeddedInstanceTypes, typeAst, className).ToArray(); + + Queue bases = new Queue(); + foreach (var b in typeAst.BaseTypes) + { + bases.Enqueue(b); + } + + while (bases.Count > 0) + { + var b = bases.Dequeue(); + var tc = b as TypeConstraintAst; + + if (tc is not null) + { + b = tc.TypeName.GetReflectionType(); + if (b is null) + { + var td = tc.TypeName as TypeName; + if (td is not null && td._typeDefinitionAst is not null) + { + ProcessMembers(embeddedInstanceTypes, td._typeDefinitionAst, className); + foreach (var b1 in td._typeDefinitionAst.BaseTypes) + { + bases.Enqueue(b1); + } + } + + continue; + } + } + } + + var result = new PSObject(); + result.Properties.Add(new PSNoteProperty("ClassName", className)); + result.Properties.Add(new PSNoteProperty("FriendlyName", className)); + result.Properties.Add(new PSNoteProperty("SuperClassName", cimSuperClassName)); + result.Properties.Add(new PSNoteProperty("ClassProperties", cimClassProperties)); + + return new[] { result }; + } + + private static List ProcessMembers(List embeddedInstanceTypes, TypeDefinitionAst typeDefinitionAst, string className) + { + List result = new List(); + + foreach (var member in typeDefinitionAst.Members) + { + var property = member as PropertyMemberAst; + + if (property == null || property.IsStatic || + property.Attributes.All(a => a.TypeName.GetReflectionAttributeType() != typeof(DscPropertyAttribute))) + { + continue; + } + + var memberType = property.PropertyType is null + ? typeof(object) + : property.PropertyType.TypeName.GetReflectionType(); + + var attributes = new List(); + for (int i = 0; i < property.Attributes.Count; i++) + { + attributes.Add(property.Attributes[i].GetAttribute()); + } + + string mofType; + bool isArrayType; + string embeddedInstanceType; + string[] enumNames = null; + + if (memberType != null) + { + mofType = MapTypeToMofType(memberType, member.Name, className, out isArrayType, out embeddedInstanceType, embeddedInstanceTypes); + if (memberType.IsEnum) + { + enumNames = Enum.GetNames(memberType); + } + } + else + { + // PropertyType can't be null, we used typeof(object) above in that case so we don't get here. + mofType = MapTypeNameToMofType(property.PropertyType.TypeName, member.Name, className, out isArrayType, out embeddedInstanceType, embeddedInstanceTypes, ref enumNames); + } + + var propertyObject = new PSObject(); + propertyObject.Properties.Add(new PSNoteProperty(@"Name", member.Name)); + propertyObject.Properties.Add(new PSNoteProperty(@"CimType", mofType + (isArrayType ? "Array" : string.Empty))); + if (!string.IsNullOrEmpty(embeddedInstanceType)) + { + propertyObject.Properties.Add(new PSNoteProperty(@"ReferenceClassName", embeddedInstanceType)); + } + + PSObject attributesPSObject = null; + foreach (var attr in attributes) + { + var dscProperty = attr as DscPropertyAttribute; + if (dscProperty is not null) + { + if (attributesPSObject is null) + { + attributesPSObject = new PSObject(); + } + + if (dscProperty.Key) + { + attributesPSObject.Properties.Add(new PSNoteProperty("Key", true)); + } + + if (dscProperty.Mandatory) + { + attributesPSObject.Properties.Add(new PSNoteProperty("Required", true)); + } + + if (dscProperty.NotConfigurable) + { + attributesPSObject.Properties.Add(new PSNoteProperty("Read", true)); + } + + continue; + } + + var validateSet = attr as ValidateSetAttribute; + if (validateSet is not null) + { + if (attributesPSObject is null) + { + attributesPSObject = new PSObject(); + } + + List valueMap = new List(validateSet.ValidValues); + List values = new List(validateSet.ValidValues); + attributesPSObject.Properties.Add(new PSNoteProperty("ValueMap", valueMap)); + attributesPSObject.Properties.Add(new PSNoteProperty("Values", values)); + } + } + + if (attributesPSObject is not null) + { + propertyObject.Properties.Add(new PSNoteProperty(@"Qualifiers", attributesPSObject)); + } + + result.Add(propertyObject); + } + + return result; + } + + private static bool GetResourceDefinitionsFromModule(string fileName, out IEnumerable resourceDefinitions, Collection errorList, IScriptExtent extent) + { + resourceDefinitions = null; + + if (string.IsNullOrEmpty(fileName)) + { + return false; + } + + if (!".psm1".Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase) && + !".ps1".Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + Token[] tokens; + ParseError[] errors; + var ast = Parser.ParseFile(fileName, out tokens, out errors); + + if (errors is not null && errors.Length > 0) + { + if (errorList is not null && extent is not null) + { + List errorMessages = new List(); + foreach (var error in errors) + { + errorMessages.Add(error.ToString()); + } + + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.FailToParseModuleScriptFile, fileName, string.Join(Environment.NewLine, errorMessages)); + e.SetErrorId("FailToParseModuleScriptFile"); + errorList.Add(e); + } + + return false; + } + + resourceDefinitions = ast.FindAll( + n => + { + var typeAst = n as TypeDefinitionAst; + if (typeAst is not null) + { + for (int i = 0; i < typeAst.Attributes.Count; i++) + { + var a = typeAst.Attributes[i]; + if (a.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute)) + { + return true; + } + } + } + + return false; + }, + false); + + return true; + } + + private static bool LoadPowerShellClassResourcesFromModule(string fileName, PSModuleInfo module, ICollection resourcesToImport, ICollection resourcesFound, Dictionary functionsToDefine, Collection errorList, IScriptExtent extent) + { + IEnumerable resourceDefinitions; + if (!GetResourceDefinitionsFromModule(fileName, out resourceDefinitions, errorList, extent)) + { + return false; + } + + var result = false; + + const WildcardOptions options = WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant; + IEnumerable patternList = SessionStateUtilities.CreateWildcardsFromStrings(module._declaredDscResourceExports, options); + + foreach (var r in resourceDefinitions) + { + result = true; + var resourceDefnAst = (TypeDefinitionAst)r; + + if (!SessionStateUtilities.MatchesAnyWildcardPattern(resourceDefnAst.Name, patternList, true)) + { + continue; + } + + bool skip = true; + foreach (var toImport in resourcesToImport) + { + if (WildcardPattern.Get(toImport, WildcardOptions.IgnoreCase).IsMatch(resourceDefnAst.Name)) + { + skip = false; + break; + } + } + + if (skip) + { + continue; + } + + // Parse the Resource Attribute to see if RunAs behavior is specified for the resource. + DSCResourceRunAsCredential runAsBehavior = DSCResourceRunAsCredential.Default; + foreach (var attr in resourceDefnAst.Attributes) + { + if (attr.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute)) + { + foreach (var na in attr.NamedArguments) + { + if (na.ArgumentName.Equals("RunAsCredential", StringComparison.OrdinalIgnoreCase)) + { + var dscResourceAttribute = attr.GetAttribute() as DscResourceAttribute; + if (dscResourceAttribute != null) + { + runAsBehavior = dscResourceAttribute.RunAsCredential; + } + } + } + } + } + + var classes = GenerateJsonClassesForAst(resourceDefnAst, module, runAsBehavior); + + ProcessJsonForDynamicKeywords(module, resourcesFound, functionsToDefine, classes, runAsBehavior, errorList); + } + + return result; + } + + private static readonly Dictionary s_mapPrimitiveDotNetTypeToMof = new Dictionary() + { + { typeof(sbyte), "sint8" }, + { 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(string), "string" }, + { typeof(DateTime), "datetime" }, + { typeof(PSCredential), "string" }, + { typeof(char), "char16" }, + }; + + internal static string MapTypeToMofType(Type type, string memberName, string className, out bool isArrayType, out string embeddedInstanceType, List embeddedInstanceTypes) + { + isArrayType = false; + if (type.IsValueType) + { + type = Nullable.GetUnderlyingType(type) ?? type; + } + + if (type.IsEnum) + { + embeddedInstanceType = null; + return "string"; + } + + if (type == typeof(Hashtable)) + { + // Hashtable is obviously not an array, but in the mof, we represent + // it as string[] (really, embeddedinstance of MSFT_KeyValuePair), but + // we need an array to hold each entry in the hashtable. + isArrayType = true; + embeddedInstanceType = "MSFT_KeyValuePair"; + return "string"; + } + + if (type == typeof(PSCredential)) + { + embeddedInstanceType = "MSFT_Credential"; + return "string"; + } + + if (type.IsArray) + { + isArrayType = true; + bool temp; + var elementType = type.GetElementType(); + if (!elementType.IsArray) + { + return MapTypeToMofType(type.GetElementType(), memberName, className, out temp, out embeddedInstanceType, embeddedInstanceTypes); + } + } + else + { + string cimType; + if (s_mapPrimitiveDotNetTypeToMof.TryGetValue(type, out cimType)) + { + embeddedInstanceType = null; + return cimType; + } + } + + bool supported = false; + bool missingDefaultConstructor = false; + if (type.IsValueType) + { + if (s_mapPrimitiveDotNetTypeToMof.ContainsKey(type)) + { + supported = true; + } + } + else if (!type.IsAbstract) + { + // Must have default constructor, at least 1 public property/field, and no base classes + if (type.GetConstructor(Type.EmptyTypes) is null) + { + missingDefaultConstructor = true; + } + else if (type.BaseType == typeof(object) && + (type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Length > 0 || + type.GetFields(BindingFlags.Instance | BindingFlags.Public).Length > 0)) + { + supported = true; + } + } + + if (supported) + { + if (!embeddedInstanceTypes.Contains(type)) + { + embeddedInstanceTypes.Add(type); + } + + // The type is obviously not a string, but in the mof, we represent + // it as string (really, embeddedinstance of the class type) + embeddedInstanceType = type.FullName.Replace('.', '_'); + return "string"; + } + + if (missingDefaultConstructor) + { + throw new NotSupportedException(string.Format( + CultureInfo.InvariantCulture, + ParserStrings.DscResourceMissingDefaultConstructor, + type.Name)); + } + else + { + throw new NotSupportedException(string.Format( + CultureInfo.InvariantCulture, + ParserStrings.UnsupportedPropertyTypeOfDSCResourceClass, + memberName, + type.Name, + className)); + } + } + + private static void ProcessJsonForDynamicKeywords( + PSModuleInfo module, + ICollection resourcesFound, + Dictionary functionsToDefine, + PSObject[] classes, + DSCResourceRunAsCredential runAsBehavior, + Collection errors) + { + foreach (dynamic c in classes) + { + var className = c.ClassName; + string alias = GetFriendlyName(c); + var friendlyName = string.IsNullOrEmpty(alias) ? className : alias; + if (!CacheResourcesFromMultipleModuleVersions) + { + // Find & remove the previous version of the resource. + List> resourceList = FindResourceInCache(module.Name, className, friendlyName); + + if (resourceList.Count > 0 && !string.IsNullOrEmpty(resourceList[0].Key)) + { + ClassCache.Remove(resourceList[0].Key); + + // keyword is already defined and it is a Inbox resource, remove it + if (DynamicKeyword.ContainsKeyword(friendlyName) && resourceList[0].Value.IsImportedImplicitly) + { + DynamicKeyword.RemoveKeyword(friendlyName); + } + } + } + + var moduleQualifiedResourceName = GetModuleQualifiedResourceName(module.Name, module.Version.ToString(), className, friendlyName); + DscClassCacheEntry existingCacheEntry = null; + if (ClassCache.TryGetValue(moduleQualifiedResourceName, out existingCacheEntry)) + { + if (errors is not null) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.DuplicateCimClassDefinition, className, module.Path, existingCacheEntry.ModulePath); + e.SetErrorId("DuplicateCimClassDefinition"); + errors.Add(e); + } + } + else + { + var classCacheEntry = new DscClassCacheEntry(runAsBehavior, false, c, module.Path); + ClassCache[moduleQualifiedResourceName] = classCacheEntry; + GuestConfigClassCache[moduleQualifiedResourceName] = classCacheEntry; + ByClassModuleCache[className] = new Tuple(module.Name, module.Version); + resourcesFound.Add(className); + CreateAndRegisterKeywordFromCimClass(module.Name, module.Version, c, functionsToDefine, runAsBehavior); + } + } + } + + /// + /// Returns an error record to use in the case of a malformed resource reference in the DependsOn list. + /// + /// The malformed resource. + /// The referencing resource instance. + /// Generated error record. + public static ErrorRecord GetBadlyFormedRequiredResourceIdErrorRecord(string badDependsOnReference, string definingResource) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.GetBadlyFormedRequiredResourceId, badDependsOnReference, definingResource); + e.SetErrorId("GetBadlyFormedRequiredResourceId"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of a malformed resource reference in the exclusive resources list. + /// + /// The malformed resource. + /// The referencing resource instance. + /// Generated error record. + public static ErrorRecord GetBadlyFormedExclusiveResourceIdErrorRecord(string badExclusiveResourcereference, string definingResource) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.GetBadlyFormedExclusiveResourceId, badExclusiveResourcereference, definingResource); + e.SetErrorId("GetBadlyFormedExclusiveResourceId"); + return e.ErrorRecord; + } + + /// + /// If a partial configuration is in 'Pull' Mode, it needs a configuration source. + /// + /// Resource id. + /// Generated error record. + public static ErrorRecord GetPullModeNeedConfigurationSource(string resourceId) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.GetPullModeNeedConfigurationSource, resourceId); + e.SetErrorId("GetPullModeNeedConfigurationSource"); + return e.ErrorRecord; + } + + /// + /// Refresh Mode can not be Disabled for the Partial Configurations. + /// + /// Resource id. + /// Generated error record. + public static ErrorRecord DisabledRefreshModeNotValidForPartialConfig(string resourceId) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.DisabledRefreshModeNotValidForPartialConfig, resourceId); + e.SetErrorId("DisabledRefreshModeNotValidForPartialConfig"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of a malformed resource reference in the DependsOn list. + /// + /// The duplicate resource identifier. + /// The node being defined. + /// The error record to use. + public static ErrorRecord DuplicateResourceIdInNodeStatementErrorRecord(string duplicateResourceId, string nodeName) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.DuplicateResourceIdInNodeStatement, duplicateResourceId, nodeName); + e.SetErrorId("DuplicateResourceIdInNodeStatement"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of a configuration name is invalid. + /// + /// Configuration name. + /// Generated error record. + public static ErrorRecord InvalidConfigurationNameErrorRecord(string configurationName) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.InvalidConfigurationName, configurationName); + e.SetErrorId("InvalidConfigurationName"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of the given value for a property is invalid. + /// + /// Property name. + /// Property value. + /// Keyword name. + /// Valid property values. + /// Generated error record. + public static ErrorRecord InvalidValueForPropertyErrorRecord(string propertyName, string value, string keywordName, string validValues) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.InvalidValueForProperty, value, propertyName, keywordName, validValues); + e.SetErrorId("InvalidValueForProperty"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in case the given property is not valid LocalConfigurationManager property. + /// + /// Property name. + /// Valid properties. + /// Generated error record. + public static ErrorRecord InvalidLocalConfigurationManagerPropertyErrorRecord(string propertyName, string validProperties) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.InvalidLocalConfigurationManagerProperty, propertyName, validProperties); + e.SetErrorId("InvalidLocalConfigurationManagerProperty"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of the given value for a property is not supported. + /// + /// Property name. + /// Property value. + /// Keyword name. + /// Valid property values. + /// Generated error record. + public static ErrorRecord UnsupportedValueForPropertyErrorRecord(string propertyName, string value, string keywordName, string validValues) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.UnsupportedValueForProperty, value, propertyName, keywordName, validValues); + e.SetErrorId("UnsupportedValueForProperty"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of no value is provided for a mandatory property. + /// + /// Keyword name. + /// Type name. + /// Property name. + /// Generated error record. + public static ErrorRecord MissingValueForMandatoryPropertyErrorRecord(string keywordName, string typeName, string propertyName) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.MissingValueForMandatoryProperty, keywordName, typeName, propertyName); + e.SetErrorId("MissingValueForMandatoryProperty"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use in the case of more than one values are provided for DebugMode property. + /// + /// Generated error record. + public static ErrorRecord DebugModeShouldHaveOneValue() + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.DebugModeShouldHaveOneValue); + e.SetErrorId("DebugModeShouldHaveOneValue"); + return e.ErrorRecord; + } + + /// + /// Return an error to indicate a value is out of range for a dynamic keyword property. + /// + /// Rroperty name. + /// Resource name. + /// Provided value. + /// Valid range lower bound. + /// Valid range upper bound. + /// Generated error record. + public static ErrorRecord ValueNotInRangeErrorRecord(string property, string name, int providedValue, int lower, int upper) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.ValueNotInRange, property, name, providedValue, lower, upper); + e.SetErrorId("ValueNotInRange"); + return e.ErrorRecord; + } + + /// + /// Returns an error record to use when composite resource and its resource instances both has PsDscRunAsCredentials value. + /// + /// ResourceId of resource. + /// Generated error record. + public static ErrorRecord PsDscRunAsCredentialMergeErrorForCompositeResources(string resourceId) + { + PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(ParserStrings.PsDscRunAsCredentialMergeErrorForCompositeResources, resourceId); + e.SetErrorId("PsDscRunAsCredentialMergeErrorForCompositeResources"); + return e.ErrorRecord; + } + + /// + /// Routine to format a usage string from keyword. The resulting string should look like: + /// User [string] #ResourceName + /// { + /// UserName = [string] + /// [ Description = [string] ] + /// [ Disabled = [bool] ] + /// [ Ensure = [string] { Absent | Present } ] + /// [ Force = [bool] ] + /// [ FullName = [string] ] + /// [ Password = [PSCredential] ] + /// [ PasswordChangeNotAllowed = [bool] ] + /// [ PasswordChangeRequired = [bool] ] + /// [ PasswordNeverExpires = [bool] ] + /// [ DependsOn = [string[]] ] + /// } + /// + /// Dynamic keyword. + /// Usage string. + public static string GetDSCResourceUsageString(DynamicKeyword keyword) + { + StringBuilder usageString; + switch (keyword.NameMode) + { + // Name must be present and simple non-empty bare word + case DynamicKeywordNameMode.SimpleNameRequired: + usageString = new StringBuilder(keyword.Keyword + " [string] # Resource Name"); + break; + + // Name must be present but can also be an expression + case DynamicKeywordNameMode.NameRequired: + usageString = new StringBuilder(keyword.Keyword + " [string[]] # Name List"); + break; + + // Name may be optionally present, but if it is present, it must be a non-empty bare word. + case DynamicKeywordNameMode.SimpleOptionalName: + usageString = new StringBuilder(keyword.Keyword + " [ [string] ] # Optional Name"); + break; + + // Name may be optionally present, expression or bare word + case DynamicKeywordNameMode.OptionalName: + usageString = new StringBuilder(keyword.Keyword + " [ [string[]] ] # Optional NameList"); + break; + + // Does not take a name + default: + usageString = new StringBuilder(keyword.Keyword); + break; + } + + usageString.Append("\n{\n"); + + bool listKeyProperties = true; + while (true) + { + foreach (var prop in keyword.Properties.OrderBy(ob => ob.Key)) + { + if (string.Equals(prop.Key, "ResourceId", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var propVal = prop.Value; + if ((listKeyProperties && propVal.IsKey) || (!listKeyProperties && !propVal.IsKey)) + { + usageString.Append(propVal.Mandatory ? " " : " [ "); + usageString.Append(prop.Key); + usageString.Append(" = "); + usageString.Append(FormatCimPropertyType(propVal, !propVal.Mandatory)); + } + } + + if (listKeyProperties) + { + listKeyProperties = false; + } + else + { + break; + } + } + + usageString.Append('}'); + + return usageString.ToString(); + } + + /// + /// Format the type name of a CIM property in a presentable way. + /// + /// Dynamic keyword property. + /// If this is optional property or not. + /// CIM property type string. + private static StringBuilder FormatCimPropertyType(DynamicKeywordProperty prop, bool isOptionalProperty) + { + string cimTypeName = prop.TypeConstraint; + StringBuilder formattedTypeString = new StringBuilder(); + + if (string.Equals(cimTypeName, "MSFT_Credential", StringComparison.OrdinalIgnoreCase)) + { + formattedTypeString.Append("[PSCredential]"); + } + else if (string.Equals(cimTypeName, "MSFT_KeyValuePair", StringComparison.OrdinalIgnoreCase) || string.Equals(cimTypeName, "MSFT_KeyValuePair[]", StringComparison.OrdinalIgnoreCase)) + { + formattedTypeString.Append("[Hashtable]"); + } + else + { + string convertedTypeString = System.Management.Automation.LanguagePrimitives.ConvertTypeNameToPSTypeName(cimTypeName); + if (!string.IsNullOrEmpty(convertedTypeString) && !string.Equals(convertedTypeString, "[]", StringComparison.OrdinalIgnoreCase)) + { + formattedTypeString.Append(convertedTypeString); + } + else + { + formattedTypeString.Append("[" + cimTypeName + "]"); + } + } + + // Do the property values map + if (prop.ValueMap is not null && prop.ValueMap.Count > 0) + { + formattedTypeString.Append(" { " + string.Join(" | ", prop.ValueMap.Keys.OrderBy(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('\n'); + + return formattedTypeString; + } + + /// + /// Gets the scriptblock that implements the CIM keyword functionality. + /// + private static ScriptBlock CimKeywordImplementationFunction + { + get + { + // The scriptblock cache will handle mutual exclusion + return s_cimKeywordImplementationFunction ??= ScriptBlock.Create(CimKeywordImplementationFunctionText); + } + } + + private static ScriptBlock s_cimKeywordImplementationFunction; + + private const string CimKeywordImplementationFunctionText = @" + param ( + [Parameter(Mandatory)] + $KeywordData, + [Parameter(Mandatory)] + $Name, + [Parameter(Mandatory)] + [Hashtable] + $Value, + [Parameter(Mandatory)] + $SourceMetadata + ) + +# walk the call stack to get at all of the enclosing configuration resource IDs + $stackedConfigs = @(Get-PSCallStack | + where { ($null -ne $_.InvocationInfo.MyCommand) -and ($_.InvocationInfo.MyCommand.CommandType -eq 'Configuration') }) +# keep all but the top-most + $stackedConfigs = $stackedConfigs[0..(@($stackedConfigs).Length - 2)] +# and build the complex resource ID suffix. + $complexResourceQualifier = ( $stackedConfigs | ForEach-Object { '[' + $_.Command + ']' + $_.InvocationInfo.BoundParameters['InstanceName'] } ) -join '::' + +# +# Utility function used to validate that the DependsOn arguments are well-formed. +# The function also adds them to the define nodes resource collection. +# in the case of resources generated inside a script resource, this routine +# will also fix up the DependsOn references to '[Type]Instance::[OuterType]::OuterInstance +# + function Test-DependsOn + { + +# make sure the references are well-formed + $updatedDependsOn = foreach ($DependsOnVar in $value['DependsOn']) { +# match [ResourceType]ResourceName. ResourceName should starts with [a-z_0-9] followed by [a-z_0-9\p{Zs}\.\\-]* + if ($DependsOnVar -notmatch '^\[[a-z]\w*\][a-z_0-9][a-z_0-9\p{Zs}\.\\-]*$') + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::GetBadlyFormedRequiredResourceIdErrorRecord($DependsOnVar, $resourceId)) + } + +# Fix up DependsOn for nested names + if ($MyTypeName -and $typeName -ne $MyTypeName -and $InstanceName) + { + ""$DependsOnVar::$complexResourceQualifier"" + } + else + { + $DependsOnVar + } + } + + $value['DependsOn']= $updatedDependsOn + + if($null -ne $DependsOn) + { +# +# Combine DependsOn with dependson from outer composite resource +# which is set as local variable $DependsOn at the composite resource context +# + $value['DependsOn']= @($value['DependsOn']) + $DependsOn + } + +# Save the resource id in a per-node dictionary to do cross validation at the end + Set-NodeResources $resourceId @( $value['DependsOn']) + +# Remove depends on because it need to be fixed up for composite resources +# We do it in ValidateNodeResource and Update-Depends on in configuration/Node function + $value.Remove('DependsOn') + } + +# A copy of the value object with correctly-cased property names + $canonicalizedValue = @{} + + $typeName = $keywordData.ResourceName # CIM type + $keywordName = $keywordData.Keyword # user-friendly alias that is used in scripts + $keyValues = '' + $debugPrefix = "" ${TypeName}:"" # set up a debug prefix string that makes it easier to track what's happening. + + Write-Debug ""${debugPrefix} RESOURCE PROCESSING STARTED [KeywordName='$keywordName'] Function='$($myinvocation.Invocationname)']"" + +# Check whether it's an old style metaconfig + $OldMetaConfig = $false + if ((-not $IsMetaConfig) -and ($keywordName -ieq 'LocalConfigurationManager')) { + $OldMetaConfig = $true + } + +# Check to see if it's a resource keyword. If so add the meta-properties to the canonical property collection. + $resourceId = $null +# todo: need to include configuration managers and partial configuration + if (($keywordData.Properties.Keys -contains 'DependsOn') -or (($KeywordData.ImplementingModule -ieq 'PSDesiredStateConfigurationEngine') -and ($KeywordData.NameMode -eq [System.Management.Automation.Language.DynamicKeywordNameMode]::NameRequired))) + { + + $resourceId = ""[$keywordName]$name"" + if ($MyTypeName -and $keywordName -ne $MyTypeName -and $InstanceName) + { + $resourceId += ""::$complexResourceQualifier"" + } + + Write-Debug ""${debugPrefix} ResourceID = $resourceId"" + +# copy the meta-properties + $canonicalizedValue['ResourceID'] = $resourceId + $canonicalizedValue['SourceInfo'] = $SourceMetadata + if(-not $IsMetaConfig) + { + $canonicalizedValue['ModuleName'] = $keywordData.ImplementingModule + $canonicalizedValue['ModuleVersion'] = $keywordData.ImplementingModuleVersion -as [string] + } + +# see if there is already a resource with this ID. + if (Test-NodeResources $resourceId) + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::DuplicateResourceIdInNodeStatementErrorRecord($resourceId, (Get-PSCurrentConfigurationNode))) + } + else + { +# If there are prerequisite resources, validate that the references are well-formed strings +# This routine also adds the resource to the global node resources table. + Test-DependsOn + +# Check if PsDscRunCredential is being specified as Arguments to Configuration + if($null -ne $PsDscRunAsCredential) + { +# Check if resource is also trying to set the value for RunAsCred +# In that case we will generate error during compilation, this is merge error + if($null -ne $value['PsDscRunAsCredential']) + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::PsDscRunAsCredentialMergeErrorForCompositeResources($resourceId)) + } +# Set the Value of RunAsCred to that of outer configuration + else + { + $value['PsDscRunAsCredential'] = $PsDscRunAsCredential + } + } + +# Save the resource id in a per-node dictionary to do cross validation at the end + if($keywordData.ImplementingModule -ieq ""PSDesiredStateConfigurationEngine"") + { +#$keywordName is PartialConfiguration + if($keywordName -eq 'PartialConfiguration') + { +# RefreshMode is 'Pull' and .ConfigurationSource is empty + if($value['RefreshMode'] -eq 'Pull' -and -not $value['ConfigurationSource']) + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::GetPullModeNeedConfigurationSource($resourceId)) + } + +# Verify that RefreshMode is not Disabled for Partial configuration + if($value['RefreshMode'] -eq 'Disabled') + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::DisabledRefreshModeNotValidForPartialConfig($resourceId)) + } + + if($null -ne $value['ConfigurationSource']) + { + Set-NodeManager $resourceId $value['ConfigurationSource'] + } + + if($null -ne $value['ResourceModuleSource']) + { + Set-NodeResourceSource $resourceId $value['ResourceModuleSource'] + } + } + + if($null -ne $value['ExclusiveResources']) + { +# make sure the references are well-formed + foreach ($ExclusiveResource in $value['ExclusiveResources']) { + if (($ExclusiveResource -notmatch '^[a-z][a-z_0-9]*\\[a-z][a-z_0-9]*$') -and ($ExclusiveResource -notmatch '^[a-z][a-z_0-9]*$') -and ($ExclusiveResource -notmatch '^[a-z][a-z_0-9]*\\\*$')) + { + Update-ConfigurationErrorCount + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::GetBadlyFormedExclusiveResourceIdErrorRecord($ExclusiveResource, $resourceId)) + } + } + +# Save the resource id in a per-node dictionary to do cross validation at the end +# Validate resource exist +# Also update the resource reference from module\friendlyname to module\name + $value['ExclusiveResources'] = @(Set-NodeExclusiveResources $resourceId @( $value['ExclusiveResources'] )) + } + } + } + } + else + { + Write-Debug ""${debugPrefix} TYPE IS NOT AS DSC RESOURCE"" + } + +# +# Copy the user-supplied values into a new collection with canonicalized property names +# + foreach ($key in $keywordData.Properties.Keys) + { + Write-Debug ""${debugPrefix} Processing property '$key' ["" + + if ($value.Contains($key)) + { + if ($OldMetaConfig -and (-not ($V1MetaConfigPropertyList -contains $key))) + { + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::InvalidLocalConfigurationManagerPropertyErrorRecord($key, ($V1MetaConfigPropertyList -join ', '))) + Update-ConfigurationErrorCount + } +# see if there is a list of allowed values for this property (similar to an enum) + $allowedValues = $keywordData.Properties[$key].Values +# If there is and user-provided value is not in that list, write an error. + if ($allowedValues) + { + if(($null -eq $value[$key]) -and ($allowedValues -notcontains $value[$key])) + { + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::InvalidValueForPropertyErrorRecord($key, ""$($value[$key])"", $keywordData.Keyword, ($allowedValues -join ', '))) + Update-ConfigurationErrorCount + } + else + { + $notAllowedValue=$null + foreach($v in $value[$key]) + { + if($allowedValues -notcontains $v) + { + $notAllowedValue +=$v.ToString() + ', ' + } + } + + if($notAllowedValue) + { + $notAllowedValue = $notAllowedValue.Substring(0, $notAllowedValue.Length -2) + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::UnsupportedValueForPropertyErrorRecord($key, $notAllowedValue, $keywordData.Keyword, ($allowedValues -join ', '))) + Update-ConfigurationErrorCount + } + } + } + +# see if a value range is defined for this property + $allowedRange = $keywordData.Properties[$key].Range + if($allowedRange) + { + $castedValue = $value[$key] -as [int] + if((($castedValue -is [int]) -and (($castedValue -lt $keywordData.Properties[$key].Range.Item1) -or ($castedValue -gt $keywordData.Properties[$key].Range.Item2))) -or ($null -eq $castedValue)) + { + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ValueNotInRangeErrorRecord($key, $keywordName, $value[$key], $keywordData.Properties[$key].Range.Item1, $keywordData.Properties[$key].Range.Item2)) + Update-ConfigurationErrorCount + } + } + + Write-Debug ""${debugPrefix} Canonicalized property '$key' = '$($value[$key])'"" + + if ($keywordData.Properties[$key].IsKey) + { + if($null -eq $value[$key]) + { + $keyValues += ""::__NULL__"" + } + else + { + $keyValues += ""::"" + $value[$key] + } + } + +# see if ValueMap is also defined for this property (actual values) + $allowedValueMap = $keywordData.Properties[$key].ValueMap +#if it is and the ValueMap contains the user-provided value as a key, use the actual value + if ($allowedValueMap -and $allowedValueMap.ContainsKey($value[$key])) + { + $canonicalizedValue[$key] = $allowedValueMap[$value[$key]] + } + else + { + $canonicalizedValue[$key] = $value[$key] + } + } + elseif ($keywordData.Properties[$key].Mandatory) + { +# If the property was mandatory but the user didn't provide a value, write and error. + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::MissingValueForMandatoryPropertyErrorRecord($keywordData.Keyword, $keywordData.Properties[$key].TypeConstraint, $Key)) + Update-ConfigurationErrorCount + } + + Write-Debug ""${debugPrefix} Processing completed '$key' ]"" + } + + if($keyValues) + { + $keyValues = $keyValues.Substring(2) # Remove the leading '::' + Add-NodeKeys $keyValues $keywordName + Test-ConflictingResources $keywordName $canonicalizedValue $keywordData + } + +# update OMI_ConfigurationDocument + if($IsMetaConfig) + { + if($keywordData.ResourceName -eq 'OMI_ConfigurationDocument') + { + if($(Get-PSMetaConfigurationProcessed)) + { + $PSMetaConfigDocumentInstVersionInfo = Get-PSMetaConfigDocumentInstVersionInfo + $canonicalizedValue['MinimumCompatibleVersion']=$PSMetaConfigDocumentInstVersionInfo['MinimumCompatibleVersion'] + } + else + { + Set-PSMetaConfigDocInsProcessedBeforeMeta + $canonicalizedValue['MinimumCompatibleVersion']='1.0.0' + } + } + + if(($keywordData.ResourceName -eq 'MSFT_WebDownloadManager') ` + -or ($keywordData.ResourceName -eq 'MSFT_FileDownloadManager') ` + -or ($keywordData.ResourceName -eq 'MSFT_WebResourceManager') ` + -or ($keywordData.ResourceName -eq 'MSFT_FileResourceManager') ` + -or ($keywordData.ResourceName -eq 'MSFT_WebReportManager') ` + -or ($keywordData.ResourceName -eq 'MSFT_SignatureValidation') ` + -or ($keywordData.ResourceName -eq 'MSFT_PartialConfiguration')) + { + Set-PSMetaConfigVersionInfoV2 + } + } + elseif($keywordData.ResourceName -eq 'OMI_ConfigurationDocument') + { + $canonicalizedValue['MinimumCompatibleVersion']='1.0.0' + $canonicalizedValue['CompatibleVersionAdditionalProperties']=@('Omi_BaseResource:ConfigurationName') + } + + if(($keywordData.ResourceName -eq 'MSFT_DSCMetaConfiguration') -or ($keywordData.ResourceName -eq 'MSFT_DSCMetaConfigurationV2')) + { + if($canonicalizedValue['DebugMode'] -and @($canonicalizedValue['DebugMode']).Length -gt 1) + { +# we only allow one value for debug mode now. + Write-Error -ErrorRecord ([Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::DebugModeShouldHaveOneValue()) + Update-ConfigurationErrorCount + } + } + +# Generate the MOF text for this resource instance. +# when generate mof text for OMI_ConfigurationDocument we handle below two cases: +# 1. we will add versioning related property based on meta configuration instance already process +# 2. we update the existing OMI_ConfigurationDocument instance if it already exists when process meta configuration instance + $aliasId = ConvertTo-MOFInstance $keywordName $canonicalizedValue + +# If a OMI_ConfigurationDocument is executed outside of a node statement, it becomes the default +# for all nodes that don't have an explicit OMI_ConfigurationDocument declaration + if ($keywordData.ResourceName -eq 'OMI_ConfigurationDocument' -and -not (Get-PSCurrentConfigurationNode)) + { + $data = Get-MoFInstanceText $aliasId + Write-Debug ""${debugPrefix} DEFINING DEFAULT CONFIGURATION DOCUMENT: $data"" + Set-PSDefaultConfigurationDocument $data + } + + Write-Debug ""${debugPrefix} MOF alias for this resource is '$aliasId'"" + +# always return the aliasId so the generated file will be well-formed if not valid + $aliasId + + Write-Debug ""${debugPrefix} RESOURCE PROCESSING COMPLETED. TOTAL ERROR COUNT: $(Get-ConfigurationErrorCount)"" + + "; + } +} 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 dbb8d3a2085..d9763164679 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -272,6 +272,10 @@ internal static IEnumerable GetFormatData() "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+ForegroundColor", ViewsOf_System_Management_Automation_PSStyleForegroundColor()); @@ -2039,6 +2043,8 @@ private static IEnumerable ViewsOf_System_Management_Autom .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.ErrorAccent)$($_.Formatting.ErrorAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.ErrorAccent") @@ -2046,6 +2052,9 @@ private static IEnumerable ViewsOf_System_Management_Autom .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(@"""$($_.Foreground.Black)$($_.Foreground.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Black") .AddItemScriptBlock(@"""$($_.Foreground.White)$($_.Foreground.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.White") .AddItemScriptBlock(@"""$($_.Foreground.DarkGray)$($_.Foreground.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.DarkGray") @@ -2097,6 +2106,18 @@ private static IEnumerable ViewsOf_System_Management_Autom .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") + .EndEntry() + .EndList()); + } + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleForegroundColor() { yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ForegroundColor", diff --git a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs index 48a791177ba..18b74cbcfe1 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs @@ -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; diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs index 3ad6f649c87..43cab48d003 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/FormatTable.cs @@ -32,7 +32,8 @@ public class FormatTableLoadException : RuntimeException /// /// 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(); diff --git a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs index b68288ff9ab..8c1c251f149 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/typeDataXmlLoader.cs @@ -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 } }; diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index f27a5b89da9..aa00bdf9e18 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -23,16 +23,28 @@ public enum OutputRendering } #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 class PSStyle + public sealed class PSStyle { /// /// Contains foreground colors. /// - public class ForegroundColor + public sealed class ForegroundColor { /// /// Gets the color black. @@ -147,7 +159,7 @@ public string FromRgb(int rgb) /// /// Contains background colors. /// - public class BackgroundColor + public sealed class BackgroundColor { /// /// Gets the color black. @@ -259,10 +271,31 @@ public string FromRgb(int rgb) } } + /// + /// Contains configuration for the progress bar visualization. + /// + public sealed class ProgressConfiguration + { + /// + /// Gets or sets the style for progress bar. + /// + public string Style { get; set; } = "\x1b[33;1m"; + + /// + /// Gets or sets the max width of the progress bar. + /// + public int MaxWidth { get; set; } = 120; + + /// + /// Gets or sets the view for progress bar. + /// + public ProgressView View { get; set; } = ProgressView.Minimal; + } + /// /// Contains formatting styles for steams and objects. /// - public class FormattingData + public sealed class FormattingData { /// /// Gets or sets the accent style for formatting. @@ -308,12 +341,12 @@ public class FormattingData /// /// Gets value to turn off blink. /// - public string BlinkOff { get; } = "\x1b[5m"; + public string BlinkOff { get; } = "\x1b[25m"; /// /// Gets value to turn on blink. /// - public string Blink { get; } = "\x1b[25m"; + public string Blink { get; } = "\x1b[5m"; /// /// Gets value to turn off bold. @@ -365,11 +398,37 @@ public class FormattingData /// 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. /// @@ -385,6 +444,7 @@ public class FormattingData private PSStyle() { Formatting = new FormattingData(); + Progress = new ProgressConfiguration(); Foreground = new ForegroundColor(); Background = new BackgroundColor(); } diff --git a/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs b/src/System.Management.Automation/FormatAndOutput/common/Utilities/MshObjectUtil.cs index 902f6f3f9d6..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) @@ -290,10 +296,12 @@ internal static string SmartToString(PSObject so, PSPropertyExpressionFactory ex // 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); diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 562b98361ac..dd1d6d14dde 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -16,16 +16,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs b/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs index 3197361faea..a663160645c 100644 --- a/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs +++ b/src/System.Management.Automation/cimSupport/cmdletization/ScriptWriter.cs @@ -832,9 +832,9 @@ private static string EscapeModuleNameForHelpComment(string name) 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); } diff --git a/src/System.Management.Automation/engine/ApplicationInfo.cs b/src/System.Management.Automation/engine/ApplicationInfo.cs index ffaae6fb800..5fe76424f5a 100644 --- a/src/System.Management.Automation/engine/ApplicationInfo.cs +++ b/src/System.Management.Automation/engine/ApplicationInfo.cs @@ -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/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index 19a7aa881e7..8ab2530b030 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 { diff --git a/src/System.Management.Automation/engine/COM/ComUtil.cs b/src/System.Management.Automation/engine/COM/ComUtil.cs index bc7609b7336..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); diff --git a/src/System.Management.Automation/engine/CommandBase.cs b/src/System.Management.Automation/engine/CommandBase.cs index 3f477895bb5..da2e97e516b 100644 --- a/src/System.Management.Automation/engine/CommandBase.cs +++ b/src/System.Management.Automation/engine/CommandBase.cs @@ -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 { diff --git a/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs b/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs index 4d89d87e51c..f31065080c6 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs @@ -1301,7 +1301,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 95b26ff6907..f8961956a31 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs @@ -526,6 +526,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 { // @@ -820,6 +826,7 @@ internal List GetResultHelper(CompletionContext completionCont case TokenKind.Equals: case TokenKind.Comma: case TokenKind.AtParen: + case TokenKind.LParen: { if (lastAst is AssignmentStatementAst assignmentAst) { @@ -829,25 +836,18 @@ internal List GetResultHelper(CompletionContext completionCont break; } } + + 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; } @@ -1721,7 +1721,10 @@ private static List GetResultForIdentifierInConfiguration( foreach (var keyword in matchedResults) { - string usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword); + string usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.NewApiIsUsed + ? Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.GetDSCResourceUsageString(keyword) + : Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword); + if (results == null) { results = new List(); diff --git a/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs b/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs index c86fc34cfaf..0d195280239 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/PseudoParameterBinder.cs @@ -728,7 +728,10 @@ internal ParameterBindingResult() /// public object ConstantValue { - get { return _constantValue; } + get + { + return _constantValue; + } internal set { @@ -745,7 +748,10 @@ internal set /// public CommandElementAst Value { - get { return _value; } + get + { + return _value; + } internal set { diff --git a/src/System.Management.Automation/engine/CommandDiscovery.cs b/src/System.Management.Automation/engine/CommandDiscovery.cs index 2b328767f4c..ee6e5943800 100644 --- a/src/System.Management.Automation/engine/CommandDiscovery.cs +++ b/src/System.Management.Automation/engine/CommandDiscovery.cs @@ -65,7 +65,10 @@ internal CommandLookupEventArgs(string commandName, CommandOrigin commandOrigin, /// public ScriptBlock CommandScriptBlock { - get { return _scriptBlock; } + get + { + return _scriptBlock; + } set { @@ -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", diff --git a/src/System.Management.Automation/engine/CommandInfo.cs b/src/System.Management.Automation/engine/CommandInfo.cs index 56e17ef0f5f..7538d9fb19f 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 { @@ -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 027373ec676..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; diff --git a/src/System.Management.Automation/engine/CommandProcessorBase.cs b/src/System.Management.Automation/engine/CommandProcessorBase.cs index 6ab07114652..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 { diff --git a/src/System.Management.Automation/engine/CommandSearcher.cs b/src/System.Management.Automation/engine/CommandSearcher.cs index b349255bab8..9745d2aa9ad 100644 --- a/src/System.Management.Automation/engine/CommandSearcher.cs +++ b/src/System.Management.Automation/engine/CommandSearcher.cs @@ -1087,7 +1087,7 @@ private static bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInf 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 static bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInf // 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 static bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInf /// 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/ErrorPackage.cs b/src/System.Management.Automation/engine/ErrorPackage.cs index 6d7a6c8326a..7d6a1f2759f 100644 --- a/src/System.Management.Automation/engine/ErrorPackage.cs +++ b/src/System.Management.Automation/engine/ErrorPackage.cs @@ -769,7 +769,10 @@ public string Message /// public string RecommendedAction { - get { return ErrorRecord.NotNull(_recommendedAction); } + get + { + return ErrorRecord.NotNull(_recommendedAction); + } set { @@ -1761,6 +1764,7 @@ public ErrorRecord(Exception exception, string errorId, ErrorCategory errorCateg /// /// is no longer available. /// +#nullable enable public interface IContainsErrorRecord { /// @@ -1789,6 +1793,7 @@ public interface IContainsErrorRecord /// ErrorRecord ErrorRecord { get; } } +#nullable restore /// /// Objects implementing this interface can be used by diff --git a/src/System.Management.Automation/engine/EventManager.cs b/src/System.Management.Automation/engine/EventManager.cs index 4afde8a9913..fd30298669e 100644 --- a/src/System.Management.Automation/engine/EventManager.cs +++ b/src/System.Management.Automation/engine/EventManager.cs @@ -1895,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) @@ -1924,9 +1932,17 @@ 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; } @@ -2456,8 +2472,12 @@ public class PSEventJob : Job /// The name of the job /// /// - public PSEventJob(PSEventManager eventManager, PSEventSubscriber subscriber, ScriptBlock action, string name) : - base(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)); diff --git a/src/System.Management.Automation/engine/ExecutionContext.cs b/src/System.Management.Automation/engine/ExecutionContext.cs index 9c484a7c56f..3857de9ba38 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; diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs b/src/System.Management.Automation/engine/ExperimentalFeature/EnableDisableExperimentalFeatureCommand.cs index c15d8628cb9..7a76a18ddb9 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) { diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs index f1be0c5acc8..5eeaf814e10 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 PSAnsiProgressFeatureName = "PSAnsiProgress"; #endregion @@ -123,12 +124,18 @@ static ExperimentalFeature() new ExperimentalFeature( name: "PSNotApplyErrorActionToStderr", description: "Don't have $ErrorActionPreference affect stderr output"), + new ExperimentalFeature( + name: "PS7DscSupport", + description: "Support the cross-platform class-based DSC"), new ExperimentalFeature( name: "PSSubsystemPluginModel", description: "A plugin model for registering and un-registering PowerShell subsystems"), new ExperimentalFeature( name: "PSAnsiRendering", description: "Enable $PSStyle variable to control ANSI rendering of strings"), + new ExperimentalFeature( + name: PSAnsiProgressFeatureName, + description: "Enable lightweight progress bar that leverages ANSI codes for rendering"), }; EngineExperimentalFeatures = new ReadOnlyCollection(engineFeatures); diff --git a/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs b/src/System.Management.Automation/engine/ExtendedTypeSystemException.cs index 3c6e23369bc..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) { } diff --git a/src/System.Management.Automation/engine/ExternalScriptInfo.cs b/src/System.Management.Automation/engine/ExternalScriptInfo.cs index b97da3b9970..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(); + } } /// diff --git a/src/System.Management.Automation/engine/GetCommandCommand.cs b/src/System.Management.Automation/engine/GetCommandCommand.cs index 17efeb4ac73..9007bed247c 100644 --- a/src/System.Management.Automation/engine/GetCommandCommand.cs +++ b/src/System.Management.Automation/engine/GetCommandCommand.cs @@ -280,7 +280,10 @@ public SwitchParameter ListImported [ValidateNotNullOrEmpty] public string[] ParameterName { - get { return _parameterNames; } + get + { + return _parameterNames; + } set { @@ -1489,22 +1492,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; + } } } diff --git a/src/System.Management.Automation/engine/InformationRecord.cs b/src/System.Management.Automation/engine/InformationRecord.cs index ad4aeeff5a9..310c34a8809 100644 --- a/src/System.Management.Automation/engine/InformationRecord.cs +++ b/src/System.Management.Automation/engine/InformationRecord.cs @@ -109,7 +109,10 @@ public string User return _user; } - set { _user = value; } + set + { + _user = value; + } } private string _user; @@ -143,7 +146,10 @@ public uint 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 2495a4ac0fe..257cb79ce7b 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() { diff --git a/src/System.Management.Automation/engine/InternalCommands.cs b/src/System.Management.Automation/engine/InternalCommands.cs index 0928cc8a0d4..b7b1d87cc82 100644 --- a/src/System.Management.Automation/engine/InternalCommands.cs +++ b/src/System.Management.Automation/engine/InternalCommands.cs @@ -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 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 @@ -2655,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 1ae22542c63..6020b6e53a0 100644 --- a/src/System.Management.Automation/engine/InvocationInfo.cs +++ b/src/System.Management.Automation/engine/InvocationInfo.cs @@ -204,7 +204,10 @@ public Dictionary BoundParameters return _boundParameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase); } - internal set { _boundParameters = value; } + internal set + { + _boundParameters = value; + } } /// @@ -381,7 +384,10 @@ internal IScriptExtent ScriptPosition } } - set { _scriptPosition = value; } + set + { + _scriptPosition = value; + } } /// diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index c397385e557..83361fe9662 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -1502,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; @@ -1595,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[]" }, @@ -2133,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, diff --git a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs index 8b055d8fb0f..084c8c4674e 100644 --- a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs +++ b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs @@ -27,7 +27,7 @@ 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 readonly AnalysisCacheData s_cacheData = AnalysisCacheData.Get(); @@ -371,7 +371,7 @@ 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, diff --git a/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs b/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs index 20eaf0baabe..8520e39258b 100644 --- a/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ExportModuleMemberCommand.cs @@ -28,7 +28,10 @@ public sealed class ExportModuleMemberCommand : PSCmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { - get { return _functionList; } + get + { + return _functionList; + } set { @@ -57,7 +60,10 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { - get { return _cmdletList; } + get + { + return _cmdletList; + } set { @@ -86,7 +92,10 @@ public string[] Cmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Variable { - get { return _variableExportList; } + get + { + return _variableExportList; + } set { @@ -115,7 +124,10 @@ public string[] Variable [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Alias { - get { return _aliasExportList; } + get + { + return _aliasExportList; + } set { diff --git a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs index 35e0b61ab20..365d6e7642c 100644 --- a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs @@ -117,7 +117,10 @@ public string Prefix [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { - get { return _functionImportList; } + get + { + return _functionImportList; + } set { @@ -144,7 +147,10 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { - get { return _cmdletImportList; } + get + { + return _cmdletImportList; + } set { @@ -172,7 +178,10 @@ public string[] Cmdlet [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Variable { - get { return _variableExportList; } + get + { + return _variableExportList; + } set { @@ -199,7 +208,10 @@ public string[] Variable [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Alias { - get { return _aliasExportList; } + get + { + return _aliasExportList; + } set { @@ -375,7 +387,10 @@ public SwitchParameter DisableNameChecking [ValidateSet("Local", "Global")] public string Scope { - get { return _scope; } + get + { + return _scope; + } set { diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index 94ce2664703..9d5af609710 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -1014,7 +1014,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); diff --git a/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs b/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs index b661df41de1..d47681166a0 100644 --- a/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/NewModuleCommand.cs @@ -42,7 +42,10 @@ public string Name [ValidateNotNull] public ScriptBlock ScriptBlock { - get { return _scriptBlock; } + get + { + return _scriptBlock; + } set { @@ -60,7 +63,10 @@ public ScriptBlock ScriptBlock [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Function { - get { return _functionImportList; } + get + { + return _functionImportList; + } set { @@ -88,7 +94,10 @@ public string[] Function [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")] public string[] Cmdlet { - get { return _cmdletImportList; } + get + { + return _cmdletImportList; + } set { diff --git a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs index bf2e76501cc..30036e035e2 100644 --- a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs +++ b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs @@ -662,8 +662,7 @@ private static string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamW continue; } - ModuleSpecification moduleSpecification = (ModuleSpecification) - LanguagePrimitives.ConvertTo( + ModuleSpecification moduleSpecification = (ModuleSpecification)LanguagePrimitives.ConvertTo( spec, typeof(ModuleSpecification), CultureInfo.InvariantCulture); diff --git a/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs b/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs index f2ab485aef0..f8625697800 100644 --- a/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs +++ b/src/System.Management.Automation/engine/Modules/PSModuleInfo.cs @@ -470,7 +470,10 @@ public string Author /// public ModuleAccessMode AccessMode { - get { return _accessMode; } + get + { + return _accessMode; + } set { diff --git a/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs b/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs index 9ece4af620f..c52a752c640 100644 --- a/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs +++ b/src/System.Management.Automation/engine/Modules/RemoteDiscoveryHelper.cs @@ -25,7 +25,7 @@ namespace System.Management.Automation { - internal class RemoteDiscoveryHelper + internal static class RemoteDiscoveryHelper { #region PSRP @@ -815,9 +815,10 @@ private static IEnumerable GetCimModules( ErrorRecord errorRecord = GetErrorRecordForRemoteDiscoveryProvider(exception); if (!cmdlet.MyInvocation.ExpectingInput) { - if ((errorRecord.FullyQualifiedErrorId.IndexOf(DiscoveryProviderNotFoundErrorId, StringComparison.OrdinalIgnoreCase) != (-1)) || - (cancellationToken.IsCancellationRequested || (exception is OperationCanceledException)) || - (!cimSession.TestConnection())) + if (errorRecord.FullyQualifiedErrorId.Contains(DiscoveryProviderNotFoundErrorId, StringComparison.OrdinalIgnoreCase) + || cancellationToken.IsCancellationRequested + || exception is OperationCanceledException + || !cimSession.TestConnection()) { cmdlet.ThrowTerminatingError(errorRecord); } diff --git a/src/System.Management.Automation/engine/MshCommandRuntime.cs b/src/System.Management.Automation/engine/MshCommandRuntime.cs index a1cd276fa89..e43e49631aa 100644 --- a/src/System.Management.Automation/engine/MshCommandRuntime.cs +++ b/src/System.Management.Automation/engine/MshCommandRuntime.cs @@ -3136,7 +3136,10 @@ internal ActionPreference WarningPreference /// internal bool Verbose { - get { return _verboseFlag; } + get + { + return _verboseFlag; + } set { @@ -3209,7 +3212,10 @@ internal SwitchParameter UseTransaction /// internal bool Debug { - get { return _debugFlag; } + get + { + return _debugFlag; + } set { diff --git a/src/System.Management.Automation/engine/MshMemberInfo.cs b/src/System.Management.Automation/engine/MshMemberInfo.cs index 9bbec9c4312..73ee243f6e8 100644 --- a/src/System.Management.Automation/engine/MshMemberInfo.cs +++ b/src/System.Management.Automation/engine/MshMemberInfo.cs @@ -3670,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) { @@ -4974,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) @@ -5028,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")) { @@ -5070,7 +5070,7 @@ public bool MoveNext() { _currentIndex++; - S member = null; + T member = null; while (_currentIndex < _allMembers.Count) { member = _allMembers[_currentIndex]; @@ -5096,7 +5096,7 @@ public bool MoveNext() /// Current PSMemberInfo in the enumeration. /// /// For invalid arguments. - S IEnumerator.Current + T IEnumerator.Current { get { @@ -5109,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 2253c7c913e..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); } } diff --git a/src/System.Management.Automation/engine/PSVersionInfo.cs b/src/System.Management.Automation/engine/PSVersionInfo.cs index 289f105987e..5830cdc7f02 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; @@ -77,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; + string productVersion = currentAssembly.GetCustomAttribute().InformationalVersion; // Get 'GitCommitId' and 'PSVersion' from the 'productVersion' assembly attribute. // diff --git a/src/System.Management.Automation/engine/Pipe.cs b/src/System.Management.Automation/engine/Pipe.cs index c930a43ef99..8ee000a4faf 100644 --- a/src/System.Management.Automation/engine/Pipe.cs +++ b/src/System.Management.Automation/engine/Pipe.cs @@ -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 { diff --git a/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs b/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs index 2a686578e48..b8a89b9b31f 100644 --- a/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateDriveAPIs.cs @@ -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 adf4c396473..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 { diff --git a/src/System.Management.Automation/engine/SessionStateScope.cs b/src/System.Management.Automation/engine/SessionStateScope.cs index 6f0c4fbbec3..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 { @@ -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; } diff --git a/src/System.Management.Automation/engine/ShellVariable.cs b/src/System.Management.Automation/engine/ShellVariable.cs index f8a32fca917..424be295346 100644 --- a/src/System.Management.Automation/engine/ShellVariable.cs +++ b/src/System.Management.Automation/engine/ShellVariable.cs @@ -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 { diff --git a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs index 30deb1b3093..edc8fb272a2 100644 --- a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs +++ b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/CommandPrediction.cs @@ -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?> PredictInput(string client, Ast ast, Token[] astTokens) { - return PredictInput(ast, astTokens, millisecondsTimeout: 20); + return PredictInput(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?> PredictInput(string client, Ast ast, Token[] astTokens, int millisecondsTimeout) { Requires.Condition(millisecondsTimeout > 0, nameof(millisecondsTimeout)); @@ -85,8 +94,8 @@ public static class CommandPrediction state => { var predictor = (ICommandPredictor)state!; - List? texts = predictor.GetSuggestion(context, cancellationSource.Token); - return texts?.Count > 0 ? new PredictionResult(predictor.Id, predictor.Name, texts) : null; + SuggestionPackage pkg = predictor.GetSuggestion(client, context, cancellationSource.Token); + return pkg.SuggestionEntries?.Count > 0 ? new PredictionResult(predictor.Id, predictor.Name, pkg.Session, pkg.SuggestionEntries) : null; }, predictor, cancellationSource.Token, @@ -99,7 +108,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) @@ -107,19 +116,20 @@ await Task.WhenAny( PredictionResult? result = task.Result; if (result != null) { - results.Add(result); + resultList.Add(result); } } } - return results; + return resultList; } /// /// 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(string client, IReadOnlyList history) { Requires.NotNull(history, nameof(history)); @@ -134,7 +144,37 @@ public static void OnCommandLineAccepted(IReadOnlyList history) if (predictor.SupportEarlyProcessing) { ThreadPool.QueueUserWorkItem( - state => state.StartEarlyProcessing(history), + state => state.StartEarlyProcessing(client, history), + predictor, + preferLocal: false); + } + } + } + + /// + /// 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(string client, Guid predictorId, uint session, int countOrIndex) + { + var predictors = SubsystemManager.GetSubsystems(); + if (predictors.Count == 0) + { + return; + } + + foreach (ICommandPredictor predictor in predictors) + { + if (predictor.AcceptFeedback && predictor.Id == predictorId) + { + ThreadPool.QueueUserWorkItem( + state => state.OnSuggestionDisplayed(client, session, countOrIndex), predictor, preferLocal: false); } @@ -142,11 +182,13 @@ public static void OnCommandLineAccepted(IReadOnlyList history) } /// - /// 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(string client, Guid predictorId, uint session, string suggestionText) { Requires.NotNullOrEmpty(suggestionText, nameof(suggestionText)); @@ -161,7 +203,7 @@ public static void OnSuggestionAccepted(Guid predictorId, string suggestionText) if (predictor.AcceptFeedback && predictor.Id == predictorId) { ThreadPool.QueueUserWorkItem( - state => state.OnSuggestionAccepted(suggestionText), + state => state.OnSuggestionAccepted(client, session, suggestionText), predictor, preferLocal: false); } diff --git a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs index 0edd768cf89..d55d37a90df 100644 --- a/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs +++ b/src/System.Management.Automation/engine/Subsystem/CommandPrediction/ICommandPredictor.cs @@ -40,22 +40,37 @@ public interface ICommandPredictor : ISubsystem /// 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 StartEarlyProcessing(string clientId, IReadOnlyList history); /// - /// The suggestion given by the predictor was accepted. + /// Get the predictive suggestions. It indicates the start of a suggestion rendering session. /// - /// The accepted suggestion text. - void OnSuggestionAccepted(string acceptedSuggestion); + /// 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(string clientId, PredictionContext context, CancellationToken cancellationToken); /// - /// Get the predictive suggestions. + /// One or more suggestions provided by the predictor were 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); + /// 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(string clientId, 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(string clientId, uint session, string acceptedSuggestion); } /// @@ -160,4 +175,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/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 6a4a863d23c..fa1ef13572e 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -2312,6 +2312,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/WinRT/IInspectable.cs b/src/System.Management.Automation/engine/WinRT/IInspectable.cs index f6f4d9ee7d9..abc589b4875 100644 --- a/src/System.Management.Automation/engine/WinRT/IInspectable.cs +++ b/src/System.Management.Automation/engine/WinRT/IInspectable.cs @@ -26,7 +26,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/hostifaces/InformationalRecord.cs b/src/System.Management.Automation/engine/hostifaces/InformationalRecord.cs index 510cb8f9544..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; + } } /// diff --git a/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs b/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs index b30d64d04db..57f3f675ffc 100644 --- a/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs +++ b/src/System.Management.Automation/engine/hostifaces/InternalHostUserInterface.cs @@ -993,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) diff --git a/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs b/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs index 1e3da98da26..e6d40c72419 100644 --- a/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs +++ b/src/System.Management.Automation/engine/hostifaces/MshHostUserInterface.cs @@ -1202,6 +1202,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 { /// @@ -1226,9 +1227,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 diff --git a/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs b/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs index 1743e6d4678..d51c96a33e0 100644 --- a/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs +++ b/src/System.Management.Automation/engine/hostifaces/PSDataCollection.cs @@ -390,7 +390,10 @@ public bool IsOpen /// public int DataAddedCount { - get { return _dataAddedFrequency; } + get + { + return _dataAddedFrequency; + } set { @@ -1809,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); } @@ -1822,14 +1825,14 @@ 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 readonly PSDataCollection _collToEnumerate; + private readonly PSDataCollection _collToEnumerate; private readonly bool _neverBlock; #endregion @@ -1845,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"); @@ -1854,7 +1857,7 @@ internal PSDataCollectionEnumerator(PSDataCollection collection, bool neverBl _collToEnumerate = collection; _index = 0; - _currentElement = default(W); + _currentElement = default(T); _collToEnumerate.IsEnumerated = true; _neverBlock = neverBlock; } @@ -1872,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 { @@ -1933,7 +1936,7 @@ public bool MoveNext(bool block) _currentElement = _collToEnumerate[_index]; if (_collToEnumerate.ReleaseOnEnumeration) { - _collToEnumerate[_index] = default(W); + _collToEnumerate[_index] = default(T); } _index++; @@ -1975,7 +1978,7 @@ public bool MoveNext(bool block) /// public void Reset() { - _currentElement = default(W); + _currentElement = default(T); _index = 0; } @@ -2028,7 +2031,10 @@ internal PSInformationalBuffers(Guid psInstanceId) /// internal PSDataCollection Progress { - get { return progress; } + get + { + return progress; + } set { @@ -2044,7 +2050,10 @@ internal PSDataCollection Progress /// internal PSDataCollection Verbose { - get { return verbose; } + get + { + return verbose; + } set { @@ -2060,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/RunspacePoolInternal.cs b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs index 6a2adf3cf69..aac3acfbdf8 100644 --- a/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs +++ b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs @@ -276,7 +276,10 @@ public virtual RunspaceConnectionInfo ConnectionInfo /// public TimeSpan CleanupInterval { - get { return _cleanupInterval; } + get + { + return _cleanupInterval; + } set { diff --git a/src/System.Management.Automation/engine/interpreter/InstructionList.cs b/src/System.Management.Automation/engine/interpreter/InstructionList.cs index 972c3f8635c..3c810d186e0 100644 --- a/src/System.Management.Automation/engine/interpreter/InstructionList.cs +++ b/src/System.Management.Automation/engine/interpreter/InstructionList.cs @@ -1086,9 +1086,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/LocalVariables.cs b/src/System.Management.Automation/engine/interpreter/LocalVariables.cs index aaee75d0234..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 { diff --git a/src/System.Management.Automation/engine/interpreter/Utilities.cs b/src/System.Management.Automation/engine/interpreter/Utilities.cs index 3d4307f1d3a..be7bb1935c7 100644 --- a/src/System.Management.Automation/engine/interpreter/Utilities.cs +++ b/src/System.Management.Automation/engine/interpreter/Utilities.cs @@ -224,7 +224,7 @@ internal static Type MakeDelegate(Type[] types) } } - internal class ScriptingRuntimeHelpers + internal static class ScriptingRuntimeHelpers { internal static object Int32ToObject(int i) { @@ -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/parser/Compiler.cs b/src/System.Management.Automation/engine/parser/Compiler.cs index 5d632d55a38..794b2834331 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; diff --git a/src/System.Management.Automation/engine/parser/PSType.cs b/src/System.Management.Automation/engine/parser/PSType.cs index 7ffc308369f..7a60d06a6be 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,"; diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index cac1019ea67..5b8ca433454 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -12,6 +12,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Dsc = Microsoft.PowerShell.DesiredStateConfiguration.Internal; namespace System.Management.Automation.Language { @@ -2932,6 +2933,7 @@ private StatementAst ConfigurationStatementRule(IEnumerable custom // Runspaces.Runspace localRunspace = null; bool topLevel = false; + bool useCrossPlatformSchema = false; try { // At this point, we'll need a runspace to use to hold the metadata for the parse. If there is no @@ -2967,7 +2969,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. @@ -2995,7 +2996,43 @@ private StatementAst ConfigurationStatementRule(IEnumerable custom { // Load the default CIM keywords Collection CIMKeywordErrors = new Collection(); - Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + if (ExperimentalFeature.IsEnabled(Dsc.CrossPlatform.DscClassCache.DscExperimentalFeatureName)) + { + // In addition to checking if experimental feature is enabled + // also check if PSDesiredStateConfiguration is already loaded + // if pre-v3 is already loaded then use old mof-based APIs + // otherwise use json-based APIs + + p.AddCommand(new CmdletInfo("Get-Module", typeof(Microsoft.PowerShell.Commands.GetModuleCommand))); + p.AddParameter("Name", "PSDesiredStateConfiguration"); + + bool prev3IsLoaded = false; + foreach (PSModuleInfo moduleInfo in p.Invoke()) + { + if (moduleInfo.Version.Major < 3) + { + prev3IsLoaded = true; + break; + } + } + + p.Commands.Clear(); + + useCrossPlatformSchema = !prev3IsLoaded; + + if (useCrossPlatformSchema) + { + Dsc.CrossPlatform.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + } + else + { + Dsc.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + } + } + else + { + Dsc.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors); + } // Report any errors encountered while loading CIM dynamic keywords. if (CIMKeywordErrors.Count > 0) @@ -3237,7 +3274,15 @@ 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(); + if (useCrossPlatformSchema) + { + Dsc.CrossPlatform.DscClassCache.ClearCache(); + } + else + { + Dsc.DscClassCache.ClearCache(); + } + System.Management.Automation.Language.DynamicKeyword.Reset(); } diff --git a/src/System.Management.Automation/engine/parser/Position.cs b/src/System.Management.Automation/engine/parser/Position.cs index 5e967e432b6..54f4c3eccbe 100644 --- a/src/System.Management.Automation/engine/parser/Position.cs +++ b/src/System.Management.Automation/engine/parser/Position.cs @@ -646,8 +646,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/TypeResolver.cs b/src/System.Management.Automation/engine/parser/TypeResolver.cs index 85325b61305..8843ff5cd31 100644 --- a/src/System.Management.Automation/engine/parser/TypeResolver.cs +++ b/src/System.Management.Automation/engine/parser/TypeResolver.cs @@ -671,7 +671,7 @@ public override int GetHashCode() } } - internal class TypeCache + internal static class TypeCache { private class KeyComparer : IEqualityComparer> { diff --git a/src/System.Management.Automation/engine/parser/ast.cs b/src/System.Management.Automation/engine/parser/ast.cs index 156e0365b4a..56693513b75 100644 --- a/src/System.Management.Automation/engine/parser/ast.cs +++ b/src/System.Management.Automation/engine/parser/ast.cs @@ -8184,10 +8184,12 @@ public interface ITypeName IScriptExtent Extent { get; } } +#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. diff --git a/src/System.Management.Automation/engine/pipeline.cs b/src/System.Management.Automation/engine/pipeline.cs index fb753652c93..14837fd1c5c 100644 --- a/src/System.Management.Automation/engine/pipeline.cs +++ b/src/System.Management.Automation/engine/pipeline.cs @@ -1467,7 +1467,10 @@ internal void ForgetFailure() /// internal PipelineReader ExternalInput { - get { return _externalInputPipe; } + get + { + return _externalInputPipe; + } set { @@ -1493,7 +1496,10 @@ internal PipelineReader ExternalInput /// internal PipelineWriter ExternalSuccessOutput { - get { return _externalSuccessOutput; } + get + { + return _externalSuccessOutput; + } set { @@ -1520,7 +1526,10 @@ internal PipelineWriter ExternalSuccessOutput /// internal PipelineWriter ExternalErrorOutput { - get { return _externalErrorOutput; } + get + { + return _externalErrorOutput; + } set { @@ -1567,7 +1576,10 @@ internal LocalPipeline LocalPipeline /// internal SessionStateScope ExecutionScope { - get { return _executionScope; } + get + { + return _executionScope; + } set { diff --git a/src/System.Management.Automation/engine/remoting/client/Job.cs b/src/System.Management.Automation/engine/remoting/client/Job.cs index 8e876902c26..657b72bef7a 100644 --- a/src/System.Management.Automation/engine/remoting/client/Job.cs +++ b/src/System.Management.Automation/engine/remoting/client/Job.cs @@ -670,7 +670,10 @@ public IList ChildJobs /// public string PSJobTypeName { - get { return _jobTypeName; } + get + { + return _jobTypeName; + } protected internal set { @@ -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) { } /// @@ -2288,7 +2289,10 @@ public override string StatusMessage /// internal bool HideComputerName { - get { return _hideComputerName; } + get + { + return _hideComputerName; + } set { @@ -2936,7 +2940,10 @@ public override string Location /// internal bool HideComputerName { - get { return _hideComputerName; } + get + { + return _hideComputerName; + } set { diff --git a/src/System.Management.Automation/engine/remoting/client/Job2.cs b/src/System.Management.Automation/engine/remoting/client/Job2.cs index 37776ef2a4b..ae5976ec9f8 100644 --- a/src/System.Management.Automation/engine/remoting/client/Job2.cs +++ b/src/System.Management.Automation/engine/remoting/client/Job2.cs @@ -533,7 +533,10 @@ public sealed class ContainerParentJob : Job2 internal PSEventManager EventManager { - get { return _eventManager; } + get + { + return _eventManager; + } set { diff --git a/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs b/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs index 7c0771d94b3..0de48ff6dfc 100644 --- a/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs +++ b/src/System.Management.Automation/engine/remoting/client/RemotingErrorRecord.cs @@ -32,7 +32,8 @@ public OriginInfo OriginInfo /// /// 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; } diff --git a/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs b/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs index ede18c5a8b7..c791d728809 100644 --- a/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs +++ b/src/System.Management.Automation/engine/remoting/client/remotepipeline.cs @@ -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; diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index c9202190221..aa90fca60a4 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -2373,7 +2373,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( diff --git a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs index f306246e289..56bd72e90d8 100644 --- a/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs +++ b/src/System.Management.Automation/engine/remoting/commands/NewPSSessionConfigurationFile.cs @@ -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 diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs index bbb2056189c..9fafd34eec4 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs @@ -669,7 +669,10 @@ public virtual PSSessionOption SessionOption return _sessionOption; } - set { _sessionOption = value; } + set + { + _sessionOption = value; + } } private PSSessionOption _sessionOption; @@ -707,7 +710,10 @@ public virtual AuthenticationMechanism Authentication [Parameter(ParameterSetName = NewPSSessionCommand.UriParameterSet)] public virtual string CertificateThumbprint { - get { return _thumbPrint; } + get + { + return _thumbPrint; + } set { @@ -2434,7 +2440,7 @@ private static List GetUsingVariables(ScriptBlock localSc throw new ArgumentNullException(nameof(localScriptBlock), "Caller needs to make sure the parameter value is not null"); } - var allUsingExprs = UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(localScriptBlock.Ast); + var allUsingExprs = UsingExpressionAstSearcher.FindAllUsingExpressions(localScriptBlock.Ast); return allUsingExprs.Select(usingExpr => UsingExpressionAst.ExtractUsingVariable((UsingExpressionAst)usingExpr)).ToList(); } @@ -4353,7 +4359,10 @@ public PSSessionOption() /// public AuthenticationMechanism ProxyAuthentication { - get { return _proxyAuthentication; } + get + { + return _proxyAuthentication; + } set { diff --git a/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs b/src/System.Management.Automation/engine/remoting/commands/ReceiveJob.cs index 750edca6d7b..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 { 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/getrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/getrunspacecommand.cs index 0ad23712ee6..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 { diff --git a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs index 3122d7e1176..625bb86fd64 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 { diff --git a/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs b/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs index 6f520e0ac26..7593bbcc3b0 100644 --- a/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs +++ b/src/System.Management.Automation/engine/remoting/common/RemoteSessionNamedPipe.cs @@ -1141,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)) { } /// @@ -1151,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)) { } /// diff --git a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs index 9debc89ce76..ea8a9c1a9d0 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 { @@ -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) { } @@ -1104,10 +1154,9 @@ private static 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; @@ -1414,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 @@ -1545,7 +1593,10 @@ public override string ComputerName /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -1667,7 +1718,10 @@ public int ProcessId /// public string AppDomainName { - get { return _appDomainName; } + get + { + return _appDomainName; + } set { @@ -1700,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) { } /// @@ -1710,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) { } /// @@ -1736,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) { } /// @@ -1778,7 +1828,10 @@ public override string ComputerName /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { @@ -2288,7 +2341,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 { @@ -2886,7 +2942,10 @@ public override string CertificateThumbprint /// public override PSCredential Credential { - get { return _credential; } + get + { + return _credential; + } set { 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 03a3cd51a87..d99fbe21126 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs @@ -1803,7 +1803,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) { @@ -1820,9 +1820,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); } } } 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 2c3a2c65b14..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. diff --git a/src/System.Management.Automation/engine/remoting/common/fragmentor.cs b/src/System.Management.Automation/engine/remoting/common/fragmentor.cs index 4685af1e75d..8517fb059f5 100644 --- a/src/System.Management.Automation/engine/remoting/common/fragmentor.cs +++ b/src/System.Management.Automation/engine/remoting/common/fragmentor.cs @@ -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 { diff --git a/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs b/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs index 3419bde7966..4e755893886 100644 --- a/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs +++ b/src/System.Management.Automation/engine/remoting/common/psstreamobject.cs @@ -91,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) { } diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 1bf8afd3dd1..7baebdc98ae 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -88,7 +88,10 @@ internal PrioritySendDataCollection() internal Fragmentor Fragmentor { - get { return _fragmentor; } + get + { + return _fragmentor; + } set { diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs index 20db6a1dd1d..99b2d4848bd 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs @@ -558,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(); @@ -2912,12 +2915,13 @@ 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(wsManShellOperationHandle != IntPtr.Zero, "Shell operation handle cannot be IntPtr.Zero."); Dbg.Assert(connectionInfo != null, "connectionInfo cannot be null"); diff --git a/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs b/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs index 21cb200e561..2f2675e61d0 100644 --- a/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs +++ b/src/System.Management.Automation/engine/remoting/server/ServerRunspacePoolDriver.cs @@ -28,6 +28,7 @@ namespace System.Management.Automation /// Interface exposing driver single thread invoke enter/exit /// nested pipeline. /// +#nullable enable internal interface IRSPDriverInvoke { void EnterNestedPipeline(); @@ -36,6 +37,7 @@ internal interface IRSPDriverInvoke bool HandleStopSignal(); } +#nullable restore /// /// This class wraps a RunspacePoolInternal object. It is used to function diff --git a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs index 83dc432ef55..275529b7b3f 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) { diff --git a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs index 97625a9e46a..6478e9b091d 100644 --- a/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs +++ b/src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs @@ -535,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)) { } @@ -1789,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. diff --git a/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs b/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs index f5d2f51f698..93394be6808 100644 --- a/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs +++ b/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs @@ -174,11 +174,14 @@ internal static void ThrowError(ScriptBlockToPowerShellNotSupportedException ex, internal 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; } @@ -313,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. /// @@ -343,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; @@ -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. diff --git a/src/System.Management.Automation/engine/serialization.cs b/src/System.Management.Automation/engine/serialization.cs index a01f67b81e2..b4115de05cb 100644 --- a/src/System.Management.Automation/engine/serialization.cs +++ b/src/System.Management.Automation/engine/serialization.cs @@ -6871,27 +6871,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 ((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); } diff --git a/src/System.Management.Automation/help/CabinetAPI.cs b/src/System.Management.Automation/help/CabinetAPI.cs index b450cc0b870..9ccdc08baa6 100644 --- a/src/System.Management.Automation/help/CabinetAPI.cs +++ b/src/System.Management.Automation/help/CabinetAPI.cs @@ -78,7 +78,7 @@ internal abstract class ICabinetExtractorLoader /// /// Used to create a CabinetExtractor class. /// - internal class CabinetExtractorFactory + internal static class CabinetExtractorFactory { private static readonly ICabinetExtractorLoader s_cabinetLoader; internal static readonly ICabinetExtractor EmptyExtractor = new EmptyCabinetExtractor(); diff --git a/src/System.Management.Automation/help/CommandHelpProvider.cs b/src/System.Management.Automation/help/CommandHelpProvider.cs index 05a4e48af70..d5863f31819 100644 --- a/src/System.Management.Automation/help/CommandHelpProvider.cs +++ b/src/System.Management.Automation/help/CommandHelpProvider.cs @@ -1022,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 + "*"); } diff --git a/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs b/src/System.Management.Automation/help/DefaultCommandHelpObjectBuilder.cs index 6b2a63f3754..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"; /// diff --git a/src/System.Management.Automation/help/HelpCategoryInvalidException.cs b/src/System.Management.Automation/help/HelpCategoryInvalidException.cs index 2ebe763d45a..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(); diff --git a/src/System.Management.Automation/help/HelpCommentsParser.cs b/src/System.Management.Automation/help/HelpCommentsParser.cs index 21ac7b9e79d..7b853381d4d 100644 --- a/src/System.Management.Automation/help/HelpCommentsParser.cs +++ b/src/System.Management.Automation/help/HelpCommentsParser.cs @@ -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); diff --git a/src/System.Management.Automation/help/HelpNotFoundException.cs b/src/System.Management.Automation/help/HelpNotFoundException.cs index 0c546db3620..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(); 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 bf6244fe3eb..d6d3313b68d 100644 --- a/src/System.Management.Automation/help/MUIFileSearcher.cs +++ b/src/System.Management.Automation/help/MUIFileSearcher.cs @@ -127,7 +127,7 @@ private static 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; diff --git a/src/System.Management.Automation/help/MamlUtil.cs b/src/System.Management.Automation/help/MamlUtil.cs index 3022d71f4a6..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. diff --git a/src/System.Management.Automation/help/SaveHelpCommand.cs b/src/System.Management.Automation/help/SaveHelpCommand.cs index 7059550730b..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 diff --git a/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs b/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs index 6bd8b6e84b4..49d1e67e5d9 100644 --- a/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs +++ b/src/System.Management.Automation/help/UpdatableHelpCommandBase.cs @@ -102,7 +102,7 @@ public SwitchParameter UseDefaultCredentials } } - internal bool _useDefaultCredentials = false; + private bool _useDefaultCredentials = false; /// /// Forces the operation to complete. @@ -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) { diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index d302f7b9cae..31fe5362d77 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -240,7 +240,9 @@ internal class UpdatableHelpSystem : IDisposable 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 @@ -785,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; diff --git a/src/System.Management.Automation/namespaces/AliasProvider.cs b/src/System.Management.Automation/namespaces/AliasProvider.cs index 6110b29f997..8782a0d9bb5 100644 --- a/src/System.Management.Automation/namespaces/AliasProvider.cs +++ b/src/System.Management.Automation/namespaces/AliasProvider.cs @@ -331,7 +331,10 @@ public class AliasProviderDynamicParameters [Parameter] public ScopedItemOptions Options { - get { return _options; } + get + { + return _options; + } set { diff --git a/src/System.Management.Automation/namespaces/FileSystemContentStream.cs b/src/System.Management.Automation/namespaces/FileSystemContentStream.cs index 3c627542b4b..f5d299ecfd6 100644 --- a/src/System.Management.Automation/namespaces/FileSystemContentStream.cs +++ b/src/System.Management.Automation/namespaces/FileSystemContentStream.cs @@ -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) { } diff --git a/src/System.Management.Automation/namespaces/FunctionProvider.cs b/src/System.Management.Automation/namespaces/FunctionProvider.cs index 7c5d0a47c29..ea3d9a7509c 100644 --- a/src/System.Management.Automation/namespaces/FunctionProvider.cs +++ b/src/System.Management.Automation/namespaces/FunctionProvider.cs @@ -361,7 +361,10 @@ public class FunctionProviderDynamicParameters [Parameter] public ScopedItemOptions Options { - get { return _options; } + get + { + return _options; + } set { diff --git a/src/System.Management.Automation/namespaces/IContentProvider.cs b/src/System.Management.Automation/namespaces/IContentProvider.cs index f3dcc2f3b2e..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,7 +142,7 @@ 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/NavigationProviderBase.cs b/src/System.Management.Automation/namespaces/NavigationProviderBase.cs index 4cb2927f179..da8a16869d1 100644 --- a/src/System.Management.Automation/namespaces/NavigationProviderBase.cs +++ b/src/System.Management.Automation/namespaces/NavigationProviderBase.cs @@ -1036,8 +1036,7 @@ private static Stack NormalizeThePath( if (!allowNonExistingPaths) { PSArgumentException e = - (PSArgumentException) - PSTraceSource.NewArgumentException( + (PSArgumentException)PSTraceSource.NewArgumentException( nameof(path), SessionStateStrings.NormalizeRelativePathOutsideBase, path, diff --git a/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs b/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs index e6050a44d5a..3f0f52c942e 100644 --- a/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs +++ b/src/System.Management.Automation/namespaces/SessionStateProviderBase.cs @@ -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); diff --git a/src/System.Management.Automation/resources/ParserStrings.resx b/src/System.Management.Automation/resources/ParserStrings.resx index f38b78f074b..dd9ce1b8c55 100644 --- a/src/System.Management.Automation/resources/ParserStrings.resx +++ b/src/System.Management.Automation/resources/ParserStrings.resx @@ -1452,6 +1452,12 @@ 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. + + Unable to find DSC schema store at "{0}". Please ensure PSDesiredStateConfiguration v3 module is installed. + + + PS7DscSupport experimental feature is disabled; use Enable-ExperimentalFeature or update powershell.config.json to enable this feature. + {0} 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/SecuritySupport.cs b/src/System.Management.Automation/security/SecuritySupport.cs index 809c13efb3f..4afb15be55d 100644 --- a/src/System.Management.Automation/security/SecuritySupport.cs +++ b/src/System.Management.Automation/security/SecuritySupport.cs @@ -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; @@ -1335,7 +1334,7 @@ public enum ResolutionPurpose Decryption } - internal class AmsiUtils + internal static class AmsiUtils { private static string GetProcessHostName(string processName) { @@ -1407,7 +1406,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; } @@ -1581,7 +1580,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 { diff --git a/src/System.Management.Automation/security/nativeMethods.cs b/src/System.Management.Automation/security/nativeMethods.cs index 37e29c1f7cb..69f018bb7bc 100644 --- a/src/System.Management.Automation/security/nativeMethods.cs +++ b/src/System.Management.Automation/security/nativeMethods.cs @@ -13,7 +13,7 @@ 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; diff --git a/src/System.Management.Automation/security/wldpNativeMethods.cs b/src/System.Management.Automation/security/wldpNativeMethods.cs index 0eb53dbcb3a..3e0edc58fd0 100644 --- a/src/System.Management.Automation/security/wldpNativeMethods.cs +++ b/src/System.Management.Automation/security/wldpNativeMethods.cs @@ -361,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; } @@ -491,7 +491,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; @@ -541,7 +541,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/utils/CryptoUtils.cs b/src/System.Management.Automation/utils/CryptoUtils.cs index 96877437da2..e121dd62b6d 100644 --- a/src/System.Management.Automation/utils/CryptoUtils.cs +++ b/src/System.Management.Automation/utils/CryptoUtils.cs @@ -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"); diff --git a/src/System.Management.Automation/utils/HostInterfacesExceptions.cs b/src/System.Management.Automation/utils/HostInterfacesExceptions.cs index c70a007d0f1..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); @@ -125,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(); } @@ -137,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(); } @@ -184,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/MetadataExceptions.cs b/src/System.Management.Automation/utils/MetadataExceptions.cs index ebdbddc3325..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) { } @@ -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,26 +225,37 @@ 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/ObjectReader.cs b/src/System.Management.Automation/utils/ObjectReader.cs index f06243ddd5b..b333ec25be2 100644 --- a/src/System.Management.Automation/utils/ObjectReader.cs +++ b/src/System.Management.Automation/utils/ObjectReader.cs @@ -483,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 readonly PSDataCollectionEnumerator _enumerator; + private readonly PSDataCollectionEnumerator _enumerator; #endregion @@ -498,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 @@ -513,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(); } @@ -528,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()) @@ -544,7 +544,7 @@ public override ReturnType Read() /// /// /// - public override Collection ReadToEnd() + public override Collection ReadToEnd() { throw new NotSupportedException(); } @@ -554,7 +554,7 @@ public override Collection ReadToEnd() /// /// /// - public override Collection NonBlockingRead() + public override Collection NonBlockingRead() { return NonBlockingRead(Int32.MaxValue); } @@ -567,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) { @@ -576,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(); } @@ -617,12 +617,12 @@ protected override void Dispose(bool disposing) } } - private static 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; } @@ -642,12 +642,12 @@ private static ReturnType ConvertToReturnType(object inputObject) /// commands concurrently. /// Only Read() operation is supported currently. /// - internal class PSDataCollectionPipelineReader - : ObjectReaderBase + internal class PSDataCollectionPipelineReader + : ObjectReaderBase { #region Private Data - private readonly PSDataCollection _datastore; + private readonly PSDataCollection _datastore; #endregion Private Data @@ -658,7 +658,7 @@ internal class PSDataCollectionPipelineReader /// The stream to read. /// /// - internal PSDataCollectionPipelineReader(PSDataCollectionStream stream, + internal PSDataCollectionPipelineReader(PSDataCollectionStream stream, string computerName, Guid runspaceId) : base(stream) { @@ -688,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(); } @@ -703,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) { @@ -726,7 +726,7 @@ public override ReturnType Read() /// /// /// - public override Collection ReadToEnd() + public override Collection ReadToEnd() { throw new NotSupportedException(); } @@ -736,7 +736,7 @@ public override Collection ReadToEnd() /// /// /// - public override Collection NonBlockingRead() + public override Collection NonBlockingRead() { return NonBlockingRead(Int32.MaxValue); } @@ -749,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) { @@ -758,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) @@ -783,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(); } @@ -793,12 +793,12 @@ public override ReturnType Peek() /// /// Input object to convert. /// Input object converted to the specified return type. - private static 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/PlatformInvokes.cs b/src/System.Management.Automation/utils/PlatformInvokes.cs index c8dc6290511..b6d919df82e 100644 --- a/src/System.Management.Automation/utils/PlatformInvokes.cs +++ b/src/System.Management.Automation/utils/PlatformInvokes.cs @@ -8,7 +8,7 @@ namespace System.Management.Automation { - internal class PlatformInvokes + internal static class PlatformInvokes { [StructLayout(LayoutKind.Sequential)] internal class FILETIME diff --git a/src/System.Management.Automation/utils/PsUtils.cs b/src/System.Management.Automation/utils/PsUtils.cs index 187ed387bc8..e217a8f4788 100644 --- a/src/System.Management.Automation/utils/PsUtils.cs +++ b/src/System.Management.Automation/utils/PsUtils.cs @@ -560,7 +560,7 @@ 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; diff --git a/src/System.Management.Automation/utils/RuntimeException.cs b/src/System.Management.Automation/utils/RuntimeException.cs index c483e460abb..4ba776799e7 100644 --- a/src/System.Management.Automation/utils/RuntimeException.cs +++ b/src/System.Management.Automation/utils/RuntimeException.cs @@ -263,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/StructuredTraceSource.cs b/src/System.Management.Automation/utils/StructuredTraceSource.cs index 47b6e1b4e1d..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 { @@ -1457,7 +1449,10 @@ internal TraceSource TraceSource /// public PSTraceSourceOptions Options { - get { return _flags; } + get + { + return _flags; + } set { diff --git a/src/System.Management.Automation/utils/Telemetry.cs b/src/System.Management.Automation/utils/Telemetry.cs index 46026bb931d..3ff3c908867 100644 --- a/src/System.Management.Automation/utils/Telemetry.cs +++ b/src/System.Management.Automation/utils/Telemetry.cs @@ -563,19 +563,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; } /// diff --git a/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs b/src/System.Management.Automation/utils/tracing/EtwActivityReverter.cs index 5154f637283..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 diff --git a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs index 2dc3a70c34e..011d7577239 100755 --- a/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/PSSysLogProvider.cs @@ -19,7 +19,7 @@ internal class PSSysLogProvider : LogProvider 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 b11481f4c1d..27d0e133fd5 100755 --- a/src/System.Management.Automation/utils/tracing/SysLogProvider.cs +++ b/src/System.Management.Automation/utils/tracing/SysLogProvider.cs @@ -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; } } @@ -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) { @@ -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]; } @@ -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/TypeCatalogGen/TypeCatalogGen.csproj b/src/TypeCatalogGen/TypeCatalogGen.csproj index 1ba3029ff18..c7966c37b79 100644 --- a/src/TypeCatalogGen/TypeCatalogGen.csproj +++ b/src/TypeCatalogGen/TypeCatalogGen.csproj @@ -2,7 +2,7 @@ Generates CorePsTypeCatalog.cs given powershell.inc - net5.0 + net6.0 TypeCatalogGen Exe true diff --git a/src/powershell/Program.cs b/src/powershell/Program.cs index c885fa7fd2e..d9dfa2f80bd 100644 --- a/src/powershell/Program.cs +++ b/src/powershell/Program.cs @@ -266,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; } diff --git a/test/Test.Common.props b/test/Test.Common.props index 02ac0912eb9..d965a3779a0 100644 --- a/test/Test.Common.props +++ b/test/Test.Common.props @@ -6,7 +6,7 @@ Microsoft Corporation (c) Microsoft Corporation. - net5.0 + net6.0 9.0 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 cefe4fd4b90..cbf2a958859 100644 --- a/test/common/markdown/package.json +++ b/test/common/markdown/package.json @@ -6,12 +6,13 @@ "main": "gulpfile.js", "dependencies": { "gulp": "^4.0.2", - "markdownlint": "^0.21.0", + "markdownlint": "^0.22.0", "through2": "^4.0.2" }, "resolutions": { "yargs-parser": "^13.1.2" , - "y18n": "^5.0.5" + "y18n": "^5.0.5", + "ini": "^1.3.6" }, "devDependencies": { "gulp-concat": "^2.6.1", diff --git a/test/common/markdown/yarn.lock b/test/common/markdown/yarn.lock index 1d86b0465ce..b8ba175abb9 100644 --- a/test/common/markdown/yarn.lock +++ b/test/common/markdown/yarn.lock @@ -53,12 +53,10 @@ archy@^1.0.0: 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" - 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" @@ -1346,23 +1344,23 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -markdown-it@11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-11.0.0.tgz" - integrity sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg== +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 "^3.0.1" mdurl "^1.0.1" uc.micro "^1.0.5" -markdownlint@^0.21.0: - version "0.21.1" - resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.21.1.tgz" - integrity sha512-8kc88w5dyEzlmOWIElp8J17qBgzouOQfJ0LhCcpBFrwgyYK6JTKvILsk4FCEkiNqHkTxwxopT2RS2DYb/10qqg== +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 "11.0.0" + markdown-it "12.0.2" matchdep@^2.0.0: version "2.0.0" @@ -1994,11 +1992,6 @@ split-string@^3.0.1, split-string@^3.0.2: 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" - 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" 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/packaging/windows/msi.tests.ps1 b/test/packaging/windows/msi.tests.ps1 index d9541b74f06..ce9e3334557 100644 --- a/test/packaging/windows/msi.tests.ps1 +++ b/test/packaging/windows/msi.tests.ps1 @@ -53,6 +53,8 @@ Describe -Name "Windows MSI" -Fixture { } $msiX64Path = $env:PsMsiX64Path + $channel = $env:PSMsiChannel + $runtime = $env:PSMsiRuntime # Get any existing powershell in the path $beforePath = @(([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | @@ -82,12 +84,29 @@ Describe -Name "Windows MSI" -Fixture { Context "Upgrade code" { BeforeAll { - $previewUpgladeCode = '39243d76-adaf-42b1-94fb-16ecf83237c8' + 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 "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 x64 is not installed" } It "MSI should install without error" -Skip:(!(Test-Elevated)) { @@ -97,8 +116,8 @@ 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 x64 $channel" } It "MSI should uninstall without error" -Skip:(!(Test-Elevated)) { @@ -117,7 +136,7 @@ Describe -Name "Windows MSI" -Fixture { 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 } @@ -137,8 +156,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/powershell/Host/Startup.Tests.ps1 b/test/powershell/Host/Startup.Tests.ps1 index 05b2534bc9a..6ce9dfc463d 100644 --- a/test/powershell/Host/Startup.Tests.ps1 +++ b/test/powershell/Host/Startup.Tests.ps1 @@ -22,7 +22,6 @@ 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' @@ -67,6 +66,7 @@ Describe "Validate start of console host" -Tag CI { if ($IsWindows) { $allowedAssemblies += @( 'Microsoft.PowerShell.CoreCLR.Eventing.dll' + 'System.Diagnostics.FileVersionInfo.dll' 'System.DirectoryServices.dll' 'System.Management.dll' 'System.Security.Claims.dll' @@ -76,10 +76,7 @@ Describe "Validate start of console host" -Tag CI { } else { $allowedAssemblies += @( - 'System.Collections.Immutable.dll' - 'System.IO.MemoryMappedFiles.dll' 'System.Net.Sockets.dll' - 'System.Reflection.Metadata.dll' ) } diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index c42f30e510a..77667306aed 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -915,6 +915,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 = @' 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.Utility/Foreach-Object-Parallel.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1 index 484454e3a85..46f85b80bd4 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 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 '' exception if '' 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..2a24264b28e 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,48 @@ 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 + 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 '' 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/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/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 b/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 index c2fc8cf1e55..30a92d6a8ef 100644 --- a/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 +++ b/test/powershell/Modules/PSDesiredStateConfiguration/PSDesiredStateConfiguration.Tests.ps1 @@ -129,6 +129,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/26" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + $resource = Get-DscResource -Name $name $resource | Should -Not -BeNullOrEmpty $resource.Name | Should -Be $Name @@ -148,6 +152,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/26" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if ($PendingBecause) { Set-ItResult -Pending -Because $PendingBecause } @@ -225,6 +233,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "Will only find script from PSDesiredStateConfiguration without modulename" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } @@ -254,6 +266,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/12 and https://github.com/PowerShell/PowerShellGet/pull/529" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if ($PendingBecause) { Set-ItResult -Pending -Because $PendingBecause } @@ -315,6 +331,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if ($PendingBecause) { Set-ItResult -Pending -Because $PendingBecause } @@ -340,6 +360,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if ($PendingBecause) { Set-ItResult -Pending -Because $PendingBecause } @@ -402,6 +426,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + if (!$IsLinux) { $result = Invoke-DscResource -Name PSModule -ModuleName $psGetModuleSpecification -Method set -Property @{ Name = 'PsDscResources' @@ -427,6 +455,10 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } + # using create scriptBlock because $using: 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") } @@ -438,6 +470,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } $result = Invoke-DscResource -Name Script -ModuleName PSDscResources -Method Test -Property @{TestScript = { Write-Output 'test'; return $false }; GetScript = { return @{ } }; SetScript = { return } } $result | Should -Not -BeNullOrEmpty @@ -448,6 +483,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } $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" @@ -457,6 +495,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } $module = Get-Module PsDscResources -ListAvailable $moduleSpecification = @{ModuleName = $module.Name; ModuleVersion = $module.Version.ToString() } @@ -520,6 +561,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } { Invoke-DscResource -Name santoheusnaasonteuhsantoheu -Method Test -Property @{TestScript = { Write-Host 'test'; return $true }; GetScript = { return @{ } }; SetScript = { return } } -ErrorAction Stop @@ -531,6 +575,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($IsLinux) { Set-ItResult -Pending -Because "https://github.com/PowerShell/PSDesiredStateConfiguration/issues/12 and https://github.com/PowerShell/PowerShellGet/pull/529" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } $result = Invoke-DscResource -Name PSModule -ModuleName $psGetModuleSpecification -Method Get -Property @{ Name = 'PsDscResources' } $result | Should -Not -BeNullOrEmpty @@ -577,6 +624,9 @@ Describe "Test PSDesiredStateConfiguration" -tags CI { if ($MissingLibmi) { Set-ItResult -Pending -Because "Libmi not available for this platform" } + if ($IsMacOS) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } $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 diff --git a/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 b/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 index 7b621578e4d..953b28acec7 100644 --- a/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 +++ b/test/powershell/Modules/PSDesiredStateConfiguration/configuration.Tests.ps1 @@ -15,6 +15,9 @@ Describe "DSC MOF Compilation" -tags "CI" { if ($IsLinux) { Set-ItResult -Pending -Because "https://github.com/PowerShell/PowerShellGet/pull/529" } + if ($IsMacOs) { + Set-ItResult -Pending -Because "macOS is incompatible with libmi" + } Write-Verbose "DSC_HOME: ${env:DSC_HOME}" -Verbose [Scriptblock]::Create(@" diff --git a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 index bcc358bcccd..c11002fbedb 100644 --- a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 +++ b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 @@ -174,7 +174,14 @@ Describe "Default enablement of Experimental Features" -Tags CI { (Join-Path -Path $PSHOME -ChildPath 'powershell.config.json') | Should -Exist foreach ($expFeature in Get-ExperimentalFeature) { - $expFeature.Enabled | Should -BeEnabled -Name $expFeature.Name + if ($expFeature.Name -ne "PS7DscSupport") + { + $expFeature.Enabled | Should -BeEnabled -Name $expFeature.Name + } + else + { + $expFeature.Enabled | Should -Not -BeEnabled -Name $expFeature.Name + } } } } diff --git a/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 b/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 index 27dea30689e..7feb978bd9d 100644 --- a/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 +++ b/test/powershell/engine/Formatting/OutputRendering.Tests.ps1 @@ -79,7 +79,9 @@ Describe 'OutputRendering tests' { $switch = "-$stream" } - $out = pwsh -noprofile -command "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassOutputRedirectionCheck', `$true); write-$stream $switch 'hello'" - $out | Should -BeExactly "$($PSStyle.Formatting.$stream)$($stream.ToUpper()): hello" + $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" } } diff --git a/test/powershell/engine/Formatting/PSStyle.Tests.ps1 b/test/powershell/engine/Formatting/PSStyle.Tests.ps1 index 5e02e2e231c..e8de28ff610 100644 --- a/test/powershell/engine/Formatting/PSStyle.Tests.ps1 +++ b/test/powershell/engine/Formatting/PSStyle.Tests.ps1 @@ -6,8 +6,8 @@ Describe 'Tests for $PSStyle automatic variable' { $PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRendering'))) $styleDefaults = @{ Reset = "`e[0m" - BlinkOff = "`e[5m" - Blink = "`e[25m" + BlinkOff = "`e[25m" + Blink = "`e[5m" BoldOff = "`e[22m" Bold = "`e[1m" HiddenOff = "`e[28m" @@ -18,6 +18,8 @@ Describe 'Tests for $PSStyle automatic variable' { Italic = "`e[3m" UnderlineOff = "`e[24m" Underline = "`e[4m" + StrikethroughOff = "`e[29m" + Strikethrough = "`e[9m" } $formattingDefaults = @{ @@ -111,4 +113,29 @@ Describe 'Tests for $PSStyle automatic variable' { $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) + } } diff --git a/test/powershell/engine/Remoting/PSSession.Tests.ps1 b/test/powershell/engine/Remoting/PSSession.Tests.ps1 index e985ff6ab36..3b8259f3707 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 }, diff --git a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 index e48eaecb526..27d2fceb454 100644 --- a/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 +++ b/test/powershell/engine/Remoting/RemoteSession.Basic.Tests.ps1 @@ -3,19 +3,25 @@ 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 + ($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 +32,14 @@ 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 + ($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 +49,20 @@ 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 + ($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. 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/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 0eac8074de0..d31f61be763 100644 --- a/test/tools/TestExe/TestExe.cs +++ b/test/tools/TestExe/TestExe.cs @@ -48,7 +48,7 @@ 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]); } } diff --git a/test/tools/TestService/TestService.csproj b/test/tools/TestService/TestService.csproj index 8c651cabba2..21d0fc76962 100644 --- a/test/tools/TestService/TestService.csproj +++ b/test/tools/TestService/TestService.csproj @@ -13,7 +13,7 @@ - + diff --git a/test/tools/WebListener/Controllers/GetController.cs b/test/tools/WebListener/Controllers/GetController.cs index cadb34725a8..68ce98fb78f 100644 --- a/test/tools/WebListener/Controllers/GetController.cs +++ b/test/tools/WebListener/Controllers/GetController.cs @@ -36,6 +36,7 @@ public JsonResult Index() {"headers", headers}, {"origin" , Request.HttpContext.Connection.RemoteIpAddress.ToString()}, {"url" , UriHelper.GetDisplayUrl(Request)}, + {"query" , Request.QueryString.ToUriComponent()}, {"method" , Request.Method} }; diff --git a/test/tools/WebListener/Controllers/ResponseController.cs b/test/tools/WebListener/Controllers/ResponseController.cs index 6347abc98e6..903b3426b74 100644 --- a/test/tools/WebListener/Controllers/ResponseController.cs +++ b/test/tools/WebListener/Controllers/ResponseController.cs @@ -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); 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/WebListener.csproj b/test/tools/WebListener/WebListener.csproj index 6adedf53878..de62702c6e2 100644 --- a/test/tools/WebListener/WebListener.csproj +++ b/test/tools/WebListener/WebListener.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/test/xUnit/csharp/test_Prediction.cs b/test/xUnit/csharp/test_Prediction.cs index 4d67c850f6d..8f018ebb9e1 100644 --- a/test/xUnit/csharp/test_Prediction.cs +++ b/test/xUnit/csharp/test_Prediction.cs @@ -20,9 +20,9 @@ public class MyPredictor : ICommandPredictor public List AcceptedSuggestions { get; } - public static readonly MyPredictor SlowPredictor; + public List DisplayedSuggestions { get; } - public static readonly MyPredictor FastPredictor; + public static readonly MyPredictor SlowPredictor, FastPredictor; static MyPredictor() { @@ -48,6 +48,7 @@ private MyPredictor(Guid id, string name, string description, bool delay) History = new List(); AcceptedSuggestions = new List(); + DisplayedSuggestions = new List(); } public Guid Id => _id; @@ -60,17 +61,25 @@ private MyPredictor(Guid id, string name, string description, bool delay) bool ICommandPredictor.AcceptFeedback => true; - public void StartEarlyProcessing(IReadOnlyList history) + public void StartEarlyProcessing(string clientId, IReadOnlyList history) { - History.AddRange(history); + foreach (string item in history) + { + History.Add($"{clientId}-{item}"); + } + } + + public void OnSuggestionDisplayed(string clientId, uint session, int countOrIndex) + { + DisplayedSuggestions.Add($"{clientId}-{session}-{countOrIndex}"); } - public void OnSuggestionAccepted(string acceptedSuggestion) + public void OnSuggestionAccepted(string clientId, uint session, string acceptedSuggestion) { - AcceptedSuggestions.Add(acceptedSuggestion); + AcceptedSuggestions.Add($"{clientId}-{session}-{acceptedSuggestion}"); } - public List GetSuggestion(PredictionContext context, CancellationToken cancellationToken) + public SuggestionPackage GetSuggestion(string clientId, PredictionContext context, CancellationToken cancellationToken) { if (_delay) { @@ -81,24 +90,31 @@ public List GetSuggestion(PredictionContext context, Cance // You can get the user input from the AST. var userInput = context.InputAst.Extent.Text; - return new List { - new PredictiveSuggestion($"{userInput} TEST-1 from {Name}"), - new PredictiveSuggestion($"{userInput} TeSt-2 from {Name}"), + var entries = new List + { + new PredictiveSuggestion($"'{userInput}' from '{clientId}' - TEST-1 from {Name}"), + new PredictiveSuggestion($"'{userInput}' from '{clientId}' - TeSt-2 from {Name}"), }; + + return new SuggestionPackage(56, entries); } } public static class CommandPredictionTests { + private const string Client = "PredictionTest"; + private const uint Session = 56; + [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 results = CommandPrediction.PredictInput(ast, tokens).Result; + List results = CommandPrediction.PredictInput(Client, ast, tokens).Result; Assert.Null(results); try @@ -111,32 +127,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.PredictInput(Client, 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.PredictInput(Client, 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 { @@ -160,8 +179,10 @@ public static void Feedback() var history = new[] { "hello", "world" }; var ids = new HashSet { slow.Id, fast.Id }; - CommandPrediction.OnCommandLineAccepted(history); - CommandPrediction.OnSuggestionAccepted(slow.Id, "Yeah"); + CommandPrediction.OnCommandLineAccepted(Client, history); + CommandPrediction.OnSuggestionDisplayed(Client, slow.Id, Session, 2); + CommandPrediction.OnSuggestionDisplayed(Client, fast.Id, Session, -1); + CommandPrediction.OnSuggestionAccepted(Client, slow.Id, Session, "Yeah"); // The calls to 'StartEarlyProcessing' and 'OnSuggestionAccepted' are queued in thread pool, // so we wait a bit to make sure the calls are done. @@ -171,15 +192,21 @@ public static void Feedback() } 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.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_Subsystem.cs b/test/xUnit/csharp/test_Subsystem.cs index a45ebc116b5..f2ca308221f 100644 --- a/test/xUnit/csharp/test_Subsystem.cs +++ b/test/xUnit/csharp/test_Subsystem.cs @@ -95,10 +95,12 @@ public static void RegisterSubsystem() 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 predCxt = PredictionContext.Create(Input); + var results = impl.GetSuggestion(Client, 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 impls = SubsystemManager.GetSubsystems(); diff --git a/test/xUnit/xUnit.tests.csproj b/test/xUnit/xUnit.tests.csproj index 352da3d353d..f7509c8cb58 100644 --- a/test/xUnit/xUnit.tests.csproj +++ b/test/xUnit/xUnit.tests.csproj @@ -26,7 +26,7 @@ - + diff --git a/tools/UpdateDotnetRuntime.ps1 b/tools/UpdateDotnetRuntime.ps1 index 5bbe5e5faed..4bc9472bd3c 100644 --- a/tools/UpdateDotnetRuntime.ps1 +++ b/tools/UpdateDotnetRuntime.ps1 @@ -22,7 +22,7 @@ param ( [switch]$InteractiveAuth, [Parameter()] - [switch]$UseRTMFeed + [switch]$UseInternalFeed ) <# @@ -68,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() @@ -97,7 +98,13 @@ function Update-PackageVersion { $versionPattern = (Get-Content "$PSScriptRoot/../DotnetRuntimeMetadata.json" | ConvertFrom-Json).sdk.packageVersionPattern - $source = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseRTMFeed) { 'dotnet5-rtm' } 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 @@ -105,13 +112,8 @@ function Update-PackageVersion { $version = $v.Version foreach ($p in $pkgs) { - if ($UseRTMFeed -and $p.Version -eq $versionPattern) { - if ([System.Management.Automation.SemanticVersion] ($version) -lt [System.Management.Automation.SemanticVersion] ($p.Version)) { - $v.NewVersion = $p.Version - break - } - } - elseif ($p.Version -like "$versionPattern*") { + # 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 @@ -152,17 +154,21 @@ function Update-CsprojFile([string] $path, $values) { } function Get-DotnetUpdate { + $dotnetMetadataPath = "$PSScriptRoot/../DotnetRuntimeMetadata.json" + $metataJson = (Get-Content $dotnetMetadataPath -Raw | ConvertFrom-Json) + $nextChannel = $metataJson.sdk.nextChannel + $feedUrl = $metataJson.internalfeed.url + if ($SDKVersionOverride) { return @{ ShouldUpdate = $true NewVersion = $SDKVersionOverride Message = $null + FeedUrl = $feedUrl } } 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() }) $currentVersion = [System.Management.Automation.SemanticVersion] (( Get-Content -Path "$PSScriptRoot/../global.json" -Raw | ConvertFrom-Json).sdk.version) @@ -184,6 +190,7 @@ function Get-DotnetUpdate { ShouldUpdate = $shouldUpdate NewVersion = $newVersion Message = $Message + FeedUrl = $feedUrl } } @@ -210,32 +217,27 @@ if ($dotnetUpdate.ShouldUpdate) { Find-Dotnet - $feedname = if ($UseRTMFeed) { - 'dotnet5-rtm' - } elseif ($UseNuGetOrg) { - 'dotnet5' - } else { - 'dotnet-internal' - } + $feedname = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseInternalFeed) { 'dotnet-internal' } else { 'dotnet' } - $addDotnet5Source = (-not (Get-PackageSource -Name $feedname -ErrorAction SilentlyContinue)) + $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 -and $feedname -ne 'dotnet-internal') { - $dotnet5Feed = $nugetFileSources | Where-Object { $_.Key -eq $feedname } | Select-Object -ExpandProperty Value - Register-PackageSource -Name $feedname -Location $dotnet5Feed -ProviderName NuGet + 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 ($addDotnet5Source -and $InteractiveAuth -and $feedname -eq 'dotnet-internal') { + 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 "", " `r`n " - $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 = $nugetFileContent -replace "", " `r`n " + $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 } } diff --git a/tools/ci.psm1 b/tools/ci.psm1 index 2329b56db99..f978decf64a 100644 --- a/tools/ci.psm1 +++ b/tools/ci.psm1 @@ -438,33 +438,44 @@ function Get-ReleaseTag function Invoke-CIFinish { param( - [string] $NuGetKey + [string] $Runtime = 'win7-x64', + [string] $Channel = 'preview' ) if($PSEdition -eq 'Core' -and ($IsLinux -or $IsMacOS)) { - return New-LinuxPackage -NugetKey $NugetKey + return New-LinuxPackage } try { - $releaseTag = Get-ReleaseTag - $previewVersion = $releaseTag.Split('-') - $previewPrefix = $previewVersion[0] - $previewLabel = $previewVersion[1].replace('.','') - - if(Test-DailyBuild) + if($Channel -eq 'preview') { - $previewLabel= "daily{0}" -f $previewLabel - } + $releaseTag = Get-ReleaseTag - $preReleaseVersion = "$previewPrefix-$previewLabel.$env:BUILD_BUILDID" + $previewVersion = $releaseTag.Split('-') + $previewPrefix = $previewVersion[0] + $previewLabel = $previewVersion[1].replace('.','') - # Build clean before backing to remove files from testing - Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean + if(Test-DailyBuild) + { + $previewLabel= "daily{0}" -f $previewLabel + } - # Build packages - $packages = Start-PSPackage -Type msi,nupkg,zip,zip-pdb -ReleaseTag $preReleaseVersion -SkipReleaseChecks + $preReleaseVersion = "$previewPrefix-$previewLabel.$env:BUILD_BUILDID" + # Build clean before backing to remove files from testing + Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime + } + else { + $releaseTag = Get-ReleaseTag + $releaseTagParts = $releaseTag.split('.') + $preReleaseVersion = $releaseTagParts[0]+ ".9.9" + Write-Verbose "newPSReleaseTag: $preReleaseVersion" -Verbose + Start-PSBuild -CrossGen -PSModuleRestore -Configuration 'Release' -ReleaseTag $preReleaseVersion -Clean -Runtime $Runtime + } + + # Build packages $preReleaseVersion = "$previewPrefix-$previewLabel.$env:BUILD_BUILDID" + $packages = Start-PSPackage -Type msi,nupkg,zip,zip-pdb -ReleaseTag $preReleaseVersion -SkipReleaseChecks -WindowsRuntime $Runtime $artifacts = New-Object System.Collections.ArrayList foreach ($package in $packages) { @@ -490,6 +501,8 @@ function Invoke-CIFinish # the packaging tests find the MSI package using env:PSMsiX64Path $env:PSMsiX64Path = $artifacts | Where-Object { $_.EndsWith(".msi")} + $env:PSMsiChannel = $Channel + $env:PSMsiRuntime = $Runtime # Install the latest Pester and import it $maximumPesterVersion = '4.99' @@ -537,12 +550,6 @@ function Invoke-CIFinish $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) { @@ -692,10 +699,6 @@ function Invoke-LinuxTestsCore function New-LinuxPackage { - param( - [string] - $NugetKey - ) $isFullBuild = Test-DailyBuild $releaseTag = Get-ReleaseTag @@ -716,16 +719,6 @@ 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') - { - 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 - } - if($isFullBuild) { if ($package -isnot [System.IO.FileInfo]) diff --git a/tools/metadata.json b/tools/metadata.json index 77d654d1dd1..9fddef41b11 100644 --- a/tools/metadata.json +++ b/tools/metadata.json @@ -1,9 +1,9 @@ { - "StableReleaseTag": "v7.1.0", - "PreviewReleaseTag": "v7.2.0-preview.1", - "ServicingReleaseTag": "v6.2.7", - "ReleaseTag": "v7.1.0", - "LTSReleaseTag" : ["v7.0.3"], - "NextReleaseTag": "v7.2.0-preview.2", + "StableReleaseTag": "v7.1.1", + "PreviewReleaseTag": "v7.2.0-preview.2", + "ServicingReleaseTag": "v7.0.4", + "ReleaseTag": "v7.1.1", + "LTSReleaseTag" : ["v7.0.4"], + "NextReleaseTag": "v7.2.0-preview.3", "LTSRelease": false } diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index aaaee8688d0..0b80193053f 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -8,7 +8,7 @@ $packagingStrings = Import-PowerShellDataFile "$PSScriptRoot\packaging.strings.p Import-Module "$PSScriptRoot\..\Xml" -ErrorAction Stop -Force $DebianDistributions = @("ubuntu.16.04", "ubuntu.18.04", "ubuntu.20.04", "debian.9", "debian.10", "debian.11") $RedhatDistributions = @("rhel.7","centos.8") -$script:netCoreRuntime = 'net5.0' +$script:netCoreRuntime = 'net6.0' $script:iconFileName = "Powershell_black_64.png" $script:iconPath = Join-Path -path $PSScriptRoot -ChildPath "../../assets/$iconFileName" -Resolve @@ -336,6 +336,7 @@ function Start-PSPackage { if ($Runtime -match "-x86") { $TargetArchitecture = "x86" } + Write-Verbose "TargetArchitecture = $TargetArchitecture" -Verbose $Arguments = @{ ProductNameSuffix = $NameSuffix @@ -1268,19 +1269,12 @@ function Get-PackageDependencies "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") } - "ubuntu\.20\.04" { $Dependencies += @("libssl1.1", "libicu66") } - "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) { $Dependencies = @( "openssl-libs", @@ -2017,7 +2011,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 @@ -2036,24 +2030,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'" } } } @@ -2235,8 +2232,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" @@ -2268,6 +2270,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 } @@ -2367,6 +2372,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)]" @@ -2594,7 +2604,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" @@ -2939,7 +2948,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 { @@ -3173,7 +3182,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 { diff --git a/tools/packaging/packaging.strings.psd1 b/tools/packaging/packaging.strings.psd1 index 444bfa7f3a0..8fcb4e93fc5 100644 --- a/tools/packaging/packaging.strings.psd1 +++ b/tools/packaging/packaging.strings.psd1 @@ -142,7 +142,7 @@ open {0} - + 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 @@ runtime=$(RID);version=$(SemVer);PackageName=$(PackageName) $(StagingPath) True - net5.0 + net6.0 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 d6aa032de2b..1360181e9bc 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 @@ - net5.0 + net6.0 $(RefAsmVersion) true $(SnkFile) @@ -14,7 +14,7 @@ - + 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 @@ - net5.0 + net6.0 $(RefAsmVersion) true $(SnkFile) 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 a917b07fafc..76baeb19619 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 @@ - net5.0 + net6.0 $(RefAsmVersion) true $(SnkFile) @@ -9,7 +9,7 @@ - - + + diff --git a/tools/releaseBuild/azureDevOps/releasePipeline.yml b/tools/releaseBuild/azureDevOps/releasePipeline.yml index 9c752a179d9..3fc5c45d125 100644 --- a/tools/releaseBuild/azureDevOps/releasePipeline.yml +++ b/tools/releaseBuild/azureDevOps/releasePipeline.yml @@ -225,6 +225,24 @@ 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 MSIX to store + pool: server + environment: PSReleasePublishMsix + - stage: BuildInfoJson dependsOn: GitHubManualTasks displayName: Upload BuildInfoJson diff --git a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml index 053354d34c0..25295ba7c24 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-GlobalToolTest.yml @@ -39,11 +39,11 @@ 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 diff --git a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml index dd7c9618c9e..5e460147141 100644 --- a/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml +++ b/tools/releaseBuild/azureDevOps/templates/release-SDKTests.yml @@ -47,16 +47,22 @@ 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 + ## Remove old .NET SDKs if any exists + if (Test-Path -Type Container $Home/.dotnet) + { + Remove-Item $Home/.dotnet -Recurse -Force + } + ## Install latest version from the channel #Install-Dotnet -Channel "$Channel" -Version $sdkVersion + Start-PSBootstrap Write-Verbose -Message "Installing .NET SDK completed." -Verbose @@ -71,7 +77,7 @@ jobs: $localLocation = "$(Pipeline.Workspace)/releasePipeline/finalResults" $xmlElement = @" - + "@ 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/windows-packaging.yml b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml index 81eac8e5a11..1554afccaba 100644 --- a/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml +++ b/tools/releaseBuild/azureDevOps/templates/windows-packaging.yml @@ -180,7 +180,14 @@ jobs: $null = New-Item -ItemType Directory -Path $signedFilesDirectory -Force $missingSignatures | ForEach-Object { - Copy-Item -Path $_ -Destination $filesToSignDirectory + $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 diff --git a/tools/releaseTools.psm1 b/tools/releaseTools.psm1 index 1ea38df348c..ab8f0c60b1c 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] } }