├── .gitignore ├── 1.ScheduleDownloads.xml ├── 3.ScheduleEmail.xml ├── Configs ├── email_configs.xml └── mdt_configs.xml ├── Download3rdSoftware.bat ├── Get-3rdPartySoftware.ps1 ├── README.md └── SendEmail-3rdPartySoftware.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | Software 2 | Logs 3 | Tools 4 | access.txt 5 | -------------------------------------------------------------------------------- /1.ScheduleDownloads.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerShellCrack/PSThirdPartyAppsManager/8fb5a64fc1ada219cc72a8c6b15e9009d7149041/1.ScheduleDownloads.xml -------------------------------------------------------------------------------- /3.ScheduleEmail.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerShellCrack/PSThirdPartyAppsManager/8fb5a64fc1ada219cc72a8c6b15e9009d7149041/3.ScheduleEmail.xml -------------------------------------------------------------------------------- /Configs/email_configs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | internal 7 | 8 | Downloaded 3rd Party Software and Updates 9 | 10 | 11 | mail.contoso.com 12 | 25 13 | True 14 | service@contoso.com 15 | firstemail@contoso.com,secondemail@contoso.com 16 | ExchCreds.xml 17 | 18 | 19 | 20 | smtp.gmail.com 21 | 587 22 | yourgmail@gmail.com 23 | yourgmailpassword 24 | True 25 | yourgmail@gmail.com 26 | yourgmail@gmail.com 27 | 28 | 29 | -------------------------------------------------------------------------------- /Configs/mdt_configs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mdt.contoso.com 5 | deploymentshare$ 6 | D:\DeploymentShare 7 | False 8 | 9 | Configs\MDTCreds.xml 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Download3rdSoftware.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | powershell -ExecutionPolicy bypass -file "%~dp0Get-3rdPartySoftware.ps1" -------------------------------------------------------------------------------- /Get-3rdPartySoftware.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerShellCrack/PSThirdPartyAppsManager/8fb5a64fc1ada219cc72a8c6b15e9009d7149041/Get-3rdPartySoftware.ps1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3rd Party Software Downloader 2 | 3 | ## Description 4 | - Powershell script to download the latest 3rd party software 5 | 6 | ## Tags 7 | - msi 8 | - vlc-player 9 | - firefox 10 | - adobe-reader 11 | - chrome 12 | - powershell-script 13 | - google-chrome 14 | - downloader 15 | - 7zip 16 | - google-chrome-stable 17 | - powershell 18 | - third-party 19 | - java 20 | - sccm 21 | - mdt 22 | - mdt-automation-project 23 | 24 | 25 | ## Project: 26 | - This is part of my MDT/SCCM automation Project 27 | 28 | ## What it does: 29 | The script crawls through the 3rd party websites, looking for specific tags in the html and auto navigates to find the download link. Then it will download the files and store them in a folder. Once downloaded, it will build a Cixml that can be imported with another script (https://github.com/PowerShellCrack/MDTApplicationUpdater) to automaticaly updates MDT. 30 | 31 | ## Works on: 32 | - Currently it only updates wsf files (https://github.com/PowerShellCrack/MDTDeployApplications) 33 | - NOTE: The wsf file must contain the variable: sVersion 34 | 35 | ## Supports: 36 | - Adobe Reader 37 | - Adobe Reader Updates (and MUI) 38 | - Adobe Acrobat Reader DC Updates (and MUI) 39 | - Flash Player Active X 40 | - Flash Player NPAPI (Firefox) 41 | - Flash Player PPAPI (Chrome) 42 | - Shockwave (full, slim and msi) 43 | - Google Chrome Enterprise Edition (msi) 44 | - Google Chrome Standalone (exe) 45 | - Firefox (x86) 46 | - Firefox (x64) 47 | - Notepadd++ (x86) 48 | - Notepadd++ (x64) 49 | - 7Zip (x64) - MSI and EXE 50 | - 7Zip (x86) - MSI and EXE 51 | - VLC Player (x64) 52 | - VLC Player (x86) 53 | - Java 8 (x86) 54 | - Java 8 (x64) 55 | -------------------------------------------------------------------------------- /SendEmail-3rdPartySoftware.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .INFO 3 | Script: SendEmail-3rdPartySoftware.ps1 4 | Author: Richard Tracy 5 | Email: richard.tracy@hotmail.com 6 | Twitter: @rick2_1979 7 | Website: www.powershellcrack.com 8 | Last Update: 07/15/2019 9 | Version: 1.0.0 10 | 11 | .DISCLOSURE 12 | THE SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 13 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. BY USING OR DISTRIBUTING THIS SCRIPT, YOU AGREE THAT IN NO EVENT 14 | SHALL THE AUTHOR OR ANY AFFILATES BE HELD LIABLE FOR ANY DAMAGES WHATSOEVER RESULTING FROM USING OR DISTRIBUTION OF THIS SCRIPT, INCLUDING, 15 | WITHOUT LIMITATION, ANY SPECIAL, CONSEQUENTIAL, INCIDENTAL OR OTHER DIRECT OR INDIRECT DAMAGES. BACKUP UP ALL DATA BEFORE PROCEEDING. 16 | 17 | .SYNOPSIS 18 | Sends an email of 3rd party Software and updates from list generated 19 | 20 | .DESCRIPTION 21 | Imports list generated by Get-3rdPartySoftware.ps1 and emails it and formats it as table 22 | 23 | .PARAMETER SoftwareList 24 | REQUIRED: Specified path to software list 25 | 26 | .PARAMETER ConfigPath 27 | Specified path to alternate config file. Defaults to relative path of script under Config folder 28 | 29 | .PARAMETER SMTPServer 30 | NAMED SMTP. Specify basic SMTP server (usally exchange). Use config for more detail 31 | 32 | .PARAMETER From 33 | NAMED SMTP Specify from receipent when using SMTPServer param 34 | 35 | .PARAMETER To 36 | NAMED SMTP. Specify to receipent when using SMTPServer param> Use array for mutlple. EG: @("user1@domain", "user2@domain") 37 | 38 | .EXAMPLE 39 | powershell.exe -file "SendEmail-3rdPartySoftware.ps1" -SoftwareList D:\3rdPartySoftware\softwarelist.xml 40 | 41 | powershell.exe -file "SendEmail-3rdPartySoftware.ps1" -ConfigPath D:\Configs\email.xml -SoftwareList D:\3rdPartySoftware\softwarelist.xml 42 | 43 | powershell.exe -file "SendEmail-3rdPartySoftware.ps1" -SoftwareList D:\3rdPartySoftware\softwarelist.xml -SMSTServer mail.mydomain.local -From me@mydomain.local-To friend1@mydomain.local 44 | 45 | .NOTES 46 | This script is meant to be scheduled or chained with Get-3rdPartySoftware.ps1 script. Use the Schedule exposrt to build a chain task schudule. 47 | Using the config is more advanced than the params. Read the config comment sfor more info. 48 | 49 | .LINK 50 | 51 | .CHANGE LOG 52 | 1.0.0 - Jul 15, 2019 - initial 53 | #> 54 | ##*=========================================================================== 55 | ##* PARAMS 56 | ##*=========================================================================== 57 | [CmdletBinding(DefaultParameterSetName='Null')] 58 | param ( 59 | [Parameter(ParameterSetName='Config', Mandatory=$true)] 60 | [string]$ConfigPath, 61 | 62 | [Parameter(Mandatory=$true)] 63 | [string]$SoftwareList, 64 | 65 | [Parameter(ParameterSetName='SMTP', Mandatory=$true)] 66 | [string]$SMTPServer, 67 | 68 | [Parameter(ParameterSetName='SMTP',Mandatory=$false)] 69 | [string]$From = 'mdt@localhost', 70 | 71 | [Parameter(ParameterSetName='SMTP',Mandatory=$true)] 72 | [string[]]$To 73 | ) 74 | 75 | #================================================== 76 | # FUNCTIONS 77 | #================================================== 78 | Function Test-IsISE { 79 | # try...catch accounts for: 80 | # Set-StrictMode -Version latest 81 | try { 82 | return ($null -ne $psISE); 83 | } 84 | catch { 85 | return $false; 86 | } 87 | } 88 | 89 | Function Get-ScriptPath { 90 | # Makes debugging from ISE easier. 91 | if ($PSScriptRoot -eq "") 92 | { 93 | if (Test-IsISE) 94 | { 95 | $psISE.CurrentFile.FullPath 96 | #$root = Split-Path -Parent $psISE.CurrentFile.FullPath 97 | } 98 | else 99 | { 100 | $context = $psEditor.GetEditorContext() 101 | $context.CurrentFile.Path 102 | #$root = Split-Path -Parent $context.CurrentFile.Path 103 | } 104 | } 105 | else 106 | { 107 | #$PSScriptRoot 108 | $PSCommandPath 109 | #$MyInvocation.MyCommand.Path 110 | } 111 | } 112 | 113 | 114 | Function Format-DatePrefix { 115 | [string]$LogTime = (Get-Date -Format 'HH:mm:ss.fff').ToString() 116 | [string]$LogDate = (Get-Date -Format 'MM-dd-yyyy').ToString() 117 | return ($LogDate + " " + $LogTime) 118 | } 119 | 120 | Function Write-LogEntry { 121 | param( 122 | [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] 123 | [ValidateNotNullOrEmpty()] 124 | [string]$Message, 125 | [Parameter(Mandatory=$false,Position=2)] 126 | [string]$Source = '', 127 | [parameter(Mandatory=$false)] 128 | [ValidateSet(0,1,2,3,4)] 129 | [int16]$Severity, 130 | 131 | [parameter(Mandatory=$false, HelpMessage="Name of the log file that the entry will written to")] 132 | [ValidateNotNullOrEmpty()] 133 | [string]$OutputLogFile = $Global:LogFilePath, 134 | 135 | [parameter(Mandatory=$false)] 136 | [switch]$Outhost 137 | ) 138 | Begin{ 139 | [string]$LogTime = (Get-Date -Format 'HH:mm:ss.fff').ToString() 140 | [string]$LogDate = (Get-Date -Format 'MM-dd-yyyy').ToString() 141 | [int32]$script:LogTimeZoneBias = [timezone]::CurrentTimeZone.GetUtcOffset([datetime]::Now).TotalMinutes 142 | [string]$LogTimePlusBias = $LogTime + $script:LogTimeZoneBias 143 | 144 | } 145 | Process{ 146 | # Get the file name of the source script 147 | Try { 148 | If ($script:MyInvocation.Value.ScriptName) { 149 | [string]$ScriptSource = Split-Path -Path $script:MyInvocation.Value.ScriptName -Leaf -ErrorAction 'Stop' 150 | } 151 | Else { 152 | [string]$ScriptSource = Split-Path -Path $script:MyInvocation.MyCommand.Definition -Leaf -ErrorAction 'Stop' 153 | } 154 | } 155 | Catch { 156 | $ScriptSource = '' 157 | } 158 | 159 | 160 | If(!$Severity){$Severity = 1} 161 | $LogFormat = "" + "" 162 | 163 | # Add value to log file 164 | try { 165 | Out-File -InputObject $LogFormat -Append -NoClobber -Encoding Default -FilePath $OutputLogFile -ErrorAction Stop 166 | } 167 | catch { 168 | Write-Host ("[{0}] [{1}] :: Unable to append log entry to [{1}], error: {2}" -f $LogTimePlusBias,$ScriptSource,$OutputLogFile,$_.Exception.Message) -ForegroundColor Red 169 | } 170 | } 171 | End{ 172 | If($Outhost -or $Global:OutTohost){ 173 | If($Source){ 174 | $OutputMsg = ("[{0}] [{1}] :: {2}" -f $LogTimePlusBias,$Source,$Message) 175 | } 176 | Else{ 177 | $OutputMsg = ("[{0}] [{1}] :: {2}" -f $LogTimePlusBias,$ScriptSource,$Message) 178 | } 179 | 180 | Switch($Severity){ 181 | 0 {Write-Host $OutputMsg -ForegroundColor Green} 182 | 1 {Write-Host $OutputMsg -ForegroundColor Gray} 183 | 2 {Write-Warning $OutputMsg} 184 | 3 {Write-Host $OutputMsg -ForegroundColor Red} 185 | 4 {If($Global:Verbose){Write-Verbose $OutputMsg}} 186 | default {Write-Host $OutputMsg} 187 | } 188 | } 189 | } 190 | } 191 | ##*=========================================================================== 192 | ##* VARIABLES 193 | ##*=========================================================================== 194 | # Use function to get paths because Powershell ISE and other editors have differnt results 195 | $scriptPath = Get-ScriptPath 196 | [string]$scriptDirectory = Split-Path $scriptPath -Parent 197 | [string]$scriptName = Split-Path $scriptPath -Leaf 198 | [string]$scriptBaseName = [System.IO.Path]::GetFileNameWithoutExtension($scriptName) 199 | 200 | #Get required folder and File paths 201 | If($PsCmdlet.ParameterSetName -eq 'Config'){ 202 | [string]$EmailConfigPath = $Config 203 | } 204 | Else{ 205 | [string]$ConfigPath = Join-Path -Path $scriptDirectory -ChildPath 'Configs' 206 | [string]$EmailConfigPath = Join-Path -Path $ConfigPath -ChildPath "email_configs.xml" 207 | } 208 | 209 | $RelativeLogPath = Join-Path -Path $scriptDirectory -ChildPath 'Logs' 210 | #build log name 211 | [string]$FileName = $scriptBaseName + '-' + (get-date -Format MM-dd-yyyy-hh-mm-ss) + '.log' 212 | #build global log fullpath 213 | $Global:LogFilePath = Join-Path $RelativeLogPath -ChildPath $FileName 214 | 215 | #clean old log 216 | if(Test-Path $Global:LogFilePath){remove-item -Path $Global:LogFilePath -ErrorAction SilentlyContinue | Out-Null} 217 | 218 | Write-Host "Logging to file: $LogFilePath" -ForegroundColor Cyan 219 | 220 | ##* ============================== 221 | ##* MAIN - DO ACTION 222 | ##* ============================== 223 | #import the Software list 224 | If($SoftwareList){ 225 | $SoftwareObject = Import-Clixml $SoftwareList 226 | } 227 | Else{ 228 | Write-LogEntry ("No software repository path or xml file specified") -Severity 3 -Outhost 229 | Exit 230 | } 231 | 232 | $EmailParams = @{} 233 | # BUILD PATHS FROM XML 234 | #======================================================= 235 | If(Test-Path $EmailConfigPath){ 236 | [string]$EmailXMLFile = (Get-Content $EmailConfigPath -ReadCount 0) -replace '&','&' 237 | [xml]$EmailConfigs = $EmailXMLFile 238 | 239 | #get email settings 240 | [boolean]$SendEmail = [boolean]::Parse($EmailConfigs.emailConfigs.enable) 241 | [string]$EmailType = $EmailConfigs.emailConfigs.Type 242 | [string]$Subject = $EmailConfigs.emailConfigs.Subject 243 | 244 | switch($EmailType){ 245 | 246 | "internal" { 247 | [string]$Server = $EmailConfigs.emailConfigs.internalEmail.SmtpServer 248 | [string]$Port = $EmailConfigs.emailConfigs.internalEmail.Port 249 | [boolean]$UseSSL = [boolean]::Parse($EmailConfigs.emailConfigs.internalEmail.UseSSL) 250 | [string]$From = $EmailConfigs.emailConfigs.internalEmail.From 251 | $Recipents = $EmailConfigs.emailConfigs.internalEmail.To -split "," 252 | [string[]]$To = @($Recipents) 253 | #build credentials 254 | If(Get-ChildItem $EmailConfigs.emailConfigs.ExchCreds -Recurse -ErrorAction SilentlyContinue | Out-null){ 255 | [System.Management.Automation.PSCredential]$credentials = Get-credential (Import-Clixml $EmailConfigs.emailConfigs.internalEmail.ExchCreds) 256 | $EmailParams.Add('Credentials',$credentials) 257 | } 258 | } 259 | 260 | "external" { 261 | [string]$Server = $EmailConfigs.emailConfigs.externalEmail.SmtpServer 262 | [string]$Port = $EmailConfigs.emailConfigs.externalEmail.Port 263 | [boolean]$UseSSL = [boolean]::Parse($EmailConfigs.externalEmail.UseSSL) 264 | [string]$From = $EmailConfigs.emailConfigs.externalEmail.From 265 | $Recipents = $EmailConfigs.emailConfigs.internalEmail.To -split "," 266 | [string[]]$To = @($Recipents) 267 | [string]$Username = $EmailConfigs.emailConfigs.externalEmail.Username 268 | [string]$Password = $EmailConfigs.emailConfigs.externalEmail.Password 269 | #build credentials 270 | $credentials = new-object Management.Automation.PSCredential "$Username", ("$Password" | ConvertTo-SecureString -AsPlainText -Force) 271 | If($credentials){$EmailParams.Add('Credentials',$credentials)} 272 | } 273 | } 274 | Write-LogEntry ("Using {0} email type for: {1}" -f $EmailType,$Server) -Severity 1 -Outhost 275 | } 276 | Else{ 277 | Write-LogEntry ("Unable to find configuration settings: {0}" -f $EmailConfigPath) -Severity 3 -Outhost 278 | Exit 279 | } 280 | 281 | $Attachment = Get-ChildItem $RelativeLogPath -Filter '*log' | Where-Object{$_.Name -match 'Get-3rdPartySoftware'} | sort LastWriteTime | select -last 1 -ExpandProperty FullName 282 | If($Attachment){$EmailParams.Add('Attachment',$Attachment)} 283 | 284 | #Set columns list 285 | $columnsToSelect = @('DownloadDate','Publisher','Product','ProductType','File','Size','Version','Arch','Language') 286 | 287 | #Grab MDTShare properties values (if exists) 288 | $SoftwareObject | Foreach{ 289 | $ShareProperties = $_.PSObject.Properties -match 'MDTShare' | Select -ExpandProperty Name 290 | } 291 | #slat them to the columns list 292 | If($ShareProperties){$columnsToSelect += $ShareProperties} 293 | 294 | #Grab MDTStatus properties values (if exists) 295 | $SoftwareObject | Foreach{ 296 | $StatusProperties = $_.PSObject.Properties -match 'MDTStatus' | Select -ExpandProperty Name 297 | } 298 | #slat them to the columns list 299 | If($StatusProperties){$columnsToSelect += $StatusProperties} 300 | 301 | 302 | #build style 303 | $style = "" 308 | 309 | #[string]$message = $SoftwareObject | Where-Object{$_.Downloaded -eq "True"} | Select-Object Publisher,Product,@{Label='Product Type'; Expression={$_.ProductType}},File,Size,Version,Arch,Language,@{Label='Downloaded'; Expression={$_.DownloadDate}} | Sort-Object DownloadDate -Descending | ConvertTo-Html -Head $style 310 | [string]$message = $SoftwareObject | Where-Object{$_.Downloaded -eq "True"} | Select-Object $columnsToSelect | Sort-Object DownloadDate -Descending | ConvertTo-Html -Head $style 311 | 312 | Write-LogEntry ("Software columns identified: {0}" -f ($columnsToSelect -join ",")) -Severity 1 -Outhost 313 | 314 | #format message as a html table 315 | $message = $message + "SOFTWARE LOCATION: $(Split-path $SoftwareList -Parent)" 316 | $message = $message + "
" 317 | $message = $message + "HOST: $env:Computername" 318 | $message = $message + "
" 319 | $message = $message + "SCRIPT: Get-3rdPartySoftware.ps1" 320 | $message = $message + "
" 321 | $message = $message + "DATE: $(Get-date)" 322 | 323 | 324 | If($SendEmail){ 325 | Write-LogEntry ("Sending Email to: {0}" -f ($Recipents -join ",")) -Severity 1 -Outhost 326 | Try{ 327 | Send-MailMessage -From $From -To $to -Subject $Subject -Body $message -BodyAsHtml -Priority High -DeliveryNotificationOption OnSuccess, OnFailure -SmtpServer $Server -UseSsl:$UseSSL @EmailParams 328 | Write-LogEntry ("Email Sent, script completed") -Severity 1 -Outhost 329 | } 330 | Catch{ 331 | Write-LogEntry ("Unable to send email: {0}" -f $_.Exception.Message) -Severity 3 -Outhost 332 | } 333 | } 334 | --------------------------------------------------------------------------------