MegaBites-AI/Windows-powershell
0372
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]5param()6 7Describe "WSMan Config Provider" -Tag Feature,RequireAdminOnWindows {8 BeforeAll {9 #skip all tests on non-windows platform10 $originalDefaultParameterValues = $PSDefaultParameterValues.Clone()11 $PSDefaultParameterValues["it:skip"] = !$IsWindows12 13 if ($IsWindows) {14 $badCredentialError = 132615 $pluginXml = [xml](winrm g winrm/config/plugin?name=microsoft.powershell -format:xml)16 $pluginPath = "WSMan:\localhost\Plugin\microsoft.powershell"17 $testPluginXml = [xml]($pluginXml.OuterXml)18 $testPluginXml.PlugInConfiguration.Name = "TestPlugin"19 $testPluginXml.PlugInConfiguration.RemoveAttribute("xml:lang")20 $testPluginXml.PlugInConfiguration.Resources.Resource.ResourceUri = "http://schemas.microsoft.com/powershell/TestPlugin"21 $testPluginXml.PlugInConfiguration.Resources.Resource.Security.Uri = "http://schemas.microsoft.com/powershell/TestPlugin"22 Set-Content $TestDrive\plugin.xml -Value $testPluginXml.OuterXml23 $null = winrm c winrm/config/plugin?Name=TestPlugin -file:$TestDrive\plugin.xml24 $testPluginPath = "WSMan:\localhost\Plugin\TestPlugin"25 $testUser = (Get-Random)26 $testPass = "Secret123!"27 $null = net user $testUser $testPass /add28 }29 }30 31 AfterAll {32 $Global:PSDefaultParameterValues = $originalDefaultParameterValues33 if ($IsWindows) {34 $null = winrm d winrm/config/plugin?Name=TestPlugin35 $null = net user $testUser /DELETE36 }37 }38 39 Function Test-Plugin($plugin, $expectedMissingProperties, $expectedMissingAttributes) {40 $plugin.PSPath | Should -Exist41 $testPluginXml = [xml](winrm g winrm/config/plugin?name=$($plugin.Name) -format:xml)42 $pluginProperties = Get-ChildItem $plugin.PSPath43 $xmlElementCount = ($testPluginXml.PluginConfiguration | Get-Member -Type Properties).Count + $expectedMissingProperties.Count - $expectedMissingAttributes.Count44 $pluginProperties.Count | Should -BeExactly $xmlElementCount45 foreach ($pluginProperty in $pluginProperties) {46 if ($pluginProperty.Type -eq "System.String") {47 $pluginProperty.Value | Should -Be $testPluginXml.PluginConfiguration.$($pluginProperty.Name)48 (Get-Item "$($plugin.PSPath)\$($pluginProperty.Name)").Value | Should -Be $testPluginXml.PluginConfiguration.$($pluginProperty.Name)49 }50 }51 }52 53 AfterEach {54 if (-not (Test-Path wsman:))55 {56 $null = New-PSDrive -Name WSMan -PSProvider WSMan -Root "" -Scope Global57 }58 }59 60 Context "Misc tests" {61 It "Can remove and add wsman drive" {62 $wsmanDrive = Get-PSDrive -Name WSMan63 Remove-PSDrive -Name wsman64 { Get-PSDrive -Name wsman -ErrorAction Stop } | Should -Throw -ErrorId "GetLocationNoMatchingDrive,Microsoft.PowerShell.Commands.GetPSDriveCommand"65 $wsmanDrive2 = $wsmanDrive | New-PSDrive -PSProvider WSMan66 $wsmanDrive2 | Should -BeOfType System.Management.Automation.PSDriveInfo67 $wsmanDrive2.Name | Should -BeExactly "WSMan"68 $wsmanDrive2.Provider.Name | Should -BeExactly "WSMan"69 }70 71 It "WSMan Config Provider starts WinRM if it is stopped" {72 try {73 Stop-Service WinRM74 Get-ChildItem wsman:\localhost -Force | Should -Not -BeNullOrEmpty75 (Get-Service WinRM).Status | Should -Be 'Running'76 }77 finally {78 if ((Get-Service WinRM).Status -eq 'stopped') {79 Start-Service WinRM80 }81 }82 }83 84 It "Container check works" {85 Test-Path wsman:\foo -PathType container | Should -BeFalse86 }87 }88 89 Context "Get-Item tests" {90 91 It "Plugin has correct properties" {92 $plugin = Get-Item $pluginPath93 Test-Plugin -Plugin $plugin94 }95 96 It "Plugin InitializationParameters are correct" {97 $initializationParameters = Get-ChildItem $pluginPath\InitializationParameters98 $initializationParameters.Count | Should -Be (,$pluginXml.PluginConfiguration.InitializationParameters.Param).Count99 foreach ($initializationParameter in $initializationParameters) {100 $initializationParameter.Value | Should -Be ($pluginXml.PluginConfiguration.InitializationParameters | Where-Object { $_.Param.Name -eq $initializationParameter.Name }).Param.Value101 (Get-Item $pluginPath\InitializationParameters\$($initializationParameter.Name)).Value | Should -Be ($pluginXml.PluginConfiguration.InitializationParameters | Where-Object { $_.Param.Name -eq $initializationParameter.Name }).Param.Value102 }103 }104 105 It "Plugin Quotas are correct" {106 $quotas = Get-ChildItem $pluginPath\Quotas107 $quotas.Count | Should -Be ($pluginXml.PluginConfiguration.Quotas | Get-Member -Type Properties).Count108 foreach ($quota in $quotas) {109 $quota.Value | Should -Be $pluginXml.PluginConfiguration.Quotas.$($quota.Name)110 }111 }112 113 It "Plugin Resources are correct" {114 $resources = Get-ChildItem $pluginPath\Resources115 $resources.Count | Should -Be (,$pluginXml.PluginConfiguration.Resources.Resource).Count116 }117 118 It "Plugin Security Resource is correct" {119 (,$pluginXml.PluginConfiguration.Resources.Resource).Count | Should -Be 1 # by default only Security resource should be there120 $resource = Get-ChildItem "$pluginPath\Resources" | Select-Object -First 1121 $resourceUri = Get-Item "$($resource.PSPath)\ResourceUri"122 $resourceUri.Value | Should -Be "http://schemas.microsoft.com/powershell/microsoft.powershell"123 $securityContainer = Get-ChildItem "$pluginPath\Resources\$($resource.Name)\Security" | Select-Object -First 1124 $securityProperties = Get-ChildItem $securityContainer.PSPath125 $skippedAttributes = @("ParentResourceUri","xmlns") # these are added by the WSMan Config Provider but not in the original xml126 127 # ParentResourceUri is added by the Config Provider, xmlns existing seems to be dependent on WinRM which is inconsistent128 $securityProperties.Count | Should -BeGreaterThan (($pluginXml.PluginConfiguration.Resources.Resource.Security | Get-Member -Type Properties).Count)129 foreach ($securityProperty in $securityProperties) {130 if ($skippedAttributes -notcontains $securityProperty.Name) {131 $securityProperty.Value | Should -Be ($pluginXml.PluginConfiguration.Resources.Resource.Security.$($securityProperty.Name))132 (Get-Item "$($securityContainer.PSPath)\$($securityProperty.Name)").Value | Should -Be ($pluginXml.PluginConfiguration.Resources.Resource.Security.$($securityProperty.Name))133 }134 }135 }136 }137 138 Context "Set-Item tests" {139 It "Set-Item should fail for `$null value" {140 { Set-Item WSMan:\localhost\Client\TrustedHosts $null } | Should -Throw -ErrorId "System.ArgumentException,Microsoft.PowerShell.Commands.SetItemCommand"141 }142 143 It "Set-Item should fail for <path>" -TestCases @(144 @{path="WSMan:\"},145 @{path="WSMan:\localhost"}146 ) {147 param ($path)148 { Set-Item $path "foo" } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"149 }150 151 It "Set-Item -WhatIf should work" {152 $trustedHostsPath = "WSMan:\localhost\Client\TrustedHosts"153 $trustedHosts = Get-Item $trustedHostsPath154 Set-Item $trustedHostsPath "hello" -WhatIf155 (Get-Item $trustedHostsPath).Value | Should -Be $trustedHosts.Value156 }157 158 It "Set-Item on TrustedHosts should succeed" {159 try {160 $trustedHostsPath = "WSMan:\localhost\Client\TrustedHosts\"161 $trustedHosts = Get-Item $trustedHostsPath162 Set-Item -Path $trustedHostsPath -Value "hello" -Force163 (Get-Item $trustedHostsPath).Value | Should -Be "hello"164 }165 finally {166 Set-Item $trustedHostsPath $trustedHosts.Value -Force167 }168 }169 170 It "Set-Item on plugin RunAsUser should fail for invalid creds" {171 #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]172 $password = ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force173 $creds = [pscredential]::new((Get-Random),$password)174 $exception = { Set-Item $testPluginPath\RunAsUser $creds } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand" -PassThru175 $exception.Exception.Message | Should -Match ".*$badCredentialError.*"176 }177 178 It "Set-Item and Clear-Item on plugin RunAsUser should succeed for valid creds" {179 $password = ConvertTo-SecureString $testPass -AsPlainText -Force180 $creds = [pscredential]::new($testUser,$password)181 Set-Item $testPluginPath\RunAsUser $creds -WarningAction SilentlyContinue182 (Get-Item $testPluginPath\RunAsUser).Value | Should -Be $testUser183 (Get-Item $testPluginPath\RunAsPassword).Value | Should -Be "System.Security.SecureString"184 Clear-Item $testPluginPath\RunAsUser -WarningAction SilentlyContinue185 (Get-Item $testPluginPath\RunAsUser).Value | Should -BeNullOrEmpty186 (Get-Item $testPluginPath\RunAsPassword).Value | Should -BeNullOrEmpty187 }188 189 It "Set-Item on plugin RunAsUser should fail for invalid password" {190 #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]191 $password = ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force192 $creds = [pscredential]::new($testUser,$password)193 $exception = { Set-Item $testPluginPath\RunAsUser $creds } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand" -PassThru194 $exception.Exception.Message | Should -Match ".*$badCredentialError.*"195 }196 197 It "Set-Item on password without user on plugin should fail for <password>" -TestCases @(198 #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]199 @{password=(ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force)},200 #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]201 @{password="hello"}202 ) {203 param($password)204 Clear-Item $testPluginPath\RunAsUser -WarningAction SilentlyContinue205 { Set-Item $testPluginPath\RunAsPassword $password } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"206 }207 208 It "Set-Item on plugin XmlRenderingType property should succeed for '<type>'" -TestCases @(209 @{type="XmlReader"},210 @{type="text"},211 @{type="xMLrEADER"},212 @{type="TEXT"}213 ) {214 param ($type)215 Set-Item $testPluginPath\XmlRenderingType $type -WarningAction SilentlyContinue216 (Get-Item $testPluginPath\XmlRenderingType).Value | Should -Be $type217 }218 219 It "Set-Item on non-existent property should fail" {220 { Set-Item $testPluginPath\foo "bar" } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"221 }222 223 It "Set-Item on plugin Resource '<property>' property with '<value>' should succeed" -TestCases @(224 @{property="SupportsOptions"; value=$false; expected="False"},225 @{property="sUPPORTSoPTIONS"; value=$true; expected="True"}226 ) {227 param($property, $value, $expected)228 $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1229 Set-Item "$($resource.PSPath)\$property" $value -WarningAction SilentlyContinue230 (Get-Item "$($resource.PSPath)\$property").Value | Should -BeExactly $expected231 }232 233 It "Set-Item on plugin Security Resource '<property>' property with '<value>' should succeed" -TestCases @(234 # truncated version of the default SDDL235 @{property="Sddl"; value="O:NSG:BAD:P(A;;GA;;;BA)"},236 # default SDDL set by WinRM237 @{property="SDDL"; value="O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;IU)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)"}238 ) {239 param($property, $value, $expected)240 $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1241 $security = Get-ChildItem "$($resource.PSPath)\Security" | Select-Object -First 1242 Set-Item "$($security.PSPath)\$property" $value -WarningAction SilentlyContinue -Force243 (Get-Item "$($security.PSPath)\$property").Value | Should -Be $value244 }245 246 It "Set-Item on plugin Security Resource '<property>' property with invalid '<value>' should fail" -TestCases @(247 @{property="Sddl"; value="foo"},248 @{property="sDDL"; value="D:P(A;;GA;;;BA)"} # truncated version of default SDDL with owner removed249 ) {250 param($property, $value, $expected)251 $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1252 $security = Get-ChildItem "$($resource.PSPath)\Security" | Select-Object -First 1253 { Set-Item "$($security.PSPath)\$property" $value -Force } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"254 }255 256 It "Set-Item on plugin InitializationParameters '<property>' property with '<value>' should succeed" -TestCases @(257 @{property="PSVersion"; value="6.0.0"},258 @{property="psvERSION"; value="5.1"}259 ) {260 param($property, $value)261 Set-Item "$testPluginPath\InitializationParameters\$property" $value -WarningAction SilentlyContinue262 (Get-Item "$testPluginPath\InitializationParameters\$property").Value | Should -Be $value263 }264 265 It "Set-Item on plugin Quotas '<property>' property with '<value>' should succeed" -TestCases @(266 @{property="IdleTimeoutms"; value=61000},267 @{property="iDLEtIMEOUTMS"; value=7200000},268 @{property="MaxShells"; value=1},269 @{property="mAXsHELLS"; value=2147483647}270 ) {271 param($property, $value)272 Set-Item "$testPluginPath\Quotas\$property" $value -WarningAction SilentlyContinue273 (Get-Item "$testPluginPath\Quotas\$property").Value | Should -Be $value274 }275 276 It "Set-Item on plugin Quotas out of range on '<property>' property with '<value>' should fail" -TestCases @(277 @{property="IdleTimeoutms"; value=59999},278 @{property="MaxShells"; value=0}279 ) {280 param($property, $value)281 { Set-Item "$testPluginPath\Quotas\$property" $value -WarningAction SilentlyContinue } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"282 }283 }284 285 Context "Clear-Item tests" {286 It "Clear-Item on <property> should fail" -TestCases @(287 @{property="Filename"},288 @{property="Quotas\IdleTimeoutms"},289 @{property="InitializationParameters\PSVersion"}290 ) {291 { Clear-Item "$testPluginPath\$property" -WarningAction SilentlyContinue } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.ClearItemCommand"292 }293 }294 295 Context "New-Item and Remove-Item tests" {296 It "New-Item and Remove-Item at root should succeed" -TestCases @(297 @{name=$env:computername;expected=$env:computername},298 @{name="${env:computername}\";expected=$env:computername}299 ) {300 param($name, $expected)301 try {302 $connections = Get-ChildItem wsman:\303 $newItem = New-Item WSMan:\$name304 "WSMan:\$name" | Should -Exist305 (Get-ChildItem wsman:\).Count | Should -Be ($connections.Count + 1)306 # not a .Net type so can't use BeOfType307 $newItem.PSObject.TypeNames[0] | Should -Be "Microsoft.WSMan.Management.WSManConfigContainerElement#ComputerLevel"308 $newItem.Name | Should -Be $expected309 Remove-Item WSMan:\$name -Recurse -Force310 "WSMan:\$name" | Should -Not -Exist311 }312 finally {313 Remove-Item WSMan:\$name -Recurse -Force -ErrorAction SilentlyContinue314 }315 }316 317 It "New-Item and Remove-Item for a listener" {318 try {319 $newListener = New-Item -Path WSMan:\localhost\Listener\ -Address IP:127.0.0.1 -port 6666 -Transport HTTP -Enabled $false -HostName foo -URLPrefix bar -Force320 $listenerName = $newListener.Name321 $listenerName | Should -Not -BeNullOrEmpty322 $properties = Get-ChildItem "WSMan:\localhost\Listener\$listenerName"323 $listenerXml = [xml](winrm g winrm/config/listener?Address=IP:127.0.0.1+Transport=HTTP -format:xml)324 $expectedMissingAttributes = "cfg","xsi","lang"325 $properties.Count | Should -Be (($listenerXml.Listener | Get-Member -Type Properties).Count - $expectedMissingAttributes.Count)326 foreach ($property in $properties) {327 if (-not $property.Name.StartsWith("ListeningOn")) { # this property is represented differently328 $property.Value | Should -Be $listenerXml.Listener.$($property.Name)329 }330 }331 Remove-Item -Path "WSMan:\localhost\Listener\$listenerName" -Recurse -Force332 $newListener.PSPath | Should -Not -Exist333 }334 finally {335 Remove-Item -Path "WSMan:\localhost\Listener\$listenerName" -Recurse -Force -ErrorAction SilentlyContinue336 }337 }338 339 It "New-Item and Remove-Item for a plugin using parameters" {340 try {341 $password = ConvertTo-SecureString $testPass -AsPlainText -Force342 $creds = [pscredential]::new($testUser, $password)343 $plugin = New-Item -Plugin TestPlugin2 -UseSharedProcess -AutoRestart `344 -ProcessIdleTimeoutSec 120 -FileName "${env:windir}\system32\pwrshplugin.dll" `345 -SDKVersion 2 -Resource foo -Capability shell -XMLRenderingType text -Path WSMan:\localhost\plugin `346 -RunAsCredential $creds347 $expectedMissingProperties = @("InitializationParameters")348 Test-Plugin -Plugin $plugin -expectedMissingProperties $expectedMissingProperties349 Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force350 "WSMan:\localhost\Plugin\TestPlugin2" | Should -Not -Exist351 }352 finally {353 Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force -ErrorAction SilentlyContinue354 }355 }356 357 It "New-Item and Remove-Item for a plugin using a file" {358 $fileXml = @"359<PlugInConfiguration Name="TestPlugin2" Filename="${env:windir}\system32\pwrshplugin.dll" SDKVersion="2" XmlRenderingType="text" Enabled="false"360 Architecture="64" UseSharedProcess="true" ProcessIdleTimeoutSec="0" RunAsUser="" RunAsPassword="" AutoRestart="false" RunAsVirtualAccount="false"361 RunAsVirtualAccountGroups="" OutputBufferingMode="Block" xmlns="http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration">362 <InitializationParameters>363 <Param Name="PSVersion" Value="5.1"></Param>364 </InitializationParameters>365 <Resources>366 <Resource ResourceUri="http://schemas.microsoft.com/powershell/TestPlugin2" SupportsOptions="true" ExactMatch="true">367 <Security Uri="http://schemas.microsoft.com/powershell/TestPlugin2"368 Sddl="O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;IU)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)" ExactMatch="False"></Security>369 <Capability Type="Shell"></Capability>370 </Resource>371 </Resources>372 <Quotas MaxIdleTimeoutms="2147483646" MaxConcurrentUsers="{0}" IdleTimeoutms="6200000" MaxProcessesPerShell="2147483646"373 MaxMemoryPerShellMB="2147483646" MaxConcurrentCommandsPerShell="2147483646" MaxShells="2147483646" MaxShellsPerUser="2147483646"></Quotas>374</PlugInConfiguration>375"@376 $osInfo = [System.Environment]::OSVersion.Version377 $isSrv2k12R2 = $osInfo.Major -eq 6 -and $osInfo.Minor -eq 3378 379 # On Windows Server 2012R2 MaxConcurrentUsers is limited to 100.380 $maxConcurrentUsers = if ($isSrv2k12R2) { '50' } else { '2147483646' }381 382 $fileXml = $fileXml -f $maxConcurrentUsers383 384 Set-Content -Path $testdrive\plugin.xml -Value $fileXml385 try {386 $plugin = New-Item -Path WSMan:\localhost\Plugin -File $testdrive\plugin.xml -Name TestPlugin2387 Test-Plugin -Plugin $plugin388 Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force389 "WSMan:\localhost\Plugin\TestPlugin2\" | Should -Not -Exist390 }391 finally {392 Remove-Item "WSMan:\localhost\Plugin\TestPlugin2\" -Recurse -Force -ErrorAction SilentlyContinue393 }394 }395 396 It "New-Item and Remove-Item for a plugin resource" {397 try {398 $resource = New-Item -Path WSMan:\localhost\Plugin\TestPlugin\Resources\ `399 -ResourceUri http://foo -Capability shell400 $resource.PSPath | Should -Exist401 $properties = Get-ChildItem $resource.PSPath402 ($properties | Where-Object { $_.Name -eq "ResourceUri" }).Value | Should -Be "http://foo/"403 ($properties | Where-Object { $_.Name -eq "Capability" })[0].Value | Should -Be "shell"404 Remove-Item $resource.PSPath -Recurse -Force405 $resource.PSPath | Should -Not -Exist406 }407 finally {408 Remove-Item $resource.PSPath -Recurse -Force -ErrorAction SilentlyContinue409 }410 }411 412 It "New-Item and Remove-Item for an initialization parameter" {413 try {414 $parameter = New-Item -Path WSMan:\localhost\Plugin\TestPlugin\InitializationParameters `415 -ParamName foo -ParamValue bar416 $parameterObj = Get-Item $parameter.PSPath417 $parameterObj.Name | Should -Be "foo"418 $parameterObj.Value | Should -Be "bar"419 Remove-Item $parameter.PSPath -Force420 $parameter.PSPath | Should -Not -Exist421 }422 finally {423 Remove-Item $parameter.PSPath -Force -ErrorAction SilentlyContinue424 }425 }426 427 It "New-Item and Remove-Item for a security resource" {428 try {429 $sddl = "O:NSG:BAD:P(A;;GA;;;BA)"430 $resource = Get-ChildItem -Path WSMan:\localhost\Plugin\TestPlugin\Resources\ | Select-Object -First 1431 # remove existing security resource since the folder name is just a hash of the resource uri432 Get-ChildItem "$($resource.PSPath)\Security" | Remove-Item -Recurse -Force433 $security = New-Item "$($resource.PSPath)\Security" -SDDL $sddl -Force434 $security.PSPath | Should -Exist435 $securityObj = Get-Item $security.PSPath436 (Get-ChildItem $securityObj.PSPath | Where-Object { $_.Name -eq 'sddl' }).Value | Should -Be $sddl437 Remove-Item $security.PSPath -Recurse -Force438 $security.PSPath | Should -Not -Exist439 }440 finally {441 Remove-Item $security.PSPath -Recurse -Force -ErrorAction SilentlyContinue442 }443 }444 }445 446 Context "Get-Help tests" {447 It "Get-Help while in WSMan: drive works" {448 try {449 Push-Location WSMan:\localhost450 Get-Help New-Item | Should -Not -BeNullOrEmpty451 }452 finally {453 Pop-Location454 }455 }456 }457 458 Context 'ItemSeparator properties' {459 It 'WSMan provider has ItemSeparator properties' {460 461 (Get-PSProvider WSMan).ItemSeparator | Should -Be '\'462 (Get-PSProvider WSMan).AltItemSeparator | Should -Be '/'463 }464 465 It 'ItemSeparator properties is read-only in WSMan provider' {466 { (Get-PSProvider WSMan).ItemSeparator = $null } | Should -Throw467 { (Get-PSProvider WSMan).AltItemSeparator = $null } | Should -Throw468 }469 }470}471 