LARSINUS.psm1


function Add-Prefix {
      <#
            .SYNOPSIS
            Adds a line prefix
            .PARAMETER Color
            .PARAMETER InfoType
            .DESCRIPTION
            It will add a prefix that you can use in front of your Write-Host.
            The output is a square brackets with some text (of your choice) between in a color (of your choice)
            .EXAMPLE
            Add-Prefix -Color Red -InfoType Error
            [ERROR]
            .EXAMPLE
            Add-Prefix -Color Magenta -InfoType Information ; Write-Host 'Hello World!'
            [INFORMATION] Hello World!
      #>

      param (
            [Parameter()]
            #[validateset('Black','DarkBlue','DarkGreen','DarkCyan','DarkRed','DarkMagenta','DarkYellow','Gray','DarkGray','Blue','Green','Cyan','Red','Magenta','Yellow','White')]
            [ConsoleColor]$Color,
            [Parameter()]
            [string]$InfoType
      )

      Write-Host '[' -NoNewline
      Write-Host -ForegroundColor $color ($infoType).ToUpper() -NoNewline
      Write-Host '] ' -noNewline
}

function Add-Space () {
      <#
            .SYNOPSIS
            Adds spaces after previous text block based on that length.
            .PARAMETER TextLength
            .PARAMETER MaxSpace
            .DESCRIPTION
            Used to make sure your columns are aligned correctly when doing Write-Host and the previous text block had different length.
            This will calculate how much space should be added at the end of the previous text block.
            .EXAMPLE
            Add-Space -TextLength $String.Length -MaxSpace 25
      #>

      param (
            [Parameter (Mandatory = $true)]
            [int]$TextLength,
            [Parameter (Mandatory = $True)]
            [int]$MaxSpace
      )

      $SpaceToAdd = ($MaxSpace - $TextLength)

      While ($SpaceToAdd -gt 0) {
            $Space = $Space + ' '
            $SpaceToAdd--
      }
      Write-Host $Space -NoNewline
}

function Open-File {
      <#
            .SYNOPSIS
            Gets a file.
            .PARAMETER Path
            .DESCRIPTION
            Opens the Windows Explorer so you can browse to a file to be used in your script.
            Can be used together with other functions/cmdlets
            .EXAMPLE
            Open-File
            Opens Windows Explorer in the current directory you're in.
            .EXAMPLE
            Open-File -Path C:\Users\User1\OneDrive\MyScripts
            .EXAMPLE
            $information = Get-Content (Open-File -Path "C:fso") | ConvertFrom-Json
      #>

      param (
            [parameter()]
            $Path = 'C:fso'
      )

      [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”)
      Out-Null
      $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
      $OpenFileDialog.initialDirectory = $Path
      $OpenFileDialog.filter = “All files (*.*)| *.*”
      $OpenFileDialog.ShowDialog() | Out-Null
      $OpenFileDialog.filename
}

function Save-File {
      <#
            .SYNOPSIS
            Saves a file.
            .PARAMETER Path
            .PARAMETER FileDialogFileType
            .DESCRIPTION
            Opens the Windows Explorer so you can browse to where you want to save the file.
            Use the parameter -FileDialogFileType to specify which file type you want the user to be able to save as.
            .EXAMPLE
            Save-File -FileDialogFileType *.*
            Opens Windows Explorer in the current directory you're in.
            .EXAMPLE
            Save-File -Path C:\Users\User1\OneDrive\Scripts\Logs -FileDialogFileType *.log
      #>

      param (
            [parameter()]
            $Path = 'C:fso',
            [Parameter(Mandatory = $true)]
            [String]$FileDialogFileType
      )

      [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”)
      Out-Null
      $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
      $SaveFileDialog.initialDirectory = $Path
      $SaveFileDialog.filter = “All files ($FileDialogFileType )| $FileDialogFileType ”
      $result = $SaveFileDialog.ShowDialog()

      if ($result -eq 'OK') {
            Out-File -FilePath $SaveFileDialog.filename -InputObject $arrCollections
      }
}

function Enable-Sideloading {
      <#
            .SYNOPSIS
            Enables Sidelaoding of apps
            .DESCRIPTION
            ---[ MUST BE RUN WITH ELEVATED PRIVILEGES ]---
            Enables sideloading of applications in Windows 10.
            Being used to allow installations of custom/LOB .msix packaged apps.
            Since they are not published to the Microsoft Store, we need to enable sideloading.
            They are secured by using certificates.
            .EXAMPLE
            Enable-Sideloading.ps1
      #>


      $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
      $Name1 = "AllowAllTrustedApps"
      $value1 = "1"
      New-ItemProperty -Path $registryPath -Name $name1 -Value $value1 -PropertyType DWORD -Force

      $Name2 = "AllowDevelopmentWithoutDevLicense"
      $value2 = "0"

      New-ItemProperty -Path $registryPath -Name $name2 -Value $value2 -PropertyType DWORD -Force
}

