├── ClockWidget.ps1 ├── Convert-OutputForCSV.ps1 ├── ConvertCSV-ToExcel.ps1 ├── Get-ADGroupMemberDate.ps1 ├── Get-Certificate.ps1 ├── Get-ClientWSUSSetting.ps1 ├── Get-ExchangeCachedMode.ps1 ├── Get-FileHash.ps1 ├── Get-GeoIP.ps1 ├── Get-Icon.ps1 ├── Get-LocalGroupMembership.ps1 ├── Get-NetworkInfo.ps1 ├── Get-PSSQLInstance.ps1 ├── Get-PendingUpdate.ps1 ├── Get-ProductKey.ps1 ├── Get-SCCMClientUpdate.ps1 ├── Get-ServiceStartModeEvent.ps1 ├── Get-ServiceStateEvent.ps1 ├── Get-TCPResponse.ps1 ├── Get-USGSWaterData.ps1 ├── Get-WebPage.ps1 ├── Install-WSUSServer.ps1 ├── Invoke-BalloonTip.ps1 ├── Invoke-WSUSClientFixID.ps1 ├── Invoke-WSUSDBMaintenance.ps1 ├── LICENSE ├── New-SymLink.ps1 ├── Out-Voice.ps1 ├── README.md ├── Remove-LocalProfile.ps1 ├── Set-ClientWSUSSetting.ps1 ├── Set-Owner.ps1 ├── Set-Password.ps1 ├── Set-Window.ps1 ├── Start-CountDownTimer.ps1 ├── Test-IsAdmin.ps1 ├── Test-Port-README.md └── Test-Port.ps1 /ClockWidget.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYSNOPSIS 3 | Displays a clock on the screen with date. 4 | 5 | .DESCRIPTION 6 | Displays a clock on the screen with date. 7 | 8 | .PARAMETER TimeColor 9 | Specify the color of the time display. 10 | 11 | .PARAMETER DateColor 12 | Specify the color of the date display. 13 | 14 | Default is White 15 | 16 | .NOTES 17 | Author: Boe Prox 18 | Created: 27 March 2014 19 | Version History: 20 | Version 1.0 -- 27 March 2014 21 | -Initial build 22 | 23 | .EXAMPLE 24 | .\ClockWidget.ps1 25 | 26 | Description 27 | ----------- 28 | Clock is displayed on screen 29 | 30 | .EXAMPLE 31 | .\ClockWidget.ps1 -TimeColor DarkRed -DateColor Gold 32 | 33 | Description 34 | ----------- 35 | Clock is displayed on screen with alternate colors 36 | 37 | .EXAMPLE 38 | .\ClockWidget.ps1 –TimeColor "#669999" –DateColor "#334C4C" 39 | 40 | Description 41 | ----------- 42 | Clock is displayed on screen with alternate colors as hex values 43 | 44 | #> 45 | Param ( 46 | [parameter()] 47 | [string]$TimeColor = "White", 48 | [parameter()] 49 | [string]$DateColor = "White" 50 | ) 51 | $Clockhash = [hashtable]::Synchronized(@{}) 52 | $Runspacehash = [hashtable]::Synchronized(@{}) 53 | $Runspacehash.host = $Host 54 | $Clockhash.TimeColor = $TimeColor 55 | $Clockhash.DateColor = $DateColor 56 | $Runspacehash.runspace = [RunspaceFactory]::CreateRunspace() 57 | $Runspacehash.runspace.ApartmentState = “STA” 58 | $Runspacehash.runspace.ThreadOptions = “ReuseThread” 59 | $Runspacehash.runspace.Open() 60 | $Runspacehash.psCmd = {Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase}.GetPowerShell() 61 | $Runspacehash.runspace.SessionStateProxy.SetVariable("Clockhash",$Clockhash) 62 | $Runspacehash.runspace.SessionStateProxy.SetVariable("Runspacehash",$Runspacehash) 63 | $Runspacehash.runspace.SessionStateProxy.SetVariable("TimeColor",$TimeColor) 64 | $Runspacehash.runspace.SessionStateProxy.SetVariable("DateColor",$DateColor) 65 | $Runspacehash.psCmd.Runspace = $Runspacehash.runspace 66 | $Runspacehash.Handle = $Runspacehash.psCmd.AddScript({ 67 | 68 | $Script:Update = { 69 | $day,$Month, $Day_n, $Year, $Time, $AMPM = (Get-Date -f "dddd,MMMM,dd,yyyy,hh:mm,tt") -Split ',' 70 | 71 | $Clockhash.time_txtbox.text = $Time.TrimStart("0") 72 | $Clockhash.day_txtbx.Text = $day 73 | $Clockhash.ampm_txtbx.text = $AMPM 74 | $Clockhash.day_n_txtbx.text = $Day_n 75 | $Clockhash.month_txtbx.text = $Month 76 | $Clockhash.year_txtbx.text = $year 77 | } 78 | 79 | [xml]$xaml = @" 80 | 85 | 86 | 88 | 89 | 90 | 91 | 92 | 94 | 95 | 96 | 97 | 98 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 116 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | "@ 125 | 126 | $reader=(New-Object System.Xml.XmlNodeReader $xaml) 127 | $Clockhash.Window=[Windows.Markup.XamlReader]::Load( $reader ) 128 | 129 | $Clockhash.time_txtbox = $Clockhash.window.FindName("time_txtbox") 130 | $Clockhash.ampm_txtbx = $Clockhash.Window.FindName("ampm_txtbx") 131 | $Clockhash.day_n_txtbx = $Clockhash.Window.FindName("day_n_txtbx") 132 | $Clockhash.month_txtbx = $Clockhash.Window.FindName("month_txtbx") 133 | $Clockhash.year_txtbx = $Clockhash.Window.FindName("year_txtbx") 134 | $Clockhash.day_txtbx = $Clockhash.Window.FindName("day_txtbx") 135 | 136 | #Timer Event 137 | $Clockhash.Window.Add_SourceInitialized({ 138 | #Create Timer object 139 | Write-Verbose "Creating timer object" 140 | $Script:timer = new-object System.Windows.Threading.DispatcherTimer 141 | #Fire off every 1 minutes 142 | Write-Verbose "Adding 1 minute interval to timer object" 143 | $timer.Interval = [TimeSpan]"0:0:1.00" 144 | #Add event per tick 145 | Write-Verbose "Adding Tick Event to timer object" 146 | $timer.Add_Tick({ 147 | $Update.Invoke() 148 | [Windows.Input.InputEventHandler]{ $Clockhash.Window.UpdateLayout() } 149 | 150 | }) 151 | #Start timer 152 | Write-Verbose "Starting Timer" 153 | $timer.Start() 154 | If (-NOT $timer.IsEnabled) { 155 | $Clockhash.Window.Close() 156 | } 157 | }) 158 | 159 | $Clockhash.Window.Add_Closed({ 160 | $timer.Stop() 161 | $Runspacehash.PowerShell.Dispose() 162 | 163 | [gc]::Collect() 164 | [gc]::WaitForPendingFinalizers() 165 | }) 166 | $Clockhash.month_txtbx.Add_SizeChanged({ 167 | [int]$clockhash.length = [math]::Round(($Clockhash.day_txtbx.ActualWidth,$Clockhash.month_txtbx.ActualWidth | 168 | Sort -Descending)[0]) 169 | [int]$Adjustment = $clockhash.length + 52 + 10 #Hard coded margin plus white space 170 | 171 | $YearMargin = $Clockhash.year_txtbx.Margin 172 | $Clockhash.year_txtbx.Margin = ("{0},{1},{2},{3}" -f ($Adjustment), 173 | $YearMargin.Top,$YearMargin.Right,$YearMargin.Bottom) 174 | }) 175 | $Clockhash.time_txtbox.Add_SizeChanged({ 176 | If ($Clockhash.time_txtbox.text.length -eq 4) { 177 | $Clockhash.ampm_txtbx.Margin = "133,0,86,0" 178 | } Else { 179 | $Clockhash.ampm_txtbx.Margin = "172,0,48,0" 180 | } 181 | }) 182 | $Clockhash.Window.Add_MouseRightButtonUp({ 183 | $This.close() 184 | }) 185 | $Clockhash.Window.Add_MouseLeftButtonDown({ 186 | $This.DragMove() 187 | }) 188 | $Update.Invoke() 189 | $Clockhash.Window.ShowDialog() | Out-Null 190 | }).BeginInvoke() -------------------------------------------------------------------------------- /Convert-OutputForCSV.ps1: -------------------------------------------------------------------------------- 1 | Function Convert-OutputForCSV { 2 | <# 3 | .SYNOPSIS 4 | Provides a way to expand collections in an object property prior 5 | to being sent to Export-Csv. 6 | 7 | .DESCRIPTION 8 | Provides a way to expand collections in an object property prior 9 | to being sent to Export-Csv. This helps to avoid the object type 10 | from being shown such as system.object[] in a spreadsheet. 11 | 12 | .PARAMETER InputObject 13 | The object that will be sent to Export-Csv 14 | 15 | .PARAMETER OutPropertyType 16 | This determines whether the property that has the collection will be 17 | shown in the CSV as a comma delimmited string or as a stacked string. 18 | 19 | Possible values: 20 | Stack 21 | Comma 22 | 23 | Default value is: Stack 24 | 25 | .NOTES 26 | Name: Convert-OutputForCSV 27 | Author: Boe Prox 28 | Created: 24 Jan 2014 29 | Version History: 30 | 1.1 - 02 Feb 2014 31 | -Removed OutputOrder parameter as it is no longer needed; inputobject order is now respected 32 | in the output object 33 | 1.0 - 24 Jan 2014 34 | -Initial Creation 35 | 36 | .EXAMPLE 37 | $Output = 'PSComputername','IPAddress','DNSServerSearchOrder' 38 | 39 | Get-WMIObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" | 40 | Select-Object $Output | Convert-OutputForCSV | 41 | Export-Csv -NoTypeInformation -Path NIC.csv 42 | 43 | Description 44 | ----------- 45 | Using a predefined set of properties to display ($Output), data is collected from the 46 | Win32_NetworkAdapterConfiguration class and then passed to the Convert-OutputForCSV 47 | funtion which expands any property with a collection so it can be read properly prior 48 | to being sent to Export-Csv. Properties that had a collection will be viewed as a stack 49 | in the spreadsheet. 50 | 51 | #> 52 | #Requires -Version 3.0 53 | [cmdletbinding()] 54 | Param ( 55 | [parameter(ValueFromPipeline)] 56 | [psobject]$InputObject, 57 | [parameter()] 58 | [ValidateSet('Stack','Comma')] 59 | [string]$OutputPropertyType = 'Stack' 60 | ) 61 | Begin { 62 | $PSBoundParameters.GetEnumerator() | ForEach { 63 | Write-Verbose "$($_)" 64 | } 65 | $FirstRun = $True 66 | } 67 | Process { 68 | If ($FirstRun) { 69 | $OutputOrder = $InputObject.psobject.properties.name 70 | Write-Verbose "Output Order:`n $($OutputOrder -join ', ' )" 71 | $FirstRun = $False 72 | #Get properties to process 73 | $Properties = Get-Member -InputObject $InputObject -MemberType *Property 74 | #Get properties that hold a collection 75 | $Properties_Collection = @(($Properties | Where-Object { 76 | $_.Definition -match "Collection|\[\]" 77 | }).Name) 78 | #Get properties that do not hold a collection 79 | $Properties_NoCollection = @(($Properties | Where-Object { 80 | $_.Definition -notmatch "Collection|\[\]" 81 | }).Name) 82 | Write-Verbose "Properties Found that have collections:`n $(($Properties_Collection) -join ', ')" 83 | Write-Verbose "Properties Found that have no collections:`n $(($Properties_NoCollection) -join ', ')" 84 | } 85 | 86 | $InputObject | ForEach { 87 | $Line = $_ 88 | $stringBuilder = New-Object Text.StringBuilder 89 | $Null = $stringBuilder.AppendLine("[pscustomobject] @{") 90 | 91 | $OutputOrder | ForEach { 92 | If ($OutputPropertyType -eq 'Stack') { 93 | $Null = $stringBuilder.AppendLine("`"$($_)`" = `"$(($line.$($_) | Out-String).Trim())`"") 94 | } ElseIf ($OutputPropertyType -eq "Comma") { 95 | $Null = $stringBuilder.AppendLine("`"$($_)`" = `"$($line.$($_) -join ', ')`"") 96 | } 97 | } 98 | $Null = $stringBuilder.AppendLine("}") 99 | 100 | Invoke-Expression $stringBuilder.ToString() 101 | } 102 | } 103 | End {} 104 | } -------------------------------------------------------------------------------- /ConvertCSV-ToExcel.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/ConvertCSV-ToExcel.ps1 -------------------------------------------------------------------------------- /Get-ADGroupMemberDate.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADGroupMemberDate { 2 | <# 3 | .SYNOPSIS 4 | Provides the date that a member was added to a specified Active Directory group. 5 | 6 | .DESCRIPTION 7 | Provides the date that a member was added to a specified Active Directory group. 8 | 9 | .PARAMETER Group 10 | The group that will be inspected for members and date added. If a distinguished name (dn) is not used, 11 | an attempt to get the dn before making the query. 12 | 13 | .PARAMETER DomainController 14 | Name of the domain controller to query. Optional parameter. 15 | 16 | .NOTES 17 | Name: Get-ADGroupMemberDate 18 | Author: Boe Prox 19 | DateCreated: 17 May 2013 20 | Version 1.0 21 | 22 | The State property will be one of the following: 23 | 24 | PRESENT: User currently exists in group and the replicated using Linked Value Replication (LVR). 25 | ABSENT: User has been removed from group and has not been garbage collected based on Tombstone Lifetime (TSL). 26 | LEGACY: User currently exists as a member of the group but has no replication data via LVR. 27 | 28 | .EXAMPLE 29 | Get-ADGroupMemberDate -Group "Domain Admins" -DomainController DC3 30 | 31 | ModifiedCount : 2 32 | DomainController : DC3 33 | LastModified : 5/4/2013 6:48:06 PM 34 | Username : joesmith 35 | State : ABSENT 36 | Group : CN=Domain Admins,CN=Users,DC=Domain,DC=Com 37 | 38 | ModifiedCount : 1 39 | DomainController : DC3 40 | LastModified : 1/6/2010 7:36:08 AM 41 | Username : adminuser 42 | State : PRESENT 43 | Group : CN=Domain Admins,CN=Users,DC=Domain,DC=Com 44 | ... 45 | 46 | Description 47 | ----------- 48 | This lists out all of the members of Domain Admins using DC3 as the Domain Controller. 49 | 50 | .EXAMPLE 51 | Get-ADGroup -Identity "TestGroup" | Get-ADGroupMemberDate 52 | 53 | ModifiedCount : 2 54 | DomainController : DC1 55 | LastModified : 5/4/2013 6:48:06 PM 56 | Username : joesmith 57 | State : ABSENT 58 | Group : CN=TestGroup,OU=Groups,DC=Domain,DC=Com 59 | 60 | ModifiedCount : 1 61 | DomainController : DC1 62 | LastModified : 1/6/2010 7:36:08 AM 63 | Username : bobsmith 64 | State : PRESENT 65 | Group : CN=TestGroup,OU=Groups,DC=Domain,DC=Com 66 | ... 67 | 68 | Description 69 | ----------- 70 | This lists out all of the members of TestGroup from the output of Get-ADGroup and auto-selecting DC1 as the Domain Controller. 71 | 72 | #> 73 | [OutputType('ActiveDirectory.Group.Info')] 74 | [cmdletbinding()] 75 | Param ( 76 | [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True,Mandatory=$True)] 77 | [Alias('DistinguishedName')] 78 | [string]$Group, 79 | [parameter()] 80 | [string]$DomainController = ($env:LOGONSERVER -replace "\\\\") 81 | ) 82 | Begin { 83 | #RegEx pattern for output 84 | [regex]$pattern = '^(?\w+)\s+member(?:\s(?\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s+(?:.*\\)?(?\w+|(?:(?:\w{8}-(?:\w{4}-){3}\w{12})))\s+(?:\d+)\s+(?:\d+)\s+(?\d+))?' 85 | } 86 | Process { 87 | If ($Group -notmatch "^CN=.*") { 88 | Write-Verbose "Attempting to get distinguished name of $Group" 89 | 90 | Try { 91 | $distinguishedName = ([adsisearcher]"name=$group").Findone().Properties['distinguishedname'][0] 92 | If (-Not $distinguishedName) {Throw "Fail!"} 93 | } Catch { 94 | Write-Warning "Unable to locate $group" 95 | Break 96 | } 97 | 98 | } Else {$distinguishedName = $Group} 99 | 100 | Write-Verbose "Distinguished Name is $distinguishedName" 101 | $data = (repadmin /showobjmeta $DomainController $distinguishedName | Select-String "^\w+\s+member" -Context 2) 102 | 103 | ForEach ($rep in $data) { 104 | If ($rep.line -match $pattern) { 105 | $object = New-Object PSObject -Property @{ 106 | Username = [regex]::Matches($rep.context.postcontext,"CN=(?.*?),.*") | ForEach {$_.Groups['Username'].Value} 107 | LastModified = If ($matches.DateTime) {[datetime]$matches.DateTime} Else {$Null} 108 | DomainController = $matches.dc 109 | Group = $distinguishedName 110 | State = $matches.state 111 | ModifiedCount = $matches.modified 112 | } 113 | 114 | $object.pstypenames.insert(0,'ActiveDirectory.Group.Info') 115 | $object 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /Get-Certificate.ps1: -------------------------------------------------------------------------------- 1 | Function Get-Certificate { 2 | <# 3 | .SYNOPSIS 4 | Retrieves certificates from a local or remote system. 5 | 6 | .DESCRIPTION 7 | Retrieves certificates from a local or remote system. Also includes the 8 | time until expiration and allows for filtering of certificates and includes 9 | archived certificates. 10 | 11 | .PARAMETER Computername 12 | A single or list of computernames to perform search against 13 | 14 | .PARAMETER StoreName 15 | The name of the certificate store name that you want to search 16 | 17 | .PARAMETER StoreLocation 18 | The location of the certificate store. 19 | 20 | .PARAMETER IncludeArchive 21 | Includes certificates that have been archived 22 | 23 | .PARAMETER Issuer 24 | Filter by certificate Issuer 25 | 26 | .PARAMETER Subject 27 | Filter by certificate Subject 28 | 29 | .PARAMETER Thumbprint 30 | Filter by certificate Thumbprint 31 | 32 | .NOTES 33 | Name: Get-Certificate 34 | Author: Boe Prox 35 | Version History: 36 | 1.3 //Boe Prox 37 | -Added parameters for filtering 38 | -Removed parametersetnames 39 | -Fixed computername output in verbose streams 40 | 1.0 //Boe Prox 41 | -Initial Version 42 | 43 | .EXAMPLE 44 | Get-Certificate -Computername 'boe-pc' -StoreName My -StoreLocation LocalMachine 45 | 46 | Thumbprint Subject 47 | ---------- ------- 48 | F29B6CB248E3395B2EB45FCA6EA15005F64F2B4E CN=SomeCert 49 | B93BA840652FB8273CCB1ABD804B2A035AA39877 CN=YetAnotherCert 50 | B1FF5E183E5C4F03559E80B49C2546BBB14CCB18 CN=BOE 51 | 65F5A012F0FE3DF8AC6B5D6E07817F05D2DF5104 CN=SomeOtherCert 52 | 63BD74490E182A341405B033DFE6768E00ECF21B CN=www.example.com 53 | 54 | Description 55 | ----------- 56 | Lists all certificates 57 | 58 | .EXAMPLE 59 | Get-Certificate -Computername 'boe-pc' -StoreName My -StoreLocation LocalMachine -Subject '*Boe*' 60 | 61 | Thumbprint Subject 62 | ---------- ------- 63 | B1FF5E183E5C4F03559E80B49C2546BBB14CCB18 CN=BOE 64 | 65 | Description 66 | ----------- 67 | Lists certificates that contain the subject: boe 68 | 69 | #> 70 | [cmdletbinding()] 71 | Param ( 72 | [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] 73 | [Alias('PSComputername','__Server','IPAddress')] 74 | [string[]]$Computername = $env:COMPUTERNAME, 75 | [parameter()] 76 | [System.Security.Cryptography.X509Certificates.StoreName]$StoreName = 'My', 77 | [parameter()] 78 | [System.Security.Cryptography.X509Certificates.StoreLocation]$StoreLocation = 'LocalMachine', 79 | [parameter()] 80 | [switch]$IncludeArchive, 81 | [parameter()] 82 | [string]$Issuer, 83 | [parameter()] 84 | [string]$Subject, 85 | [parameter()] 86 | [string]$Thumbprint 87 | 88 | ) 89 | Begin { 90 | $WhereList = New-Object System.Collections.ArrayList 91 | If ($PSBoundParameters.ContainsKey('Issuer')) { 92 | [void]$WhereList.Add('$_.Issuer -LIKE $Issuer') 93 | } 94 | If ($PSBoundParameters.ContainsKey('Subject')) { 95 | [void]$WhereList.Add('$_.Subject -LIKE $Subject') 96 | } 97 | If ($PSBoundParameters.ContainsKey('Thumbprint')) { 98 | [void]$WhereList.Add('$_.Thumbprint -LIKE $Thumbprint') 99 | } 100 | If ($WhereList.count -gt 0) { 101 | $Where = [scriptblock]::Create($WhereList -join ' -AND ') 102 | Write-Debug "WhereBlock: $($Where)" 103 | } 104 | } 105 | Process { 106 | ForEach ($Computer in $Computername) { 107 | Try { 108 | Write-Verbose ("Connecting to \\{0}\{1}\{2}" -f $Computer,$StoreLocation,$StoreName) 109 | $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($Computer)\$($StoreName)", $StoreLocation 110 | If ($PSBoundParameters.ContainsKey('IncludeArchive')) { 111 | $Flags = [System.Security.Cryptography.X509Certificates.OpenFlags]'ReadOnly','IncludeArchived' 112 | } Else { 113 | $Flags = [System.Security.Cryptography.X509Certificates.OpenFlags]'ReadOnly' 114 | } 115 | $CertStore.Open($Flags) 116 | If ($WhereList.count -gt 0) { 117 | $Certificates = $CertStore.Certificates | Where $Where 118 | } Else { 119 | $Certificates = $CertStore.Certificates 120 | } 121 | $Certificates | ForEach { 122 | $Days = Switch ((New-TimeSpan -End $_.NotAfter).Days) { 123 | {$_ -gt 0} {$_} 124 | Default {'Expired'} 125 | } 126 | $_ | Add-Member -MemberType NoteProperty -Name ExpiresIn -Value $Days -PassThru | 127 | Add-Member -MemberType NoteProperty -Name Computername -Value $Computer -PassThru 128 | } 129 | } Catch { 130 | Write-Warning "$($Computer): $_" 131 | } 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /Get-ClientWSUSSetting.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-ClientWSUSSetting.ps1 -------------------------------------------------------------------------------- /Get-ExchangeCachedMode.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ExchangeCachedMode { 2 | <# 3 | .SYNOPSIS 4 | Retrieves the CachedMode setting for Outlook 2010 on a workstation. 5 | 6 | .DESCRIPTION 7 | Retrieves the CacheMode setting for Outlook 2010 on a workstation. 8 | 9 | .PARAMETER Computername 10 | Collection of computers to check for the CachedMode setting. 11 | 12 | .PARAMETER Throttle 13 | Used to determine how many asynchronous jobs to run. 14 | 15 | .NOTES 16 | Name: Get-ExchangeCachedMode 17 | Author: Boe Prox 18 | 19 | .EXAMPLE 20 | 21 | Get-ExchangeCachedMode -Computername Computer01 22 | 23 | Computername : Computer01 24 | SID : S-1-5-21-0133314170-616249376-839522115-56832 25 | OutlookProfile : Outlook 26 | CachedMode : Disabled 27 | RegValue : 4,16,0,0 28 | isLoggedOn : True 29 | RegKey : 600aa55f87091746a6c0ff6a2b78af55 30 | RegValueName : 00036601 31 | User : Rivendell\PROXB 32 | 33 | Computername : Computer01 34 | SID : S-1-5-21-0133314170-839522115-616249376-56832 35 | OutlookProfile : proxb 36 | CachedMode : Disabled 37 | RegValue : 4,16,0,0 38 | isLoggedOn : True 39 | RegKey : 5470707acae06d4f9d9dd7dfdf21dab5 40 | RegValueName : 00036601 41 | User : Rivendell\PROXB 42 | 43 | Computername : Computer01 44 | SID : S-1-5-21-634939626-536326981-3066512030-1001 45 | OutlookProfile : Outlook 46 | CachedMode : Disabled 47 | RegValue : 4,16,0,0 48 | isLoggedOn : True 49 | RegKey : 5689237acae06d4f9d9dd7dfdf7r8g9u 50 | RegValueName : 00036601 51 | User : Rivendell\SMITHB 52 | 53 | Description 54 | ----------- 55 | Performs a query for the CachedMode setting against a remote system. 56 | #> 57 | [cmdletbinding()] 58 | Param ( 59 | [parameter(ValueFromPipeLine=$True,ValueFromPipeLineByPropertyName=$True)] 60 | [string[]]$Computername = $Env:Computername, 61 | [parameter()] 62 | [int]$Throttle = 15 63 | ) 64 | Begin { 65 | #Required Functions 66 | Function Get-RunspaceData { 67 | [cmdletbinding()] 68 | param( 69 | [switch]$Wait 70 | ) 71 | Do { 72 | $more = $false 73 | Foreach($runspace in $runspaces) { 74 | If ($runspace.Runspace.isCompleted) { 75 | $runspace.powershell.EndInvoke($runspace.Runspace) 76 | $runspace.powershell.dispose() 77 | $runspace.Runspace = $null 78 | $runspace.powershell = $null 79 | $Script:i++ 80 | } ElseIf ($runspace.Runspace -ne $null) { 81 | $more = $true 82 | } 83 | } 84 | If ($more -AND $PSBoundParameters['Wait']) { 85 | Start-Sleep -Milliseconds 100 86 | } 87 | #Clean out unused runspace jobs 88 | $temphash = $runspaces.clone() 89 | $temphash | Where { 90 | $_.runspace -eq $Null 91 | } | ForEach { 92 | Write-Verbose ("Removing {0}" -f $_.computer) 93 | $Runspaces.remove($_) 94 | } 95 | } while ($more -AND $PSBoundParameters['Wait']) 96 | } #End Function 97 | 98 | #Main collection to hold all data returned from runspace jobs 99 | $Script:report = @() 100 | 101 | #Define hash table for Get-RunspaceData function 102 | $runspacehash = @{} 103 | 104 | #Define Scriptblock for runspaces 105 | $scriptblock = { 106 | Param ($Computer) 107 | #Function required for SID to Username translation 108 | Function ConvertSID-ToUserName { 109 | [cmdletbinding()] 110 | Param ( 111 | [parameter()] 112 | [string[]]$SID 113 | ) 114 | Process { 115 | ForEach ($S in $Sid) { 116 | Try { 117 | $s = [system.security.principal.securityidentifier]$s 118 | $user = $s.Translate([System.Security.Principal.NTAccount]) 119 | New-Object PSObject -Property @{ 120 | Name = $user.value 121 | SID = $s.value 122 | } 123 | } Catch { 124 | Write-Warning ("Unable to translate {0}.`n{1}" -f $UserName,$_.Exception.Message) 125 | } 126 | } 127 | } 128 | } #End Function 129 | 130 | #Get logged on user 131 | Try { 132 | $Username = (Get-WmiObject -ComputerName $Computer -Class Win32_ComputerSystem -ErrorAction Stop).Username 133 | } Catch { 134 | Write-Warning ("{0}: {1}" -f $Computer,$_.Exception.Message) 135 | $Username = "N\A" 136 | } 137 | 138 | $rootkey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("Users",$computer) 139 | 140 | $SIDs = $rootkey.GetSubKeyNames() | Where { 141 | $_ -match "^S-1-5-\d{2}-\d{10}-\d{9}-\d{9}-\d{5}$" 142 | } 143 | 144 | #Match up the SID to a username 145 | $Hash = @{} 146 | $SIDs | ForEach { 147 | $Hash.$_ = (ConvertSID-ToUserName $_ | Select -Expand Name) 148 | $Hash[$hash.$_] = $_ 149 | } 150 | 151 | $SIDs | ForEach { 152 | $SID = $_ 153 | Try { 154 | If ($hash.$_ -eq $Username) { 155 | $LoggedOn = $True 156 | } Else { 157 | $LoggedOn = $False 158 | } 159 | $Key = $rootkey.OpenSubKey("$_\Software\Microsoft\Windows NT\CurrentVersion\") 160 | If ($Key.GetSubKeyNames() -Contains "Windows Messaging Subsystem") { 161 | $User = $hash.$_ 162 | $Profiles = $Key.OpenSubKey("Windows Messaging SubSystem\Profiles") 163 | Write-Verbose ("Getting list of profiles") 164 | $Profiles.GetSubKeyNames() | ForEach { 165 | $OutlookProfile = $_ 166 | $Profile = $Profiles.OpenSubKey(("$_")) 167 | $profile.GetSubKeyNames() | ForEach { 168 | If ($profile.OpenSubKey("$_").GetValueNames() -Contains "00036601") { 169 | Write-Verbose ("Checking value for Cached Mode on profile: {0}" -f $OutlookProfile) 170 | $RegKey = $_ 171 | $Key = $profile.OpenSubKey("$_") 172 | $Value = $Key.GetValue("00036601") 173 | If ((($Value[0] -bor 0x80) -eq $Value[0]) -AND (($Value[1] -bor 0x1) -eq $Value[1])) { 174 | $CachedMode = 'Enabled' 175 | } Else { 176 | $CachedMode = 'Disabled' 177 | } 178 | New-Object PSObject -Property @{ 179 | User = $User 180 | OutlookProfile = $OutlookProfile 181 | CachedMode = $CachedMode 182 | RegValue = ($Value -Join ",") 183 | RegKey = $RegKey 184 | RegValueName = "00036601" 185 | Computername = $Computer 186 | isLoggedOn = $LoggedOn 187 | SID = $SID 188 | } 189 | } Else { 190 | Write-Warning ("[$($Computer)]$OutlookProfile") 191 | } 192 | } 193 | } 194 | } Else { 195 | Write-Warning "Outlook not installed or missing configuration information" 196 | } 197 | } Catch { 198 | Write-Warning ("{0}: {1}" -f $Computer,$_.Exception.Message) 199 | } 200 | } #End ForEach 201 | } #End Scriptblock 202 | 203 | Write-Verbose ("Creating runspace pool and session states") 204 | $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() 205 | $runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host) 206 | $runspacepool.Open() 207 | 208 | Write-Verbose ("Creating empty collection to hold runspace jobs") 209 | $Script:runspaces = New-Object System.Collections.ArrayList 210 | 211 | } 212 | Process { 213 | 214 | ForEach ($Computer in $Computername) { 215 | If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) { 216 | #Create the powershell instance and supply the scriptblock with the other parameters 217 | $powershell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($computer).AddArgument($wmihash) 218 | 219 | #Add the runspace into the powershell instance 220 | $powershell.RunspacePool = $runspacepool 221 | 222 | #Create a temporary collection for each runspace 223 | $temp = "" | Select-Object PowerShell,Runspace,Computer 224 | $Temp.Computer = $Computer 225 | $temp.PowerShell = $powershell 226 | 227 | #Save the handle output when calling BeginInvoke() that will be used later to end the runspace 228 | $temp.Runspace = $powershell.BeginInvoke() 229 | Write-Verbose ("Adding {0} collection" -f $temp.Computer) 230 | $runspaces.Add($temp) | Out-Null 231 | } Else { 232 | Write-Warning ("{0}: Unavailable" -f $Computer) 233 | } 234 | 235 | Write-Verbose ("Checking status of runspace jobs") 236 | Get-RunspaceData @runspacehash 237 | } 238 | } #End Process 239 | End { 240 | Write-Verbose ("Finish processing the remaining runspace jobs: {0}" -f (@(($runspaces | Where {$_.Runspace -ne $Null}).Count))) 241 | $runspacehash.Wait = $true 242 | Get-RunspaceData @runspacehash 243 | 244 | Write-Verbose ("Closing the runspace pool") 245 | $runspacepool.close() 246 | } 247 | } -------------------------------------------------------------------------------- /Get-FileHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-FileHash { 2 | <# 3 | .SYNOPSIS 4 | Calculates the hash on a given file based on the seleced hash algorithm. 5 | 6 | .DESCRIPTION 7 | Calculates the hash on a given file based on the seleced hash algorithm. Multiple hashing 8 | algorithms can be used with this command. 9 | 10 | .PARAMETER Path 11 | File or files that will be scanned for hashes. 12 | 13 | .PARAMETER Algorithm 14 | The type of algorithm that will be used to determine the hash of a file or files. 15 | Default hash algorithm used is SHA256. More then 1 algorithm type can be used. 16 | 17 | Available hash algorithms: 18 | 19 | MD5 20 | SHA1 21 | SHA256 (Default) 22 | SHA384 23 | SHA512 24 | RIPEM160 25 | 26 | .NOTES 27 | Name: Get-FileHash 28 | Author: Boe Prox 29 | Created: 18 March 2013 30 | Modified: 28 Jan 2014 31 | 1.1 - Fixed bug with incorrect hash when using multiple algorithms 32 | 33 | .OUTPUTS 34 | System.IO.FileInfo.Hash 35 | 36 | .EXAMPLE 37 | Get-FileHash -Path Test2.txt 38 | Path SHA256 39 | ---- ------ 40 | C:\users\prox\desktop\TEST2.txt 5f8c58306e46b23ef45889494e991d6fc9244e5d78bc093f1712b0ce671acc15 41 | 42 | Description 43 | ----------- 44 | Displays the SHA256 hash for the text file. 45 | 46 | .EXAMPLE 47 | Get-FileHash -Path .\TEST2.txt -Algorithm MD5,SHA256,RIPEMD160 | Format-List 48 | Path : C:\users\prox\desktop\TEST2.txt 49 | MD5 : cb8e60205f5e8cae268af2b47a8e5a13 50 | SHA256 : 5f8c58306e46b23ef45889494e991d6fc9244e5d78bc093f1712b0ce671acc15 51 | RIPEMD160 : e64d1fa7b058e607319133b2aa4f69352a3fcbc3 52 | 53 | Description 54 | ----------- 55 | Displays MD5,SHA256 and RIPEMD160 hashes for the text file. 56 | 57 | .EXAMPLE 58 | Get-ChildItem -Filter *.exe | Get-FileHash -Algorithm MD5 59 | Path MD5 60 | ---- --- 61 | C:\users\prox\desktop\handle.exe 50c128c5b28237b3a01afbdf0e546245 62 | C:\users\prox\desktop\PortQry.exe c6ac67f4076ca431acc575912c194245 63 | C:\users\prox\desktop\procexp.exe b4caa7f3d726120e1b835d52fe358d3f 64 | C:\users\prox\desktop\Procmon.exe 9c85f494132cc6027762d8ddf1dd5a12 65 | C:\users\prox\desktop\PsExec.exe aeee996fd3484f28e5cd85fe26b6bdcd 66 | C:\users\prox\desktop\pskill.exe b5891462c9ca5bddfe63d3bae3c14e0b 67 | C:\users\prox\desktop\Tcpview.exe 485bc6763729511dcfd52ccb008f5c59 68 | 69 | Description 70 | ----------- 71 | Uses pipeline input from Get-ChildItem to get MD5 hashes of executables. 72 | 73 | #> 74 | [CmdletBinding()] 75 | Param( 76 | [Parameter(Position=0,Mandatory=$true, ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$True)] 77 | [Alias("PSPath","FullName")] 78 | [string[]]$Path, 79 | 80 | [Parameter(Position=1)] 81 | [ValidateSet("MD5","SHA1","SHA256","SHA384","SHA512","RIPEMD160")] 82 | [string[]]$Algorithm = "SHA256" 83 | ) 84 | Process { 85 | ForEach ($item in $Path) { 86 | $item = (Resolve-Path $item).ProviderPath 87 | If (-Not ([uri]$item).IsAbsoluteUri) { 88 | Write-Verbose ("{0} is not a full path, using current directory: {1}" -f $item,$pwd) 89 | $item = (Join-Path $pwd ($item -replace "\.\\","")) 90 | } 91 | If(Test-Path $item -Type Container) { 92 | Write-Warning ("Cannot calculate hash for directory: {0}" -f $item) 93 | Return 94 | } 95 | $object = New-Object PSObject -Property @{ 96 | Path = $item 97 | } 98 | #Open the Stream 99 | $stream = ([IO.StreamReader]$item).BaseStream 100 | foreach($Type in $Algorithm) { 101 | [string]$hash = -join ([Security.Cryptography.HashAlgorithm]::Create( $Type ).ComputeHash( $stream ) | 102 | ForEach { "{0:x2}" -f $_ }) 103 | $null = $stream.Seek(0,0) 104 | #If multiple algorithms are used, then they will be added to existing object 105 | $object = Add-Member -InputObject $Object -MemberType NoteProperty -Name $Type -Value $Hash -PassThru 106 | } 107 | $object.pstypenames.insert(0,'System.IO.FileInfo.Hash') 108 | #Output an object with the hash, algorithm and path 109 | Write-Output $object 110 | 111 | #Close the stream 112 | $stream.Close() 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /Get-GeoIP.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-GeoIP.ps1 -------------------------------------------------------------------------------- /Get-Icon.ps1: -------------------------------------------------------------------------------- 1 | Function Get-Icon { 2 | <# 3 | .SYNOPSIS 4 | Gets the icon from a file 5 | 6 | .DESCRIPTION 7 | Gets the icon from a file and displays it in a variety formats. 8 | 9 | .PARAMETER Path 10 | The path to a file to get the icon 11 | 12 | .PARAMETER ToBytes 13 | Displays outputs as a byte array 14 | 15 | .PARAMETER ToBitmap 16 | Display the icon as a bitmap object 17 | 18 | .PARAMETER ToBase64 19 | Displays the icon in Base64 encoded format 20 | 21 | .NOTES 22 | Name: Get-Icon 23 | Author: Boe Prox 24 | Version History: 25 | 1.0 //Boe Prox - 11JAN2016 26 | - Initial version 27 | 28 | .OUTPUT 29 | System.Drawing.Icon 30 | System.Drawing.Bitmap 31 | System.String 32 | System.Byte[] 33 | 34 | .EXAMPLE 35 | Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' 36 | 37 | FullName : C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe 38 | Handle : 164169893 39 | Height : 32 40 | Size : {Width=32, Height=32} 41 | Width : 32 42 | 43 | Description 44 | ----------- 45 | Returns the System.Drawing.Icon representation of the icon 46 | 47 | .EXAMPLE 48 | Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBitmap 49 | 50 | Tag : 51 | PhysicalDimension : {Width=32, Height=32} 52 | Size : {Width=32, Height=32} 53 | Width : 32 54 | Height : 32 55 | HorizontalResolution : 96 56 | VerticalResolution : 96 57 | Flags : 2 58 | RawFormat : [ImageFormat: b96b3caa-0728-11d3-9d7b-0000f81ef32e] 59 | PixelFormat : Format32bppArgb 60 | Palette : System.Drawing.Imaging.ColorPalette 61 | FrameDimensionsList : {7462dc86-6180-4c7e-8e3f-ee7333a7a483} 62 | PropertyIdList : {} 63 | PropertyItems : {} 64 | 65 | Description 66 | ----------- 67 | Returns the System.Drawing.Bitmap representation of the icon 68 | 69 | .EXAMPLE 70 | $FileName = 'C:\Temp\PowerShellIcon.png' 71 | $Format = [System.Drawing.Imaging.ImageFormat]::Png 72 | (Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBitmap).Save($FileName,$Format) 73 | 74 | Description 75 | ----------- 76 | Saves the icon as a file. 77 | 78 | .EXAMPLE 79 | Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBase64 80 | 81 | AAABAAEAICAQHQAAAADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAA 82 | AAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP 83 | //AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 84 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmZmZmZmZmZmZmZgAAAAAAaId3d3d3d4iIiIdgAA 85 | AHdmhmZmZmZmZmZmZoZAAAB2ZnZmZmZmZmZmZmZ3YAAAdmZ3ZmiHZniIiHZmaGAAAHZmd2Zv/4eIiIi 86 | GZmhgAAB2ZmdmZ4/4eIh3ZmZnYAAAd2ZnZmZo//h2ZmZmZ3YAAHZmaGZmZo//h2ZmZmd2AAB3Zmd2Zm 87 | Znj/h2ZmZmhgAAd3dndmZmZuj/+GZmZoYAAHd3dod3dmZuj/9mZmZ2AACHd3aHd3eIiP/4ZmZmd2AAi 88 | Hd2iIiIiI//iId2ZndgAIiIhoiIiIj//4iIiIiIYACIiId4iIiP//iIiIiIiGAAiIiIaIiI//+IiIiI 89 | iIhkAIiIiGiIiP/4iIiIiIiIdgCIiIhoiIj/iIiIiIiIiIYAiIiIeIiIiIiIiIiIiIiGAAiIiIaP/// 90 | ////////4hgAAAAAGZmZmZmZmZmZmZmYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 91 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////gA 92 | AAf4AAAD+AAAAfgAAAHAAAABwAAAAcAAAAHAAAAAwAAAAMAAAADAAAAAwAAAAMAAAABAAAAAQAAAAEA 93 | AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAP4AAAH//////////////////////////w== 94 | 95 | Description 96 | ----------- 97 | Returns the Base64 encoded representation of the icon 98 | 99 | .EXAMPLE 100 | Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBase64 | Clip 101 | 102 | Description 103 | ----------- 104 | Returns the Base64 encoded representation of the icon and saves it to the clipboard. 105 | 106 | .EXAMPLE 107 | (Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBytes) -Join '' 108 | 109 | 0010103232162900002322002200040000320006400010400000128200000000000000000000000 110 | 0128001280001281280128000128012801281280012812812801921921920002550025500025525 111 | 5025500025502550255255002552552550000000000000000000000000000000000000000000000 112 | 0000000000000000000000000000000000006102102102102102102102102102102960000613611 113 | 9119119119119120136136136118000119102134102102102102102102102102102134640011810 114 | 2118102102102102102102102102102119960011810211910210413510212013613611810210496 115 | 0011810211910211125513513613613613410210496001181021031021031432481201361191021 116 | 0210396001191021031021021042552481181021021021031180011810210410210210214325513 117 | 5102102102103118001191021031181021021031432481181021021021340011911910311810210 118 | 2102232255248102102102134001191191181351191181021101432551021021021180013511911 119 | 8135119119136136255248102102102119960136119118136136136136143255136135118102119 120 | 9601361361341361361361362552551361361361361369601361361351201361361432552481361 121 | 3613613613696013613613610413613625525513613613613613613610001361361361041361362 122 | 5524813613613613613613611801361361361041361362551361361361361361361361340136136 123 | 1361201361361361361361361361361361361340813613613414325525525525525525525525524 124 | 8134000061021021021021021021021021021021020000000000000000000000000000000000000 125 | 0000000000000000000000000000000000000000000025525525525525525525525525525525525 126 | 5224003122400152240072240070007000700070003000300030003000300010001000100010000 127 | 0000000000000000000012800025400125525525525525525525525525525525525525525525525 128 | 5255255255255 129 | 130 | Description 131 | ----------- 132 | Returns the bytes representation of the icon. -Join was used in this for the sake 133 | of displaying all of the data. 134 | 135 | #> 136 | [cmdletbinding( 137 | DefaultParameterSetName = '__DefaultParameterSetName' 138 | )] 139 | Param ( 140 | [parameter(ValueFromPipelineByPropertyName=$True)] 141 | [ValidateNotNullorEmpty()] 142 | [string]$Path, 143 | [parameter(ParameterSetName = 'Bytes')] 144 | [switch]$ToBytes, 145 | [parameter(ParameterSetName = 'Bitmap')] 146 | [switch]$ToBitmap, 147 | [parameter(ParameterSetName = 'Base64')] 148 | [switch]$ToBase64 149 | ) 150 | Begin { 151 | If ($PSBoundParameters.ContainsKey('Debug')) { 152 | $DebugPreference = 'Continue' 153 | } 154 | Add-Type -AssemblyName System.Drawing 155 | } 156 | Process { 157 | $Path = Convert-Path -Path $Path 158 | Write-Debug $Path 159 | If (Test-Path -Path $Path) { 160 | $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)| 161 | Add-Member -MemberType NoteProperty -Name FullName -Value $Path -PassThru 162 | If ($PSBoundParameters.ContainsKey('ToBytes')) { 163 | Write-Verbose "Retrieving bytes" 164 | $MemoryStream = New-Object System.IO.MemoryStream 165 | $Icon.save($MemoryStream) 166 | Write-Debug ($MemoryStream | Out-String) 167 | $MemoryStream.ToArray() 168 | $MemoryStream.Flush() 169 | $MemoryStream.Dispose() 170 | } ElseIf ($PSBoundParameters.ContainsKey('ToBitmap')) { 171 | $Icon.ToBitMap() 172 | } ElseIf ($PSBoundParameters.ContainsKey('ToBase64')) { 173 | $MemoryStream = New-Object System.IO.MemoryStream 174 | $Icon.save($MemoryStream) 175 | Write-Debug ($MemoryStream | Out-String) 176 | $Bytes = $MemoryStream.ToArray() 177 | $MemoryStream.Flush() 178 | $MemoryStream.Dispose() 179 | [convert]::ToBase64String($Bytes) 180 | } Else { 181 | $Icon 182 | } 183 | } Else { 184 | Write-Warning "$Path does not exist!" 185 | Continue 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /Get-LocalGroupMembership.ps1: -------------------------------------------------------------------------------- 1 | Function Get-LocalGroupMembership { 2 | <# 3 | .SYNOPSIS 4 | Recursively list all members of a specified Local group. 5 | 6 | .DESCRIPTION 7 | Recursively list all members of a specified Local group. This can be run against a local or 8 | remote system or systems. Recursion is unlimited unless specified by the -Depth parameter. 9 | 10 | Alias: glgm 11 | 12 | .PARAMETER Computername 13 | Local or remote computer/s to perform the query against. 14 | 15 | Default value is the local system. 16 | 17 | .PARAMETER Group 18 | Name of the group to query on a system for all members. 19 | 20 | Default value is 'Administrators' 21 | 22 | .PARAMETER Depth 23 | Limit the recursive depth of a query. 24 | 25 | Default value is 2147483647. 26 | 27 | .PARAMETER Throttle 28 | Number of concurrently running jobs to run at a time 29 | 30 | Default value is 10 31 | 32 | .NOTES 33 | Author: Boe Prox 34 | Created: 8 AUG 2013 35 | Version 1.0 (8 AUG 2013): 36 | -Initial creation 37 | 38 | .EXAMPLE 39 | Get-LocalGroupMembership 40 | 41 | Name ParentGroup isGroup Type Computername Depth 42 | ---- ----------- ------- ---- ------------ ----- 43 | Administrator Administrators False Domain DC1 1 44 | boe Administrators False Domain DC1 1 45 | testuser Administrators False Domain DC1 1 46 | bob Administrators False Domain DC1 1 47 | proxb Administrators False Domain DC1 1 48 | Enterprise Admins Administrators True Domain DC1 1 49 | Sysops Admins Enterprise Admins True Domain DC1 2 50 | Domain Admins Enterprise Admins True Domain DC1 2 51 | Administrator Enterprise Admins False Domain DC1 2 52 | Domain Admins Administrators True Domain DC1 1 53 | proxb Domain Admins False Domain DC1 2 54 | Administrator Domain Admins False Domain DC1 2 55 | Sysops Admins Administrators True Domain DC1 1 56 | Org Admins Sysops Admins True Domain DC1 2 57 | Enterprise Admins Sysops Admins True Domain DC1 2 58 | 59 | Description 60 | ----------- 61 | Gets all of the members of the 'Administrators' group on the local system. 62 | 63 | .EXAMPLE 64 | Get-LocalGroupMembership -Group 'Administrators' -Depth 1 65 | 66 | Name ParentGroup isGroup Type Computername Depth 67 | ---- ----------- ------- ---- ------------ ----- 68 | Administrator Administrators False Domain DC1 1 69 | boe Administrators False Domain DC1 1 70 | testuser Administrators False Domain DC1 1 71 | bob Administrators False Domain DC1 1 72 | proxb Administrators False Domain DC1 1 73 | Enterprise Admins Administrators True Domain DC1 1 74 | Domain Admins Administrators True Domain DC1 1 75 | Sysops Admins Administrators True Domain DC1 1 76 | 77 | Description 78 | ----------- 79 | Gets the members of 'Administrators' with only 1 level of recursion. 80 | 81 | #> 82 | [cmdletbinding()] 83 | Param ( 84 | [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] 85 | [Alias('CN','__Server','Computer','IPAddress')] 86 | [string[]]$Computername = $env:COMPUTERNAME, 87 | [parameter()] 88 | [string]$Group = "Administrators", 89 | [parameter()] 90 | [int]$Depth = ([int]::MaxValue), 91 | [parameter()] 92 | [Alias("MaxJobs")] 93 | [int]$Throttle = 10 94 | ) 95 | Begin { 96 | $PSBoundParameters.GetEnumerator() | ForEach { 97 | Write-Verbose $_ 98 | } 99 | #region Extra Configurations 100 | Write-Verbose ("Depth: {0}" -f $Depth) 101 | #endregion Extra Configurations 102 | #Define hash table for Get-RunspaceData function 103 | $runspacehash = @{} 104 | #Function to perform runspace job cleanup 105 | Function Get-RunspaceData { 106 | [cmdletbinding()] 107 | param( 108 | [switch]$Wait 109 | ) 110 | Do { 111 | $more = $false 112 | Foreach($runspace in $runspaces) { 113 | If ($runspace.Runspace.isCompleted) { 114 | $runspace.powershell.EndInvoke($runspace.Runspace) 115 | $runspace.powershell.dispose() 116 | $runspace.Runspace = $null 117 | $runspace.powershell = $null 118 | } ElseIf ($runspace.Runspace -ne $null) { 119 | $more = $true 120 | } 121 | } 122 | If ($more -AND $PSBoundParameters['Wait']) { 123 | Start-Sleep -Milliseconds 100 124 | } 125 | #Clean out unused runspace jobs 126 | $temphash = $runspaces.clone() 127 | $temphash | Where { 128 | $_.runspace -eq $Null 129 | } | ForEach { 130 | Write-Verbose ("Removing {0}" -f $_.computer) 131 | $Runspaces.remove($_) 132 | } 133 | } while ($more -AND $PSBoundParameters['Wait']) 134 | } 135 | 136 | #region ScriptBlock 137 | $scriptBlock = { 138 | Param ($Computer,$Group,$Depth,$NetBIOSDomain,$ObjNT,$Translate) 139 | $Script:Depth = $Depth 140 | $Script:ObjNT = $ObjNT 141 | $Script:Translate = $Translate 142 | $Script:NetBIOSDomain = $NetBIOSDomain 143 | Function Get-LocalGroupMember { 144 | [cmdletbinding()] 145 | Param ( 146 | [parameter()] 147 | [System.DirectoryServices.DirectoryEntry]$LocalGroup 148 | ) 149 | # Invoke the Members method and convert to an array of member objects. 150 | #Change3 comment from web page by Craig Dempsey to fixe Powershell 5.0 issue 151 | #$Members= @($LocalGroup.psbase.Invoke("Members")) 152 | $Members= @($LocalGroup.psbase.Invoke("Members")) | foreach{([System.DirectoryServices.DirectoryEntry]$_)} 153 | $Counter++ 154 | ForEach ($Member In $Members) { 155 | Try { 156 | #Change3 157 | #$Name = $Member.GetType().InvokeMember("Name", 'GetProperty', $Null, $Member, $Null) 158 | #$Path = $Member.GetType().InvokeMember("ADsPath", 'GetProperty', $Null, $Member, $Null) 159 | $Name = $Member.InvokeGet("Name") 160 | $Path = $Member.InvokeGet("AdsPath") 161 | 162 | # Check if this member is a group. 163 | #Change3 164 | #$isGroup = ($Member.GetType().InvokeMember("Class", 'GetProperty', $Null, $Member, $Null) -eq "group") 165 | $isGroup = ($Member.InvokeGet("Class") -eq "group") 166 | 167 | #region Change1 by Kensel 168 | #Remove the domain from the computername to fix the type comparison when supplied with FQDN 169 | IF ($Computer.Contains('.')){ 170 | $Computer = $computer.Substring(0,$computer.IndexOf('.')) 171 | } 172 | #endregion Change1 by Kensel 173 | 174 | If (($Path -like "*/$Computer/*")) { 175 | $Type = 'Local' 176 | } Else {$Type = 'Domain'} 177 | #Change2 by Kensel - Add the Group to the output 178 | New-Object PSObject -Property @{ 179 | Computername = $Computer 180 | Name = $Name 181 | Type = $Type 182 | ParentGroup = $LocalGroup.Name[0] 183 | isGroup = $isGroup 184 | Depth = $Counter 185 | Group = $Group 186 | } 187 | If ($isGroup) { 188 | # Check if this group is local or domain. 189 | #$host.ui.WriteVerboseLine("(RS)Checking if Counter: {0} is less than Depth: {1}" -f $Counter, $Depth) 190 | If ($Counter -lt $Depth) { 191 | If ($Type -eq 'Local') { 192 | If ($Groups[$Name] -notcontains 'Local') { 193 | $host.ui.WriteVerboseLine(("{0}: Getting local group members" -f $Name)) 194 | $Groups[$Name] += ,'Local' 195 | # Enumerate members of local group. 196 | Get-LocalGroupMember $Member 197 | } 198 | } Else { 199 | If ($Groups[$Name] -notcontains 'Domain') { 200 | $host.ui.WriteVerboseLine(("{0}: Getting domain group members" -f $Name)) 201 | $Groups[$Name] += ,'Domain' 202 | # Enumerate members of domain group. 203 | Get-DomainGroupMember $Member $Name $True 204 | } 205 | } 206 | } 207 | } 208 | } Catch { 209 | $host.ui.WriteWarningLine(("GLGM{0}" -f $_.Exception.Message)) 210 | } 211 | } 212 | } 213 | 214 | Function Get-DomainGroupMember { 215 | [cmdletbinding()] 216 | Param ( 217 | [parameter()] 218 | $DomainGroup, 219 | [parameter()] 220 | [string]$NTName, 221 | [parameter()] 222 | [string]$blnNT 223 | ) 224 | Try { 225 | If ($blnNT -eq $True) { 226 | # Convert NetBIOS domain name of group to Distinguished Name. 227 | $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (3, ("{0}{1}" -f $NetBIOSDomain.Trim(),$NTName))) 228 | $DN = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 1) 229 | $ADGroup = [ADSI]"LDAP://$DN" 230 | } Else { 231 | $DN = $DomainGroup.distinguishedName 232 | $ADGroup = $DomainGroup 233 | } 234 | $Counter++ 235 | ForEach ($MemberDN In $ADGroup.Member) { 236 | $MemberGroup = [ADSI]("LDAP://{0}" -f ($MemberDN -replace '/','\/')) 237 | #Change2 by Kensel - Add the Group to the output 238 | New-Object PSObject -Property @{ 239 | Computername = $Computer 240 | Name = $MemberGroup.name[0] 241 | Type = 'Domain' 242 | ParentGroup = $NTName 243 | isGroup = ($MemberGroup.Class -eq "group") 244 | Depth = $Counter 245 | Group = $Group 246 | } 247 | # Check if this member is a group. 248 | If ($MemberGroup.Class -eq "group") { 249 | If ($Counter -lt $Depth) { 250 | If ($Groups[$MemberGroup.name[0]] -notcontains 'Domain') { 251 | Write-Verbose ("{0}: Getting domain group members" -f $MemberGroup.name[0]) 252 | $Groups[$MemberGroup.name[0]] += ,'Domain' 253 | # Enumerate members of domain group. 254 | Get-DomainGroupMember $MemberGroup $MemberGroup.Name[0] $False 255 | } 256 | } 257 | } 258 | } 259 | } Catch { 260 | $host.ui.WriteWarningLine(("GDGM{0}" -f $_.Exception.Message)) 261 | } 262 | } 263 | #region Get Local Group Members 264 | $Script:Groups = @{} 265 | $Script:Counter=0 266 | # Bind to the group object with the WinNT provider. 267 | $ADSIGroup = [ADSI]"WinNT://$Computer/$Group,group" 268 | Write-Verbose ("Checking {0} membership for {1}" -f $Group,$Computer) 269 | $Groups[$Group] += ,'Local' 270 | Get-LocalGroupMember -LocalGroup $ADSIGroup 271 | #endregion Get Local Group Members 272 | } 273 | #endregion ScriptBlock 274 | Write-Verbose ("Checking to see if connected to a domain") 275 | Try { 276 | $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 277 | $Root = $Domain.GetDirectoryEntry() 278 | $Base = ($Root.distinguishedName) 279 | 280 | # Use the NameTranslate object. 281 | $Script:Translate = New-Object -comObject "NameTranslate" 282 | $Script:objNT = $Translate.GetType() 283 | 284 | # Initialize NameTranslate by locating the Global Catalog. 285 | $objNT.InvokeMember("Init", "InvokeMethod", $Null, $Translate, (3, $Null)) 286 | 287 | # Retrieve NetBIOS name of the current domain. 288 | $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (1, "$Base")) 289 | [string]$Script:NetBIOSDomain =$objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 3) 290 | } Catch {Write-Warning ("{0}" -f $_.Exception.Message)} 291 | 292 | #region Runspace Creation 293 | Write-Verbose ("Creating runspace pool and session states") 294 | $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() 295 | $runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host) 296 | $runspacepool.Open() 297 | 298 | Write-Verbose ("Creating empty collection to hold runspace jobs") 299 | $Script:runspaces = New-Object System.Collections.ArrayList 300 | #endregion Runspace Creation 301 | } 302 | 303 | Process { 304 | ForEach ($Computer in $Computername) { 305 | #Create the powershell instance and supply the scriptblock with the other parameters 306 | $powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($computer).AddArgument($Group).AddArgument($Depth).AddArgument($NetBIOSDomain).AddArgument($ObjNT).AddArgument($Translate) 307 | 308 | #Add the runspace into the powershell instance 309 | $powershell.RunspacePool = $runspacepool 310 | 311 | #Create a temporary collection for each runspace 312 | $temp = "" | Select-Object PowerShell,Runspace,Computer 313 | $Temp.Computer = $Computer 314 | $temp.PowerShell = $powershell 315 | 316 | #Save the handle output when calling BeginInvoke() that will be used later to end the runspace 317 | $temp.Runspace = $powershell.BeginInvoke() 318 | Write-Verbose ("Adding {0} collection" -f $temp.Computer) 319 | $runspaces.Add($temp) | Out-Null 320 | 321 | Write-Verbose ("Checking status of runspace jobs") 322 | Get-RunspaceData @runspacehash 323 | } 324 | } 325 | End { 326 | Write-Verbose ("Finish processing the remaining runspace jobs: {0}" -f (@(($runspaces | Where {$_.Runspace -ne $Null}).Count))) 327 | $runspacehash.Wait = $true 328 | Get-RunspaceData @runspacehash 329 | 330 | #region Cleanup Runspace 331 | Write-Verbose ("Closing the runspace pool") 332 | $runspacepool.close() 333 | $runspacepool.Dispose() 334 | #endregion Cleanup Runspace 335 | } 336 | } 337 | 338 | Set-Alias -Name glgm -Value Get-LocalGroupMembership -------------------------------------------------------------------------------- /Get-NetworkInfo.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-NetworkInfo.ps1 -------------------------------------------------------------------------------- /Get-PSSQLInstance.ps1: -------------------------------------------------------------------------------- 1 | Function Get-PSSQLInstance { 2 | <# 3 | .SYNOPSIS 4 | Retrieves SQL server information from a local or remote servers. 5 | 6 | .DESCRIPTION 7 | Retrieves SQL server information from a local or remote servers. Pulls all 8 | instances from a SQL server and detects if in a cluster or not. 9 | 10 | .PARAMETER Computername 11 | Local or remote systems to query for SQL information. 12 | 13 | .NOTES 14 | Name: Get-PSSQLInstance 15 | Author: Boe Prox 16 | Version History: 17 | 1.5 //Boe Prox - 31 May 2016 18 | - Added WMI queries for more information 19 | - Custom object type name 20 | 1.0 //Boe Prox - 07 Sept 2013 21 | - Initial Version 22 | 23 | .EXAMPLE 24 | Get-PSSQLInstance -Computername SQL1 25 | 26 | Computername : SQL1 27 | Instance : MSSQLSERVER 28 | SqlServer : SQLCLU 29 | WMINamespace : ComputerManagement10 30 | Sqlstates : 2061 31 | Version : 10.53.6000.34 32 | Splevel : 3 33 | Clustered : True 34 | Installpath : C:\Program Files\Microsoft SQL 35 | Server\MSSQL10_50.MSSQLSERVER\MSSQL 36 | Datapath : D:\MSSQL10_50.MSSQLSERVER\MSSQL 37 | Language : 1033 38 | Fileversion : 2009.100.6000.34 39 | Vsname : SQLCLU 40 | Regroot : Software\Microsoft\Microsoft SQL 41 | Server\MSSQL10_50.MSSQLSERVER 42 | Sku : 1804890536 43 | Skuname : Enterprise Edition (64-bit) 44 | Instanceid : MSSQL10_50.MSSQLSERVER 45 | Startupparameters : -dD:\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\master.mdf;-eD:\MSSQL1 46 | 0_50.MSSQLSERVER\MSSQL\Log\ERRORLOG;-lD:\MSSQL10_50.MSSQLSERV 47 | ER\MSSQL\DATA\mastlog.ldf 48 | Errorreporting : False 49 | Dumpdir : D:\MSSQL10_50.MSSQLSERVER\MSSQL\LOG\ 50 | Sqmreporting : False 51 | Iswow64 : False 52 | BackupDirectory : F:\MSSQL10_50.MSSQLSERVER\MSSQL\Backup 53 | AlwaysOnName : 54 | Nodes : {SQL1, SQL2} 55 | Caption : SQL Server 2008 R2 56 | FullName : SQLCLU\MSSQLSERVER 57 | 58 | Description 59 | ----------- 60 | Retrieves the SQL information from SQL1 61 | #> 62 | [OutputType('SQLServer.Information')] 63 | [cmdletbinding()]  64 | Param( 65 | [parameter(ValueFromPipeline=$True)] 66 | [string[]]$Computername = 'G13' 67 | ) 68 | Process { 69 | ForEach ($Computer in $Computername) { 70 | # 1 = MSSQLSERVER 71 | $Filter = "SELECT * FROM SqlServiceAdvancedProperty WHERE SqlServiceType=1" 72 | $WMIParams=@{ 73 | Computername = $Computer 74 | NameSpace='root\Microsoft\SqlServer' 75 | Query="SELECT name FROM __NAMESPACE WHERE name LIKE 'ComputerManagement%'" 76 | Authentication = 'PacketPrivacy' 77 | ErrorAction = 'Stop' 78 | } 79 | Write-Verbose "[$Computer] Starting SQL Scan" 80 | $PropertyHash = [ordered]@{ 81 | Computername = $Computer 82 | Instance = $Null 83 | SqlServer = $Null 84 | WmiNamespace = $Null 85 | SQLSTATES = $Null 86 | VERSION = $Null 87 | SPLEVEL = $Null 88 | CLUSTERED = $Null 89 | INSTALLPATH = $Null 90 | DATAPATH = $Null 91 | LANGUAGE = $Null 92 | FILEVERSION = $Null 93 | VSNAME = $Null 94 | REGROOT = $Null 95 | SKU = $Null 96 | SKUNAME = $Null 97 | INSTANCEID = $Null 98 | STARTUPPARAMETERS = $Null 99 | ERRORREPORTING = $Null 100 | DUMPDIR = $Null 101 | SQMREPORTING = $Null 102 | ISWOW64 = $Null 103 | BackupDirectory = $Null 104 | AlwaysOnName = $Null 105 | } 106 | Try { 107 | Write-Verbose "[$Computer] Performing Registry Query" 108 | $Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer) 109 | } 110 | Catch { 111 | Write-Warning "[$Computer] $_" 112 | Continue 113 | } 114 | $baseKeys = "SOFTWARE\\Microsoft\\Microsoft SQL Server", 115 | "SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SQL Server" 116 | Try { 117 | $ErrorActionPreference = 'Stop' 118 | If ($Registry.OpenSubKey($basekeys[0])) { 119 | $regPath = $basekeys[0] 120 | } 121 | ElseIf ($Registry.OpenSubKey($basekeys[1])) { 122 | $regPath = $basekeys[1] 123 | } 124 | Else { 125 | Continue 126 | } 127 | } 128 | Catch { 129 | Continue 130 | } 131 | Finally { 132 | $ErrorActionPreference = 'Continue' 133 | } 134 | $RegKey= $Registry.OpenSubKey("$regPath") 135 | If ($RegKey.GetSubKeyNames() -contains "Instance Names") { 136 | $RegKey= $Registry.OpenSubKey("$regpath\\Instance Names\\SQL" ) 137 | $instances = @($RegKey.GetValueNames()) 138 | } 139 | ElseIf ($regKey.GetValueNames() -contains 'InstalledInstances') { 140 | $isCluster = $False 141 | $instances = $RegKey.GetValue('InstalledInstances') 142 | } 143 | Else { 144 | Continue 145 | } 146 | 147 | If ($instances.count -gt 0) { 148 | ForEach ($Instance in $Instances) { 149 | $PropertyHash['Instance']=$Instance 150 | $Nodes = New-Object System.Collections.Arraylist 151 | $clusterName = $Null 152 | $isCluster = $False 153 | $instanceValue = $regKey.GetValue($instance) 154 | $instanceReg = $Registry.OpenSubKey("$regpath\\$instanceValue") 155 | If ($instanceReg.GetSubKeyNames() -contains "Cluster") { 156 | $isCluster = $True 157 | $instanceRegCluster = $instanceReg.OpenSubKey('Cluster') 158 | $clusterName = $instanceRegCluster.GetValue('ClusterName') 159 | $clusterReg = $Registry.OpenSubKey("Cluster\\Nodes") 160 | $clusterReg.GetSubKeyNames() | ForEach { 161 | $null = $Nodes.Add($clusterReg.OpenSubKey($_).GetValue('NodeName')) 162 | } 163 | } 164 | $PropertyHash['Nodes'] = $Nodes 165 | 166 | $instanceRegSetup = $instanceReg.OpenSubKey("Setup") 167 | Try { 168 | $edition = $instanceRegSetup.GetValue('Edition') 169 | } Catch { 170 | $edition = $Null 171 | } 172 | $PropertyHash['Skuname'] = $edition 173 | Try { 174 | $ErrorActionPreference = 'Stop' 175 | #Get from filename to determine version 176 | $servicesReg = $Registry.OpenSubKey("SYSTEM\\CurrentControlSet\\Services") 177 | $serviceKey = $servicesReg.GetSubKeyNames() | Where { 178 | $_ -eq ('MSSQL${0}' -f $instance) 179 | } | Select -First 1 180 | $service = $servicesReg.OpenSubKey($serviceKey).GetValue('ImagePath') 181 | $file = $service -replace '^.*(\w:\\.*\\sqlservr.exe).*','$1' 182 | $PropertyHash['version'] =(Get-Item ("\\$Computer\$($file -replace ":","$")")).VersionInfo.ProductVersion 183 | } Catch { 184 | #Use potentially less accurate version from registry 185 | $PropertyHash['Version'] = $instanceRegSetup.GetValue('Version') 186 | } Finally { 187 | $ErrorActionPreference = 'Continue' 188 | } 189 | 190 | Try { 191 | Write-Verbose "[$Computer] Performing WMI Query" 192 | $Namespace = $Namespace = (Get-WMIObject @WMIParams | Sort-Object -Descending | Select-Object -First 1).Name 193 | If ($Namespace) { 194 | $PropertyHash['WMINamespace'] = $Namespace 195 | $WMIParams.NameSpace="root\Microsoft\SqlServer\$Namespace" 196 | $WMIParams.Query=$Filter 197 | 198 | $WMIResults = Get-WMIObject @WMIParams 199 | $GroupResults = $WMIResults | Group ServiceName 200 | $PropertyHash['Instance'] = $GroupResults.Name 201 | $WMIResults | ForEach { 202 | $Name = "{0}{1}" -f ($_.PropertyName.SubString(0,1),$_.PropertyName.SubString(1).ToLower()) 203 | $Data = If ($_.PropertyStrValue) { 204 | $_.PropertyStrValue 205 | } 206 | Else { 207 | If ($Name -match 'Clustered|ErrorReporting|SqmReporting|IsWow64') { 208 | [bool]$_.PropertyNumValue 209 | } 210 | Else { 211 | $_.PropertyNumValue 212 | } 213 | } 214 | $PropertyHash[$Name] = $Data 215 | } 216 | 217 | #region Always on availability group 218 | if ($PropertyHash['Version'].Major -ge 11) { 219 | $splat.Query="SELECT WindowsFailoverClusterName FROM HADRServiceSettings WHERE InstanceName = '$($Group.Name)'" 220 | $PropertyHash['AlwaysOnName'] = (Get-WmiObject @WMIParams).WindowsFailoverClusterName 221 | if ($PropertyHash['AlwaysOnName']) { 222 | $PropertyHash.SqlServer = $PropertyHash['AlwaysOnName'] 223 | } 224 | } 225 | else { 226 | $PropertyHash['AlwaysOnName'] = $null 227 | } 228 | #endregion Always on availability group 229 | 230 | #region Backup Directory 231 | $RegKey=$Registry.OpenSubKey("$($PropertyHash['RegRoot'])\MSSQLServer") 232 | $PropertyHash['BackupDirectory'] = $RegKey.GetValue('BackupDirectory') 233 | #endregion Backup Directory 234 | }#IF NAMESPACE 235 | } 236 | Catch { 237 | } 238 | #region Caption 239 | $Caption = {Switch -Regex ($PropertyHash['version']) { 240 | "^13" {'SQL Server 2016';Break} 241 | "^12" {'SQL Server 2014';Break} 242 | "^11" {'SQL Server 2012';Break} 243 | "^10\.5" {'SQL Server 2008 R2';Break} 244 | "^10" {'SQL Server 2008';Break} 245 | "^9" {'SQL Server 2005';Break} 246 | "^8" {'SQL Server 2000';Break} 247 | Default {'Unknown'} 248 | }}.InvokeReturnAsIs() 249 | $PropertyHash['Caption'] = $Caption 250 | #endregion Caption 251 | 252 | #region Full SQL Name 253 | $Name = If ($clusterName) { 254 | $clusterName 255 | $PropertyHash['SqlServer'] = $clusterName 256 | } 257 | Else { 258 | $Computer 259 | $PropertyHash['SqlServer'] = $Computer 260 | } 261 | $PropertyHash['FullName'] = ("{0}\{1}" -f $Name,$PropertyHash['Instance']) 262 | #emdregion Full SQL Name 263 | $Object = [pscustomobject]$PropertyHash 264 | $Object.pstypenames.insert(0,'SQLServer.Information') 265 | $Object 266 | }#FOREACH INSTANCE 267 | }#IF 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /Get-PendingUpdate.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-PendingUpdate.ps1 -------------------------------------------------------------------------------- /Get-ProductKey.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-ProductKey.ps1 -------------------------------------------------------------------------------- /Get-SCCMClientUpdate.ps1: -------------------------------------------------------------------------------- 1 | Function Get-SCCMClientUpdate { 2 | <# 3 | .SYNOPSIS 4 | Allows you to query for updates via the SCCM Client Agent 5 | 6 | .DESCRIPTION 7 | Allows you to query for updates via the SCCM Client Agent 8 | 9 | .PARAMETER ShowHidden 10 | If in Quiet mode, use ShowHidden to view updates. 11 | 12 | .PARAMETER UpdateAction 13 | Define the type of action to query for. 14 | 15 | The following values are allowed: 16 | Install - This setting retrieves all updates that are available to be installed or in the process of being installed. 17 | Uninstall - This setting retrieves updates that are already installed and are available to be uninstalled. 18 | 19 | .NOTES 20 | Author: Boe Prox 21 | Created: 3July2012 22 | Name: Get-SCCMClientUpdate 23 | 24 | .EXAMPLE 25 | Get-SCCMClientUpdate -ShowHidden | Format-Table Name,KB,BulletinID,EnforcementDeadline,UpdateStatus 26 | 27 | Name KB BulletinID EnforcementDeadline UpdateStatus 28 | ---- -- ---------- ------------------- ------------ 29 | Security Update for ... 2709162 {MS12-041} 6/26/2012 1:00:00 AM JobStateWaitInstall 30 | Service Pack 3 for V... 2526301 {} 6/4/2012 8:00:00 PM JobStateDownloading 31 | Security Update for ... 2656374 {MS12-025} 6/26/2012 1:00:00 AM JobStateWaitInstall 32 | Security Update for ... 2656351 {MS11-100} 6/3/2012 11:00:00 PM JobStateStateError 33 | Security Update for ... 2686833 {MS12-038} 6/26/2012 1:00:00 AM JobStateWaitInstall 34 | Cumulative Security ... 2699988 {MS12-037} 6/26/2012 1:00:00 AM JobStateWaitInstall 35 | Security Update for ... 2656368 {MS12-025} 6/26/2012 1:00:00 AM JobStateWaitInstall 36 | Security Update for ... 2686827 {MS12-038} 6/26/2012 1:00:00 AM JobStateWaitInstall 37 | Update for Windows V... 2677070 {} 6/26/2012 1:00:00 AM JobStateWaitInstall 38 | Update for Windows V... 2718704 {} 6/26/2012 1:00:00 AM JobStateWaitInstall 39 | Security Update for ... 2685939 {MS12-036} 6/26/2012 1:00:00 AM JobStateWaitInstall 40 | Windows Malicious So... 890830 {} 6/26/2012 1:00:00 AM JobStateWaitInstall 41 | 42 | Description 43 | ----------- 44 | This command will show all updates waiting to be installed on SCCM Client. 45 | #> 46 | [cmdletbinding()] 47 | Param( 48 | [parameter()] 49 | [switch]$ShowHidden, 50 | [parameter()] 51 | [ValidateSet('Install','Uninstall')] 52 | [string]$UpdateAction = 'Install' 53 | ) 54 | Begin { 55 | $PSBoundParameters.GetEnumerator() | ForEach { 56 | Write-Verbose ("{0}" -f $_) 57 | } 58 | 59 | $Action = [hashtable]@{ 60 | Install = 2 61 | Uninstall = 3 62 | } 63 | $statusHash = [hashtable]@{ 64 | 0 = 'JobStateNone' 65 | 1 = 'JobStateAvailable' 66 | 2 = 'JobStateSubmitted' 67 | 3 = 'JobStateDetecting' 68 | 4 = 'JobStateDownloadingCIDef' 69 | 5 = 'JobStateDownloadingSdmPkg' 70 | 6 = 'JobStatePreDownload' 71 | 7 = 'JobStateDownloading' 72 | 8 = 'JobStateWaitInstall' 73 | 9 = 'JobStateInstalling' 74 | 10 = 'JobStatePendingSoftReboot' 75 | 11 = 'JobStatePendingHardReboot' 76 | 12 = 'JobStateWaitReboot' 77 | 13 = 'JobStateVerifying' 78 | 14 = 'JobStateInstallComplete' 79 | 15 = 'JobStateStateError' 80 | 16 = 'JobStateWaitServiceWindo' 81 | } 82 | [ref]$progress = $Null 83 | } 84 | Process { 85 | Write-Verbose ("UpdateAction: {0}" -f $UpdateAction) 86 | Try { 87 | $SCCMUpdate = New-Object -ComObject UDA.CCMUpdatesDeployment 88 | $updates = $SCCMUpdate.EnumerateUpdates( 89 | $Action[$UpdateAction], 90 | $PSBoundParameters['ShowHidden'], 91 | $Progress 92 | ) 93 | $Count = $updates.GetCount() 94 | } Catch { 95 | Write-Warning ("{0}" -f $_.Exception.Message) 96 | } 97 | If ($Count -gt 0) { 98 | Write-Verbose ("Found {0} updates!" -f $Count) 99 | Try { 100 | For ($i=0;$i -lt $Count;$i++) { 101 | [ref]$status = $Null 102 | [ref]$Complete = $Null 103 | [ref]$Errors = $Null 104 | $update = $updates.GetUpdate($i) 105 | $UpdateObject = New-Object PSObject -Property @{ 106 | KB = $update.GetArticleID() 107 | BulletinID = {Try {$update.GetBulletinID()} Catch {}}.invoke() 108 | DownloadSize = $update.GetDownloadSize() 109 | EnforcementDeadline = $update.GetEnforcementDeadline() 110 | ExclusiveUpdateOption = $update.GetExclusiveUpdateOption() 111 | ID = $update.GetID() 112 | InfoLink = $update.GetInfoLink(1033) 113 | Manufacture = $update.GetManufacturer(1033) 114 | Name = $update.GetName(1033) 115 | NotificationOption = $update.GetNotificationOption() 116 | Progress = $update.GetProgress($status,$Complete,$Errors) 117 | UpdateStatus = $statusHash[$status.value] 118 | ErrorCode = $Errors.Value 119 | RebootDeadling = $update.GetRebootDeadline() 120 | State = $update.GetState() 121 | Summary = $update.GetSummary(1033) 122 | } 123 | $UpdateObject.PSTypeNames.Insert(0,'SCCMUpdate.Update') 124 | $UpdateObject 125 | } 126 | } Catch { 127 | Write-Warning ("{0}" -f $_.Exception.Message) 128 | } 129 | } Else { 130 | Write-Verbose 'No updates found!' 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /Get-ServiceStartModeEvent.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ServiceStartModeEvent { 2 | <# 3 | .SYNOPSIS 4 | Finds all events related to a service startmode change in the event log. 5 | 6 | .DESCRIPTION 7 | Finds all events related to a service startmode change in the event log. 8 | 9 | .PARAMETER Computername 10 | Name of the computer to query 11 | 12 | .PARAMETER Path 13 | The full path to a specified event log that has been archived or saved to 14 | a filesystem location. 15 | 16 | .NOTES 17 | Name: Get-ServiceStartModeEvent 18 | Author: Boe Prox 19 | Version History: 20 | 1.0 //Boe Prox - 07/08/2016 21 | - Initial version 22 | 23 | .EXAMPLE 24 | Get-ServiceStartModeEvent -Computer $Env:Computername 25 | 26 | Description 27 | ----------- 28 | Displays all events related to service startmode changes. 29 | #> 30 | [cmdletbinding( 31 | DefaultParameterSetName = 'Computer' 32 | )] 33 | Param ( 34 | [parameter(ParameterSetName='Computer')] 35 | [string[]]$Computername = $env:COMPUTERNAME, 36 | [parameter(ParameterSetName='File', ValueFromPipelineByPropertyName = $True)] 37 | [Alias('Fullname')] 38 | [string[]]$Path 39 | ) 40 | Begin { 41 | Write-Verbose $PSCmdlet.ParameterSetName 42 | If ($PScmdlet.parametersetname -eq 'File') { 43 | $Query = @" 44 | 45 | 46 | 47 | 48 | 49 | "@ 50 | } Else { 51 | $Query = @" 52 | 53 | 54 | 55 | 56 | 57 | "@ 58 | } 59 | } 60 | Process { 61 | Switch ($PScmdlet.ParameterSetName) { 62 | 'Computer' { 63 | ForEach ($Computer in $Computername) { 64 | Get-WinEvent -ComputerName $Computer -LogName System -FilterXPath $Query | ForEach { 65 | $Properties = $_.Properties 66 | [pscustomobject] @{ 67 | Computername = $_.MachineName 68 | TimeCreated = $_.TimeCreated 69 | Servicename = $Properties[0].Value 70 | PriorStartMode = $Properties[1].Value 71 | CurrentStartMode = $Properties[2].Value 72 | ChangedBy = ([System.Security.Principal.SecurityIdentifier]$_.UserID).Translate([System.Security.Principal.NTAccount]).Value 73 | } 74 | } 75 | } 76 | } 77 | 'File' { 78 | ForEach ($Item in $Path) { 79 | $SearchQuery = $Query -Replace 'TOREPLACE',$Item 80 | Write-Verbose $SearchQuery 81 | Get-WinEvent -Path $Item -FilterXPath $SearchQuery | ForEach { 82 | $Properties = $_.Properties 83 | [pscustomobject] @{ 84 | Computername = $_.MachineName 85 | TimeCreated = $_.TimeCreated 86 | Servicename = $Properties[0].Value 87 | PriorStartMode = $Properties[1].Value 88 | CurrentStartMode = $Properties[2].Value 89 | ChangedBy = ([System.Security.Principal.SecurityIdentifier]$_.UserID).Translate([System.Security.Principal.NTAccount]).Value 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Get-ServiceStateEvent.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ServiceStateEvent { 2 | <# 3 | .SYNOPSIS 4 | Finds all events related to a service state change in the event log. 5 | 6 | .DESCRIPTION 7 | Finds all events related to a service state change in the event log. 8 | 9 | .PARAMETER Computername 10 | Name of the computer to query 11 | 12 | .PARAMETER Path 13 | The full path to a specified event log that has been archived or saved to 14 | a filesystem location. 15 | 16 | .NOTES 17 | Name: Get-ServiceStateEvent 18 | Author: Boe Prox 19 | Version History: 20 | 1.0 //Boe Prox - 07/08/2016 21 | - Initial version 22 | 23 | .EXAMPLE 24 | Get-ServiceStateEvent -Computer $Env:Computername 25 | 26 | Description 27 | ----------- 28 | Displays all events related to service state changes. 29 | #> 30 | [cmdletbinding( 31 | DefaultParameterSetName = 'Computer' 32 | )] 33 | Param ( 34 | [parameter(ParameterSetName='Computer')] 35 | [string[]]$Computername = $env:COMPUTERNAME, 36 | [parameter(ParameterSetName='File', ValueFromPipelineByPropertyName = $True)] 37 | [Alias('Fullname')] 38 | [string[]]$Path 39 | ) 40 | Begin { 41 | Write-Verbose $PSCmdlet.ParameterSetName 42 | If ($PScmdlet.parametersetname -eq 'File') { 43 | $Query = @" 44 | 45 | 46 | 47 | 48 | 49 | "@ 50 | } Else { 51 | $Query = @" 52 | 53 | 54 | 55 | 56 | 57 | "@ 58 | } 59 | } 60 | Process { 61 | Switch ($PScmdlet.ParameterSetName) { 62 | 'Computer' { 63 | ForEach ($Computer in $Computername) { 64 | Get-WinEvent -ComputerName $Computer -LogName System -FilterXPath $Query | ForEach { 65 | $Properties = $_.Properties 66 | [pscustomobject] @{ 67 | Computername = $_.MachineName 68 | TimeCreated = $_.TimeCreated 69 | Servicename = $Properties[0].Value 70 | State = $Properties[1].Value 71 | } 72 | } 73 | } 74 | } 75 | 'File' { 76 | ForEach ($Item in $Path) { 77 | $SearchQuery = $Query -Replace 'TOREPLACE',$Item 78 | Write-Verbose $SearchQuery 79 | Get-WinEvent -Path $Item -FilterXPath $SearchQuery | ForEach { 80 | $Properties = $_.Properties 81 | [pscustomobject] @{ 82 | Computername = $_.MachineName 83 | TimeCreated = $_.TimeCreated 84 | Servicename = $Properties[0].Value 85 | State = $Properties[1].Value 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Get-TCPResponse.ps1: -------------------------------------------------------------------------------- 1 | Function Get-TCPResponse { 2 | <# 3 | .SYNOPSIS 4 | Tests TCP port of remote or local system and returns a response header 5 | if applicable 6 | 7 | .DESCRIPTION 8 | Tests TCP port of remote or local system and returns a response header 9 | if applicable 10 | 11 | If server has no default response, then Response property will be NULL 12 | 13 | .PARAMETER Computername 14 | Local or remote system to test connection 15 | 16 | .PARAMETER Port 17 | TCP Port to connect to 18 | 19 | .PARAMETER TCPTimeout 20 | Time until connection should abort 21 | 22 | .NOTES 23 | Name: Get-TCPResponse 24 | Author: Boe Prox 25 | Version History: 26 | 1.0 -- 15 Jan 2014 27 | -Initial build 28 | 29 | .INPUTS 30 | System.String 31 | 32 | .OUTPUTS 33 | Net.TCPResponse 34 | 35 | .EXAMPLE 36 | Get-TCPResponse -Computername Exchange1 -Port 25 37 | 38 | Computername : Exchange1 39 | Port : 25 40 | IsOpen : True 41 | Response : 220 SMTP Server Ready 42 | 43 | Description 44 | ----------- 45 | Checks port 25 of an exchange server and displays header response. 46 | #> 47 | [OutputType('Net.TCPResponse')] 48 | [cmdletbinding()] 49 | Param ( 50 | [parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)] 51 | [Alias('__Server','IPAddress','IP')] 52 | [string[]]$Computername = $env:Computername, 53 | [int[]]$Port = 902, 54 | [int]$TCPTimeout = 1000 55 | ) 56 | Process { 57 | ForEach ($Computer in $Computername) { 58 | ForEach ($_port in $Port) { 59 | $stringBuilder = New-Object Text.StringBuilder 60 | $tcpClient = New-Object System.Net.Sockets.TCPClient 61 | $connect = $tcpClient.BeginConnect($Computer,$_port,$null,$null) 62 | $wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout,$false) 63 | If (-NOT $wait) { 64 | $object = [pscustomobject] @{ 65 | Computername = $Computer 66 | Port = $_Port 67 | IsOpen = $False 68 | Response = $Null 69 | } 70 | } Else { 71 | While ($True) { 72 | #Let buffer 73 | Start-Sleep -Milliseconds 1000 74 | Write-Verbose "Bytes available: $($tcpClient.Available)" 75 | If ([int64]$tcpClient.Available -gt 0) { 76 | $stream = $TcpClient.GetStream() 77 | $bindResponseBuffer = New-Object Byte[] -ArgumentList $tcpClient.Available 78 | [Int]$response = $stream.Read($bindResponseBuffer, 0, $bindResponseBuffer.count) 79 | $Null = $stringBuilder.Append(($bindResponseBuffer | ForEach {[char][int]$_}) -join '') 80 | } Else { 81 | Break 82 | } 83 | } 84 | $object = [pscustomobject] @{ 85 | Computername = $Computer 86 | Port = $_Port 87 | IsOpen = $True 88 | Response = $stringBuilder.Tostring() 89 | } 90 | } 91 | $object.pstypenames.insert(0,'Net.TCPResponse') 92 | Write-Output $object 93 | If ($Stream) { 94 | $stream.Close() 95 | $stream.Dispose() 96 | } 97 | $tcpClient.Close() 98 | $tcpClient.Dispose() 99 | } 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /Get-USGSWaterData.ps1: -------------------------------------------------------------------------------- 1 | Function Get-USGSWaterData { 2 | <# 3 | .SYNOPSIS 4 | Retrieves the water height of the Papio Creek along Ft Crook station in Bellevue, NE. 5 | Running without parameters shows last 24 hours worth of data. 6 | 7 | .DESCRIPTION 8 | Retrieves the water height of the Papio Creek along Ft Crook station in Bellevue, NE. 9 | Running without parameters shows last 24 hours worth of data. 10 | 11 | .PARAMETER Location 12 | The location to query for water information. 13 | 14 | Default Value is: 06610795 (Ft Crook - Papio Creek; Bellevue, NE) 15 | Find other values at: http://maps.waterdata.usgs.gov/mapper/index.html 16 | 17 | .PARAMETER StartTime 18 | Oldest starting time to look for data 19 | 20 | .PARAMETER EndTime 21 | The latest time to end search for data 22 | 23 | .NOTES 24 | Name: Get-USGSPapioBellevue 25 | Author: Boe Prox 26 | Version History: 27 | 1.0 //Boe Prox - 16 May 2016 28 | - Initial build 29 | 30 | .INPUTS 31 | System.String 32 | 33 | .OUTPUTS 34 | Web.USGS.Data 35 | 36 | .LINK 37 | http://maps.waterdata.usgs.gov/mapper/index.html 38 | 39 | .EXAMPLE 40 | Get-USGSWaterData | Select-Object -Last 1 | Format-List 41 | 42 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 43 | DateTime : 5/18/2016 6:15:00 AM 44 | Height_FT : 10.52 45 | Discharge : 354 46 | 47 | Description 48 | ----------- 49 | Retrieves the last 24 hours worth of data and looking at the most recent 10 entries 50 | 51 | .EXAMPLE 52 | Get-USGSWaterData -StartDate '05/10/2015' -EndDate '05/12/2015' | Select-Object -Last 5 | Format-List 53 | 54 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 55 | DateTime : 5/12/2015 10:45:00 PM 56 | Height_FT : 10.83 57 | Discharge : 413 58 | 59 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 60 | DateTime : 5/12/2015 11:00:00 PM 61 | Height_FT : 10.82 62 | Discharge : 411 63 | 64 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 65 | DateTime : 5/12/2015 11:15:00 PM 66 | Height_FT : 10.84 67 | Discharge : 416 68 | 69 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 70 | DateTime : 5/12/2015 11:30:00 PM 71 | Height_FT : 10.83 72 | Discharge : 413 73 | 74 | Location : 06610795-Papillion-Creek-at-Fort-Crook-Nebr 75 | DateTime : 5/12/2015 11:45:00 PM 76 | Height_FT : 10.82 77 | Discharge : 411 78 | 79 | Description 80 | ----------- 81 | Retrieves entries from 05/10/2015 to 05/12/2015 82 | #> 83 | [OutputType('Web.USGS.Data')] 84 | [cmdletbinding()] 85 | Param ( 86 | [string]$Location = '06610795', #Ft Crook Rd in Bellevue, NE 87 | [datetime]$StartDate = (Get-Date).AddDays(-1), 88 | [datetime]$EndDate = (Get-Date) 89 | ) 90 | 91 | If ($PSBoundParameters.ContainsKey('Debug')) { 92 | $DebugPreference = 'Continue' 93 | } 94 | If ($StartDate.Date -eq (Get-Date).Date) { 95 | $StartDate = $StartDate.AddDays(-1) 96 | } 97 | 98 | $__StartDate = $StartDate.ToString('yyyy-MM-dd') 99 | $__EndDate = $EndDate.ToString('yyyy-MM-dd') 100 | $URI = "http://waterdata.usgs.gov/ne/nwis/uv?cb_00065=on&cb_00060=on&format=html&site_no=$($Location)&period=&begin_date=$($__StartDate)&end_date=$($__EndDate)" 101 | $RegEx = [regex]"^(?(?:\d{2}/){2}\d{4}\s\d{2}:\d{2})\s(?[a-zA-Z]{1,})(?\d{1,}\.\d{2})(?:A|P)\s{2}(?(?:\d{1,},)*\d{1,})(?:A|P)" 102 | 103 | Try { 104 | $Data = Invoke-WebRequest -Uri $URI 105 | } 106 | Catch { 107 | Write-Warning $_ 108 | BREAK 109 | } 110 | 111 | If ($Data.ParsedHtml.body.innertext -match 'Redirecting') { 112 | Write-Verbose "Requesting data older or longer than 120 days, performing redirection" 113 | $Data = Invoke-WebRequest -Uri $Data.links.href 114 | } 115 | 116 | $Title = ((@($Data.ParsedHtml.getElementsByTagName('Title'))[0].Text -replace '.*USGS(.*)','$1').Trim() -replace ',|\.') -replace ' ','-' 117 | Write-Verbose "[$($Title)]" 118 | @($Data.ParsedHtml.getElementsByTagName('Table'))[3].InnerText -split '\r\n' | ForEach { 119 | If ($_ -match $RegEx) { 120 | $Object = [pscustomobject]@{ 121 | Location = $Title 122 | DateTime = [datetime]$Matches.DateTime 123 | Height_FT = [decimal]$Matches.Height 124 | Discharge = [decimal]$Matches.Discharge -replace ',' 125 | } 126 | $Object.pstypenames.insert(0,'Web.USGS.Data') 127 | $Object 128 | } 129 | Else { 130 | Write-Debug "[$($_)] No match found!" 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /Get-WebPage.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Get-WebPage.ps1 -------------------------------------------------------------------------------- /Install-WSUSServer.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Install-WSUSServer.ps1 -------------------------------------------------------------------------------- /Invoke-BalloonTip.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-BalloonTip { 2 | <# 3 | .Synopsis 4 | Display a balloon tip message in the system tray. 5 | 6 | .Description 7 | This function displays a user-defined message as a balloon popup in the system tray. This function 8 | requires Windows Vista or later. 9 | 10 | .Parameter Message 11 | The message text you want to display. Recommended to keep it short and simple. 12 | 13 | .Parameter Title 14 | The title for the message balloon. 15 | 16 | .Parameter MessageType 17 | The type of message. This value determines what type of icon to display. Valid values are 18 | 19 | .Parameter SysTrayIcon 20 | The path to a file that you will use as the system tray icon. Default is the PowerShell ISE icon. 21 | 22 | .Parameter Duration 23 | The number of seconds to display the balloon popup. The default is 1000. 24 | 25 | .Inputs 26 | None 27 | 28 | .Outputs 29 | None 30 | 31 | .Notes 32 | NAME: Invoke-BalloonTip 33 | VERSION: 1.0 34 | AUTHOR: Boe Prox 35 | #> 36 | 37 | [CmdletBinding()] 38 | Param ( 39 | [Parameter(Mandatory=$True,HelpMessage="The message text to display. Keep it short and simple.")] 40 | [string]$Message, 41 | 42 | [Parameter(HelpMessage="The message title")] 43 | [string]$Title="Attention $env:username", 44 | 45 | [Parameter(HelpMessage="The message type: Info,Error,Warning,None")] 46 | [System.Windows.Forms.ToolTipIcon]$MessageType="Info", 47 | 48 | [Parameter(HelpMessage="The path to a file to use its icon in the system tray")] 49 | [string]$SysTrayIconPath='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe', 50 | 51 | [Parameter(HelpMessage="The number of milliseconds to display the message.")] 52 | [int]$Duration=1000 53 | ) 54 | 55 | Add-Type -AssemblyName System.Windows.Forms 56 | 57 | If (-NOT $global:balloon) { 58 | $global:balloon = New-Object System.Windows.Forms.NotifyIcon 59 | 60 | #Mouse double click on icon to dispose 61 | [void](Register-ObjectEvent -InputObject $balloon -EventName MouseDoubleClick -SourceIdentifier IconClicked -Action { 62 | #Perform cleanup actions on balloon tip 63 | Write-Verbose 'Disposing of balloon' 64 | $global:balloon.dispose() 65 | Unregister-Event -SourceIdentifier IconClicked 66 | Remove-Job -Name IconClicked 67 | Remove-Variable -Name balloon -Scope Global 68 | }) 69 | } 70 | 71 | #Need an icon for the tray 72 | $path = Get-Process -id $pid | Select-Object -ExpandProperty Path 73 | 74 | #Extract the icon from the file 75 | $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($SysTrayIconPath) 76 | 77 | #Can only use certain TipIcons: [System.Windows.Forms.ToolTipIcon] | Get-Member -Static -Type Property 78 | $balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]$MessageType 79 | $balloon.BalloonTipText = $Message 80 | $balloon.BalloonTipTitle = $Title 81 | $balloon.Visible = $true 82 | 83 | #Display the tip and specify in milliseconds on how long balloon will stay visible 84 | $balloon.ShowBalloonTip($Duration) 85 | 86 | Write-Verbose "Ending function" 87 | 88 | } -------------------------------------------------------------------------------- /Invoke-WSUSClientFixID.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-WSUSClientFix { 2 | <# 3 | .SYNOPSIS 4 | Performs a WSUS client reset on local or remote system. 5 | 6 | .DESCRIPTION 7 | Performs a WSUS client reset on local or remote system. 8 | 9 | .PARAMETER Computername 10 | Name of the remote or local system. 11 | 12 | .NOTES 13 | Name: Invoke-WSUSClientFix 14 | Author: Boe Prox 15 | DateCreated: 18JAN2012 16 | DateModified: 28Mar2014 17 | 18 | .EXAMPLE 19 | Invoke-WSUSClientFix -Computername 'Server' -Verbose 20 | 21 | VERBOSE: Server: Testing network connection 22 | VERBOSE: Server: Stopping wuauserv service 23 | VERBOSE: Server: Making remote registry connection to LocalMachine hive 24 | VERBOSE: Server: Connection to WSUS Client registry keys 25 | VERBOSE: Server: Removing Software Distribution folder and subfolders 26 | VERBOSE: Server: Starting wuauserv service 27 | VERBOSE: Server: Sending wuauclt /resetauthorization /detectnow command 28 | 29 | Description 30 | ----------- 31 | This command resets the WSUS client information on Server. 32 | #> 33 | [cmdletbinding( 34 | SupportsShouldProcess=$True 35 | )] 36 | Param ( 37 | [parameter(ValueFromPipeLine=$True,ValueFromPipeLineByPropertyName=$True)] 38 | [Alias('__Server','Server','CN')] 39 | [string[]]$Computername = $Env:Computername 40 | ) 41 | Begin { 42 | $reghive = [microsoft.win32.registryhive]::LocalMachine 43 | } 44 | Process { 45 | ForEach ($Computer in $Computername) { 46 | Write-Verbose ("{0}: Testing network connection" -f $Computer) 47 | If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) { 48 | Write-Verbose ("{0}: Stopping wuauserv service" -f $Computer) 49 | $wuauserv = Get-Service -ComputerName $Computer -Name wuauserv 50 | Stop-Service -InputObject $wuauserv 51 | 52 | Write-Verbose ("{0}: Making remote registry connection to {1} hive" -f $Computer, $reghive) 53 | $remotereg = [microsoft.win32.registrykey]::OpenRemoteBaseKey($reghive,$Computer) 54 | Write-Verbose ("{0}: Connection to WSUS Client registry keys" -f $Computer) 55 | $wsusreg1 = $remotereg.OpenSubKey('Software\Microsoft\Windows\CurrentVersion\WindowsUpdate',$True) 56 | $wsusreg2 = $remotereg.OpenSubKey('Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update',$True) 57 | 58 | #Begin deletion of registry values for WSUS Client 59 | If (-Not [string]::IsNullOrEmpty($wsusreg1.GetValue('SusClientId'))) { 60 | If ($PScmdlet.ShouldProcess("SusClientId","Delete Registry Value")) { 61 | $wsusreg1.DeleteValue('SusClientId') 62 | } 63 | } 64 | If (-Not [string]::IsNullOrEmpty($wsusreg1.GetValue('SusClientIdValidation'))) { 65 | If ($PScmdlet.ShouldProcess("SusClientIdValidation","Delete Registry Value")) { 66 | $wsusreg1.DeleteValue('SusClientIdValidation') 67 | } 68 | } 69 | If (-Not [string]::IsNullOrEmpty($wsusreg1.GetValue('PingID'))) { 70 | If ($PScmdlet.ShouldProcess("PingID","Delete Registry Value")) { 71 | $wsusreg1.DeleteValue('PingID') 72 | } 73 | } 74 | If (-Not [string]::IsNullOrEmpty($wsusreg1.GetValue('AccountDomainSid'))) { 75 | If ($PScmdlet.ShouldProcess("AccountDomainSid","Delete Registry Value")) { 76 | $wsusreg1.DeleteValue('AccountDomainSid') 77 | } 78 | } 79 | If (-Not [string]::IsNullOrEmpty($wsusreg2.GetValue('LastWaitTimeout'))) { 80 | If ($PScmdlet.ShouldProcess("LastWaitTimeout","Delete Registry Value")) { 81 | $wsusreg2.DeleteValue('LastWaitTimeout') 82 | } 83 | } 84 | If (-Not [string]::IsNullOrEmpty($wsusreg2.GetValue('DetectionStartTimeout'))) { 85 | If ($PScmdlet.ShouldProcess("DetectionStartTimeout","Delete Registry Value")) { 86 | $wsusreg2.DeleteValue('DetectionStartTimeout') 87 | } 88 | } 89 | If (-Not [string]::IsNullOrEmpty($wsusreg2.GetValue('NextDetectionTime'))) { 90 | If ($PScmdlet.ShouldProcess("NextDetectionTime","Delete Registry Value")) { 91 | $wsusreg2.DeleteValue('NextDetectionTime') 92 | } 93 | } 94 | If (-Not [string]::IsNullOrEmpty($wsusreg2.GetValue('AUState'))) { 95 | If ($PScmdlet.ShouldProcess("AUState","Delete Registry Value")) { 96 | $wsusreg2.DeleteValue('AUState') 97 | } 98 | } 99 | 100 | Write-Verbose ("{0}: Removing Software Distribution folder and subfolders" -f $Computer) 101 | Try { 102 | Remove-Item "\\$Computer\c$\Windows\SoftwareDistribution" -Recurse -Force -Confirm:$False -ErrorAction Stop 103 | } Catch { 104 | Write-Warning ("{0}: {1}" -f $Computer,$_.Exception.Message) 105 | } 106 | 107 | Write-Verbose ("{0}: Starting wuauserv service" -f $Computer) 108 | Start-Service -InputObject $wuauserv 109 | 110 | Write-Verbose ("{0}: Sending wuauclt /resetauthorization /detectnow command" -f $Computer) 111 | Try { 112 | Invoke-WmiMethod -Path Win32_Process -ComputerName $Computer -Name Create ` 113 | -ArgumentList "wuauclt /resetauthorization /detectnow" -ErrorAction Stop | Out-Null 114 | } Catch { 115 | Write-Warning ("{0}: {1}" -f $Computer,$_.Exception.Message) 116 | } 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Invoke-WSUSDBMaintenance.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-WSUSDBMaintenance { 2 | <# 3 | .SYSNOPSIS 4 | Performs maintenance tasks on the SUSDB database using the WSUS API and T-SQL code. 5 | 6 | .DESCRIPTION 7 | Performs maintenance tasks on the SUSDB database using the WSUS API. 8 | 9 | 1. Identifies indexes that are fragmented and defragments them. For certain 10 | tables, a fill-factor is set in order to improve insert performance. 11 | Based on MSDN sample at http://msdn2.microsoft.com/en-us/library/ms188917.aspx 12 | and tailored for SUSDB requirements 13 | 2. Updates potentially out-of-date table statistics. 14 | 15 | .PARAMETER UpdateServer 16 | Update server to connect to 17 | 18 | .PARAMETER Port 19 | Port to connect to the Update Server. Default port is 80. 20 | 21 | .PARAMETER Secure 22 | Use a secure connection 23 | 24 | .NOTES 25 | Name: Invoke-WSUSDBMaintenance 26 | Author: Boe Prox 27 | DateCreated: 03 Jul 2013 28 | 29 | T-SQL Code used from http://gallery.technet.microsoft.com/scriptcenter/6f8cde49-5c52-4abd-9820-f1d270ddea61 30 | 31 | .EXAMPLE 32 | Invoke-WSUSDBMaintenance -UpdateServer DC1 -Port 80 -Verbose 33 | 34 | VERBOSE: Connecting to DC1 35 | VERBOSE: Connecting to SUSDB on DC1 36 | VERBOSE: Performing operation "Database Maintenance" on Target "SUSDB". 37 | VERBOSE: Completed. 38 | 39 | Description 40 | ----------- 41 | Performs database maintenance on the database for Update Server DC1 on DC1 42 | #> 43 | [cmdletbinding( 44 | SupportsShouldProcess = $True 45 | )] 46 | Param( 47 | [parameter(Mandatory=$True)] 48 | [ValidateScript({ 49 | If (-Not (Get-Module -List -Name UpdateServices)) { 50 | Try { 51 | Add-Type -Path "$Env:ProgramFiles\Update Services\Api\Microsoft.UpdateServices.Administration.dll" 52 | $True 53 | } Catch { 54 | Throw ("Missing the required assemblies to use the WSUS API from {0}" -f "$Env:ProgramFiles\Update Services\Api") 55 | } 56 | } Else {$True} 57 | })] 58 | [string]$UpdateServer, 59 | [parameter()] 60 | [ValidateSet('80','443','8530','8531')] 61 | [int]$Port = 80, 62 | [parameter()] 63 | [switch]$Secure 64 | ) 65 | $tSQL = @" 66 | SET NOCOUNT ON; 67 | 68 | -- Rebuild or reorganize indexes based on their fragmentation levels 69 | DECLARE @work_to_do TABLE ( 70 | objectid int 71 | , indexid int 72 | , pagedensity float 73 | , fragmentation float 74 | , numrows int 75 | ) 76 | 77 | DECLARE @objectid int; 78 | DECLARE @indexid int; 79 | DECLARE @schemaname nvarchar(130); 80 | DECLARE @objectname nvarchar(130); 81 | DECLARE @indexname nvarchar(130); 82 | DECLARE @numrows int 83 | DECLARE @density float; 84 | DECLARE @fragmentation float; 85 | DECLARE @command nvarchar(4000); 86 | DECLARE @fillfactorset bit 87 | DECLARE @numpages int 88 | 89 | -- Select indexes that need to be defragmented based on the following 90 | -- * Page density is low 91 | -- * External fragmentation is high in relation to index size 92 | INSERT @work_to_do 93 | SELECT 94 | f.object_id 95 | , index_id 96 | , avg_page_space_used_in_percent 97 | , avg_fragmentation_in_percent 98 | , record_count 99 | FROM 100 | sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'SAMPLED') AS f 101 | WHERE 102 | (f.avg_page_space_used_in_percent < 85.0 and f.avg_page_space_used_in_percent/100.0 * page_count < page_count - 1) 103 | or (f.page_count > 50 and f.avg_fragmentation_in_percent > 15.0) 104 | or (f.page_count > 10 and f.avg_fragmentation_in_percent > 80.0) 105 | 106 | 107 | SELECT @numpages = sum(ps.used_page_count) 108 | FROM 109 | @work_to_do AS fi 110 | INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 111 | INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 112 | 113 | -- Declare the cursor for the list of indexes to be processed. 114 | DECLARE curIndexes CURSOR FOR SELECT * FROM @work_to_do 115 | 116 | -- Open the cursor. 117 | OPEN curIndexes 118 | 119 | -- Loop through the indexes 120 | WHILE (1=1) 121 | BEGIN 122 | FETCH NEXT FROM curIndexes 123 | INTO @objectid, @indexid, @density, @fragmentation, @numrows; 124 | IF @@FETCH_STATUS < 0 BREAK; 125 | 126 | SELECT 127 | @objectname = QUOTENAME(o.name) 128 | , @schemaname = QUOTENAME(s.name) 129 | FROM 130 | sys.objects AS o 131 | INNER JOIN sys.schemas as s ON s.schema_id = o.schema_id 132 | WHERE 133 | o.object_id = @objectid; 134 | 135 | SELECT 136 | @indexname = QUOTENAME(name) 137 | , @fillfactorset = CASE fill_factor WHEN 0 THEN 0 ELSE 1 END 138 | FROM 139 | sys.indexes 140 | WHERE 141 | object_id = @objectid AND index_id = @indexid; 142 | 143 | IF ((@density BETWEEN 75.0 AND 85.0) AND @fillfactorset = 1) OR (@fragmentation < 30.0) 144 | SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; 145 | ELSE IF @numrows >= 5000 AND @fillfactorset = 0 146 | SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD WITH (FILLFACTOR = 90)'; 147 | ELSE 148 | SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD'; 149 | EXEC (@command); 150 | END 151 | 152 | -- Close and deallocate the cursor. 153 | CLOSE curIndexes; 154 | DEALLOCATE curIndexes; 155 | 156 | IF EXISTS (SELECT * FROM @work_to_do) 157 | BEGIN 158 | SELECT @numpages = @numpages - sum(ps.used_page_count) 159 | FROM 160 | @work_to_do AS fi 161 | INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 162 | INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 163 | END 164 | 165 | --Update all statistics 166 | EXEC sp_updatestats 167 | "@ 168 | Write-Verbose ("Connecting to {0}" -f $UpdateServer) 169 | Try { 170 | If (Get-Module -List -Name UpdateServices) { 171 | $Wsus = Get-WSUSServer -Name $UpdateServer -PortNumber $Port 172 | } Else { 173 | $Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($UpdateServer,$Secure,$Port) 174 | } 175 | $db = $wsus.GetDatabaseConfiguration().CreateConnection() 176 | Write-Verbose ("Connecting to {0} on {1}" -f $db.databasename,$db.servername) 177 | $db.Connect() 178 | If ($PSCmdlet.ShouldProcess($db.Databasename,'Database Maintenance')) { 179 | $db.ExecuteCommandNoResult($tSQL,[System.Data.CommandType]::Text) 180 | $db.CloseCommand() 181 | $db.Close() 182 | } 183 | } Catch { 184 | Write-Warning ("{0}" -f $_.Exception.Message) 185 | } 186 | Write-Verbose "Completed" 187 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Boe Prox 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 | -------------------------------------------------------------------------------- /New-SymLink.ps1: -------------------------------------------------------------------------------- 1 | Function New-SymLink { 2 | <# 3 | .SYNOPSIS 4 | Creates a Symbolic link to a file or directory 5 | 6 | .DESCRIPTION 7 | Creates a Symbolic link to a file or directory as an alternative to mklink.exe 8 | 9 | .PARAMETER Path 10 | Name of the path that you will reference with a symbolic link. 11 | 12 | .PARAMETER SymName 13 | Name of the symbolic link to create. Can be a full path/unc or just the name. 14 | If only a name is given, the symbolic link will be created on the current directory that the 15 | function is being run on. 16 | 17 | .PARAMETER File 18 | Create a file symbolic link 19 | 20 | .PARAMETER Directory 21 | Create a directory symbolic link 22 | 23 | .NOTES 24 | Name: New-SymLink 25 | Author: Boe Prox 26 | Created: 15 Jul 2013 27 | 28 | 29 | .EXAMPLE 30 | New-SymLink -Path "C:\users\admin\downloads" -SymName "C:\users\admin\desktop\downloads" -Directory 31 | 32 | SymLink Target Type 33 | ------- ------ ---- 34 | C:\Users\admin\Desktop\Downloads C:\Users\admin\Downloads Directory 35 | 36 | Description 37 | ----------- 38 | Creates a symbolic link to downloads folder that resides on C:\users\admin\desktop. 39 | 40 | .EXAMPLE 41 | New-SymLink -Path "C:\users\admin\downloads\document.txt" -SymName "SomeDocument" -File 42 | 43 | SymLink Target Type 44 | ------- ------ ---- 45 | C:\users\admin\desktop\SomeDocument C:\users\admin\downloads\document.txt File 46 | 47 | Description 48 | ----------- 49 | Creates a symbolic link to document.txt file under the current directory called SomeDocument. 50 | #> 51 | [cmdletbinding( 52 | DefaultParameterSetName = 'Directory', 53 | SupportsShouldProcess=$True 54 | )] 55 | Param ( 56 | [parameter(Position=0,ParameterSetName='Directory',ValueFromPipeline=$True, 57 | ValueFromPipelineByPropertyName=$True,Mandatory=$True)] 58 | [parameter(Position=0,ParameterSetName='File',ValueFromPipeline=$True, 59 | ValueFromPipelineByPropertyName=$True,Mandatory=$True)] 60 | [ValidateScript({ 61 | If (Test-Path $_) {$True} Else { 62 | Throw "`'$_`' doesn't exist!" 63 | } 64 | })] 65 | [string]$Path, 66 | [parameter(Position=1,ParameterSetName='Directory')] 67 | [parameter(Position=1,ParameterSetName='File')] 68 | [string]$SymName, 69 | [parameter(Position=2,ParameterSetName='File')] 70 | [switch]$File, 71 | [parameter(Position=2,ParameterSetName='Directory')] 72 | [switch]$Directory 73 | ) 74 | Begin { 75 | Try { 76 | $null = [mklink.symlink] 77 | } Catch { 78 | Add-Type @" 79 | using System; 80 | using System.Runtime.InteropServices; 81 | 82 | namespace mklink 83 | { 84 | public class symlink 85 | { 86 | [DllImport("kernel32.dll")] 87 | public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); 88 | } 89 | } 90 | "@ 91 | } 92 | } 93 | Process { 94 | #Assume target Symlink is on current directory if not giving full path or UNC 95 | If ($SymName -notmatch "^(?:[a-z]:\\)|(?:\\\\\w+\\[a-z]\$)") { 96 | $SymName = "{0}\{1}" -f $pwd,$SymName 97 | } 98 | $Flag = @{ 99 | File = 0 100 | Directory = 1 101 | } 102 | If ($PScmdlet.ShouldProcess($Path,'Create Symbolic Link')) { 103 | Try { 104 | $return = [mklink.symlink]::CreateSymbolicLink($SymName,$Path,$Flag[$PScmdlet.ParameterSetName]) 105 | If ($return) { 106 | $object = New-Object PSObject -Property @{ 107 | SymLink = $SymName 108 | Target = $Path 109 | Type = $PScmdlet.ParameterSetName 110 | } 111 | $object.pstypenames.insert(0,'System.File.SymbolicLink') 112 | $object 113 | } Else { 114 | Throw "Unable to create symbolic link!" 115 | } 116 | } Catch { 117 | Write-warning ("{0}: {1}" -f $path,$_.Exception.Message) 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /Out-Voice.ps1: -------------------------------------------------------------------------------- 1 | Function Out-Voice { 2 | <# 3 | .SYNOPSIS 4 | Used to allow PowerShell to speak to you or sends data to a WAV file for later listening. 5 | 6 | .DESCRIPTION 7 | Used to allow PowerShell to speak to you or sends data to a WAV file for later listening. 8 | 9 | .PARAMETER InputObject 10 | Data that will be spoken or sent to a WAV file. 11 | 12 | .PARAMETER Rate 13 | Sets the speaking rate 14 | 15 | .PARAMETER Volume 16 | Sets the output volume 17 | 18 | .PARAMETER ToWavFile 19 | Append output to a Waveform audio format file in a specified format 20 | 21 | .NOTES 22 | Name: Out-Voice 23 | Author: Boe Prox 24 | DateCreated: 12/4/2013 25 | 26 | To Do: 27 | -Support for other installed voices 28 | 29 | .EXAMPLE 30 | "This is a test" | Out-Voice 31 | 32 | Description 33 | ----------- 34 | Speaks the string that was given to the function in the pipeline. 35 | 36 | .EXAMPLE 37 | "Today's date is $((get-date).toshortdatestring())" | Out-Voice 38 | 39 | Description 40 | ----------- 41 | Says todays date 42 | 43 | .EXAMPLE 44 | "Today's date is $((get-date).toshortdatestring())" | Out-Voice -ToWavFile "C:\temp\test.wav" 45 | 46 | Description 47 | ----------- 48 | Says todays date 49 | 50 | #> 51 | 52 | [cmdletbinding( 53 | )] 54 | Param ( 55 | [parameter(ValueFromPipeline='True')] 56 | [string[]]$InputObject, 57 | [parameter()] 58 | [ValidateRange(-10,10)] 59 | [Int]$Rate, 60 | [parameter()] 61 | [ValidateRange(1,100)] 62 | $Volume, 63 | [parameter()] 64 | [string]$ToWavFile 65 | ) 66 | Begin { 67 | $Script:parameter = $PSBoundParameters 68 | Write-Verbose "Listing parameters being used" 69 | $PSBoundParameters.GetEnumerator() | ForEach { 70 | Write-Verbose "$($_)" 71 | } 72 | Write-Verbose "Loading assemblies" 73 | Add-Type -AssemblyName System.speech 74 | Write-Verbose "Creating Speech object" 75 | $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer 76 | Write-Verbose "Setting volume" 77 | If ($PSBoundParameters['Volume']) { 78 | $speak.Volume = $PSBoundParameters['Volume'] 79 | } Else { 80 | Write-Verbose "No volume given, using default: 100" 81 | $speak.Volume = 100 82 | } 83 | Write-Verbose "Setting speech rate" 84 | If ($PSBoundParameters['Rate']) { 85 | $speak.Rate = $PSBoundParameters['Rate'] 86 | } Else { 87 | Write-Verbose "No rate given, using default: -2" 88 | $speak.rate = -2 89 | } 90 | If ($PSBoundParameters['WavFile']) { 91 | Write-Verbose "Saving speech to wavfile: $wavfile" 92 | $speak.SetOutputToWaveFile($wavfile) 93 | } 94 | } 95 | Process { 96 | ForEach ($line in $inputobject) { 97 | Write-Verbose "Speaking: $line" 98 | $Speak.SpeakAsync(($line | Out-String)) | Out-Null 99 | } 100 | } 101 | End { 102 | If ($PSBoundParameters['ToWavFile']) { 103 | Write-Verbose "Performing cleanup" 104 | $speak.dispose() 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell_Scripts 2 | Miscellaneous scripts for things that I have done; more scripts will arrive as I get time to update this repo. 3 | Feel free to help update these scripts. 4 | -------------------------------------------------------------------------------- /Remove-LocalProfile.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Remove-LocalProfile.ps1 -------------------------------------------------------------------------------- /Set-ClientWSUSSetting.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Set-ClientWSUSSetting.ps1 -------------------------------------------------------------------------------- /Set-Owner.ps1: -------------------------------------------------------------------------------- 1 | Function Set-Owner { 2 | <# 3 | .SYNOPSIS 4 | Changes owner of a file or folder to another user or group. 5 | 6 | .DESCRIPTION 7 | Changes owner of a file or folder to another user or group. 8 | 9 | .PARAMETER Path 10 | The folder or file that will have the owner changed. 11 | 12 | .PARAMETER Account 13 | Optional parameter to change owner of a file or folder to specified account. 14 | 15 | Default value is 'Builtin\Administrators' 16 | 17 | .PARAMETER Recurse 18 | Recursively set ownership on subfolders and files beneath given folder. 19 | 20 | .NOTES 21 | Name: Set-Owner 22 | Author: Boe Prox 23 | Version History: 24 | 1.0 - Boe Prox 25 | - Initial Version 26 | 27 | .EXAMPLE 28 | Set-Owner -Path C:\temp\test.txt 29 | 30 | Description 31 | ----------- 32 | Changes the owner of test.txt to Builtin\Administrators 33 | 34 | .EXAMPLE 35 | Set-Owner -Path C:\temp\test.txt -Account 'Domain\bprox 36 | 37 | Description 38 | ----------- 39 | Changes the owner of test.txt to Domain\bprox 40 | 41 | .EXAMPLE 42 | Set-Owner -Path C:\temp -Recurse 43 | 44 | Description 45 | ----------- 46 | Changes the owner of all files and folders under C:\Temp to Builtin\Administrators 47 | 48 | .EXAMPLE 49 | Get-ChildItem C:\Temp | Set-Owner -Recurse -Account 'Domain\bprox' 50 | 51 | Description 52 | ----------- 53 | Changes the owner of all files and folders under C:\Temp to Domain\bprox 54 | #> 55 | [cmdletbinding( 56 | SupportsShouldProcess = $True 57 | )] 58 | Param ( 59 | [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] 60 | [Alias('FullName')] 61 | [string[]]$Path, 62 | [parameter()] 63 | [string]$Account = 'Builtin\Administrators', 64 | [parameter()] 65 | [switch]$Recurse 66 | ) 67 | Begin { 68 | #Prevent Confirmation on each Write-Debug command when using -Debug 69 | If ($PSBoundParameters['Debug']) { 70 | $DebugPreference = 'Continue' 71 | } 72 | Try { 73 | [void][TokenAdjuster] 74 | } Catch { 75 | $AdjustTokenPrivileges = @" 76 | using System; 77 | using System.Runtime.InteropServices; 78 | 79 | public class TokenAdjuster 80 | { 81 | [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 82 | internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, 83 | ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); 84 | [DllImport("kernel32.dll", ExactSpelling = true)] 85 | internal static extern IntPtr GetCurrentProcess(); 86 | [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 87 | internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr 88 | phtok); 89 | [DllImport("advapi32.dll", SetLastError = true)] 90 | internal static extern bool LookupPrivilegeValue(string host, string name, 91 | ref long pluid); 92 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 93 | internal struct TokPriv1Luid 94 | { 95 | public int Count; 96 | public long Luid; 97 | public int Attr; 98 | } 99 | internal const int SE_PRIVILEGE_DISABLED = 0x00000000; 100 | internal const int SE_PRIVILEGE_ENABLED = 0x00000002; 101 | internal const int TOKEN_QUERY = 0x00000008; 102 | internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; 103 | public static bool AddPrivilege(string privilege) 104 | { 105 | try 106 | { 107 | bool retVal; 108 | TokPriv1Luid tp; 109 | IntPtr hproc = GetCurrentProcess(); 110 | IntPtr htok = IntPtr.Zero; 111 | retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); 112 | tp.Count = 1; 113 | tp.Luid = 0; 114 | tp.Attr = SE_PRIVILEGE_ENABLED; 115 | retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); 116 | retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); 117 | return retVal; 118 | } 119 | catch (Exception ex) 120 | { 121 | throw ex; 122 | } 123 | } 124 | public static bool RemovePrivilege(string privilege) 125 | { 126 | try 127 | { 128 | bool retVal; 129 | TokPriv1Luid tp; 130 | IntPtr hproc = GetCurrentProcess(); 131 | IntPtr htok = IntPtr.Zero; 132 | retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); 133 | tp.Count = 1; 134 | tp.Luid = 0; 135 | tp.Attr = SE_PRIVILEGE_DISABLED; 136 | retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); 137 | retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); 138 | return retVal; 139 | } 140 | catch (Exception ex) 141 | { 142 | throw ex; 143 | } 144 | } 145 | } 146 | "@ 147 | Add-Type $AdjustTokenPrivileges 148 | } 149 | 150 | #Activate necessary admin privileges to make changes without NTFS perms 151 | [void][TokenAdjuster]::AddPrivilege("SeRestorePrivilege") #Necessary to set Owner Permissions 152 | [void][TokenAdjuster]::AddPrivilege("SeBackupPrivilege") #Necessary to bypass Traverse Checking 153 | [void][TokenAdjuster]::AddPrivilege("SeTakeOwnershipPrivilege") #Necessary to override FilePermissions 154 | } 155 | Process { 156 | ForEach ($Item in $Path) { 157 | Write-Verbose "FullName: $Item" 158 | #The ACL objects do not like being used more than once, so re-create them on the Process block 159 | $DirOwner = New-Object System.Security.AccessControl.DirectorySecurity 160 | $DirOwner.SetOwner([System.Security.Principal.NTAccount]$Account) 161 | $FileOwner = New-Object System.Security.AccessControl.FileSecurity 162 | $FileOwner.SetOwner([System.Security.Principal.NTAccount]$Account) 163 | $DirAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity 164 | $FileAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity 165 | $AdminACL = New-Object System.Security.AccessControl.FileSystemAccessRule('Builtin\Administrators','FullControl','ContainerInherit,ObjectInherit','InheritOnly','Allow') 166 | $FileAdminAcl.AddAccessRule($AdminACL) 167 | $DirAdminAcl.AddAccessRule($AdminACL) 168 | Try { 169 | $Item = Get-Item -LiteralPath $Item -Force -ErrorAction Stop 170 | If (-NOT $Item.PSIsContainer) { 171 | If ($PSCmdlet.ShouldProcess($Item, 'Set File Owner')) { 172 | Try { 173 | $Item.SetAccessControl($FileOwner) 174 | } Catch { 175 | Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Directory.FullName)" 176 | $Item.Directory.SetAccessControl($FileAdminAcl) 177 | $Item.SetAccessControl($FileOwner) 178 | } 179 | } 180 | } Else { 181 | If ($PSCmdlet.ShouldProcess($Item, 'Set Directory Owner')) { 182 | Try { 183 | $Item.SetAccessControl($DirOwner) 184 | } Catch { 185 | Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Parent.FullName)" 186 | $Item.Parent.SetAccessControl($DirAdminAcl) 187 | $Item.SetAccessControl($DirOwner) 188 | } 189 | } 190 | If ($Recurse) { 191 | [void]$PSBoundParameters.Remove('Path') 192 | Get-ChildItem $Item -Force | Set-Owner @PSBoundParameters 193 | } 194 | } 195 | } Catch { 196 | Write-Warning "$($Item): $($_.Exception.Message)" 197 | } 198 | } 199 | } 200 | End { 201 | #Remove priviledges that had been granted 202 | [void][TokenAdjuster]::RemovePrivilege("SeRestorePrivilege") 203 | [void][TokenAdjuster]::RemovePrivilege("SeBackupPrivilege") 204 | [void][TokenAdjuster]::RemovePrivilege("SeTakeOwnershipPrivilege") 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /Set-Password.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Set-Password.ps1 -------------------------------------------------------------------------------- /Set-Window.ps1: -------------------------------------------------------------------------------- 1 | Function Set-Window { 2 | <# 3 | .SYNOPSIS 4 | Sets the window size (height,width) and coordinates (x,y) of 5 | a process window. 6 | 7 | .DESCRIPTION 8 | Sets the window size (height,width) and coordinates (x,y) of 9 | a process window. 10 | 11 | .PARAMETER ProcessName 12 | Name of the process to determine the window characteristics 13 | 14 | .PARAMETER X 15 | Set the position of the window in pixels from the top. 16 | 17 | .PARAMETER Y 18 | Set the position of the window in pixels from the left. 19 | 20 | .PARAMETER Width 21 | Set the width of the window. 22 | 23 | .PARAMETER Height 24 | Set the height of the window. 25 | 26 | .PARAMETER Passthru 27 | Display the output object of the window. 28 | 29 | .NOTES 30 | Name: Set-Window 31 | Author: Boe Prox 32 | Version History 33 | 1.0//Boe Prox - 11/24/2015 34 | - Initial build 35 | 36 | .OUTPUT 37 | System.Automation.WindowInfo 38 | 39 | .EXAMPLE 40 | Get-Process powershell | Set-Window -X 2040 -Y 142 -Passthru 41 | 42 | ProcessName Size TopLeft BottomRight 43 | ----------- ---- ------- ----------- 44 | powershell 1262,642 2040,142 3302,784 45 | 46 | Description 47 | ----------- 48 | Set the coordinates on the window for the process PowerShell.exe 49 | 50 | #> 51 | [OutputType('System.Automation.WindowInfo')] 52 | [cmdletbinding()] 53 | Param ( 54 | [parameter(ValueFromPipelineByPropertyName=$True)] 55 | $ProcessName, 56 | [int]$X, 57 | [int]$Y, 58 | [int]$Width, 59 | [int]$Height, 60 | [switch]$Passthru 61 | ) 62 | Begin { 63 | Try{ 64 | [void][Window] 65 | } Catch { 66 | Add-Type @" 67 | using System; 68 | using System.Runtime.InteropServices; 69 | public class Window { 70 | [DllImport("user32.dll")] 71 | [return: MarshalAs(UnmanagedType.Bool)] 72 | public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 73 | 74 | [DllImport("User32.dll")] 75 | public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); 76 | } 77 | public struct RECT 78 | { 79 | public int Left; // x position of upper-left corner 80 | public int Top; // y position of upper-left corner 81 | public int Right; // x position of lower-right corner 82 | public int Bottom; // y position of lower-right corner 83 | } 84 | "@ 85 | } 86 | } 87 | Process { 88 | $Rectangle = New-Object RECT 89 | $Handle = (Get-Process -Name $ProcessName).MainWindowHandle 90 | $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) 91 | If (-NOT $PSBoundParameters.ContainsKey('Width')) { 92 | $Width = $Rectangle.Right - $Rectangle.Left 93 | } 94 | If (-NOT $PSBoundParameters.ContainsKey('Height')) { 95 | $Height = $Rectangle.Bottom - $Rectangle.Top 96 | } 97 | If ($Return) { 98 | $Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True) 99 | } 100 | If ($PSBoundParameters.ContainsKey('Passthru')) { 101 | $Rectangle = New-Object RECT 102 | $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) 103 | If ($Return) { 104 | $Height = $Rectangle.Bottom - $Rectangle.Top 105 | $Width = $Rectangle.Right - $Rectangle.Left 106 | $Size = New-Object System.Management.Automation.Host.Size -ArgumentList $Width, $Height 107 | $TopLeft = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Left, $Rectangle.Top 108 | $BottomRight = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Right, $Rectangle.Bottom 109 | If ($Rectangle.Top -lt 0 -AND $Rectangle.LEft -lt 0) { 110 | Write-Warning "Window is minimized! Coordinates will not be accurate." 111 | } 112 | $Object = [pscustomobject]@{ 113 | ProcessName = $ProcessName 114 | Size = $Size 115 | TopLeft = $TopLeft 116 | BottomRight = $BottomRight 117 | } 118 | $Object.PSTypeNames.insert(0,'System.Automation.WindowInfo') 119 | $Object 120 | } 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /Start-CountDownTimer.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Start-CountDownTimer.ps1 -------------------------------------------------------------------------------- /Test-IsAdmin.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proxb/PowerShell_Scripts/65d0ac81cb2f73b51dba318e6ae721bdea0db204/Test-IsAdmin.ps1 -------------------------------------------------------------------------------- /Test-Port-README.md: -------------------------------------------------------------------------------- 1 | # Test-Port 2 | ## SYNOPSIS 3 | Tests port on computer. 4 | 5 | ## SYNTAX 6 | ```powershell 7 | Test-Port [-computer] [-port] [-TCPtimeout ] [-UDPtimeout ] [-TCP] [-UDP] [-LocalIP ] [] 8 | ``` 9 | 10 | ## DESCRIPTION 11 | Performing test(s) if port(s) on remote computer(s) is/are open or not. Test is performed by opening the connection using selected protocol TCP/UDP or both. 12 | 13 | ## PARAMETERS 14 | ### -computer <Array> 15 | Name of server to test port state 16 | ``` 17 | Required? true 18 | Position? 1 19 | Accept pipeline input? true (ByValue) 20 | Accept wildcard characters? false 21 | ``` 22 | 23 | ### -port <Array> 24 | Port to test 25 | ``` 26 | Required? true 27 | Position? 2 28 | Accept pipeline input? false 29 | Accept wildcard characters? false 30 | ``` 31 | 32 | ### -TCPtimeout <Int32> 33 | Sets a timeout for TCP port query. (In milliseconds, Default is 1000) 34 | ``` 35 | Required? false 36 | Position? named 37 | Default value 1000 38 | Accept pipeline input? false 39 | Accept wildcard characters? false 40 | ``` 41 | 42 | ### -UDPtimeout <Int32> 43 | Sets a timeout for UDP port query. (In milliseconds, Default is 1000) 44 | ``` 45 | Required? false 46 | Position? named 47 | Default value 1000 48 | Accept pipeline input? false 49 | Accept wildcard characters? false 50 | ``` 51 | 52 | ### -TCP <SwitchParameter> 53 | Use TCP protocol. If any protocol is not selected than TCP is used. 54 | ``` 55 | Required? false 56 | Position? named 57 | Default value False 58 | Accept pipeline input? false 59 | Accept wildcard characters? false 60 | ``` 61 | 62 | ### -UDP <SwitchParameter> 63 | Use UDP protocol. If any protocol is not selected than TCP is used. 64 | ``` 65 | Required? false 66 | Position? named 67 | Default value False 68 | Accept pipeline input? false 69 | Accept wildcard characters? false 70 | ``` 71 | 72 | ### -LocalIP <IPAddress> 73 | Local IP address used to probe. If not specified any - generally based on a route table - will be used. 74 | ``` 75 | Required? false 76 | Position? named 77 | Accept pipeline input? false 78 | Accept wildcard characters? false 79 | ``` 80 | 81 | ## NOTES 82 | Name: Test-Port.ps1 83 | 84 | Author: Boe Prox 85 | 86 | Updated by: Wojciech Sciesinski, https://www.linkedin.com/in/sciesinskiwojciech 87 | 88 | DateCreated: 18Aug2010 89 | 90 | Version: 20160519a 91 | 92 | 93 | 94 | List of Ports: https://www.iana.org/assignments/port-numbers 95 | 96 | 97 | 98 | To Do: 99 | 100 | - Add capability to run background jobs for each host to shorten the time to scan. 101 | 102 | ## EXAMPLES 103 | ### EXAMPLE 1 104 | ```powershell 105 | PS C:\>Test-Port -computer 'server' -port 80 106 | 107 | Server : server 108 | Port : 3389 109 | TypePort : TCP 110 | Open : True 111 | LocalIP : 0.0.0.0 112 | Notes : 113 | 114 | Checks port 3389 on server 'server' to see if it is listening 115 | ``` 116 | 117 | ### EXAMPLE 2 118 | ```powershell 119 | PS C:\>'server' | Test-Port -port 80 120 | 121 | Server : server 122 | Port : 80 123 | TypePort : TCP 124 | Open : True 125 | LocalIP : 0.0.0.0 126 | Notes : 127 | 128 | Checks port 80 on server 'server' to see if it is listening 129 | ``` 130 | 131 | 132 | ### EXAMPLE 3 133 | ```powershell 134 | PS C:\>Test-Port -computer @("server1","server2") -port 80 135 | 136 | Server : server1 137 | Port : 80 138 | TypePort : TCP 139 | Open : True 140 | LocalIP : 0.0.0.0 141 | Notes : 142 | 143 | Server : server2 144 | Port : 80 145 | TypePort : TCP 146 | Open : False 147 | LocalIP : 0.0.0.0 148 | Notes : Connection to Port Timed Out 149 | 150 | Checks port 80 on server1 and server2 to see if it is listening. 151 | ``` 152 | 153 | 154 | ### EXAMPLE 4 155 | ```powershell 156 | PS C:\>Test-Port -comp dc1 -port 17 -udp -UDPtimeout 10000 157 | 158 | Server : dc1 159 | Port : 17 160 | TypePort : UDP 161 | Open : True 162 | LocalIP : 0.0.0.0 163 | Notes : 164 | 165 | Queries port 17 (qotd) using the UDP protocol and returns whether port is open or not. 166 | ``` 167 | 168 | ### EXAMPLE 5 169 | ```powershell 170 | PS C:\>Test-Port -Computer server3 -Port 53 -UDP -LocalIP 192.168.13.2 171 | 172 | Server : server3 173 | Port : 53 174 | TypePort : UDP 175 | Open : True 176 | LocalIP : 192.168.13.2 177 | Notes : 178 | 179 | 180 | Checks port 53 using the UDP protocol on destination computer with the name server3 using as a source interface with IP address 192.168.13.2 assigned 181 | ``` 182 | 183 | ### EXAMPLE 6 184 | ```powershell 185 | PS C:\>@("server1","server2") | Test-Port -port 80 186 | 187 | Checks port 80 on server1 and server2 to see if it is listening. 188 | ``` 189 | 190 | ### EXAMPLE 7 191 | ```powershell 192 | PS C:\>(Get-Content hosts.txt) | Test-Port -port 80 193 | 194 | Checks port 80 on servers in host file to see if it is listening. 195 | ``` 196 | 197 | ### EXAMPLE 8 198 | ```powershell 199 | PS C:\>Test-Port -computer (Get-Content hosts.txt) -port 80 200 | 201 | Checks port 80 on servers in host file to see if it is listening 202 | ``` 203 | 204 | 205 | ### EXAMPLE 9 206 | ```powershell 207 | PS C:\>Test-Port -computer (Get-Content hosts.txt) -port @(1..59) 208 | 209 | Checks a range of ports from 1-59 on all servers in the hosts.txt file 210 | ``` 211 | -------------------------------------------------------------------------------- /Test-Port.ps1: -------------------------------------------------------------------------------- 1 | function Test-Port { 2 | <# 3 | .SYNOPSIS 4 | Tests port on computer. 5 | 6 | .DESCRIPTION 7 | Performing test(s) if port(s) on remote computer(s) is/are open or not. Test is performed by opening the connection using selected protocol TCP/UDP or both. 8 | 9 | .PARAMETER computer 10 | Name of server to test port state 11 | 12 | .PARAMETER port 13 | Port to test 14 | 15 | .PARAMETER tcp 16 | Use TCP protocol. If any protocol is not selected than TCP is used. 17 | 18 | .PARAMETER udp 19 | Use UDP protocol. If any protocol is not selected than TCP is used. 20 | 21 | .PARAMETER UDPTimeOut 22 | Sets a timeout for UDP port query. (In milliseconds, Default is 1000) 23 | 24 | .PARAMETER TCPTimeOut 25 | Sets a timeout for TCP port query. (In milliseconds, Default is 1000) 26 | 27 | .PARAMETER LocalIP 28 | Local IP address used to probe. If not specified any - generally based on a route table - will be used. 29 | 30 | .NOTES 31 | Name: Test-Port.ps1 32 | Author: Boe Prox 33 | Updated by: Wojciech Sciesinski, https://www.linkedin.com/in/sciesinskiwojciech 34 | DateCreated: 18Aug2010 35 | Version: 20160519a 36 | 37 | List of Ports: https://www.iana.org/assignments/port-numbers 38 | 39 | To Do: 40 | Add capability to run background jobs for each host to shorten the time to scan. 41 | .LINK 42 | https://boeprox.wordpress.org 43 | 44 | .LINK 45 | https://github.com/proxb/PowerShell_Scripts 46 | 47 | .EXAMPLE 48 | Test-Port -computer 'server' -port 80 49 | 50 | Server : server 51 | Port : 3389 52 | TypePort : TCP 53 | Open : True 54 | LocalIP : 0.0.0.0 55 | Notes : 56 | 57 | Checks port 3389 on server 'server' to see if it is listening 58 | 59 | .EXAMPLE 60 | 'server' | Test-Port -port 80 61 | 62 | Server : server 63 | Port : 80 64 | TypePort : TCP 65 | Open : True 66 | LocalIP : 0.0.0.0 67 | Notes : 68 | 69 | Checks port 80 on server 'server' to see if it is listening 70 | 71 | .EXAMPLE 72 | Test-Port -computer @("server1","server2") -port 80 73 | 74 | Server : server1 75 | Port : 80 76 | TypePort : TCP 77 | Open : True 78 | LocalIP : 0.0.0.0 79 | Notes : 80 | 81 | Server : server2 82 | Port : 80 83 | TypePort : TCP 84 | Open : False 85 | LocalIP : 0.0.0.0 86 | Notes : Connection to Port Timed Out 87 | 88 | Checks port 80 on server1 and server2 to see if it is listening. 89 | 90 | .EXAMPLE 91 | Test-Port -comp dc1 -port 17 -udp -UDPtimeout 10000 92 | 93 | Server : dc1 94 | Port : 17 95 | TypePort : UDP 96 | Open : True 97 | LocalIP : 0.0.0.0 98 | Notes : 99 | 100 | Queries port 17 (qotd) using the UDP protocol and returns whether port is open or not. 101 | 102 | .EXAMPLE 103 | Test-Port -Computer server3 -Port 53 -UDP -LocalIP 192.168.13.2 104 | 105 | Server : server3 106 | Port : 53 107 | TypePort : UDP 108 | Open : True 109 | LocalIP : 192.168.13.2 110 | Notes : 111 | 112 | Checks port 53 using the UDP protocol on destination computer with the name server3 using as a source interface with IP address 192.168.13.2 assigned 113 | 114 | .EXAMPLE 115 | @("server1","server2") | Test-Port -port 80 116 | 117 | Checks port 80 on server1 and server2 to see if it is listening. 118 | 119 | .EXAMPLE 120 | (Get-Content hosts.txt) | Test-Port -port 80 121 | 122 | Checks port 80 on servers in host file to see if it is listening. 123 | 124 | .EXAMPLE 125 | Test-Port -computer (Get-Content hosts.txt) -port 80 126 | 127 | Checks port 80 on servers in host file to see if it is listening 128 | 129 | .EXAMPLE 130 | Test-Port -computer (Get-Content hosts.txt) -port @(1..59) 131 | 132 | Checks a range of ports from 1-59 on all servers in the hosts.txt file 133 | 134 | 135 | 136 | #> 137 | [cmdletbinding( 138 | DefaultParameterSetName = '', 139 | ConfirmImpact = 'low' 140 | )] 141 | Param ( 142 | [Parameter( 143 | Mandatory = $True, 144 | Position = 0, 145 | ParameterSetName = '', 146 | ValueFromPipeline = $True)] 147 | [array]$computer, 148 | [Parameter( 149 | Position = 1, 150 | Mandatory = $True, 151 | ParameterSetName = '')] 152 | [ValidateRange(0, 65535)] 153 | [array]$port, 154 | [Parameter( 155 | Mandatory = $False, 156 | ParameterSetName = '')] 157 | [int]$TCPtimeout = 1000, 158 | [Parameter( 159 | Mandatory = $False, 160 | ParameterSetName = '')] 161 | [int]$UDPtimeout = 1000, 162 | [Parameter( 163 | Mandatory = $False, 164 | ParameterSetName = '')] 165 | [switch]$TCP, 166 | [Parameter( 167 | Mandatory = $False, 168 | ParameterSetName = '')] 169 | [switch]$UDP, 170 | [Parameter( 171 | Mandatory = $False, 172 | ParameterSetName = '')] 173 | [ipaddress]$LocalIP 174 | ) 175 | Begin { 176 | If (!$tcp -AND !$udp) { $tcp = $True } 177 | #Typically you never do this, but in this case I felt it was for the benefit of the function 178 | #as any errors will be noted in the output of the report 179 | #$ErrorActionPreference = "SilentlyContinue" 180 | $report = New-Object System.Collections.ArrayList 181 | } 182 | Process { 183 | ForEach ($c in $computer) { 184 | ForEach ($p in $port) { 185 | If ($tcp) { 186 | #Create temporary holder 187 | $temp = "" | Select-Object -Property Server, Port, TypePort, Open, LocalIP, Notes 188 | 189 | #If LocalIP value is provided create IPEndPoint object 190 | # and use it in the constructor Socket constractor 191 | 192 | If ($LocalIP) { 193 | #Create object for connecting to port on computer, provided local IP is used as source 194 | $EndPoint = New-Object System.Net.IPEndPoint ($LocalIP, 0) 195 | Try { 196 | $tcpobject = new-Object Net.Sockets.TcpClient $EndPoint -ErrorAction Continue 197 | } 198 | Catch { 199 | [String]$MessageText = "Network address {0} is not available on the local computer." -f $LocalIP 200 | Throw $MessageText 201 | } 202 | $tempLocalIP = $LocalIP 203 | 204 | #If LocalIP value is not provide use any local IP 205 | } 206 | Else { 207 | #Create object for connecting to port on computer 208 | $tcpobject = new-Object system.Net.Sockets.TcpClient 209 | [ipaddress]$tempLocalIP = "0.0.0.0" 210 | } 211 | 212 | #Connect to remote machine's port 213 | $connect = $tcpobject.BeginConnect($c, $p, $null, $null) 214 | 215 | $connec.s 216 | 217 | #Configure a timeout before quitting 218 | $wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout, $false) 219 | #If timeout 220 | If (!$wait) { 221 | #Close connection 222 | $tcpobject.Close() 223 | Write-Verbose "Connection Timeout" 224 | #Build report 225 | $temp.Server = $c 226 | $temp.Port = $p 227 | $temp.TypePort = "TCP" 228 | $temp.Open = $False 229 | $temp.LocalIP = $tempLocalIP 230 | $temp.Notes = "Connection to Port Timed Out" 231 | } 232 | Else { 233 | $error.Clear() 234 | $tcpobject.EndConnect($connect) | out-Null 235 | #If error 236 | If ($error[0]) { 237 | #Begin making error more readable in report 238 | [string]$string = ($error[0].exception).message 239 | $message = (($string.split(":")[1]).replace('"', "")).TrimStart() 240 | $failed = $true 241 | } 242 | #Close connection 243 | $tcpobject.Close() 244 | #If unable to query port to due failure 245 | If ($failed) { 246 | #Build report 247 | $temp.Server = $c 248 | $temp.Port = $p 249 | $temp.TypePort = "TCP" 250 | $temp.Open = $False 251 | $temp.LocalIP = $tempLocalIP 252 | $temp.Notes = "$message" 253 | } 254 | Else { 255 | #Build report 256 | $temp.Server = $c 257 | $temp.Port = $p 258 | $temp.TypePort = "TCP" 259 | $temp.Open = $True 260 | $temp.LocalIP = $tempLocalIP 261 | $temp.Notes = "" 262 | } 263 | } 264 | #Reset failed value 265 | $failed = $Null 266 | #Merge temp array with report 267 | $report.add($temp) | Out-Null 268 | } 269 | If ($udp) { 270 | #Create temporary holder 271 | $temp = "" | Select-Object -Property Server, Port, TypePort, Open, LocalIP, Notes 272 | 273 | #If LocalIP value is provided create IPEndPoint object 274 | # and use it in the constructor Socket constractor 275 | If ($LocalIP) { 276 | #Create object for connecting to port on computer, provided local IP is used as source 277 | $EndPoint = New-Object System.Net.IPEndPoint ($LocalIP, 0) 278 | Try { 279 | $udpobject = new-Object Net.Sockets.Udpclient $EndPoint -ErrorAction Continue 280 | } 281 | Catch { 282 | [String]$MessageText = "Network address {0} is not available on the local computer." -f $LocalIP 283 | Throw $MessageText 284 | } 285 | 286 | $tempLocalIP = $LocalIP 287 | #If LocalIP value is not provide use any local IP 288 | } 289 | Else { 290 | #Create object for connecting to port on computer, any local IP is used 291 | $udpobject = new-Object system.Net.Sockets.Udpclient 292 | [ipaddress]$tempLocalIP = "0.0.0.0" 293 | } 294 | 295 | #Set a timeout on receiving message 296 | $udpobject.client.ReceiveTimeout = $UDPTimeout 297 | 298 | #Connect to remote machine's port 299 | Write-Verbose "Making UDP connection to remote server" 300 | $udpobject.Connect("$c", $p) 301 | #Sends a message to the host to which you have connected. 302 | Write-Verbose "Sending message to remote host" 303 | $a = new-object system.text.asciiencoding 304 | $byte = $a.GetBytes("$(Get-Date)") 305 | [void]$udpobject.Send($byte, $byte.length) 306 | #IPEndPoint object will allow us to read datagrams sent from any source. 307 | Write-Verbose "Creating remote endpoint" 308 | $remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any, 0) 309 | Try { 310 | #Blocks until a message returns on this socket from a remote host. 311 | Write-Verbose "Waiting for message return" 312 | $receivebytes = $udpobject.Receive([ref]$remoteendpoint) 313 | [string]$returndata = $a.GetString($receivebytes) 314 | If ($returndata) { 315 | Write-Verbose "Connection Successful" 316 | #Build report 317 | $temp.Server = $c 318 | $temp.Port = $p 319 | $temp.TypePort = "UDP" 320 | $temp.Open = $True 321 | $temp.LocalIP = $tempLocalIP 322 | $temp.Notes = $returndata 323 | $udpobject.close() 324 | } 325 | } 326 | Catch { 327 | If ($Error[0].ToString() -match "\bRespond after a period of time\b") { 328 | #Close connection 329 | $udpobject.Close() 330 | #Make sure that the host is online and not a false positive that it is open 331 | If (Test-Connection -comp $c -count 1 -quiet) { 332 | Write-Verbose "Connection Open" 333 | #Build report 334 | $temp.Server = $c 335 | $temp.Port = $p 336 | $temp.TypePort = "UDP" 337 | $temp.Open = $True 338 | $temp.LocalIP = $tempLocalIP 339 | $temp.Notes = "" 340 | } 341 | Else { 342 | <# 343 | It is possible that the host is not online or that the host is online, 344 | but ICMP is blocked by a firewall and this port is actually open. 345 | #> 346 | Write-Verbose "Host maybe unavailable" 347 | #Build report 348 | $temp.Server = $c 349 | $temp.Port = $p 350 | $temp.TypePort = "UDP" 351 | $temp.Open = $False 352 | $temp.LocalIP = $tempLocalIP 353 | $temp.Notes = "Unable to verify if port is open or if host is unavailable." 354 | } 355 | } 356 | ElseIf ($Error[0].ToString() -match "forcibly closed by the remote host") { 357 | #Close connection 358 | $udpobject.Close() 359 | Write-Verbose "Connection Timeout" 360 | #Build report 361 | $temp.Server = $c 362 | $temp.Port = $p 363 | $temp.TypePort = "UDP" 364 | $temp.Open = $False 365 | $temp.LocalIP = $tempLocalIP 366 | $temp.Notes = "Connection to Port Timed Out" 367 | } 368 | Else { 369 | $udpobject.close() 370 | } 371 | } 372 | #Merge temp array with report 373 | $report.add($temp) | out-null 374 | } 375 | } 376 | } 377 | } 378 | End { 379 | #Generate Report 380 | Return $report 381 | } 382 | } 383 | --------------------------------------------------------------------------------