mirror of
https://github.com/freedbygrace/ADDAP.git
synced 2026-07-26 19:18:13 +00:00
343 lines
22 KiB
PowerShell
343 lines
22 KiB
PowerShell
## Microsoft Function Naming Convention: http://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx
|
|
|
|
#region Function Invoke-FileDownload
|
|
Function Invoke-FileDownload
|
|
{
|
|
<#
|
|
.SYNOPSIS
|
|
Downloads the specified URL.
|
|
|
|
.DESCRIPTION
|
|
The file will only be downloaded if the last modified date of the source URL is different from the last modified date of the file that has already been downloaded or if the file have not already been downloaded.
|
|
|
|
.PARAMETER URL
|
|
The URL where the file is located.
|
|
|
|
.PARAMETER Destination
|
|
The full file path where the cabinet will be downloaded to. If not specified, a default value will be used.
|
|
|
|
.EXAMPLE
|
|
Invoke-FileDownload -URL 'https://dl.dell.com/catalog/DriverPackCatalog.cab' -Destination "$($Env:ProgramData)\Dell\DriverPackCatalog\DriverPackCatalog.cab" -Verbose
|
|
|
|
.EXAMPLE
|
|
$DownloadDetails = Invoke-FileDownload -URL 'https://dl.dell.com/catalog/DriverPackCatalog.cab' -Destination "$($Env:ProgramData)\Dell\DriverPackCatalog\DriverPackCatalog.cab" -Verbose
|
|
|
|
Write-Output -InputObject ($DownloadDetails)
|
|
|
|
.EXAMPLE
|
|
$InvokeFileDownloadParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$InvokeFileDownloadParameters.URL = 'https://dl.dell.com/catalog/DriverPackCatalog.cab' -As [System.URI]
|
|
$InvokeFileDownloadParameters.Destination = "$($Env:ProgramData)\Dell\DriverPackCatalog\DriverPackCatalog.cab" -As [System.IO.FileInfo]
|
|
$InvokeFileDownloadParameters.ContinueOnError = $False
|
|
$InvokeFileDownloadParameters.Verbose = $True
|
|
|
|
$InvokeFileDownloadResult = Invoke-FileDownload @InvokeFileDownloadParameters
|
|
|
|
Write-Output -InputObject ($InvokeFileDownloadResult)
|
|
|
|
.NOTES
|
|
NEL : {"report_to":"network-errors","max_age":3600}
|
|
Report-To : {"group":"network-errors","max_age":3600,"endpoints":[{"url":"https://www.dell.com/support/onlineapi/nellogger/log"}]}
|
|
Accept-Ranges : bytes
|
|
Content-Type : application/vnd.ms-cab-compressed
|
|
ETag : "8043933683ddd81:0"
|
|
Last-Modified : Tue, 11 Oct 2022 15:07:43 GMT
|
|
Server : Microsoft-IIS/10.0
|
|
X-Powered-By : ASP.NET
|
|
x-arr-set : arr4
|
|
Content-Length : 270867
|
|
Date : Thu, 20 Oct 2022 15:51:44 GMT
|
|
Connection : keep-alive
|
|
Akamai-Request-BC : [a=23.207.199.174,b=78861523,c=g,n=US_VA_STERLING,o=20940]
|
|
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest?view=netframework-4.8
|
|
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient.downloaddata?view=netframework-4.8#system-net-webclient-downloaddata(system-uri)
|
|
#>
|
|
|
|
[CmdletBinding(ConfirmImpact = 'Low', SupportsShouldProcess = $True)]
|
|
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$True, ValueFromPipelineByPropertyName = $True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[ValidatePattern('^http(s)\:\/\/.*\/.*\.(.{3,4})$')]
|
|
[System.URI]$URL,
|
|
|
|
[Parameter(Mandatory=$False, ValueFromPipelineByPropertyName = $True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.IO.DirectoryInfo]$Destination,
|
|
|
|
[Parameter(Mandatory=$False, ValueFromPipelineByPropertyName = $True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[ValidatePattern('^.*\.(.*)$')]
|
|
[String]$FileName,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[Switch]$ContinueOnError
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Try
|
|
{
|
|
Switch ($True)
|
|
{
|
|
{([String]::IsNullOrEmpty($Destination) -eq $True) -or ([String]::IsNullOrWhiteSpace($Destination) -eq $True)}
|
|
{
|
|
[System.IO.DirectoryInfo]$Destination = "$($Env:Windir)\Temp"
|
|
}
|
|
|
|
{([String]::IsNullOrEmpty($FileName) -eq $True) -or ([String]::IsNullOrWhiteSpace($FileName) -eq $True)}
|
|
{
|
|
[String]$FileName = [System.IO.Path]::GetFileName($URL.OriginalString)
|
|
}
|
|
}
|
|
|
|
[System.IO.FileInfo]$DestinationPath = "$($Destination.FullName)\$($FileName)"
|
|
|
|
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy @ hh:mm:ss tt' ###Monday, January 01, 2019 @ 10:15:34 AM###
|
|
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
|
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
|
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
|
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
|
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
|
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
|
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
|
$TextInfo = (Get-Culture).TextInfo
|
|
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$LoggingDetails.Add('LogMessage', $Null)
|
|
$LoggingDetails.Add('WarningMessage', $Null)
|
|
$LoggingDetails.Add('ErrorMessage', $Null)
|
|
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
|
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
|
|
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
|
|
|
|
[ScriptBlock]$ErrorHandlingDefinition = {
|
|
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
|
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
|
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
|
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
|
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
|
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
|
|
|
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
|
{
|
|
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
|
Write-Warning -Message ($LoggingDetails.ErrorMessage)
|
|
}
|
|
|
|
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
Throw
|
|
}
|
|
}
|
|
}
|
|
|
|
#Determine the date and time we executed the function
|
|
$FunctionStartTime = (Get-Date)
|
|
|
|
[String]$CmdletName = $MyInvocation.MyCommand.Name
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($CmdletName)`' is beginning. Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
#Define Default Action Preferences
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
[String[]]$AvailableScriptParameters = (Get-Command -Name ($CmdletName)).Parameters.GetEnumerator() | Where-Object {($_.Value.Name -inotin $CommonParameterList)} | ForEach-Object {"-$($_.Value.Name):$($_.Value.ParameterType.Name)"}
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Available Function Parameter(s) = $($AvailableScriptParameters -Join ', ')"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
[String[]]$SuppliedScriptParameters = $PSBoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key):$($_.Value.GetType().Name)"}
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Supplied Function Parameter(s) = $($SuppliedScriptParameters -Join ', ')"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($CmdletName) began on $($FunctionStartTime.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$OutputObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$OutputObjectProperties.DownloadRequired = $False
|
|
}
|
|
Catch
|
|
{
|
|
$ErrorHandlingDefinition.Invoke()
|
|
}
|
|
Finally
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
Process
|
|
{
|
|
Try
|
|
{
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to create a web request for `"$($URL.OriginalString)`". Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$WebRequest = [System.Net.WebRequest]::Create($URL.OriginalString)
|
|
|
|
$WebRequestResponse = $WebRequest.GetResponse()
|
|
|
|
$WebRequestResponseHeaders = $WebRequestResponse.Headers
|
|
|
|
$WebRequestHeaderProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
|
|
ForEach ($WebRequestResponseHeader In $WebRequestResponseHeaders.AllKeys)
|
|
{
|
|
$WebRequestHeaderProperties."$($WebRequestResponseHeader)" = ($WebRequestResponseHeaders.GetValues($WebRequestResponseHeader))[0]
|
|
}
|
|
|
|
$WebRequestHeaders = New-Object -TypeName 'PSObject' -Property ($WebRequestHeaderProperties)
|
|
|
|
$WebRequestHeaders.'Last-Modified' = (Get-Date -Date $WebRequestHeaders.'Last-Modified').ToUniversalTime()
|
|
|
|
$ContentLengthInMB = [System.Math]::Round(($WebRequestHeaders.'Content-Length' / 1MB), 2)
|
|
|
|
[ScriptBlock]$ExecuteDownload = {
|
|
$WebClient = New-Object -TypeName 'System.Net.WebClient'
|
|
$WebClient.UseDefaultCredentials = $True
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to download data stream from `"$($URL.OriginalString)`". Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Download Size: $($ContentLengthInMB) MegaBytes"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$Null = Measure-Command -Expression {[Byte[]]$DownloadedData = $WebClient.DownloadData($URL.OriginalString)} -OutVariable 'DownloadExecutionTimespan'
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Stream download took $($DownloadExecutionTimespan.Hours.ToString()) hour(s), $($DownloadExecutionTimespan.Minutes.ToString()) minute(s), $($DownloadExecutionTimespan.Seconds.ToString()) second(s), and $($DownloadExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to flush the downloaded data stream to file `"$($DestinationPath.FullName)`". Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
If ([System.IO.Directory]::Exists($DestinationPath.Directory.FullName) -eq $False) {$Null = [System.IO.Directory]::CreateDirectory($DestinationPath.Directory.FullName)}
|
|
|
|
$Null = [System.IO.File]::WriteAllBytes($DestinationPath.FullName, $DownloadedData)
|
|
|
|
[Int]$SecondsToWait = 3
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Pausing script execution for $($SecondsToWait) second(s). Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$Null = Start-Sleep -Seconds ($SecondsToWait)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to update the last modified date of `"$($DestinationPath.FullName)`" to match `"$($URL.OriginalString)`". Please Wait..."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Last Modified Date (Local): $($DestinationPath.LastWriteTimeUTC.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Last Modified Date (Source): $($WebRequestHeaders.'Last-Modified'.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$Null = (Get-Item -Path $DestinationPath.FullName -Force).LastWriteTimeUTC = $WebRequestHeaders.'Last-Modified'
|
|
|
|
$Null = $WebClient.Dispose()
|
|
}
|
|
|
|
Switch ([System.IO.File]::Exists($DestinationPath.FullName))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Destination path `"$($DestinationPath.FullName)`" already exists."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to check the last modified date of `"$($DestinationPath.FullName)`" to see if a download is necessary."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Last Modified Date (Source): $($WebRequestHeaders.'Last-Modified'.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Last Modified Date (Local): $($DestinationPath.LastWriteTimeUTC.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
Switch (($DestinationPath.LastWriteTimeUTC -ine $WebRequestHeaders.'Last-Modified'))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A redownload of `"$($URL.OriginalString)`" is necessary."
|
|
Write-Warning -Message ($LoggingDetails.WarningMessage)
|
|
|
|
$OutputObjectProperties.DownloadRequired = $True
|
|
|
|
$ExecuteDownload.InvokeReturnAsIs()
|
|
}
|
|
|
|
Default
|
|
{
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A redownload of `"$($URL.OriginalString)`" is not necessary."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
}
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Destination path `"$($DestinationPath.FullName)`" does not exist."
|
|
Write-Warning -Message ($LoggingDetails.WarningMessage)
|
|
|
|
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A download of `"$($URL.OriginalString)`" is necessary."
|
|
Write-Warning -Message ($LoggingDetails.WarningMessage)
|
|
|
|
$OutputObjectProperties.DownloadRequired = $True
|
|
|
|
$ExecuteDownload.InvokeReturnAsIs()
|
|
}
|
|
}
|
|
}
|
|
Catch
|
|
{
|
|
$ErrorHandlingDefinition.Invoke()
|
|
}
|
|
Finally
|
|
{
|
|
Try {$Null = $WebRequestResponse.Dispose()} Catch {}
|
|
}
|
|
}
|
|
|
|
End
|
|
{
|
|
Try
|
|
{
|
|
#Determine the date and time the function completed execution
|
|
$FunctionEndTime = (Get-Date)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($CmdletName) ended on $($FunctionEndTime.ToString($DateTimeLogFormat))"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
#Log the total script execution time
|
|
$FunctionExecutionTimespan = New-TimeSpan -Start ($FunctionStartTime) -End ($FunctionEndTime)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function execution took $($FunctionExecutionTimespan.Hours.ToString()) hour(s), $($FunctionExecutionTimespan.Minutes.ToString()) minute(s), $($FunctionExecutionTimespan.Seconds.ToString()) second(s), and $($FunctionExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
|
|
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($CmdletName)`' is completed."
|
|
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
|
}
|
|
Catch
|
|
{
|
|
$ErrorHandlingDefinition.Invoke()
|
|
}
|
|
Finally
|
|
{
|
|
$DestinationPathDetails = Get-Item -Path $DestinationPath.FullName -Force
|
|
|
|
$OutputObjectProperties.DownloadPath = $DestinationPathDetails
|
|
$OutputObjectProperties.URL = $URL
|
|
$OutputObjectProperties.URLHeaders = $WebRequestHeaders
|
|
|
|
$OutputObject = New-Object -TypeName 'PSObject' -Property ($OutputObjectProperties)
|
|
|
|
Write-Output -InputObject ($OutputObject)
|
|
}
|
|
}
|
|
}
|
|
#endregion |