function New-LHGUID {
      <#
            .SYNOPSIS
            Creates a new GUID
            .DESCRIPTION
            Creates one or more GUID's in different color to easier differentiate between them.
            .Parameter Count
            .EXAMPLE
            New-LHGUID
            Writes one new GUID to the screen.
            .EXAMPLE
            New-LHGUID -Count 4
            Writes four new GUID's to the screen.
      #>

      [CmdletBinding()]
      param (
            $Count = 1
      )
  
      for ($i = 0; $i -lt $Count; $i++) {
            $header = "[$($i+1)] "
            $guid = (New-Guid).Guid
            $arrGuids += @("$header $guid")
      }
      return $arrGuids
}

function Set-LogPath {
      <#
            .SYNOPSIS
            Tests if the logging path exists and creates it if not.
            .DESCRIPTION
            Tests if the logging path exists and creates it if not.
            Use parameter -WriteLog if you want to leverage the Write-Log Cmdlet to write to a specific log file.
            If it is not used it will write status messages to the screen.
            .PARAMETER Path
            The directory path to test and create.
            .PARAMETER WriteLog
            Switch parameter to use the Write-Log Cmdlet.
            .EXAMPLE
            Set-LogPath -Path $env:\SystemDrive\MyLogFolder
            .EXAMPLE
            Set-LogPath -Path $env:\SystemDrive\MyLogFolder -WriteLog
            .INPUTS
            [string]
            .OUTPUTS
            [bool]
      #>

      [CmdletBinding()] 
      param (
            [Parameter(Mandatory)][string]$Path,
            [Parameter()][switch]$WriteLog = $false
      )
      try {
            if (!(Test-Path -Path $Path)) {
                  switch ($WriteLog) {
                        $true { Write-Log -Message "[$($MyInvocation.MyCommand)]: Logging directory [$Path] was not found. Attempting to create." }
                        $false { Write-Host "[$($MyInvocation.MyCommand)]: Logging directory [$Path] was not found. Attempting to create." }
                  }
                  
                  $null = New-Item -ItemType Directory -Path $Path -Force -ErrorAction Stop
                  switch ($WriteLog) {
                        $true { Write-Log -Message "[$($MyInvocation.MyCommand)]: Logging directory creation was successful." }
                        $false { Write-Host "[$($MyInvocation.MyCommand)]: Logging directory creation was successful." }
                  }                  
                  return $true
            }
            
            switch ($WriteLog) {
                  $true { Write-Log -Message "[$($MyInvocation.MyCommand)]: Logging directory [$Path] was found. Skipping creation." }
                  $false { Write-Host "[$($MyInvocation.MyCommand)]: Logging directory [$Path] was found. Skipping creation." }
            }    
            return $true
      }
      catch {
            Write-Error -Message "[$($MyInvocation.MyCommand)]: Failure encountered attempting to create logging directory [$Path]. Exception: $($_.Exception.Message)"
            return $false
      }
}

function Write-Log {
      <#
            .SYNOPSIS
            Logs a message.
            .DESCRIPTION
            Logs a message.
            .PARAMETER Message
            The message to log.
            .EXAMPLE
            Write-Log -Message 'log message'
            .INPUTS
            [string]
            .OUTPUTS
            [string]
      #>

      param (
            [Parameter(Mandatory, HelpMessage = 'Text to write to the log.')] [string]$Message
      )
      
      [string]$date = ("[$((Get-Date).ToUniversalTime().ToString('MM/dd/yyyy HH:mm:ss')) UTC]")
      Write-Output "$date $Message"
}

