├── Add-CMSystemDiscoveryMethodContainer.ps1
├── Clear-GpoRegistrySettings.ps1
├── Example_Report_07.27.2019.txt
├── Get-ComponentDescription.ps1
├── Get-KBDownloadLink.ps1
├── Get-KnownIssuesWindowsUpdates.ps1
├── Get-MissingDeviceUpdate.ps1
├── Get-SccmSoftwareUpdateStatus.ps1
├── Get-UpdateHistory.ps1
├── Get-WindowsUpdateError.ps1
├── Get-WindowsUpdateErrorCode.ps1
├── Install-7Zip.ps1
├── Install-AzureCli.ps1
├── Install-AzureStorageExplorer.ps1
├── Install-CherryTree.ps1
├── Install-DrawIO.ps1
├── Install-FileZilla.ps1
├── Install-GitForWindows.ps1
├── Install-KeePass.ps1
├── Install-NodeJS.ps1
├── Install-NotepadPlusPlus.ps1
├── Install-PowerShellCore.ps1
├── Install-Putty.ps1
├── Install-RemoteDesktopManager.ps1
├── Install-SSMS.ps1
├── Install-SccmAgent.ps1
├── Install-Signal.ps1
├── Install-VLC.ps1
├── Install-VSCode.ps1
├── Install-WinRAR.ps1
├── Install-WinSCP.ps1
├── Install-WinSCPNetAssembly.ps1
├── Invoke-MissingUpdateInstallation.ps1
├── Invoke-SccmClientAction.ps1
├── LICENSE
├── README.md
├── Remove-CMSystemDiscoveryMethodContainer.ps1
├── Remove-WindowsUpdate.ps1
├── Repair-WindowsUpdate.ps1
├── Reset-SccmAgent.ps1
└── Update-Windows.ps1
/Add-CMSystemDiscoveryMethodContainer.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 | Function Add-CMSystemDiscoveryMethodContainer {
3 | <#
4 | .SYNOPSIS
5 | Import Organizational Units (OU) defined by their distinguished name to an Active Directory System Discovery components in ConfigMgr
6 |
7 |
8 | .DESCRIPTION
9 | This cmdlet uses the distinguished name defined in -SearchBase to the System Discovery method on an SCCM server. Existing containers for the specified Discovery Method will be preserved. If a container is already present, it will not be added again.
10 |
11 |
12 | .PARAMETER SiteServer
13 | SCCM Site Server to connect too
14 |
15 | .PARAMETER UseSSL
16 | Creates CIM session to SCCM server using SSL (WinRM over HTTPS)
17 |
18 | .PARAMETER SkipCACheck
19 | Skip Certificate authority trust check on WinRM connnection
20 |
21 | .PARAMETER SkipCNCheck
22 | Skip verifying the CN/subject name on the WinRM certificate
23 |
24 | .PARAMETER SkipRevocationCheck
25 | Skip checking certificate revocation for WinRM connections
26 |
27 | .PARAMETER SearchBase
28 | Define the LDAP container OU path to new domains being added to System Discovery
29 |
30 | .PARAMETER RestartService
31 | Tells the SCCM server to restart the System Discovery service after adding new containers to search for
32 |
33 | .PARAMETER Credential
34 | Enter credentials to authenticate to the SCCM server
35 |
36 |
37 | .EXAMPLE
38 | Add-CMSystemDiscoveryMethodContainer -SiteServer sccm-server.domain.com -SearchBase "DC=domain,DC=com"
39 | # This example adds the domain.com LDAP search base filter to the domain System Discovery method on the sccm-server.domain.com SCCM server
40 |
41 | .EXAMPLE
42 | Add-CMSystemDiscoveryMethodContainer -SiteServer sccm-server.domain.com -UseSSL -SkipCACheck -SkipCNCheck -SkipRevocationCheck -SearchBase "LDAP:\\DC=domain,DC=com"
43 | # This example adds the domain.com LDAP search base filter to the domain System Discovery method on the sccm-server.domain.com SCCM server
44 |
45 |
46 | .NOTES
47 | Author: Robert H. Osborne
48 | Alias: tobor
49 | Contact: info@osbornerpo.com
50 |
51 |
52 | .INPUTS
53 | None
54 |
55 |
56 | .OUTPUTS
57 | None
58 | #>
59 | [CmdletBinding(
60 | SupportsShouldProcess=$True,
61 | ConfirmImpact="Medium"
62 | )] # End CmdletBinding
63 | param(
64 | [Parameter(
65 | Mandatory=$True,
66 | ValueFromPipeline=$False,
67 | HelpMessage="Site server where the SMS Provider is installed.")] # End Parameter
68 | [ValidateNotNullOrEmpty()]
69 | [String]$SiteServer,
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$UseSSL,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$SkipCACheck,
80 |
81 | [Parameter(
82 | Mandatory=$False
83 | )] # End Parameter
84 | [Switch]$SkipCNCheck,
85 |
86 | [Parameter(
87 | Mandatory=$False
88 | )] # End Parameter
89 | [Switch]$SkipRevocationCheck,
90 |
91 | [Parameter(
92 | Mandatory=$True,
93 | ValueFromPipeline=$True,
94 | ValueFromPipelineByPropertyName=$False,
95 | HelpMessage="Specify the Active Directory Search Base `nEXAMPLE: DC=domain,DC=com : ")] # End Parameter
96 | [ValidateScript({$_ -like "*DC=*,DC=*"})]
97 | [String]$SearchBase,
98 |
99 | [Parameter(
100 | Mandatory=$False
101 | )] # End Parameter
102 | [Switch]$RestartService
103 |
104 | [ValidateNotNull()]
105 | [System.Management.Automation.PSCredential]
106 | [System.Management.Automation.Credential()]
107 | $Credential = [System.Management.Automation.PSCredential]::Empty
108 | ) # End param
109 |
110 | BEGIN {
111 |
112 | $ComponentName = "SMS_AD_SYSTEM_DISCOVERY_AGENT"
113 | Try {
114 |
115 | Write-Verbose -Message "Determining Site Code for Site server: '$($SiteServer)'"
116 | $CIMSession = New-CimSession -Credential $Credential -ComputerName $SiteServer -SessionOption (New-CimSessionOption -UseSSL:$UseSSL.IsPresent -SkipCACheck:$SkipCACheck.IsPresent -SkipCNCheck:$SkipCNCheck.IsPresent -SkipRevocationCheck:$SkipReovcationCheck.IsPresent -Verbose:$False) -Verbose:$False
117 | $SiteCodeObjects = Get-CimInstance -CimSession $CIMSession -Namespace "Root\SMS" -ClassName SMS_ProviderLocation -ErrorAction Stop
118 |
119 | ForEach ($SiteCodeObject in $SiteCodeObjects) {
120 |
121 | If ($SiteCodeObject.ProviderForLocalSite -eq $True) {
122 |
123 | $SiteCode = $SiteCodeObject.SiteCode
124 | Write-Verbose -Message "Site Code: $($SiteCode)"
125 | Break
126 |
127 | } # End If
128 |
129 | } # End ForEach
130 |
131 | } Catch [System.UnauthorizedAccessException] {
132 |
133 | Throw "[x] Access denied"
134 |
135 | } Catch [System.Exception] {
136 |
137 | Throw "[x] Unable to determine Site Code"
138 |
139 | } # End Try Catch Catch
140 |
141 | If ($SearchBase -notlike "LDAP://*") {
142 |
143 | $SearchBase = "LDAP://$($SearchBase)"
144 |
145 | } # End If
146 |
147 | Try {
148 |
149 | $ContainerData = New-Object -TypeName PSCustomObject -Property @{
150 | DistinguishedName="$($SearchBase)";
151 | Recursive="Yes";
152 | Group="Excluded";
153 | } # End New-Object -Property
154 |
155 | } Catch [System.Exception] {
156 |
157 | Write-Warning -Message "$($_.Exception.Message). Line: $($_.InvocationInfo.ScriptLineNumber)"
158 | Break
159 |
160 | } # End Try Catch
161 |
162 | $OptionTable = @{
163 | Yes = 0
164 | No = 1
165 | Included = 0
166 | Excluded = 1
167 | } # End $OptionTable
168 |
169 | } PROCESS {
170 |
171 | # Determine existing containers for selected Discovery Method
172 | Try {
173 |
174 | $DiscoveryContainerList = New-Object -TypeName System.Collections.ArrayList
175 | $DiscoveryComponent = Get-WmiObject -Class SMS_SCI_Component -Namespace "Root\SMS\Site_$($SiteCode)" -ComputerName $SiteServer -Filter "ComponentName like '$($ComponentName)'" -Credential $Credential -ErrorAction Stop -Verbose:$False
176 | $DiscoveryPropListADContainer = $DiscoveryComponent.PropLists | Where-Object -FilterScript { $_.PropertyListName -like "AD Containers" }
177 |
178 | If ($DiscoveryPropListADContainer.PropertyListName -eq "AD Containers") {
179 |
180 | $DiscoveryContainerList.AddRange(@($DiscoveryPropListADContainer.Values)) | Out-Null
181 |
182 | } # End If
183 |
184 | } Catch [System.Exception] {
185 |
186 | Throw "[x] Unable to determine existing discovery method component properties"
187 |
188 | } # End Catch
189 |
190 |
191 | ForEach ($ContainerItem in $ContainerData) {
192 |
193 | If ($ContainerItem.DistinguishedName -notlike "LDAP://*") {
194 |
195 | $ContainerItem.DistinguishedName = "LDAP://$($ContainerItem.DistinguishedName)"
196 |
197 | } # End If
198 |
199 |
200 | If ($ContainerItem.DistinguishedName -notin $DiscoveryContainerList) {
201 |
202 | Write-Verbose -Message "Adding new container item $($ContainerItem.DistinguishedName)"
203 | $DiscoveryContainerList.AddRange(@($ContainerItem.DistinguishedName, $OptionTable[$ContainerItem.Recursive], $OptionTable[$ContainerItem.Group])) | Out-Null
204 |
205 | } Else {
206 |
207 | Write-Verbose -Message "Detected duplicate container object: $($ContainerItem.DistinguishedName)"
208 |
209 | } # End If Else
210 |
211 | } # End ForEach
212 |
213 | Write-Verbose -Message "Attempting to save changes made to the $($ComponentName) component PropList"
214 | Try {
215 |
216 | $DiscoveryPropListADContainer.Values = $DiscoveryContainerList
217 | $DiscoveryComponent.PropLists = $DiscoveryPropListADContainer
218 | If ($PSCmdlet.ShouldProcess($DiscoveryComponent, '$DiscoveryComponent.Put()')) {
219 |
220 | $DiscoveryComponent.Put() | Out-Null
221 |
222 | } # End If
223 |
224 | } Catch [System.Exception] {
225 |
226 | Throw "[x] Unable to save changes made to $($ComponentName) component"
227 |
228 | } # End Try Catch
229 |
230 |
231 | If ($RestartService.IsPresent) {
232 |
233 | Write-Verbose -Message "Restarting the SMS_SITE_COMPONENT_MANAGER service"
234 | Try {
235 |
236 | Write-Output -InputObject "[*] Restarting the SMS_SITE_COMPONENT_MANAGER service on $SiteServer"
237 | Get-CimInstance -CimSession $CIMSession -ClassName Win32_Service -Filter 'Name = "SMS_SITE_COMPONENT_MANAGER"' -Verbose:$False | Invoke-CimMethod -MethodName StopService -WhatIf:$False -Verbose:$False | Out-Null
238 | Get-CimInstance -CimSession $CIMSession -ClassName Win32_Service -Filter 'Name = "SMS_SITE_COMPONENT_MANAGER"' -Verbose:$False | Invoke-CimMethod -MethodName StartService -WhatIf:$False -Verbose:$False | Out-Null
239 |
240 | } Catch [System.Exception] {
241 |
242 | Write-Warning -Message "$($_.Exception.Message). Line: $($_.InvocationInfo.ScriptLineNumber)"
243 | Break
244 |
245 | } # End Try Catch
246 |
247 | } # End If
248 |
249 | } END {
250 |
251 | If ($CIMSession) {
252 |
253 | Remove-CimSession -CimSession $CIMSession -Confirm:$False -WhatIf:$False -Verbose:$False
254 |
255 | } # End If
256 |
257 | } # End END
258 |
259 | } # End Function Add-CMSystemDiscoveryMethodContainer
260 |
--------------------------------------------------------------------------------
/Clear-GpoRegistrySettings.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to rebuild the registry.pol machine group policy settings
4 |
5 |
6 | .DESCRIPTION
7 | Rename the registry.pol file to rebuild a local machines group policy settings
8 |
9 |
10 | .PARAMETER NewName
11 | Define a location to save the backup of the registry.pol file using this value
12 |
13 | .PARAMETER SkipGpUpdate
14 | Tell the cmdlet to not execute a gpupdate after renaming the registry.pol machine group policy file
15 |
16 |
17 | .EXAMPLE
18 | Clear-GpoRegistrySettings
19 | # This example renames C:\Windows\System32\GroupPolicy\Machine\Registry.pol to C:\Windows\System32\GroupPolicy\Machine\Registry.old and runs a gpupdate
20 |
21 | .EXAMPLE
22 | Clear-GpoRegistrySettings -NewName C:\Windows\System32\GroupPolicy\Machine\Registry.old
23 | # This example renames C:\Windows\System32\GroupPolicy\Machine\Registry.pol to C:\Windows\System32\GroupPolicy\Machine\Registry.old and runs a gpupdate
24 |
25 | .EXAMPLE
26 | Clear-GpoRegistrySettings -SkipGpUpdate
27 | # This example renames C:\Windows\System32\GroupPolicy\Machine\Registry.pol to C:\Windows\System32\GroupPolicy\Machine\Registry.old and does not run a gpupdate
28 |
29 |
30 | .NOTES
31 | Author: Robert H. Osborne
32 | Alias: tobor
33 | Contact: rosborne@osbornepro.com
34 |
35 |
36 | .INPUTS
37 | None
38 |
39 |
40 | .OUTPUTS
41 | None
42 |
43 |
44 | .LINK
45 | https://osbornepro.com
46 | https://btpssecpack.osbornepro.com
47 | https://writeups.osbornepro.com
48 | https://github.com/OsbornePro
49 | https://github.com/tobor88
50 | https://www.powershellgallery.com/profiles/tobor
51 | https://www.hackthebox.eu/profile/52286
52 | https://www.linkedin.com/in/roberthosborne/
53 | https://www.credly.com/users/roberthosborne/badges
54 | #>
55 | Function Clear-GpoRegistrySettings {
56 | [CmdletBinding(SupportsShouldProcess)]
57 | param(
58 | [Parameter(
59 | Position=0,
60 | Mandatory=$False,
61 | ValueFromPipeline=$False)] # End Parameter
62 | [String]$NewName = "C:\Windows\System32\GroupPolicy\Machine\Registry.old",
63 |
64 | [Parameter(
65 | Mandatory=$False)] # End Parameter
66 | [Switch][Bool]$SkipGpUpdate
67 | ) # End param
68 |
69 | $RegPolPath = "C:\Windows\System32\GroupPolicy\Machine\Registry.pol"
70 | If (Test-Path -Path $RegPolPath -ErrorAction SilentlyContinue) {
71 |
72 | If ($PSCmdlet.ShouldProcess($NewName)) {
73 |
74 | Write-Output "[*] $RegPolPath file verified to exist, renaming file"
75 | Move-Item -Path $RegPolPath -Destination $NewName -Force -Confirm:$False -PassThru -ErrorVariable $MoveFailed
76 |
77 | If ($MoveFailed) {
78 |
79 | Write-Ouput "[x] Failed to rename Registry.pol file to $NewName"
80 |
81 | } # End If
82 |
83 | If (Test-ComputerSecureChannel) {
84 |
85 | If (!($SkipGpUpdate.IsPresent)) {
86 |
87 | Write-Output "[*] Performing group policy update"
88 | gpupdate /force
89 |
90 | } # End If
91 |
92 | } Else {
93 |
94 | Throw "[x] $env:COMPUTERNAME : Domain trust failed, group policy update can not be performed"
95 |
96 | } # End If Else
97 |
98 |
99 | } Else {
100 |
101 | # Rename $RegPolPath to $NewName and performs a group policy update
102 | Move-Item -Path $RegPolPath -Destination $NewName -Force -Confirm:$False -PassThru -WhatIf
103 |
104 | } # End If Else
105 |
106 | } Else {
107 |
108 | Write-Error "[x] $RegPolPath file does NOT exist!"
109 |
110 | } # End If Else
111 |
112 | } # End Function Clear-GpoRegistrySettings
113 |
--------------------------------------------------------------------------------
/Example_Report_07.27.2019.txt:
--------------------------------------------------------------------------------
1 | #===================================================================#
2 | # Update Report #
3 | #===================================================================#
4 |
5 | Computer Hostname : DESKTOP
6 |
7 | Creation Date : 07/27/2019 22:24:00
8 |
9 | Report Directory : C:\Windows\Temp\DESKTOP
10 |
11 | ---------------------------------------------------------------------
12 | AVAILABLE UPDATES
13 | ---------------------------------------------------------------------
14 |
15 | 1.) Microsoft Silverlight (KB4481252)
16 | 2.) Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.299.668.0)
17 |
18 | ---------------------------------------------------------------------
19 | INITIALISING UPDATE DOWNLOADS
20 | ---------------------------------------------------------------------
21 |
22 | 1.) Downloading Update: Microsoft Silverlight (KB4481252)
23 |
24 | Download Status: FAILED With Error
25 | Cannot create a file when that file already exists
26 |
27 |
28 | 2.) Downloading Update: Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.299.668.0)
29 |
30 | Download Status: FAILED With Error
31 | A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 207.46.163.74:25
32 |
33 |
34 | ---------------------------------------------------------------------
35 | UPDATE INSTALLATION
36 | ---------------------------------------------------------------------
37 |
38 | 1.) Installing Update: Microsoft Silverlight (KB4481252)
39 |
40 | - Update Installation Status: SUCCESS
41 |
42 | 2.) Installing Update: Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.299.668.0)
43 |
44 | - Update Installation Status: SUCCESS
45 |
46 | #===================================================================#
47 | # END OF REPORT #
48 | #===================================================================#
49 |
--------------------------------------------------------------------------------
/Get-KBDownloadLink.ps1:
--------------------------------------------------------------------------------
1 | Function Get-KBDownloadLink {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to retrieve from the Microsoft Update Catalog, a download link for the Article ID KB number you specify
5 |
6 |
7 | .DESCRIPTION
8 | Retrieves the KB Download link from the Microsoft Update Catalog
9 |
10 |
11 | .PARAMETER ArticleID
12 | Defines the KB identification number you want to retrieve a download link for
13 |
14 | .PARAMETER OperatingSystem
15 | Define the Operating System you want a link for
16 |
17 | .PARAMETER Architecture
18 | Define the architecture of the system you are going to install the update on. Default value is x64
19 |
20 | .PARAMETER VersionInfo
21 | Define the version of Windows 10 or 11 being used
22 |
23 |
24 | .EXAMPLE
25 | Get-KBDownloadLink -ArticleId KB5014692
26 | # This obtains the download link for KB5014692 for the OS version and arhcitecture of the machine this command is executed on
27 |
28 | .EXAMPLE
29 | Get-KBDownloadLink -ArticleId KB5014692 -Architecture "x64" -OperatingSystem 'Windows Server 2019'
30 | # This obtains the download link for KB5014692 for a 64-bit architecture Windows Server 2019 machine
31 |
32 | .EXAMPLE
33 | Get-KBDownloadLink -ArticleId KB5014692 -Architecture "x64" -OperatingSystem 'Windows 10' -VersionInfo '21H1'
34 | # This obtains the download link for KB5014692 for a 64-bit architecture Windows 10 Enterprise version 21H1 machine
35 |
36 |
37 | .INPUTS
38 | None
39 |
40 |
41 | .OUTPUTS
42 | System.String[]
43 |
44 |
45 | .NOTES
46 | Author: Robrt H. Osborne
47 | Alias: tobor
48 | Contact: rosborne@osbornepro.com
49 |
50 |
51 | .LINK
52 | https://github.com/tobor88
53 | https://github.com/osbornepro
54 | https://www.powershellgallery.com/profiles/tobor
55 | https://osbornepro.com
56 | https://writeups.osbornepro.com
57 | https://encrypit.osbornepro.com
58 | https://btpssecpack.osbornepro.com
59 | https://www.powershellgallery.com/profiles/tobor
60 | https://www.hackthebox.eu/profile/52286
61 | https://www.linkedin.com/in/roberthosborne/
62 | https://www.credly.com/users/roberthosborne/badges
63 | #>
64 | [CmdletBinding(DefaultParameterSetName="Server")]
65 | param(
66 | [Parameter(
67 | Position=0,
68 | Mandatory=$True,
69 | ValueFromPipeline=$False,
70 | HelpMessage="Enter the KB number `nEXAMPLE: KB5014692 `nEXAMPLE: 5014692 "
71 | )] # End Parameter
72 | [Alias("Id","Article","KB")]
73 | [String]$ArticleId,
74 |
75 | [Parameter(
76 | Position=1,
77 | Mandatory=$False,
78 | ValueFromPipeline=$False
79 | )] # End Parameter
80 | [ValidateSet("Windows Server 2012 R2", "Windows Server 2016", "Windows Server 2019", "Windows Server 2022", "Windows 10", "Windows 11","SQL Server 2014","SQL Server 2016","SQL Server 2017","SQL Server 2019")]
81 | [String]$OperatingSystem = "$((Get-CimInstance -ClassName Win32_OperatingSystem).Caption.Replace('Microsoft ','').Replace(' Pro','').Replace(' Standard ','').Replace(' Datacenter ',''))",
82 |
83 | [Parameter(
84 | Position=2,
85 | Mandatory=$False,
86 | ValueFromPipeline=$False
87 | )] # End Parameter
88 | [ValidateSet("x64", "x86", "ARM")]
89 | [String]$Architecture,
90 |
91 | [Parameter(
92 | ParameterSetName="Windows10",
93 | Position=3,
94 | Mandatory=$False,
95 | ValueFromPipeline=$False
96 | )] # End Parameter
97 | [Alias('Windows10Version','Windows11Version')]
98 | [String]$VersionInfo
99 | ) # End param
100 |
101 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]'Tls12,Tls13'
102 | $DownloadLink = @()
103 | $UpdateIdResponse = Invoke-WebRequest -Uri "https://www.catalog.update.microsoft.com/Search.aspx?q=$ArticleId" -Method GET -UserAgent 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0' -ContentType 'text/html; charset=utf-8' -UseBasicParsing
104 | $DownloadOptions = ($UpdateIdResponse.Links | Where-Object -Property ID -like "*_link")
105 |
106 | If (!($PSBoundParameters.ContainsKey('Architecture') -and $OperatingSystem -notlike "*SQL*")) {
107 |
108 | $Architecture = "x$((Get-CimInstance -ClassName Win32_OperatingSystem).OSArchitecture.Replace('-bit',''))"
109 |
110 | } # End If
111 |
112 | If ($PSCmdlet.ParameterSetName -eq "Windows10" -and $OperatingSystem -notlike "*SQL*") {
113 |
114 | If (!($PSBoundParameters.ContainsKey('VersionInfo') -and $OperatingSystem -notlike "*SQL*")) {
115 |
116 | $VersionInfo = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name DisplayVersion).DisplayVersion
117 |
118 | } # End If
119 |
120 | Write-verbose -Message "$OperatingSystem link being discovered"
121 | $DownloadOptions = $DownloadOptions | Where-Object -FilterScript { $_.OuterHTML -like "*$($OperatingSystem)*" -and $_.OuterHTML -notlike "*Dynamic*" }
122 | If ($PSBoundParameters.Contains('Architecture')) {
123 |
124 | $DownloadOptions = $DownloadOptions | Where-Object -FilterScript { $_.OuterHTML -like "*$($Architecture)*" }
125 |
126 | } # End If
127 |
128 | } Else {
129 |
130 | Write-verbose -Message "$OperatingSystem link being discovered"
131 | $DownloadOptions = $DownloadOptions | Where-Object -FilterScript { $_.OuterHTML -like "*$($OperatingSystem)*" -and $_.OuterHTML -notlike "*Dynamic*" }
132 | If ($PSBoundParameters.ContainsKey('Architecture') -and $OperatingSystem -notlike "*SQL*") {
133 |
134 | $DownloadOptions = $DownloadOptions | Where-Object -FilterScript { $_.OuterHTML -like "*$($Architecture)*" }
135 |
136 | } # End If
137 |
138 | } # End If Else
139 |
140 | If ($Null -eq $DownloadOptions) {
141 |
142 | Throw "[x] No results were returned using the specified options $OperatingSystem and $Architecture"
143 |
144 | } # End If
145 |
146 | ForEach ($DownloadOption in $DownloadOptions) {
147 |
148 | $Guid = $DownloadOption.id.Replace("_link","")
149 | Write-Verbose -Message "Downloading information for $($ArticleID) $($Guid)"
150 | $Body = @{ UpdateIDs = "[$(@{ Size = 0; UpdateID = $Guid; UidInfo = $Guid } | ConvertTo-Json -Compress)]" }
151 | $LinksResponse = (Invoke-WebRequest -Uri 'https://catalog.update.microsoft.com/DownloadDialog.aspx' -Method POST -Body $Body -UseBasicParsing -SessionVariable WebSession).Content
152 | $DownloadLink += ($LinksResponse.Split("$([Environment]::NewLine)") | Select-String -Pattern 'downloadInformation' | Select-String -Pattern 'url' | Out-String).Trim()
153 | If ($PSBoundParameters.ContainsKey('Architecture') -and $OperatingSystem -like "*SQL*") {
154 |
155 | $DownloadLink = ($DownloadLink | ForEach-Object { $_.Split("$([System.Environment]::NewLine)") } | Where-Object -FilterScript { $_ -like "*$Architecture*" }).Trim().Split("'")[-2]
156 |
157 | } ElseIf ($OperatingSystem -like "*SQL*") {
158 |
159 | $DownloadLink = ($DownloadLink | ForEach-Object { $_.Split("'") } | Where-Object -FilterScript { $_ -like "https://*" }).Split("$([System.Environment]::NewLine)")
160 |
161 | } Else {
162 |
163 | $DownloadLink = ($LinksResponse.Split("$([Environment]::NewLine)") | Select-String -Pattern 'downloadInformation' | Select-String -Pattern 'url' | Out-String).Trim().Split("'")[-2]
164 |
165 | } # End If Else
166 |
167 | } # End ForEach
168 |
169 | Return $DownloadLink
170 |
171 | } # End Function Get-KBDownloadLink
172 |
--------------------------------------------------------------------------------
/Get-MissingDeviceUpdate.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to retrieve a list of updates that are missing from a device
4 |
5 |
6 | .DESCRIPTION
7 | Get all missing or all SCCM approved updates that are missing from device(s) that are remote or local
8 |
9 |
10 | .PARAMETER CompuerName
11 | Define the remote device(s) you want to return missing update information on
12 |
13 | .PARAMETER UseSSL
14 | Create CIM sessions using WinRM over HTTPS
15 |
16 | .PARAMETER CompliantOnly
17 | Used to return only SCCM approved updates that are missing from a device
18 |
19 | .PARAMETER Credential
20 | Enter credentials to remotely establish connections with remote machines using WinRM CIM Sessions
21 |
22 |
23 | .EXAMPLE
24 | Get-MissingDeviceUpdate
25 | # Get all missing updates on the local device
26 |
27 | .EXAMPLE
28 | Get-MissingDeviceUpdate -CompliantOnly
29 | # Get all SCCM approved missing updates
30 |
31 | .EXAMPLE
32 | Get-MissingDeviceUpdate -ComputerName "dc01.domain.com","dhcp.domain.com","fs01.domain.com" -UseSSL -CompliantOnly -Credential $LiveCred
33 | # Get all SCCM Approved missing updates on those remote devices using WinRM over HTTPS to build your CIM sessions
34 |
35 |
36 | .INPUTS
37 | System.String, System.Array
38 |
39 |
40 | .OUTPUTS
41 | PSCustomObject
42 |
43 |
44 | .NOTES
45 | Author: Robert H. Osborne
46 | Alias: tobor
47 | Contact: rosborne@osbornepro.com
48 |
49 |
50 | .LINK
51 | https://github.com/tobor88
52 | https://github.com/OsbornePro
53 | https://www.powershellgallery.com/profiles/tobor
54 | https://osbornepro.com
55 | https://writeups.osbornepro.com
56 | https://btpssecpack.osbornepro.com
57 | https://www.powershellgallery.com/profiles/tobor
58 | https://www.hackthebox.eu/profile/52286
59 | https://www.linkedin.com/in/roberthosborne/
60 | https://www.credly.com/users/roberthosborne/badges
61 | #>
62 | Function Get-MissingDeviceUpdate {
63 | [CmdletBinding(DefaultParameterSetName="Local")]
64 | param(
65 | [Parameter(
66 | ParameterSetName="Remote",
67 | Position=0,
68 | Mandatory=$False,
69 | ValueFromPipelineByPropertyName=$True,
70 | ValueFromPipeline=$True)] # End Parameter
71 | [String[]]$ComputerName = "$env:COMPUTERNAME.$((Get-CimInstance -ClassName Win32_ComputerSystem).Domain)",
72 |
73 | [Parameter(
74 | ParameterSetName="Remote",
75 | Mandatory=$False)] # End Parameter
76 | [Switch][Bool]$UseSSL,
77 |
78 | [Parameter(
79 | Mandatory=$False)] # End Parameter
80 | [Switch][Bool]$CompliantOnly,
81 |
82 | [ValidateNotNull()]
83 | [System.Management.Automation.PSCredential]
84 | [System.Management.Automation.Credential()]
85 | [Parameter(
86 | Mandatory=$True,
87 | ParameterSetName="Remote")]
88 | $Credential = [System.Management.Automation.PSCredential]::Empty
89 | ) # End param
90 |
91 | BEGIN {
92 |
93 | $Return = @()
94 | $NotReachable = @()
95 |
96 | $ConfirmSSL = $False
97 | If ($UseSSL.IsPresent) {
98 |
99 | $ConfirmSSL = $True
100 |
101 | } # End If
102 |
103 | } PROCESS {
104 |
105 | If ($PSCmdlet.ParameterSetName -eq "Remote") {
106 |
107 |
108 | Write-Verbose "Creating CIM Sessions to $ComputerName"
109 | $CIMSession = New-CimSession -ComputerName $ComputerName -SessionOption (New-CimSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -UseSsl:$ConfirmSSL) -Credential $Credential -ErrorAction SilentlyContinue
110 |
111 | $CIMConnections = (Get-CimSession).ComputerName
112 | ForEach ($C in $ComputerName) {
113 |
114 | If ($C -notin $CIMConnections) {
115 |
116 | $NotReachable += $C
117 |
118 | } # End If
119 |
120 | } # End ForEach
121 |
122 | Write-Verbose "Getting all missing updates from $ComputerName"
123 | If ($CompliantOnly.IsPresent) {
124 |
125 | $CCMUpdates = Get-CimInstance -CimSession $CIMSession -NameSpace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate" -Filter "ComplianceState=0" -ErrorAction Continue
126 |
127 | } Else {
128 |
129 | $CCMUpdates = Get-CimInstance -CimSession $CIMSession -Namespace 'Root\CCM\SoftwareUpdates\UpdatesStore' -ClassName CCM_UpdateStatus -ErrorAction Continue | Where-Object -FilterScript { $_.Status -eq "Missing" }
130 |
131 | } # End If Else
132 |
133 | If ($Null -eq $CCMUpdates) {
134 |
135 | Write-Output "[*] All updates are installed on $ComputerName"
136 |
137 | } Else {
138 |
139 | If ($CompliantOnly.IsPresent) {
140 |
141 | $Return += $CCMUpdates | ForEach-Object {
142 |
143 | New-Object -TypeName PSCustomObject -Property @{
144 | ExecutingDevice=$env:COMPUTERNAME;
145 | ComputerName=$_.PSComputerName;
146 | PercentComplete=$_.PercentComplete;
147 | ComplianceState=$_.ComplianceState;
148 | Deadline=$_.Deadline;
149 | Article=$_.ArticleID;
150 | ErrorCode=$_.ErrorCode;
151 | Update=$_.Name;
152 | } # End New-Object -Property
153 |
154 | } # End ForEach-Object
155 |
156 | } Else {
157 |
158 | $Return += $CCMUpdates | ForEach-Object {
159 |
160 | New-Object -TypeName PSCustomObject -Property @{
161 | RunningDevice=$env:COMPUTERNAME;
162 | ComputerName=$_.PSComputerName;
163 | Status=$_.Status;
164 | Article=$_.Article;
165 | Title=$_.Title;
166 | } # End New-Object -Property
167 |
168 | } # End ForEach-Object
169 |
170 | } # End If Else
171 |
172 | } # End If Else
173 |
174 | If ($CIMSession) {
175 |
176 | Write-Verbose "Closing CIM Sessions"
177 | Remove-CimSession -CimSession $CIMSession -Confirm:$False -ErrorAction SilentlyContinue | Out-Null
178 |
179 | } # End If
180 |
181 | } Else {
182 |
183 | Write-Verbose "Getting all missing updates from $ComputerName"
184 | If ($CompliantOnly.IsPresent) {
185 |
186 | $CCMUpdates = Get-CimInstance -NameSpace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate" -Filter "ComplianceState=0" -ErrorAction Continue
187 |
188 | } Else {
189 |
190 | $CCMUpdates = Get-CimInstance -Namespace 'Root\CCM\SoftwareUpdates\UpdatesStore' -ClassName CCM_UpdateStatus -ErrorAction Continue | Where-Object -FilterScript { $_.Status -eq "Missing" }
191 |
192 | } # End If Else
193 |
194 | If ($Null -eq $CCMUpdates) {
195 |
196 | Write-Output "[*] All updates are installed on $ComputerName"
197 |
198 | } Else {
199 |
200 | If ($CompliantOnly.IsPresent) {
201 |
202 | $Return += $CCMUpdates | ForEach-Object {
203 |
204 | New-Object -TypeName PSCustomObject -Property @{
205 | ExecutingDevice=$env:COMPUTERNAME;
206 | ComputerName=$_.PSComputerName;
207 | PercentComplete=$_.PercentComplete;
208 | ComplianceState=$_.ComplianceState;
209 | Deadline=$_.Deadline;
210 | Article=$_.ArticleID;
211 | ErrorCode=$_.ErrorCode;
212 | Update=$_.Name;
213 | } # End New-Object -Property
214 |
215 | } # End ForEach-Object
216 |
217 | } Else {
218 |
219 | $Return += $CCMUpdates | ForEach-Object {
220 |
221 | New-Object -TypeName PSCustomObject -Property @{
222 | RunningDevice=$env:COMPUTERNAME;
223 | ComputerName=$_.PSComputerName;
224 | Status=$_.Status;
225 | Article=$_.Article;
226 | Title=$_.Title;
227 | } # End New-Object -Property
228 |
229 | } # End ForEach-Object
230 |
231 | } # End If Else
232 |
233 | } # End If Else
234 |
235 | If ($CIMSession) {
236 |
237 | Write-Verbose "Closing CIM Sessions"
238 | Remove-CimSession -CimSession $CIMSession -Confirm:$False -ErrorAction SilentlyContinue | Out-Null
239 |
240 | } # End If
241 |
242 | } # End If Else
243 |
244 | } END {
245 |
246 | If ($NotReachable) {
247 |
248 | $NotReachable | ForEach-Object {
249 |
250 | $Return += New-Object -TypeName PSCustomObject -Property @{
251 | RunningDevice=$env:COMPUTERNAME;
252 | ComputerName=$_;
253 | Status="No CIM Session could be created";
254 | Article="NA";
255 | Title="NA";
256 | } # End New-Object -Property
257 |
258 | } # End ForEach-Object
259 |
260 | } # End If
261 |
262 | If ($Null -ne $Return) {
263 |
264 | Return $Return
265 |
266 | } # End If
267 |
268 | } # End B P E
269 |
270 | } # End Function Get-MissingDeviceUpdate
271 |
--------------------------------------------------------------------------------
/Get-SccmSoftwareUpdateStatus.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to return devices and their update deployment results from an SCCM server
4 |
5 |
6 | .DESCRIPTION
7 | Return information on deployment statuses for devices in an SCCM group
8 |
9 |
10 | .PARAMETER SiteCode
11 | The SCCM Site code
12 |
13 | .PARAMETER SiteServer
14 | Defines the SCCM site server FQDN or hostname
15 |
16 | .PARAMETER DeploymentID
17 | Define the deployment by its assignment ID value
18 |
19 | .PARAMETER Status
20 | Specify the results you would like to see returned. Can be Success, InProgress, Error, Unknown, or left blank
21 |
22 | .PARAMETER UseSSL
23 | Specifies the CIM session that gets created should use SSL
24 |
25 | .PARAMETER Credential
26 | Enter your credentials used to connect to the SCCM server when creating the CIM session
27 |
28 |
29 | .EXAMPLE
30 | Get-SccmSoftwareUpdateStatus -SiteCode ABC -SiteServer sccm.osbornepro.com -DeploymentId 16779910 -UseSSL -Credential (Get-Credential)
31 | # This example creates an SSL protected CIM session to an SCCM server and returns the devices with an Error Status
32 |
33 | .EXAMPLE
34 | $DeploymentResults = (Get-CMSoftwareUpdateDeployment | Where-Object -FilterScript { $_.AssignmentName -like "DEV 2022-06-14"}) | ForEach-Object { $_ | Get-CMSoftwareUpdateDeploymentStatus | Where-Object -FilterScript { $_.CollectionName -like "Patch Tuesday" }
35 | FprEach ($D in $DeploymentResults) { Get-SccmSoftwareUpdateStatus -SiteCode 123 -SiteServer sccm.osbornepro.com -UseSSL -DeploymentId $D.AssignmentId -Status Unknown -Credential (Get-Credential) }
36 | # This example gets deployment IDs from SCCM and uses them to return Unknown device status results from the deployment
37 |
38 |
39 | .INPUTS
40 | System.Int
41 |
42 |
43 | .OUTPUTS
44 | PSCustomObject
45 |
46 |
47 | .NOTES
48 | Author: Robrt H. Osborne
49 | Alias: tobor
50 | Contact: rosborne@osbornepro.com
51 |
52 |
53 | .LINK
54 | https://github.com/tobor88
55 | https://github.com/osbornepro
56 | https://www.powershellgallery.com/profiles/tobor
57 | https://osbornepro.com
58 | https://writeups.osbornepro.com
59 | https://btpssecpack.osbornepro.com
60 | https://www.powershellgallery.com/profiles/tobor
61 | https://www.hackthebox.eu/profile/52286
62 | https://www.linkedin.com/in/roberthosborne/
63 | https://www.credly.com/users/roberthosborne/badges
64 | #>
65 | Function Get-SccmSoftwareUpdateStatus {
66 | [CmdletBinding()]
67 | param(
68 | [Parameter(
69 | Position=0,
70 | Mandatory=$True,
71 | ValueFromPipeline=$False,
72 | HelpMessage="Get you SCCM servers Site Code from your SCCM servers \Monitoring\Overview\System Status\Site Status location. EXAMPLE: ABC")] # End Parameter
73 | [String]$SiteCode,
74 |
75 | [Parameter(
76 | Position=1,
77 | Mandatory=$True,
78 | ValueFromPipeline=$False,
79 | HelpMessage="Enter the FQDN of your SCCM server. `nEXAMPLE: sscm-server01.domain.com")] # End Parameter
80 | [String]$SiteServer,
81 |
82 | [Parameter(
83 | Position=3,
84 | Mandatory=$True,
85 | ValueFromPipeline=$True,
86 | ValueFromPipelineByPropertyName=$True,
87 | HelpMessage="Define the deployment ID a.k.a Assignment ID to return results in. `,EXAMPLE: 16779910")] # End Parameter
88 | [Alias('ID', 'AssignmentID')]
89 | [Int32]$DeploymentID,
90 |
91 | [Parameter(
92 | Position=4,
93 | Mandatory=$False,
94 | ValueFromPipeline=$False)] # End Parameter
95 | [ValidateSet('Success', 'InProgress', 'Error', 'Unknown')]
96 | [String]$Status,
97 |
98 | [Parameter(
99 | Mandatory=$False)] # End Parameter
100 | [Switch][Bool]$UseSSL,
101 |
102 | [ValidateNotNull()]
103 | [System.Management.Automation.PSCredential]
104 | [System.Management.Automation.Credential()]
105 | $Credential = [System.Management.Automation.PSCredential]::Empty
106 | ) # End param
107 |
108 | BEGIN {
109 |
110 | If ((Get-PackageProvider -Name Nuget).Version -lt 2.8.5.201) {
111 |
112 | Try {
113 |
114 | Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Confirm:$False
115 |
116 | } Catch {
117 |
118 | Throw $Error
119 |
120 | } # End Try Catch
121 |
122 | } # End If
123 |
124 | $Module = "ConfigurationManager"
125 | If (!(Get-Module -ListAvailable -Name $Module)) {
126 |
127 | Install-Module -Name $Module -Force -Confirm:$False
128 |
129 | } # End If
130 |
131 | $ConfigManagerPath = (Get-Module -Name ConfigurationManager).Path
132 | If (Test-Path -Path $ConfigManagerPath) {
133 |
134 | Import-Module -Name $ConfigManagerPath
135 | Set-Location -Path "$env:SMS_ADMIN_UI_PATH\..\"
136 | New-PSDrive -Name "$($SiteCode)" -PSProvider "CMSite" -Root "$SiteServer" -Description "$SiteCode SCCM Site" | Out-Null
137 | Set-Location -Path "$($SiteCode):\"
138 |
139 | } Else {
140 |
141 | Throw "[x] ConfigurationManager PowerShell module not available on this device"
142 |
143 | } # End If Else
144 |
145 | Switch ($Status) {
146 |
147 | 'Success' { $StatusType = 1 }
148 | 'InProgress' { $StatusType = 2 }
149 | 'Unknown' { $StatusType = 4 }
150 | 'Error' { $StatusType = 5 }
151 |
152 | } # End Switch
153 |
154 | $Confirm = $False
155 | If ($UseSSL.IsPresent) {
156 |
157 | $Confirm = $True
158 |
159 | } # End If
160 |
161 | $FilterDate = Get-Date -Date $FilterDate -Format yyyy-MM-dd
162 |
163 | } PROCESS {
164 |
165 | Write-Verbose "Creating CIM session to $SiteServer"
166 | $CIMSession = New-CimSession -ComputerName $SiteServer -Credential $Credential -SessionOption (New-CimSessionOption -UseSsl:$Confirm) -ErrorAction Stop
167 |
168 | If ($Status) {
169 |
170 | $Results = Get-CimInstance -CimSession $CIMSession -ClassName SMS_SUMDeploymentAssetDetails -Namespace root\sms\site_$SiteCode -Filter "AssignmentID = $DeploymentID and StatusType = $StatusType"
171 | $Return = $Results | ForEach-Object {
172 |
173 | New-Object -TypeName PSCustomObject -Property @{
174 | DeploymentName=$($_.AssignmentName | Select-Object -Unique);
175 | AssignmentId=$($_.AssignmentId | Select-Object -Unique);
176 | DeviceName=$($_.DeviceName);
177 | CollectionName=$($_.CollectionName);
178 | StatusTime=$(Get-Date -Date ($_.StatusTime));
179 | Status=$(If ($_.StatusType -eq 1) {'Success'} ElseIf ($_.StatusType -eq 2) {'InProgress'} ElseIf ($_.StatusType -eq 5) {'Error'} ElseIf ($_.StatusType -eq 4) {'Unknown'})
180 | } # End New-Object Properties
181 |
182 | } # End ForEach-Object
183 |
184 | } Else {
185 |
186 | $Results = Get-CimInstance -ComputerName $SiteServer -ClassName SMS_SUMDeploymentAssetDetail -Namespace root\sms\site_$SiteCode -Filter "AssignmentID = $DeploymentID"
187 | $Return = $Results | ForEach-Object {
188 |
189 | New-Object -TypeName PSCustomObject -Property @{
190 | DeploymentName=$($_.AssignmentName | Select-Object -Unique);
191 | AssignmentId=$($_.AssignmentId | Select-Object -Unique);
192 | DeviceName=$_.DeviceName;
193 | CollectionName=$_.CollectionName;
194 | StatusTime=$($_.ConvertToDateTime($_.StatusTime));
195 | Status=$(If ($_.StatusType -eq 1) {'Success'} ElseIf ($_.StatusType -eq 2) {'InProgress'} ElseIf ($_.StatusType -eq 5) {'Error'} ElseIf ($_.StatusType -eq 4) {'Unknown'})
196 | } # End New-Object Properties
197 |
198 | } # End ForEach-Object
199 |
200 | } # End If Else
201 |
202 | If ($Null -eq $Results) {
203 |
204 | Throw "[x] Deployment ID $($DeploymentID) was not found to exist"
205 |
206 | } # End If
207 |
208 | } END {
209 |
210 | If ($Return) {
211 |
212 | Write-Verbose "Closing CIM Session Connection"
213 | Remove-CimSession -CimSession $CIMSession -Confirm:$False
214 |
215 | Return $Return
216 |
217 | } Else {
218 |
219 | Write-Output "[i] No results returned"
220 |
221 | } # End If Else
222 |
223 | } # End B P E
224 |
225 | } # End Get-SccmSoftwareUpdateStatus
226 |
--------------------------------------------------------------------------------
/Get-UpdateHistory.ps1:
--------------------------------------------------------------------------------
1 | Function Get-UpdateHistory {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to return information on the history of Windows Updates
5 |
6 |
7 | .DESCRIPTION
8 | Return a list of installed updates on local or remote devices
9 |
10 |
11 | .PARAMETER ComputerName
12 | Define computer(s) to remotely return the Windows Update history of
13 |
14 |
15 | .EXAMPLE
16 | "DC01.domain.com","DHCP.domain.com" | Get-WUHistory
17 | # Return information on Windows Update history for remote devices
18 |
19 |
20 | .EXAMPLE
21 | Get-WUHistory
22 | # Return information on Windows Updates that were installed and how
23 |
24 |
25 | .NOTES
26 | Author: Robert Osborne
27 | Contact: rosborne@advisor360.com, rosborne@vinebrooktech.com
28 |
29 |
30 | .LINK
31 | https://vinebrooktech.com
32 |
33 |
34 | .INPUTS
35 | System.String[]
36 |
37 |
38 | .OUTPUTS
39 | PSCustonObject
40 | #>
41 | [OutputType('PSWindowsUpdate.WUHistory')]
42 | [CmdletBinding(
43 | SupportsShouldProcess=$True,
44 | ConfirmImpact="Low")]
45 | param(
46 | [Parameter(
47 | Position=0,
48 | Mandatory=$False,
49 | ValueFromPipeline=$True,
50 | ValueFromPipelineByPropertyName=$True)] # End Parameter
51 | [ValidateScript({Test-Connection -CompuerName $env:COMPUTERNAME -Count 2 -BufferSize 32 -Quiet})]
52 | [String[]]$ComputerName = $env:COMPUTERNAME
53 | ) # End param
54 |
55 | BEGIN {
56 |
57 | $UpdateCollection = @()
58 |
59 | } PROCESS {
60 |
61 | ForEach ($Computer in $ComputerName) {
62 |
63 | Write-Verbose "Building Windows Update history list"
64 |
65 | If ($PSCmdlet.ShouldProcess($Computer,"Get updates history")) {
66 |
67 | Write-Verbose -Message "Getting updates history for $Computer"
68 | If ($Computer -like $env:COMPUTERNAME) {
69 |
70 | Write-Verbose -Message "Creating Microsoft.Update.Session object for local device $Computer"
71 | $Session = New-Object -ComObject Microsoft.Update.Session
72 |
73 | } Else {
74 |
75 | Write-Verbose -Message "Creating update session for remote device $Computer"
76 | $Session = [Activator]::CreateInstance([Type]::GetTypeFromProgID("Microsoft.Update.Session",$Computer))
77 |
78 | } # End If Else
79 |
80 | Write-Verbose -Message "Creating update searcher for $Computer"
81 | $Searcher = $Session.CreateUpdateSearcher()
82 | $TotalHistoryCount = $Searcher.GetTotalHistoryCount()
83 |
84 | If($TotalHistoryCount -gt 0) {
85 |
86 | $History = $Searcher.QueryHistory(0, $TotalHistoryCount)
87 | $NumberOfUpdate = 1
88 | Foreach($H in $History) {
89 |
90 | Write-Verbose -Message "Searching $($NumberOfUpdate)/$($TotalHistoryCount) $($H.Title) `nUPDATE: $($H.Title)"
91 |
92 | $Matches = $Null
93 | $H.Title -match "KB(\d+)" | Out-Null
94 |
95 | If($Matches -eq $Null) {
96 |
97 | Add-Member -InputObject $H -MemberType NoteProperty -Name KB -Value ""
98 |
99 | } Else {
100 |
101 | Add-Member -InputObject $H -MemberType NoteProperty -Name KB -Value ($matches[0])
102 |
103 | } # End If Else
104 |
105 | Add-Member -InputObject $H -MemberType NoteProperty -Name ComputerName -Value $Computer
106 | Switch ($H.ResultCode) {
107 |
108 | '1' { $Result = "In Progress" }
109 |
110 | '2' { $Result = "Succeeded" }
111 |
112 | '3' { $Result = "Succeeded with Errors" }
113 |
114 | '4' { $Result = "Failed" }
115 |
116 | '5' { $Result = "Aborted" }
117 |
118 | } # End Switch
119 | Add-Member -InputObject $H -MemberType NoteProperty -Name Result -Value $Result
120 |
121 | $H.PSTypeNames.Clear()
122 | $H.PSTypeNames.Add('PSWindowsUpdate.WUHistory')
123 |
124 | $UpdateCollection += $H
125 | $NumberOfUpdate++
126 |
127 | } # End Foreach
128 |
129 | } Else {
130 |
131 | Write-Warning "Update history was likely cleared. No results could be returned"
132 |
133 | } # End If Else
134 |
135 | } # End If
136 |
137 | } # End Foreach
138 |
139 | } END {
140 |
141 | Return $UpdateCollection
142 |
143 | } # End BPE
144 |
145 | } # End Function Get-UpdateHistory
146 |
--------------------------------------------------------------------------------
/Get-WindowsUpdateError.ps1:
--------------------------------------------------------------------------------
1 | Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force -Confirm:$False
2 | Write-Output "[*] Building update log file, please wait as this may take a up to a minute to complete."
3 | $Job = Start-Job -ScriptBlock { Get-WindowsUpdateLog -ErrorVariable ErrorVariable }
4 | $Job | Wait-Job | Remove-Job
5 |
6 |
7 | Write-Output "[*] Verifying log was updated today"
8 | If ($env:OneDrive) {
9 |
10 | $UpdateLog = "$env:OneDrive\Desktop\WindowsUpdate.log"
11 |
12 | } Else {
13 |
14 | $UpdateLog = "$env:USERPROFILE\Desktop\WindowsUpdate.log"
15 |
16 | } # End If Else
17 |
18 |
19 | Write-Output "[*] Verifying update log was last written too today"
20 | [datetime]$Today = Get-Date
21 | $FileProperties = Get-ChildItem -Path $UpdateLog
22 | If ((Test-Path -Path $UpdateLog) -and ($FileProperties.LastWriteTime.ToShortDateString() -eq ($Today).ToShortDateString())) {
23 |
24 | Write-Output "[*] Successfully created Windows Update log file"
25 | $Pattern = 'ERROR'
26 | $ErrorLog = $UpdateLog.Replace("WindowsUpdate.log","WindowsError.log")
27 | Get-Content -Path $UpdateLog | Select-String -Pattern $Pattern | Out-File -FilePath $ErrorLog
28 | $ErrorLogContents = Get-Content -Path $ErrorLog
29 |
30 | Do {
31 |
32 | $Answer = Read-Host -Prompt "Would you like to view errors from the last 24 hours or the Week? [t/w]"
33 | If ($Answer -like "t*") {
34 |
35 | $WriteLine = @()
36 | ForEach ($Line in $ErrorLogContents) {
37 |
38 | If ($Line -NotLike "*succeeded with errors = 0*" -and $Line -NotLike "*and error 0") {
39 |
40 | Write-Verbose "Checking for entires in the last 24 hours"
41 | Try {
42 |
43 | [datetime]$CheckDate = ($Line.ToCharArray() | Select-Object -First 19 ) -Join ''
44 | If (($Null -ne $CheckDate) -and ($CheckDate -gt $Today.AddHours(-24))) {
45 |
46 | $WriteLine += $Line
47 |
48 | } # End If
49 |
50 | } Catch {
51 |
52 | Continue
53 |
54 | } # End Try Catch
55 |
56 | } # End If
57 |
58 | } # End ForEach
59 |
60 | If (!$WriteLine) {
61 |
62 | Write-Host "SUCCESS! No Windows Update errors over the last 24 hours" -ForegroundColor Green
63 |
64 | } Else {
65 |
66 | $WriteLine
67 | $Answer = Read-Host -Prompt "Based on the error messages above, should we run the Windows Update Troubleshooter? [y/N]"
68 | If ($Answer -like "y*") {
69 |
70 | Get-TroubleshootingPack -Path "C:\Windows\Diagnostics\System\WindowsUpdate" | Invoke-TroubleshootingPack -Result "C:\DiagResult"
71 | Write-Output "[*] Troubleshooter results saved to C:\DiagResult"
72 |
73 | } # End If
74 |
75 | $RunUpdate = Read-Host -Prompt "Would you like to try updating Windows again now? [y/N]"
76 | If ($RunUpdate -like "y*") {
77 |
78 | Write-Output "[*] Running Windows Update"
79 | $Updates = Start-WUScan -SearchCriteria "Type='Software' AND IsInstalled=0"
80 | If ($Updates) {
81 |
82 | Install-WUUpdates -Updates $Updates
83 |
84 | } Else {
85 |
86 | Write-Host "Hooray! No more Windows Updates to install" -ForegroundColor Green
87 |
88 | } # End Else
89 |
90 | } # End If
91 |
92 | } # End If Else
93 |
94 | } ElseIf ($Answer -like "w*") {
95 |
96 | $WriteLine = @()
97 | ForEach ($Line in $ErrorLogContents) {
98 |
99 | If ($Line -NotLike "*succeeded with errors = 0*" -and $Line -NotLike "*and error 0") {
100 |
101 | Write-Verbose "Checking all the Windows Update error log entries"
102 | $WriteLine += $Line
103 |
104 | } # End If
105 |
106 | } # End ForEach
107 |
108 | If (!$WriteLine) {
109 |
110 | Write-Host "SUCCESS! No Windows Update errors over the last 24 hours" -ForegroundColor Green
111 |
112 | } Else {
113 |
114 | $WriteLine + "`n"
115 | $Answer = Read-Host -Prompt "Based on the error messages above, should we run the Windows Update Troubleshooter? [y/N]"
116 | If ($Answer -like "y*") {
117 |
118 | Get-TroubleshootingPack -Path "C:\Windows\Diagnostics\System\WindowsUpdate" | Invoke-TroubleshootingPack -Result "C:\DiagResult"
119 | Write-Output "[*] Troubleshooter results saved to C:\DiagResult"
120 |
121 | } # End If
122 |
123 | $RunUpdate = Read-Host -Prompt "Would you like to try updating Windows again now? [y/N]"
124 | If ($RunUpdate -like "y*") {
125 |
126 | Write-Output "[*] Running Windows Update"
127 | $Updates = Start-WUScan -SearchCriteria "Type='Software' AND IsInstalled=0"
128 | If ($Updates) {
129 |
130 | Install-WUUpdates -Updates $Updates
131 |
132 | } Else {
133 |
134 | Write-Host "Hooray! No more Windows Updates to install" -ForegroundColor Green
135 |
136 | } # End Else
137 |
138 |
139 | } # End If
140 |
141 | Write-Output "[*] Script Execution Complete"
142 |
143 | } # End If Else
144 |
145 | } Else {
146 |
147 | Write-Output "You just had to be difficult :) Lets try again"
148 |
149 | } # End If ElseIf Else
150 |
151 | } Until ($Answer -like "t*" -or $Answer -like "w*") # End Do Until
152 |
153 | } Else {
154 |
155 | Write-Output "[x] Failed to create Windows Update log file"
156 | Throw "$ErrorVariable"
157 |
158 | } # End If Else
159 |
--------------------------------------------------------------------------------
/Get-WindowsUpdateErrorCode.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to return the error code that caused a windows update to fail.
4 |
5 |
6 | .DESCRIPTION
7 | Return the error codes that contains information on a failed Windows or SCCM update
8 |
9 |
10 | .PARAMETER Path
11 | Define the log file or directory containing log files to search for error codes in. Accepts wildcard values
12 |
13 | .PARAMETER Date
14 | Define the date to use when searching a collection of C:\Windows\CCM\Log files for SCCM error codes. This parameter can not be used in conjunction with -Path and is for searching SCCM logs
15 |
16 | .PARAMETER All
17 | Return every error code found in the log files instead of the latest unique values only
18 |
19 |
20 | .EXAMPLE
21 | Get-WindowsUpdateErrorCode
22 | # Generates a Windows Update log file and saves it to the running users desktop and returns the error code for the failed updates
23 |
24 | .EXAMPLE
25 | Get-WindowsUpdateErrorCode -Path C:\Windows\Temp\Custom.log -All
26 | # Searches the log file Custom.log for error codes and returns everyone one of them
27 |
28 | .EXAMPLE
29 | Get-WindowsUpdateErrorCode -Date (Get-Date).AddDays(-3)
30 | # Searches all log files in C:\Windows\CCM\Log that have the date from 3 days ago in the log files name
31 |
32 |
33 | .NOTES
34 | Author: Robert H. Osborne
35 | Alias: tobor
36 | Contact: rosborne@osbornepro.com
37 |
38 |
39 | .LINK
40 | https://github.com/tobor88
41 | https://github.com/osbornepro
42 | https://gitlab.com/tobor88
43 | https://osbornepro.com
44 | https://writeups.osbornepro.com
45 | https://btpssecpack.osbornepro.com
46 | https://www.powershellgallery.com/profiles/tobor
47 | https://www.hackthebox.eu/profile/52286
48 | https://www.credly.com/users/roberthosborne/badges
49 | https://www.linkedin.com/in/roberthosborne/
50 |
51 |
52 | .INPUTS
53 | None
54 |
55 |
56 | .OUTPUTS
57 | System.String
58 | #>
59 | Function Get-WindowsUpdateErrorCode {
60 | [CmdletBinding()]
61 | param(
62 | [Parameter(
63 | ParameterSetName="File",
64 | Position=0,
65 | Mandatory=$True,
66 | ValueFromPipeline=$True,
67 | HelpMessage="Define the path to log files. Wildcards are accepted EXAMPLE: C:\Windows\CCM\Logs\*202205*.log")] # End Parameter
68 | [SupportsWildcards()]
69 | [String]$Path,
70 |
71 | [Parameter(
72 | ParameterSetName="SCCM",
73 | Position=0,
74 | Mandatory=$False,
75 | ValueFromPipeline=$False
76 | #HelpMessage="Enter the date of the log files you are checking for errors on. `nEXAMPLE: Get-Date -Date 6/14/2022 `nEXAMPLE: (Get-Date).AddDays(-7)"
77 | )] # End Parameter
78 | [DateTime]$Date = (Get-Date),
79 |
80 | [Parameter(
81 | Mandatory=$False)]
82 | [Switch][Bool]$All
83 | ) # End param
84 |
85 | If ($PSCmdlet.ParameterSetName -eq "SCCM") {
86 |
87 | $Month = $Date.Month.ToString("00")
88 | $Year = $Date.Year.ToString("0000")
89 | $Day = $Date.Day.ToString("00")
90 |
91 | $Path = "C:\Windows\CCM\Logs\*$($Year)$($Month)$($Day)*.log"
92 |
93 | } # End If
94 |
95 | If (Test-Path -Path $Path -ErrorAction SilentlyContinue) {
96 |
97 | Write-Verbose "Successfully created Windows Update log file"
98 | [regex]$Pattern = '0x8(.*){5,20}'
99 |
100 | $Results = Select-String -Pattern $Pattern -Path $Path -AllMatches | Where-Object -FilterScript { $_ -notlike "*HRESULT = `"0x00000000`";*" -and $_ -notlike "*0x0,*"} | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value }
101 | $CodeFilter = @()
102 | ForEach ($Line in $Results) {
103 |
104 | $Code = Try { (($Line | Out-String).Substring(0,10) | Select-String -Pattern $Pattern | Out-String).Trim() } Catch { Continue }
105 |
106 | If ($All.IsPresent) {
107 |
108 | $TimeFilter = Try { ($Line | Out-String).Split("=")[1].Split(" ")[0].Replace('"','').Split(".")[0] } Catch { "Error" }
109 | $DateFilter = Try { ($Line | Out-String).Split("=")[2].Split(" ")[0].Replace('"','') } Catch { Continue }
110 | $ComponentFilter = Try { ($Line | Out-String).Split("=")[3].Split(" ")[0].Replace('"','') } Catch { Continue }
111 | If ($ComponentFilter) { Try { $Description = Get-ComponentDescription -Name $ComponentFilter } Catch { $Description = "No translation available. Update Get-ComponentDescription" } }
112 |
113 | $CodeFilter += New-Object -TypeName PSCustomObject -Property @{ErrorCode=$Code;Date=$DateFilter;Time=$TimeFilter;Log=$ComponentFilter;LogDesc=$Description}
114 |
115 | } ElseIf ($Code -notin $CodeFilter.ErrorCode) {
116 |
117 | $Line = (($Results | Select-String -Pattern $Code)[-1] | Out-String).Trim()
118 | $TimeFilter = Try { ($Line | Out-String).Split("=")[1].Split(" ")[0].Replace('"','').Split(".")[0] } Catch { "Error" }
119 | $DateFilter = Try { ($Line | Out-String).Split("=")[2].Split(" ")[0].Replace('"','') } Catch { Continue }
120 | $ComponentFilter = Try { ($Line | Out-String).Split("=")[3].Split(" ")[0].Replace('"','') } Catch { Continue }
121 | If ($ComponentFilter) { Try { $Description = Get-ComponentDescription -Name $ComponentFilter } Catch { $Description = "No translation available. Update Get-ComponentDescription" } }
122 |
123 | $CodeFilter += New-Object -TypeName PSCustomObject -Property @{ErrorCode=$Code;Date=$DateFilter;Time=$TimeFilter;Log=$ComponentFilter;LogDesc=$Description}
124 |
125 | } # End If ElseIf
126 |
127 | } # End ForEach
128 |
129 | If (-Not $All.IsPresent) {
130 |
131 | Write-Verbose "Selecting unique error codes"
132 | $Results = $CodeFilter | Sort-Object -Unique -Property ErrorCode
133 |
134 | } Else {
135 |
136 | Write-Verbose "Selecting all error codes"
137 | $Results = $CodeFilter
138 |
139 | } # End If Else
140 |
141 | If (!$Results) {
142 |
143 | Write-Output "[*] SUCCESS! No Windows Update errors on $($Date.ToShortDateString())"
144 |
145 | } Else {
146 |
147 | If ($Null -ne $CodeFilter) {
148 |
149 | Return $Results
150 |
151 | } Else {
152 |
153 | Write-Output "[i] No error codes found in the windows update logs"
154 |
155 | } # End If Else
156 |
157 | } # End If Else
158 |
159 | } Else {
160 |
161 | Write-Error "[x] No log files in the location specified: $Path"
162 |
163 | } # End If Else
164 |
165 | } # End Function Get-WindowsUpdateErrorCode
166 |
--------------------------------------------------------------------------------
/Install-7Zip.ps1:
--------------------------------------------------------------------------------
1 | Function Install-7Zip {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update 7Zip for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates 7Zip installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 7/25/2023 due to 1.3 being so new
19 |
20 | .EXAMPLE
21 | PS> Install-7Zip
22 | # This example downloads the 7Zip installer and verifies the checksum before installing it
23 |
24 |
25 | .EXAMPLE
26 | PS> Install-7Zip -OutFile "$env:TEMP\7zip-installer.msi"
27 | # This example downloads the 7Zip installer and installs it
28 |
29 | .EXAMPLE
30 | PS> Install-7Zip -OutFile "$env:TEMP\7zip-installer.msi" -DownloadOnly
31 | # This example downloads the 7Zip installer
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding(DefaultParameterSetName="Installer")]
63 | param(
64 | [Parameter(
65 | Mandatory=$False
66 | )] # End Parameter
67 | [ValidateScript({$_ -like "*.exe"})]
68 | [String]$OutFile = "$env:TEMP\7zip-installer.exe",
69 |
70 | [Parameter(
71 | Mandatory=$False
72 | )] # End Parameter
73 | [ValidateSet('32','64')]
74 | [String]$Architecture = "64",
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$DownloadOnly,
80 |
81 | [Parameter(
82 | Mandatory=$False
83 | )] # End Parameter
84 | [Switch]$TryTLSv13
85 | ) # End param
86 |
87 | $TlsVersion = "TLSv1.2"
88 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
89 | If ($TryTLSv13.IsPresent) {
90 |
91 | $TlsVersion = "TLSv1.3"
92 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
93 |
94 | } # End If
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
96 |
97 | $MainUrl = "https://www.7-zip.org/download.html"
98 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
99 |
100 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Obtaining latest version information for 7Zip"
101 | $Version = ((Invoke-WebRequest -UseBasicParsing -Uri $MainUrl -UserAgent $UserAgent -Method GET -ContentType 'text/html' -Verbos:$False).Links | Where-Object -FilterScript { $_.outerHTML -like "*7z*64.exe`">Download<*" } | Select-Object -First 1 -ExpandProperty href).Split('z')[1].Split('-')[0]
102 | Switch ($Architecture) {
103 |
104 | '32' { $DownloadLink = "https://www.7-zip.org/a/7z$($Version).exe" }
105 |
106 | '64' { $DownloadLink = "https://www.7-zip.org/a/7z$($Version)-x64.exe" }
107 |
108 | } # End Switch
109 |
110 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading 7zip"
111 | Invoke-WebRequest -UseBasicParsing -Uri $DownloadLink -UserAgent $UserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False -ErrorAction Stop | Out-Null
112 |
113 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
114 |
115 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') File saved to $OutFile"
116 |
117 | } Else {
118 |
119 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of 7zip version $Version"
120 | Start-Process -FilePath $OutFile -ArgumentList @("/S") -NoNewWindow -Wait -PassThru -ErrorAction Stop
121 |
122 | } # End If Else
123 |
124 | } # End Function Install-7Zip
125 |
--------------------------------------------------------------------------------
/Install-AzureCli.ps1:
--------------------------------------------------------------------------------
1 | Function Install-AzureCli {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update AzureCli for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates AzureCli installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-AzureCli
23 | # This example downloads the AzureCli installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-AzureCli -OutFile "$env:TEMP\AzureCli-Setup.exe"
27 | # This example downloads the AzureCli installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-AzureCli -OutFile "$env:TEMP\AzureCli-Setup.exe" -DownloadOnly
31 | # This example downloads the AzureCli installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.msi"})]
69 | [String]$OutFile = "$env:TEMP\azure-cli-version.msi",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
93 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Azure CLI from GitHub"
94 | Try {
95 |
96 | $DownloadLink = 'https://aka.ms/installazurecliwindows'
97 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -Verbose:$False | Out-Null
98 |
99 | } Catch {
100 |
101 | Throw $Error[0]
102 |
103 | } # End Try Catch Catch
104 |
105 | Write-Warning -Message "[!] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') I have not been able to find a checksum for the Azure CLI installer file"
106 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
107 |
108 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file for Azure CLI.`n[i] File saved to $OutFile"
109 |
110 | } Else {
111 |
112 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Microsoft Azure CLI for Windows"
113 | If (Test-Path -Path $OutFile) {
114 |
115 | Start-Process -FilePath "C:\Windows\System32\msiexec.exe" -ArgumentList @('/i', "$OutFile", '/quiet') -NoNewWindow -Wait -PassThru -ErrorAction Stop
116 |
117 | } Else {
118 |
119 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to download file for Azure CLI"
120 |
121 | } # End If Else
122 |
123 | } # End If Else
124 |
125 | } # End FunctionInstall-AzureCli
126 |
--------------------------------------------------------------------------------
/Install-AzureStorageExplorer.ps1:
--------------------------------------------------------------------------------
1 | Function Install-AzureStorageExplorer {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Azure Storage Explorer for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Azure Storage Explorer installed for Windows. I have not found a checksum to verify the hash
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 4/26/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-AzureStorageExplorer
23 | # This example downloads the Azure Storage Explorer installer. I have not found a check to verify the hash before installing it
24 |
25 | .EXAMPLE
26 | Install-AzureStorageExplorer -OutFile "$env:TEMP\Windows_StorageExplorer.exe"
27 | # This example downloads the Azure Storage Explorer installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-AzureStorageExplorer -OutFile "$env:TEMP\Windows_StorageExplorer.exe" -DownloadOnly
31 | # This example downloads the Azure Storage Explorer installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "C:\Windows\Temp\Windows_StorageExplorer.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
93 | $Uri = "https://api.github.com/repos/Microsoft/AzureStorageExplorer/releases/latest"
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Azure Storage Explorer from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $DownloadLink = ($GetLinks.assets | Where-Object -FilterScript { $_.Name -like "Windows-StorageExplorer.exe"}).browser_download_url
100 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
109 |
110 | Write-Warning -Message "[!] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') I have not found a checksum value online to compare for Azure Storage Explorer"
111 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file for Azure Storage Explorer.`n[i] File saved to $OutFile"
112 |
113 | } Else {
114 |
115 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Windows Azure Storage Explorer for Windows"
116 | Start-Process -FilePath $OutFile -ArgumentList @('/VERYSILENT', '/NORESTART', '/ALLUSERS') -NoNewWindow -Wait -PassThru -ErrorAction Stop
117 |
118 | } # End If Else
119 |
120 | } # End Function Install-AzureStorageExplorer
121 |
--------------------------------------------------------------------------------
/Install-CherryTree.ps1:
--------------------------------------------------------------------------------
1 | Function Install-CherryTree {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update CherryTree for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates CherryTree installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-CherryTree
23 | # This example downloads the CherryTree installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-CherryTree -OutFile "$env:TEMP\CherryTreeClientx64.exe"
27 | # This example downloads the CherryTree installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-CherryTree -OutFile "$env:TEMP\CherryTreeClientx64.exe" -DownloadOnly
31 | # This example downloads the CherryTree installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\cherrytree-version_win64_setup.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = "https://api.github.com/repos/giuspen/cherrytree/releases/latest"
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading CherryTree from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $DownloadLink = ($GetLinks.assets | Where-Object -Property Name -like "cherrytree_*_win64_setup.exe").browser_download_url
100 |
101 | } Catch {
102 |
103 | Throw $Error[0]
104 |
105 | } # End Try Catch Catch
106 |
107 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading CherryTree"
108 | Invoke-WebRequest -UseBasicParsing -Uri $DownloadLink -UserAgent $UserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
109 |
110 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting hash values for CherryTree"
111 | $Version = (Get-Item -Path $OutFile).VersionInfo.ProductVersion
112 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
113 | $CheckSum = ((Invoke-WebRequest -UseBasicParsing -Uri "https://www.giuspen.net/cherrytree/#downl" -UserAgent $UserAgent -ContentType 'text/html; charset=UTF-8' -Verbose:$False).RawContent.Split("`n") | Select-String -Pattern "cherrytree_$($Version.Trim())_win64_setup.exe" | Out-String).Split(" ")[-3].Split('>')[-1].Trim()
114 |
115 | If ($CheckSum -eq $FileHash) {
116 |
117 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for CherryTree version $Version"
118 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
119 |
120 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
121 |
122 | } Else {
123 |
124 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of CherryTree version $Version"
125 | Move-Item -Path $OutFile -Destination $OutFile.Replace("version", $Version) -Force -Confirm:$False
126 | Start-Process -FilePath $OutFile.Replace("version", $Version) -ArgumentList @('/VERYSILENT') -NoNewWindow -Wait -PassThru
127 |
128 | } # End If Else
129 |
130 | } Else {
131 |
132 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for CherryTree version $Version"
133 |
134 | } # End If Else
135 |
136 | } # End Function Install-CherryTree
137 |
--------------------------------------------------------------------------------
/Install-DrawIO.ps1:
--------------------------------------------------------------------------------
1 | Function Install-DrawIO {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Draw.IO for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Draw.IO installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-DrawIO
23 | # This example downloads the Draw.IO installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-DrawIO -OutFile "$env:TEMP\Draw.IOClientx64.exe"
27 | # This example downloads the Draw.IO installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-DrawIO -OutFile "$env:TEMP\Draw.IOClientx64.exe" -DownloadOnly
31 | # This example downloads the Draw.IO installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\draw.io-version-windows-installer.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = 'https://api.github.com/repos/jgraph/drawio-desktop/releases/latest'
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting download link for DrawIO from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $DownloadLink = ($GetLinks.assets | Where-Object -Property Name -like "draw.io-*-windows-installer.exe").browser_download_url
100 | $CheckSumLink = ($GetLinks.assets | Where-Object -FilterScript { $_.Name -like "Files-SHA256-Hashes.txt" }).browser_download_url
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Draw.IO"
109 | Invoke-WebRequest -UseBasicParsing -Uri $DownloadLink -UserAgent $UserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
110 |
111 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting hash values for Draw.IO"
112 | $Version = (Get-Item -Path $OutFile).VersionInfo.ProductVersion
113 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
114 | $CheckSum = ((Invoke-WebRequest -UseBasicParsing -Uri $CheckSumLink -UserAgent $UserAgent -ContentType 'application/octet-stream' -Method GET -Verbose:$False).RawContent.Split("`n") | Where-Object -FilterScript { $_ -like "draw.io-$($Version.Trim())-windows-installer.exe *"}).Split(' ')[-1]
115 |
116 | If ($CheckSum -eq $FileHash) {
117 |
118 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Draw.IO version $Version"
119 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
120 |
121 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
122 |
123 | } Else {
124 |
125 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Draw.IO version $Version"
126 | Move-Item -Path $OutFile -Destination $OutFile.Replace("version", $Version) -Force -Confirm:$False
127 | Start-Process -FilePath $OutFile.Replace("version", $Version) -ArgumentList @('/S') -NoNewWindow -Wait -PassThru
128 |
129 | } # End If Else
130 |
131 | } Else {
132 |
133 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for Draw.IO version $Version"
134 |
135 | } # End If Else
136 |
137 | } # End Function Install-DrawIO
138 |
--------------------------------------------------------------------------------
/Install-FileZilla.ps1:
--------------------------------------------------------------------------------
1 | Function Install-FileZilla {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update FileZilla Client for Windows on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates FileZilla Client installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-FileZilla
23 | # This example downloads the FileZilla installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-FileZilla -OutFile "$env:TEMP\FilezillaClientx64.exe"
27 | # This example downloads the FileZilla installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-FileZilla -OutFile "$env:TEMP\FilezillaClientx64.exe" -DownloadOnly
31 | # This example downloads the FileZilla installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\filezilla-client-win64-setup.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
93 | $Uri = 'https://filezilla-project.org/download.php?show_all=1'
94 |
95 | Try {
96 |
97 | $HtmlLinks = Invoke-WebRequest -Uri $Uri -UserAgent $UserAgent -UseBasicParsing -Method GET -ContentType 'text/html; charset=UTF-8' -Verbose:$False
98 | $Links = (($HtmlLinks.Links | Where-Object -FilterScript { $_.href -like "*win64-setup.exe*" }).href | Out-String).Replace("$([System.Environment]::NewLine)","")
99 | $Url = $Links.Substring(0, $Links.IndexOf('download'))
100 |
101 | } Catch {
102 |
103 | Throw $Error[0]
104 |
105 | } # End Try Catch Catch
106 |
107 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading FileZilla Client"
108 | Invoke-WebRequest -UseBasicParsing -Uri $Url -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
109 |
110 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting hash values for FileZilla Client"
111 | $Version = (Get-Item -Path $OutFile).VersionInfo.FileVersion
112 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA512).Hash.ToLower()
113 | $Hashes = ($HtmlLinks.RawContent.Split("`n") | Select-String -Pattern "SHA-512 hash:" | Out-String)
114 | $CheckSum = $Hashes.Split(":").Replace(' ','').Split("`n") | ForEach-Object { If ($_.Length -ge 128) { $_.Replace('
', '') }}
115 |
116 | #If ($CheckSum -contains $FileHash) {
117 |
118 | # Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for FileZilla Client version $Version"
119 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
120 |
121 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
122 |
123 | } Else {
124 |
125 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of FileZilla Client version $Version"
126 | Start-Process -FilePath $OutFile -ArgumentList @('/S', '/D=%PROGRAMFILES%/FileZilla FTP Client', '/user=all') -NoNewWindow -Wait -PassThru
127 |
128 | } # End If Else
129 |
130 | # } Else {
131 |
132 | # Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for FileZilla Client version $Version"
133 |
134 | # } # End If Else
135 |
136 | } # End Function Install-FileZilla
137 |
--------------------------------------------------------------------------------
/Install-GitForWindows.ps1:
--------------------------------------------------------------------------------
1 | Function Install-GitForWindows {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Git For Windows on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Git For Windows installed for Windows, verify that hash and instal the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER InfFile
15 | Define an INF configuration file for Git if you have customizations you prefere to make.
16 | SAMPLE INF FILE CONTENTS
17 | [Setup]
18 | Lang=default
19 | Dir=C:\Program Files\Git
20 | Group=Git
21 | NoIcons=0
22 | SetupType=default
23 | Compontents=ext,ext\shellhere,ext\guihere,gitlfs,assoc,autoupdate
24 | Tasks=
25 | EditorOption=powershell
26 | CustomEditorPath=
27 | PathOption=Cmd
28 | SSHOption=OpenSSH
29 | TortoiseOption=false
30 | CURLOption=WinSSL
31 | CRLFOption=LFOnly
32 | BashTerminalOption=ConHost
33 | PerformanceTweaksFSCache=Enabled
34 | UseCredentialManager=Enabled
35 | UseCredentialManager=Enabled
36 | EnableSymlinks=Disabled
37 | EnalbedBuiltinInteractiveAdd=Disabled
38 |
39 | .PARAMETER DownloadOnly
40 | Switch parameter to specify you only want to download the installer
41 |
42 | .PARAMETER TryTLSv13
43 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
44 |
45 |
46 | .EXAMPLE
47 | Install-GitForWindows
48 | # This example downloads the Git For Windows installer and verifies the checksum before installing it
49 |
50 | .EXAMPLE
51 | Install-GitForWindows -OutFile "$env:TEMP\git-for-windows-x64-bit.exe"
52 | # This example downloads the Git For Windows installer and verifies the checksum before installing it
53 |
54 | .EXAMPLE
55 | Install-GitForWindows -OutFile "$env:TEMP\git-for-windows-x64-bit.exe" -DownloadOnly
56 | # This example downloads the Git For Windows installer and verifies the checksum
57 |
58 |
59 | .NOTES
60 | Author: Robert H. Osborne
61 | Alias: tobor
62 | Contact: rosborne@osbornepro.com
63 |
64 |
65 | .LINK
66 | https://github.com/tobor88
67 | https://github.com/osbornepro
68 | https://www.powershellgallery.com/profiles/tobor
69 | https://osbornepro.com
70 | https://writeups.osbornepro.com
71 | https://encrypit.osbornepro.com
72 | https://btpssecpack.osbornepro.com
73 | https://www.powershellgallery.com/profiles/tobor
74 | https://www.hackthebox.eu/profile/52286
75 | https://www.linkedin.com/in/roberthosborne/
76 | https://www.credly.com/users/roberthosborne/badges
77 |
78 |
79 | .INPUTS
80 | None
81 |
82 |
83 | .OUTPUTS
84 | System.Management.Automation.PSObject
85 | #>
86 | [OutputType([System.Management.Automation.PSObject])]
87 | [CmdletBinding()]
88 | param(
89 | [Parameter(
90 | Position=0,
91 | Mandatory=$False
92 | )] # End Parameter
93 | [ValidateScript({$_ -like "*.exe"})]
94 | [String]$OutFile = "$env:TEMP\git-for-windows-x64-bit.exe",
95 |
96 | [Parameter(
97 | Position=1,
98 | Mandatory=$False
99 | )] # End Parameter
100 | [ValidateScript({ ($_ -like "*.inf") -and (Test-Path -Path $_) })]
101 | [String]$InfFile,
102 |
103 | [Parameter(
104 | Mandatory=$False
105 | )] # End Parameter
106 | [Switch]$DownloadOnly,
107 |
108 | [Parameter(
109 | Mandatory=$False
110 | )] # End Parameter
111 | [Switch]$TryTLSv13
112 | ) # End param
113 |
114 | $TlsVersion = "TLSv1.2"
115 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
116 | If ($TryTLSv13.IsPresent) {
117 |
118 | $TlsVersion = "TLSv1.3"
119 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
120 |
121 | } # End If
122 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
123 |
124 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
125 | $Uri = 'https://api.github.com/repos/git-for-windows/git/releases/latest'
126 |
127 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Git for Windows from GitHub"
128 | Try {
129 |
130 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
131 | $DownloadLink = ($GetLinks | ForEach-Object { $_.Assets } | Where-Object -Property Name -like "*64-bit.exe").browser_download_url
132 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
133 |
134 | } Catch {
135 |
136 | Throw $Error[0]
137 |
138 | } # End Try Catch Catch
139 |
140 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
141 | $CheckSum = ($GetLinks.body.Split("`n") | Where-Object -FilterScript { $_ -like "*Git-*-64-bit.exe*" } | Out-String).Split(" ")[-1].Trim()
142 |
143 | If ($FileHash -eq $CheckSum) {
144 |
145 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Git for Windows"
146 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
147 |
148 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
149 |
150 | } Else {
151 |
152 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Git for Windows"
153 | If ($PSBoundParameters.ContainsKey("InfFile")) {
154 |
155 | Start-Process -FilePath $OutFile -ArgumentList @('/SP-','/VERYSILENT', '/SUPPRESSMSGBOXES', '/NOCANCEL', '/NORESTART', '/CLOSEAPPLICATIONS', '/RESTARTAPPLICATIONS', '/LOADINF=`"$InfFile`"') -NoNewWindow -Wait -PassThru
156 |
157 | } Else {
158 |
159 | Start-Process -FilePath $OutFile -ArgumentList @('/SP-','/VERYSILENT', '/SUPPRESSMSGBOXES', '/NOCANCEL', '/NORESTART', '/CLOSEAPPLICATIONS', '/RESTARTAPPLICATIONS') -NoNewWindow -Wait -PassThru
160 |
161 | } # End If Else
162 |
163 | } # End If Else
164 |
165 | } Else {
166 |
167 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for Git for Windows"
168 |
169 | } # End If Else
170 |
171 | } # End Function Install-GitForWindows
172 |
--------------------------------------------------------------------------------
/Install-KeePass.ps1:
--------------------------------------------------------------------------------
1 | Function Install-KeePass {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update KeePass on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates KeePass installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-KeePass
23 | # This example downloads the KeePass installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-KeePass -OutFile "$env:TEMP\KeePass-Setup.exe"
27 | # This example downloads the KeePass installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-KeePass -OutFile "$env:TEMP\KeePass-Setup.exe" -DownloadOnly
31 | # This example downloads the KeePass installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\KeePass-Setup.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False)] # End Parameter
73 | [Switch]$DownloadOnly,
74 |
75 | [Parameter(
76 | Mandatory=$False)] # End Parameter
77 | [Switch]$TryTLSv13
78 | ) # End param
79 |
80 | $TlsVersion = "TLSv1.2"
81 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
82 | If ($TryTLSv13.IsPresent) {
83 |
84 | $TlsVersion = "TLSv1.3"
85 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
86 |
87 | } # End If
88 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
89 |
90 | $DLUserAgebt = "wget"
91 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
92 | $DownloadPage = 'https://keepass.info/download.html'
93 | $CheckSumPage = 'https://keepass.info/integrity.html'
94 |
95 | Try {
96 |
97 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading KeePass"
98 | $Uri = ((Invoke-WebRequest -Uri $DownloadPage -UseBasicParsing -UserAgent $UserAgent -ContentType 'text/html' -Verbose:$False).Links | Where-Object -Property "OuterHTML" -like "','').Replace(' | ','').Replace(' | ','').Replace("SHA-256:","").Replace(" ","").Trim().ToLower()
112 | $CheckSum = $Hashes.Split([System.Environment]::NewLine) | Where-Object -FilterScript { $_ -like $FileHash }
113 |
114 | If ($CheckSum -eq $FileHash) {
115 |
116 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for KeePass"
117 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
118 |
119 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
120 |
121 | } Else {
122 |
123 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of KeePass"
124 | Start-Process -FilePath $OutFile -ArgumentList @('/VERYSILENT') -NoNewWindow -Wait -PassThru
125 |
126 | } # End If Else
127 |
128 | } Else {
129 |
130 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for KeePass"
131 |
132 | } # End If Else
133 |
134 | } # End Function Install-KeePass
135 |
--------------------------------------------------------------------------------
/Install-NodeJS.ps1:
--------------------------------------------------------------------------------
1 | Function Install-NodeJS {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update NodeJS for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the latest NodeJS installed for Windows, verify the checksum and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 7/5/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-NodeJS
23 | # This example downloads the NodeJS installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-NodeJS -OutFile "$env:TEMP\NodeJS-Installer.exe"
27 | # This example downloads the NodeJS installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-NodeJS -OutFile "$env:TEMP\NodeJS-Installer.exe" -DownloadOnly
31 | # This example downloads the NodeJS installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.msi"})]
69 | [String]$OutFile = "$env:TEMP\node-installer.msi",
70 |
71 | [Parameter(
72 | Position=1,
73 | Mandatory=$False
74 | )] # End Parameter
75 | [ValidateSet("86", "64")]
76 | [String]$Architecture = $(If ($env:PROCESSOR_ARCHITECTURE -like "AMD64") { "64" } Else { "86" }),
77 |
78 | [Parameter(
79 | Mandatory=$False
80 | )] # End Parameter
81 | [Switch]$DownloadOnly
82 | ) # End param
83 |
84 | $TlsVersion = "TLSv1.2"
85 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
86 | If ($TryTLSv13.IsPresent) {
87 |
88 | $TlsVersion = "TLSv1.3"
89 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
90 |
91 | } # End If
92 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
93 |
94 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
95 | $Uri = "https://api.github.com/repos/nodejs/node/releases/latest"
96 |
97 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Node.JS from GitHub"
98 | Try {
99 |
100 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -Verbose:$False
101 | $DownloadLink = "https://nodejs.org/dist/$($GetLinks.tag_name)/node-$($GetLinks.tag_name)-x64.msi"
102 | $CheckSumLink = "https://nodejs.org/dist/$($GetLinks.tag_name)/SHASUMS256.txt"
103 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -Verbose:$False | Out-Null
104 |
105 | } Catch {
106 |
107 | Throw $Error[0]
108 |
109 | } # End Try Catch Catch
110 |
111 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256 -Verbose:$False).Hash.ToLower()
112 | $CheckSum = ((Invoke-WebRequest -Uri $CheckSumLink -Method GET -UseBasicParsing -UserAgent $UserAgent -Verbose:$False).RawContent.Split("`n") | Where-Object -FilterScript { $_ -like "*node-$($GetLinks.tag_name)-x64.msi" }).Split(' ')[0]
113 |
114 | If ($FileHash -eq $CheckSum) {
115 |
116 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Node.JS"
117 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
118 |
119 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
120 |
121 | } Else {
122 |
123 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Node.JS"
124 | If (Test-Path -Path $OutFile) {
125 |
126 | Start-Process -FilePath "C:\Windows\System32\msiexec.exe" -ArgumentList @('/a', "$OutFile", '/quiet') -NoNewWindow -Wait -PassThru -ErrorAction Stop
127 |
128 | } Else {
129 |
130 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to download file"
131 |
132 | } # End If Else
133 |
134 | } # End If Else
135 |
136 | } Else {
137 |
138 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for Node.JS"
139 |
140 | } # End If Else
141 |
142 | } # End Function Install-NodeJS
143 |
--------------------------------------------------------------------------------
/Install-NotepadPlusPlus.ps1:
--------------------------------------------------------------------------------
1 | Function Install-NotepadPlusPlus {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Notepad++ on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Notepad++ installed for Windows, verify that hash and instal the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-NotepadPlusPlus
23 | # This example downloads the Notepad++ installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-NotepadPlusPlus -OutFile "$env:TEMP\npp.latest.Installer.x64.exe"
27 | # This example downloads the Notepad++ installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-NotepadPlusPlus -OutFile "$env:TEMP\npp.latest.Installer.x64.exe" -DownloadOnly
31 | # This example downloads the Notepad++ installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\npp.latest.Installer.x64.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = 'https://api.github.com/repos/notepad-plus-plus/notepad-plus-plus/releases/latest'
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Notepad++ from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $DownloadLink = ($GetLinks.assets | Where-Object -Property Name -like "npp.*.Installer.x64.exe").browser_download_url
100 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Verbose:$False | Out-Null
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
109 | $CheckSum = ($GetLinks.body.Split(" ") | Where-Object -FilterScript { $_ -like "*$FileHash*" } | Out-String).Trim().ToLower().Split("`n")[-1]
110 |
111 | If ($FileHash -eq $CheckSum) {
112 |
113 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Notepad++"
114 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
115 |
116 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
117 |
118 | } Else {
119 |
120 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Notepad++"
121 | Start-Process -FilePath $OutFile -ArgumentList @('/S') -NoNewWindow -Wait -PassThru
122 |
123 | } # End If Else
124 |
125 | } Else {
126 |
127 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for Notepad++"
128 |
129 | } # End If Else
130 |
131 | } # End Function Install-NotepadPlusPlus
132 |
--------------------------------------------------------------------------------
/Install-PowerShellCore.ps1:
--------------------------------------------------------------------------------
1 | Function Install-PowerShellCore {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update PowerShell Core on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates PowerShell Core installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-PowerShellCore
23 | # This example downloads the PowerShell Core installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-PowerShellCore -OutFile "$env:TEMP\PowerShell-version-win-x64.msi"
27 | # This example downloads the PowerShell Core installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-PowerShellCore -OutFile "$env:TEMP\PowerShell-version-win-x64.msi" -DownloadOnly
31 | # This example downloads the FileZilla installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.msi"})]
69 | [String]$OutFile = "$env:TEMP\PowerShell-version-win-x64.msi",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest'
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading PowerShell Core from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $DownloadLink = ($GetLinks.assets | Where-Object -Property Name -like "*PowerShell-*-win-x64.msi").browser_download_url
100 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
109 | $CheckSum = ($GetLinks.body.Split("-") | Where-Object -FilterScript { $_ -like "*$FileHash*" } | Out-String).Trim().ToLower()
110 |
111 | If ($FileHash -eq $CheckSum) {
112 |
113 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for PowerShell Core"
114 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
115 |
116 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
117 |
118 | } Else {
119 |
120 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of PowerShell Core"
121 | Start-Process -FilePath "C:\Windows\System32\msiexec.exe" -ArgumentList @('/i', "$OutFile", '/quiet') -NoNewWindow -Wait -PassThru
122 |
123 | } # End If Else
124 |
125 | } Else {
126 |
127 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for PowerShell Core"
128 |
129 | } # End If Else
130 |
131 | } # End Function Install-PowerShellCore
132 |
--------------------------------------------------------------------------------
/Install-Putty.ps1:
--------------------------------------------------------------------------------
1 | Function Install-Putty {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Putty for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Putty installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-Putty
23 | # This example downloads the Signal installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-Putty -OutFile "$env:TEMP\putty-installer.msi"
27 | # This example downloads the Signal installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-Putty -OutFile "$env:TEMP\putty-installer.exe" -DownloadOnly
31 | # This example downloads the Signal installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://gitlab.com/tobor88
43 | https://github.com/osbornepro
44 | https://www.powershellgallery.com/profiles/tobor
45 | https://osbornepro.com
46 | https://writeups.osbornepro.com
47 | https://encrypit.osbornepro.com
48 | https://btpssecpack.osbornepro.com
49 | https://www.powershellgallery.com/profiles/tobor
50 | https://www.hackthebox.eu/profile/52286
51 | https://www.linkedin.com/in/roberthosborne/
52 | https://www.credly.com/users/roberthosborne/badges
53 |
54 |
55 | .INPUTS
56 | None
57 |
58 |
59 | .OUTPUTS
60 | System.Management.Automation.PSObject
61 | #>
62 | [OutputType([System.Management.Automation.PSObject])]
63 | [CmdletBinding(DefaultParameterSetName="Installer")]
64 | param(
65 | [Parameter(
66 | ParameterSetName="Installer",
67 | Position=0,
68 | Mandatory=$False
69 | )] # End Parameter
70 | [ValidateScript({$_ -like "*.msi"})]
71 | [String]$OutFile = "$env:TEMP\putty-installer.msi",
72 |
73 | [Parameter(
74 | ParameterSetName="Portable",
75 | Position=0,
76 | Mandatory=$False
77 | )] # End Parameter
78 | [ValidateScript({$_ -like "*.exe"})]
79 | [String]$FilePath = "$env:TEMP\putty.exe",
80 |
81 | [Parameter(
82 | Position=1,
83 | Mandatory=$False
84 | )] # End Parameter
85 | [ValidateSet('32','64','arm64')]
86 | [String]$Architecture = "64",
87 |
88 | [Parameter(
89 | ParameterSetName="Portable",
90 | Mandatory=$False
91 | )] # End Parameter
92 | [Switch]$DownloadPortable,
93 |
94 | [Parameter(
95 | Mandatory=$False
96 | )] # End Parameter
97 | [Switch]$TryTLSv13
98 | ) # End param
99 |
100 | $TlsVersion = "TLSv1.2"
101 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
102 | If ($TryTLSv13.IsPresent) {
103 |
104 | $TlsVersion = "TLSv1.3"
105 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
106 |
107 | } # End If
108 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
109 |
110 | $MainUrl = "https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html"
111 | $CheckSumLink = "https://the.earth.li/~sgtatham/putty/latest/sha256sums"
112 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
113 |
114 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Obtaining latest version information for Putty"
115 | $Version = (Invoke-RestMethod -UseBasicParsing -Uri $MainUrl -Method GET -UserAgent $UserAgent -ContentType 'text/html' -Verbose:$False).Split("`n")[2].Split('(')[-1].Split(')')[0]
116 |
117 | Write-Debug -Message "[d] ParameterSetName: $($PSCmdlet.ParameterSetName)"
118 | Switch ($Architecture) {
119 |
120 | '32' {
121 |
122 | If ($PSCmdlet.ParameterSetName -eq "Portable") {
123 |
124 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/w$($Architecture)/putty.exe"
125 | $Path = $FilePath
126 |
127 | } Else {
128 |
129 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/w$($Architecture)/putty-$($Version)-installer.msi"
130 | $Path = $OutFile
131 |
132 | } # End If Else
133 |
134 | } '64' {
135 |
136 | If ($PSCmdlet.ParameterSetName -eq "Portable") {
137 |
138 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/w$($Architecture)/putty.exe"
139 | $Path = $FilePath
140 |
141 | } Else {
142 |
143 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/w$($Architecture)/putty-$($Architecture)bit-$($Version)-installer.msi"
144 | $Path = $OutFile
145 |
146 | } # End If Else
147 |
148 | } 'arm64' {
149 |
150 | If ($PSCmdlet.ParameterSetName -eq "Portable") {
151 |
152 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/wa64/putty.exe"
153 | $Path = $FilePath
154 |
155 | } Else {
156 |
157 | $Uri = "https://the.earth.li/~sgtatham/putty/latest/wa64/putty-$($Architecture)-$($Version)-installer.msi"
158 | $Path = $OutFile
159 |
160 | } # End If Else
161 |
162 | } # End Switch Options
163 |
164 | } # End Switch
165 |
166 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Obtaining checksums for Putty"
167 | $CheckSumList = ((Invoke-RestMethod -UseBasicParsing -Uri $CheckSumLink -Method GET -UserAgent $UserAgent -ContentType 'text/html' -Verbose:$False).Split(' ').Split("`n") | ForEach-Object { If ($_.Length -eq 64) { $_ } }).Trim()
168 |
169 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Putty"
170 | Invoke-WebRequest -UseBasicParsing -Uri $Uri -UserAgent $UserAgent -OutFile $Path -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
171 | $CheckSumValue = (Get-FileHash -Path $Path -Algorithm SHA256 -Verbose:$False).Hash.ToLower()
172 |
173 | If ($CheckSumList -contains $CheckSumValue) {
174 |
175 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Putty"
176 | If ($DownloadPortable.IsPresent -and (Test-Path -Path $Path)) {
177 |
178 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') File saved to $Path"
179 |
180 | } Else {
181 |
182 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Putty version $Version"
183 | Start-Process -FilePath "C:\Windows\System32\msiexec.exe" -ArgumentList @("/i", $Path, "/qn", "ALLUSERS=1") -NoNewWindow -Wait -PassThru -ErrorAction Stop
184 |
185 | } # End If Else
186 |
187 | } Else {
188 |
189 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate checksum of the downloaded file $Path"
190 |
191 | } # End If Else
192 |
193 | } # End Function Install-Putty
194 |
--------------------------------------------------------------------------------
/Install-RemoteDesktopManager.ps1:
--------------------------------------------------------------------------------
1 | Function Install-RemoteDesktopManager {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Remote Desktop Manager for Windows on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Remote Desktop Manager installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 8/9/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-RemoteDesktopManager
23 | # This example downloads the RemoteDesktopManager installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-RemoteDesktopManager -OutFile "$env:TEMP\RemoteDesktopManager-Installer.exe"
27 | # This example downloads the Remote Desktop Manager installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-RemoteDesktopManager -OutFile "$env:TEMP\RemoteDesktopManager-Installer.exe" -DownloadOnly
31 | # This example downloads the Remote Desktop Manager installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\RemoteDesktopManager-installer.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
93 | $VersionUri = "https://devolutions.net/remote-desktop-manager/home/download/"
94 | $Version = (((Invoke-WebRequest -UseBasicParsing -Uri $VersionUri -Method GET -UserAgent $UserAgent -ContentType 'text/html' -Verbose:$False).Content.Split("`n") | Select-String -Pattern "data-g-version=")[0] | Out-String).Trim().Split('"')[1]
95 | $Uri = "https://cdn.devolutions.net/download/Setup.RemoteDesktopManager.$($Version).exe"
96 |
97 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading RemoteDesktopManager"
98 | Invoke-WebRequest -UseBasicParsing -Method GET -Uri $Uri -OutFile $OutFile -UserAgent $UserAgent -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
99 |
100 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting hash values for RemoteDesktopManager"
101 | #$FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA512).Hash.ToLower()
102 |
103 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Remote Desktop Manager version $Version"
104 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
105 |
106 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash: $OutFile"
107 |
108 | } Else {
109 |
110 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Remote Desktop Manager version $Version"
111 | Start-Process -FilePath $OutFile -ArgumentList @('/S') -NoNewWindow -Wait -PassThru
112 |
113 | } # End If Else
114 |
115 | } # End Function Install-RemoteDesktopManager
116 |
--------------------------------------------------------------------------------
/Install-SSMS.ps1:
--------------------------------------------------------------------------------
1 | Function Install-SSMS {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update SQL Server Management Studio (SSMS) on a Windows machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates SQL Server Management Studio and install for Windows
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 8/9/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-SSMS
23 | # This example downloads the SSMS installer and installs it
24 |
25 | .EXAMPLE
26 | Install-SSMS -OutFile "$env:TEMP\SSMS-installer.exe"
27 | # This example downloads the SSMS installer and installs it
28 |
29 | .EXAMPLE
30 | Install-SSMS -OutFile "$env:TEMP\SSMS-installer.exe" -DownloadOnly
31 | # This example downloads the SSMS installer
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\SSMS-installer.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
93 | $Uri = 'https://aka.ms/ssmsfullsetup'
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading SSMS from Microsoft"
96 | Invoke-WebRequest -UseBasicParsing -Uri $Uri -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
97 |
98 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting hash values for SSMS"
99 | $Version = (Get-Item -Path $OutFile).VersionInfo.FileVersion
100 | #$FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA512).Hash.ToLower()
101 |
102 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for SSMS version $Version"
103 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
104 |
105 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file: $OutFile"
106 |
107 | } Else {
108 |
109 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of SSMS version $Version"
110 | Start-Process -FilePath $OutFile -ArgumentList "/Install /Quiet" -NoNewWindow -Wait -PassThru
111 |
112 | } # End If Else
113 |
114 | } # End Function Install-SSMS
115 |
--------------------------------------------------------------------------------
/Install-SccmAgent.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to install the SCCM Agent or Reinstall the SCCM agent on a local machine
4 |
5 |
6 | .DESCRIPTION
7 | Install the SCCM agent or reinstall the SCCM agent. This will require you to have a location to install the ccmsetup.exe file from
8 |
9 |
10 | .PARAMETER FilePath
11 | Set the aboslute path to the ccmsetup.exe file you want to use to install the SCCM Agent
12 |
13 | .PARAMETER SiteCode
14 | Define the Site Code for your SCCM server that should be used during the ccmsetup.exe installation
15 |
16 | .PARAMETER Destination
17 | Define the destination directory to save your ccmsetup.exe file too
18 |
19 | .PARAMETER ReInstall
20 | Set this parameter when you want to reinstall the SCCM Agent locally on a machine
21 |
22 |
23 | .EXAMPLE
24 | Install-SccmAgent -FilePath \\sccmserver\D$\Installer\ccmsetup.exe -Destination $env:TEMP -SiteCode OBP
25 | # This example copies ccmsetup.exe to your users temp directory and install the SCCM Agent using site code OBP
26 |
27 | .EXAMPLE
28 | Install-SccmAgent -FilePath \\sccmserver\D$\Installer\ccmsetup.exe -SiteCode OBP -ReInstall
29 | # This example copies ccmsetup.exe to your Downloads directory and uninstalls, waits 15 minutes then reinstalls the SCCM agent using site code OBP
30 |
31 |
32 | .INPUTS
33 | None
34 |
35 |
36 | .OUTPUTS
37 | None
38 |
39 |
40 | .NOTES
41 | Author: Robert H. Osborne
42 | Alias: tobor
43 | Contact: rosborne@osbornepro.com
44 |
45 |
46 | .LINK
47 | https://github.com/tobor88
48 | https://github.com/OsbornePro
49 | https://www.powershellgallery.com/profiles/tobor
50 | https://osbornepro.com
51 | https://writeups.osbornepro.com
52 | https://btpssecpack.osbornepro.com
53 | https://www.powershellgallery.com/profiles/tobor
54 | https://www.hackthebox.eu/profile/52286
55 | https://www.linkedin.com/in/roberthosborne/
56 | https://www.credly.com/users/roberthosborne/badges
57 | #>
58 | Function Install-SccmAgent {
59 | [CmdletBinding()]
60 | param(
61 | [Parameter(
62 | Position=0,
63 | Mandatory=$True,
64 | ValueFromPipeline=$False,
65 | HelpMessage="Enter the absolute path to the ccmsetup.exe file you wish to install. EXAMPLE: C:\Temp\ccmsetup.exe : "
66 | )] # End Parameter
67 | [ValidateScript({[System.IO.File]::Exists($_)})]
68 | [String]$FilePath,
69 |
70 | [Parameter(
71 | Position=1,
72 | Mandatory=$True,
73 | ValueFromPipeline=$False,
74 | HelpMessage="Enter the site code to use when install the ccmsetup.exe file EXAMPLE: ABC : "
75 | )] # End Parameter
76 | [String]$SiteCode,
77 |
78 | [Parameter(
79 | Position=2,
80 | Mandatory=$False,
81 | ValueFromPipeline=$False,
82 | HelpMessage="Enter the absolute path to the directory you wish to copy ccmsetup.exe too. EXAMPLE: C:\Temp : "
83 | )] # End Parameter
84 | [ValidateScript({[System.IO.Directory]::Exists($_)})]
85 | [String]$Destination = "$env:USERPROFILE\Downloads",
86 |
87 | [Parameter(
88 | Mandatory=$False
89 | )] # End Parameter
90 | [Switch][Bool]$ReInstall
91 | ) # End param
92 |
93 | Write-Verbose "Copying installation file to $env:COMPUTERNAME"
94 | $FileName = $FilePath.Split("\")[-1]
95 | $Source = $FilePath.Replace("\$($FileName)","")
96 |
97 | robocopy $Source $Destination $FileName
98 |
99 | If ($ReInstall.IsPresent) {
100 |
101 | Write-Verbose "Uninstalling the SCCM Agent on $env:COMPUTERNAME"
102 | Start-Process -FilePath "$Destination\ccmsetup.exe" -ArgumentList @("/uninstall") -NoNewWindow -Wait
103 |
104 | Start-Sleep -Seconds 300
105 |
106 | } # End If
107 |
108 | Write-Verbose "Installing the SCCM Agent on $env:COMPUTERNAME"
109 | Start-Process -FilePath "$Destination\ccmsetup.exe" -ArgumentList @("SMSSITECODE=$SiteCode") -NoNewWindow -Wait
110 |
111 | } # End Function Install-SccmAgent
112 |
--------------------------------------------------------------------------------
/Install-Signal.ps1:
--------------------------------------------------------------------------------
1 | Function Install-Signal {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update Signal for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates Signal installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-Signal
23 | # This example downloads the Signal installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-Signal -OutFile "$env:TEMP\SignalClientx64.exe"
27 | # This example downloads the Signal installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-Signal -OutFile "$env:TEMP\SignalClientx64.exe" -DownloadOnly
31 | # This example downloads the Signal installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\SignalSetup.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = 'https://api.github.com/repos/signalapp/Signal-Desktop/releases/latest'
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Signal from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-RestMethod -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'application/json; charset=utf-8' -Verbose:$False
99 | $Version = ($GetLinks.html_url.Split('/')[-1]).Replace("v", "")
100 | $DownloadLink = "https://updates.signal.org/desktop/signal-desktop-win-$($Version).exe"
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading Signal"
109 | Invoke-WebRequest -UseBasicParsing -Uri $DownloadLink -UserAgent $UserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
110 |
111 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for Signal version $Version"
112 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
113 |
114 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
115 |
116 | } Else {
117 |
118 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of Signal version $Version"
119 | Start-Process -FilePath $OutFile -ArgumentList @('/S') -NoNewWindow -Wait -PassThru
120 |
121 | } # End If Else
122 |
123 | } # End Function Install-Signal
124 |
--------------------------------------------------------------------------------
/Install-VLC.ps1:
--------------------------------------------------------------------------------
1 | Function Install-VLC {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update VLC for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates VLC installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-VLC
23 | # This example downloads the VLC installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-VLC -OutFile "$env:TEMP\vlc-3.0.18-win64.exe"
27 | # This example downloads the VLC installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-VLC -OutFile "$env:TEMP\vlc-3.0.18-win64.exe" -DownloadOnly
31 | # This example downloads the VLC installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\vlc-version-win64.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $Uri = 'https://www.videolan.org/vlc/download-windows.html'
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 |
95 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Getting VLC download link from GitHub"
96 | Try {
97 |
98 | $GetLinks = Invoke-WebRequest -Uri $Uri -Method GET -UseBasicParsing -UserAgent $UserAgent -ContentType 'text/html' -Verbose:$False
99 | $CheckSumLink = "https:" + $($GetLinks.Links | Where-Object -FilterScript { $_.href -like "*//get.videolan.org*" -and $_.outerHTML -like "*win64.exe*" } | Select-Object -ExpandProperty href -First 1)
100 | $Version = $CheckSumLink.Split('-')[-2]
101 | $DownloadLink = "https://mirrors.ocf.berkeley.edu/videolan-ftp/vlc/$($Version)/win64/vlc-$($Version)-win64.exe"
102 |
103 | } Catch {
104 |
105 | Throw $Error[0]
106 |
107 | } # End Try Catch Catch
108 |
109 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading VLC"
110 | Invoke-WebRequest -UseBasicParsing -Uri $DownloadLink -UserAgent $UserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
111 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
112 | $CheckSum = ((Invoke-RestMethod -UseBasicParsing -Uri $CheckSumLink -UserAgent $UserAgent -ContentType 'text/html; charset=UTF-8' -Method GET -Verbose:$False).Split("`n") | Where-Object -FilterScript { $_ -like "*Display Checksum*" }).Split(':')[-1].Split('<')[0].Trim()
113 |
114 | If ($FileHash -eq $CheckSum) {
115 |
116 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for VLC version $Version"
117 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
118 |
119 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
120 |
121 | } Else {
122 |
123 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of VLC version $Version"
124 | Move-Item -Path $OutFile -Destination $OutFile.Replace("version", $Version) -Force -Confirm:$False
125 | Start-Process -FilePath $OutFile.Replace("version", $Version) -ArgumentList @('/S') -NoNewWindow -Wait -PassThru
126 |
127 | } # End If Else
128 |
129 | } Else {
130 |
131 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Checsum value does not match the VLC sha256 hash of the downloaded file"
132 |
133 | } # End If Else
134 |
135 | } # End Function Install-VLC
136 |
--------------------------------------------------------------------------------
/Install-VSCode.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 | Function Install-VSCode {
3 | <#
4 | .SYNOPSIS
5 | This cmdlet is used to install/update VSCode on a machine. It can also be used to simply download the installer
6 |
7 |
8 | .DESCRIPTION
9 | Download the lates VSCode installed for Windows, verify that hash and install the file
10 |
11 |
12 | .PARAMETER OutFile
13 | Define where to save the installer file. Default location is your Temp directory
14 |
15 | .PARAMETER DownloadOnly
16 | Switch parameter to specify you only want to download the installer
17 |
18 | .PARAMETER TryTLSv13
19 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
20 |
21 |
22 | .EXAMPLE
23 | Install-VSCode
24 | # This example downloads the VSCode installer and verifies the checksum before installing it
25 |
26 | .EXAMPLE
27 | Install-VSCode -OutFile "$env:TEMP\PowerShell-version-win-x64.msi"
28 | # This example downloads the VSCode installer and verifies the checksum before installing it
29 |
30 | .EXAMPLE
31 | Install-VSCode -OutFile "$env:TEMP\PowerShell-version-win-x64.msi" -DownloadOnly
32 | # This example downloads the FileZilla installer and verifies the checksum
33 |
34 |
35 | .NOTES
36 | Author: Robert H. Osborne
37 | Alias: tobor
38 | Contact: rosborne@osbornepro.com
39 |
40 |
41 | .LINK
42 | https://code.visualstuido.com.com/tobor88
43 | https://code.visualstuido.com.com/osbornepro
44 | https://www.powershellgallery.com/profiles/tobor
45 | https://osbornepro.com
46 | https://writeups.osbornepro.com
47 | https://encrypit.osbornepro.com
48 | https://btpssecpack.osbornepro.com
49 | https://www.powershellgallery.com/profiles/tobor
50 | https://www.hackthebox.eu/profile/52286
51 | https://www.linkedin.com/in/roberthosborne/
52 | https://www.credly.com/users/roberthosborne/badges
53 |
54 |
55 | .INPUTS
56 | None
57 |
58 |
59 | .OUTPUTS
60 | System.Management.Automation.PSObject
61 | #>
62 | [OutputType([System.Management.Automation.PSObject])]
63 | [CmdletBinding()]
64 | param(
65 | [Parameter(
66 | Position=0,
67 | Mandatory=$False
68 | )] # End Parameter
69 | [ValidateScript({$_ -like "*.exe"})]
70 | [String]$OutFile = "$env:TEMP\vscode-setup-win.exe",
71 |
72 | [Parameter(
73 | Mandatory=$False
74 | )] # End Parameter
75 | [Switch]$DownloadOnly,
76 |
77 | [Parameter(
78 | Mandatory=$False
79 | )] # End Parameter
80 | [Switch]$TryTLSv13
81 | ) # End param
82 |
83 | $TlsVersion = "TLSv1.2"
84 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
85 | If ($TryTLSv13.IsPresent) {
86 |
87 | $TlsVersion = "TLSv1.3"
88 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
89 |
90 | } # End If
91 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
92 |
93 | #$CheckSumLink = 'https://code.visualstudio.com/Download' #JavaScript is preventing ability to obtain. Requires more research
94 | $DownloadLink = 'https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user'
95 | $UserAgent = "wget"
96 |
97 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading VSCode from code.visualstuido.com"
98 | Try {
99 |
100 | #$CheckSum = Invoke-RestMethod -Uri $CheckSumLink -Method GET -UseBasicParsing -UserAgent "wget" -ContentType 'text/html; charset=utf-8' -Verbose:$False
101 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -UserAgent $UserAgent -OutFile $OutFile -Method GET -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
102 |
103 | } Catch {
104 |
105 | Throw $Error[0]
106 |
107 | } # End Try Catch Catch
108 |
109 | #$FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
110 | #$CheckSum = ($GetLinks.body.Split("-") | Where-Object -FilterScript { $_ -like "*$FileHash*" } | Out-String).Trim().ToLower()
111 |
112 | #If ($FileHash -eq $CheckSum) {
113 |
114 | # Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for VSCode"
115 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
116 |
117 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
118 |
119 | } Else {
120 |
121 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of VSCode"
122 | Start-Process -FilePath $OutFile -ArgumentList @('/FORCECLOSEAPPLICATIONS', "/LANG=$PSUICulture", '/VERYSILENT') -NoNewWindow -Wait -PassThru
123 |
124 | } # End If Else
125 |
126 | #} Else {
127 |
128 | # Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for VSCode"
129 |
130 | #} # End If Else
131 |
132 | } # End Function Install-VSCode
133 |
--------------------------------------------------------------------------------
/Install-WinRAR.ps1:
--------------------------------------------------------------------------------
1 | Function Install-WinRAR {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update WinRAR for Windows. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates WinRAR installed for Windows, verify that hash and install the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-WinRAR
23 | # This example downloads the WinRAR installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-WinRAR -OutFile "$env:TEMP\WinRAR-Installer.exe"
27 | # This example downloads the WinRAR installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-WinRAR -OutFile "$env:TEMP\WinRAR-Installer.exe" -DownloadOnly
31 | # This example downloads the WinRAR installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False
67 | )] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "C:\Windows\Temp\winrar-x64-version.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False
73 | )] # End Parameter
74 | [Switch]$DownloadOnly,
75 |
76 | [Parameter(
77 | Mandatory=$False
78 | )] # End Parameter
79 | [Switch]$TryTLSv13
80 | ) # End param
81 |
82 | $TlsVersion = "TLSv1.2"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
84 | If ($TryTLSv13.IsPresent) {
85 |
86 | $TlsVersion = "TLSv1.3"
87 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
88 |
89 | } # End If
90 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
91 |
92 | $OutFile = $OutFile.Replace("version",$WrVersion)
93 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
94 | $WrVersion = (((Invoke-WebRequest -Uri https://www.rarlab.com/ -UseBasicParsing -UserAgent $UserAgent -Method GET -Verbose:$False).Links | Where-Object -FilterScript { $_.outerHTML -like "*/rar/winrar-x64-*" }).href.Split('=').Split('.') | Where-Object -FilterScript { $_ -match "(.*)\d{1,6}$"}).Split('-')[-1]
95 | $DownloadLink = "https://rarlab.com/rar/winrar-x64-$WrVersion.exe"
96 |
97 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading WinRAR version $WrVersion"
98 | Try {
99 |
100 | (New-Object -TypeName System.Net.WebCLient).DownloadFile("$DownloadLink", "$OutFile")
101 |
102 | } Catch [System.Net.WebException] {
103 |
104 | If ($Error[0] -like "*Request forbidden by administrative rules.*") {
105 |
106 | Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -Method GET -ContentType 'application/octet-stream' -UserAgent $UserAgent -OutFile $OutFile -Verbose:$False -ErrorAction Stop | Out-Null
107 |
108 | } Else {
109 |
110 | Throw $Error[0]
111 |
112 | } # End If Else
113 |
114 | } Catch {
115 |
116 | Throw $Error[0]
117 |
118 | } # End Try Catch Catch
119 |
120 | Write-Warning -Message "[!] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') WinRAR does NOT offer a checksum value to verify a files integrity with. Use 7Zip it is way better"
121 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
122 |
123 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded WinRAR file and verified hash.`n[i] File saved to $OutFile"
124 |
125 | } Else {
126 |
127 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of WinRAR version $WrVersion"
128 | Start-Process -FilePath $OutFile -ArgumentList @('/S') -NoNewWindow -Wait -PassThru -ErrorAction Stop
129 |
130 | } # End If Else
131 |
132 | } # End Function Install-WinRAR
133 |
--------------------------------------------------------------------------------
/Install-WinSCP.ps1:
--------------------------------------------------------------------------------
1 | Function Install-WinSCP {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install/update WinSCP on a machine. It can also be used to simply download the installer
5 |
6 |
7 | .DESCRIPTION
8 | Download the lates WinSCP installed for Windows, verify that hash and instal the file
9 |
10 |
11 | .PARAMETER OutFile
12 | Define where to save the installer file. Default location is your Temp directory
13 |
14 | .PARAMETER DownloadOnly
15 | Switch parameter to specify you only want to download the installer
16 |
17 | .PARAMETER TryTLSv13
18 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
19 |
20 |
21 | .EXAMPLE
22 | Install-WinSCP
23 | # This example downloads the WinSCP installer and verifies the checksum before installing it
24 |
25 | .EXAMPLE
26 | Install-WinSCP -OutFile "$env:TEMP\WinSCP-Version-Setup.exe"
27 | # This example downloads the WinSCP installer and verifies the checksum before installing it
28 |
29 | .EXAMPLE
30 | Install-WinSCP -OutFile "$env:TEMP\WinSCP-Version-Setup.exe" -DownloadOnly
31 | # This example downloads the WinSCP installer and verifies the checksum
32 |
33 |
34 | .NOTES
35 | Author: Robert H. Osborne
36 | Alias: tobor
37 | Contact: rosborne@osbornepro.com
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://github.com/osbornepro
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://encrypit.osbornepro.com
47 | https://btpssecpack.osbornepro.com
48 | https://www.powershellgallery.com/profiles/tobor
49 | https://www.hackthebox.eu/profile/52286
50 | https://www.linkedin.com/in/roberthosborne/
51 | https://www.credly.com/users/roberthosborne/badges
52 |
53 |
54 | .INPUTS
55 | None
56 |
57 |
58 | .OUTPUTS
59 | System.Management.Automation.PSObject
60 | #>
61 | [OutputType([System.Management.Automation.PSObject])]
62 | [CmdletBinding()]
63 | param(
64 | [Parameter(
65 | Position=0,
66 | Mandatory=$False,
67 | ValueFromPipeline=$False)] # End Parameter
68 | [ValidateScript({$_ -like "*.exe"})]
69 | [String]$OutFile = "$env:TEMP\WinSCP-Version-Setup.exe",
70 |
71 | [Parameter(
72 | Mandatory=$False)] # End Parameter
73 | [Switch]$DownloadOnly,
74 |
75 | [Parameter(
76 | Mandatory=$False)] # End Parameter
77 | [Switch]$TryTLSv13
78 | ) # End param
79 |
80 | $TlsVersion = "TLSv1.2"
81 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
82 | If ($TryTLSv13.IsPresent) {
83 |
84 | $TlsVersion = "TLSv1.3"
85 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
86 |
87 | } # End If
88 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
89 |
90 | $DLUserAgent = "Wget"
91 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
92 | $DlUrl = 'https://winscp.net/eng/download.php'
93 | $Version = ((Invoke-WebRequest -Uri $DlUrl -UseBasicParsing -Method GET -UserAgent $UserAgent -ErrorAction Stop -Verbose:$False).Links | Where-Object -FilterScript { $_.outerHTML -like "*List of all changes*" }).href.Split('=')[-1]
94 | $Uri = "https://winscp.net/download/WinSCP-$Version`-Setup.exe"
95 |
96 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading WinSCP from their website"
97 | Try {
98 |
99 | Invoke-WebRequest -Uri $Uri -UseBasicParsing -Method GET -UserAgent $DLUserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
100 | $CheckSum = (((Invoke-WebRequest -Uri $Uri -UseBasicParsing -Method GET -UserAgent $UserAgent -Verbose:$False).Content).Split("`n") | Select-String -Pattern "SHA-256:").ToString().Trim().Replace('','').Split(" ")[-1]
101 |
102 | } Catch {
103 |
104 | Throw $Error[0]
105 |
106 | } # End Try Catch Catch
107 |
108 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
109 | If ($FileHash -eq $CheckSum) {
110 |
111 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for WinSCP"
112 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
113 |
114 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
115 |
116 | } Else {
117 |
118 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Executing installation of WinSCP"
119 | Start-Process -FilePath $OutFile -ArgumentList @('/VERYSILENT', '/ALLUSERS' ,'NORESTART') -NoNewWindow -Wait -PassThru -ErrorAction Stop
120 |
121 | } # End If Else
122 |
123 | } Else {
124 |
125 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for WinSCP"
126 |
127 | } # End If Else
128 |
129 | } # End Function Install-WinSCP
130 |
--------------------------------------------------------------------------------
/Install-WinSCPNetAssembly.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 | Function Install-WinSCPNetAssembly {
3 | <#
4 | .SYNOPSIS
5 | This cmdlet is used to install/update WinSCP NET Assembly DLL on a machine. It can also be used to simply download the installer
6 |
7 |
8 | .DESCRIPTION
9 | Download the lates WinSCP installed for Windows, verify that hash and instal the file
10 |
11 |
12 | .PARAMETER OutFile
13 | Define where to save the NET assembly zip file. Default location is your Temp directory
14 |
15 | .PARAMETER DownloadOnly
16 | Switch parameter to specify you only want to download the installer
17 |
18 | .PARAMETER TryTLSv13
19 | Switch parameter that tells PowerShell to try download file using TLSv1.3. This seems to fail as of 3/28/2023 due to 1.3 being so new
20 |
21 |
22 | .EXAMPLE
23 | Install-WinSCPNetAssembly
24 | # This example downloads the WinSCP automation and verifies the checksum before installing it
25 |
26 | .EXAMPLE
27 | Install-WinSCPNetAssembly -OutFile "$env:TEMP\WinSCP-Version-Automation.zip"
28 | # This example downloads the WinSCP automation and verifies the checksum before installing it
29 |
30 | .EXAMPLE
31 | Install-WinSCPNetAssembly -OutFile "$env:TEMP\WinSCP-Version-Automation.zip" -DownloadOnly
32 | # This example downloads the WinSCP automation and verifies the checksum
33 |
34 |
35 | .NOTES
36 | Author: Robert Osborne
37 | Contact: rosborne@vinebrooktech.com
38 |
39 |
40 | .LINK
41 | https://www.vinebrooktech.com
42 |
43 |
44 | .INPUTS
45 | None
46 |
47 |
48 | .OUTPUTS
49 | System.Management.Automation.PSObject
50 | #>
51 | [OutputType([System.Management.Automation.PSObject])]
52 | [CmdletBinding()]
53 | param(
54 | [Parameter(
55 | Position=0,
56 | Mandatory=$False
57 | )] # End Parameter
58 | [ValidateScript({$_ -like "*.zip"})]
59 | [String]$OutFile = "$env:TEMP\WinSCP-Version-Automation.zip",
60 |
61 | [Parameter(
62 | Position=1,
63 | Mandatory=$False
64 | )] # End Parameter
65 | [String]$DestinationPath = "$env:ProgramData\WinSCP",
66 |
67 | [Parameter(
68 | Mandatory=$False
69 | )] # End Parameter
70 | [Switch]$DownloadOnly,
71 |
72 | [Parameter(
73 | Mandatory=$False
74 | )] # End Parameter
75 | [Switch]$TryTLSv13
76 | ) # End param
77 |
78 | $TlsVersion = "TLSv1.2"
79 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
80 | If ($TryTLSv13.IsPresent) {
81 |
82 | $TlsVersion = "TLSv1.3"
83 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13
84 |
85 | } # End If
86 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') utilizing $TlsVersion"
87 |
88 | $DLUserAgent = "Wget"
89 | $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox
90 | $DlUrl = 'https://winscp.net/eng/download.php'
91 | $Version = ((Invoke-WebRequest -Uri $DlUrl -UseBasicParsing -Method GET -UserAgent $UserAgent -ErrorAction Stop -Verbose:$False).Links | Where-Object -FilterScript { $_.outerHTML -like "*List of all changes*" }).href.Split('=')[-1]
92 | $Uri = "https://winscp.net/download/WinSCP-$Version`-Automation.zip"
93 |
94 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Downloading WinSCP NET Assembly from their website"
95 | Try {
96 |
97 | Invoke-WebRequest -Uri $Uri -UseBasicParsing -Method GET -UserAgent $DLUserAgent -OutFile $OutFile -ContentType 'application/octet-stream' -Verbose:$False | Out-Null
98 | $CheckSum = (((Invoke-WebRequest -Uri $Uri -UseBasicParsing -Method GET -UserAgent $UserAgent -Verbose:$False).Content).Split("`n") | Select-String -Pattern "SHA-256:").ToString().Trim().Replace('','').Split(" ")[-1]
99 |
100 | } Catch {
101 |
102 | Throw $Error[0]
103 |
104 | } # End Try Catch Catch
105 |
106 | $FileHash = (Get-FileHash -Path $OutFile -Algorithm SHA256).Hash.ToLower()
107 | If ($FileHash -eq $CheckSum) {
108 |
109 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully verified hash of newly downloaded file for WinSCP"
110 | If ($DownloadOnly.IsPresent -and (Test-Path -Path $OutFile)) {
111 |
112 | Write-Output -InputObject "[*] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Successfully downloaded file and verified hash.`n[i] File saved to $OutFile"
113 |
114 | } Else {
115 |
116 | Write-Verbose -Message "[v] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Extracting zip archive to $DestinationPath"
117 | Expand-Archive -Path $OutFile -DestinationPath $DestinationPath -Force -Confirm:$False -Verbose:$False
118 |
119 | } # End If Else
120 |
121 | } Else {
122 |
123 | Throw "[x] $(Get-Date -Format 'MM-dd-yyyy hh:mm:ss') Failed to validate hash of newly downloaded file for WinSCP"
124 |
125 | } # End If Else
126 |
127 | } # End Function Install-WinSCPNetAssembly
128 |
--------------------------------------------------------------------------------
/Invoke-MissingUpdateInstallation.ps1:
--------------------------------------------------------------------------------
1 | Function Invoke-MissingUpdateInstallation {
2 | <#
3 | .SYNOPSIS
4 | This cmdlet is used to install missing Windows and 3rd Party Application updates that are approved in SCCMs Software Center. You can specify a retry count for updates that fail the first time or two. This uses CIM connections to accomplish the task
5 |
6 |
7 | .DESCRIPTION
8 | This cmdlet can be run locally on a machine to look for and install any approved SCCM server approved updates. This allows you to attempt multiple times to install an update since the first attempt will seomtimes fail
9 |
10 |
11 | .PARAMETER ComputerName
12 | Define remote computer(s) you wish to install missing updates on
13 |
14 | .PARAMETER KBs
15 | Define the specific KBs you wish to install
16 |
17 | .PARAMETER Credential
18 | Define the credentials that should be used to remotely connect to devices using CIM sessions with WinRM
19 |
20 | .PARAMETER Seconds
21 | Define the number of seconds to wait in between retry attempts
22 |
23 | .PARAMETER RetryCount
24 | Define the number of times to retry and installation before giving up on it
25 |
26 | .PARAMETER UseSSL
27 | Build CIM Sessions using WinRM over HTTPS
28 |
29 |
30 | .EXAMPLE
31 | Invoke-MissingUpdateInstallation
32 | # This example attempts to install any missing SCCM approved updates on the local device. It retries failed updates twice with 90 second intervals bewteen attempts
33 |
34 | .EXAMPLE
35 | Invoke-MissingUpdateInstallation -ComputerName DC01.domain.com,FS01.domain.com,DHCP.domain.com -UseSSL -Credential $LiveCred -Seconds 45 -RetryCount 1
36 | # This example installs missing updates on the 3 defined remote machines over a WinRM over HTTPS CIM session. If an attempt fails it will wait 45 seconds and retry once more before moving on to the next update check
37 |
38 |
39 | .INPUTS
40 | System.String ComputerName
41 |
42 | .OUTPUTS
43 | PSCustomObject
44 |
45 |
46 | .NOTES
47 | Author: Robert H. Osborne
48 | Alias: tobor
49 | Contact: rosborne@osbornepro.com
50 |
51 |
52 | .LINK
53 | https://github.com/tobor88
54 | https://github.com/OsbornePro
55 | https://www.powershellgallery.com/profiles/tobor
56 | https://osbornepro.com
57 | https://writeups.osbornepro.com
58 | https://btpssecpack.osbornepro.com
59 | https://www.powershellgallery.com/profiles/tobor
60 | https://www.hackthebox.eu/profile/52286
61 | https://www.linkedin.com/in/roberthosborne/
62 | https://www.credly.com/users/roberthosborne/badges
63 | #>
64 | [CmdletBinding(DefaultParameterSetName="Local")]
65 | param(
66 | [Parameter(
67 | ParameterSetName="Remote",
68 | Position=0,
69 | Mandatory=$True,
70 | ValueFromPipeline=$True,
71 | ValueFromPipelineByPropertyName=$True)] # End Parameter
72 | [Parameter(
73 | ParameterSetName="Local",
74 | Position=0,
75 | Mandatory=$False,
76 | ValueFromPipeline=$True,
77 | ValueFromPipelineByPropertyName=$True)] # End Parameter
78 | [String[]]$ComputerName = "$env:COMPUTERNAME.$((Get-CimInstance -ClassName Win32_ComputerSystem).Domain)",
79 |
80 | [Parameter(
81 | Mandatory=$False,
82 | Position=1,
83 | ValueFromPipeline=$False
84 | )] # End Parameter
85 | [String[]]$KBs,
86 |
87 | [ValidateNotNull()]
88 | [System.Management.Automation.PSCredential]
89 | [System.Management.Automation.Credential()]
90 | [Parameter(ParameterSetName="Remote")]
91 | $Credential = [System.Management.Automation.PSCredential]::Empty,
92 |
93 | [Parameter(
94 | Mandatory=$False,
95 | ValueFromPipeline=$False
96 | )] # End Parameter
97 | [Int32]$Seconds = 90,
98 |
99 | [Parameter(
100 | Mandatory=$False,
101 | ValueFromPipeline=$False
102 | )] # End Parameter
103 | [Int32]$RetryCount = 3,
104 |
105 | [Parameter(
106 | ParameterSetName="Remote",
107 | Mandatory=$False)] # End Parameter
108 | [Switch][Bool]$UseSSL
109 | ) # End param
110 |
111 | BEGIN {
112 |
113 | $Return = @()
114 | $NotReachable = @()
115 |
116 | $ConfirmSSL = $False
117 | If ($UseSSL.IsPresent) {
118 |
119 | $ConfirmSSL = $True
120 |
121 | } # End If
122 |
123 | } PROCESS {
124 |
125 | If ($PSCmdlet.ParameterSetName -eq "Remote") {
126 |
127 | Write-Verbose "Builindg CIM Sessions for $ComputerName"
128 | $CIMSession = New-CimSession -ComputerName $ComputerName -Credential $Credential -SessionOption (New-CIMSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -UseSsl:$ConfirmSSL) -ErrorAction SilentlyContinue
129 | $CIMConnections = (Get-CimSession).ComputerName
130 | ForEach ($C in $ComputerName) {
131 |
132 | If ($C -notin $CIMConnections) {
133 |
134 | $NotReachable += $C
135 |
136 | } # End If
137 |
138 | } # End ForEach
139 |
140 | } # End If
141 |
142 | Write-Verbose "Getting the missing updates from SCCM clients"
143 | If ($CIMSession) {
144 |
145 | Write-Output "[*] Getting missing updates on $ComputerName"
146 | [CimInstance[]]$MissingUpdates = Get-CimInstance -CimSession $CIMSession -NameSpace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate" -Filter "ComplianceState=0" -ErrorAction Stop
147 |
148 | } Else {
149 |
150 | Write-Output "[*] Getting Missing updates on $env:COMPUTERNAME"
151 | [CimInstance[]]$MissingUpdates = Get-CimInstance -NameSpace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate" -Filter "ComplianceState=0"
152 |
153 | } # End If Else
154 |
155 |
156 | If ($Null -eq $MissingUpdates) {
157 |
158 | Write-Output "[*] No missing updates found."
159 |
160 | } Else {
161 |
162 | If ($PSBoundParameters.ContainsKey('KBs')) {
163 |
164 | [CimInstance[]]$MissingUpdates = $MissingUpdates | Where-Object -FilterScript { $_.ArticleID -in $KBs.Replace("KB","") }
165 |
166 | } # End If
167 |
168 | Write-Output "[*] Installing the below missing updates: `n$($MissingUpdates | Select-Object -ExpandProperty ArticleID -Unique)"
169 | If ($CIMSession) {
170 |
171 | Invoke-CimMethod -CimSession $CIMSession -Namespace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdatesManager" -MethodName InstallUpdates -Arguments @{ CCMUpdates=[CimInstance[]]$MissingUpdates} -ErrorAction SilentlyContinue | Out-Null
172 |
173 | } Else {
174 |
175 | Invoke-CimMethod -Namespace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdatesManager" -MethodName InstallUpdates -Arguments @{ CCMUpdates=[CimInstance[]]$MissingUpdates} -ErrorAction SilentlyContinue | Out-Null
176 |
177 | } # End If Else
178 |
179 | ForEach ($C in $ComputerName) {
180 |
181 | ForEach ($MissingUpdate in $MissingUpdates) {
182 |
183 | $State = $MissingUpdate | Select-Object -ExpandProperty EvaluationState
184 | Switch ($State) {
185 |
186 | '0' { $JobState = "ciJobStateNone" }
187 | '1' { $JobState = "ciJobStateAvailable" }
188 | '2' { $JobState = "ciJobStateSubmitted" }
189 | '3' { $JobState = "ciJobStateDetecting" }
190 | '4' { $JobState = "ciJobStatePreDownload" }
191 | '5' { $JobState = "ciJobStateDownloading" }
192 | '6' { $JobState = "ciJobStateWaitInstall" }
193 | '7' { $JobState = "ciJobStateInstalling" }
194 | '8' { $JobState = "ciJobStatePendingSoftReboot" }
195 | '9' { $JobState = "ciJobStatePendingHardReboot" }
196 | '10' { $JobState = "ciJobStateWaitReboot" }
197 | '11' { $JobState = "ciJobStateVerifying" }
198 | '12' { $JobState = "ciJobStateInstallComplete" }
199 | '13' { $JobState = "ciJobStateError" }
200 | '14' { $JobState = "ciJobStateWaitServiceWindow" }
201 | '15' { $JobState = "ciJobStateWaitUserLogon" }
202 | '16' { $JobState = "ciJobStateWaitUserLogoff" }
203 | '17' { $JobState = "ciJobStateWaitJobUserLogon" }
204 | '18' { $JobState = "ciJobStateWaitUserReconnect" }
205 | '19' { $JobState = "ciJobStatePendingUserLogoff" }
206 | '20' { $JobState = "ciJobStatePendingUpdate" }
207 | '21' { $JobState = "ciJobStateWaitingRetry" }
208 | '22' { $JobState = "ciJobStateWaitPresModeOff" }
209 | '23' { $JobState = "ciJobStateWaitForOrchestration" }
210 |
211 | } # End Switch
212 |
213 | $Return += New-Object -TypeName PSCustomObject -Property @{
214 | JobState=$JobState;
215 | ComputerName=$C;
216 | Update=$MissingUpdate.Name;
217 | PercentComplete=$MissingUpdate.PercentComplete;
218 | ArticleId=$MissingUpdate.ArticleID;
219 | ComplianceState=$MissingUpdate.ComplianceState;
220 | Deadline=$MissingUpdate.Deadline;
221 | UpdateID=$MissingUpdate.UpdateID;
222 | } # End New-Object -Property
223 |
224 | } # End ForEach
225 |
226 | } # End ForEach
227 |
228 | $NotReachable | ForEach-Object {
229 |
230 | $Return += New-Object -TypeName PSCustomObject -Property @{
231 | JobState="CIM Session could not be created";
232 | ComputerName=$_;
233 | Update="CIM Session could not be created";
234 | PercentComplete="CIM Session could not be created";
235 | ArticleId="CIM Session could not be created";
236 | ComplianceState="CIM Session could not be created";
237 | Deadline="CIM Session could not be created";
238 | UpdateID="CIM Session could not be created";
239 | } # End New-Object -Property
240 |
241 | } # End ForEach
242 |
243 | Write-Output "[*] Waiting $Seconds seconds for updates to reach an in progress related status"
244 | Start-Sleep -Seconds $Seconds
245 |
246 | $Result = $True
247 | $Counter = 0
248 | While ($Result -eq $True -or $Counter -ne $RetryCount) {
249 |
250 | If ($CIMSession) {
251 |
252 | $CCMUpdate = Get-CimInstance -CimSession $CIMSession -Namespace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate" -ErrorAction SilentlyContinue
253 |
254 | } Else {
255 |
256 | $CCMUpdate = Get-CimInstance -Namespace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdate"
257 |
258 | } # End If Else
259 |
260 | [Array]$UniqueStatus = $CCMUpdate | Sort-Object -Property EvalutationState -Unique
261 | If ([Array]$UniqueStatus.EvaluationState -Contains 13 -or $UniqueStatus -Contains 21) {
262 |
263 | $RetryUpdate = $CCMUpdate | Where-Object -FilterScript { $_.EvalutationState -eq 13 -or $_.EvaluationState -eq 21 }
264 | $RetryCIM = $CIMSession | Where-Object -FilterScript { $_.ComputerName -in $RetryUpdate.ComputerName }
265 |
266 | Write-Output "[*] Retrying one last time the installation attempt of the missing updates"
267 | Invoke-CimMethod -ComputerName $RetryCIM -Namespace "Root\CCM\ClientSDK" -ClassName "CCM_SoftwareUpdatesManager" -MethodName InstallUpdates -Arguments @{ CCMUpdates=[CimInstance[]]$MissingUpdates} -ErrorAction SilentlyContinue | Out-Null
268 |
269 | Write-Output "[*] Waiting $Seconds Seconds for update to start"
270 | Start-Sleep -Seconds $Seconds
271 |
272 | } # End If
273 |
274 | $Result = If (@($CCMUpdate | Where-Object -FilterScript { $_.EvaluationState -eq 2 -or $_.EvaluationState -eq 3 -or $_.EvaluationState -eq 4 -or $_.EvaluationState -eq 5 -or $_.EvaluationState -eq 6 -or $_.EvaluationState -eq 7 -or $_.EvaluationState -eq 11 }).length -ne 0) {
275 |
276 | $True
277 |
278 | } Else {
279 |
280 | $False
281 |
282 | } # End If Else
283 |
284 | Start-Sleep -Seconds 5
285 | $Counter++
286 |
287 | } # End While
288 |
289 | If ($CIMSession) {
290 |
291 | Write-Verbose "Closing CIM Sessions"
292 | Remove-CimSession -CimSession $CIMSession -Confirm:$False -ErrorAction SilentlyContinue
293 |
294 | } # End If
295 |
296 | } # End If Else
297 |
298 | } END {
299 |
300 | Return $Return
301 |
302 | } # End B P E
303 |
304 | } # End Function Invoke-MissingUpdateInstallation
305 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 tobor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Windows Updates
2 |
3 | This repository contains a collection of PowerShell cmdlets that are useful in updating Windows and troubleshooting issues. Updates that deal with SCCM are also included.
4 |
5 |
6 | ## Cmdlet List
7 |
8 | - **Add-CMSystemDiscoveryMethodContainer** (*Adds new LDAP containers to query to the SCCM servers system discovery filter*)
9 | - **Clear-GpoRegistrySettings.ps1** (*Fix failed Windows Updates caused by policy errors*)
10 | - **Get-ComponentDescription** (*Return descriptino of log file based on component name*)
11 | - **Get-KBDownloadLink.ps1** (*Returns a download link for the defined KB article ID for the current OS version and architecture or defined version and architecture*)
12 | - **Get-KnownIssuesWindowsUpdates.ps1** (*Returns information on the latest months Windows patching issues*)
13 | - **Get-MissingDeviceUpdate.ps1** (*Return information on missing updates or approved missing SCCM updates*)
14 | - **Get-SccmSoftwareUpdateStatus.ps1** (*Return device in SCCM matching a certain status such as Error or Unknown*)
15 | - **Get-WindowsUpdateError.ps1** (*Save a log file to your desktop containing logs on Windows Updates*)
16 | - **Get-WindowsUpdateErrorCode.ps1** (*Return the error code reason for failed Windows Updates, save log files to desktop, and option to run troubleshooter*)
17 | - **Get-UpdateHistory.p1** (*Returns information on the history of Windows Updates*)
18 | - **Install-7Zip.ps1** (*Install or update 7Zip. I have not found a checksum to use for verification*)
19 | - **Install-AzureCLI.ps1** (*Install or update the Azure CLI. I have not found a checksum to use for verification*)
20 | - **Install-AzureStorageExplorer.ps1** (*Install or update the Azure Storage Explorer. I have not found a checksum to use for verification*)
21 | - **Install-CherryTree.ps1** (*Install or update CherryTree after verifying checksum*)
22 | - **Install-DrawIO.ps1** (*Install or update Draw.io after verifying checksum*)
23 | - **Install-FileZilla.ps1** (*Install or update FileZilla after verifying checksum*)
24 | - **Install-GitForWindows.ps1** (*Install or update Git for Windows after verifying checksum*)
25 | - **Install-KeePass.ps1** (*Install or update KeePass after verifying checksum*)
26 | - **Install-NodeJS.ps1** (*Install or update NodeJS after verifying checksum*)
27 | - **Install-NotepadPlusPlus.ps1** (*Install or update Notepad++ after verifying checksum*)
28 | - **Install-PowerShellCore.ps1** (*Install or update PowerShell Core after verifying checksum*)
29 | - **Install-Putty.ps1** (*Download and install Putty and verifiy checksum*)
30 | - **Install-RemoteDesktopManager.ps1** (*Download and install Remote Desktop Manager*)
31 | - **Install-SccmAgent.ps1** (*Install or reinstall the SCCM Agent on a device*)
32 | - **Install-Signal.ps1** (*Install or update Signal after verifying checksum*)
33 | - **Install-SSMS.ps1** (*Installs or updates SSMS. No checksum value that can be verified*)
34 | - **Install-VLC.ps1** (*Install or update VLC after verifying checksum*)
35 | - **Install-VSCode.ps1** (*Install or update Visual Studio Code. Unable to verify checksum automatically yet*)
36 | - **Install-WinRAR.ps1** (*Install or update WinRAR. They do not offer a checksum. Use 7Zip its better*)
37 | - **Install-WinSCP.ps1** (*Install or update WinSCP after verifying checksum*)
38 | - **Install-WinSCPNETAssembly.ps1** (*Download the WinSCP DLL required for writing PowerShell scripts with NET assembly. Checksum gets verified*)
39 | - **Invoke-MissingUpdateInstallation.ps1** (*Installs SCCM approved missing updates ona device*)
40 | - **Remove-CMSystemDiscoveryMethodContainer** (*Removes LDAP containers from query on the SCCM servers system discovery filter*)
41 | - **Remove-WindowsUpdate.ps1** (*Uninstall a Windows Update by KB number on a remote or local device*)
42 | - **Repair-WindowsUpdate.ps1** (*Stops Windows Update related services and renames directory locations which fixes 90% of all update issues in my experience*)
43 | - **Reset-SccmAgent.ps1** (*Delete the SCCM cache files and restart the service*)
44 | - **Update-Windows.ps1** (*Install any missing Windows Updates*)
45 |
46 |
47 | ### I am merely a contributor to the Update-Windows script.
48 |
49 | __REFERENCE:__ HERE
50 | __REFERENCE:__ HERE.
51 |
52 | I have added some functionality and improved them wherever I saw fit.
53 |
54 | If you make any changes or find a better way to do something feel free to send it to me so I have it too. :)
55 |
--------------------------------------------------------------------------------
/Remove-CMSystemDiscoveryMethodContainer.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 | Function Remove-CMSystemDiscoveryMethodContainer {
3 | <#
4 | .SYNOPSIS
5 | Remove an Organizational Units (OU) by distinguished name from Active Directory System Discovery components in ConfigMgr
6 |
7 |
8 | .DESCRIPTION
9 | This cmdlet uses the distinguished name defined in -SearchBase to remove the System Discovery method on an SCCM server
10 |
11 |
12 | .PARAMETER SiteServer
13 | SCCM Site Server to connect too
14 |
15 | .PARAMETER UseSSL
16 | Creates CIM session to SCCM server using SSL (WinRM over HTTPS)
17 |
18 | .PARAMETER SkipCACheck
19 | Skip Certificate authority trust check on WinRM connnection
20 |
21 | .PARAMETER SkipCNCheck
22 | Skip verifying the CN/subject name on the WinRM certificate
23 |
24 | .PARAMETER SkipRevocationCheck
25 | Skip checking certificate revocation for WinRM connections
26 |
27 | .PARAMETER SearchBase
28 | Define the LDAP container OU path to new domains being added to System Discovery
29 |
30 | .PARAMETER Credential
31 | Enter credentials to authenticate to the SCCM server
32 |
33 |
34 | .EXAMPLE
35 | Remove-CMSystemDiscoveryMethodContainer -SiteServer sccm-server.domain.com -SearchBase "DC=domain,DC=com"
36 | # This example adds the domain.com LDAP search base filter to the domain System Discovery method on the sccm-server.domain.com SCCM server
37 |
38 | .EXAMPLE
39 | Remove-CMSystemDiscoveryMethodContainer -SiteServer sccm-server.domain.com -UseSSL -SkipCACheck -SkipCNCheck -SkipRevocationCheck -SearchBase "LDAP:\\DC=domain,DC=com"
40 | # This example adds the domain.com LDAP search base filter to the domain System Discovery method on the sccm-server.domain.com SCCM server
41 |
42 |
43 | .NOTES
44 | Author: Robert H. Osborne
45 | Alias: tobor
46 | Contact: info@osbornerpo.com
47 |
48 |
49 | .INPUTS
50 | None
51 |
52 |
53 | .OUTPUTS
54 | None
55 | #>
56 | [CmdletBinding(
57 | SupportsShouldProcess=$True,
58 | ConfirmImpact="Medium"
59 | )] # End CmdletBinding
60 | param(
61 | [Parameter(
62 | Mandatory=$True,
63 | ValueFromPipeline=$False,
64 | HelpMessage="Site server where the SMS Provider is installed.")] # End Parameter
65 | [ValidateNotNullOrEmpty()]
66 | [String]$SiteServer,
67 |
68 | [Parameter(
69 | Mandatory=$False
70 | )] # End Parameter
71 | [Switch]$UseSSL,
72 |
73 | [Parameter(
74 | Mandatory=$False
75 | )] # End Parameter
76 | [Switch]$SkipCACheck,
77 |
78 | [Parameter(
79 | Mandatory=$False
80 | )] # End Parameter
81 | [Switch]$SkipCNCheck,
82 |
83 | [Parameter(
84 | Mandatory=$False
85 | )] # End Parameter
86 | [Switch]$SkipRevocationCheck,
87 |
88 | [Parameter(
89 | Mandatory=$True,
90 | ValueFromPipeline=$True,
91 | ValueFromPipelineByPropertyName=$False,
92 | HelpMessage="Specify the Active Directory Search Base `nEXAMPLE: DC=domain,DC=com : ")] # End Parameter
93 | [ValidateScript({$_ -like "*DC=*,DC=*"})]
94 | [String]$SearchBase,
95 |
96 | [ValidateNotNull()]
97 | [System.Management.Automation.PSCredential]
98 | [System.Management.Automation.Credential()]
99 | $Credential = [System.Management.Automation.PSCredential]::Empty
100 | ) # End param
101 |
102 | BEGIN {
103 |
104 | $ComponentName = "SMS_AD_SYSTEM_DISCOVERY_AGENT"
105 | Try {
106 |
107 | Write-Verbose -Message "Determining Site Code for Site server: '$($SiteServer)'"
108 | $CIMSession = New-CimSession -Credential $Credential -ComputerName $SiteServer -SessionOption (New-CimSessionOption -UseSSL:$UseSSL.IsPresent -SkipCACheck:$SkipCACheck.IsPresent -SkipCNCheck:$SkipCNCheck.IsPresent -SkipRevocationCheck:$SkipReovcationCheck.IsPresent -Verbose:$False) -Verbose:$False
109 | $SiteCodeObjects = Get-CimInstance -CimSession $CIMSession -Namespace "Root\SMS" -ClassName SMS_ProviderLocation -ErrorAction Stop
110 |
111 | ForEach ($SiteCodeObject in $SiteCodeObjects) {
112 |
113 | If ($SiteCodeObject.ProviderForLocalSite -eq $True) {
114 |
115 | $SiteCode = $SiteCodeObject.SiteCode
116 | Write-Verbose -Message "Site Code: $($SiteCode)"
117 | Break
118 |
119 | } # End If
120 |
121 | } # End ForEach
122 |
123 | } Catch [System.UnauthorizedAccessException] {
124 |
125 | Throw "[x] Access denied"
126 |
127 | } Catch [System.Exception] {
128 |
129 | Throw "[x] Unable to determine Site Code"
130 |
131 | } # End Try Catch Catch
132 |
133 | If ($SearchBase -notlike "LDAP://*") {
134 |
135 | $SearchBase = "LDAP://$($SearchBase)"
136 |
137 | } # End If
138 |
139 | } PROCESS {
140 |
141 | Write-Verbose -Message "Determining the existing containers for selected Discovery Method"
142 | Try {
143 |
144 | $DiscoveryContainerList = New-Object -TypeName System.Collections.ArrayList
145 | $DiscoveryComponent = Get-WmiObject -Class SMS_SCI_Component -Namespace "Root\SMS\Site_$($SiteCode)" -ComputerName $SiteServer -Filter "ComponentName like '$($ComponentName)'" -Credential $Credential -ErrorAction Stop -Verbose:$False
146 | $DiscoveryPropListADContainer = $DiscoveryComponent.PropLists | Where-Object -FilterScript { $_.PropertyListName -like "AD Containers" }
147 |
148 | } Catch [System.Exception] {
149 |
150 | Throw "[x] Unable to determine existing discovery method component properties"
151 |
152 | } # End Catch
153 |
154 | Try {
155 |
156 | Write-Verbose -Message "Attempting to save changes made to the $($ComponentName) component PropList"
157 | $LdapLocations = ($DiscoveryPropListADContainer.Values | Select-String -Pattern "LDAP:\\*" | Out-String).Trim().Split([System.Environment]::NewLine) | Where-Object -FilterScript { $_ -notlike $SearchBase -and $_ -notlike "" }
158 | $DiscoveryContainerList.AddRange(@($($LdapLocations | ForEach-Object { $_; 0; 1} ))))
159 | $DiscoveryPropListADContainer.Values = $DiscoveryContainerList
160 | If ($PSCmdlet.ShouldProcess($DiscoveryComponent.Put())) {
161 |
162 | $DiscoveryComponent.Put() | Out-Null
163 |
164 | } # End If
165 |
166 | } Catch {
167 |
168 | Throw "[x] Unable to save changes made to $($ComponentName) component"
169 |
170 | } # End Try Catch
171 |
172 | } END {
173 |
174 | If ($CIMSession) {
175 |
176 | Remove-CimSession -CimSession $CIMSession -Confirm:$False -WhatIf:$False -Verbose:$False
177 |
178 | } # End If
179 |
180 | } # End END
181 |
182 | } # End Function Remove-CMSystemDiscoveryMethodContainer
183 |
--------------------------------------------------------------------------------
/Remove-WindowsUpdate.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is for uninstalling a Windows Update.
4 | This can remove multiple hot fixes and it can remove hot fixes from an array of remote computers.
5 |
6 |
7 | .DESCRIPTION
8 | Cmdlet that is used to remove a speficied Windows Update or Updatesfrom a local computer or a remote host or hosts.
9 | A list of computer names can be piped to this function by property name.
10 |
11 |
12 | .PARAMETER HotFixID
13 | Specifies the hotfix IDs that this cmdlet gets.
14 |
15 | .PARAMETER ComputerName
16 | Specifies a remote computer. The default is the local computer.
17 |
18 | .PARAMETER Restart
19 | Indicates you wish to perform a restart after removing the update.
20 |
21 | .EXAMPLE
22 | Remove-WindowsUpdate -HotFixID "4556799"
23 | # This examples uninstalls 4556799 from the local computer if it is installed.
24 |
25 | .EXAMPLE
26 | Remove-WindowsUpdate "KB4556799"
27 | # This examples also uninstalls HotFix KB4556799 from the local computer.
28 |
29 | .EXAMPLE
30 | Remove-WindowsUpdate -HotFixID "KB4556799" -ComputerName 10.10.10.120 -Restart
31 | # This examples uninstalls HotFix KB4556799 from a remote computer at 10.10.10.120 and if a restart is needed allows it to restart.
32 |
33 | .EXAMPLE
34 | Remove-WindowsUpdate "KB4556799" 10.10.10.120
35 | # This examples also uninstalls HotFix KB4556799 from a remote computer at 10.10.10.120.
36 |
37 |
38 | .NOTES
39 | Author: Robrt H. Osborne
40 | Alias: tobor
41 | Contact: rosborne@osbornepro.com
42 |
43 |
44 | .INPUTS
45 | System.String
46 | You can pipe computer names to this cmdlet..
47 | In Windows PowerShell 2.0, the ComputerName parameter takes input from the pipeline only by property name.
48 | In Windows PowerShell 3.0, the ComputerName parameter takes input from the pipeline by value.
49 |
50 |
51 | .OUTPUTS
52 | None, System.Management.Automation.RemotingJob
53 | This cmdlet returns a job object, if you specify the AsJob parameter. Otherwise, it does not generate any output.
54 |
55 |
56 | .LINK
57 | https://github.com/tobor88
58 | https://github.com/osbornepro
59 | https://www.powershellgallery.com/profiles/tobor
60 | https://osbornepro.com
61 | https://writeups.osbornepro.com
62 | https://btpssecpack.osbornepro.com
63 | https://www.powershellgallery.com/profiles/tobor
64 | https://www.hackthebox.eu/profile/52286
65 | https://www.linkedin.com/in/roberthosborne/
66 | https://www.credly.com/users/roberthosborne/badges
67 | #>
68 | Function Remove-WindowsUpdate {
69 | [CmdletBinding()]
70 | param(
71 | [Parameter(
72 | Mandatory=$True,
73 | Position=0,
74 | ValueFromPipeline=$False,
75 | HelpMessage="Enter the Windows Update KB number(s) you wish to uninstall. Separate multiple values with a comma.`nExample: KB4556799','KB4556798' (4556799 is also acceptable) `n")] # End Paramater
76 | [String[]]$HotFixID,
77 |
78 | [Parameter(
79 | Mandatory=$False,
80 | Position=1,
81 | ValueFromPipeline=$True,
82 | ValueFromPipelineByPropertyName=$True,
83 | HelpMessage="Enter the name or names of the remote compute you wish to uninstall. Separate multiple values with a comma. `nExample: 'Comp1.domain.com','Comp2','10.10.10.123'`n")] # End Paramater
84 | [ValidateNotNullOrEmpty()]
85 | [String[]]$ComputerName,
86 |
87 | [Parameter(
88 | Mandatory=$False,
89 | ValueFromPipeline=$False)]
90 | [ValidateNotNull()]
91 | [System.Management.Automation.PSCredential]
92 | [System.Management.Automation.Credential()]
93 | $Credential = [System.Management.Automation.PSCredential]::Empty,
94 |
95 | [Parameter(
96 | Mandatory=$False)]
97 | [Switch][Bool]$Restart
98 | ) # End param
99 |
100 | BEGIN {
101 |
102 | If ($ComputerName) {
103 |
104 | For ($i = 0; $i -lt $ComputerName.Count ; $i++) {
105 |
106 | ForEach ($Computer in $ComputerName) {
107 |
108 | Write-Verbose "[*] Testing specified $Computer is reachable"
109 | If (Test-Connection -ComputerName $Computer -Count 2 -BufferSize 32 -Quiet -ErrorAction Inquire) {
110 |
111 | Write-Verbose "[*] $Computer is reachable"
112 | If ($Null -eq $Credential) {
113 |
114 | $Credential = Get-Credential -Message "Administrator Credentials are required to execute commands on remote hosts" -Username ($env:USERNAME + "@" + $env:USERDNSDOMAIN)
115 |
116 | } # End If
117 |
118 | New-Variable -Name "Session$i" -Value (New-PsSession -ComputerName $Computer -Credential $Credential -Name $Computer -EnableNetworkAccess -Port 5985)
119 |
120 | } # End If
121 |
122 | } # End ForEach
123 |
124 | } # End For
125 |
126 | } # End If
127 |
128 | } # End BEGIN
129 | PROCESS {
130 |
131 | If ($ComputerName) {
132 |
133 | For ($n = 0; $n -lt $ComputerName.Count; $n++) {
134 |
135 | ForEach ($C in $ComputerName) {
136 |
137 | Write-Verbose "[*] Starting connection to $C"
138 | Invoke-Command -Session (Get-Variable -Name "Session$n").Value -ArgumentList $HotFixID -ScriptBlock {
139 | param([array]$HotFixID)
140 |
141 | Write-Output "[*] $env:COMPUTERNAME: Getting list of installed patches"
142 | $PatchList = Get-CimInstance -ClassName "Win32_QuickFixEngineering" -Namespace "root\cimv2"
143 |
144 | ForEach ($HotFix in $HotFixID) {
145 |
146 | $Patch = $PatchList | Where-Object { $_.HotFixID -like "$HotFix" }
147 | Write-Output "[*] $Patch will be removed from $env:COMPUTERNAME"
148 |
149 | If (!($Patch)) {
150 |
151 | Write-Output "[!] $env:COMPUTERNAME: The Windows Update KB number you defined is not installed on $env:COMPUTERNAME. Below is a table of installed patches: "
152 | Remove-Variable -Name "Patch"
153 |
154 | $PatchList
155 |
156 | } # End If
157 | Else {
158 |
159 | Write-Output "[*] $env:COMPUTERNAME: $HotFix is installed on $env:COMPUTERNAME, continuing uninstallation"
160 | $KBNumber = $Patch.HotfixId.Replace("KB", "") | Out-String
161 |
162 | If ($Restart.IsPresent) {
163 |
164 | Write-Output "[*] $env:COMPUTERNAME: Restart switch parameter is defined. You will be prompted to restart."
165 | cmd /c wusa /uninstall /kb:$KBNumber /promptrestart /log
166 |
167 | } # End If
168 | Else {
169 |
170 | cmd /c echo y | wusa /uninstall /kb:$KBNumber /norestart /log
171 |
172 | } # End Else
173 |
174 | While (@(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0) {
175 |
176 | Start-Sleep -Seconds 10
177 | Write-Output "[*] $env:COMPUTERNAME: Waiting for update removal to finish. Please wait..."
178 |
179 | } # End While
180 |
181 | } # End Else
182 |
183 | } # End ForEach
184 |
185 | } # End Invoke-Command
186 |
187 | Write-Output "[*] Finished removing updates from $C"
188 |
189 | } # End ForEach
190 |
191 | } # End For
192 |
193 | } # End If
194 | Else {
195 |
196 | Write-Verbose "[*] $env:COMPUTERNAME: Getting list of installed patches"
197 | $PatchList = Get-CimInstance -ClassName "Win32_QuickFixEngineering" -Namespace "root\cimv2"
198 |
199 | ForEach ($HotFix in $HotFixID) {
200 |
201 | $Patch = $PatchList | Where-Object { $_.HotFixID -like "$HotFix" }
202 | If (!($Patch)) {
203 |
204 | Write-Output "[!] $env:COMPUTERNAME: The Windows Update KB number you defined is not installed on $env:COMPUTERNAME. Below is a table of installed patches: "
205 | Remove-Variable -Name "Patch"
206 |
207 | $PatchList
208 |
209 | } # End If
210 | Else {
211 |
212 | $KBNumber = $Patch.HotfixId.Replace("KB", "") | Out-String
213 | If ($Restart.IsPresent) {
214 |
215 | Write-Output "[*] $env:COMPUTERNAME: Restart switch parameter is defined. You will be prompted to restart."
216 | cmd /c wusa /uninstall /kb:$KBNumber /promptrestart /log
217 |
218 | } # End If
219 | Else {
220 |
221 | cmd /c wusa /uninstall /kb:$KBNumber /norestart /log
222 |
223 | } # End Else
224 |
225 | While (@(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0) {
226 |
227 | Start-Sleep -Seconds 10
228 | Write-Output "[*] Waiting for update removal to finish. Please wait..."
229 |
230 | } # End While
231 |
232 | Write-Output "[*] Update removal has completed"
233 |
234 | } # End Else
235 |
236 | } # End ForEach
237 |
238 | } # End Else
239 |
240 | } # End PROCESS
241 | END {
242 |
243 | If (Get-PsSession) {
244 |
245 | Write-Verbose "[*] Closing connection to remote computers."
246 | Remove-PsSession *
247 |
248 | } # End If
249 |
250 | } # End END
251 |
252 | } # End Function Remove-WindowsUpdate
253 |
--------------------------------------------------------------------------------
/Repair-WindowsUpdate.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to perform a typical repair operation for Windows Updates that are stuck in a Retry Fail cycle
4 |
5 |
6 | .DESCRIPTION
7 | Performs actions that typicall repair Windows Updates that fail to install
8 |
9 |
10 | .PARAMETER ServiceName
11 | Define the services to stop that allow you to renamed the defined files
12 |
13 | .PARAMETER Path
14 | Define the path(s) to directories to rename that will allow windows update to try downloading and installing updates again
15 |
16 |
17 | .EXAMPLE
18 | Repair-WindowsUpdate -Path "C:\Windows\SoftwareDistribution","C:\Windows\System32\catroot2"
19 | # Stops the services cryptsvc,wuauserv,bits,msiserver and renames the Windows Update directories C:\Windows\SoftwareDistribution and C:\Windows\System32\catroot2 before restarting the computer
20 |
21 | .EXAMPLE
22 | Repair-WindowsUpdate
23 | # Stops the services cryptsvc,wuauserv,bits,msiserver and renames the Windows Update directories C:\Windows\SoftwareDistribution and C:\Windows\System32\catroot2 before restarting the computer
24 |
25 |
26 | .NOTES
27 | Author: Robrt H. Osborne
28 | Alias: tobor
29 | Contact: rosborne@osbornepro.com
30 |
31 |
32 | .INPUTS
33 | None
34 |
35 |
36 | .OUTPUTS
37 | None
38 |
39 |
40 | .LINK
41 | https://github.com/tobor88
42 | https://gitlab.com/tobor88
43 | https://www.powershellgallery.com/profiles/tobor
44 | https://osbornepro.com
45 | https://writeups.osbornepro.com
46 | https://btpssecpack.osbornepro.com
47 | https://www.powershellgallery.com/profiles/tobor
48 | https://www.hackthebox.eu/profile/52286
49 | https://www.linkedin.com/in/roberthosborne/
50 | https://www.credly.com/users/roberthosborne/badges
51 | #>
52 | Function Repair-WindowsUpdate {
53 | [CmdletBinding(SupportsShouldProcess)]
54 | param(
55 | [Parameter(
56 | Position=0,
57 | Mandatory=$False,
58 | ValueFromPipeline=$False)] # End Parameter
59 | [ValidateScript({Get-Service -Name $_})]
60 | [String[]]$Services = @("cryptsvc","wuauserv","bits","msiserver"),
61 |
62 | [Parameter(
63 | Position=1,
64 | Mandatory=$False,
65 | ValueFromPipeline=$False)] # End Parameter
66 | [ValidateScript({Test-Path -Path $_})]
67 | [String[]]$Path = @("C:\Windows\SoftwareDistribution","C:\Windows\System32\catroot2"),
68 |
69 | [Parameter(
70 | Mandatory=$False)] # End Parameter
71 | [Switch][Bool]$Restart
72 |
73 | ) # End param
74 |
75 | If ($PSCmdlet.ShouldProcess($Path)) {
76 |
77 | Write-Output "[*] Stopping services that use the directories we need renamed"
78 | Stop-Service -Name $Services -Force -Confirm:$False
79 |
80 | ForEach ($P in $Path) {
81 |
82 | If (Test-Path -Path "$($P).bak") {
83 |
84 | Write-Output "[*] Removing the previously backed up directory $($P).bak"
85 | Remove-Item -Path "$($P).bak" -Recurse -Force -Confirm:$False
86 |
87 | } # End If
88 |
89 | Write-Output "[*] Renaming $($P) to $($P).bak"
90 | Try {
91 |
92 | Move-Item -Path $P -Destination "$($P).bak" -Force -Confirm:$False
93 |
94 | } Catch {
95 |
96 | Rename-Item -Path $P -NewName "$($P).bak" -Force -Confirm:$False
97 |
98 | } # End Catch
99 |
100 | If ($Restart.IsPresent) {
101 |
102 | Write-Output "[*] Restarting device, update Windows After the restart"
103 | Restart-Computer -Confirm:$False -Force
104 |
105 | } Else {
106 |
107 | Write-Output "[!] Machine still requires a restart to finish fixing failed update"
108 |
109 | } # End If Else
110 |
111 | } # End ForEach
112 |
113 | } Else {
114 |
115 | # The -WhatIf parameter was used. Simulating requested actions.
116 | Stop-Service -Name $Services -Force -Confirm:$False -WhatIf
117 |
118 | ForEach ($P in $Path) {
119 |
120 | If (Test-Path -Path "$($P).bak") {
121 |
122 | Remove-Item -Path "$($P).bak" -Recurse -Force -WhatIf
123 |
124 | } # End If
125 |
126 | Move-Item -Path $P -Destination "$($P).bak" -WhatIf
127 |
128 | If ($Restart.IsPresent) {
129 |
130 | Restart-Computer -WhatIf
131 |
132 | } # End If
133 |
134 | } # End ForEach
135 |
136 | } # End If Else ShouldProcess
137 |
138 | } # End Function Repair-WindowsUpdate
139 |
--------------------------------------------------------------------------------
/Reset-SccmAgent.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This cmdlet is used to clear the SCCM cache and restart the SCCM service which runs all the Actions in Configuration Manager
4 |
5 |
6 | .DESCRIPTION
7 | Clear the SCCM cache and restart the CcmExec service
8 |
9 |
10 | .PARAMETER ServiceName
11 | Define the SCCM service name to restart. Default value is CcmExec
12 |
13 | .PARAMETER Path
14 | Define a path to the SCCM Cache parent directory. Default value is C:\Windows\ccmcache
15 |
16 |
17 | .EXAMPLE
18 | Reset-SccmAgent
19 | # This example restarts the CcmExec service and deletes the cache files in C:\Windows\ccmcache
20 |
21 | .EXAMPLE
22 | Reset-SccmAgent -ServiceName -Path C:\Windows\ccmcache
23 | # This example restarts the CcmExec service and deletes the cache files in C:\Windows\ccmcache
24 |
25 |
26 | .NOTES
27 | Author: Robert H. Osborne
28 | Alias: tobor
29 | Contact: rosborne@osbornepro.com
30 |
31 |
32 | .INPUTS
33 | None
34 |
35 |
36 | .OUTPUTS
37 | None
38 |
39 |
40 | .LINK
41 | https://osbornepro.com
42 | https://btpssecpack.osbornepro.com
43 | https://writeups.osbornepro.com
44 | https://github.com/OsbornePro
45 | https://github.com/tobor88
46 | https://www.powershellgallery.com/profiles/tobor
47 | https://www.hackthebox.eu/profile/52286
48 | https://www.linkedin.com/in/roberthosborne/
49 | https://www.credly.com/users/roberthosborne/badges
50 | #>
51 | Function Reset-SccmAgent {
52 | [CmdletBinding()]
53 | param(
54 | [Parameter(
55 | Position=0,
56 | Mandatory=$False)] # End Parameter
57 | [ValidateScript({Get-Service -Name $_})]
58 | [String]$ServiceName = 'CcmExec',
59 |
60 | [Parameter(
61 | Position=1,
62 | Mandatory=$False
63 | #HelpMessage="Define the SCCM directory containing cache files EXAMPLE: C:\Windows\ccmcache"
64 | )] # End Parameter
65 | [ValidateScript({Test-Path -Path $_})]
66 | [String]$Path = "C:\Windows\ccmcache"
67 | ) # End param
68 |
69 | Write-Verbose "Restarting the $ServiceName service"
70 | Restart-Service -Name $ServiceName -Force -Confirm:$False -PassThru
71 |
72 | Try {
73 |
74 | Write-Verbose "Deleting the file $Path"
75 | Remove-Item -Path $Path -Recurse -Force -ErrorAction Stop
76 |
77 | } Catch {
78 |
79 | Write-Error $_.Exception.Message
80 |
81 | } # End Catch
82 |
83 | } # End Reset-SccmAgent
84 |
--------------------------------------------------------------------------------
/Update-Windows.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Update-Windows is a cmdlet created to update Windows when updates are available. This cmdlet also creates logs of update attempts
4 | System Administrators will be alerted if updates fail. This cmdlet creates a CSV file to be uploaded into a SQL database.
5 | Originally I had this function upload the csv contents into a SQL database. To better coform to PowerShell scripting guidelines I am changing this behavior.
6 |
7 |
8 | .DESCRIPTION
9 | This cmdlet updates windows, logs results, and alerts administrators of failures.
10 |
11 |
12 | .EXAMPLE
13 | Update-Windows
14 | # This example checks for all available Windows Updates and the downloads and installs them logging the results to C:\Windows\Temp\$env:COMPUTERNAME
15 |
16 |
17 | .NOTES
18 | Author: Robert H. Osborne
19 | Alias: tobor
20 | Contact: rosborne@osbornepro.com
21 |
22 | .LINK
23 | https://github.com/tobor88
24 | https://github.com/osbornepro
25 | https://www.powershellgallery.com/profiles/tobor
26 | https://osbornepro.com
27 | https://writeups.osbornepro.com
28 | https://btpssecpack.osbornepro.com
29 | https://www.powershellgallery.com/profiles/tobor
30 | https://www.hackthebox.eu/profile/52286
31 | https://www.linkedin.com/in/roberthosborne/
32 | https://www.credly.com/users/roberthosborne/badges
33 | #>
34 | Function Update-Windows {
35 | [CmdletBinding()]
36 | param () # End param
37 |
38 | $ErrorActionPreference = "SilentlyContinue"
39 | $Today = Get-Date
40 | $FormattedDate = Get-Date -Format MM.dd.yyyy
41 | $UpdateCollection = New-Object -ComObject Microsoft.Update.UpdateColl
42 | $UpdateSearch = New-Object -ComObject Microsoft.Update.Searcher
43 | $Session = New-Object -ComObject Microsoft.Update.Session
44 |
45 | If ($Error) {
46 |
47 | $Error.Clear()
48 |
49 | } # End If
50 |
51 | Write-Verbose "`n`tInitialising and Checking for Applicable Updates. Please wait ..."
52 | $Result = $UpdateSearch.Search("IsInstalled=0 and Type='Software' and IsHidden=0")
53 |
54 | If ($Result.Updates.Count -EQ 0) {
55 |
56 | Write-Verbose "`t$env:COMPUTERNAME is currently up to date."
57 |
58 | } # End if
59 | Else {
60 |
61 | $ReportFile = "C:\Windows\Temp\$env:COMPUTERNAME\$env:COMPUTERNAME`_Report_$FormattedDate.txt"
62 | If (Test-Path -Path $ReportFile) {
63 |
64 | Write-Verbose "Update attempt was run already today. Previous attempt saved as a .txt.old file. New File is located at the following location. `nLOCATION:$ReportFile"
65 | Rename-Item -Path $ReportFile -NewName ("$ReportFile.old") -Force
66 |
67 | } # End If
68 | Elseif (!(Test-Path -Path "C:\Windows\Temp\$env:COMPUTERNAME")) {
69 |
70 | Write-Verbose "Logging folder previously did not exist and is being created at the below location. `nLOCATION: C:\Windows\Temp\$env:COMPUTERNAME"
71 | New-Item -Path "C:\Windows\Temp\$env:COMPUTERNAME" -ItemType Directory -Force | Out-Null
72 |
73 | } # End Elseif
74 |
75 | New-Item -Path $ReportFile -Type 'File' -Force -Value "#===================================================================#`n# Update Report #`n#===================================================================#" | Out-Null
76 |
77 | Add-Content -Path $ReportFile -Value "`n`nComputer Hostname : $env:COMPUTERNAME`r`nCreation Date : $Today`rReport Directory : C:\Windows\Temp\$env:COMPUTERNAME`r`n"
78 | Add-Content -Path $ReportFile -Value "---------------------------------------------------------------------`nAVAILABLE UPDATES`n---------------------------------------------------------------------`r"
79 |
80 | Write-Verbose "`t Preparing List of Applicable Updates For $env:COMPUTERNAME..."
81 | For ($Counter = 0; $Counter -lt $Result.Updates.Count; $Counter++) {
82 |
83 | $DisplayCount = $Counter + 1
84 | $Update = $Result.Updates.Item($Counter)
85 | $UpdateTitle = $Update.Title
86 |
87 | Add-Content -Path $ReportFile -Value "$DisplayCount.) $UpdateTitle"
88 |
89 | $UpdateResultInfo = New-Object -TypeName System.Management.Automation.PSCustomObject -Property @{
90 | UpdateTitle = $UpdateTitle
91 | Hostname = $env:COMPUTERNAME
92 | Date = $FormattedDate } # End Property
93 |
94 | New-Variable -Name UpdateResultInfo$Counter -Value $UpdateResultInfo
95 |
96 | } # End For
97 |
98 | $Counter = 0
99 | $DisplayCount = 0
100 |
101 | Write-Verbose "`t Initialising Download of Applicable Updates ..."
102 | Add-Content -Path $ReportFile -Value "`n---------------------------------------------------------------------`nINITIALISING UPDATE DOWNLOADS`n---------------------------------------------------------------------`n"
103 |
104 | $Downloader = $Session.CreateUpdateDownloader()
105 | $UpdatesList = $Result.Updates
106 |
107 | For ($Counter = 0; $Counter -LT $Result.Updates.Count; $Counter++) {
108 |
109 | $UpdateCollection.Add($UpdatesList.Item($Counter)) | Out-Null
110 | $ShowThis = $UpdatesList.Item($Counter).Title
111 | $DisplayCount = $Counter + 1
112 |
113 | Add-Content -Path $ReportFile -Value "$DisplayCount.) Downloading Update: $ShowThis `r"
114 |
115 | $Downloader.Updates = $UpdateCollection
116 | $Track = $Downloader.Download()
117 |
118 | If (($Track.HResult -EQ 0) -AND ($Track.ResultCode -EQ 2)) {
119 |
120 | Add-Content -Path $ReportFile -Value "`tDownload Status: SUCCESS"
121 |
122 | If ($ShowThis -like ((Get-Variable -Name UpdateResultInfo($Counter)).Title)) {
123 |
124 | Add-Member -InputObject (Get-Variable -Name UpdateResultInfo($Counter)) -NotePropertyName "DownloadStatus" -NotePropertyValue 'Successfully Downloaded'
125 |
126 | } # End If
127 |
128 | } # End If
129 |
130 | Else {
131 |
132 | $FailError = $Error[0]
133 | Add-Content -Path $ReportFile -Value "`tDownload Status: FAILED With Error `n`t`t $FailError"
134 | If ($ShowThis -like ((Get-Variable -Name UpdateResultInfo($Counter)).Title)) {
135 |
136 | Add-Member -InputObject (Get-Variable -Name UpdateResultInfo($Counter)) -NotePropertyName "DownloadStatus" -NotePropertyValue $FailError
137 |
138 | } # End If
139 |
140 | $Error.Clear()
141 | Add-content -Path $ReportFile -Value "`r"
142 |
143 | } # End Else
144 |
145 | } # End For
146 |
147 | $Counter = 0
148 | $DisplayCount = 0
149 |
150 | Write-Verbose "`tStarting Installation of Downloaded Updates ..."
151 | Add-Content -Path $ReportFile -Value "---------------------------------------------------------------------`nUPDATE INSTALLATION`n---------------------------------------------------------------------`n"
152 |
153 | $Installer = New-Object -ComObject Microsoft.Update.Installer
154 |
155 | For ($Counter = 0; $Counter -lt $UpdateCollection.Count; $Counter++) {
156 |
157 | $Track = $Null
158 | $DisplayCount = $Counter + 1
159 | $WriteThis = $UpdateCollection.Item($Counter).Title
160 |
161 | Add-Content -Path $ReportFile -Value "$DisplayCount.) Installing Update: $WriteThis `r"
162 |
163 | $Installer.Updates = $UpdateCollection
164 |
165 | Try {
166 |
167 | $Track = $Installer.Install()
168 |
169 | Add-Content -Path $ReportFile -Value " - Update Installation Status: SUCCESS`n"
170 |
171 | If ($WriteThis -like ((Get-Variable -Name UpdateResultInfo($Counter)).Title)) {
172 |
173 | Add-Member -InputObject (Get-Variable -Name UpdateResultInfo($Counter)) -NotePropertyName "InstallStatus" -NotePropertyValue 'Successfully Installed'
174 |
175 | } # End If
176 |
177 | } Catch {
178 |
179 | [System.Exception]
180 | $InstallError = $Error[0]
181 | Add-Content -Path $ReportFile -Value " - Update Installation Status: FAILED With Error `n`t`t$InstallError`r"
182 |
183 | If ($WriteThis -like ((Get-Variable -Name UpdateResultInfo($Counter)).Title)) {
184 |
185 | Add-Member -InputObject (Get-Variable -Name UpdateResultInfo($Counter)) -NotePropertyName "InstallStatus" -NotePropertyValue $InstallError
186 |
187 | } # End If
188 |
189 | $Error.Clear()
190 |
191 | } # End Try Catch
192 |
193 | } # End For
194 |
195 | Add-Content -Path $ReportFile -Value "#===================================================================#`n# END OF REPORT #`n#===================================================================#"
196 |
197 | $Obj = New-Object -TypeName PSCustomObject -Properties @{
198 | UpdateTitle=$UpdateResultInfo.UpdateTitle
199 | HostName=$UpdateResultInfo.HostName
200 | Date=$UpdateResultInfo.Date
201 | DownloadStatus=$UpdateResultInfo.DownloadStatus
202 | InstallStatus=$UpdateResultInfo.InstallStatus
203 | } # End Properties
204 |
205 | Write-Output $Obj
206 |
207 | } # End Else
208 |
209 | } # End Funtion Update-Windows
210 |
--------------------------------------------------------------------------------