From a20db4291fcec04cd815aa44e5561dfe22c24ad6 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 19 Nov 2021 13:21:48 -0800 Subject: [PATCH 01/20] Fixed: Carbon fails to import on PowerShell 4. --- Carbon/Carbon.psd1 | 10 +++------- Carbon/Carbon.psm1 | 6 ++++-- Carbon/Functions/Grant-Permission.ps1 | 3 ++- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Carbon/Carbon.psd1 b/Carbon/Carbon.psd1 index 3450e023..6959cb82 100644 --- a/Carbon/Carbon.psd1 +++ b/Carbon/Carbon.psd1 @@ -25,7 +25,7 @@ RootModule = 'Carbon.psm1' # Version number of this module. - ModuleVersion = '2.11.0' + ModuleVersion = '2.12.0' # ID used to uniquely identify this module GUID = '075d9444-c01b-48c3-889a-0b3490716fa2' @@ -359,13 +359,9 @@ All functions are idempotent: when run multiple times with the same arguments, y # ReleaseNotes of this module ReleaseNotes = @' +# 2.12.0 -# 2.11.0 - -* Fixed: Resolve-CPathCase fails on PowerShell Core. -* New: 'Grant-Permission', 'Get-Permission', and 'Revoke-Permission' scripts now execute correctly on -non-Windows platforms. -* Fixed: Install-CService now will update services when file permissions or user account privileges have changed. +* Fixed: Importing Carbon fails under PowerShell 4. '@ } # End of PSData hashtable diff --git a/Carbon/Carbon.psm1 b/Carbon/Carbon.psm1 index c1732218..c053effb 100644 --- a/Carbon/Carbon.psm1 +++ b/Carbon/Carbon.psm1 @@ -139,7 +139,8 @@ foreach( $developerImport in $developerImports ) } # Allows us to be platform agnostic in our calls of 'GetAccessControl'. -if( -not ([IO.DirectoryInfo]::New([Environment]::CurrentDirectory) | Get-Member -Name 'GetAccessControl') ) +$currentDirInfo = New-Object -TypeName 'IO.DirectoryInfo' -ArgumentList ([Environment]::CurrentDirectory) +if( -not ($currentDirInfo | Get-Member -Name 'GetAccessControl') ) { Update-TypeData -MemberName 'GetAccessControl' -MemberType 'ScriptMethod' -TypeName 'IO.DirectoryInfo' -Value { [CmdletBinding()] @@ -151,7 +152,8 @@ if( -not ([IO.DirectoryInfo]::New([Environment]::CurrentDirectory) | Get-Member } } -if( -not ([IO.FileInfo]::New($PSCommandPath) | Get-Member -Name 'GetAccessControl') ) +$currentCmdInfo = New-Object -TypeName 'IO.FileInfo' -ArgumentList $PSCommandPath +if( -not ($currentCmdInfo | Get-Member -Name 'GetAccessControl') ) { Update-TypeData -MemberName 'GetAccessControl' -MemberType 'ScriptMethod' -TypeName 'IO.FileInfo' -Value { [CmdletBinding()] diff --git a/Carbon/Functions/Grant-Permission.ps1 b/Carbon/Functions/Grant-Permission.ps1 index da2d91c6..f7149c81 100644 --- a/Carbon/Functions/Grant-Permission.ps1 +++ b/Carbon/Functions/Grant-Permission.ps1 @@ -276,7 +276,8 @@ function Grant-CPermission return } - $grantPermissionParams = [Collections.Generic.Dictionary[[string], [object]]]::New($PSBoundParameters) + $grantPermissionParams = New-Object -TypeName 'Collections.Generic.Dictionary[[string], [object]]' ` + -ArgumentList $PSBoundParameters $grantPermissionParams.Remove('Path') foreach( $privateKeyFile in $privateKeyFiles ) From 04aae988bfdabc5d87fd522eecd723a1c5f164e4 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 19 Nov 2021 13:36:20 -0800 Subject: [PATCH 02/20] Moving release notes to CHANGELOG.md. --- RELEASE NOTES.txt => CHANGELOG.md | 186 +++++++++++++++++++++++++++++- Carbon.nuspec | 3 +- Carbon/Carbon.psd1 | 6 +- New-Website.ps1 | 4 +- Publish-Carbon.ps1 | 2 +- README.md | 3 +- whiskey.yml | 2 + 7 files changed, 190 insertions(+), 16 deletions(-) rename RELEASE NOTES.txt => CHANGELOG.md (91%) diff --git a/RELEASE NOTES.txt b/CHANGELOG.md similarity index 91% rename from RELEASE NOTES.txt rename to CHANGELOG.md index c8e51f55..17a72d93 100644 --- a/RELEASE NOTES.txt +++ b/CHANGELOG.md @@ -1,3 +1,164 @@ +# 2.12.0 + +* Fixed: Importing Carbon fails under PowerShell 4. + +# 2.11.0 + +* Fixed: Resolve-CPathCase fails on PowerShell Core. +* New: 'Grant-Permission', 'Get-Permission', and 'Revoke-Permission' scripts now execute correctly on +non-Windows platforms. +* Fixed: Install-CService now will update services when file permissions or user account privileges have changed. + + +# 2.10.2 + +* Fixed: Carbon fails to import if IIS isn't installed. + + +# 2.10.1 + +* Fixed: Carbon fails to import on PowerShell 4. + + +# 2.10.0 + +## TL;DR Changes + +* Fixed: Carbon's backward compatible aliases replaced with shim functions. Carbon no longer aggressively loads its +functions. +* New: Carbon now warns when you're using a function shim with a deprecated name. Update your code so that all Carbon +functions have a `C` prefix. Carbon has a `Use-CarbonPrefix.ps1` script in its bin directory that will update files to +use the new prefix. +* Migrated the following functions to new Carbon.Core and Carbon.Cryptography modules. These functions still exist in +Carbon 2, so if you use all these modules together, you'll probably run into naming collisions and errors depending on +how you install, import, and use Carbon. You'll get a warning if you use any of the functions that migrated. + * `ConvertTo-CBase64`, `Get-CPowerShellPath`, and `Invoke-CPowerShell` are now in the Carbon.Core module. + * The `Test-COSIs32Bit` and `Test-COSIs64Bit` functions merged into a `Test-COperatingSystem` function in the + Carbon.Core module. + * The `Test-CPowerShellIs32Bit` and `Test-CPowerShellIs64Bit` functions merged into a `Test-CPowerShell` function in + the Carbon.Core module. + * New: `Convert-CSecureStringToString`, `Get-CCertificate`, `Install-CCertificate`, `Uninstall-CCertificate`, + `Protect-CString`, and `Unprotect-CString` migrated to the Carbon.Cryptography module. +* Fixed: the `Install-CCertificate` function causes an extra file to be written to the Windows directory where private +keys are saved. Depending on your environment, this could put many, many extra very small files on the file system or a +full disk. +* Fixed: the `Install-CCertificate` function could fail to install a certificate with a private key in a remote +computer's LocalMachine store if you passed in a certificate object to install. +* Fixed: the `Install-CCertificate` function always installs a certificate even if it exists in the destination store. +Depending on your environment, this could put many, many extra very small files on the file system or a full disk. Use +the `-Force` switch to always install a certificate even if it already exists in the destination store. +* Added a `-Force` switch to the `Install-CCertificate` function to force certificates to be installed if they already +exist in the destination store. +* Fixed: `Install-Service` always writes a verbose message when installing a service. + +## Naming Collisions Solved (Again) + +Fixed: In Carbon 2.7.0, we added a `C` prefix to all the Carbon functions, with aliases that used the old function +names to preserve backwards-compatability. We didn't realize at the time that aliases have the highest precedence of +commands, so Carbon's aliases hid any other commands on your system that may have been named the same. Bad idea. With +this release, Carbon no longer uses aliases for backwards-compatability. Instead, it dynamically creates shim functions +named after the old functions. These shim functions write a warning that the function with the old name is deprecated +then calls the function using its new name. Hopefully, this will finally fix the name collisions problems. The function +names with out the `C` prefix will be removed in Carbon 3, so update your code to make upgrading easier. +Because Carbon creates these backwards-compatible function shims dynamically, Carbon *won't* create a shim if a +function with the old name exists. If there is a name conflict between Carbon and another module, if you import that +module first, Carbon won't export its shim function. + +## Carbon on PowerShell Core + +We need parts of Carbon to work on PowerShell Core. The current size of Carbon makes that hard (over 200 functions and +automated tests that take a long time). So, we're breaking Carbon into smaller modules. The new modules will all require +PowerShell 5.1+. If you use Carbon 2 and the new modules together, you'll get naming conflicts during installation and +when importing. +The first two modules are already out: Carbon.Core and Carbon.Cryptography. + +## Carbon.Core +Carbon.Core will contain all the functions that are foundational to all or most other future Carbon modules, or generic +functions we feel are core to Carbon and/or PowerShell. It has no dependencies. The following functions were migrated to +it: +* `ConvertTo-CBase64` (with some added functionality) +* `Get-CPowerShellPath` +* `Invoke-CPowerShell` +* `Test-COperatingSystem`: Replaces `Test-OSIs32Bit` and `Test-OSIs64Bit`. Tests operating system type, too, so you +can use this function instead of the `$IsWindows`, `$IsLinux`, or `$IsMacOS` variables. Works on versions of PowerShell +that don't define those variables. +* `Test-CPowerShell`: Replaces `Test-PowerShellIs32Bit` and `Test-PowerShellIs64Bit`. Tests edition, too. Use this +function instead of `$PSVersionTable.PSEdition`. Handles when $PSVersionTable doesn't have the PSEdition property. + +## Carbon.Cryptography +Carbon.Crytography contains functions that are used when encrypting and decrypting strings. This is where certificate +management funtions live. These function were migrated from Carbon: +* `Convert-CSecureStringToString` +* `Get-CCertificate`: works on Linux and macOS when opening certificate files. +* `Install-CCertificate` +* `Uninstall-CCertificate` +* `Protect-CString`: works on Linux and macOS. +* `Unprotect-CString`: works on Linux and macOS. + + +# 2.9.4 + +* Fixed: Convert-XmlFile fails in PowerShell Core (thanks to +(Joseph Block)[https://github.com/JosephBlock] for the fix). + + +# 2.9.3 + +* Fixed: Protect-CString and Unprotect-CString failed under PowerShell Core. +* Fixed: Invoke-CPowerShell failed under PowerShell Core. +* Fixed: Install-CCertificate fails under PowerShell Core. +* Fixed: Unprotect-CString adds extra null bytes to the end of a decrypted string when using AES (`-Key`) encryption. + + +# 2.9.2 + +* Fixed: when encryptiong/decrypting with a thumbprint, `Protect-String` and `Unprotect-String` take more time the more +certificates you have in your stores. + + +# 2.9.1 + +* Fixed: `Import-Carbon.ps1` fails if Carbon is already imported from a different location than the location from which +it will import Carbon. + + +# 2.9.0 + +* Carbon should now import in less than a second. +* Fixed: `Grant-CHttpUrlPermission` documentation uses command named `Grant-CHttpUrlAclPermission`. (Fixes +[issue 66](https://github.com/webmd-health-services/Carbon/issues/66).) +* Fixed: `Enable-CNtfsCompression` always enables compression even if compression is already enabled. +* Fixed: `Disable-CNtfsCompression` always disables compression even if compression is already disabled. +* Fixed: `Uninstall-CService` can write an error when a service's process exits at unexpected times. +* Fixed: `Get-CUser` can sometimes take 60 to 90 seconds to lookup a specific user. +* Fixed: `Get-CGroup` can sometimes take 60 to 90 seconds to lookup a specific group. +* Improved `Set-CEnvironmentVariable` and `Remove-CEnvironmentVariable` functions' reliability when setting and removing +variables for a specific user (they now use `Start-Job` instead of Carbon's `Invoke-CPowerShell`). +* Fixed: Carbon was hiding the ServerManager module's `Get-WindowsFeature`, `Install-WindowsFeature`, and +`Uninstall-WindowsFeature` cmdlets (fixes issue #55). +* Fixed: `Set-CHostsEntry` can sometimes clear the hosts file (fixes issue #39). +* Fixed: `Get-CServiceConfiguration` fails with a terminating exception if a service doesn't exist. + + +# 2.8.1 + +* Added verification information to Chocolatey package. +* Updated copyright. + + +# 2.8.0 + +* Carbon is now *importable* on PowerShell Core on all platforms. Most functions will not work on Linux/MacOS since they +are Windows-specific. Many functions will also not work on PowerShell Core. The next major version of Carbon, 3, should +fully support PowerShell Core on Windows. +* `Get-CScheduledTask` can now return `RegisteredTask` objects from the Scheduler.Service COM API. Use the new +`AsComObject` switch. Getting COM objects is an order of magnitude faster than the old way. +* Fixed: `Get-CScheduledTask` isn't able to parse some task information returned on Windows 10. +* Deprecated `Test-CWindowsFeature`. +* Fixed: `Get-CComPermission` fails when there are permission to a non-existent identity. +* Fixed: looking up local users/groups is extremely slow on some machines. + + # 2.7.0 * Uninstall-Service now kills a service's process when that service stops but is actually still running. This should decrease the frequency of needing to reboot a computer when uninstalling a service. @@ -6,6 +167,7 @@ * `Get-CCertificate`: Added `Path` note property to returned objects. * Fixed: Chocolatey uninstaller fails if the `PSModulePath` environment variable contains trailing or sequential semicolons. + # 2.6.0 * `Enable-IisSecurityAuthentication` and `Disable-IisSecurityAuthentication` sometimes hang. We don't know why, but we're working around the problem. These functions no longer always apply a configuration change. Instead, they only enable/disable security authentication if its not already enabled/disabled. @@ -13,6 +175,7 @@ * Added `ArgumentList` property/parameter to `Carbon_Service` DSC resource. Thanks to [Luigi Grilli](https://github.com/gigi81) for the contribution. * Fixed: `Get-HttpUrlAcl` returns no ACLs if any ACLs exist whose identities no longer exist. + # 2.5.1, 2.5.2, 2.5.3, and 2.5.4 (3 June 2018) *Note*: 2.5.1 through 2.5.4 contain the same code and changes. We created new build and deployment automation that, due to bugs, required us to publish multiple versions. @@ -23,6 +186,7 @@ * Import-Carbon.ps1 now hides verbose messages typically shown by Import-Module and Remove-Module cmdlets. * Fixed: `Assert-FirewallConfigurable` fails on Windows 10 due to firewall service display name change. + # 2.5.0 (18 June 2017) ## Enhancements @@ -44,7 +208,7 @@ * Fixed: Importing Carbon in 32-bit PowerShell fails on a 64-bit operating system. DSC isn't available so the `Initialize-Lcm` function can't be exported. Thanks to [Anders Andersson](https://bitbucket.org/McAndersDK/) for contribuging the fix. * Fixed: `Install-Service` and `Carbon_Service` DSC resource fail to change the identity a service runs as if switching from a custom account to the default `NetworkService` account. * Fixed: `Get-PowerShellModuleInstallPath` returns nothing when run under 32-bit (x86) PowerShell on 64-bit Windows.Fixed: `Get-PowerShellModuleInstallPath` returns nothing when run under 32-bit (x86) PowerShell on 64-bit Windows. - + # 2.4.1 (21 February 2017) @@ -220,8 +384,7 @@ * Fixed: errors importing Carbon when IIS not installed on Windows 2012 R2 and Windows 10 (fixes [issue 168: Cannot import Carbon 2.0 module due to issues with IIS related functionality](https://bitbucket.org/splatteredbits/carbon/issues/168)). * Fixed Carbon copyright statements. * Improved Carbon's module description. - - + # 2.0.0 (10 October 2015) @@ -547,7 +710,8 @@ The following functions were re-written to use the `System.DirectoryServices.Acc * Deprecated `Quiet` switch. * Only sets value if the value is changed. Use the `Force` parameter to preserve previous behavior. * `Uninstall-Service` no longer returns sc.exe stdout. - + + # 1.9.0 (8 November 2014) This is the last minor release for version 1.0. Future 1.0-compatible releases will *only* contain bug fixes, no new features. It takes too much time to maintain two versions, and I'd rather spend my time getting 2.0 out the door. Carbon 2.0 will require PowerShell 4.0, so start planning. @@ -604,7 +768,7 @@ This is the last minor release for version 1.0. Future 1.0-compatible releases w * `Install-Service` wasn't restarting a manual service if it was running when configuration began. * `Uninstall-Service` hard codes the path to the Windows directory (fixes issue [#143](https://bitbucket.org/splatteredbits/carbon/issue/143/uninstall-service-script-has-hard-coded)). Thanks to [Travis Mathison](https://bitbucket.org/tdmathison) for the fix. - + # 1.8.0 (7 September 2014) ## Enhancements @@ -776,7 +940,7 @@ This is the last minor release for version 1.0. Future 1.0-compatible releases w * The `Carbon.Identity.FindByName` method and the `Resolve-IdentityName` and `Test-Identity` functions now handle identity names with `.` for the domain/machine name, e.g. `.\Administrator`. * The `Carbon.Identity.FullName` property returns the wrong value when domain is empty/null, e.g. `Resolve-IdentityName -Name 'Everyone'` returns `\Everyone`, when it should return `Everyone`. * The `Carbon.Identity.FindByName` method and the `Resolve-IdentityName` and `Test-Identity` functions unable to resolve `LocalSystem` account (which is actually `NT AUTHORITY\SYSTEM`). - + # 1.7.0 (30 April 2014) @@ -819,6 +983,7 @@ There is now [a Carbon support mailing list](https://groups.google.com/forum/#!f * `Grant-Permission` doesn't handle non-existent paths, causing cascading errors. * `Test-Permission` always returns `$false` when testing leaf-level permissions and the `ApplyTo` parameter is provided, i.e. it doesn't ignore inheritance/propagation flags on leaves. + # 1.6.0 (1 February 2014) ## Bug Fixes @@ -1269,6 +1434,7 @@ There is now [a Carbon support mailing list](https://groups.google.com/forum/#!f * Added `Uninstall-WindowsFeatures` alias for `Uninstall-WindowsFeature`, for backwards-compatibility with earlier releases. * Added `Features` alias for `Uninstall-WindowsFeature's` `Name` parameter, for backwards-compatibility with earlier releases. + # 0.5.0.0 (7 January 2013) ## Upgrade Instructions @@ -1488,6 +1654,7 @@ Replace usages of: ## Bug fixes * `Enable-IisSsl` not setting SSL flags correctly when requiring client certificates. + # 0.4.0.0 (17 November 2012) ## Upgrade Instructions @@ -1542,6 +1709,7 @@ Replace usages of: * Added a `Quiet` parameter to `Set-RegistryKeyValue` so that `Write-Host` output is muffled. * Created `Reset-MsmqQueueManagerID` function, which resets MSMQ's Queue Manager ID. + # 0.3.0 (28 September 2012) ## Upgrade Instructions @@ -1592,6 +1760,7 @@ If you call `Invoke-PowerShell` without the `x86` switch and PowerShell is 32-bi * `Unprotect-AclAccessRules`: Turns off inherited access rules on an item in the file system or registry. * Added a `Clear` parameter to the `Grant-Permissions` function for clearing any non-inherited permissions on a file system/registry item. + # 0.2.6 (30 June 2012) ## Enhancements @@ -1629,6 +1798,7 @@ If you call `Invoke-PowerShell` without the `x86` switch and PowerShell is 32-bi ## Bug fixes * `Install-IisWebsite` now validates website bindings + # 0.2.5 (29 June 2012) ## Enhancements @@ -1700,6 +1870,7 @@ If you call `Invoke-PowerShell` without the `x86` switch and PowerShell is 32-bi * Set-IisWebsiteSslCertifiate * Set-IisWindowsAuthentication + # 0.2.3 (27 June 2012) ## Enhancements @@ -1721,6 +1892,7 @@ If you call `Invoke-PowerShell` without the `x86` switch and PowerShell is 32-bi * Invoke-WindowsInstaller doesn't validate that installer path ends in '.msi'. * Invoke-WindowsInstaller not showing correct exit code when installation fails. + # 0.2.2 (19 June 2012) ## Enhancements @@ -1731,12 +1903,14 @@ If you call `Invoke-PowerShell` without the `x86` switch and PowerShell is 32-bi * Add-GroupMembers fails when adding built-in accounts multiple times. * Add-GroupMembers fails to add domain user to a local group. + # 0.2.1 (28 April 2012) * Added IsJunction property to DirectoryInfo objects. Returns true if a directory is a junction/reparse point. * Created a Carbon assembly for compiled code. Moved P/Invoke functions from FileSystem.ps1 into assembly. This is a backwards compatible change. * Created a Carbon.IO.JunctionPoint helper class for creating/removing/getting junction/reparse points. Updated New-Junction and Remove-Junction to use the new helper class. * Added TargetPath property to DirectoryInfo objects. If the directory is a junction/reparse points, returns the path to the junction's target. Otherwise, $null. + # 0.2.0 (4 April 2012) ## Enhancements diff --git a/Carbon.nuspec b/Carbon.nuspec index ae96e6c5..ec651e55 100644 --- a/Carbon.nuspec +++ b/Carbon.nuspec @@ -55,6 +55,7 @@ All functions are idempotent: when run multiple times with the same arguments, y - + + \ No newline at end of file diff --git a/Carbon/Carbon.psd1 b/Carbon/Carbon.psd1 index 6959cb82..b61e8cc2 100644 --- a/Carbon/Carbon.psd1 +++ b/Carbon/Carbon.psd1 @@ -358,11 +358,7 @@ All functions are idempotent: when run multiple times with the same arguments, y Prerelease = '' # ReleaseNotes of this module - ReleaseNotes = @' -# 2.12.0 - -* Fixed: Importing Carbon fails under PowerShell 4. -'@ + ReleaseNotes = 'https://github.com/webmd-health-services/Carbon/blob/master/CHANGELOG.md' } # End of PSData hashtable } # End of PrivateData hashtable diff --git a/New-Website.ps1 b/New-Website.ps1 index b5425da4..bd8a46f9 100644 --- a/New-Website.ps1 +++ b/New-Website.ps1 @@ -143,10 +143,10 @@ Get-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Carbon\en-US\about_Car } | Out-HtmlPage -Title $carbonTitle -VirtualPath '/index.html' -Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath 'RELEASE NOTES.txt') -Raw | +Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath 'CHANGLOG.md') -Raw | Edit-HelpText -ModuleName 'Carbon' | Convert-MarkdownToHtml | - Out-HtmlPage -Title ('Release Notes - {0}' -f $carbonTitle) -VirtualPath '/releasenotes.html' + Out-HtmlPage -Title ('CHANGELOG - {0}' -f $carbonTitle) -VirtualPath '/changelog.html' Copy-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Tools\Silk\Resources\silk.css' -Resolve) ` -Destination $WebRoot -Verbose \ No newline at end of file diff --git a/Publish-Carbon.ps1 b/Publish-Carbon.ps1 index f3f3818b..e168ac57 100644 --- a/Publish-Carbon.ps1 +++ b/Publish-Carbon.ps1 @@ -25,7 +25,7 @@ Set-StrictMode -Version Latest $licenseFileName = 'LICENSE.txt' $noticeFileName = 'NOTICE.txt' -$releaseNotesFileName = 'RELEASE NOTES.txt' +$releaseNotesFileName = 'CHANGELOG.md' $releaseNotesPath = Join-Path -Path $PSScriptRoot -ChildPath $releaseNotesFileName -Resolve $manifestPath = Join-Path -Path $PSScriptRoot -ChildPath 'Carbon\Carbon.psd1' diff --git a/README.md b/README.md index 864fbf69..6a88fe12 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ -Carbon is a PowerShell module for automating the configuration and setup of Windows workstations and servers. More information is available at http://get-carbon.org. +Carbon is a PowerShell module for automating the configuration and setup of Windows workstations and servers. More +information is available at http://get-carbon.org. Contributions are welcomed and encouraged! \ No newline at end of file diff --git a/whiskey.yml b/whiskey.yml index 4be070b5..fb9e89d1 100644 --- a/whiskey.yml +++ b/whiskey.yml @@ -81,6 +81,8 @@ Build: Path: - LICENSE.txt - NOTICE.txt + - README.md + - CHANGELOG.md DestinationDirectory: Carbon - NuGetPack: Path: Carbon.nuspec From 1d446c95dd80dfd59314388a413796e731997b4c Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 19 Nov 2021 15:01:23 -0800 Subject: [PATCH 03/20] Install-CMsi, Get-CMsi, and Get-CProgramInstallInfo moved to new Carbon.Windows.Installer module. --- CHANGELOG.md | 5 + Carbon/Carbon.psm1 | 110 ++- Carbon/Carbon.psm1.Import.Post.ps1 | 9 +- Carbon/Functions/Complete-Job.ps1 | 2 +- Carbon/Functions/Compress-Item.ps1 | 5 +- .../Convert-SecureStringToString.ps1 | 5 +- Carbon/Functions/ConvertTo-Base64.ps1 | 4 +- Carbon/Functions/Get-Certificate.ps1 | 4 +- Carbon/Functions/Get-Msi.ps1 | 10 +- Carbon/Functions/Get-PowershellPath.ps1 | 4 +- Carbon/Functions/Get-ProgramInstallInfo.ps1 | 8 +- Carbon/Functions/Get-WindowsFeature.ps1 | 6 +- Carbon/Functions/Install-Certificate.ps1 | 4 +- Carbon/Functions/Install-Msi.ps1 | 26 +- Carbon/Functions/Install-Msmq.ps1 | 2 +- Carbon/Functions/Install-WindowsFeature.ps1 | 4 +- Carbon/Functions/Invoke-PowerShell.ps1 | 4 +- Carbon/Functions/Protect-String.ps1 | 4 +- Carbon/Functions/Resolve-NetPath.ps1 | 3 +- .../Functions/Resolve-WindowsFeatureName.ps1 | 2 +- Carbon/Functions/Test-OSIs32Bit.ps1 | 6 +- Carbon/Functions/Test-OSIs64Bit.ps1 | 6 +- Carbon/Functions/Test-PowerShellIs32Bit.ps1 | 6 +- Carbon/Functions/Test-PowerShellIs64Bit.ps1 | 6 +- Carbon/Functions/Test-WindowsFeature.ps1 | 2 +- Carbon/Functions/Uninstall-Certificate.ps1 | 5 +- Carbon/Functions/Uninstall-WindowsFeature.ps1 | 4 +- Carbon/Functions/Unprotect-String.ps1 | 4 +- Carbon/Functions/Write-File.ps1 | 5 +- Source/Carbon.Installer.sln | 37 - .../CarbonTestInstaller.vdproj | 681 ---------------- ...arbonTestInstallerWithCustomActions.vdproj | 771 ------------------ Source/Compile-CarbonTestInstaller.ps1 | 47 -- Source/Computer/ProgramInstallInfo.cs | 1 + Source/Msi/MsiInfo.cs | 1 + Test/Get-ProgramInstallInfo.Tests.ps1 | 206 ----- Test/Install-Msi.Tests.ps1 | 201 ----- Test/MSI/Test-GetMsi.ps1 | 79 -- whiskey.yml | 6 - 39 files changed, 172 insertions(+), 2123 deletions(-) delete mode 100644 Source/Carbon.Installer.sln delete mode 100644 Source/CarbonTestInstaller/CarbonTestInstaller.vdproj delete mode 100644 Source/CarbonTestInstallerWithCustomActions/CarbonTestInstallerWithCustomActions.vdproj delete mode 100644 Source/Compile-CarbonTestInstaller.ps1 delete mode 100644 Test/Get-ProgramInstallInfo.Tests.ps1 delete mode 100644 Test/Install-Msi.Tests.ps1 delete mode 100644 Test/MSI/Test-GetMsi.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 17a72d93..64c8a45d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # 2.12.0 * Fixed: Importing Carbon fails under PowerShell 4. +* The `Install-CMsi`, `Get-CMsi`, and `Get-CProgramInstallInfo` functions have moved to a new `Carbon.Windows.Installer` +module, now available on the PowerShell Gallery. Please switch to the new module and update usages. If you use these +functions from Carbon, a warning message will be written. These function will be removed in the next major version of +Carbon. + # 2.11.0 diff --git a/Carbon/Carbon.psm1 b/Carbon/Carbon.psm1 index c053effb..70c03b6e 100644 --- a/Carbon/Carbon.psm1 +++ b/Carbon/Carbon.psm1 @@ -102,24 +102,120 @@ Get-ChildItem -Path (Join-Path -Path $functionRoot -ChildPath '*') -Filter '*.ps . $_.FullName } -function Write-CWarningOnce +function Write-CObsoleteCommandWarning { [CmdletBinding()] param( - [Parameter(Mandatory,Position=0)] - [String]$Message + [Parameter(Mandatory)] + [String] $CommandName, + + [String] $NewCommandName, + + [String] $NewModuleName, + + [switch] $NewCommandBuiltin ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + + $msg = "Carbon's ""$($CommandName)"" function is OBSOLETE and will be removed in the next major version of Carbon." + + if( $NewModuleName -and $NewCommandName ) + { + $msg = "$($msg) Use the ""$($NewCommandName)"" command in the ""$($ModuleName)"" module instead." + } + elseif( $NewModuleName ) + { + $msg = "$($msg) Use commands in the ""$($ModuleName)"" module instead." + } + elseif( $NewCommandName ) + { + $builtinMsg = 'the ' + if( $NewCommandBuiltin ) + { + $builtinMsg = 'PowerShell''s ' + } - if( $script:warnings[$Message] ) + $msg = "$($msg) Use $($builtinMsg)""$($NewCommandName)"" command instead." + } + else + { + $msg = "$($msg) Remove usages." + } + + Write-CWarningOnce -Message $msg +} + +function Write-CRefactoredCommandWarning +{ + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $CommandName, + + [Parameter(Mandatory)] + [String] $ModuleName, + + [String] $NewCommandName + ) + + Set-StrictMode -Version 'Latest' + Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + + $msg = "Carbon's ""$($CommandName)"" function MOVED to new ""$($ModuleName)"" module" + if( $NewCommandName ) { - return + $msg = "$($msg) and renamed ""$($NewCommandName)""" } - Write-Warning -Message $Message - $script:warnings[$Message] = $true + $msg = "$($msg). ""$($CommandName)"" will be removed from the next major version of Carbon. Switch to the new " + + """$($ModuleName)"" module, available on the PowerShell Gallery." + + Write-CWarningOnce -Message $msg +} + +function Write-CRenamedCommandWarning +{ + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $CommandName, + + [Parameter(Mandatory)] + [String] $NewCommandName + ) + + Set-StrictMode -Version 'Latest' + Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + + $msg = "Carbon's ""$($CommandName)"" function RENAMED to ""$($NewCommandName)"". The old ""$($CommandName)"" " + + "function will be removed from the next major version of Carbon. Update usages." + Write-CWarningOnce -Message $msg +} + + +function Write-CWarningOnce +{ + [CmdletBinding()] + param( + [Parameter(Mandatory, Position=0, ParameterSetName='Message', ValueFromPipeline)] + [String] $Message + ) + + process + { + Set-StrictMode -Version 'Latest' + Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + + if( $script:warnings[$Message] ) + { + return + } + + Write-Warning -Message $Message + $script:warnings[$Message] = $true + } } $developerImports = & { diff --git a/Carbon/Carbon.psm1.Import.Post.ps1 b/Carbon/Carbon.psm1.Import.Post.ps1 index a014edd5..2c2b43d4 100644 --- a/Carbon/Carbon.psm1.Import.Post.ps1 +++ b/Carbon/Carbon.psm1.Import.Post.ps1 @@ -151,14 +151,7 @@ begin Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet `$PSCmdlet -SessionState `$ExecutionContext.SessionState - if( -not `$script:warnings['$($oldFunctionName)'] ) - { - `$msg = "The Carbon module's ""$($oldFunctionName)"" function was renamed to ""$($functionName)"". Please update " + - "your code to use the new ""$($functionName)"" name. The old ""$($oldFunctionName)"" function will be " + - 'removed in the next major version of Carbon.' - Write-CWarningOnce -Message `$msg - `$script:warnings['$($oldFunctionName)'] = `$true - } + Write-CRenamedCommandWarning -CommandName `$MyInvocation.MyCommand.Name -NewCommandName '$($functionName)' } process diff --git a/Carbon/Functions/Complete-Job.ps1 b/Carbon/Functions/Complete-Job.ps1 index e9ad81f1..faeb4d52 100644 --- a/Carbon/Functions/Complete-Job.ps1 +++ b/Carbon/Functions/Complete-Job.ps1 @@ -29,7 +29,7 @@ function Complete-CJob Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce ('Complete-CJob is obsolete and will be removed in a future major version of Carbon. Use PowerShell''s `Wait-Job` cmdlet instead.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name -NewCommandName 'Wait-Job' $errorAction = 'Continue' $params = $PSBoundParameters diff --git a/Carbon/Functions/Compress-Item.ps1 b/Carbon/Functions/Compress-Item.ps1 index 4407064d..a24a8ca2 100644 --- a/Carbon/Functions/Compress-Item.ps1 +++ b/Carbon/Functions/Compress-Item.ps1 @@ -244,10 +244,7 @@ function Compress-Item Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState - $msg = "The Carbon module's ""Compress-Item"" function was renamed to ""Compress-CItem"". Please update " + - "your code to use the new ""Compress-CItem"" name. The old ""Compress-Item"" function will be " + - 'removed in the next major version of Carbon.' - Write-CWarningOnce -Message $msg + Write-CRenamedCommandWarning -CommandName $MyInvocation.MyCommand.Name -NewCommandName 'Compress-CItem' $paths = New-Object 'Collections.ArrayList' } diff --git a/Carbon/Functions/Convert-SecureStringToString.ps1 b/Carbon/Functions/Convert-SecureStringToString.ps1 index ca1e9ca6..533a44d5 100644 --- a/Carbon/Functions/Convert-SecureStringToString.ps1 +++ b/Carbon/Functions/Convert-SecureStringToString.ps1 @@ -31,10 +31,7 @@ function Convert-CSecureStringToString if( -not $NoWarn ) { - $msg = 'Carbon''s "Convert-CSecureStringToString" function is OBSOLETE and will be removed in the next major ' + - 'version of Carbon. Use the "Convert-CSecureStringToString" function in the new "Carbon.Cryptography"' + - 'module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } $stringPtr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString) diff --git a/Carbon/Functions/ConvertTo-Base64.ps1 b/Carbon/Functions/ConvertTo-Base64.ps1 index dda0acc0..1b821773 100644 --- a/Carbon/Functions/ConvertTo-Base64.ps1 +++ b/Carbon/Functions/ConvertTo-Base64.ps1 @@ -51,9 +51,7 @@ function ConvertTo-CBase64 if( -not $NoWarn ) { - $msg = 'Carbon''s "ConvertTo-CBase64" function is OBSOLETE and will be removed in the next major version ' + - 'of Carbon. Use the "ConvertTo-CBase64" function in the new Carbon.Core module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -NewModuleName 'Carbon.Core' } } diff --git a/Carbon/Functions/Get-Certificate.ps1 b/Carbon/Functions/Get-Certificate.ps1 index d29fe87d..e4a22af1 100644 --- a/Carbon/Functions/Get-Certificate.ps1 +++ b/Carbon/Functions/Get-Certificate.ps1 @@ -98,9 +98,7 @@ function Get-CCertificate if( -not $NoWarn ) { - $msg = 'Carbon''s "Get-CCertificate" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the "Get-CCertificate" function in the new "Carbon.Cryptography" module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } function Add-PathMember diff --git a/Carbon/Functions/Get-Msi.ps1 b/Carbon/Functions/Get-Msi.ps1 index b162edfb..74e1a612 100644 --- a/Carbon/Functions/Get-Msi.ps1 +++ b/Carbon/Functions/Get-Msi.ps1 @@ -36,18 +36,18 @@ function Get-CMsi [CmdletBinding()] [OutputType('Carbon.Msi.MsiInfo')] param( - [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] - [Alias('FullName')] - [string[]] # Path to the MSI file whose information to retrieve. Wildcards supported. - $Path + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Alias('FullName')] + [string[]] $Path ) begin { Set-StrictMode -Version 'Latest' - Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState + + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Windows.Installer' } process diff --git a/Carbon/Functions/Get-PowershellPath.ps1 b/Carbon/Functions/Get-PowershellPath.ps1 index 140ef239..ad7b013c 100644 --- a/Carbon/Functions/Get-PowershellPath.ps1 +++ b/Carbon/Functions/Get-PowershellPath.ps1 @@ -44,9 +44,7 @@ function Get-CPowershellPath if( -not $NoWarn ) { - $msg = 'Carbon''s "Get-CPowershellPath" function is OBSOLETE and will be removed in the next major version ' + - 'of Carbon. Use the "Get-CPowerShellPath" function in the new Carbon.Core module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Core' } $psPath = $PSHOME diff --git a/Carbon/Functions/Get-ProgramInstallInfo.ps1 b/Carbon/Functions/Get-ProgramInstallInfo.ps1 index 20973208..03e96b47 100644 --- a/Carbon/Functions/Get-ProgramInstallInfo.ps1 +++ b/Carbon/Functions/Get-ProgramInstallInfo.ps1 @@ -36,15 +36,17 @@ function Get-CProgramInstallInfo [CmdletBinding()] [OutputType([Carbon.Computer.ProgramInstallInfo])] param( - [string] # The name of a specific program to get. Wildcards supported. - $Name + [string] $Name ) Set-StrictMode -Version 'Latest' - Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -ModuleName 'Carbon.Windows.Installer' ` + -NewCommandName 'Get-CInstalledProgram' + if( -not (Test-Path -Path 'hku:\') ) { $null = New-PSDrive -Name 'HKU' -PSProvider Registry -Root 'HKEY_USERS' diff --git a/Carbon/Functions/Get-WindowsFeature.ps1 b/Carbon/Functions/Get-WindowsFeature.ps1 index 486e582c..79820ee3 100644 --- a/Carbon/Functions/Get-WindowsFeature.ps1 +++ b/Carbon/Functions/Get-WindowsFeature.ps1 @@ -52,8 +52,10 @@ if( -not (Get-Command -Name 'Get-WindowsFeature*' | Where-Object { $_.ModuleName Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - - Write-CWarningOnce -Message ('Get-CWindowsFeature is obsolete and will be removed in a future major version of Carbon.') + + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -NewCommandName 'Get-WindowsFeature' ` + -NewModuleName 'ServerManager' if( -not (Assert-WindowsFeatureFunctionsSupported) ) { diff --git a/Carbon/Functions/Install-Certificate.ps1 b/Carbon/Functions/Install-Certificate.ps1 index 68f198d2..12197c86 100644 --- a/Carbon/Functions/Install-Certificate.ps1 +++ b/Carbon/Functions/Install-Certificate.ps1 @@ -98,9 +98,7 @@ function Install-CCertificate if( -not $NoWarn ) { - $msg = 'Carbon''s "Install-CCertificate" function is OBSOLETE and will be removed in the next major version ' + - 'of Carbon. Use the "Install-CCertificate" function in the new "Carbon.Cryptography" module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } if( $Password -and $Password -isnot [securestring] ) diff --git a/Carbon/Functions/Install-Msi.ps1 b/Carbon/Functions/Install-Msi.ps1 index 1b4aae65..9c8e9e33 100644 --- a/Carbon/Functions/Install-Msi.ps1 +++ b/Carbon/Functions/Install-Msi.ps1 @@ -22,31 +22,31 @@ function Install-CMsi Demonstrates how to pipe MSI files into `Install-CMsi` for installation. #> - [CmdletBinding(SupportsShouldProcess=$true)] + [CmdletBinding(SupportsShouldProcess)] param( - [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] - [Alias('FullName')] - [string[]] # The path to the installer to run. Wildcards supported. - $Path, + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Alias('FullName')] + [String[]] $Path, - [Parameter(DontShow=$true)] - [Switch] # OBSOLETE. Installers are run in quiet mode by default. This switch will be removed in a future major version of Carbon. - $Quiet, + [Parameter(DontShow)] + [switch] $Quiet, - [Switch] # Install the MSI even if it has already been installed. Will cause a repair/reinstall to run. - $Force + [switch] $Force ) Set-StrictMode -Version 'Latest' - Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - if( $PSBoundParameters.ContainsKey( 'Quiet' ) ) + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Windows.Installer' + + if( $PSBoundParameters.ContainsKey('Quiet') ) { - Write-CWarningOnce ('Install-CMsi''s `Quiet` switch is obsolete and will be removed in a future major version of Carbon. Installers are run in quiet mode by default. Please remove usages of the `Quiet` switch.') + $msg = 'Install-CMsi''s `Quiet` switch is obsolete and will be removed in the next major version of Carbon. ' + + 'Installers are now run in quiet mode by default. Remove usages of the `Quiet` switch.' + Write-CWarningOnce -Message $msg } Get-CMsi -Path $Path | diff --git a/Carbon/Functions/Install-Msmq.ps1 b/Carbon/Functions/Install-Msmq.ps1 index c696c749..b8e13d70 100644 --- a/Carbon/Functions/Install-Msmq.ps1 +++ b/Carbon/Functions/Install-Msmq.ps1 @@ -40,7 +40,7 @@ function Install-CMsmq Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce -Message ('Install-CMsmq is obsolete and will be removed in a future major version of Carbon.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name $optionalArgs = @{ } if( $HttpSupport ) diff --git a/Carbon/Functions/Install-WindowsFeature.ps1 b/Carbon/Functions/Install-WindowsFeature.ps1 index 673ccee0..2c8810e9 100644 --- a/Carbon/Functions/Install-WindowsFeature.ps1 +++ b/Carbon/Functions/Install-WindowsFeature.ps1 @@ -74,7 +74,9 @@ if( -not (Get-Command -Name 'Get-WindowsFeature*' | Where-Object { $_.ModuleName Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce -Message ('Install-CWindowsFeature is obsolete and will be removed in a future major version of Carbon.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -NewCommandName 'Install-WindowsFeature' ` + -NewModuleName 'ServerManager' if( -not (Assert-WindowsFeatureFunctionsSupported) ) { diff --git a/Carbon/Functions/Invoke-PowerShell.ps1 b/Carbon/Functions/Invoke-PowerShell.ps1 index 7ad61231..527eda56 100644 --- a/Carbon/Functions/Invoke-PowerShell.ps1 +++ b/Carbon/Functions/Invoke-PowerShell.ps1 @@ -154,9 +154,7 @@ function Invoke-CPowerShell if( -not $NoWarn ) { - $msg = 'Carbon''s "Invoke-CPowerShell" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the "Invoke-CPowerShell" function in the new Carbon.Core module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Core' } $powerShellv3Installed = Test-Path -Path HKLM:\SOFTWARE\Microsoft\PowerShell\3 diff --git a/Carbon/Functions/Protect-String.ps1 b/Carbon/Functions/Protect-String.ps1 index b4ccb13b..68602532 100644 --- a/Carbon/Functions/Protect-String.ps1 +++ b/Carbon/Functions/Protect-String.ps1 @@ -158,9 +158,7 @@ filter Protect-CString if( -not $NoWarn ) { - $msg = 'Carbon''s "Protect-CString" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the "Protect-CString" function in the new "Carbon.Cryptography" module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } Add-Type -AssemblyName 'System.Security' diff --git a/Carbon/Functions/Resolve-NetPath.ps1 b/Carbon/Functions/Resolve-NetPath.ps1 index 539aaa77..2ba779cd 100644 --- a/Carbon/Functions/Resolve-NetPath.ps1 +++ b/Carbon/Functions/Resolve-NetPath.ps1 @@ -18,10 +18,9 @@ function Resolve-CNetPath ) Set-StrictMode -Version 'Latest' - Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce ('Resolve-CNetPath is obsolete and will be removed in a future major version of Carbon. Do not use.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name $netCmd = Get-Command -CommandType Application -Name net.exe* | Where-Object { $_.Name -eq 'net.exe' } diff --git a/Carbon/Functions/Resolve-WindowsFeatureName.ps1 b/Carbon/Functions/Resolve-WindowsFeatureName.ps1 index 2a02d354..0a318989 100644 --- a/Carbon/Functions/Resolve-WindowsFeatureName.ps1 +++ b/Carbon/Functions/Resolve-WindowsFeatureName.ps1 @@ -26,7 +26,7 @@ function Resolve-WindowsFeatureName Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce -Message ('Resolve-WindowsFeatureName is obsolete and will be removed in a future major version of Carbon.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name Assert-WindowsFeatureFunctionsSupported -WarningAction SilentlyContinue | Out-Null diff --git a/Carbon/Functions/Test-OSIs32Bit.ps1 b/Carbon/Functions/Test-OSIs32Bit.ps1 index 6b5795db..172c7b9a 100644 --- a/Carbon/Functions/Test-OSIs32Bit.ps1 +++ b/Carbon/Functions/Test-OSIs32Bit.ps1 @@ -29,9 +29,9 @@ function Test-COSIs32Bit if( -not $NoWarn ) { - $msg = 'Carbon''s "Test-COSIs32Bit" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the new "Test-COperatingSystem" function in the new Carbon.Core module instead.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -ModuleName 'Carbon.Core' ` + -NewCommandName 'Test-COperatingSystem' } return -not (Test-COSIs64Bit -NoWarn) diff --git a/Carbon/Functions/Test-OSIs64Bit.ps1 b/Carbon/Functions/Test-OSIs64Bit.ps1 index d437889f..8eb59dd1 100644 --- a/Carbon/Functions/Test-OSIs64Bit.ps1 +++ b/Carbon/Functions/Test-OSIs64Bit.ps1 @@ -29,9 +29,9 @@ function Test-COSIs64Bit if( -not $NoWarn ) { - $msg = 'Carbon''s "Test-COSIs64Bit" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the new "Test-COperatingSystem" function in the new Carbon.Core module instead.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -ModuleName 'Carbon.Core' ` + -NewCommandName 'Test-COperatingSystem' } return ([Environment]::Is64BitOperatingSystem) diff --git a/Carbon/Functions/Test-PowerShellIs32Bit.ps1 b/Carbon/Functions/Test-PowerShellIs32Bit.ps1 index a3ac58c1..b00db2f6 100644 --- a/Carbon/Functions/Test-PowerShellIs32Bit.ps1 +++ b/Carbon/Functions/Test-PowerShellIs32Bit.ps1 @@ -29,9 +29,9 @@ function Test-CPowerShellIs32Bit if( -not $NoWarn ) { - $msg = 'Carbon''s "Test-CPowerShellIs32Bit" function is OBSOLETE and will be removed in the next major ' + - 'version of Carbon. Use the new "Test-CPowerShell" function in the new Carbon.Core module instead.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -ModuleName 'Carbon.Core' ` + -NewCommandName 'Test-CPowerShell' } return -not (Test-CPowerShellIs64Bit -NoWarn) diff --git a/Carbon/Functions/Test-PowerShellIs64Bit.ps1 b/Carbon/Functions/Test-PowerShellIs64Bit.ps1 index 397cd4f2..0bb05569 100644 --- a/Carbon/Functions/Test-PowerShellIs64Bit.ps1 +++ b/Carbon/Functions/Test-PowerShellIs64Bit.ps1 @@ -29,9 +29,9 @@ function Test-CPowerShellIs64Bit if( -not $NoWarn ) { - $msg = 'Carbon''s "Test-CPowerShellIs64Bit" function is OBSOLETE and will be removed in the next major ' + - 'version of Carbon. Use the new "Test-CPowerShell" function in the new Carbon.Core module instead.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -ModuleName 'Carbon.Core' ` + -NewCommandName 'Test-CPowerShell' } return ([Environment]::Is64BitProcess) diff --git a/Carbon/Functions/Test-WindowsFeature.ps1 b/Carbon/Functions/Test-WindowsFeature.ps1 index ef8aa55b..4269ab79 100644 --- a/Carbon/Functions/Test-WindowsFeature.ps1 +++ b/Carbon/Functions/Test-WindowsFeature.ps1 @@ -44,7 +44,7 @@ function Test-CWindowsFeature Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce -Message ('Test-CWindowsFeature is obsolete and will be removed in a future major version of Carbon.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name if( -not (Get-Module -Name 'ServerManager') -and -not (Assert-WindowsFeatureFunctionsSupported) ) { diff --git a/Carbon/Functions/Uninstall-Certificate.ps1 b/Carbon/Functions/Uninstall-Certificate.ps1 index dfa055c5..9f2b573e 100644 --- a/Carbon/Functions/Uninstall-Certificate.ps1 +++ b/Carbon/Functions/Uninstall-Certificate.ps1 @@ -109,10 +109,7 @@ function Uninstall-CCertificate if( -not $NoWarn ) { - $msg = 'Carbon''s "Uninstall-CCertificate" function is OBSOLETE and will be removed in the next major ' + - 'version of Carbon. Use the "Uninstall-CCertificate" function in the new "Carbon.Cryptography" ' + - 'module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } if( $PSCmdlet.ParameterSetName -like 'ByCertificate*' ) diff --git a/Carbon/Functions/Uninstall-WindowsFeature.ps1 b/Carbon/Functions/Uninstall-WindowsFeature.ps1 index d3dd80f9..ceb2fdda 100644 --- a/Carbon/Functions/Uninstall-WindowsFeature.ps1 +++ b/Carbon/Functions/Uninstall-WindowsFeature.ps1 @@ -71,7 +71,9 @@ if( -not (Get-Command -Name 'Get-WindowsFeature*' | Where-Object { $_.ModuleName Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Write-CWarningOnce -Message ('Uninstall-CWindowsFeature is obsolete and will be removed in a future major version of Carbon.') + Write-CObsoleteCommandWarning -CommandName $MyInvocation.MyCommand.Name ` + -NewCommandName 'Uninstall-WindowsFeature' ` + -NewModuleName 'ServerManager' if( -not (Assert-WindowsFeatureFunctionsSupported) ) { diff --git a/Carbon/Functions/Unprotect-String.ps1 b/Carbon/Functions/Unprotect-String.ps1 index c1d7c83d..20dabbf3 100644 --- a/Carbon/Functions/Unprotect-String.ps1 +++ b/Carbon/Functions/Unprotect-String.ps1 @@ -134,9 +134,7 @@ filter Unprotect-CString if( -not $NoWarn ) { - $msg = 'Carbon''s "Unprotect-CString" function is OBSOLETE and will be removed in the next major version of ' + - 'Carbon. Use the "Unprotect-CString" function in the new "Carbon.Cryptography" module.' - Write-CWarningOnce -Message $msg + Write-CRefactoredCommandWarning -CommandName $MyInvocation.MyCommand.Name -ModuleName 'Carbon.Cryptography' } Add-Type -AssemblyName 'System.Security' diff --git a/Carbon/Functions/Write-File.ps1 b/Carbon/Functions/Write-File.ps1 index 688cc7f1..c687e5d5 100644 --- a/Carbon/Functions/Write-File.ps1 +++ b/Carbon/Functions/Write-File.ps1 @@ -161,10 +161,7 @@ function Write-File Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState - $msg = "The Carbon module's ""Write-File"" function was renamed to ""Write-CFile"". Please update " + - "your code to use the new ""Write-CFile"" name. The old ""Write-File"" function will be " + - 'removed in the next major version of Carbon.' - Write-CWarningOnce -Message $msg + Write-CRenamedCommandWarning -CommandName $MyInvocation.MyCommand.Name -NewCommandName 'Write-CFile' $stuffToPipe = New-Object 'Collections.ArrayList' } diff --git a/Source/Carbon.Installer.sln b/Source/Carbon.Installer.sln deleted file mode 100644 index 4b6160e3..00000000 --- a/Source/Carbon.Installer.sln +++ /dev/null @@ -1,37 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.168 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "CarbonTestInstaller", "CarbonTestInstaller\CarbonTestInstaller.vdproj", "{A309DF25-7E93-4D08-A418-DB0615C20AA8}" -EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "CarbonTestInstallerWithCustomActions", "CarbonTestInstallerWithCustomActions\CarbonTestInstallerWithCustomActions.vdproj", "{11EBB385-A890-4692-AD41-F53F0747678F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Carbon.Test.Installer", "Test\Installer\Carbon.Test.Installer.csproj", "{D3F2D40C-A985-46D4-A317-03D7CF6B10E0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A309DF25-7E93-4D08-A418-DB0615C20AA8}.Debug|Any CPU.ActiveCfg = Debug - {A309DF25-7E93-4D08-A418-DB0615C20AA8}.Debug|Any CPU.Build.0 = Debug - {A309DF25-7E93-4D08-A418-DB0615C20AA8}.Release|Any CPU.ActiveCfg = Release - {A309DF25-7E93-4D08-A418-DB0615C20AA8}.Release|Any CPU.Build.0 = Release - {11EBB385-A890-4692-AD41-F53F0747678F}.Debug|Any CPU.ActiveCfg = Debug - {11EBB385-A890-4692-AD41-F53F0747678F}.Debug|Any CPU.Build.0 = Debug - {11EBB385-A890-4692-AD41-F53F0747678F}.Release|Any CPU.ActiveCfg = Release - {11EBB385-A890-4692-AD41-F53F0747678F}.Release|Any CPU.Build.0 = Release - {D3F2D40C-A985-46D4-A317-03D7CF6B10E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D3F2D40C-A985-46D4-A317-03D7CF6B10E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D3F2D40C-A985-46D4-A317-03D7CF6B10E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D3F2D40C-A985-46D4-A317-03D7CF6B10E0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {97C21930-68C6-4DB3-8B1C-3935E4985FCC} - EndGlobalSection -EndGlobal diff --git a/Source/CarbonTestInstaller/CarbonTestInstaller.vdproj b/Source/CarbonTestInstaller/CarbonTestInstaller.vdproj deleted file mode 100644 index 6400e94c..00000000 --- a/Source/CarbonTestInstaller/CarbonTestInstaller.vdproj +++ /dev/null @@ -1,681 +0,0 @@ -"DeployProject" -{ -"VSVersion" = "3:800" -"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" -"IsWebType" = "8:FALSE" -"ProjectName" = "8:CarbonTestInstaller" -"LanguageId" = "3:1033" -"CodePage" = "3:1252" -"UILanguageId" = "3:1033" -"SccProjectName" = "8:" -"SccLocalPath" = "8:" -"SccAuxPath" = "8:" -"SccProvider" = "8:" - "Hierarchy" - { - } - "Configurations" - { - "Debug" - { - "DisplayName" = "8:Debug" - "IsDebugOnly" = "11:TRUE" - "IsReleaseOnly" = "11:FALSE" - "OutputFilename" = "8:..\\..\\Test\\MSI\\CarbonTestInstaller.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:3" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.5" - { - "Name" = "8:Microsoft .NET Framework 4.5 (x86 and x64)" - "ProductCode" = "8:.NETFramework,Version=v4.5" - } - } - } - } - "Release" - { - "DisplayName" = "8:Release" - "IsDebugOnly" = "11:FALSE" - "IsReleaseOnly" = "11:TRUE" - "OutputFilename" = "8:..\\..\\Test\\MSI\\CarbonTestInstaller.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:2" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.5" - { - "Name" = "8:Microsoft .NET Framework 4.5 (x86 and x64)" - "ProductCode" = "8:.NETFramework,Version=v4.5" - } - } - } - } - } - "Deployable" - { - "CustomAction" - { - } - "DefaultFeature" - { - "Name" = "8:DefaultFeature" - "Title" = "8:" - "Description" = "8:" - } - "ExternalPersistence" - { - "LaunchCondition" - { - } - } - "File" - { - } - "FileType" - { - } - "Folder" - { - "{1525181F-901A-416C-8A58-119130FE478E}:_6C7D2B0913C84F079D82D6F887EA995C" - { - "Name" = "8:#1916" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:DesktopFolder" - "Folders" - { - } - } - "{1525181F-901A-416C-8A58-119130FE478E}:_7CCFFEABB6944A40A1F37D34990EBD28" - { - "Name" = "8:#1919" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:ProgramMenuFolder" - "Folders" - { - } - } - "{3C67513D-01DD-4637-8A68-80971EB9504F}:_E89DD5DD809849A6A340ED3E5E715E13" - { - "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" - "Name" = "8:#1925" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:TARGETDIR" - "Folders" - { - } - } - } - "LaunchCondition" - { - } - "Locator" - { - } - "MsiBootstrapper" - { - "LangId" = "3:1033" - "RequiresElevation" = "11:FALSE" - } - "Product" - { - "Name" = "8:Microsoft Visual Studio" - "ProductName" = "8:Carbon Test Installer" - "ProductCode" = "8:{E1724ABC-A8D6-4D88-BBED-2E077C9AE6D2}" - "PackageCode" = "8:{38CAAD30-1CA4-4F5F-B436-457CBEE51C58}" - "UpgradeCode" = "8:{287AD39E-FCB3-4F42-AABA-21AF57EC8434}" - "AspNetVersion" = "8:4.0.30319.0" - "RestartWWWService" = "11:FALSE" - "RemovePreviousVersions" = "11:FALSE" - "DetectNewerInstalledVersion" = "11:TRUE" - "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.0.0" - "Manufacturer" = "8:Carbon" - "ARPHELPTELEPHONE" = "8:" - "ARPHELPLINK" = "8:" - "Title" = "8:Carbon Test Installer" - "Subject" = "8:" - "ARPCONTACT" = "8:Aaron Jensen" - "Keywords" = "8:" - "ARPCOMMENTS" = "8:Installer for testing Carbon MSI functions." - "ARPURLINFOABOUT" = "8:http://get-carbon.org/" - "ARPPRODUCTICON" = "8:" - "ARPIconIndex" = "3:0" - "SearchPath" = "8:" - "UseSystemSearchPath" = "11:TRUE" - "TargetPlatform" = "3:0" - "PreBuildEvent" = "8:" - "PostBuildEvent" = "8:" - "RunPostBuildEvent" = "3:0" - } - "Registry" - { - "HKLM" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_50A65A7422E7476AAECF7CA3C2EF9C4F" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_BA17D762B3914D99A3365E03BD044C99" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCU" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_2D5E15EA98374C80B934426550412248" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_42783B3594254339B9E16B87221EDDC4" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCR" - { - "Keys" - { - } - } - "HKU" - { - "Keys" - { - } - } - "HKPU" - { - "Keys" - { - } - } - } - "Sequences" - { - } - "Shortcut" - { - } - "UserInterface" - { - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_0D0CDB4325BD42CC8C1402106DCE9C2B" - { - "Name" = "8:#1900" - "Sequence" = "3:1" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_6E8C56AC92304710AC872ED2167BBEEE" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E8D983725E8C46A091D6A6E31CE9ED1D" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1203" - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_EACBDB264BF9429DB12B4B4A955B2CC2" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "InstallAllUsersVisible" - { - "Name" = "8:InstallAllUsersVisible" - "DisplayName" = "8:#1059" - "Description" = "8:#1159" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_1F21E4E71CFE4E748464A78A5F9147DA" - { - "Name" = "8:#1901" - "Sequence" = "3:1" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_164A34EDB54D488F90842BE7CCEB51E4" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_38FAA8A9AEF1448CB0DDE321E403943C" - { - "Name" = "8:#1902" - "Sequence" = "3:1" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_64B546F1D1F84B3589A226F7A04B3C0B" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "UpdateText" - { - "Name" = "8:UpdateText" - "DisplayName" = "8:#1058" - "Description" = "8:#1158" - "Type" = "3:15" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1258" - "DefaultValue" = "8:#1258" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_5168094523DE4367A108A4BFCBA597FE" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdUserInterface.wim" - } - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_B1DFB3E747E4425385ED92CA6537DC97" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdBasicDialogs.wim" - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_C7412D091FB84EC0B101184056F06D1E" - { - "Name" = "8:#1900" - "Sequence" = "3:2" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2340C4A889C946F6B9A4EF16FB46696D" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1203" - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_8CF42318E5A644F9B4E5D3463B42C804" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_ACE7B69A92AC48ADA770C2E094761AC6" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E0120C6DA61442398B57F54EF663CFD1" - { - "Name" = "8:#1901" - "Sequence" = "3:2" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_638B814BF5A841C99438EA69E26F0D17" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E971A6DAA66E4619BA7BCB4116272818" - { - "Name" = "8:#1902" - "Sequence" = "3:2" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E292837F017843C0B099448E682B68F5" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - } - "MergeModule" - { - } - "ProjectOutput" - { - } - } -} diff --git a/Source/CarbonTestInstallerWithCustomActions/CarbonTestInstallerWithCustomActions.vdproj b/Source/CarbonTestInstallerWithCustomActions/CarbonTestInstallerWithCustomActions.vdproj deleted file mode 100644 index 66a17762..00000000 --- a/Source/CarbonTestInstallerWithCustomActions/CarbonTestInstallerWithCustomActions.vdproj +++ /dev/null @@ -1,771 +0,0 @@ -"DeployProject" -{ -"VSVersion" = "3:800" -"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" -"IsWebType" = "8:FALSE" -"ProjectName" = "8:CarbonTestInstallerWithCustomActions" -"LanguageId" = "3:1033" -"CodePage" = "3:1252" -"UILanguageId" = "3:1033" -"SccProjectName" = "8:" -"SccLocalPath" = "8:" -"SccAuxPath" = "8:" -"SccProvider" = "8:" - "Hierarchy" - { - "Entry" - { - "MsmKey" = "8:_B8F0BD8399864520B77B80351C914B4C" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_B8F0BD8399864520B77B80351C914B4C" - "MsmSig" = "8:_UNDEFINED" - } - } - "Configurations" - { - "Debug" - { - "DisplayName" = "8:Debug" - "IsDebugOnly" = "11:TRUE" - "IsReleaseOnly" = "11:FALSE" - "OutputFilename" = "8:..\\..\\Test\\MSI\\CarbonTestInstallerWithCustomActions.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:3" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.5" - { - "Name" = "8:Microsoft .NET Framework 4.5 (x86 and x64)" - "ProductCode" = "8:.NETFramework,Version=v4.5" - } - } - } - } - "Release" - { - "DisplayName" = "8:Release" - "IsDebugOnly" = "11:FALSE" - "IsReleaseOnly" = "11:TRUE" - "OutputFilename" = "8:..\\..\\Test\\MSI\\CarbonTestInstallerWithCustomActions.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:2" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.5" - { - "Name" = "8:Microsoft .NET Framework 4.5 (x86 and x64)" - "ProductCode" = "8:.NETFramework,Version=v4.5" - } - } - } - } - } - "Deployable" - { - "CustomAction" - { - "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_0EA58D118CAB44379FB39A451F743924" - { - "Name" = "8:Primary output from Carbon.Test.Installer (Active)" - "Condition" = "8:" - "Object" = "8:_B8F0BD8399864520B77B80351C914B4C" - "FileType" = "3:1" - "InstallAction" = "3:4" - "Arguments" = "8:" - "EntryPoint" = "8:" - "Sequence" = "3:1" - "Identifier" = "8:_F8F6D891_F0F0_4929_903B_7718A097B181" - "InstallerClass" = "11:TRUE" - "CustomActionData" = "8:" - } - "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_1CA730EB40BC4D4B8E4845E849036972" - { - "Name" = "8:Primary output from Carbon.Test.Installer (Active)" - "Condition" = "8:" - "Object" = "8:_B8F0BD8399864520B77B80351C914B4C" - "FileType" = "3:1" - "InstallAction" = "3:1" - "Arguments" = "8:" - "EntryPoint" = "8:" - "Sequence" = "3:1" - "Identifier" = "8:_4AB380EB_3C5C_4FD6_AD39_0CE67173263E" - "InstallerClass" = "11:TRUE" - "CustomActionData" = "8:" - } - "{4AA51A2D-7D85-4A59-BA75-B0809FC8B380}:_6CAD561D3A9A4453B01D8119F40A85C0" - { - "Name" = "8:Primary output from Carbon.Test.Installer (Active)" - "Condition" = "8:" - "Object" = "8:_B8F0BD8399864520B77B80351C914B4C" - "FileType" = "3:1" - "InstallAction" = "3:2" - "Arguments" = "8:" - "EntryPoint" = "8:" - "Sequence" = "3:1" - "Identifier" = "8:_7BE486B0_0B92_4838_8A9A_357C05495D32" - "InstallerClass" = "11:TRUE" - "CustomActionData" = "8:" - } - } - "DefaultFeature" - { - "Name" = "8:DefaultFeature" - "Title" = "8:" - "Description" = "8:" - } - "ExternalPersistence" - { - "LaunchCondition" - { - "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_60FE66D057CD4ACCBAB4A6B94D18C8ED" - { - "Name" = "8:.NET Framework" - "Message" = "8:[VSDNETMSG]" - "FrameworkVersion" = "8:.NETFramework,Version=v4.5" - "AllowLaterVersions" = "11:FALSE" - "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=395269" - } - } - } - "File" - { - } - "FileType" - { - } - "Folder" - { - "{1525181F-901A-416C-8A58-119130FE478E}:_6C7D2B0913C84F079D82D6F887EA995C" - { - "Name" = "8:#1916" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:DesktopFolder" - "Folders" - { - } - } - "{1525181F-901A-416C-8A58-119130FE478E}:_7CCFFEABB6944A40A1F37D34990EBD28" - { - "Name" = "8:#1919" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:ProgramMenuFolder" - "Folders" - { - } - } - "{3C67513D-01DD-4637-8A68-80971EB9504F}:_E89DD5DD809849A6A340ED3E5E715E13" - { - "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" - "Name" = "8:#1925" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:TARGETDIR" - "Folders" - { - } - } - } - "LaunchCondition" - { - } - "Locator" - { - } - "MsiBootstrapper" - { - "LangId" = "3:1033" - "RequiresElevation" = "11:FALSE" - } - "Product" - { - "Name" = "8:Microsoft Visual Studio" - "ProductName" = "8:Carbon Test Installer (Advanced)" - "ProductCode" = "8:{9FB04550-432E-4E8C-86C3-D51E31522EBC}" - "PackageCode" = "8:{AB408DEE-0052-4159-AB52-43F056E03228}" - "UpgradeCode" = "8:{287AD39E-FCB3-4F42-AABA-21AF57EC8434}" - "AspNetVersion" = "8:4.0.30319.0" - "RestartWWWService" = "11:FALSE" - "RemovePreviousVersions" = "11:FALSE" - "DetectNewerInstalledVersion" = "11:TRUE" - "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.0.0" - "Manufacturer" = "8:Carbon" - "ARPHELPTELEPHONE" = "8:" - "ARPHELPLINK" = "8:" - "Title" = "8:Carbon Test Installer (Advanced)" - "Subject" = "8:" - "ARPCONTACT" = "8:Aaron Jensen" - "Keywords" = "8:" - "ARPCOMMENTS" = "8:Test installer with custom actions for testing MSI functions." - "ARPURLINFOABOUT" = "8:http://get-carbon.org/" - "ARPPRODUCTICON" = "8:" - "ARPIconIndex" = "3:0" - "SearchPath" = "8:" - "UseSystemSearchPath" = "11:TRUE" - "TargetPlatform" = "3:0" - "PreBuildEvent" = "8:" - "PostBuildEvent" = "8:" - "RunPostBuildEvent" = "3:0" - } - "Registry" - { - "HKLM" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_50A65A7422E7476AAECF7CA3C2EF9C4F" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_BA17D762B3914D99A3365E03BD044C99" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCU" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_2D5E15EA98374C80B934426550412248" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_42783B3594254339B9E16B87221EDDC4" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCR" - { - "Keys" - { - } - } - "HKU" - { - "Keys" - { - } - } - "HKPU" - { - "Keys" - { - } - } - } - "Sequences" - { - } - "Shortcut" - { - } - "UserInterface" - { - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_0D0CDB4325BD42CC8C1402106DCE9C2B" - { - "Name" = "8:#1900" - "Sequence" = "3:1" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_6E8C56AC92304710AC872ED2167BBEEE" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E8D983725E8C46A091D6A6E31CE9ED1D" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1203" - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_EACBDB264BF9429DB12B4B4A955B2CC2" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "InstallAllUsersVisible" - { - "Name" = "8:InstallAllUsersVisible" - "DisplayName" = "8:#1059" - "Description" = "8:#1159" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_1F21E4E71CFE4E748464A78A5F9147DA" - { - "Name" = "8:#1901" - "Sequence" = "3:1" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_164A34EDB54D488F90842BE7CCEB51E4" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_38FAA8A9AEF1448CB0DDE321E403943C" - { - "Name" = "8:#1902" - "Sequence" = "3:1" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_64B546F1D1F84B3589A226F7A04B3C0B" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "UpdateText" - { - "Name" = "8:UpdateText" - "DisplayName" = "8:#1058" - "Description" = "8:#1158" - "Type" = "3:15" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1258" - "DefaultValue" = "8:#1258" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_5168094523DE4367A108A4BFCBA597FE" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdUserInterface.wim" - } - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_B1DFB3E747E4425385ED92CA6537DC97" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdBasicDialogs.wim" - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_C7412D091FB84EC0B101184056F06D1E" - { - "Name" = "8:#1900" - "Sequence" = "3:2" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2340C4A889C946F6B9A4EF16FB46696D" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1203" - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_8CF42318E5A644F9B4E5D3463B42C804" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_ACE7B69A92AC48ADA770C2E094761AC6" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E0120C6DA61442398B57F54EF663CFD1" - { - "Name" = "8:#1901" - "Sequence" = "3:2" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_638B814BF5A841C99438EA69E26F0D17" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E971A6DAA66E4619BA7BCB4116272818" - { - "Name" = "8:#1902" - "Sequence" = "3:2" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E292837F017843C0B099448E682B68F5" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - } - "MergeModule" - { - } - "ProjectOutput" - { - "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_B8F0BD8399864520B77B80351C914B4C" - { - "SourcePath" = "8:..\\Test\\Installer\\obj\\Release\\Carbon.Test.Installer.dll" - "TargetName" = "8:" - "Tag" = "8:" - "Folder" = "8:_E89DD5DD809849A6A340ED3E5E715E13" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - "ProjectOutputGroupRegister" = "3:1" - "OutputConfiguration" = "8:" - "OutputGroupCanonicalName" = "8:Built" - "OutputProjectGuid" = "8:{D3F2D40C-A985-46D4-A317-03D7CF6B10E0}" - "ShowKeyOutput" = "11:TRUE" - "ExcludeFilters" - { - } - } - } - } -} diff --git a/Source/Compile-CarbonTestInstaller.ps1 b/Source/Compile-CarbonTestInstaller.ps1 deleted file mode 100644 index f6af76ac..00000000 --- a/Source/Compile-CarbonTestInstaller.ps1 +++ /dev/null @@ -1,47 +0,0 @@ -<# -#> - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -[CmdletBinding()] -param( - [Parameter(Mandatory)] - [string] - $Configuration -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 'Latest' -#Requires -Version 5.1 - -Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\PSModules\VSSetup' -Resolve) - -$instances = Get-VSSetupInstance -$instances | Format-List | Out-String | Write-Verbose -$instance = $instances | - Where-Object { $_.DisplayName -notlike '* Test Agent *' } | - Sort-Object -Descending -Property InstallationVersion | - Select-Object -First 1 - -$idePath = Join-Path -Path $instance.InstallationPath -ChildPath 'Common7\IDE' -Resolve -Write-Verbose -Message ('Using {0} {1} found at "{2}".' -f $instance.DisplayName,$instance.InstallationVersion,$idePath) -$installerSlnPath = Join-Path -Path $PSScriptRoot -ChildPath 'Carbon.Installer.sln' -Resolve - -$env:PATH = '{0}{1}{2}' -f $env:PATH,[IO.Path]::PathSeparator,$idePath - -Write-Verbose ('devenv "{0}" /build "{1}"' -f $installerSlnPath,$Configuration) -devenv $installerSlnPath /build $Configuration -if( $LASTEXITCODE ) -{ - Write-Error -Message ('Failed to build Carbon test installers. Check the output above for details. If the build failed because of this error: "ERROR: An error occurred while validating. HRESULT = ''8000000A''", open a command prompt, move into the "{0}" directory, and run ".\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild\DisableOutOfProcBuild.exe".' -f $instance.InstallationPath) -} \ No newline at end of file diff --git a/Source/Computer/ProgramInstallInfo.cs b/Source/Computer/ProgramInstallInfo.cs index 41d87e39..9e0f0b5d 100644 --- a/Source/Computer/ProgramInstallInfo.cs +++ b/Source/Computer/ProgramInstallInfo.cs @@ -18,6 +18,7 @@ namespace Carbon.Computer { + [Obsolete("Functionality moved to Carbon.Windows.Installer module.")] public sealed class ProgramInstallInfo { public ProgramInstallInfo(RegistryKey key) diff --git a/Source/Msi/MsiInfo.cs b/Source/Msi/MsiInfo.cs index 3bd02591..57740e38 100644 --- a/Source/Msi/MsiInfo.cs +++ b/Source/Msi/MsiInfo.cs @@ -19,6 +19,7 @@ namespace Carbon.Msi { + [Obsolete("Functionality moved to Carbon.Windows.Installer module.")] public sealed class MsiInfo { public MsiInfo(string path) diff --git a/Test/Get-ProgramInstallInfo.Tests.ps1 b/Test/Get-ProgramInstallInfo.Tests.ps1 deleted file mode 100644 index f909d814..00000000 --- a/Test/Get-ProgramInstallInfo.Tests.ps1 +++ /dev/null @@ -1,206 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#Requires -Version 4 -Set-StrictMode -Version 'Latest' - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -Describe 'Get-ProgramInstallInfo.when getting all programs' { - $programs = Get-ProgramInstallInfo - It 'should get all installed programs' { - $programs | Should -Not -BeNullOrEmpty - } - - It ('should get information about each program') { - foreach( $program in $programs ) - { - Write-Verbose -Message $program.DisplayName - $program | Should Not BeNullOrEmpty - [Microsoft.Win32.RegistryKey]$key = $program.Key - $valueNames = $key.GetValueNames() - foreach( $property in (Get-Member -InputObject $program -MemberType Property) ) - { - $propertyName = $property.Name - Write-Verbose -Message (' {0}' -f $propertyName) - if( $propertyName -eq 'Version' ) - { - Write-Verbose 'BREAK' - } - - if( $propertyName -eq 'Key' ) - { - continue - } - - $keyValue = $key.GetValue( $propertyName ) - $propertyValue = $program.$propertyName - - if( $propertyName -eq 'ProductCode' ) - { - $propertyValue = Split-Path -Leaf -Path $key.Name - [Guid]$guid = [Guid]::Empty - [Guid]::TryParse( $propertyValue, [ref]$guid ) - $propertyValue = $guid - $keyValue = $guid - } - elseif( $propertyName -eq 'User' ) - { - if( $key.Name -match 'HKEY_USERS\\([^\\]+)\\' ) - { - $sddl = $Matches[1] - $sid = New-Object 'Security.Principal.SecurityIdentifier' $sddl - try - { - $propertyValue = $sid.Translate([Security.Principal.NTAccount]).Value - } - catch - { - $propertyValue = $sid.ToString() - } - $keyValue = $propertyValue - } - } - - $typeName = $program.GetType().GetProperty($propertyName).PropertyType.Name - if( $keyValue -eq $null ) - { - if( $typeName -eq 'Int32' ) - { - $keyValue = 0 - } - elseif( $typeName -eq 'Version' ) - { - $keyValue = $null - } - elseif( $typeName -eq 'DateTime' ) - { - $keyValue = [DateTime]::MinValue - } - elseif( $typeName -eq 'Boolean' ) - { - $keyValue = $false - } - elseif( $typeName -eq 'Guid' ) - { - $keyValue = [Guid]::Empty - } - else - { - $keyValue = '' - } - } - else - { - if( $typeName -eq 'DateTime' ) - { - [DateTime]$dateTime = [DateTime]::MinValue - - if( -not ([DateTime]::TryParse($keyValue,[ref]$dateTime)) ) - { - [DateTime]::TryParseExact( $keyValue, 'yyyyMMdd', [Globalization.CultureInfo]::CurrentCulture, [Globalization.DateTimeStyles]::None, [ref]$dateTime) - } - $keyValue = $dateTime - } - elseif( $typeName -eq 'Int32' ) - { - $intValue = 0 - $keyValue = [Int32]::TryParse($keyValue, [ref] $intValue) - $keyValue = $intValue - } - elseif( $typeName -eq 'Version' ) - { - [int]$intValue = 0 - if( $keyValue -isnot [int32] -and [int]::TryParse($keyValue,[ref]$intValue) ) - { - $keyValue = $intValue - } - - if( $keyValue -is [int32] ) - { - $major = $keyValue -shr 24 # First 8 bits - $minor = ($keyValue -band 0x00ff0000) -shr 16 # bits 9 - 16 - $build = $keyValue -band 0x0000ffff # last 8 bits - $keyValue = New-Object 'Version' $major,$minor,$build - } - else - { - [Version]$version = $null - if( [Version]::TryParse($keyValue, [ref]$version) ) - { - $keyValue = $version - } - } - } - } - - if( $keyValue -eq $null ) - { - $propertyValue | Should BeNullOrEmpty - } - else - { - $propertyValue | Should Be $keyValue - } - } - } - } -} - -Describe 'Get-ProgramInstallInfo.when getting a program by name' { - $p = Get-ProgramInstallInfo | Select-Object -First 1 - $p2 = Get-ProgramInstallInfo $p.DisplayName - It 'should get just that program' { - $p2 | Should Not BeNullOrEmpty - $p2 | Should Be $p - } -} - -Describe 'Get-ProgramInstallInfo.when getting programs by wildcard' { - - $p = Get-ProgramInstallInfo | Select-Object -First 1 - - $wildcard = $p.DisplayName.Substring(0,$p.DisplayName.Length - 1) - $wildcard = '{0}*' -f $wildcard - $p2 = Get-ProgramInstallInfo $wildcard - - It 'should find the program' { - $p2 | Should Not BeNullOrEmpty - $p2 | Should Be $p - } -} - -Describe 'Get-ProgramInstallInfo.when there are invalid integer versions' { - - $program = Get-ProgramInstallInfo | Select-Object -First 1 - - $regKeyPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\CarbonGetProgramInstallInfo' - Install-RegistryKey -Path $regKeyPath - try - { - $name = 'Carbon+Get-ProgramInstallInfo' - Set-RegistryKeyValue -Path $regKeyPath -Name 'DisplayName' -String $name - Set-RegistryKeyValue -Path $regKeyPath -Name 'Version' -DWord 0xff000000 - - $program = Get-ProgramInstallInfo -Name $name - - It 'should ignore the invalid version' { - $program.Version | Should BeNullOrEmpty - } - } - finally - { - Remove-Item -Path $regKeyPath -Recurse - } - - -} diff --git a/Test/Install-Msi.Tests.ps1 b/Test/Install-Msi.Tests.ps1 deleted file mode 100644 index 75c139ac..00000000 --- a/Test/Install-Msi.Tests.ps1 +++ /dev/null @@ -1,201 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) -$carbonTestInstaller = Join-Path -Path $PSScriptRoot -ChildPath 'MSI\CarbonTestInstaller.msi' -Resolve -$carbonTestInstallerActions = Join-Path -Path $PSScriptRoot -ChildPath 'MSI\CarbonTestInstallerWithCustomActions.msi' -Resolve - -Describe 'Install-Msi' { - - function Assert-CarbonTestInstallerInstalled - { - $Global:Error.Count | Should Be 0 - $maxTries = 200 - $tryNum = 0 - do - { - $item = Get-ProgramInstallInfo -Name 'Carbon Test Installer*' - if( $item ) - { - break - } - - Start-Sleep -Milliseconds 100 - } - while( $tryNum++ -lt $maxTries ) - $item | Should Not BeNullOrEmpty - } - - function Assert-CarbonTestInstallerNotInstalled - { - $maxTries = 200 - $tryNum = 0 - do - { - $item = Get-ProgramInstallInfo -Name 'Carbon Test Installer*' - if( -not $item ) - { - break - } - - Start-Sleep -Milliseconds 100 - } - while( $tryNum++ -lt $maxTries ) - - $item | Should BeNullOrEmpty - } - - function Uninstall-CarbonTestInstaller - { - Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'MSI') -Filter *.msi | - Get-Msi | - Where-Object { Get-ProgramInstallInfo -Name $_.ProductName } | - ForEach-Object { - #msiexec /fa $_.Path /quiet /l*vx 'D:\restore.log' - $msiProcess = Start-Process -FilePath "msiexec.exe" -ArgumentList "/quiet","/fa",('"{0}"' -f $_.Path) -NoNewWindow -Wait -PassThru - if( $msiProcess.ExitCode -ne $null -and $msiProcess.ExitCode -ne 0 ) - { - Write-Error ("{0} {1} repair failed. (Exit code: {2}; MSI: {3})" -f $_.ProductName,$_.ProductVersion,$msiProcess.ExitCode,$_.Path) - } - #msiexec /uninstall $_.Path /quiet /l*vx 'D:\uninstall.log' - $msiProcess = Start-Process -FilePath "msiexec.exe" -ArgumentList "/quiet","/uninstall",('"{0}"' -f $_.Path) -NoNewWindow -Wait -PassThru - if( $msiProcess.ExitCode -ne $null -and $msiProcess.ExitCode -ne 0 ) - { - Write-Error ("{0} {1} uninstall failed. (Exit code: {2}; MSI: {3})" -f $_.ProductName,$_.ProductVersion,$msiProcess.ExitCode,$_.Path) - } - } - Assert-CarbonTestInstallerNotInstalled - } - - BeforeEach { - $Global:Error.Clear() - Uninstall-CarbonTestInstaller - } - - AfterEach { - Uninstall-CarbonTestInstaller - } - - It 'should validate file is an MSI' { - Invoke-WindowsInstaller -Path $PSCommandPath -ErrorAction SilentlyContinue - $Global:Error.Count | Should BeGreaterThan 0 - } - - It 'should support what if' { - Assert-CarbonTestInstallerNotInstalled - Invoke-WindowsInstaller -Path $carbonTestInstaller -WhatIf - $Global:Error.Count | Should Be 0 - Assert-CarbonTestInstallerNotInstalled - } - - It 'should install msi' { - Assert-CarbonTestInstallerNotInstalled - Install-Msi -Path $carbonTestInstaller - Assert-CarbonTestInstallerInstalled - } - - It 'should warn quiet switch is obsolete' { - $warnings = @() - Install-CMsi -Path $carbonTestInstaller -Quiet -WarningVariable 'warnings' - $warnings.Count | Should Be 1 - ($warnings[0] -like '*obsolete*') | Should Be $true - } - - It 'should handle failed installer' { - Set-EnvironmentVariable -Name 'CARBON_TEST_INSTALLER_THROW_INSTALL_EXCEPTION' -Value $true -ForComputer - try - { - Install-Msi -Path $carbonTestInstallerActions -ErrorAction SilentlyContinue - Assert-CarbonTestInstallerNotInstalled - } - finally - { - Remove-EnvironmentVariable -Name 'CARBON_TEST_INSTALLER_THROW_INSTALL_EXCEPTION' -ForComputer - } - } - - It 'should support wildcards' { - $tempDir = 'TestDrive:' - Copy-Item $carbonTestInstaller -Destination (Join-Path -Path $tempDir -ChildPath 'One.msi') - Copy-Item $carbonTestInstaller -Destination (Join-Path -Path $tempDir -ChildPath 'Two.msi') - Install-Msi -Path (Join-Path -Path $tempDir -ChildPath '*.msi') - Assert-CarbonTestInstallerInstalled - } - - It 'should not reinstall if already installed' { - Install-Msi -Path $carbonTestInstallerActions - Assert-CarbonTestInstallerInstalled - $msi = Get-Msi -Path $carbonTestInstallerActions - $installDir = Join-Path ${env:ProgramFiles(x86)} -ChildPath ('{0}\{1}' -f $msi.Manufacturer,$msi.ProductName) - $installDir | Should Exist - $tempName = [IO.Path]::GetRandomFileName() - Rename-Item -Path $installDir -NewName $tempName - try - { - Install-Msi -Path $carbonTestInstallerActions - $installDir | Should Not Exist - } - finally - { - $tempDir = Split-Path -Path $installDir -Parent - $tempDir = Join-Path -Path $tempDir -ChildPath $tempName - Rename-Item -Path $tempDir -NewName (Split-Path -Path $installDir -Leaf) - } - } - - It 'should reinstall if forced to' { - Install-Msi -Path $carbonTestInstallerActions - Assert-CarbonTestInstallerInstalled - $msi = Get-Msi -Path $carbonTestInstallerActions - - $installDir = Join-Path ${env:ProgramFiles(x86)} -ChildPath ('{0}\{1}' -f $msi.Manufacturer,$msi.ProductName) - $maxTries = 100 - $tryNum = 0 - do - { - if( (Test-Path -Path $installDir -PathType Container) ) - { - break - } - Start-Sleep -Milliseconds 100 - } - while( $tryNum++ -lt $maxTries ) - - $installDir | Should Exist - - $tryNum = 0 - do - { - Remove-Item -Path $installDir -Recurse -ErrorAction Ignore - if( -not (Test-Path -Path $installDir -PathType Container) ) - { - break - } - Start-Sleep -Milliseconds 100 - } - while( $tryNum++ -lt $maxTries ) - - $installDir | Should Not Exist - - Install-Msi -Path $carbonTestInstallerActions -Force - $installDir | Should Exist - } - - It 'should install msi with spaces in path' { - $tempDir = 'TestDrive:' - $newInstaller = Join-Path -Path $tempDir -ChildPath 'Installer With Spaces.msi' - Copy-Item -Path $carbonTestInstaller -Destination $newInstaller - Install-Msi -Path $newInstaller - Assert-CarbonTestInstallerInstalled - } -} - diff --git a/Test/MSI/Test-GetMsi.ps1 b/Test/MSI/Test-GetMsi.ps1 deleted file mode 100644 index f8ceb9a9..00000000 --- a/Test/MSI/Test-GetMsi.ps1 +++ /dev/null @@ -1,79 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -& (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) - -function Test-ShouldGetMsi -{ - $msi = Get-Msi -Path (Join-Path -Path $PSScriptRoot -ChildPath 'CarbonTestInstaller.msi' -Resolve) -} - -function Test-ShouldAcceptPipelineInput -{ - $msi = Get-ChildItem -Path $PSScriptRoot -Filter *.msi | Get-Msi - Assert-NotNull $msi - $msi | ForEach-Object { Assert-CarbonMsi $_ } -} - -function Test-ShouldAcceptArrayOfStrings -{ - $path = Join-Path -Path $PSScriptRoot -ChildPath 'CarbonTestInstaller.msi' - - $msi = Get-Msi -Path @( $path, $path ) - Assert-Is $msi ([object[]]) - foreach( $item in $msi ) - { - Assert-CarbonMsi $item - } -} - -function Test-ShouldAcceptArrayOfFileInfo -{ - $path = Join-Path -Path $PSScriptRoot -ChildPath 'CarbonTestInstaller.msi' - - $item = Get-Item -Path $path - $msi = Get-Msi -Path @( $item, $item ) - - Assert-Is $msi ([object[]]) - foreach( $item in $msi ) - { - Assert-CarbonMsi $item - } -} - -function Test-ShouldSupportWildcards -{ - $msi = Get-Msi -Path (Join-Path -Path $PSScriptRoot -ChildPath '*.msi') - Assert-Is $msi ([object[]]) - foreach( $item in $msi ) - { - Assert-CarbonMsi $item - } -} - -function Assert-CarbonMsi -{ - param( - $msi - ) - - Assert-NotNull $msi - Assert-Is $msi ([Carbon.Msi.MsiInfo]) - Assert-Equal 'Carbon' $msi.Manufacturer - Assert-Like $msi.ProductName 'Carbon *' - Assert-NotNull $msi.ProductCode - Assert-NotEqual $msi.ProductCode ([Guid]::Empty) - Assert-Equal 1033 $msi.ProductLanguage - Assert-Equal '1.0.0' $msi.ProductVersion - Assert-NotNull $msi.Properties - Assert-GreaterThan $msi.Properties.Count 5 -} diff --git a/whiskey.yml b/whiskey.yml index fb9e89d1..2e873ade 100644 --- a/whiskey.yml +++ b/whiskey.yml @@ -21,12 +21,6 @@ Build: Path: Source\Carbon.sln Property: - SignAssembly=$(SignAssembly) -- PowerShell: - OnlyDuring: Build - OnlyBy: BuildServer - Path: Source\Compile-CarbonTestInstaller.ps1 - Argument: - Configuration: $(WHISKEY_MSBUILD_CONFIGURATION) - DotNet: Command: publish Path: Source\Test\Carbon.Test.csproj From d5f5bfb9f181026426b1461131f7696340cb775b Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 19 Nov 2021 15:10:03 -0800 Subject: [PATCH 04/20] Don't run tests for functions that moved to Carbon.Cryptography. --- Test/Cryptography/CarbonTestDsaKey.cer | Bin 846 -> 0 bytes Test/Cryptography/CarbonTestPublicKey2.cer | Bin 1541 -> 0 bytes Test/Cryptography/Unprotect-String.ps1 | 30 -- Test/Get-Certificate.Tests.ps1 | 173 ----------- Test/Install-Certificate.Tests.ps1 | 215 -------------- Test/Protect-String.Tests.ps1 | 278 ------------------ .../Test-ConvertSecureStringToString.ps1 | 25 -- Test/Uninstall-Certificate.Tests.ps1 | 188 ------------ Test/Unprotect-String.Tests.ps1 | 214 -------------- whiskey.yml | 4 - 10 files changed, 1127 deletions(-) delete mode 100644 Test/Cryptography/CarbonTestDsaKey.cer delete mode 100644 Test/Cryptography/CarbonTestPublicKey2.cer delete mode 100644 Test/Cryptography/Unprotect-String.ps1 delete mode 100644 Test/Get-Certificate.Tests.ps1 delete mode 100644 Test/Install-Certificate.Tests.ps1 delete mode 100644 Test/Protect-String.Tests.ps1 delete mode 100644 Test/Security/Test-ConvertSecureStringToString.ps1 delete mode 100644 Test/Uninstall-Certificate.Tests.ps1 delete mode 100644 Test/Unprotect-String.Tests.ps1 diff --git a/Test/Cryptography/CarbonTestDsaKey.cer b/Test/Cryptography/CarbonTestDsaKey.cer deleted file mode 100644 index 606d4dc1e55c8fa576d7bb774cdc540917c80bce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 846 zcmXqLV)imkM91dY7{~$wt1745}moS@iVo_3lo}r|HI7on5SO6jrl3HBi671-mT4^9B z&TD95U}0ckWN2z^Y!M~SYiwy~WDG>6mZp|bRI{gval1hiqc+R~j6jYYQ)45;(oOx( zV|&!R@>Uc%^534f)%4jCvylB?{Wm<#&cF9%a;;K`S^oT6-&fpRyjF?T$iJ(}@sd49 z!`ue#Bk$L6|13BA@{~<}mdCVXL1m_IxvtGA%asf4Unk!m@*{cUqTVe(_MLobJk9*- z*;{Yed>a=u{=FPku&JAH?!lK@X-;`n&gG{K7O|6WI)~Zr%=zf< zd*Z;M%HuN`H znyg^x*!bo2(*=UT=CZZ5yU)J=kh1&Mg~eaG_W1HXOEEB16L-m7EsE)UAws6 z#x!h(Lvw_4XLYM@OAiCT=H8b)o9yS5Z!{JAyH-sk;nJ67%T#vl?Fw3V|9wvGi68PT zPuQkB|J!~3VU1vOa65NelfU~Nfop46j-00`?-fzd3hLvG zcdL%PlJ(m8@y%NbXD6#FT@3A!KNs4(b76PCp5FteyLx}ZM6caek`MHX&AtCstYmgm z|9Xzy?J2G6dSvzEnV(d&0t=qApr*U(Y zslI%;XmRkq_8mFfKir+|@0jO%WB&Zs9OVtx*N=M45!Ah6)6T@q$iTR`@t8s5VFLwV zf|g}rWc<$}W*}m~XTZb8rOn33!q{Za#3;(l#NJ>a3{s)W!ehY2#sQRKWo2h(HfZbw zi88V@HX7772%Pi2Cb<9bkC)u~hodgGHuElwq*>x_B9x{iCi#WB8%<%d0c#mcAg|}|aCyLDXtt?r1&a86P(i1siE*Z&x zlaijE6g7O;z0sxE>fu>K`%BL){M>cFF}RA|Jh;ut<;1>ISN7gIcEVKa*Xq99qg{IU zRvpo)ve0Iabk#c${ba@z6_cjZ+uoH-Ze10+q2S1~L!Ty#PS(=kVrw`$vF`Hbw<_lU z9i;1f_sy7gT<#?pN5l|F*MSJvC!I5BTpcvRe+VD^Ax;r||-uS*nHJG$rKuT5E| z-Ofu`9!$QoQs+1CyUYvn+unPf-koikcz5jytzx zbr~{_ZJBWDs@a$Lj?=Ld4MoqaJ9Q`1XW!-j8J{+N(UuOf{#e!hLSq|edF30eZ+c4) zGwhbs+h*TX5)$(}Ym(8rcNaqpf1ZEiDB2#gYUU$L(+j%ZslF- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -param( - [Parameter(Mandatory=$true)] - [string] - # A base-64 encoded string that was protected with Carbon's `protect-String`. - $ProtectedString -) - -Set-StrictMode -Version 'Latest' - -Add-Type -AssemblyName 'System.Security' - -Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\..\Carbon\Carbon.psd1' -Resolve) - -Unprotect-CString -ProtectedString $ProtectedString -NoWarn - diff --git a/Test/Get-Certificate.Tests.ps1 b/Test/Get-Certificate.Tests.ps1 deleted file mode 100644 index 9163f3b0..00000000 --- a/Test/Get-Certificate.Tests.ps1 +++ /dev/null @@ -1,173 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -$TestCertPath = JOin-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificate.cer' -Resolve -$TestCert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 $TestCertPath -$testCertificateThumbprint = '7D5CE4A8A5EC059B829ED135E9AD8607977691CC' -$testCertFriendlyName = 'Pup Test Certificate' -$testCertCertProviderPath = 'cert:\CurrentUser\My\{0}' -f $testCertificateThumbprint - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -function Assert-TestCert -{ - param( - $actualCert - ) - - $actualCert | Should Not BeNullOrEmpty - $actualCert.Thumbprint | Should Be $TestCert.Thumbprint -} - -function Init -{ - $Global:Error.Clear() - if( -not (Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My) ) - { - Install-Certificate -Path $TestCertPath -StoreLocation CurrentUser -StoreName My -NoWarn - } -} - -Describe 'Get-Certificate.when getting certificate from a file' { - Init - $cert = Get-CCertificate -Path $TestCertPath - It ('should have Path property') { - $cert.Path | Should -Be $TestCertPath - } -} - -Describe 'Get-Certificate.when getting certificate by path from certificate store' { - Init - $cert = Get-CCertificate -Path $testCertCertProviderPath -NoWarn - It ('should have Path property') { - $cert.Path | Should -Be $testCertCertProviderPath - } -} - -Describe 'Get-Certificate.when getting certificate by thumbprint' { - Init - $cert = Get-CCertificate -Thumbprint $testCertificateThumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - It ('should have Path property') { - $cert.Path | Should -Be $testCertCertProviderPath - } -} - -Describe 'Get-Certificate.when getting certificate by friendly name' { - Init - $cert = Get-CCertificate -FriendlyName $testCertFriendlyName -StoreLocation CurrentUser -StoreName My -NoWarn - It ('should have Path property') { - $cert.Path | Should -Be $testCertCertProviderPath - } -} - -Describe 'Get-Certificate' { - It 'should find certificates by friendly name' { - Init - $cert = Get-Certificate -FriendlyName $TestCert.friendlyName -StoreLocation CurrentUser -StoreName My -NoWarn - Assert-TestCert $cert - } - - - It 'should find certificate by path' { - Init - $cert = Get-Certificate -Path $TestCertPath -NoWarn - Assert-TestCert $cert - } - - It 'should find certificate by relative path' { - Init - Push-Location -Path $PSScriptRoot - try - { - $cert = Get-Certificate -Path ('.\Certificates\{0}' -f (Split-Path -Leaf -Path $TestCertPath)) -NoWarn - Assert-TestCert $cert - } - finally - { - Pop-Location - } - } - - It 'should find certificate by thumbprint' { - Init - $cert = Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - Assert-TestCert $cert - } - - It 'should not throw error when certificate does not exist' { - Init - $cert = Get-Certificate -Thumbprint '1234567890abcdef1234567890abcdef12345678' -StoreLocation CurrentUser -StoreName My -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should Be 0 - $cert | Should BeNullOrEmpty - } - - It 'should find certificate in custom store by thumbprint' { - Init - $expectedCert = Install-Certificate -Path $TestCertPath -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - try - { - $cert = Get-Certificate -Thumbprint $expectedCert.Thumbprint -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - $cert | Should Not BeNullOrEmpty - $cert.Thumbprint | Should Be $expectedCert.Thumbprint - } - finally - { - Uninstall-Certificate -Certificate $expectedCert -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - } - } - - It 'should find certificate in custom store by friendly name' { - Init - $expectedCert = Install-Certificate -Path $TestCertPath -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - try - { - $cert = Get-Certificate -FriendlyName $expectedCert.FriendlyName -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - $cert | Should Not BeNullOrEmpty - $cert.Thumbprint | Should Be $expectedCert.Thumbprint - } - finally - { - Uninstall-Certificate -Certificate $expectedCert -StoreLocation CurrentUser -CustomStoreName 'Carbon' -NoWarn - } - } - - It 'should get password protected certificate' { - Init - [Security.Cryptography.X509Certificates.X509Certificate2]$cert = Get-Certificate -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificateWithPassword.cer') -Password 'password' -NoWarn - $Global:Error.Count | Should Be 0 - $cert | Should Not BeNullOrEmpty - $cert.Thumbprint | Should Be 'DE32D78122C2B5136221DE51B33A2F65A98351D2' - $cert.FriendlyName | Should Be 'Carbon Test Certificate - Password Protected' - } - - It 'should include exception when failing to load certificate' { - Init - $cert = Get-Certificate -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificateWithPassword.cer') -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should BeGreaterThan 0 - $Global:Error[0] | Should Match 'password' - $cert | Should BeNullOrEmpty - $Error[1].Exception | Should Not BeNullOrEmpty - $Error[1].Exception | Should BeOfType ([Management.Automation.MethodInvocationException]) - } - - It 'should get certificates in CA store' { - Init - $foundACert = $false - dir Cert:\CurrentUser\CA | ForEach-Object { - $cert = Get-Certificate -Thumbprint $_.Thumbprint -StoreLocation CurrentUser -StoreName CertificateAuthority -NoWarn - $cert | Should Not BeNullOrEmpty - $foundACert = $true - } - } -} - -Uninstall-Certificate -Certificate $TestCert -storeLocation CurrentUser -StoreName My -NoWarn diff --git a/Test/Install-Certificate.Tests.ps1 b/Test/Install-Certificate.Tests.ps1 deleted file mode 100644 index 8fbdd01a..00000000 --- a/Test/Install-Certificate.Tests.ps1 +++ /dev/null @@ -1,215 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -Set-StrictMode -Version 'Latest' - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -$TestCertPath = Join-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificate.cer' -Resolve -$TestCert = New-Object 'Security.Cryptography.X509Certificates.X509Certificate2' $TestCertPath -$TestCertProtectedPath = Join-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificateWithPassword.cer' -Resolve -$TestCertProtected = New-Object 'Security.Cryptography.X509Certificates.X509Certificate2' $TestCertProtectedPath,'password' - -function Measure-MachineKey -{ - [CmdletBinding()] - param( - [Parameter(Mandatory)] - [Security.Cryptography.X509Certificates.StoreLocation]$Location - ) - - $path = Join-Path -Path $env:APPDATA -ChildPath 'Microsoft\Crypto\RSA\*\*' - if( $Location -eq [Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine ) - { - $path = Join-Path -Path $env:ProgramData -ChildPath 'Microsoft\Crypto\RSA\MachineKeys' - } - Get-ChildItem -Path $path | Measure-Object | Select-Object -ExpandProperty 'Count' -} - -function Reset -{ - Uninstall-CCertificate -Certificate $TestCert -StoreLocation CurrentUser -StoreName My -NoWarn - Uninstall-CCertificate -Certificate $TestCert -StoreLocation LocalMachine -StoreName My -NoWarn - Uninstall-CCertificate -Certificate $TestCertProtected -StoreLocation CurrentUser -StoreName My -NoWarn - Uninstall-CCertificate -Certificate $TestCertProtected -StoreLocation LocalMachine -StoreName My -NoWarn -} - -Describe "Install-Certificate" { - - foreach( $location in @('CurrentUser', 'LocalMachine') ) - { - Context "for $($location)" { - function Assert-CertificateInstalled - { - param( - $StoreLocation = 'CurrentUser', - $StoreName = 'My', - $ExpectedCertificate = $TestCert - ) - - $duration = [Diagnostics.Stopwatch]::StartNew() - $timeout = New-Object 'TimeSpan' (0, 0, 10) - do - { - $cert = Get-CCertificate -Thumbprint $ExpectedCertificate.Thumbprint ` - -StoreLocation $StoreLocation ` - -StoreName $StoreName ` - -NoWarn - if( $cert ) - { - break - } - - Write-Verbose "Couldn't find $($StoreLocation)\$($StoreName)\$($ExpectedCertificate.Thumbprint). Trying again in 100ms." -Verbose - Start-Sleep -Milliseconds 100 - } - while( $duration.Elapsed -lt $timeout ) - $duration.Stop() - $duration = $null - - $cert | Should -Not -BeNullOrEmpty | Out-Null - $cert.Thumbprint | Should -Be $ExpectedCertificate.Thumbprint | Out-Null - if( $cert.HasPrivateKey ) - { - $cert.PrivateKey | Should -Not -BeNullOrEmpty - } - return $cert - } - - BeforeEach { - $Global:Error.Clear() - Reset - } - - AfterEach { - Reset - } - - It 'should install certificate' { - $cert = Install-CCertificate -Path $TestCertPath -StoreLocation $location -StoreName My - $cert.Thumbprint | Should -Be $TestCert.Thumbprint - $cert = Assert-CertificateInstalled -StoreLocation $location -StoreName My - { - $bytes = $cert.Export( [Security.Cryptography.X509Certificates.X509ContentType]::Pfx ) - } | Should -Throw - } - - It 'should install certificate with relative path' { - $DebugPreference = 'Continue' - Push-Location -Path $PSScriptRoot - try - { - $path = '.\Certificates\{0}' -f (Split-Path -Leaf -Path $TestCertPath) - $cert = Install-CCertificate -Path $path -StoreLocation $location -StoreName My -Verbose -NoWarn - $cert.Thumbprint | Should -Be $TestCert.Thumbprint - $cert = Assert-CertificateInstalled -StoreLocation $location -StoreName My - } - finally - { - Pop-Location - } - } - - It 'should install certificate as exportable' { - $cert = Install-CCertificate -Path $TestCertPath -StoreLocation $location -StoreName My -Exportable -NoWarn - $cert.Thumbprint | Should -Be $TestCert.Thumbprint - $cert = Assert-CertificateInstalled -StoreLocation $location -StoreName My - $bytes = $cert.Export( [Security.Cryptography.X509Certificates.X509ContentType]::Pfx ) - $bytes | Should -Not -BeNullOrEmpty - } - - It 'should install certificate in custom store' { - $cert = Install-CCertificate -Path $TestCertPath -StoreLocation $location -CustomStoreName 'SharePoint' -NoWarn - $cert | Should -Not -BeNullOrEmpty - "cert:\$($location)\SharePoint" | Should -Exist - "cert:\$($location)\SharePoint\$($cert.Thumbprint)" | Should -Exist - } - - It 'should install certificate idempotently' { - $countOfPrivateKeys = Measure-MachineKey $location - Install-CCertificate -Path $TestCertProtectedPath ` - -Password 'password' ` - -StoreLocation $location ` - -StoreName My ` - -NoWarn - $Global:Error | Should -BeNullOrEmpty - Install-CCertificate -Path $TestCertProtectedPath ` - -Password 'password' ` - -StoreLocation $location ` - -StoreName My ` - -NoWarn - $Global:Error | Should -BeNullOrEmpty - Assert-CertificateInstalled $location My $TestCertProtected - Measure-MachineKey $location | Should -Be ($countOfPrivateKeys + 1) - } - - It 'should re-install certificate when forced' { - $countOfPrivateKeys = Measure-MachineKey $location - Install-CCertificate -Path $TestCertProtectedPath ` - -Password 'password' ` - -StoreLocation $location ` - -StoreName My ` - -NoWarn - $Global:Error | Should -BeNullOrEmpty - Install-CCertificate -Path $TestCertProtectedPath ` - -Password 'password' ` - -StoreLocation $location ` - -StoreName My ` - -NoWarn ` - -Force - $Global:Error | Should -BeNullOrEmpty - Assert-CertificateInstalled $location My $TestCertProtected - Measure-MachineKey $location | Should -Be ($countOfPrivateKeys + 2) - } - - It 'should install certificate' { - $cert = Install-CCertificate -Certificate $TestCert -StoreLocation $location -StoreName My -NoWarn - $cert | Should -Not -BeNullOrEmpty - Assert-CertificateInstalled $location My - } - - It 'should install password protected certificate' { - $countOfPrivateKeys = Measure-MachineKey $location - $cert = Install-CCertificate -Path $TestCertProtectedPath ` - -Password 'password' ` - -StoreLocation $location ` - -StoreName My ` - -NoWarn - $cert | Should -Not -BeNullOrEmpty - Assert-CertificateInstalled $location My $TestCertProtected - # Regression: make sure importing the certificate doesn't leave behind an extra file in MachineKeys. - Measure-MachineKey $location | Should -Be ($countOfPrivateKeys + 1) - } - - It 'should install certificate in remote computer' -Skip:(Test-Path -Path 'env:APPVEYOR') { - $session = New-PSSession -ComputerName $env:COMPUTERNAME - try - { - $cert = Install-CCertificate -Certificate $TestCert -StoreLocation $location -StoreName My -Session $session -NoWarn - $cert | Should -Not -BeNullOrEmpty - Assert-CertificateInstalled $location My - } - finally - { - Remove-PSSession -Session $session - } - } - - It 'should support ShouldProcess' { - $cert = Install-CCertificate -Path $TestCertPath -StoreLocation $location -StoreName My -WhatIf -NoWarn - $cert.Thumbprint | Should -Be $TestCert.Thumbprint - Join-Path -Path "cert:\$($location)\My" -ChildPath $TestCert.Thumbprint | - Should -Not -Exist - } - } - } -} diff --git a/Test/Protect-String.Tests.ps1 b/Test/Protect-String.Tests.ps1 deleted file mode 100644 index 4f7ee3de..00000000 --- a/Test/Protect-String.Tests.ps1 +++ /dev/null @@ -1,278 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -Set-StrictMode -Version 'Latest' - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -$publicKeyFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPublicKey.cer' -Resolve -$privateKeyFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPrivateKey.pfx' -Resolve -$dsaKeyPath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestDsaKey.cer' -Resolve - -Describe 'Protect-String' { - - BeforeEach { - $Global:Error.Clear() - } - - function Assert-IsBase64EncodedString($String) - { - $String | Should Not BeNullOrEmpty 'Didn''t encrypt cipher text.' - { [Convert]::FromBase64String( $String ) } | Should Not Throw - } - - It 'should protect string' { - $cipherText = Protect-String -String 'Hello World!' -ForUser - Assert-IsBase64EncodedString( $cipherText ) - } - - It 'should protect string with scope' { - $user = Protect-String -String 'Hello World' -ForUser - $machine = Protect-String -String 'Hello World' -ForComputer - $machine | Should -Not -Be $user -Because 'encrypting at different scopes resulted in the same string' - } - - It 'should protect strings in pipeline' { - $secrets = @('Foo','Fizz','Buzz','Bar') | Protect-String -ForUser - $secrets.Length | Should Be 4 'Didn''t encrypt all items in the pipeline.' - foreach( $secret in $secrets ) - { - Assert-IsBase64EncodedString $secret - } - } - - if( -not (Test-Path -Path 'env:CCNetArtifactDirectory') ) - { - It 'should protect string for credential' { - # special chars to make sure they get handled correctly - $string = ' f u b a r '' " > ~!@#$%^&*()_+`-={}|:"<>?[]\;,./' - $protectedString = Protect-String -String $string -Credential $CarbonTestUser - $protectedString | Should Not BeNullOrEmpty ('Failed to protect a string as user {0}.' -f $CarbonTestUser.UserName) - - $decrypedString = Invoke-PowerShell -FilePath (Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\Unprotect-String.ps1') ` - -ArgumentList '-ProtectedString',$protectedString ` - -Credential $CarbonTestUser ` - -NoWarn - $decrypedString | Should Be $string - } - - It 'should handle spaces in path to Carbon' { - $tempDir = New-TempDirectory -Prefix 'Carbon Program Files' - try - { - $junctionPath = Join-Path -Path $tempDir -ChildPath 'Carbon' - Install-Junction -Link $junctionPath -Target (Join-Path -Path $PSScriptRoot -ChildPath '..\Carbon' -Resolve) - try - { - Remove-Module 'Carbon' - Import-Module $junctionPath - try - { - $ciphertext = Protect-String -String 'fubar' -Credential $CarbonTestUser - $Global:Error.Count | Should Be 0 - Assert-IsBase64EncodedString $ciphertext - } - finally - { - Remove-Module 'Carbon' - & (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - } - } - finally - { - Uninstall-Junction -Path $junctionPath - } - } - finally - { - Remove-Item -Path $tempDir -Recurse -Force - } - } - } - else - { - Write-Warning ('Can''t test protecting string under another identity: running under CC.Net, and the service user''s profile isn''t loaded, so can''t use Microsoft''s DPAPI.') - } - - It 'should encrypt with certificate' { - $cert = Get-Certificate -Path $publicKeyFilePath -NoWarn - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString() - $ciphertext = Protect-String -String $secret -Certificate $cert - $ciphertext | Should Not BeNullOrEmpty - $ciphertext | Should Not Be $secret - $privateKey = Get-Certificate -Path $privateKeyFilePath -NoWarn - (Unprotect-String -ProtectedString $ciphertext -Certificate $privateKey) | Should Be $secret - } - - It 'should handle not getting an rsa certificate' { - $cert = Get-Certificate -Path $dsaKeyPath -NoWarn - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString() - $ciphertext = Protect-String -String $secret -Certificate $cert -ErrorAction SilentlyContinue - $Global:Error.Count | Should BeGreaterThan 0 - $Global:Error[0] | Should Match 'not an RSA key' - $ciphertext | Should BeNullOrEmpty - } - - It 'should reject strings that are too long for rsa key' { - $cert = Get-Certificate -Path $privateKeyFilePath -NoWarn - $secret = 'f' * 470 - $ciphertext = Protect-String -String $secret -Certificate $cert - $Global:Error.Count | Should Be 0 - $ciphertext | Should Not BeNullOrEmpty - (Unprotect-String -ProtectedString $ciphertext -Certificate $cert) | Should Be $secret - - $secret = 'f' * 472 - $ciphertext = Protect-String -String $secret -Certificate $cert -ErrorAction SilentlyContinue - $Global:Error.Count | Should BeGreaterThan 0 - $Global:Error[0] | Should Match 'String is longer' - $ciphertext | Should BeNullOrEmpty - } - - It 'should encrypt from cert store by thumbprint' { - $cert = Get-ChildItem -Path cert:\* -Recurse | - Where-Object { $_ | Get-Member 'PublicKey' } | - Where-Object { $_.PublicKey.Key -is [Security.Cryptography.RSA] } | - Select-Object -First 1 - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString().Substring(0,20) - $expectedCipherText = Protect-String -String $secret -Thumbprint $cert.Thumbprint - $expectedCipherText | Should Not BeNullOrEmpty - } - - It 'should handle thumbprint not in store' { - $ciphertext = Protect-String -String 'fubar' -Thumbprint '1111111111111111111111111111111111111111' -ErrorAction SilentlyContinue - $Global:Error.Count | Should BeGreaterThan 0 - $Global:Error[0] | Should Match 'not found' - $ciphertext | Should BeNullOrEmpty - } - - It 'should encrypt from cert store by cert path' { - $cert = Get-ChildItem -Path cert:\* -Recurse | - Where-Object { $_ | Get-Member 'PublicKey' } | - Where-Object { $_.PublicKey.Key -is [Security.Cryptography.RSA] } | - Select-Object -First 1 - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString().Substring(0,20) - $certPath = Join-Path -Path 'cert:\' -ChildPath (Split-Path -NoQualifier -Path $cert.PSPath) - $expectedCipherText = Protect-String -String $secret -PublicKeyPath $certPath - $expectedCipherText | Should Not BeNullOrEmpty - } - - It 'should handle path not found' { - $ciphertext = Protect-String -String 'fubar' -PublicKeyPath 'cert:\currentuser\fubar' -ErrorAction SilentlyContinue - $Global:Error.Count | Should BeGreaterThan 0 - $Global:Error[0] | Should Match 'not found' - $ciphertext | Should BeNullOrEmpty - } - - It 'should encrypt from certificate file' { - $cert = Get-Certificate -Path $publicKeyFilePath -NoWarn - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString() - $ciphertext = Protect-String -String $secret -PublicKeyPath $publicKeyFilePath - $ciphertext | Should Not BeNullOrEmpty - $ciphertext | Should Not Be $secret - $privateKey = Get-Certificate -Path $privateKeyFilePath -NoWarn - (Unprotect-String -ProtectedString $ciphertext -Certificate $privateKey) | Should Be $secret - } - - It 'should encrypt a secure string' { - $cert = Get-Certificate -Path $publicKeyFilePath -NoWarn - $cert | Should Not BeNullOrEmpty - $password = 'waffles' - $secret = New-Object -TypeName System.Security.SecureString - $password.ToCharArray() | ForEach-Object { $secret.AppendChar($_) } - - $ciphertext = Protect-String -String $secret -PublicKeyPath $publicKeyFilePath - $ciphertext | Should Not BeNullOrEmpty - $ciphertext | Should Not Be $secret - $privateKey = Get-Certificate -Path $privateKeyFilePath -NoWarn - $decryptedPassword = Unprotect-String -ProtectedString $ciphertext -Certificate $privateKey - $decryptedPassword | Should Be $password - $passwordBytes = [Text.Encoding]::UTF8.GetBytes($password) - $decryptedBytes = [Text.Encoding]::UTF8.GetBytes($decryptedPassword) - $decryptedBytes.Length | Should Be $passwordBytes.Length - for( $idx = 0; $idx -lt $passwordBytes.Length; ++$idx ) - { - $passwordBytes[$idx] | Should Be $decryptedPassword[$idx] - } - } - - It 'should convert passed objects to string' { - $cert = Get-Certificate -Path $publicKeyFilePath -NoWarn - $cert | Should Not BeNullOrEmpty - $input = New-Object -TypeName Carbon.Security.SecureStringConverter - $cipherText = Protect-String -String $input -PublicKeyPath $publicKeyFilePath - $cipherText | Should Not BeNullOrEmpty - $cipherText | Should Not Be $input - $privateKey = Get-Certificate -Path $privateKeyFilePath -NoWarn - Assert-IsBase64EncodedString( $cipherText ) - (Unprotect-String -ProtectedString $cipherText -Certificate $privateKey) | Should Be $input.ToString() - } - - It 'should encrypt from certificate file with relative path' { - $cert = Get-Certificate -Path $publicKeyFilePath -NoWarn - $cert | Should Not BeNullOrEmpty - $secret = [Guid]::NewGuid().ToString() - $ciphertext = Protect-String -String $secret -PublicKeyPath (Resolve-Path -Path $publicKeyFilePath -Relative) - $ciphertext | Should Not BeNullOrEmpty - $ciphertext | Should Not Be $secret - $privateKey = Get-Certificate -Path $privateKeyFilePath -NoWarn - (Unprotect-String -ProtectedString $ciphertext -Certificate $privateKey) | Should Be $secret - } - - It 'should use direct encryption padding switch' { - $secret = [Guid]::NewGuid().ToString() - $ciphertext = Protect-String -String $secret -PublicKeyPath $publicKeyFilePath -UseDirectEncryptionPadding - $ciphertext | Should Not BeNullOrEmpty - $ciphertext | Should Not Be $secret - $revealedSecret = Unprotect-String -ProtectedString $ciphertext -PrivateKeyPath $privateKeyFilePath -UseDirectEncryptionPadding - $revealedSecret | Should Be $secret - } - -} - -foreach( $keySize in @( 128, 192, 256 ) ) -{ - Describe ('Protect-String when given a {0}-bit key' -f $keySize) { - $Global:Error.Clear() - # Generate a secret that is too long for asymmetric encryption - $secret = [Guid]::NewGuid().ToString() * 20 - $guid = [Guid]::NewGuid() - $passphrase = $guid.ToString().Substring(0,($keySize / 8)) - $keyBytes = [Text.Encoding]::UTF8.GetBytes($passphrase) - $keySecureString = New-Object -TypeName 'Security.SecureString' - foreach( $char in $passphrase.ToCharArray() ) - { - $keySecureString.AppendChar($char) - } - - foreach( $key in @( $passphrase,$keyBytes,$keySecureString) ) - { - Context ('key as {0}' -f $key.GetType().FullName) { - $ciphertext = Protect-String -String $secret -Key $key - It 'should return ciphertext' { - $ciphertext | Should Not BeNullOrEmpty - ConvertFrom-Base64 -Value $ciphertext | Should Not BeNullOrEmpty - $Global:Error.Count | Should Be 0 - } - - It 'should encrypt ciphertext' { - $revealedSecret = Unprotect-String -ProtectedString $ciphertext -Key $key - $revealedSecret | Should Be $secret - } - } - } - } -} diff --git a/Test/Security/Test-ConvertSecureStringToString.ps1 b/Test/Security/Test-ConvertSecureStringToString.ps1 deleted file mode 100644 index 99f3b683..00000000 --- a/Test/Security/Test-ConvertSecureStringToString.ps1 +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldConvertSecureStringToString -{ - $secret = "Hello World!" - $secureString = ConvertTo-SecureString -String $secret -AsPlainText -Force - $notSoSecret = Convert-SecureStringToString $secureString -NoWarn - Assert-Equal $secret $notSoSecret "Didn't convert a secure string to a string." -} - diff --git a/Test/Uninstall-Certificate.Tests.ps1 b/Test/Uninstall-Certificate.Tests.ps1 deleted file mode 100644 index 7bf1042f..00000000 --- a/Test/Uninstall-Certificate.Tests.ps1 +++ /dev/null @@ -1,188 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -Set-StrictMode -Version 'Latest' - -$TestCertPath = Join-Path -Path $PSScriptRoot -ChildPath 'Certificates\CarbonTestCertificate.cer' -Resolve -$TestCert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 $TestCertPath -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -Describe 'Uninstall-Certificate' { - - BeforeEach { - if( -not (Test-Path Cert:\CurrentUser\My\$TestCert.Thumbprint -PathType Leaf) ) - { - Install-Certificate -Path $TestCertPath -StoreLocation CurrentUser -StoreName My -NoWarn - } - } - - It 'should remove certificate by certificate' { - Uninstall-Certificate -Certificate $TestCert -StoreLocation CurrentUser -StoreName My - $cert = Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - $cert | Should BeNullOrEmpty - } - - It 'should remove certificate by thumbprint' { - Uninstall-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My - $maxTries = 10 - $tryNum = 0 - do - { - $cert = Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - if( -not $cert ) - { - break - } - Start-Sleep -Milliseconds 100 - } - while( $tryNum++ -lt $maxTries ) - $cert | Should BeNullOrEmpty - } - - It 'should support WhatIf' { - Uninstall-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -WhatIf - $cert = Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - $cert | Should Not BeNullOrEmpty - } - - It 'should uninstall certificate from custom store' { - $cert = Install-Certificate -Path $TestCertPath -StoreLocation CurrentUser -CustomStoreName 'Carbon' - $cert | Should Not BeNullOrEmpty - $certPath = 'Cert:\CurrentUser\Carbon\{0}' -f $cert.Thumbprint - $certPath | Should Exist - Uninstall-Certificate -Thumbprint $cert.Thumbprint -StoreLocation CurrentUser -CustomStoreName 'Carbon' -Verbose - while( (Test-Path -Path $certPath) ) - { - Write-Verbose -Message ('Waiting for "{0}" to get deleted.' -f $certPath) - Start-Sleep -Seconds 1 - } - $certPath | Should Not Exist - } - - It 'should uninstall certificate from remote computer' -Skip:(Test-Path -Path 'env:APPVEYOR') { - $Global:Error.Clear() - - $session = New-PSSession -ComputerName $env:COMPUTERNAME - try - { - Uninstall-Certificate -Thumbprint $TestCert.Thumbprint ` - -StoreLocation CurrentUser ` - -StoreName My ` - -Session $session - $Global:Error.Count | Should Be 0 - - $cert = Get-Certificate -Thumbprint $TestCert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - $cert | Should BeNullOrEmpty - } - finally - { - Remove-PSSession -Session $session - } - } -} - -function GivenARemotingSession -{ - $script:session = New-PSSession -ComputerName $env:COMPUTERNAME -} - -function GivenAnInstalledCertificate -{ - param( - $StoreLocation = 'CurrentUser', - $StoreName = 'My' - ) - Install-Certificate -Path $TestCertPath -StoreLocation $StoreLocation -StoreName $StoreName -} - -function WhenPipedMultipleThumbprints -{ - $TestCert.Thumbprint,$TestCert.Thumbprint | Uninstall-Certificate -} - -function WhenUninstallingViaRemoting -{ - try - { - $TestCert | Uninstall-Certificate -Session $session -NoWarn - } - finally - { - $session | Remove-PSSession - } -} - -function WhenUninstallPipedCertificate -{ - $TestCert | Uninstall-Certificate -} - -function WhenUninstallingByThumbprint -{ - Uninstall-Certificate -Thumbprint $TestCert.Thumbprint -NoWarn -} - -function WhenUninstallPipedThumbprint -{ - $TestCert.Thumbprint | Uninstall-Certificate -NoWarn -} - -function ThenCertificateUninstalled -{ - It 'should uninstall the certificate' { - Join-Path -Path 'cert:\*\*' -ChildPath $TestCert.Thumbprint | Should Not Exist - } -} - -Describe 'Uninstall-Certificate.when given just the certificate thumbprint' { - GivenAnInstalledCertificate - WhenUninstallingByThumbprint - ThenCertificateUninstalled -} - -Describe 'Uninstall-Certificate.when given just the certificate thumbprint and installed in multiple stores' { - GivenAnInstalledCertificate - GivenAnInstalledCertificate -StoreLocation 'CurrentUser' -StoreName 'My' - GivenAnInstalledCertificate -StoreLocation 'LocalMachine' -StoreName 'My' - GivenAnInstalledCertificate -StoreLocation 'LocalMachine' -StoreName 'Root' - WhenUninstallingByThumbprint - ThenCertificateUninstalled -} - -Describe 'Uninstall-Certificate.when piped thumbprint' { - GivenAnInstalledCertificate - WhenUninstallPipedThumbprint - ThenCertificateUninstalled -} - -Describe 'Uninstall-Certificate.when piped certificate object' { - GivenAnInstalledCertificate - WhenUninstallPipedCertificate - ThenCertificateUninstalled -} - -Describe 'Uninstall-Certificate.when piped multiple thumbprints' { - GivenAnInstalledCertificate - WhenPipedMultipleThumbprints - ThenCertificateUninstalled -} - -# This test ensures that certificates are uninstalled from LocalMachine stores *first*, since they will also show up in CurrentUser stores and if SYSTEM deletes the certificate in a headless process from the CurrentUser stores first, it will fail. - -Describe 'Uninstall-Certificate.when local machine cert shows up in current user store' { - GivenAnInstalledCertificate - Mock -CommandName 'Get-ChildItem' -ModuleName 'Carbon' -ParameterFilter { $Path.Count -eq 2 -and $Path[0] -eq 'Cert:\LocalMachine' -and $Path[1] -eq 'Cert:\CurrentUser' } - WhenUninstallingByThumbprint - It 'should get certificates from LocalMachine stores first' { - Assert-MockCalled -CommandName 'Get-ChildItem' -ModuleName 'Carbon' -Times 1 - } -} \ No newline at end of file diff --git a/Test/Unprotect-String.Tests.ps1 b/Test/Unprotect-String.Tests.ps1 deleted file mode 100644 index d25892d8..00000000 --- a/Test/Unprotect-String.Tests.ps1 +++ /dev/null @@ -1,214 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -& (Join-Path -Path $PSScriptRoot 'Initialize-CarbonTest.ps1' -Resolve) - -$originalText = $null -$secret = [Guid]::NewGuid().ToString() -$rsaCipherText = $null -$publicKeyPath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPublicKey.cer' -Resolve -$privateKeyPath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPrivateKey.pfx' -Resolve -$publicKey2Path = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPublicKey2.cer' -Resolve -$privateKey2Path = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPrivateKey2.pfx' -Resolve -$dsaKeyPath = Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestDsaKey.cer' -Resolve - -$rsaCipherText = Protect-String -String $secret -PublicKeyPath $privateKeyPath -NoWarn - -Describe 'Unprotect-String.RSA' { - BeforeEach { - $Global:Error.Clear() - } - - It 'should unprotect string' { - $originalText = [Guid]::NewGuid().ToString() - $protectedText = Protect-String -String $originalText -ForUser -NoWarn - $actualText = Unprotect-String -ProtectedString $protectedText -NoWarn - $actualText | Should -Be $originalText - } - - - It 'should unprotect string from machine scope' { - $secret = Protect-String -String 'Hello World' -ForComputer -NoWarn - $machine = Unprotect-String -ProtectedString $secret -NoWarn - $machine | Should -Be 'Hello World' - } - - It 'should unprotect string from user scope' { - $secret = Protect-String -String 'Hello World' -ForUser -NoWarn - $machine = Unprotect-String -ProtectedString $secret -NoWarn - $machine | Should -Be 'Hello World' - } - - - It 'should unrotect strings in pipeline' { - $secrets = @('Foo','Fizz','Buzz','Bar') | Protect-String -ForUser | Unprotect-String -NoWarn - $secrets[0] | Should -Be 'Foo' - $secrets[1] | Should -Be 'Fizz' - $secrets[2] | Should -Be 'Buzz' - $secrets[3] | Should -Be 'Bar' - } - - It 'should load certificate from file' { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath $privateKeyPath -NoWarn - $Global:Error.Count | Should -Be 0 - $revealedSecret | Should -Be $secret - } - - It 'should handle missing private key' { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath $publicKeyPath -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'doesn''t have a private key' - $revealedSecret | Should -BeNullOrEmpty - } - - # Don't actually know how to generate a non-RSA private key. May not even be possible. - It 'should handle non rsa key' -Skip { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath $dsaKeyPath -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'not an RSA key' - $revealedSecret | Should -BeNullOrEmpty - } - - # This test doesn't work on Windows 2012 R2. Bug fix? - It 'should handle ciphertext that is too long' -Skip { - $cert = Get-Certificate -Path $privateKeyPath -NoWarn - $secret = 'f' * 471 - #Write-Host $secret.Length - $ciphertext = Protect-String -String $secret -Certificate $cert -NoWarn - $Global:Error.Count | Should -Be 0 - $ciphertext | Should -Not -BeNullOrEmpty - (Unprotect-String -ProtectedString $ciphertext -Certificate $cert -ErrorAction SilentlyContinue) | Should -BeNullOrEmpty - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'too long' - } - - It 'should load password protected private key' { - $ciphertext = Protect-String -String $secret -PublicKeyPath $publicKey2Path -NoWarn - $revealedText = Unprotect-String -ProtectedString $ciphertext -PrivateKeyPath $privateKey2Path -Password 'fubar' -NoWarn - $Global:Error.Count | Should -Be 0 - $revealedText | Should -Be $secret - } - - It 'should decrypt with different padding flag' { - $revealedText = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath $privateKeyPath -UseDirectEncryptionPadding -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'padding algorithm' - $revealedText | Should -BeNullOrEmpty - } - - It 'should handle unencrypted string' { - $stringBytes = [Text.Encoding]::UTF8.GetBytes( 'fubar' ) - $mySecret = [Convert]::ToBase64String( $stringBytes ) - $result = Unprotect-String -ProtectedString $mySecret -PrivateKeyPath $privateKeyPath -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'different key' - $result | Should -BeNullOrEmpty - } - - It 'should handle encrypted by different key' { - $ciphertext = Protect-String -String 'fubar' -PublicKeyPath $publicKey2Path -NoWarn - $result = Unprotect-String -ProtectedString $ciphertext -PrivateKeyPath $privateKeyPath -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'isn''t encrypted' - $result | Should -BeNullOrEmpty - } - - It 'should decrypt with certificate' { - $cert = Get-Certificate -Path $privateKeyPath -NoWarn - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -Certificate $cert -NoWarn - $Global:Error.Count | Should -Be 0 - $revealedSecret | Should -Be $secret - } - - It 'should decrypt with thumbprint' { - $cert = Install-Certificate -Path $privateKeyPath -StoreLocation CurrentUser -StoreName My -NoWarn - try - { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -Thumbprint $cert.Thumbprint -NoWarn - $Global:Error.Count | Should -Be 0 - $revealedSecret | Should -Be $secret - } - finally - { - Uninstall-Certificate -Thumbprint $cert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - } - } - - It 'should handle invalid thumbprint' { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -Thumbprint ('1' * 40) -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'not found' - $revealedSecret | Should -BeNullOrEmpty - } - - It 'should handle thumbprint to cert with no private key' { - $cert = Get-ChildItem -Path 'cert:\*\*' -Recurse | - Where-Object { $_.PublicKey.Key -is [Security.Cryptography.RSA] } | - Where-Object { -not $_.HasPrivateKey } | - Select-Object -First 1 - $cert | Should -Not -BeNullOrEmpty - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -Thumbprint $cert.Thumbprint -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'doesn''t have a private key' - $revealedSecret | Should -BeNullOrEmpty - } - - It 'should decrypt with path to cert in store' { - $cert = Install-Certificate -Path $privateKeyPath -StoreLocation CurrentUser -StoreName My -NoWarn - try - { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath ('cert:\CurrentUser\My\{0}' -f $cert.Thumbprint) -NoWarn - $Global:Error.Count | Should -Be 0 - $revealedSecret | Should -Be $secret - } - finally - { - Uninstall-Certificate -Thumbprint $cert.Thumbprint -StoreLocation CurrentUser -StoreName My -NoWarn - } - } - - It 'should handle path not found' { - $revealedSecret = Unprotect-String -ProtectedString $rsaCipherText -PrivateKeyPath 'C:\fubar.cer' -ErrorAction SilentlyContinue -NoWarn - $Global:Error.Count | Should -BeGreaterThan 0 - $Global:Error[0] | Should -Match 'not found' - $revealedSecret | Should -BeNullOrEmpty - } - - It 'should convert to secure string' { - $originalText = [Guid]::NewGuid().ToString() - $protectedText = Protect-String -String $originalText -ForUser - [securestring]$secureSecret = Unprotect-String -ProtectedString $protectedText -AsSecureString -NoWarn - $secureSecret | Should -BeOfType ([securestring]) - (Convert-SecureStringToString -SecureString $secureSecret -NoWarn) | Should -Be $originalText - $secureSecret.IsReadOnly() | Should -Be $true - } -} - -Describe 'Unprotect-String.AES' { - It 'should fail on invalid key length' { - $key = 'a' * 8 - { Protect-CString -String 'text' -Key $key -ErrorAction Stop } | - Should -Throw 'requires a 128-bit, 192-bit, or 256-bit key (16, 24, or 32 bytes, respectively).' - } - - foreach ($keyLength in @(16, 24, 32)) - { - It "should succeed with key length: $($keyLength)" { - $key = 'a' * $keyLength - $originalText = [Guid]::NewGuid().ToString() - $protectedText = Protect-CString -String $originalText -Key $key -NoWarn - $actualText = Unprotect-CString -ProtectedString $protectedText -Key $key -NoWarn - $actualText | Should -Be $originalText -Because 'the decrypted string should be unchanged' - $actualText.Length | Should -Be $originalText.Length -Because 'the decrypted string should not contain any extra bytes' - } - } -} diff --git a/whiskey.yml b/whiskey.yml index 2e873ade..00089ba1 100644 --- a/whiskey.yml +++ b/whiskey.yml @@ -154,8 +154,6 @@ Tests: - Pester4: OnlyBy: BuildServer Script: - - Test\Install-Certificate.Tests.ps1 - - Test\Uninstall-Certificate.Tests.ps1 - Test\Invoke-PowerShell.Tests.ps1 - Test\*Iis*.ps1 - Test\Carbon_*.Tests.ps1 @@ -171,8 +169,6 @@ Tests: Script: - Test\*.Tests.ps1 Exclude: - - "*\\Test\\Install-Certificate.Tests.ps1" - - "*\\Test\\Uninstall-Certificate.Tests.ps1" - "*\\Test\\*Iis*.ps1" - "*\\Test\\Carbon_*.Tests.ps1" - "*\\Test\\*-ScheduledTask.Tests.ps1" From 6d537f203c62ff6b706642784a635920dc520310 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 19 Nov 2021 15:15:41 -0800 Subject: [PATCH 05/20] Don't run tests for functions that moved to Carbon.Core. --- Test/Computer/Test-TestOSIs32Bit.ps1 | 23 -- Test/Computer/Test-TestOSIs64Bit.ps1 | 23 -- Test/Invoke-PowerShell.Tests.ps1 | 352 ------------------ Test/PowerShell/Test-GetPowerShellPath.ps1 | 65 ---- .../PowerShell/Test-TestPowerShellIs32Bit.ps1 | 23 -- .../PowerShell/Test-TestPowerShellIs64Bit.ps1 | 23 -- Test/Text/Test-ConvertToBase64.ps1 | 82 ---- whiskey.yml | 2 - 8 files changed, 593 deletions(-) delete mode 100644 Test/Computer/Test-TestOSIs32Bit.ps1 delete mode 100644 Test/Computer/Test-TestOSIs64Bit.ps1 delete mode 100644 Test/Invoke-PowerShell.Tests.ps1 delete mode 100644 Test/PowerShell/Test-GetPowerShellPath.ps1 delete mode 100644 Test/PowerShell/Test-TestPowerShellIs32Bit.ps1 delete mode 100644 Test/PowerShell/Test-TestPowerShellIs64Bit.ps1 delete mode 100644 Test/Text/Test-ConvertToBase64.ps1 diff --git a/Test/Computer/Test-TestOSIs32Bit.ps1 b/Test/Computer/Test-TestOSIs32Bit.ps1 deleted file mode 100644 index 2f55acff..00000000 --- a/Test/Computer/Test-TestOSIs32Bit.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldDetectIfOSIs32Bit -{ - $is32Bit = -not (Test-Path env:"ProgramFiles(x86)") - Assert-Equal $is32Bit (Test-OSIs32Bit -NoWarn) -} - diff --git a/Test/Computer/Test-TestOSIs64Bit.ps1 b/Test/Computer/Test-TestOSIs64Bit.ps1 deleted file mode 100644 index 5f2ed767..00000000 --- a/Test/Computer/Test-TestOSIs64Bit.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldDetectIfOSIs64Bit -{ - $is64Bit = (Test-Path env:"ProgramFiles(x86)") - Assert-Equal $is64Bit (Test-OSIs64Bit -NoWarn) -} - diff --git a/Test/Invoke-PowerShell.Tests.ps1 b/Test/Invoke-PowerShell.Tests.ps1 deleted file mode 100644 index be24323c..00000000 --- a/Test/Invoke-PowerShell.Tests.ps1 +++ /dev/null @@ -1,352 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -Set-StrictMode -Version 'Latest' - -& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-CarbonTest.ps1' -Resolve) - -$ps3Installed = $false -$PSVersion,$CLRVersion = powershell -NoProfile -NonInteractive -Command { $PSVersionTable.PSVersion ; $PSVersionTable.CLRVersion } -$getPsVersionTablePath = Join-Path -Path $PSScriptRoot -ChildPath 'PowerShell\Get-PSVersionTable.ps1' -Resolve - -# Make sure the execution policy gets set in the different architectures of PowerShell -$setExecPolicyScriptBlock = { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned } -Invoke-CPowerShell -ScriptBlock $setExecPolicyScriptBlock -Invoke-CPowerShell -ScriptBlock $setExecPolicyScriptBlock -x86 - -function Assert-EnvVarCleanedUp -{ - It 'should clean up environment' { - ([Environment]::GetEnvironmentVariable('COMPLUS_ApplicationMigrationRuntimeActivationConfigPath')) | Should BeNullOrEmpty - } -} - -Describe 'Invoke-PowerShell.when running a ScriptBlock' { - $command = { - param( - $Argument - ) - - $Argument - } - - $result = Invoke-PowerShell -ScriptBlock $command -Args 'Hello World!' - It 'should execute the scriptblock' { - $result | Should Be 'Hello world!' - } -} - -Describe 'Invoke-PowerShell.when running a 32-bit PowerShell' { - $command = { - $env:PROCESSOR_ARCHITECTURE - } - - $result = Invoke-PowerShell -ScriptBlock $command -x86 -NoWarn - It 'should run under x86' { - $result | Should Be 'x86' - } -} - -if( Test-Path -Path HKLM:\SOFTWARE\Microsoft\PowerShell\3 ) -{ - if( $Host.Name -eq 'Windows PowerShell ISE Host' ) - { - Describe 'Invoke-PowerShell.when in the ISE host and running a scripb block under PowerShell 2' { - $command = { - $PSVersionTable.CLRVersion - } - - $error.Clear() - $result = Invoke-PowerShell -ScriptBlock $command -Runtime v2.0 -ErrorAction SilentlyContinue -NoWarn - It 'should write an error' { - $error.Count | Should Be 1 - } - - It 'should not execute the script block' { - $result | Should BeNullOrEmpty - } - - Assert-EnvVarCleanedUp - } - } - else - { - Describe 'Invoke-PowerShell.when in the console host and running a script blcok under PowerShell 2' { - if( (Test-Path -Path 'env:APPVEYOR') ) - { - return - } - - It '(the test) should make sure .NET 2 is installed' { - (Test-DotNet -V2) | Should Be $true - } - $command = { - $PSVersionTable.CLRVersion - } - - $error.Clear() - $result = Invoke-PowerShell -ScriptBlock $command -Runtime v2.0 -NoWarn - It 'should not write an error' { - $error.Count | Should Be 0 - } - - It 'should execute the script block' { - $result | Should Not BeNullOrEmpty - $result.Major | Should Be 2 - } - - Assert-EnvVarCleanedUp - } - } -} - -Describe 'Invoke-PowerShell.when running a command under PowerShell 4' { - $command = { - $PSVersionTable.CLRVersion - } - - $result = Invoke-PowerShell -Command $command -Runtime v4.0 -NoWarn - It 'should run the command' { - $result.Major | Should Be 4 - } - - Assert-EnvVarCleanedUp -} - -if( (Test-OSIs64Bit) ) -{ - Describe 'Invoke-PowerShell.when running x86 PowerShell' { - $error.Clear() - if( (Test-PowerShellIs32Bit) ) - { - $result = Invoke-PowerShell -ScriptBlock { $env:PROCESSOR_ARCHITECTURE } -NoWarn - } - else - { - $command = @" -& "$(Join-Path -Path $PSScriptRoot -ChildPath '..\Carbon\Import-Carbon.ps1' -Resolve)" -`$WarningPreference = 'SilentlyContinue' - -if( -not (Test-PowerShellIs32Bit) ) -{ - throw 'Not in 32-bit PowerShell!' -} -Invoke-PowerShell -ScriptBlock { `$env:PROCESSOR_ARCHITECTURE } -"@ - $result = Invoke-PowerShell -Command $command -Encode -x86 -NoWarn - } - - It 'should not write an error' { - $error.Count | Should Be 0 - } - - It 'should execute the scriptblock' { - $result | Should Be 'AMD64' - } - } -} - -Describe 'Invoke-PowerShell.when running 32-bit script block from 32-bit PowerShell' { - $error.Clear() - if( (Test-PowerShellIs32Bit) ) - { - $result = Invoke-PowerShell -ScriptBlock { $env:ProgramFiles } -x86 -NoWarn - } - else - { - $command = @" -& "$(Join-Path -Path $PSScriptRoot -ChildPath '..\Carbon\Import-Carbon.ps1' -Resolve)" - -if( -not (Test-PowerShellIs32Bit) ) -{ - throw 'Not in 32-bit PowerShell!' -} -Invoke-PowerShell -ScriptBlock { `$env:ProgramFiles } -x86 -"@ - $result = Invoke-PowerShell -Command $command -Encode -x86 -NoWarn - } - - It 'should not write an error' { - $error.Count | Should Be 0 - } - - It 'should run command under 32-bit PowerShell' { - ($result -like '*Program Files (x86)*') | Should Be $true - } -} - -Describe 'Invoke-PowerShell.when running a script' { - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -OutputFormat XML ` - -ExecutionPolicy RemoteSigned ` - -NoWarn - It 'should run the script' { - $result.Length | Should Be 3 - $result[0] | Should Be '' - $result[1] | Should Not BeNullOrEmpty - $result[1].PSVersion | Should Be $PSVersion - $result[1].CLRVersion | Should Be $CLRVersion - $result[2] | Should Not BeNullOrEmpty - $architecture = 'AMD64' - if( Test-OSIs32Bit ) - { - $architecture = 'x86' - } - $result[2] | Should Be $architecture - } -} - -Describe 'Invoke-PowerShell.when running a script with arguments' { - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -OutputFormat XML ` - -ArgumentList '-Message',"'Hello World'" ` - -ExecutionPolicy RemoteSigned ` - -NoWarn - It 'should pass arguments to the script' { - $result.Length | Should Be 3 - $result[0] | Should Be "'Hello World'" - $result[1] | Should Not BeNullOrEmpty - $result[1].PSVersion | Should Be $PSVersion - $result[1].CLRVersion | Should Be $CLRVersion - } -} - -Describe 'Invoke-PowerShell.when running script with -x86 switch' { - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -OutputFormat XML ` - -x86 ` - -ExecutionPolicy RemoteSigned ` - -NoWarn - It 'should run under 32-bit PowerShell' { - $result[2] | Should Be 'x86' - } -} - -Describe 'Invoke-PowerShell.when running script with v4.0 runtime' { - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -OutputFormat XML ` - -Runtime 'v4.0' ` - -ExecutionPolicy RemoteSigned ` - -NoWarn - - It 'should run under 4.0 CLR' { - ($result[1].CLRVersion -like '4.0.*') | Should Be $true - } -} - -Describe 'Invoke-PowerShell.when running script under v2.0 runtime' { - It '[the test] should make sure .NET 2 is installed' { - (Test-DotNet -V2) | Should Be $true - } - - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -OutputFormat XML ` - -Runtime 'v2.0' ` - -ExecutionPolicy RemoteSigned ` - -NoWarn - - $result | Write-Debug - It 'should run under .NET 2.0 CLR' { - ,$result | Should Not BeNullOrEmpty - ($result[1].CLRVersion -like '2.0.*') | Should Be $true - } -} - -Describe 'Invoke-PowerShell.when setting execution policy when running a script' { - $Global:Error.Clear() - $result = Invoke-PowerShell -FilePath $getPsVersionTablePath ` - -ExecutionPolicy Restricted ` - -ErrorAction SilentlyContinue 2>$null - - It 'should set the execution policy' { - $result | Should BeNullOrEmpty - ($Global:Error -join [Environment]::NewLine) | Should Match 'disabled' - } -} - -$getUsernamePath = Join-Path -Path $PSScriptRoot -ChildPath 'PowerShell\Get-Username.ps1' -Resolve - -Describe 'Invoke-PowerShell.when running a script as another user' { - $Global:Error.Clear() - $return = 'fubar' - $result = Invoke-PowerShell -FilePath $getUsernamePath ` - -ArgumentList '-InputObject',$return ` - -Credential $CarbonTestUser ` - -NoWarn - It 'should run the script' { - $result.Count | Should Be 2 - $result[0] | Should Be $return - $result[1] | Should Be $CarbonTestUser.UserName - } - - $result = Invoke-PowerShell -FilePath $getUsernamePath ` - -ArgumentList '-InputObject',$return ` - -ExecutionPolicy Restricted ` - -Credential $CarbonTestUser ` - -ErrorAction SilentlyContinue ` - -NoWarn - It 'should use PowerShell parameters' { - $result | Should BeNullOrEmpty - ($Global:Error -join [Environment]::NewLine) | Should Match 'disabled' - } -} - -Describe 'Invoke-PowerShell.when running a command as another user' { - $Global:Error.Clear() - $result = Invoke-PowerShell -Command '$env:Username' -Credential $CarbonTestUser -NoWarn - It 'should run the command as the user' { - $result | Should Be $CarbonTestUser.UserName - } - - $result = Invoke-PowerShell -Command $getUsernamePath -ExecutionPolicy Restricted -Credential $CarbonTestUser -ErrorAction SilentlyContinue -NoWarn - It 'should set powershell.exe parameters' { - $result | Should BeNullOrEmpty - ($Global:Error -join [Environment]::NewLine) | Should Match 'disabled' - } -} - -Describe 'Invoke-PowerShell.when running a script block as another user' { - $Global:Error.Clear() - $result = Invoke-PowerShell -Command { 'fubar' } -Credential $CarbonTestUser -ErrorAction SilentlyContinue -NoWarn - It 'should write an error' { - $Global:Error | Should Match 'script block as another user' - } - It 'should not write anything' { - $result | Should BeNullOrEmpty - } -} - -Describe 'Invoke-PowerShell.when running a command with an argument list' { - $Global:Error.Clear() - $result = Invoke-PowerShell -Command 'write-host fubar' -ArgumentList 'snafu' -ErrorAction SilentlyContinue -NoWarn - It 'should write an error' { - $Global:Error | Should Match 'doesn''t support' - } - - It 'should not run the command' { - $result | Should BeNullOrEmpty - } -} - -Describe 'Invoke-PowerShell.when running non-interactively' { - $Global:Error.Clear() - $result = Invoke-PowerShell -Command 'Read-Host ''prompt''' -NonInteractive -ErrorAction SilentlyContinue -NoWarn - It 'should write an error' { - Invoke-Command -ScriptBlock { - # The message can be in different places depending on host - $result - ($Global:Error -join [Environment]::NewLine) - } | - Where-Object { $_ -match 'is in NonInteractive mode' } | - Should Not BeNullOrEmpty - } -} diff --git a/Test/PowerShell/Test-GetPowerShellPath.ps1 b/Test/PowerShell/Test-GetPowerShellPath.ps1 deleted file mode 100644 index 1816141b..00000000 --- a/Test/PowerShell/Test-GetPowerShellPath.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldGetPowerShellPath -{ - $expectedPath = Join-Path $PSHome powershell.exe - if( (Test-OsIs64Bit) -and (Test-PowerShellIs32Bit) ) - { - $expectedPath = $expectedPath -replace 'SysWOW64','sysnative' - } - Assert-Equal $expectedPath (Get-PowerShellPath) -} - -function Test-ShouldGet32BitPowerShellPath -{ - $expectedPath = Join-Path $PSHome powershell.exe - if( Test-OSIs64Bit ) - { - $expectedPath = $expectedPath -replace 'System32','SysWOW64' - } - - Assert-Equal $expectedPath (Get-PowerShellPath -x86) -} - -function Test-ShouldGet64BitPowerShellUnder32BitPowerShell -{ - if( (Test-OsIs64Bit) -and (Test-PowerShellIs32Bit) ) - { - $expectedPath = $PSHome -replace 'SysWOW64','sysnative' - $expectedPath = Join-Path $expectedPath 'powershell.exe' - Assert-Equal $expectedPath (Get-PowerShellPath -NoWarn) - } - else - { - Write-Warning 'This test is only valid if running 32-bit PowerShell on a 64-bit operating system.' - } -} - -function Test-ShouldGet32BitPowerShellUnder32BitPowerShell -{ - if( (Test-OsIs64Bit) -and (Test-PowerShellIs32Bit) ) - { - Assert-Equal (Join-Path $PSHome 'powershell.exe') (Get-PowerShellPath -x86 -NoWarn) - } - else - { - Write-Warning 'This test is only valid if running 32-bit PowerShell on a 64-bit operating system.' - } -} - - diff --git a/Test/PowerShell/Test-TestPowerShellIs32Bit.ps1 b/Test/PowerShell/Test-TestPowerShellIs32Bit.ps1 deleted file mode 100644 index c8e6c31a..00000000 --- a/Test/PowerShell/Test-TestPowerShellIs32Bit.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldDetect32BitProcess -{ - $expectedResult = ( $env:PROCESSOR_ARCHITECTURE -eq 'x86' ) - Assert-Equal $expectedResult (Test-PowerShellIs32Bit -NoWarn) -} - diff --git a/Test/PowerShell/Test-TestPowerShellIs64Bit.ps1 b/Test/PowerShell/Test-TestPowerShellIs64Bit.ps1 deleted file mode 100644 index 5d9a27e7..00000000 --- a/Test/PowerShell/Test-TestPowerShellIs64Bit.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldDetect64BitProcess -{ - $expectedResult = ( $env:PROCESSOR_ARCHITECTURE -eq 'AMD64' ) - Assert-Equal $expectedResult (Test-PowerShellIs64Bit -NoWarn) -} - diff --git a/Test/Text/Test-ConvertToBase64.ps1 b/Test/Text/Test-ConvertToBase64.ps1 deleted file mode 100644 index 957af900..00000000 --- a/Test/Text/Test-ConvertToBase64.ps1 +++ /dev/null @@ -1,82 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function Start-TestFixture -{ - & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonTest.ps1' -Resolve) -} - -function Test-ShouldConvertToBase64 -{ - $expectedValue = 'YAAxADIAMwA0ADUANgA3ADgAOQAwAC0APQBxAHcAZQByAHQAeQB1AGkAbwBwAFsAXQBcAGEAcwBkAGYAZwBoAGoAawBsADsAJwB6AHgAYwB2AGIAbgBtACwALgAvACAAfgAhAEAAIwAkACUAXgAmACoAKAApAF8AKwBRAFcARQBSAFQAWQBVAEkATwBQAHsAfQB8AEEAUwBEAEYARwBIAEoASwBMADoAIgBaAFgAQwBWAEIATgBNADwAPgA/AA==' - $value = '`1234567890-=qwertyuiop[]\asdfghjkl;''zxcvbnm,./ ~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?' - - $actualValue = ConvertTo-Base64 -Value $value - - Assert-Equal $expectedValue $actualValue -} - -function Test-ShouldAcceptPipelineInput -{ - $result = ('Value1','Value2') | ConvertTo-Base64 - Assert-Equal 2 $result.Length - Assert-Equal (ConvertTo-Base64 -Value 'Value1' -NoWarn) $result[0] - Assert-Equal (ConvertTo-Base64 -Value 'Value2' -NoWarn) $result[1] -} - -function Test-ShouldAcceptArrayInput -{ - $result = ConvertTo-Base64 -Value @('Value1','Value2') - Assert-Equal 2 $result.Length - Assert-Equal (ConvertTo-Base64 -Value 'Value1' -NoWarn) $result[0] - Assert-Equal (ConvertTo-Base64 -Value 'Value2' -NoWarn) $result[1] -} - -function Test-ShouldAllowDifferentEncoding -{ - $value = 'Value1' - $result = $value | - ConvertTo-Base64 -Encoding ([Text.Encoding]::ASCII) -NoWarn | - ConvertFrom-Base64 -Encoding ([Text.Encoding]::ASCII) - Assert-Equal $value $result -} - -function Test-ShouldAllowEmptyString -{ - $result = ConvertTo-Base64 '' -NoWarn - Assert-Equal '' $result -} - -function Test-ShouldAllowNull -{ - $result = ConvertTo-Base64 $null -NoWarn - Assert-Null $null -} - -function Test-ShouldAllowNullFromPipeline -{ - $values = @('1', $null, '3') - $result = $values | ConvertTo-Base64 -NoWarn - Assert-NotNull $result - Assert-Equal 3 $result.Count - Assert-Null $result[1] -} - -function Test-ShouldAllowNullInArray -{ - $result = ConvertTo-Base64 -Value @( $null, $null ) -NoWarn - Assert-NotNull $result - Assert-Equal 2 $result.Count - Assert-Empty $result[0] - Assert-Empty $result[1] -} - diff --git a/whiskey.yml b/whiskey.yml index 00089ba1..17a9c512 100644 --- a/whiskey.yml +++ b/whiskey.yml @@ -154,7 +154,6 @@ Tests: - Pester4: OnlyBy: BuildServer Script: - - Test\Invoke-PowerShell.Tests.ps1 - Test\*Iis*.ps1 - Test\Carbon_*.Tests.ps1 - Parallel: @@ -172,7 +171,6 @@ Tests: - "*\\Test\\*Iis*.ps1" - "*\\Test\\Carbon_*.Tests.ps1" - "*\\Test\\*-ScheduledTask.Tests.ps1" - - "*\\Test\\Invoke-PowerShell.Tests.ps1" - Tasks: - PowerShell: WarningAction: SilentlyContinue From cd6156cb7e642104ce9b92d253bd31f4b43eb901 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Mon, 22 Nov 2021 13:58:54 -0800 Subject: [PATCH 06/20] Typo --- New-Website.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/New-Website.ps1 b/New-Website.ps1 index bd8a46f9..9901ca00 100644 --- a/New-Website.ps1 +++ b/New-Website.ps1 @@ -143,7 +143,7 @@ Get-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Carbon\en-US\about_Car } | Out-HtmlPage -Title $carbonTitle -VirtualPath '/index.html' -Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath 'CHANGLOG.md') -Raw | +Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath 'CHANGELOG.md') -Raw | Edit-HelpText -ModuleName 'Carbon' | Convert-MarkdownToHtml | Out-HtmlPage -Title ('CHANGELOG - {0}' -f $carbonTitle) -VirtualPath '/changelog.html' From dedbdedf9824ba5cb25d4540230ba94400881775 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Fri, 3 Jun 2022 16:34:39 -0700 Subject: [PATCH 07/20] PFORM-1305 Figuring out which tests fail for pwsh. --- Carbon/Carbon.psd1 | 2 +- .../Functions/Clear-DscLocalResourceCache.ps1 | 14 +++++- ...System.Diagnostics.Process.types.Tests.ps1 | 12 ++++- appveyor.yml | 35 ++++++++++---- init.ps1 | 47 +++++++++++++++++++ whiskey.yml | 5 ++ 6 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 init.ps1 diff --git a/Carbon/Carbon.psd1 b/Carbon/Carbon.psd1 index e721435f..4d3084ce 100644 --- a/Carbon/Carbon.psd1 +++ b/Carbon/Carbon.psd1 @@ -25,7 +25,7 @@ RootModule = 'Carbon.psm1' # Version number of this module. - ModuleVersion = '2.11.2' + ModuleVersion = '2.12.0' # ID used to uniquely identify this module GUID = '075d9444-c01b-48c3-889a-0b3490716fa2' diff --git a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 index f208d79c..887b3751 100644 --- a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 +++ b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 @@ -21,9 +21,21 @@ function Clear-CDscLocalResourceCache Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Get-WmiObject msft_providers | + if( $PSVersionTable['PSEdition'] -eq 'Core' ) + { + Get-CimInstance msft_providers | Where-Object {$_.provider -like 'dsccore'} | Select-Object -ExpandProperty HostProcessIdentifier | ForEach-Object { Get-Process -ID $_ } | Stop-Process -Force + } + else + { + Get-WmiObject msft_providers | + Where-Object {$_.provider -like 'dsccore'} | + Select-Object -ExpandProperty HostProcessIdentifier | + ForEach-Object { Get-Process -ID $_ } | + Stop-Process -Force + } + } diff --git a/Test/System.Diagnostics.Process.types.Tests.ps1 b/Test/System.Diagnostics.Process.types.Tests.ps1 index 2d059172..8c0cac4e 100644 --- a/Test/System.Diagnostics.Process.types.Tests.ps1 +++ b/Test/System.Diagnostics.Process.types.Tests.ps1 @@ -15,8 +15,16 @@ Describe 'System.Diagnostics.Process' { It 'processes have ParentProcessID' { $parents = @{} - Get-WmiObject Win32_Process | - ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } + if( $PSVersionTable['PSEdition'] -eq 'Core' ) + { + Get-CimInstance Win32_Process | + ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } + } + else + { + Get-WmiObject Win32_Process | + ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } + } $foundSome = $false Get-Process | diff --git a/appveyor.yml b/appveyor.yml index 63694289..fcc8aa52 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,9 +47,9 @@ environment: appveyor_build_worker_image: Visual Studio 2017 # TODO: Get-WmiObject doesn't exist. Does Get-CimInstance? Can Carbon support PowerShell 6? - # - job_name: Windows Server 2016, PowerShell 6 - # job_group: pwsh - # appveyor_build_worker_image: Visual Studio 2017 + - job_name: Windows Server 2016, PowerShell 6 + job_group: pwsh + appveyor_build_worker_image: Visual Studio 2017 # TODO: Get build working on a new version of the .NET SDK. # - job_name: Windows Server 2019, Windows PowerShell 5.1 @@ -57,9 +57,9 @@ environment: # appveyor_build_worker_image: Visual Studio 2022 # TODO: Get build working on a new version of the .NET SDK - # - job_name: Windows Server 2019, PowerShell 7 - # job_group: pwsh - # appveyor_build_worker_image: Visual Studio 2022 + - job_name: Windows Server 2019, PowerShell 7 + job_group: pwsh + appveyor_build_worker_image: Visual Studio 2022 artifacts: @@ -72,11 +72,28 @@ for: only: - job_group: ps build_script: - - ps: .\build.ps1 - + - ps: | + try + { + ./init.ps1 + ./build.ps1 + } + finally + { + $Global:Error | Format-List * -Force + } # Build in PowerShell - matrix: only: - job_group: pwsh build_script: - - pwsh: ./build.ps1 \ No newline at end of file + - pwsh: | + try + { + ./init.ps1 + ./build.ps1 + } + finally + { + $Global:Error | Format-List * -Force + } \ No newline at end of file diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 00000000..90ea51de --- /dev/null +++ b/init.ps1 @@ -0,0 +1,47 @@ +[CmdletBinding()] +param( +) + +Set-StrictMode -Version 'Latest' +$InformationPreference = 'Continue' + +# Run in a background job so that old PackageManagement assemblies don't get loaded. +$job = Start-Job { + $InformationPreference = 'Continue' + $psGalleryRepo = Get-PSRepository -Name 'PSGallery' + $repoToUse = $psGalleryRepo.Name + # On Windows 2012 R2, Windows PowerShell 5.1, and .NET 4.6.2, PSGallery's URL ends with a '/'. + if( -not $psGalleryRepo -or $psgalleryRepo.SourceLocation -ne 'https://www.powershellgallery.com/api/v2' ) + { + $repoToUse = 'PSGallery2' + Register-PSRepository -Name $repoToUse ` + -InstallationPolicy Trusted ` + -SourceLocation 'https://www.powershellgallery.com/api/v2' ` + -PackageManagementProvider $psGalleryRepo.PackageManagementProvider + } + + Write-Information -MessageData 'Installing latest version of PowerShell module Prism.' + Install-Module -Name 'Prism' -Scope CurrentUser -Repository $repoToUse -AllowClobber -Force + + if( -not (Get-Module -Name 'PackageManagement' -ListAvailable | Where-Object 'Version' -eq '1.4.7') ) + { + Write-Information -MessageData 'Installing PowerShell module PackageManagement 1.4.7.' + Install-Module -Name 'PackageManagement' -RequiredVersion '1.4.7'-Repository $repoToUse -AllowClobber -Force + } + + if( -not (Get-Module -Name 'PowerShellGet' -ListAvailable | Where-Object 'Version' -eq '2.2.5') ) + { + Write-Information -MessageData 'Installing PowerShell module PowerShellGet 2.2.5.' + Install-Module -Name 'PowerShellGet' -RequiredVersion '2.2.5' -Repository $repoToUse -AllowClobber -Force + } +} + +if( (Get-Command -Name 'Receive-Job' -ParameterName 'AutoRemoveJob') ) +{ + $job | Receive-Job -AutoRemoveJob -Wait +} +else +{ + $job | Wait-Job | Receive-Job + $job | Remove-Job +} \ No newline at end of file diff --git a/whiskey.yml b/whiskey.yml index 5179afad..70ecc0e3 100644 --- a/whiskey.yml +++ b/whiskey.yml @@ -163,11 +163,13 @@ Tests: - Test\Test-ImportCarbon.ps1 # These tests fail when run in parallel so they get run first. - Pester4: + UnlessExists: variable:IsWindows OnlyBy: BuildServer Script: - Test\*Iis*.ps1 - Test\Carbon_*.Tests.ps1 - Parallel: + UnlessExists: variable:IsWindows OnlyBy: BuildServer Queues: - Tasks: @@ -191,6 +193,9 @@ Tests: Recurse: true Path: Test PassThru: true +- Pester4: + IfExists: variable:IsWindows + Script: Test\*.Tests.ps1 - PowerShell: OnlyDuring: Build OnlyBy: Developer From 15d2d8cc107d9222639cd3bc4f13254d3887a288 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Wed, 29 Jun 2022 09:42:55 -0700 Subject: [PATCH 08/20] PFORM-1305 Adding support for PowerShell Core. Added new `Get-Cim` function. --- CHANGELOG.md | 8 +++ Carbon/Carbon.psd1 | 1 + Carbon/Carbon.psm1 | 20 ++---- Carbon/Carbon.psm1.Import.Obsolete.ps1 | 2 +- .../Functions/Clear-DscLocalResourceCache.ps1 | 22 ++----- Carbon/Functions/Get-Cim.ps1 | 63 +++++++++++++++++++ Carbon/Functions/Get-FileShare.ps1 | 2 +- Carbon/Functions/Get-FileSharePermission.ps1 | 12 +++- Carbon/Functions/Get-WmiLocalUserAccount.ps1 | 2 +- Carbon/Functions/Install-FileShare.ps1 | 4 +- .../Functions/Start-DscPullConfiguration.ps1 | 2 +- Carbon/Functions/Uninstall-FileShare.ps1 | 11 +++- Initialize-Server.ps1 | 2 +- Test/ActiveDirectory/Test-FindADUser.ps1 | 2 +- .../Test-GetADDomainController.ps1 | 2 +- Test/Add-GroupMember.Tests.ps1 | 4 +- Test/Grant-Permission.Tests.ps1 | 2 +- Test/Install-Service.Tests.ps1 | 2 +- Test/MSMQ/Test-GetMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-TestMSMQMessageQueue.ps1 | 2 +- Test/New-RsaKeyPair.Tests.ps1 | 2 +- Test/Share/Test-GetFileShare.ps1 | 4 +- Test/Share/Test-InstallFileShare.ps1 | 2 +- Test/Share/Test-TestFileShare.ps1 | 2 +- ...System.Diagnostics.Process.types.Tests.ps1 | 12 +--- Test/Test-Identity.Tests.ps1 | 2 +- Test/Uninstall-FileShare.Tests.ps1 | 11 +++- .../Test-GetWmiLocalUserAccount.ps1 | 2 +- Test/UsersAndGroups/Test-TestUser.ps1 | 2 +- global.json | 3 +- 32 files changed, 140 insertions(+), 73 deletions(-) create mode 100644 Carbon/Functions/Get-Cim.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index d56d0b2b..6dc2fabd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ +# 2.12.0 + +## Added suport for PowerShell Core + +* Added: `Get-Cim` function that determines which method to call when accessing a computer's Common Information Model. + `Get-Cim` will call `Get-CimInstance` when PowerShell Core is being used and `Get-WmiObject` when Windows PowerShell + is being used. + # 2.11.2 * Fixed: `Carbon.Firewall.Rule` type missing the `LocalIP` and `RemoteIP` properties (which are aliases for the diff --git a/Carbon/Carbon.psd1 b/Carbon/Carbon.psd1 index 4d3084ce..bbaaff8c 100644 --- a/Carbon/Carbon.psd1 +++ b/Carbon/Carbon.psd1 @@ -161,6 +161,7 @@ All functions are idempotent: when run multiple times with the same arguments, y 'Get-CIisSecurityAuthentication', 'Get-CIisVersion', 'Get-CIisWebsite', + 'Get-Cim', 'Get-CIPAddress', 'Get-CMsi', 'Get-CMsmqMessageQueue', diff --git a/Carbon/Carbon.psm1 b/Carbon/Carbon.psm1 index 5332e560..b026d18a 100644 --- a/Carbon/Carbon.psm1 +++ b/Carbon/Carbon.psm1 @@ -91,13 +91,10 @@ if( (Test-Path -Path 'env:SystemRoot') ) (Test-Path -Path $microsoftWebAdministrationPath -PathType Leaf) ) { $exportIisFunctions = $true - if( -not $IsPSCore ) - { - Write-Timing ('Adding Microsoft.Web.Administration assembly.') - Add-CAssembly -Path $microsoftWebAdministrationPath - Write-Timing ('Adding Carbon.Iis assembly.') - Add-CAssembly -Path (Join-Path -Path $carbonAssemblyDir -ChildPath 'Carbon.Iis.dll' -Resolve) - } + Write-Timing ('Adding Microsoft.Web.Administration assembly.') + Add-CAssembly -Path $microsoftWebAdministrationPath + Write-Timing ('Adding Carbon.Iis assembly.') + Add-CAssembly -Path (Join-Path -Path $carbonAssemblyDir -ChildPath 'Carbon.Iis.dll' -Resolve) } } @@ -184,14 +181,7 @@ Add-CTypeData -Type Diagnostics.Process ` -MemberType ScriptProperty ` -Value { $filter = "ProcessID='{0}'" -f $this.Id - if( (Get-Command -Name 'Get-CimInstance' -ErrorAction Ignore) ) - { - $process = Get-CimInstance -ClassName 'Win32_Process' -Filter $filter - } - else - { - $process = Get-WmiObject -Class 'Win32_Process' -Filter $filter - } + $process = Get-Cim -Class 'Win32_Process' -Filter $filter return $process.ParentProcessID } diff --git a/Carbon/Carbon.psm1.Import.Obsolete.ps1 b/Carbon/Carbon.psm1.Import.Obsolete.ps1 index cceb228a..4f50fe21 100644 --- a/Carbon/Carbon.psm1.Import.Obsolete.ps1 +++ b/Carbon/Carbon.psm1.Import.Obsolete.ps1 @@ -749,7 +749,7 @@ if( -not (Get-Command -Name 'Get-WindowsFeature*' | Where-Object { $_.ModuleName if( $useOCSetup ) { - Get-WmiObject -Class Win32_OptionalFeature | + Get-Cim -Class 'Win32_OptionalFeature' | Where-Object { if( $Name ) { diff --git a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 index 887b3751..62c1dc6d 100644 --- a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 +++ b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 @@ -21,21 +21,9 @@ function Clear-CDscLocalResourceCache Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - if( $PSVersionTable['PSEdition'] -eq 'Core' ) - { - Get-CimInstance msft_providers | - Where-Object {$_.provider -like 'dsccore'} | - Select-Object -ExpandProperty HostProcessIdentifier | - ForEach-Object { Get-Process -ID $_ } | - Stop-Process -Force - } - else - { - Get-WmiObject msft_providers | - Where-Object {$_.provider -like 'dsccore'} | - Select-Object -ExpandProperty HostProcessIdentifier | - ForEach-Object { Get-Process -ID $_ } | - Stop-Process -Force - } - + Get-Cim -Class 'msft_providers' | + Where-Object {$_.provider -like 'dsccore'} | + Select-Object -ExpandProperty HostProcessIdentifier | + ForEach-Object { Get-Process -ID $_ } | + Stop-Process -Force } diff --git a/Carbon/Functions/Get-Cim.ps1 b/Carbon/Functions/Get-Cim.ps1 new file mode 100644 index 00000000..ded581ce --- /dev/null +++ b/Carbon/Functions/Get-Cim.ps1 @@ -0,0 +1,63 @@ + +function Get-Cim +{ + <# + .SYNOPSIS + Gets the CIM instance of a class or information about the avaialble classes. + + .DESCRIPTION + Get-WmiObject has been deprecated since PowerShell 6 and Get-CimInstance is the new method to use. This function will determine + which method to use based on the version of PowerShell. Currently only accepting $Class, $Filter, $List, and $Query parameters + as these are the ones being used in Carbon. More parameters can be added if needed. + + .EXAMPLE + Get-Cim -ClassName 'Win32_OperatingSystem' + + Gets the instance for Win32_OperatingSystem class. + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $Class, + + [String] $Filter, + + [Switch] $List, + + [String] $Query + ) + $IsPSCore = $PSVersionTable.PSEdition -eq 'Core' + $optionalArgs = @{ } + + if( $Filter ) + { + $optionalArgs['Filter'] = $Filter + } + + if( $List -and -not $IsPSCore ) + { + $optionalArgs['List'] = $List + } + + if( $Query ) + { + $optionalArgs['Query'] = $Query + } + + if( $IsPSCore ) + { + if( $List ) + { + Get-CimClass -ClassName $Class + } + else + { + Get-CimInstance -ClassName $Class @optionalArgs + } + } + else + { + Get-WmiObject -Class $Class @optionalArgs + } +} \ No newline at end of file diff --git a/Carbon/Functions/Get-FileShare.ps1 b/Carbon/Functions/Get-FileShare.ps1 index 7a5c4992..d6e62a03 100644 --- a/Carbon/Functions/Get-FileShare.ps1 +++ b/Carbon/Functions/Get-FileShare.ps1 @@ -62,7 +62,7 @@ function Get-CFileShare $filter = '{0} and Name = ''{1}''' -f $filter,$Name } - $shares = Get-WmiObject -Class 'Win32_Share' -Filter $filter | + $shares = Get-Cim -Class 'Win32_Share' -Filter $filter | Where-Object { if( -not $wildcardSearch ) { diff --git a/Carbon/Functions/Get-FileSharePermission.ps1 b/Carbon/Functions/Get-FileSharePermission.ps1 index 7a08c865..dc4b4dd9 100644 --- a/Carbon/Functions/Get-FileSharePermission.ps1 +++ b/Carbon/Functions/Get-FileSharePermission.ps1 @@ -78,13 +78,21 @@ function Get-CFileSharePermission } $acl = $null - $lsss = Get-WmiObject -Class 'Win32_LogicalShareSecuritySetting' -Filter "name='$Name'" + $lsss = Get-Cim -Class 'Win32_LogicalShareSecuritySetting' -Filter "name='$Name'" if( -not $lsss ) { return } - $result = $lsss.GetSecurityDescriptor() + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $result = Invoke-CimMethod -InputObject $lsss -MethodName 'GetSecurityDescriptor' + } + else + { + $result = $lsss.GetSecurityDescriptor() + } + if( -not $result ) { return diff --git a/Carbon/Functions/Get-WmiLocalUserAccount.ps1 b/Carbon/Functions/Get-WmiLocalUserAccount.ps1 index 012dd566..874cd94e 100644 --- a/Carbon/Functions/Get-WmiLocalUserAccount.ps1 +++ b/Carbon/Functions/Get-WmiLocalUserAccount.ps1 @@ -31,6 +31,6 @@ function Get-CWmiLocalUserAccount Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - return Get-WmiObject Win32_UserAccount -Filter "Domain='$($env:ComputerName)' and Name='$Username'" + return Get-Cim -Class 'Win32_UserAccount' -Filter "Domain='$($env:ComputerName)' and Name='$Username'" } diff --git a/Carbon/Functions/Install-FileShare.ps1 b/Carbon/Functions/Install-FileShare.ps1 index 8c4c4657..4bf1b571 100644 --- a/Carbon/Functions/Install-FileShare.ps1 +++ b/Carbon/Functions/Install-FileShare.ps1 @@ -175,9 +175,9 @@ function Install-CFileShare New-Item -Path $Path -ItemType Directory -Force | Out-String | Write-Verbose } - $shareClass = Get-WmiObject -Class 'Win32_Share' -List Write-Verbose -Message ('[SHARE] [{0}] Sharing {1}' -f $Name,$Path) - $result = $shareClass.Create( $Path, $Name, 0, $null, $Description, $null, $shareSecurityDescriptor ) + $result = ([wmiclass]"root\cimv2:Win32_Share").Create( $Path, $Name, 0, $null, $Description, $null, $shareSecurityDescriptor ) + if( $result.ReturnValue ) { Write-Error ('Failed to create share ''{0}'' (Path: {1}). WMI returned error code {2} which means: {3}.' -f $Name,$Path,$result.ReturnValue,$errors[$result.ReturnValue]) diff --git a/Carbon/Functions/Start-DscPullConfiguration.ps1 b/Carbon/Functions/Start-DscPullConfiguration.ps1 index 95c67532..52a2d883 100644 --- a/Carbon/Functions/Start-DscPullConfiguration.ps1 +++ b/Carbon/Functions/Start-DscPullConfiguration.ps1 @@ -123,7 +123,7 @@ function Start-CDscPullConfiguration $ModuleName ) - $dscProcessID = Get-WmiObject msft_providers | + $dscProcessID = Get-Cim -Class 'msft_providers' | Where-Object {$_.provider -like 'dsccore'} | Select-Object -ExpandProperty HostProcessIdentifier Stop-Process -Id $dscProcessID -Force diff --git a/Carbon/Functions/Uninstall-FileShare.ps1 b/Carbon/Functions/Uninstall-FileShare.ps1 index cec79b02..7f5c1a34 100644 --- a/Carbon/Functions/Uninstall-FileShare.ps1 +++ b/Carbon/Functions/Uninstall-FileShare.ps1 @@ -69,7 +69,16 @@ function Uninstall-CFileShare if( $PSCmdlet.ShouldProcess( ('{0} ({1})' -f $share.Name,$share.Path), 'delete' ) ) { Write-Verbose ('Deleting file share ''{0}'' (Path: {1}).' -f $share.Name,$share.Path) - $result = $share.Delete() + + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $result = Invoke-CimMethod -InputObject $share -MethodName 'Delete' + } + else + { + $result = $share.Delete() + } + if( $result.ReturnValue ) { Write-Error ('Failed to delete share ''{0}'' (Path: {1}). Win32_Share.Delete() method returned error code {2} which means: {3}.' -f $Name,$share.Path,$result.ReturnValue,$errors[$result.ReturnValue]) diff --git a/Initialize-Server.ps1 b/Initialize-Server.ps1 index 2cb31acc..2efa7721 100644 --- a/Initialize-Server.ps1 +++ b/Initialize-Server.ps1 @@ -23,7 +23,7 @@ Set-StrictMode -Version 'Latest' $PSCommandPath = $MyInvocation.MyCommand.Definition $PSScriptRoot = Split-Path -Parent -Path $PSCommandPath -$os = Get-WmiObject -Class 'Win32_OperatingSystem' +$os = Get-Cim -Class 'Win32_OperatingSystem' # Windows 2008 $osVersion = [version]$os.Version diff --git a/Test/ActiveDirectory/Test-FindADUser.ps1 b/Test/ActiveDirectory/Test-FindADUser.ps1 index a326dfa9..dc5d10f8 100644 --- a/Test/ActiveDirectory/Test-FindADUser.ps1 +++ b/Test/ActiveDirectory/Test-FindADUser.ps1 @@ -10,7 +10,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -if( (Get-WmiObject -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) +if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) { Write-Warning -Message ('Find-ADUser tests can''t run because this computer is not part of a domain.') } diff --git a/Test/ActiveDirectory/Test-GetADDomainController.ps1 b/Test/ActiveDirectory/Test-GetADDomainController.ps1 index ec3ba5a6..66add40a 100644 --- a/Test/ActiveDirectory/Test-GetADDomainController.ps1 +++ b/Test/ActiveDirectory/Test-GetADDomainController.ps1 @@ -10,7 +10,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -if( (Get-WmiObject -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) +if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) { Write-Warning -Message ('Get-ADDomainController tests can''t run because this computer is not part of a domain.') } diff --git a/Test/Add-GroupMember.Tests.ps1 b/Test/Add-GroupMember.Tests.ps1 index a8738dce..3e3287d5 100644 --- a/Test/Add-GroupMember.Tests.ps1 +++ b/Test/Add-GroupMember.Tests.ps1 @@ -96,7 +96,7 @@ Describe 'Add-GroupMember' { function Get-LocalUsers { - return Get-WmiObject Win32_UserAccount -Filter "LocalAccount=True" | + return Get-Cim -Class 'Win32_UserAccount' -Filter "LocalAccount=True" | Where-Object { $_.Name -ne $env:COMPUTERNAME } } @@ -106,7 +106,7 @@ Describe 'Add-GroupMember' { Assert-MembersInGroup -Member $Members } - if( (Get-WmiObject -Class 'Win32_ComputerSystem').Domain -eq 'WBMD' ) + if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WBMD' ) { It 'should add member from domain' { Invoke-AddMembersToGroup -Members 'WBMD\WHS - Lifecycle Services' diff --git a/Test/Grant-Permission.Tests.ps1 b/Test/Grant-Permission.Tests.ps1 index e5a7f18a..2d53f792 100644 --- a/Test/Grant-Permission.Tests.ps1 +++ b/Test/Grant-Permission.Tests.ps1 @@ -143,7 +143,7 @@ function Invoke-GrantPermissions $assertOptionalParams['Type'] = $Type } - $ExpectedRuleType = [Type]('Security.AccessControl.{0}AccessRule' -f $ExpectedRuleType) + $ExpectedRuleType = ('Security.AccessControl.{0}AccessRule' -f $ExpectedRuleType) -as [Type] $result = Grant-Permission -Identity $Identity -Permission $Permissions -Path $path -PassThru @optionalParams It ('should return a {0}' -f $ExpectedRuleType.Name) { $result | Should Not BeNullOrEmpty diff --git a/Test/Install-Service.Tests.ps1 b/Test/Install-Service.Tests.ps1 index 86c1e1b0..0d0ae176 100644 --- a/Test/Install-Service.Tests.ps1 +++ b/Test/Install-Service.Tests.ps1 @@ -585,7 +585,7 @@ Describe 'Install-Service' { { Install-Service -Name $serviceName -Path $path @installServiceParams $service = Assert-ServiceInstalled - $svc = Get-WmiObject -Class 'Win32_Service' -Filter ('Name = "{0}"' -f $serviceName) + $svc = Get-Cim -Class 'Win32_Service' -Filter ('Name = "{0}"' -f $serviceName) $svc.PathName | Should -Be $servicePath } finally diff --git a/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 b/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 index e4d58655..4971b96f 100644 --- a/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 @@ -13,7 +13,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-WmiObject 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 b/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 index 283c32a8..9bd9cf02 100644 --- a/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 @@ -12,7 +12,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-WmiObject 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 b/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 index 75510537..3ce1d8d1 100644 --- a/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 @@ -11,7 +11,7 @@ # limitations under the License. $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-WmiObject 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 b/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 index 28a8f466..b9feb774 100644 --- a/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 @@ -13,7 +13,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-WmiObject 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/New-RsaKeyPair.Tests.ps1 b/Test/New-RsaKeyPair.Tests.ps1 index 3187c238..2e24d346 100644 --- a/Test/New-RsaKeyPair.Tests.ps1 +++ b/Test/New-RsaKeyPair.Tests.ps1 @@ -55,7 +55,7 @@ Describe 'New-RsaKeyPair' { $enhancedKeyUsage | Should Not BeNullOrEmpty # I don't think Windows 2008 supports Enhanced Key Usages. - $osVersion = (Get-WmiObject -Class 'Win32_OperatingSystem').Version + $osVersion = (Get-Cim -Class 'Win32_OperatingSystem').Version if( $osVersion -notmatch '6.1\b' ) { $usage = $enhancedKeyUsage.EnhancedKeyUsages | Where-Object { $_.FriendlyName -eq 'Document Encryption' } diff --git a/Test/Share/Test-GetFileShare.ps1 b/Test/Share/Test-GetFileShare.ps1 index 398ceb47..a26c484f 100644 --- a/Test/Share/Test-GetFileShare.ps1 +++ b/Test/Share/Test-GetFileShare.ps1 @@ -23,7 +23,7 @@ function Start-TestFixture function Stop-TestFixture { - $share = Get-WmiObject 'Win32_Share' -Filter "Name='$shareName'" + $share = Get-Cim -Class 'Win32_Share' -Filter "Name='$shareName'" if( $share -ne $null ) { [void] $share.Delete() @@ -47,7 +47,7 @@ function Test-ShouldGetSpecificShare function Test-ShouldGetOnlyFileShares { - $nonFileShares = Get-WmiObject -Class 'Win32_Share' | Where-Object { $_.Type -ne 0 -and $_.Type -ne 2147483648 } + $nonFileShares = Get-Cim -Class 'Win32_Share' | Where-Object { $_.Type -ne 0 -and $_.Type -ne 2147483648 } if( $nonFileShares ) { foreach( $nonFileShare in $nonFileShares ) diff --git a/Test/Share/Test-InstallFileShare.ps1 b/Test/Share/Test-InstallFileShare.ps1 index 4eeef1c0..48dba871 100644 --- a/Test/Share/Test-InstallFileShare.ps1 +++ b/Test/Share/Test-InstallFileShare.ps1 @@ -55,7 +55,7 @@ function Invoke-NewShare($Path = $TestDir, $FullAccess = @(), $ChangeAccess = @( function Get-Share { - return Get-WmiObject Win32_Share -Filter "Name='$ShareName'" + return Get-Cim -Class 'Win32_Share' -Filter "Name='$ShareName'" } diff --git a/Test/Share/Test-TestFileShare.ps1 b/Test/Share/Test-TestFileShare.ps1 index 462441ac..04da56c7 100644 --- a/Test/Share/Test-TestFileShare.ps1 +++ b/Test/Share/Test-TestFileShare.ps1 @@ -23,7 +23,7 @@ function Start-TestFixture function Stop-TestFixture { - $share = Get-WmiObject 'Win32_Share' -Filter "Name='$shareName'" + $share = Get-Cim -Class 'Win32_Share' -Filter "Name='$shareName'" if( $share -ne $null ) { [void] $share.Delete() diff --git a/Test/System.Diagnostics.Process.types.Tests.ps1 b/Test/System.Diagnostics.Process.types.Tests.ps1 index 8c0cac4e..172af983 100644 --- a/Test/System.Diagnostics.Process.types.Tests.ps1 +++ b/Test/System.Diagnostics.Process.types.Tests.ps1 @@ -15,17 +15,7 @@ Describe 'System.Diagnostics.Process' { It 'processes have ParentProcessID' { $parents = @{} - if( $PSVersionTable['PSEdition'] -eq 'Core' ) - { - Get-CimInstance Win32_Process | - ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } - } - else - { - Get-WmiObject Win32_Process | - ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } - } - + Get-Cim -Class 'Win32_Process' | ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } $foundSome = $false Get-Process | Where-Object { $parents.ContainsKey( [UInt32]$_.Id ) -and $_.ParentProcessID } | diff --git a/Test/Test-Identity.Tests.ps1 b/Test/Test-Identity.Tests.ps1 index 851cd8ed..184b226a 100644 --- a/Test/Test-Identity.Tests.ps1 +++ b/Test/Test-Identity.Tests.ps1 @@ -23,7 +23,7 @@ Describe 'Test-Identity' { (Test-Identity -Name $user1.SamAccountName) | Should Be $true } - if( (Get-WmiObject -Class 'Win32_ComputerSystem').Domain -ne 'WORKGROUP' ) + if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -ne 'WORKGROUP' ) { It 'should find domain user' { (Test-Identity -Name ('{0}\Administrator' -f $env:USERDOMAIN)) | Should Be $true diff --git a/Test/Uninstall-FileShare.Tests.ps1 b/Test/Uninstall-FileShare.Tests.ps1 index 865e3181..cd3899f8 100644 --- a/Test/Uninstall-FileShare.Tests.ps1 +++ b/Test/Uninstall-FileShare.Tests.ps1 @@ -27,7 +27,16 @@ Describe 'Uninstall-FileShare' { } AfterEach { - Get-FileShare -Name $shareName -ErrorAction Ignore | ForEach-Object { $_.Delete() } + Get-FileShare -Name $shareName -ErrorAction Ignore | + ForEach-Object { + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + Invoke-CimMethod -InputObject $_ -MethodName 'Delete' + } + { + $_.Delete() + } + } } It 'should delete share' { diff --git a/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 b/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 index efc8311e..e8551611 100644 --- a/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 +++ b/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 @@ -17,7 +17,7 @@ function Start-TestFixture function Test-ShouldGetUser { - Get-WmiObject Win32_UserAccount -Filter "Domain='$($env:ComputerName)'" | ForEach-Object { + Get-Cim -Class 'Win32_UserAccount' -Filter "Domain='$($env:ComputerName)'" | ForEach-Object { $user = Get-WmiLocalUserAccount -Username $_.Name Assert-NotNull $user Assert-Equal $_.Name $user.Name diff --git a/Test/UsersAndGroups/Test-TestUser.ps1 b/Test/UsersAndGroups/Test-TestUser.ps1 index f885aab0..3c52da3e 100644 --- a/Test/UsersAndGroups/Test-TestUser.ps1 +++ b/Test/UsersAndGroups/Test-TestUser.ps1 @@ -17,7 +17,7 @@ function Start-TestFixture function Test-ShouldCheckIfLocalAccountExists { - $localUserAccounts = @(Get-WmiObject -Query "select * from win32_useraccount where Domain='$($env:ComputerName)'" -Computer .) + $localUserAccounts = @(Get-Cim -Query "select * from win32_useraccount where Domain='$($env:ComputerName)'" -Computer .) Assert-True (0 -lt $localUserAccounts.Length) foreach( $localUserAccount in $localUserAccounts ) { diff --git a/global.json b/global.json index 016f082a..4b3bf9b4 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "2.2.108" + "version": "2.2.108", + "rollForward": "latestMajor" } } From 84c2f7f405d472707af217cb3c6c2d9f90c8d3b0 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Tue, 12 Jul 2022 16:20:14 -0700 Subject: [PATCH 09/20] PFORM-1305 Fixing tests for CryptoKeyRights --- .../ConvertTo-ProviderAccessControlRights.ps1 | 7 ++ Carbon/Functions/Get-Permission.ps1 | 23 ++++++- Carbon/Functions/Grant-Permission.ps1 | 2 + Carbon/Functions/Revoke-Permission.ps1 | 41 +++++++++++ Carbon/Functions/Test-Permission.ps1 | 5 ++ Test/Carbon_Permission.Tests.ps1 | 15 ++-- Test/Grant-Permission.Tests.ps1 | 69 ++++++++++++------- 7 files changed, 133 insertions(+), 29 deletions(-) diff --git a/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 b/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 index e7a2ce7c..42c267c1 100644 --- a/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 +++ b/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 @@ -35,6 +35,13 @@ function ConvertTo-ProviderAccessControlRights $rights = 0 $rightTypeName = 'Security.AccessControl.{0}Rights' -f $ProviderName + + # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead + if( $PSVersionTable.PSEdition -eq 'Core' -and $ProviderName -eq 'CryptoKey') + { + $rightTypeName = 'Security.AccessControl.FileSystemRights' + } + $foundInvalidRight = $false } diff --git a/Carbon/Functions/Get-Permission.ps1 b/Carbon/Functions/Get-Permission.ps1 index c6ab667d..9b21b33d 100644 --- a/Carbon/Functions/Get-Permission.ps1 +++ b/Carbon/Functions/Get-Permission.ps1 @@ -127,7 +127,28 @@ function Get-CPermission { if( $_.HasPrivateKey -and $_.PrivateKey ) { - $_.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity + if( -not ($_.PrivateKey | Get-Member 'CspKeyContainerInfo') ) + { + $root = "C:\programdata\microsoft\crypto\rsa\machinekeys\" + $aclPath = Join-Path -Path $root -ChildPath $_.PrivateKey.Key.UniqueName + if( Test-Path -Path $aclPath ) + { + Get-Acl -Path $aclPath + } + else + { + $root = "C:\Users\$env:UserName\AppData\Roaming\Microsoft\Crypto\RSA\*\" + $aclPath = Join-Path -Path $root -ChildPath $_.PrivateKey.Key.UniqueName + if( Test-Path $aclPath ) + { + Get-Acl -Path $aclPath + } + } + } + else + { + $_.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity + } } } else diff --git a/Carbon/Functions/Grant-Permission.ps1 b/Carbon/Functions/Grant-Permission.ps1 index f7149c81..82b480ff 100644 --- a/Carbon/Functions/Grant-Permission.ps1 +++ b/Carbon/Functions/Grant-Permission.ps1 @@ -366,6 +366,8 @@ function Grant-CPermission { $rulesToRemove = $currentAcl.Access | Where-Object { $_.IdentityReference.Value -ne $Identity } | + # Don't remove Administrators access. + Where-Object { $_.IdentityReference.Value -ne 'BUILTIN\Administrators' } | Where-Object { -not $_.IsInherited } if( $rulesToRemove ) diff --git a/Carbon/Functions/Revoke-Permission.ps1 b/Carbon/Functions/Revoke-Permission.ps1 index f0772e3e..d7d8f7dc 100644 --- a/Carbon/Functions/Revoke-Permission.ps1 +++ b/Carbon/Functions/Revoke-Permission.ps1 @@ -70,6 +70,10 @@ function Revoke-CPermission if( $providerName -eq 'Certificate' ) { $providerName = 'CryptoKey' + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $providerName = 'FileSystem' + } } $rulesToRemove = Get-CPermission -Path $Path -Identity $Identity @@ -82,6 +86,43 @@ function Revoke-CPermission ForEach-Object { if( $_.PSProvider.Name -eq 'Certificate' ) { + if( -not ($_.PrivateKey | Get-Member 'CspKeyContainerInfo') ) + { + $privateKeyFileName = $_.PrivateKey.Key.UniqueName + # See https://docs.microsoft.com/en-us/windows/win32/seccng/key-storage-and-retrieval + $keyStoragePaths = @( + "$($env:AppDATA)\Microsoft\Crypto", + "$($env:ALLUSERSPROFILE)\Application Data\Microsoft\Crypto\SystemKeys", + "$($env:WINDIR)\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\Keys", + "$($env:WINDIR)\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\Crypto\Keys", + "$($env:ALLUSERSPROFILE)\Application Data\Microsoft\Crypto", + "$($env:ALLUSERSPROFILE)\Microsoft\Crypto" + ) + $privateKeyFiles = $keyStoragePaths | Get-ChildItem -Recurse -Force -ErrorAction Ignore -Filter $privateKeyFileName + if( -not $privateKeyFiles ) + { + $msg = "Failed to find the private key file for certificate ""$($Path)"" (subject: $($_.Subject); " + + "thumbprint: $($_.Thumbprint); expected file name: $($privateKeyFileName)). This is most " + + "likely because you don't have permission to read private keys, or we''re not looking in the right " + + "places. According to [Microsoft docs](https://docs.microsoft.com/en-us/windows/win32/seccng/key-storage-and-retrieval), " + + "private keys are stored under one of these directories:" + [Environment]::NewLine + + " * $($keyStoragePaths -join "$([Environment]::NewLine) * ")" + [Environment]::NewLine + + "If there are other locations we should be looking, please " + + "[submit an issue/bug report](https://github.com/webmd-health-services/Carbon/issues)." + Write-Error -Message $msg + return + } + + $revokePermissionParams = New-Object -TypeName 'Collections.Generic.Dictionary[[string], [object]]' ` + -ArgumentList $PSBoundParameters + $revokePermissionParams.Remove('Path') + foreach( $privateKeyFile in $privateKeyFiles ) + { + Revoke-CPermission -Path $privateKeyFile.FullName @revokePermissionParams + } + return + } + [Security.Cryptography.X509Certificates.X509Certificate2]$certificate = $_ [Security.AccessControl.CryptoKeySecurity]$keySecurity = $certificate.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity diff --git a/Carbon/Functions/Test-Permission.ps1 b/Carbon/Functions/Test-Permission.ps1 index 1ee16417..dd41506e 100644 --- a/Carbon/Functions/Test-Permission.ps1 +++ b/Carbon/Functions/Test-Permission.ps1 @@ -119,6 +119,11 @@ function Test-CPermission if( $providerName -eq 'Certificate' ) { $providerName = 'CryptoKey' + # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $providerName = 'FileSystem' + } } if( ($providerName -eq 'FileSystem' -or $providerName -eq 'CryptoKey') -and $Exact ) diff --git a/Test/Carbon_Permission.Tests.ps1 b/Test/Carbon_Permission.Tests.ps1 index 077d9762..1dce49e4 100644 --- a/Test/Carbon_Permission.Tests.ps1 +++ b/Test/Carbon_Permission.Tests.ps1 @@ -181,17 +181,22 @@ Describe 'Carbon_Permission' { $cert = Install-Certificate -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Cryptography\CarbonTestPrivateKey.pfx' -Resolve) -StoreLocation LocalMachine -StoreName My -NoWarn try { + $readPermission = 'GenericRead' + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $readPermission = 'Read' + } $certPath = Join-Path -Path 'cert:\LocalMachine\My' -ChildPath $cert.Thumbprint -Resolve (Get-Permission -Path $certPath -Identity $UserName) | Should BeNullOrEmpty - (Test-TargetResource -Path $certPath -Identity $UserName -Permission 'GenericRead') | Should Be $false + (Test-TargetResource -Path $certPath -Identity $UserName -Permission $readPermission) | Should Be $false - Set-TargetResource -Identity $UserName -Path $certPath -Permission GenericRead -Ensure Present + Set-TargetResource -Identity $UserName -Path $certPath -Permission $readPermission -Ensure Present (Get-Permission -Path $certPath -Identity $UserName) | Should Not BeNullOrEmpty - (Test-TargetResource -Path $certPath -Identity $UserName -Permission 'GenericRead') | Should Be $true + (Test-TargetResource -Path $certPath -Identity $UserName -Permission $readPermission) | Should Be $true - Set-TargetResource -Identity $UserName -Path $certPath -Permission GenericRead -Ensure Absent + Set-TargetResource -Identity $UserName -Path $certPath -Permission $readPermission -Ensure Absent (Get-Permission -Path $certPath -Identity $UserName) | Should BeNullOrEmpty - (Test-TargetResource -Path $certPath -Identity $UserName -Permission 'GenericRead' -Ensure Absent) | Should Be $true + (Test-TargetResource -Path $certPath -Identity $UserName -Permission $readPermission -Ensure Absent) | Should Be $true } finally { diff --git a/Test/Grant-Permission.Tests.ps1 b/Test/Grant-Permission.Tests.ps1 index 2d53f792..a9ba6565 100644 --- a/Test/Grant-Permission.Tests.ps1 +++ b/Test/Grant-Permission.Tests.ps1 @@ -66,6 +66,11 @@ function Assert-Permissions if( $providerName -eq 'Certificate' ) { $providerName = 'CryptoKey' + # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $providerName = 'FileSystem' + } } $rights = 0 @@ -145,6 +150,7 @@ function Invoke-GrantPermissions $ExpectedRuleType = ('Security.AccessControl.{0}AccessRule' -f $ExpectedRuleType) -as [Type] $result = Grant-Permission -Identity $Identity -Permission $Permissions -Path $path -PassThru @optionalParams + $result = $result | Select-Object -Last 1 It ('should return a {0}' -f $ExpectedRuleType.Name) { $result | Should Not BeNullOrEmpty $result.IdentityReference | Should Be (Resolve-IdentityName $Identity) @@ -494,60 +500,77 @@ foreach( $location in @( 'LocalMachine','CurrentUser' ) ) $cert = Install-Certificate -Path $privateKeyPath -StoreLocation $location -StoreName My -NoWarn try { + $certPath = Join-Path -Path ('cert:\{0}\My' -f $location) -ChildPath $cert.Thumbprint + $expectedRuleType = 'CryptoKey' + $readPermission = 'GenericRead' + $writePermission = 'GenericWrite' + + # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead + if( $PSVersionTable.PSEdition -eq 'Core') + { + $expectedRuleType = 'FileSystem' + $readPermission = 'Read' + $writePermission = 'Write' + } + It 'should install the certificate' { $cert | Should Not BeNullOrEmpty } - $certPath = Join-Path -Path ('cert:\{0}\My' -f $location) -ChildPath $cert.Thumbprint Context 'adds permissions' { - Invoke-GrantPermissions -Path $certPath -Identity $user -Permission 'GenericWrite' -ExpectedRuleType 'CryptoKey' -ExpectedPermission 'GenericRead','GenericAll' + Invoke-GrantPermissions -Path $certPath -Identity $user -Permission $writePermission -ExpectedRuleType $expectedRuleType -ExpectedPermission 'GenericRead','GenericAll' } Context 'changes permissions' { - Invoke-GrantPermissions -Path $certPath -Identity $user -Permission 'GenericRead' -ExpectedRuleType 'CryptoKey' + Invoke-GrantPermissions -Path $certPath -Identity $user -Permission $readPermission -ExpectedRuleType $expectedRuleType } Context 'clearing others'' permissions' { - Invoke-GrantPermissions -Path $certPath -Identity $user2 -Permission 'GenericRead' -ExpectedRuleType 'CryptoKey' -Clear + Invoke-GrantPermissions -Path $certPath -Identity $user2 -Permission $readPermission -ExpectedRuleType $expectedRuleType -Clear It 'should remove the other user''s permissions' { - (Test-Permission -Path $certPath -Identity $user -Permission 'GenericRead') | Should Be $false + (Test-Permission -Path $certPath -Identity $user -Permission $readPermission) | Should Be $false } } Context 'clearing others'' permissions when permissions getting set haven''t changed' { - Invoke-GrantPermissions -Path $certPath -Identity $user -Permission 'GenericRead' -ExpectedRuleType 'CryptoKey' - Invoke-GrantPermissions -Path $certPath -Identity $user2 -Permission 'GenericRead' -ExpectedRuleType 'CryptoKey' -Clear + Invoke-GrantPermissions -Path $certPath -Identity $user -Permission $readPermission -ExpectedRuleType $expectedRuleType + Invoke-GrantPermissions -Path $certPath -Identity $user2 -Permission $readPermission -ExpectedRuleType $expectedRuleType -Clear It 'should remove the other user''s permissions' { - (Test-Permission -Path $certPath -Identity $user -Permission 'GenericRead') | Should Be $false + (Test-Permission -Path $certPath -Identity $user -Permission $readPermission) | Should Be $false } } Context 'running with -WhatIf switch' { - Grant-Permission -Path $certPath -Identity $user2 -Permission 'GenericWrite' -WhatIf + Grant-Permission -Path $certPath -Identity $user2 -Permission $writePermission -WhatIf It 'should not change the user''s permissions' { - Test-Permission -Path $certPath -Identity $user2 -Permission 'GenericRead' -Exact | Should Be $true - Test-Permission -Path $certPath -Identity $user2 -Permission 'GenericWrite' -Exact | Should Be $false + Test-Permission -Path $certPath -Identity $user2 -Permission $readPermission -Exact | Should Be $true + Test-Permission -Path $certPath -Identity $user2 -Permission $writePermission -Exact | Should Be $false } } Context 'creating a deny rule' { - Invoke-GrantPermissions -Path $certPath -Identity $user -Permission 'GenericRead' -Type 'Deny' -ExpectedRuleType 'CryptoKey' + Invoke-GrantPermissions -Path $certPath -Identity $user -Permission $readPermission -Type 'Deny' -ExpectedRuleType $expectedRuleType } - Mock -CommandName 'Set-CryptoKeySecurity' -Verifiable -ModuleName 'Carbon' - Context 'permissions exist' { - # Now, check that permissions don't get re-applied. - Grant-Permission -Path $certPath -Identity $user2 -Permission 'GenericRead' - It 'should not set the permissions' { - Assert-MockCalled -CommandName 'Set-CryptoKeySecurity' -ModuleName 'Carbon' -Times 0 + # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead + if( $PSVersionTable.PSEdition -ne 'Core' ) + { + Mock -CommandName 'Set-CryptoKeySecurity' -Verifiable -ModuleName 'Carbon' + + Context 'permissions exist' { + # Now, check that permissions don't get re-applied. + Grant-Permission -Path $certPath -Identity $user2 -Permission $readPermission + It 'should not set the permissions' { + Assert-MockCalled -CommandName 'Set-CryptoKeySecurity' -ModuleName 'Carbon' -Times 0 + } } - } - Context 'permissions exist but forcing the change' { - Grant-Permission -Path $certPath -Identity $user2 -Permission 'GenericRead' -Force - It 'should set the permissions' { - Assert-MockCalled -CommandName 'Set-CryptoKeySecurity' -ModuleName 'Carbon' -Times 1 -Exactly + Context 'permissions exist but forcing the change' { + Grant-Permission -Path $certPath -Identity $user2 -Permission $readPermission -Force + It 'should set the permissions' { + Assert-MockCalled -CommandName 'Set-CryptoKeySecurity' -ModuleName 'Carbon' -Times 1 -Exactly + } } } } From d581e1d46dd648e245666254a25f98243750f731 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Tue, 12 Jul 2022 18:47:18 -0700 Subject: [PATCH 10/20] PFORM-1305 Fixing Remove-DotNetAppSetting tests. --- Carbon/Carbon.psm1.Import.Obsolete.ps1 | 7 +++- init.ps1 | 47 -------------------------- 2 files changed, 6 insertions(+), 48 deletions(-) delete mode 100644 init.ps1 diff --git a/Carbon/Carbon.psm1.Import.Obsolete.ps1 b/Carbon/Carbon.psm1.Import.Obsolete.ps1 index 4f50fe21..13ac0b57 100644 --- a/Carbon/Carbon.psm1.Import.Obsolete.ps1 +++ b/Carbon/Carbon.psm1.Import.Obsolete.ps1 @@ -682,7 +682,12 @@ function Get-CPowershellPath $psPath = $PSHOME } - Join-Path $psPath powershell.exe + $powershellExe = 'powershell.exe' + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $powershellExe = 'pwsh.exe' + } + Join-Path $psPath $powershellExe } diff --git a/init.ps1 b/init.ps1 deleted file mode 100644 index 90ea51de..00000000 --- a/init.ps1 +++ /dev/null @@ -1,47 +0,0 @@ -[CmdletBinding()] -param( -) - -Set-StrictMode -Version 'Latest' -$InformationPreference = 'Continue' - -# Run in a background job so that old PackageManagement assemblies don't get loaded. -$job = Start-Job { - $InformationPreference = 'Continue' - $psGalleryRepo = Get-PSRepository -Name 'PSGallery' - $repoToUse = $psGalleryRepo.Name - # On Windows 2012 R2, Windows PowerShell 5.1, and .NET 4.6.2, PSGallery's URL ends with a '/'. - if( -not $psGalleryRepo -or $psgalleryRepo.SourceLocation -ne 'https://www.powershellgallery.com/api/v2' ) - { - $repoToUse = 'PSGallery2' - Register-PSRepository -Name $repoToUse ` - -InstallationPolicy Trusted ` - -SourceLocation 'https://www.powershellgallery.com/api/v2' ` - -PackageManagementProvider $psGalleryRepo.PackageManagementProvider - } - - Write-Information -MessageData 'Installing latest version of PowerShell module Prism.' - Install-Module -Name 'Prism' -Scope CurrentUser -Repository $repoToUse -AllowClobber -Force - - if( -not (Get-Module -Name 'PackageManagement' -ListAvailable | Where-Object 'Version' -eq '1.4.7') ) - { - Write-Information -MessageData 'Installing PowerShell module PackageManagement 1.4.7.' - Install-Module -Name 'PackageManagement' -RequiredVersion '1.4.7'-Repository $repoToUse -AllowClobber -Force - } - - if( -not (Get-Module -Name 'PowerShellGet' -ListAvailable | Where-Object 'Version' -eq '2.2.5') ) - { - Write-Information -MessageData 'Installing PowerShell module PowerShellGet 2.2.5.' - Install-Module -Name 'PowerShellGet' -RequiredVersion '2.2.5' -Repository $repoToUse -AllowClobber -Force - } -} - -if( (Get-Command -Name 'Receive-Job' -ParameterName 'AutoRemoveJob') ) -{ - $job | Receive-Job -AutoRemoveJob -Wait -} -else -{ - $job | Wait-Job | Receive-Job - $job | Remove-Job -} \ No newline at end of file From 486ec7a4e14cf0bdbc14ebb382e06c1b15c22c25 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Wed, 13 Jul 2022 18:43:18 -0700 Subject: [PATCH 11/20] PFORM-1305 Import PSDesiredConfiguration version 2+ as version 1 is not compatible with PS Core. --- Test/CarbonDscTest/CarbonDscTest.psm1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Test/CarbonDscTest/CarbonDscTest.psm1 b/Test/CarbonDscTest/CarbonDscTest.psm1 index 2726976b..987b61c6 100644 --- a/Test/CarbonDscTest/CarbonDscTest.psm1 +++ b/Test/CarbonDscTest/CarbonDscTest.psm1 @@ -27,6 +27,24 @@ function Start-CarbonDscTestFixture $script:currentDscResource = $DscResourceName Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath ('..\..\Carbon\DscResources\Carbon_{0}' -f $DscResourceName) -Resolve) -Force -Global + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + if( Get-Module -Name 'PSDesiredStateConfiguration' | Where-Object Version -lt ([Version]'2.0.0') ) + { + Remove-Module -Name 'PSDesiredStateConfiguration' + } + + if( -not (Get-Module -Name 'PSDesiredStateConfiguration' | Where-Object Version -ge ([Version]'2.0.0')) ) + { + if( -not (Get-Module -Name 'PSDesiredStateConfiguration' -ListAvailable | Where-Object Version -ge ([Version]'2.0.0')) ) + { + Install-Module -Name PSDesiredStateConfiguration -Repository PSGallery -MaximumVersion 2.99 -Force + } + Import-Module -Name 'PSDesiredStateConfiguration' -Global + } + } + Enable-PSRemoting -SkipNetworkProfileCheck -Force + $tempDir = [IO.Path]::GetRandomFileName() $tempDir = 'CarbonDscTest-{0}-{1}' -f $DscResourceName,$tempDir $script:CarbonDscOutputRoot = Join-Path -Path $env:TEMP -ChildPath $tempDir From 0e22671c67eba8f6e64b21554b253659afb98355 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Thu, 14 Jul 2022 10:16:02 -0700 Subject: [PATCH 12/20] Adding -ErrorAction SilentlyContinue to junction tests. --- Test/New-Junction.Tests.ps1 | 2 +- Test/Remove-Junction.Tests.ps1 | 2 +- Test/Uninstall-Junction.Tests.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Test/New-Junction.Tests.ps1 b/Test/New-Junction.Tests.ps1 index ec5fb405..34698672 100644 --- a/Test/New-Junction.Tests.ps1 +++ b/Test/New-Junction.Tests.ps1 @@ -30,7 +30,7 @@ Describe 'New-Junction' { function Invoke-NewJunction($link, $target) { - return New-Junction $link $target + return New-Junction $link $target -ErrorAction SilentlyContinue } It 'should create junction' { diff --git a/Test/Remove-Junction.Tests.ps1 b/Test/Remove-Junction.Tests.ps1 index 59195ee6..3cc1f83e 100644 --- a/Test/Remove-Junction.Tests.ps1 +++ b/Test/Remove-Junction.Tests.ps1 @@ -20,7 +20,7 @@ Describe 'Remove-Junction' { function Invoke-RemoveJunction($junction) { - Remove-Junction $junction + Remove-Junction $junction -ErrorAction SilentlyContinue } BeforeEach { diff --git a/Test/Uninstall-Junction.Tests.ps1 b/Test/Uninstall-Junction.Tests.ps1 index dfce12ee..225e58ea 100644 --- a/Test/Uninstall-Junction.Tests.ps1 +++ b/Test/Uninstall-Junction.Tests.ps1 @@ -31,7 +31,7 @@ Describe 'Uninstall-Junction' { function Invoke-UninstallJunction($junction) { - Uninstall-Junction $junction + Uninstall-Junction $junction -ErrorAction SilentlyContinue } It 'should uninstall junction' { From 11fe72fcaaf1c80e9a66287905bf44ffe0afddb5 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Thu, 14 Jul 2022 15:00:05 -0700 Subject: [PATCH 13/20] Fix broken tests for New-RsaKeyPair and Get-ServiceConfiguration --- Carbon/Carbon.psm1.Import.Obsolete.ps1 | 1 + Carbon/Functions/Get-ServiceConfiguration.ps1 | 3 ++- Test/New-RsaKeyPair.Tests.ps1 | 8 +++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Carbon/Carbon.psm1.Import.Obsolete.ps1 b/Carbon/Carbon.psm1.Import.Obsolete.ps1 index 13ac0b57..6a7aabf4 100644 --- a/Carbon/Carbon.psm1.Import.Obsolete.ps1 +++ b/Carbon/Carbon.psm1.Import.Obsolete.ps1 @@ -510,6 +510,7 @@ function Get-CCertificate } } +Set-Alias -Name 'Get-Certificate' -Value 'Get-CCertificate' function Get-CMsi diff --git a/Carbon/Functions/Get-ServiceConfiguration.ps1 b/Carbon/Functions/Get-ServiceConfiguration.ps1 index cf99927b..bd951885 100644 --- a/Carbon/Functions/Get-ServiceConfiguration.ps1 +++ b/Carbon/Functions/Get-ServiceConfiguration.ps1 @@ -178,8 +178,9 @@ function Get-CServiceConfiguration process { $optionalParams = @{ } - if( $ComputerName ) + if( $ComputerName -and $PSVersionTable.PSEdition -ne 'Core') { + # ComputerName parameter does not exists under PowerShell Core. $optionalParams['ComputerName'] = $ComputerName } diff --git a/Test/New-RsaKeyPair.Tests.ps1 b/Test/New-RsaKeyPair.Tests.ps1 index 2e24d346..79924df5 100644 --- a/Test/New-RsaKeyPair.Tests.ps1 +++ b/Test/New-RsaKeyPair.Tests.ps1 @@ -38,6 +38,12 @@ Describe 'New-RsaKeyPair' { $ValidTo = (Get-Date).AddDays( [Math]::Floor(([DateTime]::MaxValue - [DateTime]::UtcNow).TotalDays) ) } + $keyExchangeAlgorithm = 'RSA-PKCS1-KeyEx' + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $keyExchangeAlgorithm = 'RSA' + } + $cert = Get-Certificate -Path $publicKeyPath -NoWarn # Weird date/time stamps in generated certificate that I can't figure out/replicate. So we'll just check that the expected/actual dates are within a day of each other. [timespan]$span = $ValidTo - $cert.NotAfter @@ -45,7 +51,7 @@ Describe 'New-RsaKeyPair' { $span.TotalDays | Should BeLessThan 2 $cert.Subject | Should Be $subject $cert.PublicKey.Key.KeySize | Should Be $Length - $cert.PublicKey.Key.KeyExchangeAlgorithm | Should Be 'RSA-PKCS1-KeyEx' + $cert.PublicKey.Key.KeyExchangeAlgorithm | Should Be $keyExchangeAlgorithm $cert.SignatureAlgorithm.FriendlyName | Should Be $Algorithm $keyUsage = $cert.Extensions | Where-Object { $_ -is [Security.Cryptography.X509Certificates.X509KeyUsageExtension] } $keyUsage | Should Not BeNullOrEmpty From 92bed1573afce8604e910a9632c5a05433aa5af3 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Thu, 14 Jul 2022 18:00:30 -0700 Subject: [PATCH 14/20] Removing installation of PackageManagement and PowerShellGet from appveyor build script. --- appveyor.yml | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d9b83927..4650a7f4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -73,25 +73,6 @@ for: - job_group: ps build_script: - ps: | - if( -not (Get-Module -Name 'PowerShellGet' -ListAvailable | Where-Object Version -eq ([Version]'2.2.5')) ) - { - $job = Start-Job { - Install-Module -Name 'PowerShellGet' -RequiredVersion '2.2.5' -AllowClobber -Force -Scope CurrentUser - } - $job | Wait-Job - $job | Receive-Job - $job | Remove-Job - } - if( -not (Get-Module -Name 'PackageManagement' -ListAvailable | Where-Object Version -eq ([Version]'1.4.7')) ) - { - $job = Start-Job { - Install-Module -Name 'PackageManagement' -RequiredVersion '1.4.7' -AllowClobber -Force -Scope CurrentUser - } - $job | Wait-Job - $job | Receive-Job - $job | Remove-Job - } - Get-Module 'PowerShellGet', 'PackageManagement' -ListAvailable | Format-Table -Auto .\build.ps1 # Build in PowerShell @@ -100,23 +81,4 @@ for: - job_group: pwsh build_script: - pwsh: | - if( -not (Get-Module -Name 'PowerShellGet' -ListAvailable | Where-Object Version -eq ([Version]'2.2.5')) ) - { - $job = Start-Job { - Install-Module -Name 'PowerShellGet' -RequiredVersion '2.2.5' -AllowClobber -Force -Scope CurrentUser - } - $job | Wait-Job - $job | Receive-Job - $job | Remove-Job - } - if( -not (Get-Module -Name 'PackageManagement' -ListAvailable | Where-Object Version -eq ([Version]'1.4.7')) ) - { - $job = Start-Job { - Install-Module -Name 'PackageManagement' -RequiredVersion '1.4.7' -AllowClobber -Force -Scope CurrentUser - } - $job | Wait-Job - $job | Receive-Job - $job | Remove-Job - } - Get-Module 'PowerShellGet', 'PackageManagement' -ListAvailable | Format-Table -Auto ./build.ps1 From 52039e2dc128b6f6b7a73931a0edab52be3abba7 Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Thu, 14 Jul 2022 18:52:13 -0700 Subject: [PATCH 15/20] Get-CPowershellPath should return path to powershell.exe --- Carbon/Carbon.psm1.Import.Obsolete.ps1 | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Carbon/Carbon.psm1.Import.Obsolete.ps1 b/Carbon/Carbon.psm1.Import.Obsolete.ps1 index 6a7aabf4..651c7ac9 100644 --- a/Carbon/Carbon.psm1.Import.Obsolete.ps1 +++ b/Carbon/Carbon.psm1.Import.Obsolete.ps1 @@ -658,6 +658,10 @@ function Get-CPowershellPath } $psPath = $PSHOME + if( $PSVersionTable.PSEdition -eq 'Core' ) + { + $psPath = 'C:\Windows\System32\WindowsPowerShell\v1.0' + } if( (Test-COSIs64Bit -NoWarn) ) { if( (Test-CPowerShellIs64Bit -NoWarn) ) @@ -665,7 +669,7 @@ function Get-CPowershellPath if( $x86 ) { # x64 OS, x64 PS, want x86 path - $psPath = $PSHOME -replace 'System32','SysWOW64' + $psPath = $psPath -replace 'System32','SysWOW64' } } else @@ -673,7 +677,7 @@ function Get-CPowershellPath if( -not $x86 ) { # x64 OS, x32 PS, want x64 path - $psPath = $PSHome -replace 'SysWOW64','sysnative' + $psPath = $psPath -replace 'SysWOW64','sysnative' } } } @@ -683,12 +687,7 @@ function Get-CPowershellPath $psPath = $PSHOME } - $powershellExe = 'powershell.exe' - if( $PSVersionTable.PSEdition -eq 'Core' ) - { - $powershellExe = 'pwsh.exe' - } - Join-Path $psPath $powershellExe + Join-Path $psPath powershell.exe } From 4042bf3d26d9931a5d3e36f9c716d05783f6e10f Mon Sep 17 00:00:00 2001 From: Khoi Ky Date: Fri, 29 Jul 2022 11:15:35 -0700 Subject: [PATCH 16/20] Removing Windows Server 2016 PowerShell 6 build. --- CHANGELOG.md | 7 +++---- appveyor.yml | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2547812f..869d7ea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,9 @@ ## Added suport for PowerShell Core -* Added: `Get-Cim` function that determines which method to call when accessing a computer's Common Information Model. - `Get-Cim` will call `Get-CimInstance` when PowerShell Core is being used and `Get-WmiObject` when Windows PowerShell - is being used. - +* Added: `Get-Cim` function that determines which method to call when accessing a computer's Common Information Model based on the version of PowerShell being used. `Get-Cim` will call `Get-CimInstance` under PowerShell Core and `Get-WmiObject` under Windows PowerShell. `Get-WmiObject` has been deprecated under PowerShell Core. +* Fixed: Carbon will now use version 2 of the `PSDesiredStateConfiguration` module when running under PowerShell Core as verion 1 was incompatible. +* Fixed: Granting permissions on a certificate will use type `Security.AccessControl.FileSystemRights` as `Security.AccessControl.CryptoKeyRights` has been deprecated under PowerShell Core. # 2.11.3 diff --git a/appveyor.yml b/appveyor.yml index 4650a7f4..48f824a3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,9 +47,10 @@ environment: appveyor_build_worker_image: Visual Studio 2017 # TODO: Get-WmiObject doesn't exist. Does Get-CimInstance? Can Carbon support PowerShell 6? - - job_name: Windows Server 2016, PowerShell 6 - job_group: pwsh - appveyor_build_worker_image: Visual Studio 2017 + # Currently appveyor vm for PS6 has PowerShell Get 2.1.3 installed which causes issue when publishing modules. + # - job_name: Windows Server 2016, PowerShell 6 + # job_group: pwsh + # appveyor_build_worker_image: Visual Studio 2017 # TODO: Get build working on a new version of the .NET SDK. # - job_name: Windows Server 2019, Windows PowerShell 5.1 From d91b21e1b1568667cab9912a88ab99e52cdf2d55 Mon Sep 17 00:00:00 2001 From: "Ky, Khoi" Date: Mon, 1 Aug 2022 20:28:48 -0700 Subject: [PATCH 17/20] Get-Cim function is now broken up into Get-CCimInstance and Get-CCimClass private functions. Added Invoke-CPrivateCommand to call private functions. --- CHANGELOG.md | 2 +- Carbon/Carbon.psd1 | 1 - Carbon/Carbon.psm1 | 2 +- Carbon/Carbon.psm1.Import.Obsolete.ps1 | 66 +++++++++++++------ .../Functions/Clear-DscLocalResourceCache.ps1 | 10 +-- .../ConvertTo-ProviderAccessControlRights.ps1 | 2 +- Carbon/Functions/Get-CCimClass.ps1 | 32 +++++++++ Carbon/Functions/Get-CCimInstance.ps1 | 47 +++++++++++++ Carbon/Functions/Get-Cim.ps1 | 63 ------------------ Carbon/Functions/Get-FileShare.ps1 | 2 +- Carbon/Functions/Get-FileSharePermission.ps1 | 4 +- Carbon/Functions/Get-ServiceConfiguration.ps1 | 9 ++- Carbon/Functions/Get-WmiLocalUserAccount.ps1 | 2 +- Carbon/Functions/Install-FileShare.ps1 | 11 +++- Carbon/Functions/Revoke-Permission.ps1 | 4 +- .../Functions/Start-DscPullConfiguration.ps1 | 2 +- Carbon/Functions/Test-CCimAvailable.ps1 | 5 ++ Carbon/Functions/Test-CCryptoKeyAvailable.ps1 | 4 ++ Carbon/Functions/Test-Permission.ps1 | 2 +- Carbon/Functions/Uninstall-FileShare.ps1 | 2 +- Initialize-Server.ps1 | 2 +- Test/ActiveDirectory/Test-FindADUser.ps1 | 2 +- .../Test-GetADDomainController.ps1 | 2 +- Test/Add-GroupMember.Tests.ps1 | 4 +- Test/CarbonDscTest/CarbonDscTest.psm1 | 4 +- Test/CarbonTest.psm1 | 32 +++++++++ Test/Get-ServiceConfiguration.Tests.ps1 | 13 +++- Test/Grant-Permission.Tests.ps1 | 8 +-- Test/Initialize-CarbonTest.ps1 | 6 ++ Test/Install-Service.Tests.ps1 | 2 +- Test/MSMQ/Test-GetMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 | 2 +- Test/MSMQ/Test-TestMSMQMessageQueue.ps1 | 2 +- Test/New-RsaKeyPair.Tests.ps1 | 16 ++--- Test/Share/Test-GetFileShare.ps1 | 6 +- Test/Share/Test-InstallFileShare.ps1 | 2 +- Test/Share/Test-TestFileShare.ps1 | 2 +- ...System.Diagnostics.Process.types.Tests.ps1 | 2 +- Test/Test-Identity.Tests.ps1 | 2 +- Test/Uninstall-FileShare.Tests.ps1 | 2 +- .../Test-GetWmiLocalUserAccount.ps1 | 2 +- Test/UsersAndGroups/Test-TestUser.ps1 | 2 +- appveyor.yml | 6 +- 44 files changed, 252 insertions(+), 145 deletions(-) create mode 100644 Carbon/Functions/Get-CCimClass.ps1 create mode 100644 Carbon/Functions/Get-CCimInstance.ps1 delete mode 100644 Carbon/Functions/Get-Cim.ps1 create mode 100644 Carbon/Functions/Test-CCimAvailable.ps1 create mode 100644 Carbon/Functions/Test-CCryptoKeyAvailable.ps1 create mode 100644 Test/CarbonTest.psm1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 869d7ea6..3daa4882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Added suport for PowerShell Core -* Added: `Get-Cim` function that determines which method to call when accessing a computer's Common Information Model based on the version of PowerShell being used. `Get-Cim` will call `Get-CimInstance` under PowerShell Core and `Get-WmiObject` under Windows PowerShell. `Get-WmiObject` has been deprecated under PowerShell Core. +* Added: `Get-CCimInstance` function that determines which method to call when accessing a computer's Common Information Model based on the version of PowerShell being used. `Get-CCimInstance` will call `Get-CimInstance` under PowerShell Core and `Get-WmiObject` under Windows PowerShell. `Get-WmiObject` has been deprecated under PowerShell Core. * Fixed: Carbon will now use version 2 of the `PSDesiredStateConfiguration` module when running under PowerShell Core as verion 1 was incompatible. * Fixed: Granting permissions on a certificate will use type `Security.AccessControl.FileSystemRights` as `Security.AccessControl.CryptoKeyRights` has been deprecated under PowerShell Core. diff --git a/Carbon/Carbon.psd1 b/Carbon/Carbon.psd1 index bbaaff8c..4d3084ce 100644 --- a/Carbon/Carbon.psd1 +++ b/Carbon/Carbon.psd1 @@ -161,7 +161,6 @@ All functions are idempotent: when run multiple times with the same arguments, y 'Get-CIisSecurityAuthentication', 'Get-CIisVersion', 'Get-CIisWebsite', - 'Get-Cim', 'Get-CIPAddress', 'Get-CMsi', 'Get-CMsmqMessageQueue', diff --git a/Carbon/Carbon.psm1 b/Carbon/Carbon.psm1 index 0b8eafed..915c21ba 100644 --- a/Carbon/Carbon.psm1 +++ b/Carbon/Carbon.psm1 @@ -193,7 +193,7 @@ Add-CTypeData -Type Diagnostics.Process ` -MemberType ScriptProperty ` -Value { $filter = "ProcessID='{0}'" -f $this.Id - $process = Get-Cim -Class 'Win32_Process' -Filter $filter + $process = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Process'; Filter = $filter} return $process.ParentProcessID } diff --git a/Carbon/Carbon.psm1.Import.Obsolete.ps1 b/Carbon/Carbon.psm1.Import.Obsolete.ps1 index 651c7ac9..a28facb2 100644 --- a/Carbon/Carbon.psm1.Import.Obsolete.ps1 +++ b/Carbon/Carbon.psm1.Import.Obsolete.ps1 @@ -510,8 +510,6 @@ function Get-CCertificate } } -Set-Alias -Name 'Get-Certificate' -Value 'Get-CCertificate' - function Get-CMsi { @@ -662,32 +660,58 @@ function Get-CPowershellPath { $psPath = 'C:\Windows\System32\WindowsPowerShell\v1.0' } - if( (Test-COSIs64Bit -NoWarn) ) + + # x86 OS/x86 PowerShell. There's no 64-bit anything, so just return $PSHOME. + if( Test-COSIs32Bit ) { - if( (Test-CPowerShellIs64Bit -NoWarn) ) + if( $x86 ) { - if( $x86 ) - { - # x64 OS, x64 PS, want x86 path - $psPath = $psPath -replace 'System32','SysWOW64' - } + return Join-Path -Path $psPath -ChildPath 'powershell.exe' } - else + + $msg = 'Unable to get the path to 64-bit PowerShell: this is a 32-bit operating system and ' + + '64-bit PowerShell does not exist.' + Write-Error -Message $msg -ErrorAction Ignore + return + } + + # Make sure the paths end in '\' so we don't replace/change + # paths that start with the directory name and have extra characters. + $programFilesPath = Join-Path -Path ([Environment]::GetFolderPath('ProgramFiles')) -ChildPath '\' + $systemPath = Join-Path -Path ([Environment]::GetFolderPath('System')) -ChildPath '\' + + if( (Test-CPowerShellIs64Bit -NoWarn) ) + { + $programFilesx86Path = + Join-Path -Path ([Environment]::GetFolderPath('ProgramFilesx86')) -ChildPath '\' + $system32Path = Join-Path -Path ([Environment]::GetFolderPath('Systemx86')) -ChildPath '\' + + if( $x86 ) { - if( -not $x86 ) - { - # x64 OS, x32 PS, want x64 path - $psPath = $psPath -replace 'SysWOW64','sysnative' - } + # x64 OS/x64 PS wanting x86 paths. + # C:\Program Files\ -> C:\Program Files (x86)\ + # C:\WINDOWS\system32\ -> C:\WINDOWS\SysWOW64\ + return Join-Path -Path (($psPath -replace ([regex]::Escape($programFilesPath)), $programFilesx86Path) ` + -replace ([regex]::Escape($systemPath)), $system32Path) -ChildPath 'powershell.exe' } + + # x64 OS/PS, wanting x64 Path, which is the same as this process's PSHOME variable. + return Join-Path $psPath -ChildPath 'powershell.exe' } - else + + if( $x86 ) { - # x86 OS, no SysWOW64, everything is in $PSHOME - $psPath = $PSHOME + # x64 OS/x86 PowerShell, wanting x86 path, which is the same as this process. + return Join-Path $psPath -ChildPath 'powershell.exe' } - - Join-Path $psPath powershell.exe + + # x64 OS, x86 PowerShell, wanting x64 path + # C:\Program Files (x86)\ -> C:\Program Files\ + # C:\WINDOWS\system32\ -> C:\WINDOWS\sysnative\ + $programFiles64Path = Join-Path -Path $env:ProgramFilesW6432 -ChildPath '\' + $system64Path = Join-Path -Path ([Environment]::GetFolderPath('Windows')) -ChildPath 'sysnative\' + return Join-Path -Path (($psPath -replace ([regex]::Escape($programFilesPath)), $programFiles64Path) ` + -replace ([regex]::Escape($systemPath)), $system64Path) -ChildPath 'powershell.exe' } @@ -754,7 +778,7 @@ if( -not (Get-Command -Name 'Get-WindowsFeature*' | Where-Object { $_.ModuleName if( $useOCSetup ) { - Get-Cim -Class 'Win32_OptionalFeature' | + Get-CCimInstance -Class 'Win32_OptionalFeature' | Where-Object { if( $Name ) { diff --git a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 index 62c1dc6d..13b91206 100644 --- a/Carbon/Functions/Clear-DscLocalResourceCache.ps1 +++ b/Carbon/Functions/Clear-DscLocalResourceCache.ps1 @@ -21,9 +21,9 @@ function Clear-CDscLocalResourceCache Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - Get-Cim -Class 'msft_providers' | - Where-Object {$_.provider -like 'dsccore'} | - Select-Object -ExpandProperty HostProcessIdentifier | - ForEach-Object { Get-Process -ID $_ } | - Stop-Process -Force + Get-CCimInstance -Class 'msft_providers' | + Where-Object {$_.provider -like 'dsccore'} | + Select-Object -ExpandProperty HostProcessIdentifier | + ForEach-Object { Get-Process -ID $_ } | + Stop-Process -Force } diff --git a/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 b/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 index 42c267c1..21508721 100644 --- a/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 +++ b/Carbon/Functions/ConvertTo-ProviderAccessControlRights.ps1 @@ -37,7 +37,7 @@ function ConvertTo-ProviderAccessControlRights $rightTypeName = 'Security.AccessControl.{0}Rights' -f $ProviderName # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead - if( $PSVersionTable.PSEdition -eq 'Core' -and $ProviderName -eq 'CryptoKey') + if( $ProviderName -eq 'CryptoKey' -and -not (Test-CCryptoKeyAvailable)) { $rightTypeName = 'Security.AccessControl.FileSystemRights' } diff --git a/Carbon/Functions/Get-CCimClass.ps1 b/Carbon/Functions/Get-CCimClass.ps1 new file mode 100644 index 00000000..48d5c2e6 --- /dev/null +++ b/Carbon/Functions/Get-CCimClass.ps1 @@ -0,0 +1,32 @@ +function Get-CCimClass +{ + <# + .SYNOPSIS + Calls Get-CimClass, with a fallback to Get-WmiObject. + + .DESCRIPTION + The `Get-CCimClass` function calls PowerShell's `Get-CimClass` cmdlet. If CIM isn't available, calls `Get-WmiObject` instead. + + .EXAMPLE + Get-CCimClass -Class 'Win32_OperatingSystem' + + Demonstrates how to use `Get-CCimClass`. In this example, the function will call `Get-CimClass -ClassName 'Win32_OperatingSystem'`, except when that cmdlet doesn't exist, when it calls `Get-WmiObject -Class 'Win32_OperatingSystem' -List`. + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $Class + ) + + $useCim = Test-CCimAvailable + + if( $useCim ) + { + Get-CimClass -ClassName $Class + } + else + { + Get-WmiObject -Class $Class -List + } +} \ No newline at end of file diff --git a/Carbon/Functions/Get-CCimInstance.ps1 b/Carbon/Functions/Get-CCimInstance.ps1 new file mode 100644 index 00000000..bcd0b67f --- /dev/null +++ b/Carbon/Functions/Get-CCimInstance.ps1 @@ -0,0 +1,47 @@ + +function Get-CCimInstance +{ + <# + .SYNOPSIS + Calls Get-CimInstance, with a fallback to Get-WmiObject. + + .DESCRIPTION + The `Get-CCimInstance` function calls PowerShell's `Get-CimInstance` cmdlet. If CIM isn't available, calls `Get-WmiObject` instead. + + .EXAMPLE + Get-CCimInstance -Class 'Win32_OperatingSystem' + + Demonstrates how to use `Get-CCimInstance`. In this example, the function will call `Get-CimInstance -ClassName 'Win32_OperatingSystem'`, except when that cmdlet doesn't exist, when it calls `Get-WmiObject -Class 'Win32_OperatingSystem'`. + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $Class, + + [String] $Filter, + + [String] $Query + ) + $useCim = Test-CCimAvailable + $optionalArgs = @{ } + + if( $Filter ) + { + $optionalArgs['Filter'] = $Filter + } + + if( $Query ) + { + $optionalArgs['Query'] = $Query + } + + if( $useCim ) + { + Get-CimInstance -ClassName $Class @optionalArgs + } + else + { + Get-WmiObject -Class $Class @optionalArgs + } +} \ No newline at end of file diff --git a/Carbon/Functions/Get-Cim.ps1 b/Carbon/Functions/Get-Cim.ps1 deleted file mode 100644 index ded581ce..00000000 --- a/Carbon/Functions/Get-Cim.ps1 +++ /dev/null @@ -1,63 +0,0 @@ - -function Get-Cim -{ - <# - .SYNOPSIS - Gets the CIM instance of a class or information about the avaialble classes. - - .DESCRIPTION - Get-WmiObject has been deprecated since PowerShell 6 and Get-CimInstance is the new method to use. This function will determine - which method to use based on the version of PowerShell. Currently only accepting $Class, $Filter, $List, and $Query parameters - as these are the ones being used in Carbon. More parameters can be added if needed. - - .EXAMPLE - Get-Cim -ClassName 'Win32_OperatingSystem' - - Gets the instance for Win32_OperatingSystem class. - #> - - [CmdletBinding()] - param( - [Parameter(Mandatory)] - [String] $Class, - - [String] $Filter, - - [Switch] $List, - - [String] $Query - ) - $IsPSCore = $PSVersionTable.PSEdition -eq 'Core' - $optionalArgs = @{ } - - if( $Filter ) - { - $optionalArgs['Filter'] = $Filter - } - - if( $List -and -not $IsPSCore ) - { - $optionalArgs['List'] = $List - } - - if( $Query ) - { - $optionalArgs['Query'] = $Query - } - - if( $IsPSCore ) - { - if( $List ) - { - Get-CimClass -ClassName $Class - } - else - { - Get-CimInstance -ClassName $Class @optionalArgs - } - } - else - { - Get-WmiObject -Class $Class @optionalArgs - } -} \ No newline at end of file diff --git a/Carbon/Functions/Get-FileShare.ps1 b/Carbon/Functions/Get-FileShare.ps1 index d6e62a03..423fc38a 100644 --- a/Carbon/Functions/Get-FileShare.ps1 +++ b/Carbon/Functions/Get-FileShare.ps1 @@ -62,7 +62,7 @@ function Get-CFileShare $filter = '{0} and Name = ''{1}''' -f $filter,$Name } - $shares = Get-Cim -Class 'Win32_Share' -Filter $filter | + $shares = Get-CCimInstance -Class 'Win32_Share' -Filter $filter | Where-Object { if( -not $wildcardSearch ) { diff --git a/Carbon/Functions/Get-FileSharePermission.ps1 b/Carbon/Functions/Get-FileSharePermission.ps1 index dc4b4dd9..c927b9b5 100644 --- a/Carbon/Functions/Get-FileSharePermission.ps1 +++ b/Carbon/Functions/Get-FileSharePermission.ps1 @@ -78,13 +78,13 @@ function Get-CFileSharePermission } $acl = $null - $lsss = Get-Cim -Class 'Win32_LogicalShareSecuritySetting' -Filter "name='$Name'" + $lsss = Get-CCimInstance -Class 'Win32_LogicalShareSecuritySetting' -Filter "name='$Name'" if( -not $lsss ) { return } - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( Test-CCimAvailable ) { $result = Invoke-CimMethod -InputObject $lsss -MethodName 'GetSecurityDescriptor' } diff --git a/Carbon/Functions/Get-ServiceConfiguration.ps1 b/Carbon/Functions/Get-ServiceConfiguration.ps1 index bd951885..51b04216 100644 --- a/Carbon/Functions/Get-ServiceConfiguration.ps1 +++ b/Carbon/Functions/Get-ServiceConfiguration.ps1 @@ -178,9 +178,16 @@ function Get-CServiceConfiguration process { $optionalParams = @{ } - if( $ComputerName -and $PSVersionTable.PSEdition -ne 'Core') + if( $ComputerName ) { # ComputerName parameter does not exists under PowerShell Core. + if( -not (Get-Command -Name 'Get-Service' -ParameterName 'ComputerName' -ErrorAction Ignore) ) + { + $msg = "Unable to get service ""$($Name)"" on computer ""$($ComputerName)"": this version " + + 'of PowerShell doesn''t support services on remote computers.' + Write-Error $msg -ErrorAction $ErrorActionPreference + return + } $optionalParams['ComputerName'] = $ComputerName } diff --git a/Carbon/Functions/Get-WmiLocalUserAccount.ps1 b/Carbon/Functions/Get-WmiLocalUserAccount.ps1 index 874cd94e..497bd801 100644 --- a/Carbon/Functions/Get-WmiLocalUserAccount.ps1 +++ b/Carbon/Functions/Get-WmiLocalUserAccount.ps1 @@ -31,6 +31,6 @@ function Get-CWmiLocalUserAccount Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState - return Get-Cim -Class 'Win32_UserAccount' -Filter "Domain='$($env:ComputerName)' and Name='$Username'" + return Get-CCimInstance -Class 'Win32_UserAccount' -Filter "Domain='$($env:ComputerName)' and Name='$Username'" } diff --git a/Carbon/Functions/Install-FileShare.ps1 b/Carbon/Functions/Install-FileShare.ps1 index 4bf1b571..831454b8 100644 --- a/Carbon/Functions/Install-FileShare.ps1 +++ b/Carbon/Functions/Install-FileShare.ps1 @@ -175,8 +175,17 @@ function Install-CFileShare New-Item -Path $Path -ItemType Directory -Force | Out-String | Write-Verbose } + $shareClass = Get-CCimClass -Class 'Win32_Share' Write-Verbose -Message ('[SHARE] [{0}] Sharing {1}' -f $Name,$Path) - $result = ([wmiclass]"root\cimv2:Win32_Share").Create( $Path, $Name, 0, $null, $Description, $null, $shareSecurityDescriptor ) + + if( Test-CCimAvailable ) + { + $result = ([wmiclass]"root\cimv2:Win32_Share").Create( $Path, $Name, 0, $null, $Description, $null, $shareSecurityDescriptor ) + } + else + { + $result = $shareClass.Create( $Path, $Name, 0, $null, $Description, $null, $shareSecurityDescriptor ) + } if( $result.ReturnValue ) { diff --git a/Carbon/Functions/Revoke-Permission.ps1 b/Carbon/Functions/Revoke-Permission.ps1 index d7d8f7dc..3258c39c 100644 --- a/Carbon/Functions/Revoke-Permission.ps1 +++ b/Carbon/Functions/Revoke-Permission.ps1 @@ -70,7 +70,7 @@ function Revoke-CPermission if( $providerName -eq 'Certificate' ) { $providerName = 'CryptoKey' - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( -not (Test-CCryptoKeyAvailable) ) { $providerName = 'FileSystem' } @@ -98,7 +98,7 @@ function Revoke-CPermission "$($env:ALLUSERSPROFILE)\Application Data\Microsoft\Crypto", "$($env:ALLUSERSPROFILE)\Microsoft\Crypto" ) - $privateKeyFiles = $keyStoragePaths | Get-ChildItem -Recurse -Force -ErrorAction Ignore -Filter $privateKeyFileName + $privateKeyFiles = $keyStoragePaths | Get-ChildItem -Recurse -Force -Filter $privateKeyFileName -ErrorAction Ignore if( -not $privateKeyFiles ) { $msg = "Failed to find the private key file for certificate ""$($Path)"" (subject: $($_.Subject); " + diff --git a/Carbon/Functions/Start-DscPullConfiguration.ps1 b/Carbon/Functions/Start-DscPullConfiguration.ps1 index 52a2d883..aabb3b6f 100644 --- a/Carbon/Functions/Start-DscPullConfiguration.ps1 +++ b/Carbon/Functions/Start-DscPullConfiguration.ps1 @@ -123,7 +123,7 @@ function Start-CDscPullConfiguration $ModuleName ) - $dscProcessID = Get-Cim -Class 'msft_providers' | + $dscProcessID = Get-CCimInstance -Class 'msft_providers' | Where-Object {$_.provider -like 'dsccore'} | Select-Object -ExpandProperty HostProcessIdentifier Stop-Process -Id $dscProcessID -Force diff --git a/Carbon/Functions/Test-CCimAvailable.ps1 b/Carbon/Functions/Test-CCimAvailable.ps1 new file mode 100644 index 00000000..3a8889f6 --- /dev/null +++ b/Carbon/Functions/Test-CCimAvailable.ps1 @@ -0,0 +1,5 @@ +function Test-CCimAvailable +{ + # Windows PowerShell comes with CimCmdlets version 1.0.0 and PowerShell Core comes with CimCmdlets version > 7.0.0 + return (Get-Command -Name 'Get-CimInstance' -ErrorAction Ignore).Version.Major -ge 7 +} \ No newline at end of file diff --git a/Carbon/Functions/Test-CCryptoKeyAvailable.ps1 b/Carbon/Functions/Test-CCryptoKeyAvailable.ps1 new file mode 100644 index 00000000..95ba6678 --- /dev/null +++ b/Carbon/Functions/Test-CCryptoKeyAvailable.ps1 @@ -0,0 +1,4 @@ +function Test-CCryptoKeyAvailable +{ + return $null -ne [Type]::GetType('System.Security.AccessControl.CryptoKeyRights') +} \ No newline at end of file diff --git a/Carbon/Functions/Test-Permission.ps1 b/Carbon/Functions/Test-Permission.ps1 index dd41506e..b5fce90c 100644 --- a/Carbon/Functions/Test-Permission.ps1 +++ b/Carbon/Functions/Test-Permission.ps1 @@ -120,7 +120,7 @@ function Test-CPermission { $providerName = 'CryptoKey' # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( -not (Test-CCryptoKeyAvailable) ) { $providerName = 'FileSystem' } diff --git a/Carbon/Functions/Uninstall-FileShare.ps1 b/Carbon/Functions/Uninstall-FileShare.ps1 index 7f5c1a34..bae66817 100644 --- a/Carbon/Functions/Uninstall-FileShare.ps1 +++ b/Carbon/Functions/Uninstall-FileShare.ps1 @@ -70,7 +70,7 @@ function Uninstall-CFileShare { Write-Verbose ('Deleting file share ''{0}'' (Path: {1}).' -f $share.Name,$share.Path) - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( Test-CCimAvailable ) { $result = Invoke-CimMethod -InputObject $share -MethodName 'Delete' } diff --git a/Initialize-Server.ps1 b/Initialize-Server.ps1 index 2efa7721..5900caf5 100644 --- a/Initialize-Server.ps1 +++ b/Initialize-Server.ps1 @@ -23,7 +23,7 @@ Set-StrictMode -Version 'Latest' $PSCommandPath = $MyInvocation.MyCommand.Definition $PSScriptRoot = Split-Path -Parent -Path $PSCommandPath -$os = Get-Cim -Class 'Win32_OperatingSystem' +$os = Get-CCimInstance -Class 'Win32_OperatingSystem' # Windows 2008 $osVersion = [version]$os.Version diff --git a/Test/ActiveDirectory/Test-FindADUser.ps1 b/Test/ActiveDirectory/Test-FindADUser.ps1 index dc5d10f8..1eced66d 100644 --- a/Test/ActiveDirectory/Test-FindADUser.ps1 +++ b/Test/ActiveDirectory/Test-FindADUser.ps1 @@ -10,7 +10,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) +if( (Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'}).Domain -eq 'WORKGROUP' ) { Write-Warning -Message ('Find-ADUser tests can''t run because this computer is not part of a domain.') } diff --git a/Test/ActiveDirectory/Test-GetADDomainController.ps1 b/Test/ActiveDirectory/Test-GetADDomainController.ps1 index 66add40a..f0a0a7d2 100644 --- a/Test/ActiveDirectory/Test-GetADDomainController.ps1 +++ b/Test/ActiveDirectory/Test-GetADDomainController.ps1 @@ -10,7 +10,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WORKGROUP' ) +if( (Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'}).Domain -eq 'WORKGROUP' ) { Write-Warning -Message ('Get-ADDomainController tests can''t run because this computer is not part of a domain.') } diff --git a/Test/Add-GroupMember.Tests.ps1 b/Test/Add-GroupMember.Tests.ps1 index 3e3287d5..e877af0a 100644 --- a/Test/Add-GroupMember.Tests.ps1 +++ b/Test/Add-GroupMember.Tests.ps1 @@ -96,7 +96,7 @@ Describe 'Add-GroupMember' { function Get-LocalUsers { - return Get-Cim -Class 'Win32_UserAccount' -Filter "LocalAccount=True" | + return Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_UserAccount'; Filter = "LocalAccount=True"} | Where-Object { $_.Name -ne $env:COMPUTERNAME } } @@ -106,7 +106,7 @@ Describe 'Add-GroupMember' { Assert-MembersInGroup -Member $Members } - if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -eq 'WBMD' ) + if( (Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'}).Domain -eq 'WBMD' ) { It 'should add member from domain' { Invoke-AddMembersToGroup -Members 'WBMD\WHS - Lifecycle Services' diff --git a/Test/CarbonDscTest/CarbonDscTest.psm1 b/Test/CarbonDscTest/CarbonDscTest.psm1 index 987b61c6..32a3b54b 100644 --- a/Test/CarbonDscTest/CarbonDscTest.psm1 +++ b/Test/CarbonDscTest/CarbonDscTest.psm1 @@ -38,7 +38,9 @@ function Start-CarbonDscTestFixture { if( -not (Get-Module -Name 'PSDesiredStateConfiguration' -ListAvailable | Where-Object Version -ge ([Version]'2.0.0')) ) { - Install-Module -Name PSDesiredStateConfiguration -Repository PSGallery -MaximumVersion 2.99 -Force + Find-Module -Name 'PSDesiredStateConfiguration' -MinimumVersion '2.0' -MaximumVersion '2.99' | + Select-Object -First 1 | + Install-Module -Force } Import-Module -Name 'PSDesiredStateConfiguration' -Global } diff --git a/Test/CarbonTest.psm1 b/Test/CarbonTest.psm1 new file mode 100644 index 00000000..7b193a70 --- /dev/null +++ b/Test/CarbonTest.psm1 @@ -0,0 +1,32 @@ +function Invoke-CPrivateCommand +{ + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [String] $Name, + + [hashtable] $Parameter = @{} + ) + + $Global:CTName = $Name + $Global:CTParameter = $Parameter + + if( $VerbosePreference -eq 'Continue' ) + { + $Parameter['Verbose'] = $true + } + + $Parameter['ErrorAction'] = $ErrorActionPreference + + try + { + InModuleScope 'Carbon' { + & $CTName @CTParameter + } + } + finally + { + Remove-Variable -Name 'CTParameter' -Scope 'Global' + Remove-Variable -Name 'CTName' -Scope 'Global' + } +} \ No newline at end of file diff --git a/Test/Get-ServiceConfiguration.Tests.ps1 b/Test/Get-ServiceConfiguration.Tests.ps1 index 2bc41ccd..0e83606b 100644 --- a/Test/Get-ServiceConfiguration.Tests.ps1 +++ b/Test/Get-ServiceConfiguration.Tests.ps1 @@ -23,9 +23,18 @@ Describe 'Get-ServiceConfiguration' { Get-Service | # Skip Carbon services. They could get uninstalled at any moment. Where-Object { $_.Name -notlike 'Carbon*' } | - Get-ServiceConfiguration | + Get-CServiceConfiguration -ErrorAction 'SilentlyContinue' | Format-List -Property * - $Global:Error.Count | Should -Be 0 + + # ComputerName parameter does not exists under PowerShell Core. + if( Get-Command -Name 'Get-Service' -ParameterName 'ComputerName' -ErrorAction Ignore ) + { + $Global:Error.Count | Should -Be 0 + } + else + { + $Global:Error[0] | Should -Match 'this version of PowerShell doesn''t support services on remote computers.' + } } It 'should write an error if the service doesn''t exist' { diff --git a/Test/Grant-Permission.Tests.ps1 b/Test/Grant-Permission.Tests.ps1 index a9ba6565..3f0a30f9 100644 --- a/Test/Grant-Permission.Tests.ps1 +++ b/Test/Grant-Permission.Tests.ps1 @@ -67,7 +67,7 @@ function Assert-Permissions { $providerName = 'CryptoKey' # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( -not (Invoke-CPrivateCommand -Name 'Test-CCryptoKeyAvailable') ) { $providerName = 'FileSystem' } @@ -506,7 +506,7 @@ foreach( $location in @( 'LocalMachine','CurrentUser' ) ) $writePermission = 'GenericWrite' # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead - if( $PSVersionTable.PSEdition -eq 'Core') + if( -not (Invoke-CPrivateCommand -Name 'Test-CCryptoKeyAvailable') ) { $expectedRuleType = 'FileSystem' $readPermission = 'Read' @@ -553,8 +553,8 @@ foreach( $location in @( 'LocalMachine','CurrentUser' ) ) } - # CryptoKey does not exist in .NET standard/core so we will have to use FileSystem instead - if( $PSVersionTable.PSEdition -ne 'Core' ) + # CryptoKey does not exist in .NET standard/core + if( (Invoke-CPrivateCommand -Name 'Test-CCryptoKeyAvailable') ) { Mock -CommandName 'Set-CryptoKeySecurity' -Verifiable -ModuleName 'Carbon' diff --git a/Test/Initialize-CarbonTest.ps1 b/Test/Initialize-CarbonTest.ps1 index c1be31a2..e21e34e9 100644 --- a/Test/Initialize-CarbonTest.ps1 +++ b/Test/Initialize-CarbonTest.ps1 @@ -65,6 +65,12 @@ else } } +if( -not (Get-Module -Name 'CarbonTest') ) +{ + Write-Verbose -Message ('Importing CarbonTest.') -Verbose + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'CarbonTest.psm1') -Force +} + if( $ForDsc ) { Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'CarbonDscTest' -Resolve) -Force diff --git a/Test/Install-Service.Tests.ps1 b/Test/Install-Service.Tests.ps1 index 0d0ae176..e186cc67 100644 --- a/Test/Install-Service.Tests.ps1 +++ b/Test/Install-Service.Tests.ps1 @@ -585,7 +585,7 @@ Describe 'Install-Service' { { Install-Service -Name $serviceName -Path $path @installServiceParams $service = Assert-ServiceInstalled - $svc = Get-Cim -Class 'Win32_Service' -Filter ('Name = "{0}"' -f $serviceName) + $svc = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Service'; Filter = ('Name = "{0}"' -f $serviceName)} $svc.PathName | Should -Be $servicePath } finally diff --git a/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 b/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 index 4971b96f..60b6a259 100644 --- a/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-GetMSMQMessageQueue.ps1 @@ -13,7 +13,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'} | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 b/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 index 9bd9cf02..99d98913 100644 --- a/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-InstallMSMQMessageQueue.ps1 @@ -12,7 +12,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'} | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 b/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 index 3ce1d8d1..c41f0bba 100644 --- a/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-RemoveMSMQMessageQueue.ps1 @@ -11,7 +11,7 @@ # limitations under the License. $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'} | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 b/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 index b9feb774..080f0811 100644 --- a/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 +++ b/Test/MSMQ/Test-TestMSMQMessageQueue.ps1 @@ -13,7 +13,7 @@ # These tests should only run if MSMQ is not installed $userDomain = $env:USERDNSDOMAIN -$computerDomain = Get-Cim -Class 'Win32_ComputerSystem' | Select-Object -ExpandProperty Domain +$computerDomain = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'} | Select-Object -ExpandProperty Domain if( (Get-Service -Name MSMQ -ErrorAction SilentlyContinue) -and $userDomain -eq $computerDomain ) { diff --git a/Test/New-RsaKeyPair.Tests.ps1 b/Test/New-RsaKeyPair.Tests.ps1 index 79924df5..495db984 100644 --- a/Test/New-RsaKeyPair.Tests.ps1 +++ b/Test/New-RsaKeyPair.Tests.ps1 @@ -38,20 +38,14 @@ Describe 'New-RsaKeyPair' { $ValidTo = (Get-Date).AddDays( [Math]::Floor(([DateTime]::MaxValue - [DateTime]::UtcNow).TotalDays) ) } - $keyExchangeAlgorithm = 'RSA-PKCS1-KeyEx' - if( $PSVersionTable.PSEdition -eq 'Core' ) - { - $keyExchangeAlgorithm = 'RSA' - } - - $cert = Get-Certificate -Path $publicKeyPath -NoWarn + $cert = Get-CCertificate -Path $publicKeyPath -NoWarn # Weird date/time stamps in generated certificate that I can't figure out/replicate. So we'll just check that the expected/actual dates are within a day of each other. [timespan]$span = $ValidTo - $cert.NotAfter $span.TotalDays | Should BeGreaterThan (-2) $span.TotalDays | Should BeLessThan 2 $cert.Subject | Should Be $subject $cert.PublicKey.Key.KeySize | Should Be $Length - $cert.PublicKey.Key.KeyExchangeAlgorithm | Should Be $keyExchangeAlgorithm + $cert.PublicKey.Key.KeyExchangeAlgorithm | Should -BeLike 'RSA*' $cert.SignatureAlgorithm.FriendlyName | Should Be $Algorithm $keyUsage = $cert.Extensions | Where-Object { $_ -is [Security.Cryptography.X509Certificates.X509KeyUsageExtension] } $keyUsage | Should Not BeNullOrEmpty @@ -61,7 +55,7 @@ Describe 'New-RsaKeyPair' { $enhancedKeyUsage | Should Not BeNullOrEmpty # I don't think Windows 2008 supports Enhanced Key Usages. - $osVersion = (Get-Cim -Class 'Win32_OperatingSystem').Version + $osVersion = (Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_OperatingSystem'}).Version if( $osVersion -notmatch '6.1\b' ) { $usage = $enhancedKeyUsage.EnhancedKeyUsages | Where-Object { $_.FriendlyName -eq 'Document Encryption' } @@ -102,7 +96,7 @@ Describe 'New-RsaKeyPair' { $decryptedSecret = Unprotect-String -ProtectedString $protectedSecret -PrivateKeyPath $privateKeyPath -Password $privateKeyPassword $decryptedSecret | Should Be $secret - $publicKey = Get-Certificate -Path $publicKeyPath -NoWarn + $publicKey = Get-CCertificate -Path $publicKeyPath -NoWarn $publicKey | Should Not BeNullOrEmpty # Make sure it works with DSC @@ -196,7 +190,7 @@ Describe 'New-RsaKeyPair' { $output = New-RsaKeyPair -Subject $subject -PublicKeyFile $publicKeyPath -PrivateKeyFile $privateKeyPath -Password $null $output.Count | Should Be 2 - $privateKey = Get-Certificate -Path $privateKeyPath -NoWarn + $privateKey = Get-CCertificate -Path $privateKeyPath -NoWarn $privateKey | Should Not BeNullOrEmpty $secret = [IO.Path]::GetRandomFileName() diff --git a/Test/Share/Test-GetFileShare.ps1 b/Test/Share/Test-GetFileShare.ps1 index a26c484f..9818f669 100644 --- a/Test/Share/Test-GetFileShare.ps1 +++ b/Test/Share/Test-GetFileShare.ps1 @@ -23,7 +23,7 @@ function Start-TestFixture function Stop-TestFixture { - $share = Get-Cim -Class 'Win32_Share' -Filter "Name='$shareName'" + $share = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Share'; Filter = "Name='$shareName'"} if( $share -ne $null ) { [void] $share.Delete() @@ -47,7 +47,9 @@ function Test-ShouldGetSpecificShare function Test-ShouldGetOnlyFileShares { - $nonFileShares = Get-Cim -Class 'Win32_Share' | Where-Object { $_.Type -ne 0 -and $_.Type -ne 2147483648 } + $nonFileShares = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Share'} | + Where-Object 'Type' -NE 0 | + Where-Object 'Type' -NE 2147483648 if( $nonFileShares ) { foreach( $nonFileShare in $nonFileShares ) diff --git a/Test/Share/Test-InstallFileShare.ps1 b/Test/Share/Test-InstallFileShare.ps1 index 48dba871..63e68e4b 100644 --- a/Test/Share/Test-InstallFileShare.ps1 +++ b/Test/Share/Test-InstallFileShare.ps1 @@ -55,7 +55,7 @@ function Invoke-NewShare($Path = $TestDir, $FullAccess = @(), $ChangeAccess = @( function Get-Share { - return Get-Cim -Class 'Win32_Share' -Filter "Name='$ShareName'" + return Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Share'; Filter = "Name='$ShareName'"} } diff --git a/Test/Share/Test-TestFileShare.ps1 b/Test/Share/Test-TestFileShare.ps1 index 04da56c7..7ef18fbc 100644 --- a/Test/Share/Test-TestFileShare.ps1 +++ b/Test/Share/Test-TestFileShare.ps1 @@ -23,7 +23,7 @@ function Start-TestFixture function Stop-TestFixture { - $share = Get-Cim -Class 'Win32_Share' -Filter "Name='$shareName'" + $share = Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Share'; Filter = "Name='$shareName'"} if( $share -ne $null ) { [void] $share.Delete() diff --git a/Test/System.Diagnostics.Process.types.Tests.ps1 b/Test/System.Diagnostics.Process.types.Tests.ps1 index 172af983..a4f55571 100644 --- a/Test/System.Diagnostics.Process.types.Tests.ps1 +++ b/Test/System.Diagnostics.Process.types.Tests.ps1 @@ -15,7 +15,7 @@ Describe 'System.Diagnostics.Process' { It 'processes have ParentProcessID' { $parents = @{} - Get-Cim -Class 'Win32_Process' | ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } + Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_Process'} | ForEach-Object { $parents[$_.ProcessID] = $_.ParentProcessID } $foundSome = $false Get-Process | Where-Object { $parents.ContainsKey( [UInt32]$_.Id ) -and $_.ParentProcessID } | diff --git a/Test/Test-Identity.Tests.ps1 b/Test/Test-Identity.Tests.ps1 index 184b226a..8cd3384a 100644 --- a/Test/Test-Identity.Tests.ps1 +++ b/Test/Test-Identity.Tests.ps1 @@ -23,7 +23,7 @@ Describe 'Test-Identity' { (Test-Identity -Name $user1.SamAccountName) | Should Be $true } - if( (Get-Cim -Class 'Win32_ComputerSystem').Domain -ne 'WORKGROUP' ) + if( (Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_ComputerSystem'}).Domain -ne 'WORKGROUP' ) { It 'should find domain user' { (Test-Identity -Name ('{0}\Administrator' -f $env:USERDOMAIN)) | Should Be $true diff --git a/Test/Uninstall-FileShare.Tests.ps1 b/Test/Uninstall-FileShare.Tests.ps1 index cd3899f8..4da40dc1 100644 --- a/Test/Uninstall-FileShare.Tests.ps1 +++ b/Test/Uninstall-FileShare.Tests.ps1 @@ -29,7 +29,7 @@ Describe 'Uninstall-FileShare' { AfterEach { Get-FileShare -Name $shareName -ErrorAction Ignore | ForEach-Object { - if( $PSVersionTable.PSEdition -eq 'Core' ) + if( Invoke-CPrivateCommand -Name 'Test-CCimAvailable' ) { Invoke-CimMethod -InputObject $_ -MethodName 'Delete' } diff --git a/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 b/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 index e8551611..50e1b2fb 100644 --- a/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 +++ b/Test/UsersAndGroups/Test-GetWmiLocalUserAccount.ps1 @@ -17,7 +17,7 @@ function Start-TestFixture function Test-ShouldGetUser { - Get-Cim -Class 'Win32_UserAccount' -Filter "Domain='$($env:ComputerName)'" | ForEach-Object { + Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Class = 'Win32_UserAccount'; Filter = "Domain='$($env:ComputerName)'"} | ForEach-Object { $user = Get-WmiLocalUserAccount -Username $_.Name Assert-NotNull $user Assert-Equal $_.Name $user.Name diff --git a/Test/UsersAndGroups/Test-TestUser.ps1 b/Test/UsersAndGroups/Test-TestUser.ps1 index 3c52da3e..0d20f647 100644 --- a/Test/UsersAndGroups/Test-TestUser.ps1 +++ b/Test/UsersAndGroups/Test-TestUser.ps1 @@ -17,7 +17,7 @@ function Start-TestFixture function Test-ShouldCheckIfLocalAccountExists { - $localUserAccounts = @(Get-Cim -Query "select * from win32_useraccount where Domain='$($env:ComputerName)'" -Computer .) + $localUserAccounts = @(Invoke-CPrivateCommand -Name 'Get-CCimInstance' -Parameter @{Query = "select * from win32_useraccount where Domain='$($env:ComputerName)'"; Computer = '.'}) Assert-True (0 -lt $localUserAccounts.Length) foreach( $localUserAccount in $localUserAccounts ) { diff --git a/appveyor.yml b/appveyor.yml index 48f824a3..c1e69172 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -73,13 +73,11 @@ for: only: - job_group: ps build_script: - - ps: | - .\build.ps1 + - ps: .\build.ps1 # Build in PowerShell - matrix: only: - job_group: pwsh build_script: - - pwsh: | - ./build.ps1 + - pwsh: ./build.ps1 From 462c34ce72a7e89736b269f5ff693359d6eb2aa6 Mon Sep 17 00:00:00 2001 From: "Ky, Khoi" Date: Thu, 4 Aug 2022 13:36:12 -0700 Subject: [PATCH 18/20] Updating changelog. Removing uneeded lines from Initialize-Server. --- CHANGELOG.md | 6 +++--- Carbon/Functions/Test-CCimAvailable.ps1 | 3 +-- Initialize-Server.ps1 | 15 +-------------- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3daa4882..eda42b85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,9 @@ ## Added suport for PowerShell Core -* Added: `Get-CCimInstance` function that determines which method to call when accessing a computer's Common Information Model based on the version of PowerShell being used. `Get-CCimInstance` will call `Get-CimInstance` under PowerShell Core and `Get-WmiObject` under Windows PowerShell. `Get-WmiObject` has been deprecated under PowerShell Core. -* Fixed: Carbon will now use version 2 of the `PSDesiredStateConfiguration` module when running under PowerShell Core as verion 1 was incompatible. -* Fixed: Granting permissions on a certificate will use type `Security.AccessControl.FileSystemRights` as `Security.AccessControl.CryptoKeyRights` has been deprecated under PowerShell Core. +* Carbon now works under PowerShell 7. +* Fixed: Get-CPermission fails to grant permissions on certificates in PowerShell 6+ and on certificates that .NET Framework load as RSA cryptographic next generation keys, which don't have an API for setting private key permissions. + # 2.11.3 diff --git a/Carbon/Functions/Test-CCimAvailable.ps1 b/Carbon/Functions/Test-CCimAvailable.ps1 index 3a8889f6..f9bbce80 100644 --- a/Carbon/Functions/Test-CCimAvailable.ps1 +++ b/Carbon/Functions/Test-CCimAvailable.ps1 @@ -1,5 +1,4 @@ function Test-CCimAvailable { - # Windows PowerShell comes with CimCmdlets version 1.0.0 and PowerShell Core comes with CimCmdlets version > 7.0.0 - return (Get-Command -Name 'Get-CimInstance' -ErrorAction Ignore).Version.Major -ge 7 + return ($null -ne (Get-Command -Name 'Get-CimInstance' -ErrorAction Ignore)) } \ No newline at end of file diff --git a/Initialize-Server.ps1 b/Initialize-Server.ps1 index 5900caf5..ba3da139 100644 --- a/Initialize-Server.ps1 +++ b/Initialize-Server.ps1 @@ -23,20 +23,7 @@ Set-StrictMode -Version 'Latest' $PSCommandPath = $MyInvocation.MyCommand.Definition $PSScriptRoot = Split-Path -Parent -Path $PSCommandPath -$os = Get-CCimInstance -Class 'Win32_OperatingSystem' - -# Windows 2008 -$osVersion = [version]$os.Version -if( $osVersion.Major -eq 6 -and $osVersion.Minor -eq 1 ) -{ - Import-Module -Name 'ServerManager' - Add-WindowsFeature -Name 'PowerShell-ISE','MSMQ-Server','Net-Framework-Core','Web-Server' -} -# Windows 2012 R2 -elseif( $osVersion.Major -eq 6 -and $osVersion.Minor -eq 3 ) -{ - Install-WindowsFeature -Name 'Web-Server','MSMQ-Server','Web-Scripting-Tools' -} +Install-WindowsFeature -Name 'Web-Server','MSMQ-Server','Web-Scripting-Tools' choco install 'sysinternals' -y choco install 'conemu' -y From ea0ed651e587b79062ebaeb4fced33463bc46d70 Mon Sep 17 00:00:00 2001 From: "Ky, Khoi" Date: Fri, 5 Aug 2022 08:57:31 -0700 Subject: [PATCH 19/20] Adding Set-StrictMode an Use-CallerPreference to Get-CCimClass and Get-CCiminstance functions. --- Carbon/Functions/Get-CCimClass.ps1 | 3 +++ Carbon/Functions/Get-CCimInstance.ps1 | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/Carbon/Functions/Get-CCimClass.ps1 b/Carbon/Functions/Get-CCimClass.ps1 index 48d5c2e6..4e7880d2 100644 --- a/Carbon/Functions/Get-CCimClass.ps1 +++ b/Carbon/Functions/Get-CCimClass.ps1 @@ -19,6 +19,9 @@ function Get-CCimClass [String] $Class ) + Set-StrictMode -Version 'Latest' + Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState + $useCim = Test-CCimAvailable if( $useCim ) diff --git a/Carbon/Functions/Get-CCimInstance.ps1 b/Carbon/Functions/Get-CCimInstance.ps1 index bcd0b67f..aa2a6659 100644 --- a/Carbon/Functions/Get-CCimInstance.ps1 +++ b/Carbon/Functions/Get-CCimInstance.ps1 @@ -23,6 +23,10 @@ function Get-CCimInstance [String] $Query ) + + Set-StrictMode -Version 'Latest' + Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState + $useCim = Test-CCimAvailable $optionalArgs = @{ } From 767ef5b203ae68675a93aadb14b5dfe0d2f9d546 Mon Sep 17 00:00:00 2001 From: "Ky, Khoi" Date: Fri, 5 Aug 2022 15:25:13 -0700 Subject: [PATCH 20/20] Updating changelog remarks for version 2.12.0. --- CHANGELOG.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4f379ce..a6b87315 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,16 +4,11 @@ module, now available on the PowerShell Gallery. Please switch to the new module and update usages. If you use these functions from Carbon, a warning message will be written. These function will be removed in the next major version of Carbon. - - -# 2.12.0 - -## Added suport for PowerShell Core - * Carbon now works under PowerShell 7. -* Fixed: Get-CPermission fails to grant permissions on certificates in PowerShell 6+ and on certificates that .NET Framework load as RSA cryptographic next generation keys, which don't have an API for setting private key permissions. +* Fixed: Get-CPermission fails to grant permissions on certificates in PowerShell 6+ and on certificates that .NET +Framework load as RSA cryptographic next generation keys, which don't have an API for setting private key permissions. + - # 2.11.3 * Fixed: Carbon doesn't load Microsoft.Web.Administration assembly on PowerShell 7+.