diff --git a/Standard PowerShell Modules/Build_CT-PS-Standard.ps1 b/Standard PowerShell Modules/Build_CT-PS-Standard.ps1 new file mode 100644 index 0000000..dff5d77 --- /dev/null +++ b/Standard PowerShell Modules/Build_CT-PS-Standard.ps1 @@ -0,0 +1,58 @@ +md NuGetPublish + +Register-PSRepository -Name Local_Nuget_Feed -SourceLocation "$($PSScriptRoot)\NuGetPublish" -PublishLocation "$($PSScriptRoot)\NuGetPublish" -InstallationPolicy Trusted +#(To Remove: Unregister-PSRepository -Name Local_Nuget_Feed) + +#--- Verift/Show all PS Repository +Get-PSRepository + +$Locations = Get-ChildItem -Directory | Select-Object Name + +$GridArguments = @{ + OutputMode = 'Single' + Title = 'Please select the module folder and click OK' +} + +$ModuleName = $Locations | Out-GridView @GridArguments | foreach { $_.Name } + +cd $ModuleName + +nuget spec CT-PS-Standard -Force + +$ModuleVersion = Read-Host "Please enter module version number" + +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace '1.0.0',$ModuleVersion) | Set-Content -Path ".\$($ModuleName).nuspec" + +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace 'http://project_url_here_or_delete_this_line/','https://dev.azure.com/ct-itops-dev/Standard%20Template%20PS%20Modules') | Set-Content -Path ".\$($ModuleName).nuspec" +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace 'Package description','CT Module') | Set-Content -Path ".\$($ModuleName).nuspec" +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace 'Summary of changes made in this release of the package','$($ModuleName)') | Set-Content -Path ".\$($ModuleName).nuspec" +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace 'Tag1 Tag2','') | Set-Content -Path ".\$($ModuleName).nuspec" +((Get-Content -path ".\$($ModuleName).nuspec" -Raw) -replace '1.0.0',$ModuleVersion) | Set-Content -Path ".\$($ModuleName).nuspec" +nuget pack $ModuleName.nuspec + + +#--- Create and Install your Powershell Module as a NuGet Package ans save into the Nuget Package Repo/Feed +Publish-Module -Path .\$ModuleName -Repository Local_Nuget_Feed -NuGetApiKey 'Pacemaker_Skinning_Gigahertz9' +#(The .nupkg file is created here: c:\nuget\publish) + +#-- List Packages in Repository +nuget list -source "$($PSScriptRoot)\NuGetPublish" + +#-- Delete Package +nuget delete $ModuleName $ModuleVersion -source "$($PSScriptRoot)\NuGetPublish" + +#--- Install your Powershell module from the .nupkg file you just created +#--- In an Elevated Powershell console: +Install-Package $ModuleName + +#-- Check Nuget Package Version After Installation +get-package | where-object {$_.name -match '$($ModuleName)'} + +#--- Test Loading/Calling a Function from your PS Module +#MyFunction + +#--- List all functions in your PSM1 module +#Get-Command -Module MyModuleName + +#--- Verify the correct version of your module and manifest files were installed in the Global Modules Folder here: +#C:\Program Files\WindowsPowerShell\Modules\MyModuleName \ No newline at end of file diff --git a/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psd1 b/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psd1 new file mode 100644 index 0000000..e6e9249 --- /dev/null +++ b/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'CT-PS-Standard' +# +# Generated by: aspencer +# +# Generated on: 25/11/2022 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'CT-PS-Standard.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = '60fe5db8-4b2c-4ba1-b99d-73f11bcf0bc1' + +# Author of this module +Author = 'aspencer@ct.com.au' + +# Company or vendor of this module +CompanyName = 'Centorrino Technologies' + +# Copyright statement for this module +Copyright = '(c) Centorrino Technologies. All rights reserved.' + +# Description of the functionality provided by this module +# Description = '' + +# Minimum version of the PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# ClrVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = '*' + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = '*' + +# Variables to export from this module +VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +FileList = @('./CT-PS-Standard.psd1') + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psm1 b/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psm1 new file mode 100644 index 0000000..b212912 --- /dev/null +++ b/Standard PowerShell Modules/Standard Modules/CT-PS-Standard.psm1 @@ -0,0 +1,239 @@ + + + +trap { + write-host "Terminating error $_" + Write-Host "Script $((Get-ChildItem $MyInvocation.PSCommandPath | Select-Object -Expand Name)) ended at line $(Get-CurrentLineNumber) with exit code $($exiterror)." + Write-Host "Output log : $($Output_log)" + Write-Host "Transcript log : $($Transcript_log)" + Write-Host "API log : $($API_log)" + Write-Host "Install log (if used) : $($Install_log)" + Write-Host "**********************" + Write-Host "" + exit $exiterror +} + +function Initialize-Script { + [CmdletBinding()] + param() + <# + ---- STANDARD SCRIPT BLOCK ---- + This block is standard script settings used across all scripts and enables some consistency. + It sets up some standard variables and starts transcript so any errors are caught and can be viewed. + If installations are taking place via MSIEXEC, it also establishes the log file. + If you are installing more than one installation, make sure you setup multiple Install_Log variables for each installation and name the end of the log file accordingly + It starts transcript to the transcript log file so the history can be accessed anytime in the future + The script then tests for the CT_DEST folder and creates it if its not there. + + This needs to be imported to a script by using the following set of commands: + + -------- + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + if(Test-Path -Path "$($PSScriptRoot)\CT-PS-Standard.psm1" -PathType Leaf ) { Remove-Item "$($PSScriptRoot)\CT-PS-Standard.psm1" -Force } + Invoke-WebRequest -uri "https://raw.githubusercontent.com/alexisspencer/ct_store/main/Standard-CT-Module/CT-PS-Standard.psm1" -OutFile "$($PSScriptRoot)\CT-PS-Standard.psm1" -UseBasicParsing -Verbose:$VerbosePreference -Debug:$DebugPreference #-SkipCertificateCheck + Import-Module -Name "$($PSScriptRoot)\CT-PS-Standard.psm1" -Force -Verbose:$VerbosePreference -Debug:$DebugPreference + Initialize-Script + -------- + + #> + + $global:ErrorActionPreference = "Stop" + $global:CT_DEST="C:\CT" # Where the files are downloaded to + $global:DateStamp = get-date -Format yyyyMMddTHHmmss # A formatted date strong + $global:ScriptName = (Get-ChildItem $MyInvocation.PSCommandPath | Select-Object -Expand Name).Substring(0,(Get-ChildItem $MyInvocation.PSCommandPath | Select-Object -Expand Name).Length-4) + $global:Output_log = "$CT_DEST\logs\$($ScriptName)\$($DateStamp)_output.log" # The output + $global:Transcript_log = "$CT_DEST\logs\$($ScriptName)\$($DateStamp)_transcript.log" # The powershell transcript file + $global:API_log = "$($CT_DEST)\logs\$($ScriptName)\$($DateStamp)_API.log" + $global:Install_log = "$CT_DEST\logs\$($ScriptName)\$($DateStamp)_install.log" # The powershell installation file + + + #Transcript-Log "-------$('-' * $MyInvocation.MyCommand.Name.Length)----------" + Start-Transcript -Path $Transcript_log -Append -verbose:$VerbosePreference + Write-Host "**********************" + Write-Host "Output log : $($Output_log)" + Write-Host "Transcript log : $($Transcript_log)" + Write-Host "API log : $($API_log)" + Write-Host "Install log (if used) : $($Install_log)" + Write-Host "Script $($ScriptName) starting." + + #Transcript-Log "-------$('-' * $MyInvocation.MyCommand.Name.Length)----------" + + # Check for a CT folder on the C: and if not, create it, however that location should already exist as part of the Start-Transcript command. + if(-not( Test-Path -Path $CT_DEST )) { + try{ + mkdir $CT_DEST > $null + #Transcript-Log "New folder created at $CT_DEST." + }catch{ + #Can't create the folder, therefore cannot continue + Write-Error "Cannot create folder $CT_DEST. $($Error[0].Exception.Message)" + Write-Error $_ -verbose:$VerbosePreference + #Stop-Transcript + exit 1 + } + } + + if(-not( Test-Path -Path "$($CT_DEST)\logs" )) { + try{ + mkdir "$($CT_DEST)\logs" > $null + #Transcript-Log "New logs folder created at $CT_DEST." + }catch{ + #Can't create the folder, therefore cannot continue + Write-Error "Cannot create logs folder in $CT_DEST. $($Error[0].Exception.Message)" + Write-Error $_ -verbose:$VerbosePreference + #Stop-Transcript + exit 3 + } + } + + if(-not( Test-Path -Path "$($CT_DEST)\logs\$($ScriptName)" )) { + try{ + mkdir "$($CT_DEST)\logs\$($ScriptName)" > $null + #Transcript-Log "New logs folder for $($ScriptName) created at $CT_DEST." + }catch{ + #Can't create the folder, therefore cannot continue + Write-Error "Cannot create logs folder for $($ScriptName) in $CT_DEST. $($Error[0].Exception.Message)" + Write-Error $_ + #Stop-Transcript + exit 4 + } + } + + $global:CT_Reg_Path = "HKLM:\Software\CT\Monitoring" + $global:CT_Reg_Key = "$($CT_Reg_Path)\$($ScriptName)" + if(-not( Test-Path -Path $CT_Reg_Key )) { + try{ + $CTMonitoringReg = New-Item -Path $CT_Reg_Path -Name $ScriptName -Force + Set-ItemProperty -Path "HKLM:\Software\CT" -Name "CustomerNo" -Value $customer + }catch{ + #Can't create the regkey, therefore cannot continue + Write-Error "Cannot create registry key at $($CT_Reg_Key). $($Error[0].Exception.Message)" + Write-Error "$($CTMonitoringReg)" + Write-Error $_ + #Stop-Transcript + exit 5 + } + } + + # Create Transcript header + Write-Log "**********************" + Write-Log "Script: $($PSCmdlet.MyInvocation.ScriptName)." + Write-Log "Start time: $($DateStamp)" + Write-Log "Username: $($env:USERDOMAIN)\$($env:USERNAME)" + Write-Log "Execution Policy Preference: $($env:PSExecutionPolicyPreference)" + Write-Log "Machine: $($env:COMPUTERNAME) ($($env:OS))" + Write-Log "Process ID: $($PID))" + Write-Log "PSVersion: $($PSVersionTable.PSVersion)" + Write-Log "PSEdition: $($PSVersionTable.PSEdition)" + Write-Log "PSCompatibleVersions: $($PSVersionTable.PSCompatibleVersions)" + Write-Log "BuildVersion: $($PSVersionTable.BuildVersion)" + Write-Log "CLRVersion: $($PSVersionTable.CLRVersion)" + Write-Log "WSManStackVersion: $($PSVersionTable.WSManStackVersion)" + Write-Log "PSRemotingProtocolVersion: $($PSVersionTable.PSRemotingProtocolVersion)" + Write-Log "SerializationVersion: $($PSVersionTable.SerializationVersion)" + Write-Log "**********************" + + + <# + ---- END STANDARD SCRIPT BLOCK---- + #> + +} + +Function Write-Log { + [CmdletBinding()] + Param( + [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] + $output + ) + if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) { + Write-Verbose "($(Get-CurrentLineNumber)) $($output)" + } + $output | Out-File -FilePath "$($Output_log)" -Append +} + + +# Writes to the API log and optionally console if -Verbose flag is set at script level +Function Write-APILog { + [CmdletBinding()] + Param( + [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] + $output + ) + if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) { + Write-Verbose "($(Get-CurrentLineNumber)) $($output)" + } + $output | Out-File -FilePath "$($API_log)" -Append +} + + +Function Request-Download { + # Downloads a file using BITS if possible, and if BITS is not available, downloads directly from URL + [CmdletBinding()] + Param( + [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, Mandatory = $true)] + [string[]] $FILE_URL, + [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, Mandatory = $true)] + [string[]] $FILE_LOCAL, + [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] + [switch] $NoBITS # This is for when BITS should not be used + ) + + + # Test for existing file and remove if it exists + if(Test-Path -Path $MSIfFILE_LOCALile70 -PathType Leaf ) { + try { + Remove-Item $FILE_LOCAL -Force + } catch { + #Can't remove the MSI, therefore cannot continue + Write-Log "Cannot remove $FILE_LOCAL. Unable to continue. $($Error[0].Exception.Message)" + return $Error + } + } + + + if (!(Get-Module -ListAvailable -Name "BitsTransfer") -and !($NoBITS)) { + try{ + Import-Module BitsTransfer -Force + } catch { + $NoBITS = $true + } + } + + + + + if (!($NoBITS)) { + # Check if BranchCache Distributed Mode is enabled, and if not, enable it so BITS uses computers on the subnet to download where available + $BCStatus = Get-BCStatus + if ($BCStatus.ClientConfiguration.CurrentClientMode -ne "DistributedCache") { + try { + Enable-BCDistributed -Verbose -Force + Write-Log "BranchCache Distributed Mode is now enabled" -Verbose:$VerbosePreference + } catch { + #BranchCache cannot be enabled to work with BITS. BITS will download over the internet connection instead of cached copies on the local subnet + Write-Log "Cannot enable BranchCache Distributed Mode. $($Error[0].ErrorDetails). The installation files will download over the internet connection instead of cached copies on the local subnet" -Verbose:$VerbosePreference + } + } else { + Write-Log "BranchCache Distributed Mode is already enabled in distributed mode on this computer" -Verbose:$VerbosePreference + } + $DownloadJob = Start-BitsTransfer -Priority Normal -DisplayName "$($DateStamp) $($FILE_LOCAL)" -Source $FILE_URL -Destination $FILE_LOCAL + } else { + try { + $DownloadJob = Invoke-WebRequest -Uri $FILE_URL -OutFile $FILE_LOCAL -SkipCertificateCheck -PassThru + } catch { + Write-Log "Cannot download $($FILE_URL). $_" -Verbose:$VerbosePreference + return $_ + } + } + return $DownloadJob +} + + +function Get-CurrentLineNumber { + # Downloads a file using BITS if possible, and if BITS is not available, downloads directly from URL + [CmdletBinding()] + param() + #$LineNumber = + return $PSCmdlet.MyInvocation.ScriptLineNumber +} +