Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
HelpersCommon.psm1625 linesDownload Raw Back to HelpersCommon
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3function Wait-UntilTrue4{5    [CmdletBinding()]6    param (7        [ScriptBlock]$sb,8        [int]$TimeoutInMilliseconds = 10000,9        [int]$IntervalInMilliseconds = 100010        )11    # Get the current time12    $startTime = [DateTime]::Now13 14    # Loop until the script block evaluates to true15    while (-not ($sb.Invoke())) {16        # If the timeout period has passed, return false17        if (([DateTime]::Now - $startTime).TotalMilliseconds -gt $timeoutInMilliseconds) {18            return $false19        }20        # Wait21        Start-Sleep -Milliseconds $intervalInMilliseconds > $null22    }23    return $true24}25 26function Wait-FileToBePresent27{28    [CmdletBinding()]29    param (30        [string]$File,31        [int]$TimeoutInSeconds = 10,32        [int]$IntervalInMilliseconds = 10033    )34 35    return Wait-UntilTrue -sb { Test-Path $File } -TimeoutInMilliseconds ($TimeoutInSeconds*1000) -IntervalInMilliseconds $IntervalInMilliseconds36}37 38function Test-IsElevated39{40    $IsElevated = $false41    if ( $IsWindows ) {42        # on Windows we can determine whether we're executing in an43        # elevated context44        $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()45        $windowsPrincipal = New-Object 'Security.Principal.WindowsPrincipal' $identity46        if ($windowsPrincipal.IsInRole("Administrators") -eq 1)47        {48            $IsElevated = $true49        }50    }51    else {52        # on Linux, tests run via sudo will generally report "root" for whoami53        if ( (whoami) -match "root" ) {54            $IsElevated = $true55        }56    }57    return $IsElevated58}59function Get-RandomFileName60{61    [System.IO.Path]::GetFileNameWithoutExtension([IO.Path]::GetRandomFileName())62}63 64#65# Testhook setting functions66# note these manipulate private data in the PowerShell engine which will67# enable us to not actually alter the system or mock returned data68#69$SCRIPT:TesthookType = [system.management.automation.internal.internaltesthooks]70function Test-TesthookIsSet71{72    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingEmptyCatchBlock", '')] # , Justification = "an error message is not appropriate for this function")]73    param (74        [ValidateNotNullOrEmpty()]75        [Parameter(Mandatory=$true)]76        $testhookName77    )78    try {79        return ${Script:TesthookType}.GetField($testhookName, "NonPublic,Static").GetValue($null)80    }81    catch {82        # fall through83    }84    return $false85}86 87function Enable-Testhook88{89    param (90        [ValidateNotNullOrEmpty()]91        [Parameter(Mandatory=$true)]92        $testhookName93    )94    ${Script:TesthookType}::SetTestHook($testhookName, $true)95}96 97function Disable-Testhook98{99    param (100        [ValidateNotNullOrEmpty()]101        [Parameter(Mandatory=$true)]102        $testhookName103    )104    ${Script:TesthookType}::SetTestHook($testhookName, $false)105}106 107function Set-TesthookResult108{109    param (110        [ValidateNotNullOrEmpty()]111        [Parameter(Mandatory=$true)]112        $testhookName,113        [ValidateNotNullOrEmpty()]114        [Parameter(Mandatory=$true)]115        $value116    )117    ${Script:TesthookType}::SetTestHook($testhookName, $value)118}119 120function Add-TestDynamicType121{122    param()123 124    Add-Type -TypeDefinition @'125using System.Collections.Generic;126using System.Dynamic;127 128public class TestDynamic : DynamicObject129{130    private static readonly string[] s_dynamicMemberNames = new string[] { "FooProp", "BarProp", "FooMethod", "SerialNumber" };131 132    private static int s_lastSerialNumber;133 134    private readonly int _serialNumber;135 136    public TestDynamic()137    {138        _serialNumber = ++s_lastSerialNumber;139    }140 141    public override IEnumerable<string> GetDynamicMemberNames()142    {143        return s_dynamicMemberNames;144    }145 146    public override bool TryGetMember(GetMemberBinder binder, out object result)147    {148        result = null;149 150        if (binder.Name == "FooProp")151        {152            result = 123;153            return true;154        }155        else if (binder.Name == "BarProp")156        {157            result = 456;158            return true;159        }160        else if (binder.Name == "SerialNumber")161        {162            result = _serialNumber;163            return true;164        }165        else if (binder.Name == "HiddenProp")166        {167            // Not presented in GetDynamicMemberNames168            result = 789;169            return true;170        }171 172        return false;173    }174 175    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)176    {177        result = null;178 179        if (binder.Name == "FooMethod")180        {181            result = "yes";182            return true;183        }184        else if (binder.Name == "HiddenMethod")185        {186            // Not presented in GetDynamicMemberNames187            result = _serialNumber;188            return true;189        }190 191        return false;192    }193}194'@195}196 197# Upload an artifact in VSTS198# On other systems will just log where the file was placed199function Send-VstsLogFile {200    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = "needed for VSO")]201    param (202        [parameter(Mandatory,ParameterSetName='contents')]203        [string[]]204        $Contents,205        [parameter(Mandatory,ParameterSetName='contents')]206        [string]207        $LogName,208        [parameter(Mandatory,ParameterSetName='path')]209        [ValidateScript({Test-Path -Path $_})]210        [string]211        $Path212    )213 214    $logFolder = Join-Path -Path $PWD -ChildPath 'logfile'215    if(!(Test-Path -Path $logFolder))216    {217        $null = New-Item -Path $logFolder -ItemType Directory218        if($IsMacOS -or $IsLinux)219        {220            $null = chmod a+rw $logFolder221        }222    }223 224    $newName = ([System.Io.Path]::GetRandomFileName() + "-$LogName.txt")225    if($Contents)226    {227        $logFile = Join-Path -Path $logFolder -ChildPath $newName228 229        $Contents | Out-File -path $logFile -Encoding ascii230    }231    else232    {233        $logFile = Join-Path -Path $logFolder -ChildPath $newName234        Copy-Item -Path $Path -Destination $logFile235    }236 237    Write-Host "##vso[artifact.upload containerfolder=$newName;artifactname=$newName]$logFile"238    Write-Verbose "Log file captured as $newName" -Verbose239}240 241# Tests if the Linux or macOS user is root242function Test-IsRoot243{244    if($IsLinux -or $IsMacOS)245    {246        $uid = &id -u247        if($uid -eq 0)248        {249            return $true250        }251    }252 253    return $false254}255 256# Tests if we are running is a VSTS Linux Build257function Test-IsVstsLinux258{259    return ($env:TF_BUILD -and $IsLinux)260}261 262# Tests if we are running is a VSTS Linux Build263function Test-IsVstsWindows264{265    return ($env:TF_BUILD -and $IsWindows)266}267 268# this function wraps native command Execution269# for more information, read https://mnaoumov.wordpress.com/2015/01/11/execution-of-external-commands-in-powershell-done-right/270function Start-NativeExecution271{272    param(273        [scriptblock]$sb,274        [switch]$IgnoreExitcode,275        [switch]$VerboseOutputOnError276    )277    $backupEAP = $script:ErrorActionPreference278    $script:ErrorActionPreference = "Continue"279    try {280        if($VerboseOutputOnError.IsPresent)281        {282            $output = & $sb 2>&1283        }284        else285        {286            & $sb287        }288 289        # note, if $sb doesn't have a native invocation, $LASTEXITCODE will290        # point to the obsolete value291        if ($LASTEXITCODE -ne 0 -and -not $IgnoreExitcode) {292            if($VerboseOutputOnError.IsPresent -and $output)293            {294                $output | Out-String | Write-Verbose -Verbose295            }296 297            # Get caller location for easier debugging298            $caller = Get-PSCallStack -ErrorAction SilentlyContinue299            if($caller)300            {301                $callerLocationParts = $caller[1].Location -split ":\s*line\s*"302                $callerFile = $callerLocationParts[0]303                $callerLine = $callerLocationParts[1]304 305                $errorMessage = "Execution of {$sb} by ${callerFile}: line $callerLine failed with exit code $LASTEXITCODE"306                throw $errorMessage307            }308            throw "Execution of {$sb} failed with exit code $LASTEXITCODE"309        }310    } finally {311        $script:ErrorActionPreference = $backupEAP312    }313}314 315# Creates a new random hex string for use with things like test certificate passwords316function New-RandomHexString317{318    param([int]$Length = 10)319 320    $random = [Random]::new()321    return ((1..$Length).ForEach{ '{0:x}' -f $random.Next(0xf) }) -join ''322}323 324$script:CanWriteToPsHome = $null325function Test-CanWriteToPsHome326{327    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '', Justification = "an error message is not appropriate for this function")]328    param ()329    if ($null -ne $script:CanWriteToPsHome) {330        return $script:CanWriteToPsHome331    }332 333    $script:CanWriteToPsHome = $false334 335    try {336        $testFileName = Join-Path $PSHOME (New-Guid).Guid337        $null = New-Item -ItemType File -Path $testFileName -ErrorAction Stop338        $script:CanWriteToPsHome = $true339        Remove-Item -Path $testFileName -ErrorAction SilentlyContinue340    }341    catch {342        ; # do nothing343    }344 345    $script:CanWriteToPsHome346}347 348# Creates a password meeting Windows complexity rules349function New-ComplexPassword350{351    $numbers = "0123456789"352    $lowercase = "abcdefghijklmnopqrstuvwxyz"353    $uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"354    $symbols = "~!@#$%^&*_-+=``|\(){}[]:;`"'<>,.?/"355    $password = [string]::Empty356    # Windows password complexity rule requires minimum 8 characters and using at least 3 of the357    # buckets above, so we just pick one from each bucket twice.358    # https://learn.microsoft.com/windows/security/threat-protection/security-policy-settings/password-must-meet-complexity-requirements359    1..2 | ForEach-Object {360        $Password += $numbers[(Get-Random $numbers.Length)] + $lowercase[(Get-Random $lowercase.Length)] +361            $uppercase[(Get-Random $uppercase.Length)] + $symbols[(Get-Random $symbols.Length)]362    }363 364    $password365}366 367# return a specific string with regard to platform information368function Get-PlatformInfo {369    if ( $IsWindows ) {370        return @{Platform = "windows"; Version = '' }371    }372    if ( $IsMacOS ) {373        return @{Platform = "macos"; Version = sw_vers -productversion }374    }375    if ( $IsLinux ) {376        $osrelease = Get-Content /etc/os-release | ConvertFrom-StringData377        if ( -not [string]::IsNullOrEmpty($osrelease.ID) ) {378 379            $versionId = if (-not $osrelease.Version_ID ) {380                ''381            } else {382                $osrelease.Version_ID.trim('"')383            }384 385            $platform = $osrelease.ID.trim('"')386 387            return @{Platform = $platform; Version = $versionId }388        }389        return @{ Platform = "linux"; version = "unknown" }390    }391}392 393# return true if WsMan is supported on the current platform394function Get-WsManSupport {395    $platformInfo = Get-PlatformInfo396    if (397        ($platformInfo.Platform -eq 'centos' -and $platformInfo.Version -eq '7')398    ) {399        return $true400    }401    return $false402}403 404function Test-IsWindowsArm64 {405    return $IsWindows -and [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64406}407 408function Test-IsWinWow64 {409    return $IsWindows -and [System.Environment]::Is64BitOperatingSystem -and -not [System.Environment]::Is64BitProcess410}411 412function Test-IsPreview413{414    param(415        [parameter(Mandatory)]416        [string]417        $Version,418 419        [switch]$IsLTS420    )421 422    if ($IsLTS.IsPresent) {423        ## If we are building a LTS package, then never consider it preview.424        return $false425    }426 427    return $Version -like '*-*'428}429 430<#431    .Synopsis432        Tests if a version is a Release Candidate433    .EXAMPLE434        Test-IsReleaseCandidate -version '6.1.0-sometthing' # returns false435        Test-IsReleaseCandidate -version '6.1.0-rc.1' # returns true436        Test-IsReleaseCandidate -version '6.1.0' # returns false437#>438function Test-IsReleaseCandidate439{440    param(441        [parameter(Mandatory)]442        [string]443        $Version444    )445 446    if ($Version -like '*-rc.*')447    {448        return $true449    }450 451    return $false452}453 454function Test-IsWinServer2012R2455{456    if (-not $IsWindows) {457        return $false458    }459 460    $osInfo = [System.Environment]::OSVersion.Version461    return ($osInfo.Major -eq 6 -and $osInfo.Minor -eq 3)462}463 464function Test-IsWindows2016 {465    if (-not $IsWindows) {466        return $false467    }468 469    $osInfo = [System.Environment]::OSVersion.Version470    return ($osInfo.Major -eq 10 -and $osInfo.Minor -eq 0 -and $osInfo.Build -eq 14393)471}472 473 474# helpers for managing psdefaultparametervalues475[system.collections.generic.Stack[hashtable]]$script:DefaultParameterValueStack = [system.collections.generic.Stack[hashtable]]::new()476 477# Ensure that the global:PSDefaultParameterValues variable is a hashtable478function Initialize-PSDefaultParameterValue {479    if ( $global:PSDefaultParameterValues -isnot [hashtable] ) {480        $global:PSDefaultParameterValues = @{}481    }482}483 484# reset the stack485function Reset-DefaultParameterValueStack {486    $script:DefaultParameterValueStack = [system.collections.generic.Stack[hashtable]]::new()487    Initialize-PSDefaultParameterValue488}489 490# return the current stack491function Get-DefaultParameterValueStack {492    $script:DefaultParameterValueStack493}494 495# PSDefaultParameterValue may not have both skip and pending keys496function Test-PSDefaultParameterValue {497    if ( $global:PSDefaultParameterValues -is [hashtable] ) {498        if ( $global:PSDefaultParameterValues.ContainsKey('skip') -and $global:PSDefaultParameterValues.ContainsKey('pending') ) {499            return $false500        }501        return $true502    }503    Initialize-PSDefaultParameterValue504}505 506# push a new value onto the stack507# if $ht is null, then the current value of $global:PSDefaultParameterValues is pushed508# if $NewValue is used, then $ht is used as the new value of $global:PSDefaultParameterValues509function Push-DefaultParameterValueStack {510    param ([hashtable]$ht, [switch]$NewValue)511    Initialize-PSDefaultParameterValue512 513    $script:DefaultParameterValueStack.Push($global:PSDefaultParameterValues.Clone())514    if ( $ht ) {515        if ( $NewValue ) {516            $global:PSDefaultParameterValues = $ht517        }518        else {519            foreach ($k in $ht.Keys) {520                $global:PSDefaultParameterValues[$k] = $ht[$k]521            }522        }523        if ( ! (Test-PSDefaultParameterValue)) {524            Write-Warning -Message "PSDefaultParameterValues may not have both skip and pending keys, resetting."525            Pop-DefaultParameterValueStack526        }527    }528}529 530function Pop-DefaultParameterValueStack {531    try {532        $global:PSDefaultParameterValues = $script:DefaultParameterValueStack.Pop()533        return $true534    }535    catch {536        Initialize-PSDefaultParameterValue537        return $false538    }539}540 541function Get-HelpNetworkTestCases542{543    param(544        [switch]545        $PositiveCases546    )547    # .NET doesn't consider these path rooted and we won't go to the network:548    # \\?549    # \\.550    # \??551 552    # Command discovery does not follow symlinks to network locations for module qualified paths553    $networkBlockedError = "CommandNameNotAllowed,Microsoft.PowerShell.Commands.GetHelpCommand"554    # This error may change as long as no test cases start failing for other reasons555    $scriptBlockedError = "CommandNotFoundException"556 557    $formats = @(558        '//{0}/share/{1}'559        '\\{0}\share\{1}'560        '//{0}\share/{1}'561        'Microsoft.PowerShell.Core\filesystem:://{0}/share/{1}'562    )563 564    if (!$PositiveCases) {565        $formats += 'filesystem:://{0}/share/{1}'566    }567 568    $moduleQualifiedCommand = 'test.dll\fakecommand'569    $lanManFormat = @(570        '//;LanmanRedirector/{0}/share/{1}'571    )572 573    $hosts = @(574        'fakehost'575        'fakehost.pstest'576    )577 578    $commands = @(579        'test.ps1'580        'test.dll'581        $moduleQualifiedCommand582    )583 584    $variants = @()585    $cases = @()586    foreach($command in $commands)  {587        $hostName = $hosts[0]588        $format = $formats[0]589        $cases += @{590            Command = $format -f $hostName, $command591            ExpectedError = $networkBlockedError592        }593    }594 595    foreach($hostName in $hosts) {596        # chose the format with backslashes(\) to match the host with blackslashes597        $format = $formats[1]598        $command = $commands[0]599        $cases += @{600            Command = $format -f $hostName, $command601            ExpectedError = $networkBlockedError602        }603    }604    foreach($format in $formats) {605        $hostName = $hosts[0]606        $command = $commands[0]607        $cases += @{608            Command = $format -f $hostName, $command609            ExpectedError = $networkBlockedError610        }611    }612 613    foreach($format in $lanManFormat) {614        $hostName = $hosts[0]615        $command = $moduleQualifiedCommand616        $cases += @{617            Command = $format -f $hostName, $command618            ExpectedError = $scriptBlockedError619        }620    }621 622    return $cases | Sort-Object -Property ExpectedError, Command -Unique623}624 625