function Remove-LogFiles {
      <#
            .SYNOPSIS
            Remove outdated log files from a specific folder
            .DESCRIPTION
            Removes outdated log files from a specific folder that are older than X days
            .PARAMETER Path
            The path to where the log files are stored ($env:SystemDrive\MyLogs\)
            .PARAMETER Filter
            String to use for the log file name
            .PARAMETER Age
            # of days to retain. Anything older than the specified # of days will be removed
            .PARAMETER WriteLog
            Switch parameter to log what this function does to a file.
            To be used with the Write-Log Cmdlet from the module.
            .EXAMPLE
            Remove-LogFiles -Path $env:SystemDrive\MyLogs -Filter 'sample log' -Age 5
            .EXAMPLE
            Remove-LogFiles -Path "$env:ProgramData\My Log Folder\" -Filter * -Age 7 -WriteLog
            .EXAMPLE
            Remove-LogFiles -Path . -Filter * -Age 0
            Deletes all .log files in the current directory!
      #>

      param (
            [Parameter(Mandatory)][string]$Path,
            [Parameter(Mandatory)][string]$Filter,
            [Parameter(Mandatory)][ValidateRange(0, [int]::MaxValue)][int]$Age,
            [Parameter()][switch] $WriteLog = $false
      )
      
      $counter = 0

      if (!($Path.EndsWith('\'))) {
            $Path = ($Path + '\')
      }

      if ($Filter.EndsWith('.log')) {
            $Filter = $Filter.TrimEnd('.log')
      }
      
      If ((Test-Path $Path) -eq $false) {
            switch ($WriteLog) {
                  $true {
                        Write-Log  -Message "[$($MyInvocation.MyCommand)] ERROR! The specified path [$Path] does not exist!"
                  }
                  $false {
                        Write-Host  -ForegroundColor Red "[$($MyInvocation.MyCommand)] " -NoNewline
                        Write-Host  "ERROR! The specified path [$Path] does not exist!"
                  }
            }
            Exit 1
      }

      $logFiles = Get-ChildItem -Path $Path -Filter "$Filter*.log" -File

      if ($null -eq $logFiles) {
            switch ($WriteLog) {
                  $true {
                        Write-Log -Message "[$($MyInvocation.MyCommand)] No log files found containing the string: $Filter"
                  }
                  $false {
                        Write-Host  -ForegroundColor Yellow "[$($MyInvocation.MyCommand)] " -NoNewline
                        Write-Host "No log files found containing the string: $Filter"
                  }
            }
            Exit 1
      }
      
      foreach ($file in $logFiles) {
            if ($file.CreationTime -lt (get-date).AddDays(-1 * $Age)) {
                  $counter++
                  try {
                        Remove-Item -Path "$Path$($file.name)" -Force -Confirm:$false -ErrorAction Stop

                        switch ($WriteLog) {
                              $true {
                                    Write-Log -Message "[$($MyInvocation.MyCommand)] Removed old log file: $($file.Name)"
                              }
                              $false {
                                    Write-Host  -ForegroundColor Green "[$($MyInvocation.MyCommand)] " -NoNewline
                                    Write-Host "Removed old log file: $($file.Name)"
                              }
                        }
                  }
                  catch {
                        switch ($WriteLog) {
                              $true {
                                    Write-Log -Message "[$($MyInvocation.MyCommand)] Unable to remove old log file $($file.Name). Exception: $($_.Exception.Message)"
                              }
                              $false {
                                    Write-Host  -ForegroundColor Red "[$($MyInvocation.MyCommand)] " -NoNewline
                                    Write-Error -Message "Unable to remove old log file $($file.Name). Exception: $($_.Exception.Message)"
                              }
                        }
                        continue
                  }
            }
      }

      if ($counter -eq 0) {
            switch ($WriteLog) {
                  $true {
                        Write-Log -Message "[$($MyInvocation.MyCommand)] Found $($logFiles.Count) file(s) that cointained the string '$Filter' but was younger than the specified age of $Age day(s)."
                  }
                  $false {
                        Write-Host  -ForegroundColor Yellow "[$($MyInvocation.MyCommand)] " -NoNewline
                        Write-Host "Found $($logFiles.Count) file(s) that cointained the string '$Filter' but was younger than the specified age of $Age day(s)."
                  }
            }
      }
}

function Update-CorrelationIDs {
      <#
            .SYNOPSIS
            Updates all existing GUIDs with new GUIDs
            .DESCRIPTION
            Searches and replaces all "CorrelationId" GUIDs found in the .JSON file with new GUIDs
            .PARAMETER Path
            Specify the path to the .JSON file you want to update
            .EXAMPLE
            Update-CorrelationIDs -Path C:\myJsonRepo\exampleFile.json
      #>


      [CmdletBinding()]
      Param (
            [Parameter(Mandatory = $true, Position = 0)][string]$Path
      )

      if (Test-Path $Path) {
            $json = Get-Content -Path $filePath | ConvertFrom-Json

            foreach ($globalOperation in $json.globalOperations) {
                  $globalOperation.correlationId = $globalOperation.correlationId -replace "\b[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\b", (New-Guid)
            }
            foreach ($testOperation in $json.testOperations) {
                  $testOperation.correlationId = $testOperation.correlationId -replace "\b[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\b", (New-Guid)
            }
            foreach ($firstOperation in $json.firstOperation) {
                  $firstOperation.correlationId = $firstOperation.correlationId -replace "\b[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\b", (New-Guid)
            }
            foreach ($fastOperation in $json.fastOperations) {
                  $fastOperation.correlationId = $fastOperation.correlationId -replace "\b[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\b", (New-Guid)
            }
            foreach ($broadOperation in $json.broadOperations) {
                  $broadOperation.correlationId = $broadOperation.correlationId -replace "\b[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\b", (New-Guid)
            }
            
            $json | ConvertTo-Json -Depth 100 | Set-Content -Path $filePath
      }
      else {
            Write-Host -ForegroundColor Yellow "The file in $Path was not found."
      }
}

Export-ModuleMember -Function Add-Prefix
Export-ModuleMember -Function Add-Space
Export-ModuleMember -Function Open-File
Export-ModuleMember -Function Save-File
Export-ModuleMember -Function Enable-Sideloading
Export-ModuleMember -Function New-LHGUID
Export-ModuleMember -Function Set-LogPath
Export-ModuleMember -Function Write-Log
Export-ModuleMember -Function Remove-LogFiles
Export-ModuleMember -Function Update-CorrelationIDs