├── donate.png ├── Fun Stuff ├── Cowbell.wav └── Get-MoreCowbell.ps1 ├── SQL ├── BackupAllDB │ ├── backup.bat │ └── sp.sql ├── UsefulQueries │ ├── wait stats.sql │ ├── running queries.sql │ ├── target memory.sql │ ├── running tasks.sql │ └── missing indexes.sql └── Invoke-SqlDatabaseBackupToFile.ps1 ├── APIs ├── IPSwitchMOVEit │ ├── IpSwitchMOVEit.psd1 │ └── Prerequisites.ps1 └── PostMessageToCampfire.ps1 ├── Exchange ├── SetSignatures │ ├── clm1.txt │ ├── signatures_data.csv │ ├── clm1.html │ └── create_signatures.ps1 ├── Get-MailboxesSizes.ps1 ├── DeleteDisabledMailboxes.ps1 └── Get-AllRules-Forwarding.ps1 ├── Sharepoint └── Order Sync │ ├── bin │ └── pdftotext.exe │ ├── dellwebsite_cred.xml │ ├── .gitignore │ └── sa_automationcred.xml ├── ActiveDirectory ├── Add user to local group.ps1 ├── Remove-Disabled-Ad-Computers.ps1 ├── GetPasswordResetCountXDaysOld.ps1 ├── Get-LoginLogoutHistory.ps1 ├── SetAllEmails.ps1 ├── Check-HomeDriveConsistency │ └── config.xml ├── Bulk-AD-User-Creation.ps1 ├── Get-ClientsUnderNoSite.ps1 ├── Get-LastLoginTimeForComputersAndUsers.ps1 ├── GetAdUsersWithPasswordLastSetOlderThan.ps1 ├── Get-EmptyGroup.ps1 ├── Get-UnlinkedGpo.ps1 ├── Get-Inactive-GPOs.ps1 ├── Get-All-Docs-Password-Age.ps1 ├── Get-DisabledGpo.ps1 ├── Get-GPO-Reg-Settings.ps1 ├── Get-Empty-OUs.ps1 ├── Get-LoggedOnUser.ps1 ├── Copy-AD-User-Account.ps1 ├── Get-GPOs-Linked-To-Empty-OUs.ps1 ├── Get-Inactive-GPO-Settings.ps1 ├── Get-Old-Computer-Accounts.ps1 ├── TestSiteReplicationMod.ps1 ├── Get-AdDnsRecordAcl.ps1 ├── PasswordExpirations │ └── DebugExpirations.ps1 ├── Get-Gpo-Setting.ps1 └── FindUnusedUserAccounts.ps1 ├── Random Stuff ├── New-Invoice │ ├── NReco.PdfGenerator.dll │ ├── InvoiceTemplate.xml │ └── TempXml.xml ├── ReMap All Network Drives.ps1 ├── Confirm-Choice.ps1 ├── Show-BalloonTip.ps1 ├── Get-Weather.ps1 ├── Invoke-WindowsDiskCleanup.ps1 ├── New-Employee.ps1 └── ScriptSharing.psm1 ├── Article Examples ├── Firewall Rules from text file.xlsx └── TIP-SimpleFileSync.ps1 ├── Security ├── NTFSPermissionMigration │ ├── NTFSPermissionMigration.psd1 │ └── NTFSPermissionMigration.Tests.ps1 ├── DownloadQualysPatches.ps1 └── EFS.ps1 ├── Networking ├── Send-PingAsync.ps1 ├── connect-vpn.ps1 ├── Get-ServiceListeningPort.ps1 └── Test-NetworkPort.ps1 ├── Local Account Management ├── Add-UserToLocalGroup.ps1 └── Get-LocalGroupMembership.ps1 ├── DSC ├── SQLServer │ ├── ConfigurationData.psd1 │ └── SQLServerStandalone.ps1 ├── SetPullModeOnServerNode.ps1 └── SetupDscPullServer.ps1 ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── .gitattributes ├── Hyper-V ├── Get-HyperVUptime.ps1 ├── Checkpoint-OnlineVM.ps1 ├── Get-VMError.ps1 ├── Remove-OnlineVM.ps1 └── Install-VMIntegrationServices.ps1 ├── PowerShell Internals ├── ConvertTo-CleanScript.ps1 ├── Show-SimpleMenu.ps1 ├── Write-Params.ps1 ├── Get-FunctionDefaultParameter.ps1 ├── Get-UserCredential.ps1 ├── Get-WeekDay.ps1 ├── PSRemoting.psm1 ├── Get-WeekdayFrom.ps1 ├── Enable-RemotePSRemoting.ps1 └── Wait-Action.ps1 ├── File-Folder Management ├── Invoke-WindowsDiskCleanup2.ps1 ├── Remove-FileOlderThan.ps1 └── Compare-Folder.ps1 ├── Inventorying-Reporting Tools ├── Get-ServerUptimeReport1.ps1 ├── Get-UpTime.ps1 ├── Get-ServerUptimeReport.ps1 └── Get-FreeHardDriveSpace.ps1 ├── Print Management └── SetPrinterComments.ps1 ├── Windows ├── backup_bitlocker_key.ps1 └── RemoveEdgeDefaultForPDF.ps1 ├── README.md ├── SCOMMonitors ├── WindowsProcessExists.ps1 └── FileCountInDirectory.ps1 ├── .gitignore ├── DNS ├── Enable-DynamicDnsRegistration.ps1 ├── Test-DnsNameResolution.ps1 ├── Wait-DnsNameResolution.ps1 ├── Convert-DynamicDnsRecordToStatic.ps1 └── Get-ADDnsRecordACL.ps1 ├── Azure ├── New-AzureWebAppVirtualDirectory.ps1 ├── Get-AzrAvailableLun.ps1 ├── Save-AzrWebApp.ps1 ├── Set-Get-AzrDnsServerAddress.ps1 ├── New-AzureNanoServer.ps1 └── ConvertTo-AzureSize.ps1 ├── Windows Update ├── Reset windows updates.bat ├── Install .NET 3.5 removing WSUS.bat └── Disable wsus and reset WU.bat ├── Troubleshooting Tools └── Find-TroubleshootingEvent.ps1 ├── Text Files └── ValidateXml.ps1 ├── VMware ├── Remove-OnlineVM.ps1 └── Backup-VM.ps1 ├── SCCM ├── Start-CMApplicationDeploymentTest.ps1 └── Connect-CmRemoteTools.ps1 ├── AWS ├── EC2 │ └── Get-InstanceMetadata.ps1 └── Elastic Beanstalk │ └── New-AwsBeanstalkApp.ps1 ├── Certificates └── changes.md ├── Scheduled Tasks └── Get-MyScheduledTask.ps1 ├── DHCP ├── Get-DhcpLeasesInDomain.ps1 ├── Get-DhcpLease.ps1 └── Get-DhcpLease.Tests.ps1 ├── java └── cleanup.ps1 ├── Software ├── Install-Software.ps1 └── Get-MSIDatabaseProperties.ps1 ├── RDP └── Set-RdpSessionTimeout.ps1 ├── User Profiles ├── Get-UserProfilePath.ps1 └── Invoke-UserLogoff.ps1 ├── Group Policy └── User Logon Scripts │ └── Set-WinProfilePhotoFromAD.ps1 ├── TFS ├── TFSClientFunctions.ps1 └── New-TfsBuildTask.ps1 ├── Configuration Mangaement └── Set-ServiceAccount.ps1 ├── IIS └── New-IISWebBinding.ps1 ├── MDT └── Install-Drivers.ps1 ├── Desktop ├── New-ScreenShot.ps1 └── Remove-Win10-Apps.ps1 ├── Chef └── ConfigFileModFunctions.ps1 ├── Database-Datasets └── GoogleSheets │ └── roughcode.ps1 ├── Software Updates └── Get-MissingUpdatesViaMbsa.ps1 ├── mini-course ├── Get-ServerInformation.ps1 └── Get-ServerInformation2.0.ps1 ├── WMI-CIM └── Get-MyCimInstance.ps1 └── Processes ├── Invoke-Program.ps1 └── Invoke-Process.ps1 /donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/donate.png -------------------------------------------------------------------------------- /Fun Stuff/Cowbell.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Fun Stuff/Cowbell.wav -------------------------------------------------------------------------------- /SQL/BackupAllDB/backup.bat: -------------------------------------------------------------------------------- 1 | SqlCmd -E -S (local) -Q "EXEC dbo.usp_backup 'C:\Microsoft SQL Server\Backup\', 7" 2 | -------------------------------------------------------------------------------- /SQL/UsefulQueries/wait stats.sql: -------------------------------------------------------------------------------- 1 | 2 | SELECT * 3 | FROM sys.dm_os_wait_stats dows 4 | ORDER BY dows.wait_time_ms DESC; 5 | -------------------------------------------------------------------------------- /APIs/IPSwitchMOVEit/IpSwitchMOVEit.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/APIs/IPSwitchMOVEit/IpSwitchMOVEit.psd1 -------------------------------------------------------------------------------- /Exchange/SetSignatures/clm1.txt: -------------------------------------------------------------------------------- 1 | _________________________________________ 2 | %%NAME%% 3 | %%ROLE%% 4 | E-mail: %%MAIL%% %%TEL%% %%CELL%% %%SKYPE%% -------------------------------------------------------------------------------- /Sharepoint/Order Sync/bin/pdftotext.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Sharepoint/Order Sync/bin/pdftotext.exe -------------------------------------------------------------------------------- /Sharepoint/Order Sync/dellwebsite_cred.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Sharepoint/Order Sync/dellwebsite_cred.xml -------------------------------------------------------------------------------- /ActiveDirectory/Add user to local group.ps1: -------------------------------------------------------------------------------- 1 | $de = [ADSI]"WinNT://a-xp-2/administrators,group" 2 | $de.psbase.Invoke("Add",([ADSI]"WinNT://apollo/support").path) -------------------------------------------------------------------------------- /Random Stuff/New-Invoice/NReco.PdfGenerator.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Random Stuff/New-Invoice/NReco.PdfGenerator.dll -------------------------------------------------------------------------------- /Article Examples/Firewall Rules from text file.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Article Examples/Firewall Rules from text file.xlsx -------------------------------------------------------------------------------- /Exchange/SetSignatures/signatures_data.csv: -------------------------------------------------------------------------------- 1 | TEMPLATE,USER,NAME,ROLE,MAIL,TEL,CELL,SKYPE 2 | clm1,mrossi,Mario Rossi,Ufficio Vendite,mrossi@coso.it,555-1234165,0101010,skypeid -------------------------------------------------------------------------------- /Sharepoint/Order Sync/.gitignore: -------------------------------------------------------------------------------- 1 | ActivityLog.log 2 | 3 | *.TempPoint.ps1 4 | 5 | sample/*.txt 6 | 7 | Geheimhoudingverklaring leveranciers engels copy.pdf 8 | 9 | *.txt 10 | -------------------------------------------------------------------------------- /Security/NTFSPermissionMigration/NTFSPermissionMigration.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreaci/Random-PowerShell-Work/HEAD/Security/NTFSPermissionMigration/NTFSPermissionMigration.psd1 -------------------------------------------------------------------------------- /APIs/IPSwitchMOVEit/Prerequisites.ps1: -------------------------------------------------------------------------------- 1 | if ([Environment]::Is64BitProcess) 2 | { 3 | throw 'This module is not supported in a x64 PowerShell session. Please load this module into a x86 PowerShell session.' 4 | } -------------------------------------------------------------------------------- /Networking/Send-PingAsync.ps1: -------------------------------------------------------------------------------- 1 | $ips = '192.168.1.5','192.1..4444' 2 | $t = $ips | foreach { 3 | (New-Object Net.NetworkInformation.Ping).SendPingAsync($_, 250) 4 | } 5 | [Threading.Tasks.Task]::WaitAll($t) 6 | $t.Result -------------------------------------------------------------------------------- /Local Account Management/Add-UserToLocalGroup.ps1: -------------------------------------------------------------------------------- 1 | param ([string]$Computername,[string]$GroupName,[string]$Username) 2 | $group = [ADSI]"WinNT://$Computername/$GroupName,group" 3 | $group.Add("WinNT://$Computername/$Username,user") -------------------------------------------------------------------------------- /Local Account Management/Get-LocalGroupMembership.ps1: -------------------------------------------------------------------------------- 1 | param($Computername,$Group) 2 | $group = [ADSI]"WinNT://$Computername/$Group" 3 | @($group.Invoke("Members")) | 4 | 5 | foreach { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } -------------------------------------------------------------------------------- /SQL/UsefulQueries/running queries.sql: -------------------------------------------------------------------------------- 1 | SELECT sqltext.TEXT, 2 | req.session_id, 3 | req.status, 4 | req.command, 5 | req.cpu_time, 6 | req.total_elapsed_time 7 | FROM sys.dm_exec_requests req 8 | CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext -------------------------------------------------------------------------------- /DSC/SQLServer/ConfigurationData.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | AllNodes = @( 3 | @{ 4 | NodeName = '*' 5 | PSDscAllowPlainTextPassword = $true 6 | }, 7 | @{ 8 | NodeName = 'localhost' 9 | } 10 | ) 11 | } -------------------------------------------------------------------------------- /ActiveDirectory/Remove-Disabled-Ad-Computers.ps1: -------------------------------------------------------------------------------- 1 | $aDisabledAdComputers = Get-ADComputer -Filter * | Where-Object { $_.Enabled -eq $false }; 2 | foreach ($oAccount in $aDisabledAdComputers) { 3 | Remove-ADObject -Identity $oAccount -Confirm:$false -Recursive; 4 | }##endforeach -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # . 2 | 3 | Changes proposed in this pull request: 4 | - 5 | - 6 | - 7 | 8 | How to test this code: 9 | - 10 | - 11 | - 12 | 13 | Has been tested on (remove any that don't apply): 14 | - Powershell 3 and above 15 | - Windows 7 and above 16 | -------------------------------------------------------------------------------- /SQL/UsefulQueries/target memory.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | sqlserver_start_time, 3 | (committed_kb/1024) AS Total_Server_Memory_MB, 4 | (committed_target_kb/1024) AS Target_Server_Memory_MB 5 | FROM sys.dm_os_sys_info; 6 | 7 | SELECT * 8 | FROM sys.dm_os_wait_stats dows 9 | ORDER BY dows.wait_time_ms DESC; 10 | -------------------------------------------------------------------------------- /ActiveDirectory/GetPasswordResetCountXDaysOld.ps1: -------------------------------------------------------------------------------- 1 | param($days_old) 2 | 3 | (get-aduser -filter {enabled -eq $true} -Properties passwordlastset,employeenumber,whencreated | ? {($_.passwordlastset -gt (Get-Date).AddDays(-$days_old)) -and ($_.employeenumber) -and ($_.whenCreated -lt (Get-Date).AddDays(-$days_old))}).Count -------------------------------------------------------------------------------- /Exchange/Get-MailboxesSizes.ps1: -------------------------------------------------------------------------------- 1 | Get-MailboxStatistics | where {$_.ObjectClass –eq “Mailbox”} | Sort-Object TotalItemSize –Descending | ft @{label=”User”;expression={$_.DisplayName}},@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}},@{label=”Items”;expression={$_.ItemCount}},@{label=”Storage Limit”;expression={$_.StorageLimitStatus}} -auto 2 | -------------------------------------------------------------------------------- /Exchange/DeleteDisabledMailboxes.ps1: -------------------------------------------------------------------------------- 1 | 2 | $disabledmailboxes = @() 3 | $disabledmailboxes = Get-MailboxStatistics -Database | where {$_.DisconnectReason -eq "Disabled"} 4 | 5 | foreach ($mailbox in $disabledmailboxes) { 6 | #define variables 7 | $strIdentity = $mailbox.DisplayName 8 | $strDatabase = $mailbox.database 9 | 10 | Remove-StoreMailbox -Database $strDatabase -Identity $strIdentity -MailboxState Disabled} -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Do you want to request a *feature* or report a *bug*?** 2 | 3 | **What is the current behavior?** 4 | 5 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** 6 | 7 | **What is the expected behavior?** 8 | 9 | **Which versions of Powershell and which OS are affected by this issue? Did this work in previous versions of our scripts?** 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Exchange/SetSignatures/clm1.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | _________________________________________
4 | 5 | %%NAME%%
6 | %%ROLE%%
7 | E-mail: %%MAIL%% 8 | %%TEL%% 9 | %%CELL%% 10 | %%SKYPE%% 11 |

12 | 13 |
-------------------------------------------------------------------------------- /Sharepoint/Order Sync/sa_automationcred.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | System.Management.Automation.PSCredential 5 | System.Object 6 | 7 | System.Management.Automation.PSCredential 8 | 9 | someuser@domain.local 10 | somepassword 11 | 12 | 13 | -------------------------------------------------------------------------------- /ActiveDirectory/Get-LoginLogoutHistory.ps1: -------------------------------------------------------------------------------- 1 | cls 2 | $Usr = 'xxxxxxxxx' 3 | 4 | Get-ADDomainController -fi * | select -exp hostname | % { 5 | Write-Host $_ 6 | 7 | $ParamsEvn = @{ 8 | ‘Computername’ = $_ 9 | ‘LogName’ = ‘Security’ 10 | ‘FilterXPath’ = "*[EventData[Data[@Name='TargetUserName']='$Usr']]" 11 | } 12 | 13 | $temp = Get-WinEvent @ParamsEvn 14 | $Evnts = $Evnts + $temp 15 | } 16 | 17 | $Evnts | Sort-Object -Descending -Property TimeCreated | foreach {$_} -------------------------------------------------------------------------------- /ActiveDirectory/SetAllEmails.ps1: -------------------------------------------------------------------------------- 1 | $domain = "@coso.it" 2 | $group = "NominalUsers" 3 | 4 | $groupDN = Get-ADGroup $group | Select-Object -ExpandProperty DistinguishedName 5 | $users = Get-ADUser -Filter {Memberof -eq $groupDN} -Properties samAccountName, EmailAddress | select samAccountName, EmailAddress 6 | 7 | foreach($user in $users){ 8 | set-aduser -Identity "$($user.samAccountName)" -EmailAddress "$($user.samAccountName)$($domain)" 9 | echo "FOR USER: $($user.samAccountName) >>> $($user.samAccountName)$($domain)" 10 | } -------------------------------------------------------------------------------- /Hyper-V/Get-HyperVUptime.ps1: -------------------------------------------------------------------------------- 1 | $hyperVHost = 'HYPERVSRV' 2 | $vmUptimes = Get-VM -ComputerName $hyperVHost | select name, uptime, @{ n = 'Type'; e= { 'VM' } } 3 | 4 | $wmiParams = @{ 5 | 'ComputerName' = $hyperVHost 6 | 'Class' = 'Win32_OperatingSystem' 7 | } 8 | $hostUptime = Get-WmiObject @wmiParams | select @{ n = 'Uptime'; e = { (Get-Date) - ($_.ConvertToDateTime($_.LastBootUpTime)) } }, 9 | @{ n = 'Name'; e = { $_.PSComputerName } }, 10 | @{ n = 'Type'; e = { 'Host' } } 11 | 12 | ($vmUptimes + $hostUptime) -------------------------------------------------------------------------------- /Random Stuff/New-Invoice/InvoiceTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Adam Bertram 5 | 555 Address Ln 6 | MyCity, CA 7 | 55555 8 | myemail@gmail.com 9 | 555-444-3333 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /APIs/PostMessageToCampfire.ps1: -------------------------------------------------------------------------------- 1 | $RoomNumber = '407559' 2 | $postUrl = "https://adambertram.campfirenow.com/room/$RoomNumber/speak.json" 3 | $body = 'test message' 4 | $token = '25f1733faf39d63ac8a860430fc18448df179b28' 5 | 6 | $message = 'TextMessage'+$body+'' 7 | $baseuri = $base_url + '/speak.xml' 8 | $contentType = 'application/xml' 9 | $headers = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($token+": x"))} 10 | Invoke-WebRequest -Uri $postUrl -Headers $headers -Method Post -body $message -contenttype 'application/xml' -------------------------------------------------------------------------------- /ActiveDirectory/Check-HomeDriveConsistency/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | \\server\homedrives$\ 4 | 5 | H: 6 | CN=Home Drive,OU=Groups,DC=ad,DC=contoso,DC=com 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /PowerShell Internals/ConvertTo-CleanScript.ps1: -------------------------------------------------------------------------------- 1 | function ConvertTo-CleanScript 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [string]$Path, 9 | 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [string[]]$ToRemove = '' 13 | ) 14 | begin { 15 | $ErrorActionPreference = 'Stop' 16 | } 17 | process { 18 | try 19 | { 20 | $Ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$null, [ref]$null) 21 | 22 | 23 | } 24 | catch 25 | { 26 | Write-Error $_.Exception.Message 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /File-Folder Management/Invoke-WindowsDiskCleanup2.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.0 5 | 6 | .GUID 0ef579e1-d89d-4e8a-9b9a-f07ab5af1084 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | .PRIVATEDATA 32 | 33 | #> 34 | 35 | <# 36 | 37 | .DESCRIPTION 38 | A PowerShell wrapper script to automate the Windows Disk Cleanup utility. 39 | 40 | #> 41 | Param() 42 | 43 | 44 | -------------------------------------------------------------------------------- /Inventorying-Reporting Tools/Get-ServerUptimeReport1.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.0 5 | 6 | .GUID b918ed36-48fa-4577-b2bf-c4d9225cd095 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | .PRIVATEDATA 32 | 33 | #> 34 | 35 | <# 36 | 37 | .DESCRIPTION 38 | A simple script to determine the true uptime of one or more servers. 39 | 40 | #> 41 | Param() 42 | 43 | 44 | -------------------------------------------------------------------------------- /Random Stuff/ReMap All Network Drives.ps1: -------------------------------------------------------------------------------- 1 | $i=3 2 | while($True){ 3 | $error.clear() 4 | $MappedDrives = Get-SmbMapping |where -property Status -Value Unavailable -EQ | select LocalPath,RemotePath 5 | foreach( $MappedDrive in $MappedDrives) 6 | { 7 | try { 8 | New-SmbMapping -LocalPath $MappedDrive.LocalPath -RemotePath $MappedDrive.RemotePath -Persistent $True 9 | } catch { 10 | Write-Host "There was an error mapping $MappedDrive.RemotePath to $MappedDrive.LocalPath" 11 | } 12 | } 13 | $i = $i - 1 14 | if($error.Count -eq 0 -Or $i -eq 0) {break} 15 | 16 | Start-Sleep -Seconds 30 17 | 18 | } -------------------------------------------------------------------------------- /Print Management/SetPrinterComments.ps1: -------------------------------------------------------------------------------- 1 | ## Based off of a CSV, sets printer comments for a set of printers 2 | 3 | $Csv = Import-Csv "C:\Dropbox\Powershell\scripts\PrinterModelAndIPs.csv" 4 | $server_printers = Get-WMIObject -Class "Win32_Printer" -NameSpace "root\cimv2" -computername ctxps 5 | foreach ($row in $Csv) { 6 | $model = $row.Model; 7 | $ip = $row.IP; 8 | $printer = $server_printers | ? {$_.comment -eq $ip } 9 | if ($printer) { 10 | #$printer | foreach {"Name: $($_.Name) | $($_.PortName) | $ip | $model"} 11 | $printer | foreach { $_.Comment = "$ip $model"; $_.Put() | Out-Null} 12 | 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /Windows/backup_bitlocker_key.ps1: -------------------------------------------------------------------------------- 1 | $drives = Get-PSDrive -PSProvider FileSystem | select @{name="Name"; expression={ $_.Name+":"}} 2 | 3 | foreach ($drive in $drives){ 4 | 5 | #Enable-Bitlocker -MountPoint $drive.Name -EncryptionMehod -UsedSpaceOnly -PasswordProtector -SkipHardwareTest 6 | 7 | $BitVolume = Get-BitLockerVolume -MountPoint $drive.Name 8 | $RecoveryKey = $BitVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } 9 | 10 | Backup-BitLockerKeyProtector -MountPoint $drive.Name -KeyProtectorId $RecoveryKey.KeyProtectorID 11 | BackupToAAD-BitLockerKeyProtector -MountPoint $drive.Name -KeyProtectorId $RecoveryKey.KeyProtectorID 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Random PowerShell Work 2 | 3 | [![Donate](./donate.png)](https://www.paypal.me/adbertram/10) 4 | 5 | > If you get some use out of my scripts, drop me a few bucks. 6 | 7 | This is a conglomeration of PowerShell scripts that I've written over the years. If you'd like more PowerShell awesomeness check out my blog at [Adam, the Automator](http://www.adamtheautomator.com). This is where I write about automation, lots of PowerShell and post regularly about time-saving tricks with PowerShell. 8 | 9 | **WARNING: I cannot guarantee all scripts in this repo have been thoroughly tested or even work at all! These are working scripts that are in all different stages of development. Use at your own risk!** 10 | -------------------------------------------------------------------------------- /PowerShell Internals/Show-SimpleMenu.ps1: -------------------------------------------------------------------------------- 1 | function Show-Menu 2 | { 3 | param ( 4 | [string]$Title = 'My Menu' 5 | ) 6 | Clear-Host 7 | Write-Host "================ $Title ================" 8 | 9 | Write-Host "1: Press '1' for this option." 10 | Write-Host "2: Press '2' for this option." 11 | Write-Host "3: Press '3' for this option." 12 | Write-Host "Q: Press 'Q' to quit." 13 | } 14 | 15 | do 16 | { 17 | Show-Menu 18 | $selection = Read-Host "Please make a selection" 19 | Clear-Host 20 | switch ($selection) 21 | { 22 | '1' { 23 | 'You chose option #1' 24 | } '2' { 25 | 'You chose option #2' 26 | } '3' { 27 | 'You chose option #3' 28 | } 'q' { 29 | return 30 | } 31 | } 32 | pause 33 | } 34 | until ($selection -eq 'q') -------------------------------------------------------------------------------- /SCOMMonitors/WindowsProcessExists.ps1: -------------------------------------------------------------------------------- 1 | param ([string]$ProcessName) 2 | 3 | $API = New-Object -ComObject 'MOM.ScriptAPI' 4 | $PropertyBag = $API.CreatePropertyBag() 5 | 6 | try { 7 | $Process = Get-WmiObject -Class 'Win32_Process' -Filter "Name = '$ProcessName'" 8 | if (!$Process) { 9 | $PropertyBag.AddValue('State', 'Critical') 10 | $PropertyBag.Addvalue('Description', "The process '$ProcessName' is not running.") 11 | } else { 12 | $PropertyBag.AddValue('State', 'Healthy') 13 | $PropertyBag.AddValue('Description', "The process '$ProcessName' is running.") 14 | } 15 | $PropertyBag 16 | } catch { 17 | $PropertyBag.AddValue('State', 'Warning') 18 | $PropertyBag.Addvalue('Description', $_.Exception.Message) 19 | $PropertyBag 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ActiveDirectory/Bulk-AD-User-Creation.ps1: -------------------------------------------------------------------------------- 1 | $aPcs = Get-Content dddd.txt | where 2 | foreach ($oPc in $aPcs) { 3 | $sUser = $oPc.ToLower(); 4 | if ($sUser -eq 'isspare23') { 5 | $sLName = 'spare23' 6 | $sLName = "spare23" 7 | $sDisplayName = "spare23 spare23"; 8 | $sDesc = 'med cart laptop autologin'; 9 | } else { 10 | $sLName = $sUser.substring($sUser.length - 4, 4); 11 | $sLName = "Cart $sLName" 12 | $sDisplayName = "Medication Cart $sLName"; 13 | $sDesc = $sDisplayName; 14 | } 15 | New-AdUser $sUser -Path "" -accountpassword (ConvertTo-SecureString -AsPlainText "password" -Force) -Enabled $true -GivenName 'Medication' -Surname $sLName -DisplayName $sDisplayName -PasswordNeverExpires $true -CannotChangePassword $true -Description $sDesc; 16 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Random Stuff/New-Invoice/TempXml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | February Articles 4 | Adam Bertram 5 | 8616 Elizabeth Ln 6 | Evansville, IN 7 | 47725 8 | adbertram@gmail.com 9 | 812-453-3658 10 | 1105 Media 11 | Chris Paoli 12 | 02242015 13 | 2/24/2015 14 | 15 | 16 | 17 | 18 | 19 | Article 20 | 200 21 | 3 22 | 23 | -------------------------------------------------------------------------------- /ActiveDirectory/Get-ClientsUnderNoSite.ps1: -------------------------------------------------------------------------------- 1 | function Get-ClientsUnderNoSite 2 | { 3 | [CmdletBinding()] 4 | param () 5 | try 6 | { 7 | ## Find all DCs in the forest 8 | $dcs = ((Get-ADForest).Domains | foreach { (Get-ADDomainController -Server $_ -Filter *) }).HostName 9 | foreach ($d in $dcs) 10 | { 11 | $output = @{'DomainController' = $d} 12 | 13 | $clients = Select-String -Pattern 'NO_CLIENT_SITE: (.*) \d' -Path "\\$d\c$\windows\debug\netlogon.log" | foreach { 14 | $_.Matches.Groups[1].Value 15 | } | Group-Object 16 | if ($clients) 17 | { 18 | $clients | foreach { 19 | $output.Client = $_.Name 20 | [pscustomobject]$output 21 | } 22 | } 23 | } 24 | 25 | } 26 | catch 27 | { 28 | Write-Error -Message $_.Exception.Message 29 | } 30 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-LastLoginTimeForComputersAndUsers.ps1: -------------------------------------------------------------------------------- 1 | $comps =Get-ADComputer -Filter * -Properties lastlogondate,operatingsystem,OperatingSystemVersion,enabled,description | select @{Name="Type"; Expression={"COMPUTER"}}, @{Name="SamAccountName"; Expression=name},name,description, enabled,operatingsystem,OperatingSystemVersion,lastlogondate 2 | $users =Get-ADuser -Filter * -Properties LastLogonTimeStamp, enabled,description | select @{Name="Type"; Expression={"USER" }}, SamAccountName ,Name,description, enabled,@{Name="operatingsystem"; Expression={"-"}} ,@{Name="OperatingSystemVersion"; Expression={"-"}},@{Name="lastlogondate"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}} 3 | 4 | $comps+$users | FT 5 | 6 | -------------------------------------------------------------------------------- /DSC/SetPullModeOnServerNode.ps1: -------------------------------------------------------------------------------- 1 | Configuration PullMode { 2 | param ( 3 | [string]$Computername, 4 | [string]$Guid 5 | ) 6 | Node $Computername { 7 | LocalConfigurationManager { 8 | ConfigurationMode = 'ApplyOnly' 9 | ConfigurationID = $Guid 10 | RefreshMode = 'Pull' 11 | DownloadManagerName = 'WebDownloadManager’ 12 | DownloadManagerCustomData = @{ 13 | ServerUrl = 'http://LABDC.LAB.LOCAL:8080/PSDSCPullServer.svc' 14 | AllowUnsecureConnection = 'true' 15 | } 16 | } 17 | } 18 | } 19 | 20 | PullMode -Computername 'LABDC2.LAB2.LAB.LOCAL' –Guid 'f91e9587-8013-4714-99d5-8e4ffb2dc23f' 21 | Set-DSCLocalConfigurationManager –Computer 'LABDC2.LAB2.LAB.LOCAL' -Path ./PullMode -Verbose -------------------------------------------------------------------------------- /Security/NTFSPermissionMigration/NTFSPermissionMigration.Tests.ps1: -------------------------------------------------------------------------------- 1 | #region import modules 2 | $ThisModule = "$($MyInvocation.MyCommand.Path -replace "\.Tests\.ps1$", '').psm1" 3 | $ThisModuleName = (($ThisModule | Split-Path -Leaf) -replace ".psm1") 4 | Get-Module -Name $ThisModuleName -All | Remove-Module -Force 5 | 6 | Import-Module -Name $ThisModule -Force -ErrorAction Stop 7 | 8 | ## If a module is in $Env:PSModulePath and $ThisModule is not, you will have two modules loaded when importing and 9 | ## InModuleScope does not like that. 0.0 will always be the one imported directly from PSM1. 10 | @(Get-Module -Name $ThisModuleName).where({ $_.version -ne "0.0" }) | Remove-Module -Force 11 | #endregion 12 | 13 | InModuleScope $ThisModuleName { 14 | describe 'Restore-Acl' { 15 | 16 | } 17 | describe 'Save-Acl' { 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /ActiveDirectory/GetAdUsersWithPasswordLastSetOlderThan.ps1: -------------------------------------------------------------------------------- 1 | ## Union (Get-ADUser -filter {enabled -eq $true} -Properties employeenumber,passwordlastset | ? {$_.Employeenumber -and ($_.PasswordLastSet -gt [DateTime]::Now.Subtract([TimeSpan]::FromDays(180)))}).Count 2 | ## UAP (Get-ADUser -filter {enabled -eq $true} -Properties employeenumber,passwordlastset | ? {$_.Employeenumber -and ($_.DistinguishedName -like '*AP&S*') -and ($_.PasswordLastSet -gt [DateTime]::Now.Subtract([TimeSpan]::FromDays(180)))}).Count 3 | 4 | $MaxAge = 180 5 | 6 | $rules = @( 7 | { $_.PasswordLastSet -lt [DateTime]::Now.Subtract([TimeSpan]::FromDays($MaxAge)) }, 8 | { $_.LastLogonDate -lt [DateTime]::Now.Subtract([TimeSpan]::FromDays($MaxAge)) }, 9 | { $_.Enabled -eq $false }, 10 | { $_.PasswordExpired -eq $true } 11 | ) 12 | 13 | Get-AdUser -Filter * -Properties PasswordLastSet,LastLogonDate -------------------------------------------------------------------------------- /ActiveDirectory/Get-EmptyGroup.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 -Module ActiveDirectory 2 | 3 | function Get-EmptyGroup 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function queries the Active Directory domain the initiaing computer is in for all groups that have no members. 8 | This is common when attempting to find groups that can be removed. 9 | 10 | This does not include default AD groups like Domain Computers, Domain Users, etc. 11 | 12 | .EXAMPLE 13 | PS> Get-EmptyGroup 14 | 15 | 16 | #> 17 | [OutputType([pscustomobject])] 18 | [CmdletBinding()] 19 | param () 20 | begin 21 | { 22 | $ErrorActionPreference = 'Stop' 23 | } 24 | process 25 | { 26 | try 27 | { 28 | @(Get-ADGroup -Filter * -Properties isCriticalSystemObject,Members).where({ (-not $_.isCriticalSystemObject) -and ($_.Members.Count -eq 0) }) 29 | } 30 | catch 31 | { 32 | $PSCmdlet.ThrowTerminatingError($_) 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /SCOMMonitors/FileCountInDirectory.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$DirectoryName, 3 | [int]$MaxFileCount 4 | ) 5 | 6 | $API = New-Object -ComObject 'MOM.ScriptAPI' 7 | $PropertyBag = $API.CreatePropertyBag() 8 | 9 | try { 10 | $FileCount = (Get-ChildItem -Path $DirectoryName | Where-Object { !$_.PsIsContainer }).Count 11 | if ($FileCount -ge $MaxFileCount) { 12 | $PropertyBag.AddValue('State', 'Critical') 13 | $PropertyBag.Addvalue('Description', "There are $($FileCount - $MaxFileCount) more files than what should be in the directory $DirectoryName") 14 | } else { 15 | $PropertyBag.AddValue('State', 'Healthy') 16 | $PropertyBag.AddValue('Description', "There are less than $MaxFileCount files accumulated in the directory $DirectoryName") 17 | } 18 | $PropertyBag 19 | } catch { 20 | $PropertyBag.AddValue('State', 'Warning') 21 | $PropertyBag.Addvalue('Description', $_.Exception.Message) 22 | $PropertyBag 23 | } 24 | -------------------------------------------------------------------------------- /Random Stuff/Confirm-Choice.ps1: -------------------------------------------------------------------------------- 1 | function Confirm-Choice { 2 | [OutputType('boolean')] 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter()] 7 | [ValidateNotNullOrEmpty()] 8 | [string]$Title, 9 | 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [string]$PromptMessage 13 | ) 14 | 15 | $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes" 16 | $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No" 17 | $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) 18 | 19 | if ($PSBoundParameters.ContainsKey('Title')) { 20 | Write-Host -Object $Title -ForegroundColor Cyan 21 | } 22 | 23 | Write-Host -Object $PromptMessage -ForegroundColor Cyan 24 | $result = $host.ui.PromptForChoice($null, $null, $Options, 1) 25 | 26 | switch ($result) { 27 | 0 { 28 | $true 29 | } 30 | 1 { 31 | $false 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-UnlinkedGpo.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 -Module ActiveDirectory 2 | 3 | function Get-UnlinkedGpo 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function queries the Active Directory domain the initiaing computer is in for all GPOs that do not have a 8 | link to an object. This is common when atatempting to find GPOs that can be removed. 9 | 10 | .EXAMPLE 11 | PS> Get-UnlinkedGpo 12 | 13 | Name 14 | ---- 15 | GPOWithNoLinks1 16 | GPOWithNoLinks2 17 | GPOWithNoLinks3 18 | #> 19 | [OutputType([pscustomobject])] 20 | [CmdletBinding()] 21 | param() 22 | begin 23 | { 24 | $ErrorActionPreference = 'Stop' 25 | } 26 | process 27 | { 28 | try 29 | { 30 | $gpoReport = [xml](Get-GPOReport -All -ReportType XML) 31 | @($gpoReport.GPOs.GPO).where({ -not $_.LinksTo }).foreach({ 32 | [pscustomobject]@{ Name = $_.Name } 33 | }) 34 | } 35 | catch 36 | { 37 | $PSCmdlet.ThrowTerminatingError($_) 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-Inactive-GPOs.ps1: -------------------------------------------------------------------------------- 1 | $aOutput = @(); 2 | $aDisabledGpos = Get-GPO -All | Where-Object { $_.GpoStatus -eq 'AllSettingsDisabled' }; 3 | foreach ($oGpo in $aDisabledGpos) { 4 | $oOutput = New-Object System.Object; 5 | $oOutput | Add-Member -type NoteProperty -Name 'Status' -Value 'Disabled'; 6 | $oOutput | Add-Member -type NoteProperty -Name 'Name' -Value $oGpo.DisplayName; 7 | $aOutput += $oOutput; 8 | }##endforeach 9 | 10 | 11 | $aAllGpos = Get-Gpo -All; 12 | $aUnlinkedGpos = @(); 13 | foreach ($oGpo in $aAllGpos) { 14 | [xml]$oGpoReport = Get-GPOReport -Guid $oGpo.ID -ReportType xml; 15 | if (!(Test-Member $oGpoReport.GPO LinksTo)) { 16 | $oOutput = New-Object System.Object; 17 | $oOutput | Add-Member -type NoteProperty -Name 'Status' -Value 'Unlinked'; 18 | $oOutput | Add-Member -type NoteProperty -Name 'Name' -Value $oGpo.DisplayName; 19 | $aOutput += $oOutput; 20 | }##endif 21 | }##endforeach 22 | $aOutput.Count 23 | 24 | $aOutput | Sort-Object Name | Format-Table -AutoSize -------------------------------------------------------------------------------- /SQL/UsefulQueries/running tasks.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | r.session_id 3 | , r.command 4 | , CONVERT(NUMERIC(6,2), r.percent_complete) AS [Percent Complete] 5 | , CONVERT(VARCHAR(20), DATEADD(ms,r.estimated_completion_time,GetDate()),20) AS [ETA Completion Time] 6 | , CONVERT(NUMERIC(10,2), r.total_elapsed_time/1000.0/60.0) AS [Elapsed Min] 7 | , CONVERT(NUMERIC(10,2), r.estimated_completion_time/1000.0/60.0) AS [ETA Min] 8 | , CONVERT(NUMERIC(10,2), r.estimated_completion_time/1000.0/60.0/60.0) AS [ETA Hours] 9 | , CONVERT(VARCHAR(1000), 10 | (SELECT SUBSTRING(text,r.statement_start_offset/2, CASE WHEN r.statement_end_offset = -1 11 | THEN 1000 12 | ELSE (r.statement_end_offset-r.statement_start_offset)/2 13 | END) 14 | FROM sys.dm_exec_sql_text(sql_handle) 15 | ) 16 | ) AS [SQL] 17 | FROM sys.dm_exec_requests r 18 | 19 | -------------------------------------------------------------------------------- /Hyper-V/Checkpoint-OnlineVM.ps1: -------------------------------------------------------------------------------- 1 | function Checkpoint-OnlineVM 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function checks to see if a VM is running and if so, shuts it down and creates a checkpoint. If it's not running, 6 | it will go ahead and create the checkpoint. 7 | 8 | .PARAMETER VM 9 | A virtual machine. 10 | 11 | .EXAMPLE 12 | PS> Get-VM -Name SERVER1 | Checkpoint-OnlineVM 13 | 14 | This will find the VM called SERVER 1. If it's running, it will shut it down and create a checkpoint. If it's not 15 | running, it will simply create a checkpoint. 16 | #> 17 | 18 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'High')] 19 | param 20 | ( 21 | [Parameter(Mandatory, ValueFromPipeline)] 22 | [ValidateNotNullOrEmpty()] 23 | [Microsoft.HyperV.PowerShell.VirtualMachine[]]$VM 24 | ) 25 | process 26 | { 27 | foreach ($v in $VM) 28 | { 29 | if ($PSCmdlet.ShouldProcess($v.Name,'VM shutdown')) 30 | { 31 | $v | Stop-VM -Force -PassThru | Checkpoint-VM 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-All-Docs-Password-Age.ps1: -------------------------------------------------------------------------------- 1 | Import-Module ActiveDirectory 2 | try { 3 | $uap_docs = Import-Csv C:\scripts\All-Doc-2013-Password-Policy\all-docs-2013-password-policy.csv 4 | $ad_pw_ages = @(); 5 | foreach ($user in $uap_docs) { 6 | $ad_pw_ages += Get-AdUser $user.Username -Properties passwordlastset | % {"$($_.Givenname) $($_.Surname), $($_.PasswordLastSet)`n"} 7 | } 8 | 9 | ## Email 10 | $oFrom = New-Object system.net.Mail.MailAddress 'adbertram@gmail.com','Adam Bertram'; 11 | $oTo = New-Object system.net.Mail.MailAddress 'jdoe@email.com', 'John Doe' 12 | $oMsg = New-Object System.Net.Mail.MailMessage $oFrom, $oTo 13 | $oMsg.Subject = 'Daily Doc Password Changes' 14 | $oMsg.Body = "Here is the most recent list of docs and their password ages.`n`n$ad_pw_ages" 15 | $sSmtpServer = 'smtp.email.com'; 16 | $oSmtpClient = new-object Net.Mail.SmtpClient($sSmtpServer); 17 | 18 | $oSmtpClient.Send($oMsg); 19 | } catch [System.Exception] { 20 | return $_.Exception.Message; 21 | }##endtry -------------------------------------------------------------------------------- /Article Examples/TIP-SimpleFileSync.ps1: -------------------------------------------------------------------------------- 1 | $Folder1Path = 'C:\Folder1' 2 | $Folder2Path = 'C:\Folder2' 3 | 4 | $Folder1Files = Get-ChildItem -Path $Folder1Path 5 | $Folder2Files = Get-ChildItem -Path $Folder2Path 6 | 7 | $FileDiffs = Compare-Object -ReferenceObject $Folder1Files -DifferenceObject $Folder2Files 8 | 9 | $FileDiffs | foreach { 10 | $removeParams = @{ 11 | 'Path' = $_.InputObject.FullName 12 | } 13 | if ($_.SideIndicator -eq '<=') 14 | { 15 | $removeParams.Destination = $Folder2Path 16 | } 17 | else 18 | { 19 | $removeParams.Destination = $Folder1Path 20 | } 21 | Copy-Item @removeParams 22 | } 23 | 24 | #################################################### 25 | 26 | $Folder1Path = 'C:\Folder1' 27 | $Folder2Path = 'C:\Folder2' 28 | 29 | $Folder1Files = Get-ChildItem -Path $Folder1Path 30 | $Folder2Files = Get-ChildItem -Path $Folder2Path 31 | 32 | $FileDiffs = Compare-Object -ReferenceObject $Folder1Files -DifferenceObject $Folder2Files 33 | 34 | $FileDiffs | foreach { 35 | Remove-Item -Path $_.InputObject.FullName 36 | } -------------------------------------------------------------------------------- /DNS/Enable-DynamicDnsRegistration.ps1: -------------------------------------------------------------------------------- 1 | function Enable-DynamicDnsRegistration 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [string]$ComputerName, 9 | 10 | [Parameter()] 11 | [ValidateNotNullOrEmpty()] 12 | [pscredential]$Credential 13 | ) 14 | 15 | $icmParams = @{ 16 | 'ComputerName' = $ComputerName 17 | } 18 | if ($PSBoundParameters.ContainsKey('Credential')) 19 | { 20 | $icmParams.Credential = $Credential 21 | } 22 | 23 | $icmParams.ScriptBlock = { 24 | $VerbosePreference = $using:VerbosePreference 25 | Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='true'" | Where-Object { $_.DefaultIPGateway.Count -gt 0 } | ForEach-Object { 26 | Write-Verbose -Message "Setting DDNS registration..." 27 | $result = $_.SetDynamicDNSRegistration($true) 28 | if ($result.ReturnValue -ne 0) 29 | { 30 | throw "Failed to set DDNS registration on with return code [$($result.ReturnValue)]" 31 | } 32 | } 33 | } 34 | 35 | Invoke-Command @icmParams 36 | } -------------------------------------------------------------------------------- /Networking/connect-vpn.ps1: -------------------------------------------------------------------------------- 1 | ## One Time only. This is to securely store your VPN password to an encrypted text file 2 | Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File encrypted_password.txt 3 | 4 | ## The VPN profile name configured in your client 5 | $vpn_profile = 'Profile name' 6 | $username = 'username' 7 | 8 | ## Decrypt the password 9 | $enc_password = (gc .\encrypted_password.txt | ConvertTo-SecureString) 10 | 11 | ## Create the credentials 12 | $credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$enc_password $password = $credentials.GetNetworkCredential().Password 13 | 14 | ## Pass the appropriate arguments to the VPN client EXE 15 | Set-Location 'C:\Program Files (x86)\Cisco Systems\VPN Client' 16 | .\vpnclient.exe connect $vpn_profile user $username pwd $password 17 | 18 | ## Use this if you have a need to disconnect via script 19 | #Set-Location 'C:\Program Files (x86)\Cisco Systems\VPN Client' 20 | #.\vpnclient.exe disconnect 21 | 22 | ## RDP to a device. mstsc /v:HOSTNAME /multimon 23 | -------------------------------------------------------------------------------- /SQL/Invoke-SqlDatabaseBackupToFile.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module SQLPS 2 | 3 | function Invoke-SqlDatabaseBackupToFile 4 | { 5 | [CmdletBinding()] 6 | param 7 | ( 8 | [Parameter(Mandatory)] 9 | [ValidateNotNullOrEmpty()] 10 | [string]$Database, 11 | 12 | [Parameter(Mandatory)] 13 | [ValidateNotNullOrEmpty()] 14 | [ValidateScript({ Test-Connection -ComputerName $_ -Quiet -Count 1 })] 15 | [string]$Server, 16 | 17 | [Parameter(Mandatory)] 18 | [ValidateNotNullOrEmpty()] 19 | [ValidateSet('Full','Differential')] 20 | [string]$Type = 'Full', 21 | 22 | [Parameter(Mandatory)] 23 | [ValidateNotNullOrEmpty()] 24 | [ValidateScript({ -not (Test-Path -Path $_ -PathType Leaf) })] 25 | [string]$FilePath 26 | ) 27 | 28 | $query = @" 29 | BACKUP DATABASE $Database 30 | TO DISK = '$FilePath' 31 | "@ 32 | 33 | if ($Type -eq 'Differential') 34 | { 35 | $query += ' WITH DIFFERENTIAL' 36 | } 37 | 38 | Write-Verbose -Message "Running query: $($query)" 39 | 40 | Invoke-SQLCmd -ServerInstance $Server -Database $Database -Query $query 41 | } -------------------------------------------------------------------------------- /Azure/New-AzureWebAppVirtualDirectory.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module AzureRm 2 | 3 | param( 4 | [Parameter(Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | [string]$AzureWebAppName, 7 | 8 | [Parameter(Mandatory)] 9 | [ValidateNotNullOrEmpty()] 10 | [string]$AzureResourceGroup, 11 | 12 | [Parameter(Mandatory)] 13 | [ValidateNotNullOrEmpty()] 14 | [string]$VirtualPath, 15 | 16 | [Parameter(Mandatory)] 17 | [ValidateNotNullOrEmpty()] 18 | [string]$PhysicalPath, 19 | 20 | [Parameter()] 21 | [ValidateNotNullOrEmpty()] 22 | [bool]$PreloadEnabled = $false 23 | ) 24 | 25 | $webApp = Get-AzureRmWebApp -Name $AzureWebAppName -ResourceGroupName $AzureResourceGroup 26 | 27 | $VirtualPath = $VirtualPath.Replace('\', '/') 28 | $PhysicalPath = "site\$PhysicalPath" 29 | 30 | $virtApp = New-Object Microsoft.Azure.Management.WebSites.Models.VirtualApplication 31 | $virtApp.VirtualPath = $VirtualPath 32 | $virtApp.PhysicalPath = $PhysicalPath 33 | $virtApp.PreloadEnabled = $PreloadEnabled 34 | 35 | $null = $webApp.siteconfig.VirtualApplications.Add($virtApp) 36 | 37 | Set-AzureRmWebApp -WebApp $webApp 38 | 39 | -------------------------------------------------------------------------------- /Windows Update/Reset windows updates.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM --------------------------Start of getting superuser permissions-------------------------------------------- 4 | 5 | REM Check If the script has admin rights 6 | openfiles.exe 1>nul 2>&1 7 | 8 | REM If error flag set, we do not have admin. 9 | if '%errorlevel%' NEQ '0' ( 10 | echo Requesting administrative privileges... 11 | goto UACPrompt 12 | ) else ( goto gotAdmin ) 13 | 14 | REM Now we create temp visual basic scrit which will run this script again with UAC 15 | :UACPrompt 16 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 17 | set params=%* 18 | echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" 19 | 20 | REM Run getadmin.vbs which will run AvgSetup.bat with UAC 21 | "%temp%\getadmin.vbs" 22 | REM Delete getadmin.vbs and exit 23 | del "%temp%\getadmin.vbs" 24 | exit /B 25 | 26 | :gotAdmin 27 | 28 | 29 | net stop wuauserv 30 | del c:\WINDOWS\SoftwareDistribution\*.* /s /q 31 | gpupdate /force 32 | net start wuauserv 33 | wuauclt /detectnow /register /reportnow -------------------------------------------------------------------------------- /Troubleshooting Tools/Find-TroubleshootingEvent.ps1: -------------------------------------------------------------------------------- 1 | function Find-TroubleshootingEvent 2 | { 3 | [OutputType()] 4 | [CmdletBinding()] 5 | param 6 | ( 7 | [Parameter()] 8 | [ValidateNotNullOrEmpty()] 9 | [string[]]$ComputerName = (hostname), 10 | 11 | [Parameter()] 12 | [ValidateNotNullOrEmpty()] 13 | [int]$EventId 14 | ) 15 | try 16 | { 17 | @($ComputerName).foreach({ 18 | $computer = $_ 19 | $getEventParams = @{ 20 | ComputerName = $computer 21 | } 22 | $logNames = @(Get-WinEvent @getEventParams -ListLog *).where({ $_.RecordCount }).LogName 23 | Write-Verbose -Message "Found log names: [$($logNames -join ',')]" 24 | $filterHashTable = @{ 25 | LogName = $logNames 26 | } 27 | if ($PSBoundParameters.ContainsKey('EventId')) 28 | { 29 | $filterHashTable.Id = $EventId 30 | } 31 | $selectProperties = @('*',@{Name = 'ServerName'; Expression = {$computer}}) 32 | Get-WinEvent @getEventParams -FilterHashTable $filterHashTable | Select-Object -Property $selectProperties 33 | }) 34 | } 35 | catch 36 | { 37 | $PSCmdlet.ThrowTerminatingError($_) 38 | } 39 | } -------------------------------------------------------------------------------- /Security/DownloadQualysPatches.ps1: -------------------------------------------------------------------------------- 1 | param($scan_results_file) 2 | $download_path = 'C:\Documents and Settings\abertram\Desktop\CONFIGMANAGER Vulnerabilities' 3 | 4 | $mht_contents = gc $scan_results_file 5 | $ie = New-Object -ComObject 'InternetExplorer.Application' 6 | $webclient = New-Object System.Net.WebClient 7 | $ie.Navigate2('file:///C:\Documents and Settings\abertram\Desktop\CONFIGMANAGER Vulnerabilities\Scan_Results_unnhs_tw1_20131121_scan_1385046170_57428.mht') 8 | 9 | $links = $ie.Document.getElementsByTagName('a') | ? {($_.innertext -like '*Windows Server 2012*') -and ($_.innertext -notlike '*Core*') -and ($_.href -like 'http://*')} | select -ExpandProperty href 10 | foreach ($link in $links) { 11 | $r = Invoke-WebRequest -Uri $link -UseBasicParsing 12 | $r.Links | ? {$_.outerhtml -like '*Download*'} | % { 13 | $_.href 14 | $y = Invoke-WebRequest "http://www.microsoft.com$($_.href)" -UseBasicParsing 15 | } 16 | $y.Links | ? {$_.outerhtml -like '*Click Here*'} | select -first 1 | % {$webclient.DownloadFile($_.href,"$download_path\$(split-path $_.href -Leaf)")} 17 | } 18 | -------------------------------------------------------------------------------- /ActiveDirectory/Get-DisabledGpo.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 -Module ActiveDirectory 2 | 3 | function Get-DisabledGpo 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function queries the Active Directory domain the initiaing computer is in for all GPOs that either have 8 | their computer, user or both settings disabled. This is common when atatempting to find GPOs that can be removed. 9 | 10 | .EXAMPLE 11 | PS> Get-DisabledGpo 12 | 13 | Name DisabledSettingsCategory 14 | ---- ------------------------ 15 | GPO1 AllSetting 16 | GPO1 ComputerSetting 17 | GPO3 UserSetting 18 | #> 19 | [OutputType([pscustomobject])] 20 | [CmdletBinding()] 21 | param () 22 | begin 23 | { 24 | $ErrorActionPreference = 'Stop' 25 | } 26 | process 27 | { 28 | try 29 | { 30 | @(Get-GPO -All).where({ $_.GpoStatus -like '*Disabled' }).foreach({ 31 | [pscustomobject]@{ 32 | Name = $_.DisplayName 33 | DisabledSettingsCategory = ([string]$_.GpoStatus).TrimEnd('Disabled') 34 | } 35 | }) 36 | } 37 | catch 38 | { 39 | $PSCmdlet.ThrowTerminatingError($_) 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /PowerShell Internals/Write-Params.ps1: -------------------------------------------------------------------------------- 1 | function Write-Param 2 | { 3 | <# 4 | .SYNOPSIS 5 | Write-Param is a simple function that writes the parameters used for the calling function out to the console. This is useful 6 | in debugging situations where you have function "trees" where you have dozens of functions calling each and want to see 7 | what parameters are being passed to each function via the console. 8 | 9 | No need to pass any parameters to Write-Param. It uses the PS call stack to find what function called it and all the parameters 10 | used. 11 | 12 | .EXAMPLE 13 | function MyFunction { 14 | param( 15 | [Parameter()] 16 | [string]$Param1, 17 | 18 | [Parameter()] 19 | [string]$Param2 20 | ) 21 | 22 | Write-Params 23 | } 24 | 25 | PS> MyFunction -Param1 'hello' -Param2 'whatsup' 26 | 27 | This example would output the following to the Verbose stream: 28 | 29 | Function: Get-LocalGroup - Params used: {Param1=hello, Param2=whatsup} 30 | 31 | #> 32 | [CmdletBinding()] 33 | param () 34 | $caller = (Get-PSCallStack)[1] 35 | Write-Verbose -Message "Function: $($caller.Command) - Params used: $($caller.Arguments)" 36 | } -------------------------------------------------------------------------------- /Text Files/ValidateXml.ps1: -------------------------------------------------------------------------------- 1 | function Validate-Xml { 2 | param ([string]$XmlFilePath) 3 | try { 4 | # Get the file 5 | $XmlFile = Get-Item($XmlFilePath) 6 | 7 | # Keep count of how many errors there are in the XML file 8 | $script:ErrorCount = 0 9 | 10 | # Perform the XSD Validation 11 | $ReaderSettings = New-Object -TypeName System.Xml.XmlReaderSettings 12 | $ReaderSettings.ValidationType = [System.Xml.ValidationType]::Schema 13 | $ReaderSettings.ValidationFlags = [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessInlineSchema -bor [System.Xml.Schema.XmlSchemaValidationFlags]::ProcessSchemaLocation 14 | $ReaderSettings.add_ValidationEventHandler({ $script:ErrorCount++ }) 15 | $Reader = [System.Xml.XmlReader]::Create($XmlFile.FullName, $ReaderSettings) 16 | while ($Reader.Read()) { } 17 | $Reader.Close() 18 | 19 | # Verify the results of the XSD validation 20 | if ($script:ErrorCount -gt 0) { 21 | # XML is NOT valid 22 | $false 23 | } else { 24 | # XML is valid 25 | $true 26 | } 27 | } catch { 28 | Write-Warning "$($MyInvocation.MyCommand.Name) - Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 29 | } 30 | } -------------------------------------------------------------------------------- /VMware/Remove-OnlineVM.ps1: -------------------------------------------------------------------------------- 1 | function Remove-OnlineVM 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function is a wrapper for the PowerCLI's Remove-VM function gives you the option to force the VM 6 | to shutdown prior to removal. 7 | 8 | .PARAMETER VM 9 | A VM object from the Get-VM cmdlet. 10 | 11 | .EXAMPLE 12 | PS> Get-VM SERVER1 | Remove-OnlineVM -Shutdown 13 | 14 | This example is shutting down the SERVER1 VM (if it's on) and then removes the VM. 15 | #> 16 | 17 | [CmdletBinding(SupportsShouldProcess)] 18 | param 19 | ( 20 | [Parameter(Mandatory, ValueFromPipeline)] 21 | [ValidateNotNullOrEmpty()] 22 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]]$VM 23 | ) 24 | process 25 | { 26 | foreach ($v in $VM) 27 | { 28 | $vmName = $v.Name 29 | if ($PSCmdlet.ShouldProcess($vmName, 'Remove VM')) 30 | { 31 | if ((vmware.vimautomation.core\Get-VM -Name $vmName).PowerState -eq 'PoweredOn') 32 | { 33 | Write-Verbose -Message "[$vmName)] is online. Shutting down now." 34 | $v | vmware.vimautomation.core\Stop-VM -Confirm:$false 35 | } 36 | $v | vmware.vimautomation.core\Remove-VM -Confirm:$false 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /PowerShell Internals/Get-FunctionDefaultParameter.ps1: -------------------------------------------------------------------------------- 1 | function Get-FunctionDefaultParameter 2 | { 3 | <# 4 | .SYNOPSIS 5 | This is a function that will find all of the default parameter names and values from a given function. 6 | 7 | .EXAMPLE 8 | PS> Get-FunctionDefaultParameter -FunctionName Get-Something 9 | 10 | .PARAMETER FuntionName 11 | A mandatory string parameter representing the name of the function to find default parameters to. 12 | 13 | #> 14 | [CmdletBinding()] 15 | [OutputType([hashtable])] 16 | param 17 | ( 18 | [Parameter(Mandatory)] 19 | [ValidateNotNullOrEmpty()] 20 | [string]$FunctionName 21 | ) 22 | try 23 | { 24 | $ast = (Get-Command $FunctionName).ScriptBlock.Ast 25 | 26 | $select = @{ n = 'Name'; e = { $_.Name.VariablePath.UserPath } }, 27 | @{ n = 'Value'; e = { $_.DefaultValue.Extent.Text -replace "`"|'" } } 28 | 29 | $ht = @{} 30 | @($ast.FindAll({ $args[0] -is [System.Management.Automation.Language.ParameterAst] }, $true) | Where-Object { $_.DefaultValue } | Select-Object $select).foreach({ 31 | $ht[$_.Name] = $_.Value 32 | }) 33 | $ht 34 | 35 | } 36 | catch 37 | { 38 | Write-Error -Message $_.Exception.Message 39 | } 40 | } -------------------------------------------------------------------------------- /PowerShell Internals/Get-UserCredential.ps1: -------------------------------------------------------------------------------- 1 | #region function Get-UserCredential 2 | function Get-UserCredential 3 | { 4 | <# 5 | .SYNOPSIS 6 | Get-UserCredential provides a way to get a username and password from a normal "user". The user can provide their 7 | own credential. If not, it then prompts the user for their locally logged on username and returns a credential object. 8 | 9 | .PARAMETER Credential 10 | A pscredential object to output. 11 | #> 12 | 13 | [CmdletBinding()] 14 | param 15 | ( 16 | [Parameter()] 17 | [ValidateNotNullOrEmpty()] 18 | [pscredential]$Credential 19 | ) 20 | try 21 | { 22 | if (-not $PSBoundParameters.ContainsKey('Credential')) { 23 | if ((Get-KeystoreDefaultCertificate) -isnot 'System.Security.Cryptography.X509Certificates.X509Certificate2') 24 | { 25 | $Credential = Get-Credential -UserName (whoami) -Message 'Cannot find a suitable credential. Please input your password to use.' 26 | } 27 | else 28 | { 29 | $Credential = Get-KeyStoreCredential -Name 'svcOrchestrator' 30 | } 31 | } 32 | $Credential 33 | } 34 | catch 35 | { 36 | $PSCmdlet.ThrowTerminatingError($_) 37 | } 38 | } 39 | #endregion function Get-UserCredential -------------------------------------------------------------------------------- /Azure/Get-AzrAvailableLun.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | 3 | function Get-AzrAvailableLun 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function looks at an Azure ARM VM object and finds the next available LUN. It is typically used to find the next 8 | available LUN to use for attaching a new data disk to a VM. 9 | 10 | .EXAMPLE 11 | PS> $vm = Get-AzureRmVm -Name 'BAPP07GEN25' -ResourceGroupName 'BDT007' 12 | PS> Get-AzrAvailableLun -VM $vm 13 | 14 | This example would look at the VM object and return the next available LUN number for the VM BAPP07GEN25. 15 | 16 | .PARAMETER VM 17 | An Azure VM object 18 | #> 19 | [CmdletBinding()] 20 | param 21 | ( 22 | [Parameter(Mandatory)] 23 | [ValidateNotNullOrEmpty()] 24 | [Microsoft.Azure.Commands.Compute.Models.PSVirtualMachine]$VM 25 | ) 26 | process 27 | { 28 | $luns = $VM.StorageProfile.DataDisks 29 | if ($luns.Count -eq 0) 30 | { 31 | Write-Verbose -Message "No data disks found attached to VM: [$($VM.Name)]" 32 | 0 33 | } 34 | else 35 | { 36 | Write-Verbose -Message "Finding the next available LUN for VM: [$($VM.Name)]" 37 | $lun = ($luns.Lun | Measure-Object -Maximum).maximum + 1 38 | Write-Verbose -Message "Next available LUN is: [$($lun)]" 39 | $lun 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Random Stuff/Show-BalloonTip.ps1: -------------------------------------------------------------------------------- 1 | function Show-BalloonTip 2 | { 3 | [OutputType([void])] 4 | [CmdletBinding(DefaultParameterSetName = 'IconFilePath')] 5 | param 6 | ( 7 | [Parameter(Mandatory,ParameterSetName = 'IconFilePath')] 8 | [ValidateNotNullOrEmpty()] 9 | [string]$IconFilePath, 10 | 11 | [Parameter(Mandatory,ParameterSetName = 'Icon')] 12 | [ValidateNotNullOrEmpty()] 13 | [System.Drawing.Icon]$Icon, 14 | 15 | [Parameter(Mandatory)] 16 | [ValidateNotNullOrEmpty()] 17 | [string]$Text, 18 | 19 | [Parameter()] 20 | [ValidateNotNullOrEmpty()] 21 | [ValidateSet('Error','Info','None','Warning')] 22 | [string]$IconType = 'None', 23 | 24 | [Parameter()] 25 | [ValidateNotNullOrEmpty()] 26 | [string]$Title 27 | ) 28 | 29 | try { 30 | 31 | $balloon = New-Object System.Windows.Forms.NotifyIcon 32 | 33 | if ($IconFilePath) { 34 | $icon = $IconFilePath 35 | } 36 | $balloon.Icon = $icon 37 | $balloon.BalloonTipIcon = $IconType 38 | $balloon.BalloonTipText = $Text 39 | $balloon.BalloonTipTitle = $Title 40 | $balloon.Visible = $true 41 | 42 | $balloon.ShowBalloonTip(1) 43 | } catch { 44 | Write-Error -Message $_.Exception.Message 45 | } finally { 46 | # $balloon.Dispose() 47 | # Remove–Variable –Name balloon 48 | } 49 | } -------------------------------------------------------------------------------- /SCCM/Start-CMApplicationDeploymentTest.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | 4 | .NOTES 5 | Created on: 8/22/2014 6 | Created by: Adam Bertram 7 | Filename: 8 | Credits: 9 | Requirements: 10 | Todos: 11 | .EXAMPLE 12 | 13 | .EXAMPLE 14 | 15 | .PARAMETER PARAM1 16 | 17 | .PARAMETER PARAM2 18 | 19 | #> 20 | [CmdletBinding(DefaultParameterSetName = 'name')] 21 | [OutputType('System.Management.Automation.PSCustomObject')] 22 | param ( 23 | [Parameter(ParameterSetName = 'name', 24 | Mandatory, 25 | ValueFromPipeline, 26 | ValueFromPipelineByPropertyName)] 27 | [ValidateSet("Tom","Dick","Jane")] 28 | [ValidateRange(21,65)] 29 | [ValidateScript({Test-Path $_ -PathType 'Container'})] 30 | [ValidateNotNullOrEmpty()] 31 | [ValidateCount(1,5)] 32 | [ValidateLength(1,10)] 33 | [ValidatePattern()] 34 | [string]$Computername = 'DEFAULTVALUE' 35 | ) 36 | 37 | begin { 38 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 39 | Set-StrictMode -Version Latest 40 | try { 41 | 42 | } catch { 43 | Write-Error $_.Exception.Message 44 | } 45 | } 46 | 47 | process { 48 | try { 49 | 50 | } catch { 51 | Write-Error $_.Exception.Message 52 | } 53 | } 54 | 55 | end { 56 | try { 57 | 58 | } catch { 59 | Write-Error $_.Exception.Message 60 | } 61 | } -------------------------------------------------------------------------------- /Windows Update/Install .NET 3.5 removing WSUS.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM --------------------------Start of getting superuser permissions-------------------------------------------- 4 | 5 | REM Check If the script has admin rights 6 | openfiles.exe 1>nul 2>&1 7 | 8 | REM If error flag set, we do not have admin. 9 | if '%errorlevel%' NEQ '0' ( 10 | echo Requesting administrative privileges... 11 | goto UACPrompt 12 | ) else ( goto gotAdmin ) 13 | 14 | REM Now we create temp visual basic scrit which will run this script again with UAC 15 | :UACPrompt 16 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 17 | set params=%* 18 | echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" 19 | 20 | REM Run getadmin.vbs which will run AvgSetup.bat with UAC 21 | "%temp%\getadmin.vbs" 22 | REM Delete getadmin.vbs and exit 23 | del "%temp%\getadmin.vbs" 24 | exit /B 25 | 26 | :gotAdmin 27 | 28 | REM --------------------------End of getting superuser permissions-------------------------------------------- 29 | 30 | 31 | reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\ /f /va 32 | 33 | net stop wuauserv 34 | 35 | net start wuauserv 36 | 37 | DISM /Online /Enable-Feature /FeatureName:NetFx3 /All 38 | 39 | pause -------------------------------------------------------------------------------- /Networking/Get-ServiceListeningPort.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | 4 | .NOTES 5 | Created on: 8/22/2014 6 | Created by: Adam Bertram 7 | Filename: 8 | Credits: 9 | Requirements: 10 | Todos: 11 | .EXAMPLE 12 | 13 | .EXAMPLE 14 | 15 | .PARAMETER PARAM1 16 | 17 | .PARAMETER PARAM2 18 | 19 | #> 20 | [CmdletBinding(DefaultParameterSetName = 'name')] 21 | [OutputType('System.Management.Automation.PSCustomObject')] 22 | param ( 23 | [Parameter(ParameterSetName = 'name', 24 | Mandatory, 25 | ValueFromPipeline, 26 | ValueFromPipelineByPropertyName)] 27 | [ValidateSet("Tom","Dick","Jane")] 28 | [ValidateRange(21,65)] 29 | [ValidateScript({Test-Path $_ -PathType 'Container'})] 30 | [ValidateNotNullOrEmpty()] 31 | [ValidateCount(1,5)] 32 | [ValidateLength(1,10)] 33 | [ValidatePattern()] 34 | [string]$Computername = 'localhost' 35 | ) 36 | 37 | begin { 38 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 39 | Set-StrictMode -Version Latest 40 | } 41 | 42 | process { 43 | try { 44 | $ServiceExes = Get-WmiObject -ComputerName $Computername -Property DisplayName, PathName 45 | 46 | } catch { 47 | Write-Error $_.Exception.Message 48 | } 49 | } 50 | 51 | end { 52 | try { 53 | 54 | } catch { 55 | Write-Error $_.Exception.Message 56 | } 57 | } -------------------------------------------------------------------------------- /Inventorying-Reporting Tools/Get-UpTime.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This script gets the total time a computer has been up for. 4 | .DESCRIPTION 5 | This script queries the Win32_OperatingSystem WMI class to retrieve the 6 | LastBootupTime and output a datetime object containing the specific 7 | time the computer has been up for. 8 | .NOTES 9 | Created on: 6/9/2014 10 | Created by: Adam Bertram 11 | Filename: Get-UpTime.ps1 12 | .EXAMPLE 13 | .\Get-Uptime.ps1 -Computername 'COMPUTER' 14 | 15 | .PARAMETER Computername 16 | This is the name of the computer you'd like to query 17 | #> 18 | [CmdletBinding()] 19 | param ( 20 | [Parameter(ValueFromPipeline, 21 | ValueFromPipelineByPropertyName)] 22 | [string]$Computername = 'localhost' 23 | ) 24 | 25 | begin { 26 | Set-StrictMode -Version Latest 27 | } 28 | 29 | process { 30 | try { 31 | $WmiResult = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName 32 | $LastBoot = $WmiResult.ConvertToDateTime($WmiResult.LastBootupTime) 33 | $ObjParams = [ordered]@{'Computername' = $Computername } 34 | ((Get-Date) - $LastBoot).psobject.properties | foreach { $ObjParams[$_.Name] = $_.Value } 35 | New-Object -TypeName PSObject -Property $ObjParams 36 | } catch { 37 | Write-Error $_.Exception.Message 38 | } 39 | } 40 | 41 | end { 42 | 43 | } -------------------------------------------------------------------------------- /AWS/EC2/Get-InstanceMetadata.ps1: -------------------------------------------------------------------------------- 1 | function Get-EC2InstanceMetadata 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function queries AWS's URL to gather instance meta-data. This function is meant to be executed 6 | from a EC2 instance as the URI that exposes the metadata is not available elsewhere. 7 | .EXAMPLE 8 | PS> Get-EC2InstanceMetadata -Path 'public-hostname' 9 | 10 | This example would query the URL http://169.254.169.254/latest/meta-data/public-hostname and return the page's result. 11 | 12 | .PARAMETER Path 13 | The URL path to the metadata item you'd like to retrieve. 14 | 15 | .PARAMETER BaseUri 16 | The URI that Amazon publishes to expose instance metadata. 17 | #> 18 | [CmdletBinding()] 19 | [OutputType('System.Management.Automation.PSCustomObject')] 20 | param 21 | ( 22 | [Parameter(Mandatory)] 23 | [ValidateNotNullOrEmpty()] 24 | [string]$Path, 25 | 26 | [Parameter()] 27 | [ValidateNotNullOrEmpty()] 28 | [string]$BaseUri = 'http://169.254.169.254/latest/meta-data' 29 | ) 30 | 31 | $Uri = "$BaseUri/$Path" 32 | Write-Verbose -Message "Invoking HTTP request for URI [$($Uri)]" 33 | $result = Invoke-WebRequest -Uri $Uri 34 | if ($result.StatusCode -ne 200) 35 | { 36 | throw "The HTTP request failed when looking up URI [$Uri]" 37 | } 38 | 39 | $result.Content.Split("`n") 40 | } -------------------------------------------------------------------------------- /Certificates/changes.md: -------------------------------------------------------------------------------- 1 | ### Updates to Certificates scripts/functions: 2 | 3 | Sep 2017, by Matt Boren (@mtboren) 4 | - in `New-CertificateSigningRequest` function: 5 | - increased functionality: added ability to specify Subject Alternative Name attribtutes for CSR via new `-SubjectAlternateNameDNS` parameter 6 | - added `-WhatIf` support, which returns the proposed contents to use for .inf file with `certreq.exe` invocation 7 | - increased convenience factor: added feature that uses the local computer name if `-SubjectHost` parameter not specified 8 | - completed usefulness of certs for browsers that no longer use the Subject property of a cert, but instead rely on SAN values only -- CSRs now automatically include the SubjectHost value in the SAN field 9 | - increased flexibility: removed unnecessary requirement on consumer to use ".req" file extension for resulting CSR file name; while it might be standard, it should not be mandatory 10 | - added helpful tip in `.Notes` section on how to inspect new CSR file with `openssl.exe`, so one knows how validate the contents of the CSR before submitting it for a certificate 11 | - bugfix: fixed `Signature` value in `[Version]` section of INF contents: `$Windows` was being interpreted as an empty variable, instead of as a literal (needed to escape the `$` character) 12 | -------------------------------------------------------------------------------- /Windows Update/Disable wsus and reset WU.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM --------------------------Start of getting superuser permissions-------------------------------------------- 4 | 5 | REM Check If the script has admin rights 6 | openfiles.exe 1>nul 2>&1 7 | 8 | REM If error flag set, we do not have admin. 9 | if '%errorlevel%' NEQ '0' ( 10 | echo Requesting administrative privileges... 11 | goto UACPrompt 12 | ) else ( goto gotAdmin ) 13 | 14 | REM Now we create temp visual basic scrit which will run this script again with UAC 15 | :UACPrompt 16 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 17 | set params=%* 18 | echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" 19 | 20 | REM Run getadmin.vbs which will run AvgSetup.bat with UAC 21 | "%temp%\getadmin.vbs" 22 | REM Delete getadmin.vbs and exit 23 | del "%temp%\getadmin.vbs" 24 | exit /B 25 | 26 | :gotAdmin 27 | 28 | REM --------------------------End of getting superuser permissions-------------------------------------------- 29 | 30 | 31 | reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\ /f /va 32 | 33 | net stop wuauserv 34 | 35 | del c:\WINDOWS\SoftwareDistribution\*.* /s /q 36 | 37 | net start wuauserv 38 | 39 | wuauclt /detectnow /register /reportnow 40 | 41 | pause -------------------------------------------------------------------------------- /Hyper-V/Get-VMError.ps1: -------------------------------------------------------------------------------- 1 | function Get-VMError 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function queries a Hyper-V host for any errors that have been recorded in any 6 | HyperV event source. 7 | 8 | .PARAMETER Server 9 | The Hyper-V host that the VM is running on. 10 | 11 | .PARAMETER Credential 12 | A PSCredential object to use for alternative credentials. 13 | 14 | .EXAMPLE 15 | PS> Get-VMError -Server SERVER1 16 | 17 | This example queries all Hyper-V event sources on the host SERVER1 18 | #> 19 | 20 | [CmdletBinding()] 21 | param 22 | ( 23 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 24 | [ValidateNotNullOrEmpty()] 25 | [Alias('ComputerName')] 26 | [string]$Server, 27 | 28 | [Parameter()] 29 | [ValidateNotNullOrEmpty()] 30 | [pscredential]$Credential 31 | ) 32 | 33 | $whereFilter = { $_.TimeCreated -gt (Get-Date).AddDays(-1) -and ($_.LevelDisplayName -in @('Error', 'Critical')) } 34 | 35 | $properties = @('Machinename', 'TimeCreated', 'LevelDisplayName', 'Message') 36 | $winParams = @{ 37 | 'ComputerName' = $Server 38 | 'LogName' = 'Microsoft-Windows-Hyper-V-*' 39 | } 40 | if ($PSBoundParameters.ContainsKey('Credential')) { 41 | $winParams.Credential = $Credential 42 | } 43 | Get-WinEvent @winParams | where -FilterScript $whereFilter | Select $properties 44 | } -------------------------------------------------------------------------------- /Scheduled Tasks/Get-MyScheduledTask.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | 3 | <# 4 | .SYNOPSIS 5 | This script finds all scheduled tasks registered on a local computer. It outputs the author of the scheduled task 6 | and the creation date. This is useful in malware detection when malware might create a scheduled task in the 7 | background without anyone knowing. 8 | .NOTES 9 | Created on: 5/7/2015 10 | Created by: Adam Bertram 11 | Filename: Get-MyScheduledTask 12 | .EXAMPLE 13 | PS> Get-MyScheduledTask.ps1 | Where-Object {$_.CreationDate -lt (Get-Date).AddDays(-1)} 14 | 15 | This example will find all scheduled tasks that were created within the last day. 16 | .EXAMPLE 17 | PS> Get-MyScheduledTask.ps1 | Where-Object {($_.Author -notmatch 'Microsoft') -and $_.Author} 18 | 19 | This example will find all scheduled tasks that are non-default. It removes all scheduled tasks that have an author with 20 | the word 'Microsoft' in it or has a null value for the author 21 | #> 22 | [CmdletBinding()] 23 | [OutputType('Selected.Microsoft.Management.Infrastructure.CimInstance')] 24 | param () 25 | process { 26 | try { 27 | Get-ScheduledTask | Select-Object TaskName,Author, @{ 'n' = 'CreationDate'; 'e' = { [datetime]$_.Date } } 28 | } catch { 29 | Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 30 | } 31 | } -------------------------------------------------------------------------------- /DNS/Test-DnsNameResolution.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.1 5 | 6 | .GUID e2603db1-b42d-4456-84f8-6031a8d247fd 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | #> 32 | 33 | <# 34 | 35 | .DESCRIPTION 36 | A script to test if a DNS name can be resolved. 37 | 38 | #> 39 | [CmdletBinding()] 40 | param 41 | ( 42 | [Parameter(Mandatory)] 43 | [ValidateNotNullOrEmpty()] 44 | [string]$Name, 45 | 46 | [Parameter(Mandatory)] 47 | [ValidateNotNullOrEmpty()] 48 | [string]$Server 49 | ) 50 | 51 | $resolvParams = @{ 52 | 'Server' = $Server 53 | 'DnsOnly' = $true 54 | 'NoHostsFile' = $true 55 | 'ErrorAction' = 'SilentlyContinue' 56 | 'ErrorVariable' = 'err' 57 | 'Name' = $Name 58 | } 59 | try 60 | { 61 | if (Resolve-DnsName @resolvParams) 62 | { 63 | $true 64 | } 65 | elseif ($err -and ($err.Exception.Message -match '(DNS name does not exist)|(No such host is known)')) 66 | { 67 | $false 68 | } 69 | else 70 | { 71 | throw $err 72 | } 73 | } 74 | catch 75 | { 76 | if ($_.Exception.Message -match 'No such host is known') 77 | { 78 | $false 79 | } 80 | else 81 | { 82 | throw $_ 83 | } 84 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-GPO-Reg-Settings.ps1: -------------------------------------------------------------------------------- 1 | function findRegValues($sName,$sId,$sKeyPath,$aKeyPathHistory = $null) { 2 | $aPath = Get-GPRegistryValue -GUID $sId -Key $sKeyPath 3 | $aKeyPathHistory = @() 4 | $aUniqueSettings = @() 5 | $aUniqueDups = @() 6 | 7 | foreach ($oKeyPath in $aPath) { 8 | if ($oKeyPath) { 9 | if ('Value' -in $oKeyPath.PSObject.Properties.Name) { 10 | if ($aKeyPathHistory -notcontains $oKeyPath.FullKeyPath) { 11 | $o = @{ 12 | 'GUID' = $sId 13 | 'Name' = $sName 14 | 'Key' = $sKeyPath 15 | 'Value' = $oKeyPath.Value 16 | } 17 | if ($aUniqueSettings -notcontains "$sKeyPath|$($oKeyPath.Value)") { 18 | $aUniqueSettings += "$sKeyPath|$($oKeyPath.Value)"; 19 | } elseif ($aUniqueDups -notcontains "$sKeyPath|$($oKeyPath.Value)") { 20 | $o.Value = "$sName|$sKeyPath|$($oKeyPath.Value)"; 21 | $aUniqueDups += "$sKeyPath|$($oKeyPath.Value)"; 22 | } 23 | [pscustomobject]$o 24 | } 25 | } elseif ('FullKeyPath' -in $oKeyPath.PSObject.Properties.Name) { 26 | $aKeyPathHistory += $oKeyPath.FullKeyPath; 27 | findRegValues $sName $sId $oKeyPath.FullKeyPath $aKeyPathHistory 28 | } 29 | } 30 | } 31 | } 32 | 33 | $aRegRoots = @('HKCU\Software','HKLM\System','HKLM\Software') 34 | 35 | foreach ($oGpo in (Get-Gpo -All)) { 36 | foreach ($sRegRoot in $aRegRoots) { 37 | findRegValues $oGpo.DisplayName $oGpo.Id $sRegRoot 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DNS/Wait-DnsNameResolution.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 4 2 | [CmdletBinding()] 3 | param 4 | ( 5 | [Parameter(Mandatory)] 6 | [ValidateNotNullOrEmpty()] 7 | [ValidatePattern('^\w+\.\w+\.\w+$')] 8 | [string]$Name, 9 | 10 | [Parameter()] 11 | [switch]$NetBiosFallback, 12 | 13 | [Parameter()] 14 | [ValidateNotNullOrEmpty()] 15 | [ValidateRange(1, [int]::MaxValue)] 16 | [int]$Timeout = 60, 17 | 18 | [Parameter()] 19 | [ValidateNotNullOrEmpty()] 20 | [string]$Server 21 | 22 | ) 23 | 24 | begin 25 | { 26 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 27 | Clear-DnsClientCache 28 | } 29 | 30 | process 31 | { 32 | try 33 | { 34 | $resolveParams = @{ 35 | Name = $Name 36 | ErrorAction = 'SilentlyContinue' 37 | } 38 | if ($NetBiosFallback.IsPresent) 39 | { 40 | $resolveParams.NetBiosFallback = $true 41 | } 42 | else 43 | { 44 | $resolveParams.DnsOnly = $true 45 | } 46 | if ($PSBoundParameters.ContainsKey('Server')) 47 | { 48 | $resolveParams.Server = $Server 49 | } 50 | $timer = [Diagnostics.Stopwatch]::StartNew() 51 | while (-not (Resolve-DnsName @resolveParams)) 52 | { 53 | if ($timer.Elapsed.TotalSeconds -ge $Timeout) 54 | { 55 | throw "Timeout exceeded. Giving up on DNS record availability for [$($Name)]" 56 | } 57 | Start-Sleep -Seconds 10 58 | } 59 | } 60 | catch 61 | { 62 | throw $_ 63 | } 64 | finally 65 | { 66 | $timer.Stop() 67 | } 68 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-Empty-OUs.ps1: -------------------------------------------------------------------------------- 1 | $remove_ous = $false 2 | 3 | $ous_to_keep = @('UAP - PEAP TLS','UAP - PEAP TLS Only','Disabled Users'); 4 | 5 | $ad_objects = Get-ADObject -Filter "ObjectClass -eq 'user' -or ObjectClass -eq 'computer' -or ObjectClass -eq 'group' -or ObjectClass -eq 'organizationalUnit'"; 6 | 7 | $aOuDns = @(); 8 | foreach ($o in $ad_objects) { 9 | $sDn = $o.DistinguishedName; 10 | if ($sDn -like '*OU=*' -and $sDn -notlike '*LostAndFound*') { 11 | $sOuDn = $sDn.Substring($sDn.IndexOf('OU=')); 12 | $aOuDns += $sOuDn; 13 | }##endif 14 | }##endforeach 15 | 16 | $a0CountOus = $aOuDns | Group-Object | Where-Object { $_.Count -eq 1 } | % { $_.Name }; 17 | $empty_ous = 0; 18 | $ous_removed = 0; 19 | foreach ($sOu in $a0CountOus) { 20 | if (!(Get-ADObject -Filter "ObjectClass -eq 'organizationalUnit'" | where { $_.DistinguishedName -like "*$sOu*" -and $_.DistinguishedName -ne $sOu })) { 21 | $ou = Get-AdObject -Filter { DistinguishedName -eq $sOu }; 22 | if ($ous_to_keep -notcontains $ou.Name) { 23 | if ($remove_ous) { 24 | Set-ADOrganizationalUnit -Identity $ou.DistinguishedName -ProtectedFromAccidentalDeletion $false -confirm:$false; 25 | Remove-AdOrganizationalUnit -Identity $ou.DistinguishedName -confirm:$false 26 | $ous_removed++ 27 | }##endif 28 | $ou 29 | $empty_ous++; 30 | }##endif 31 | }##endif 32 | }##endforeach 33 | echo '-------------------' 34 | echo "Total Empty OUs Removed: $ous_removed" 35 | echo "Total Empty OUs: $empty_ous" -------------------------------------------------------------------------------- /ActiveDirectory/Get-LoggedOnUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-LoggedOnUser 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function queries CIM on the local or a remote computer and returns the user (local or Active Directory) that is currently 6 | logged on. 7 | 8 | .EXAMPLE 9 | PS> Get-LoggedOnUser 10 | 11 | This would query the local computer and return the user logged on. 12 | 13 | .EXAMPLE 14 | PS> Get-LoggedOnUser -ComputerName CLIENT 15 | 16 | This would query the remote computer CLIENT and return the user logged on. 17 | 18 | .PARAMETER ComputerName 19 | The name of the computer you'd like to run this function against. 20 | 21 | #> 22 | [OutputType([pscustomobject])] 23 | [CmdletBinding()] 24 | param 25 | ( 26 | [Parameter()] 27 | [ValidateNotNullOrEmpty()] 28 | [string[]]$ComputerName = $env:COMPUTERNAME 29 | ) 30 | begin 31 | { 32 | $ErrorActionPreference = 'Stop' 33 | } 34 | process 35 | { 36 | try 37 | { 38 | foreach ($comp in $ComputerName) 39 | { 40 | $output = @{ 41 | ComputerName = $comp 42 | UserName = 'Unknown' 43 | ComputerStatus = 'Offline' 44 | } 45 | if (Test-Connection -ComputerName $comp -Count 1 -Quiet) { 46 | $output.UserName = (Get-WmiObject -Class win32_computersystem -ComputerName $comp).UserName 47 | $output.ComputerStatus = 'Online' 48 | } 49 | [pscustomobject]$output 50 | } 51 | } 52 | catch 53 | { 54 | $PSCmdlet.ThrowTerminatingError($_) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Fun Stuff/Get-MoreCowbell.ps1: -------------------------------------------------------------------------------- 1 | function Get-MoreCowbell 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter()] 7 | [ValidateNotNullOrEmpty()] 8 | [switch]$Introduction, 9 | 10 | [Parameter()] 11 | [ValidateNotNullOrEmpty()] 12 | [int]$Repeat = 10, 13 | 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [string]$CowbellUrl = 'http://emmanuelprot.free.fr/Drums%20kit%20Manu/Cowbell.wav', 17 | 18 | [Parameter()] 19 | [ValidateNotNullOrEmpty()] 20 | [string]$IntroUrl = 'http://www.innervation.com/crap/cowbell.wav' 21 | 22 | 23 | ) 24 | begin { 25 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 26 | } 27 | process { 28 | try 29 | { 30 | $sound = new-Object System.Media.SoundPlayer 31 | $CowBellLoc = "$($env:TEMP)\Cowbell.wav" 32 | if (-not (Test-Path -Path $CowBellLoc -PathType Leaf)) 33 | { 34 | Invoke-WebRequest -Uri $CowbellUrl -OutFile $CowBellLoc 35 | } 36 | if ($Introduction.IsPresent) 37 | { 38 | $IntroLoc = "$($env:TEMP)\CowbellIntro.wav" 39 | if (-not (Test-Path -Path $IntroLoc -PathType Leaf)) 40 | { 41 | Invoke-WebRequest -Uri $IntroUrl -OutFile $IntroLoc 42 | } 43 | $sound.SoundLocation = $IntroLoc 44 | $sound.Play() 45 | sleep 2 46 | } 47 | $sound.SoundLocation = $CowBellLoc 48 | for ($i=0; $i -lt $Repeat; $i++) { 49 | $sound.Play(); 50 | Start-Sleep -Milliseconds 500 51 | } 52 | } 53 | catch 54 | { 55 | Write-Error $_.Exception.Message 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /DHCP/Get-DhcpLeasesInDomain.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module DhcpServer 2 | 3 | <# 4 | .SYNOPSIS 5 | This script finds all DHCP servers in Active Directory, all scopes on all DHCP servers 6 | and outputs all leases in all of those scopes 7 | .NOTES 8 | Created on: 12/10/2014 9 | Created by: Adam Bertram 10 | Filename: Get-DhcpLeasesInDomain.ps1 11 | .EXAMPLE 12 | PS> .\Get-DhcpLeasesInDomain.ps1 13 | 14 | #> 15 | [CmdletBinding()] 16 | [OutputType('Selected.Microsoft.Management.Infrastructure.CimInstance')] 17 | param () 18 | 19 | begin { 20 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 21 | Set-StrictMode -Version Latest 22 | } 23 | 24 | process { 25 | try { 26 | $DhcpServers = Get-DhcpServerInDC | where { Test-Connection -ComputerName $_.DnsName -Quiet -Count 1 } | Select-Object -ExpandProperty DnsName 27 | foreach ($DhcpServer in $DhcpServers) { 28 | try { 29 | try { $Scopes = Get-DhcpServerv4Scope -ComputerName $DhcpServer } catch {Write-Warning -Message "Error: $($_.Exception.Message)"} 30 | foreach ($Scope in $Scopes) { 31 | try { Get-DhcpServerv4Lease -ComputerName $DhcpServer -ScopeId $Scope.ScopeId | Select-Object * -ExcludeProperty 'Cim*' } catch { Write-Warning -Message "Error: $($_.Exception.Message)" } 32 | } 33 | } catch { 34 | Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 35 | } 36 | } 37 | } catch { 38 | Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 39 | } 40 | } -------------------------------------------------------------------------------- /Windows/RemoveEdgeDefaultForPDF.ps1: -------------------------------------------------------------------------------- 1 | # This script will check the registry for all file associations that might be set to open by default by Edge browser 2 | # For those who do not want Edge browser opening pdf files or anything else by default 3 | 4 | 5 | # Identify the edge application class 6 | $Packages = "HKCU:SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\Repository\Packages" 7 | $edge = Get-ChildItem $Packages -Recurse -include "MicrosoftEdge" 8 | 9 | # Specify the paths to the file and URL associations 10 | $FileAssocKey = Join-Path $edge.PSPath Capabilities\FileAssociations 11 | $URLAssocKey = Join-Path $edge.PSPath Capabilities\URLAssociations 12 | 13 | # get the software classes for the file and URL types that Edge will associate 14 | $FileTypes = Get-Item $FileAssocKey 15 | $URLTypes = Get-Item $URLAssocKey 16 | 17 | $FileAssoc = Get-ItemProperty $FileAssocKey 18 | $URLAssoc = Get-ItemProperty $URLAssocKey 19 | 20 | $Associations = @() 21 | $Filetypes.Property | foreach {$Associations += $FileAssoc.$_} 22 | $URLTypes.Property | foreach {$Associations += $URLAssoc.$_} 23 | 24 | # add registry values in each software class to stop edge from associating as the default 25 | foreach ($Association in $Associations) 26 | { 27 | $Class = Join-Path HKCU:SOFTWARE\Classes $Association 28 | #if (Test-Path $class) 29 | # {write-host $Association} 30 | # Get-Item $Class 31 | Set-ItemProperty $Class -Name NoOpenWith -Value "" 32 | Set-ItemProperty $Class -Name NoStaticDefaultVerb -Value "" 33 | } 34 | -------------------------------------------------------------------------------- /ActiveDirectory/Copy-AD-User-Account.ps1: -------------------------------------------------------------------------------- 1 | $samaccount_to_copy = 'abertram' 2 | $new_samaccountname = 'aaaa' 3 | $new_displayname = 'displayname' 4 | $new_firstname = 'firstname' 5 | $new_lastname = 'lastname' 6 | $new_name = 'namehere' 7 | $new_user_logon_name = 'logonname' 8 | $new_password = 'password' 9 | $new_description = 'description' 10 | $new_ou_DN = '' 11 | $enable_user_after_creation = $true 12 | $password_never_expires = $false 13 | $cannot_change_password = $false 14 | 15 | 16 | $ad_account_to_copy = Get-Aduser $samaccount_to_copy -Properties memberOf 17 | 18 | $params = @{'SamAccountName' = $new_samaccountname; 19 | 'Instance' = $ad_account_to_copy; 20 | 'DisplayName' = $new_displayname; 21 | 'GivenName' = $new_firstname; 22 | 'SurName' = $new_lastname; 23 | 'PasswordNeverExpires' = $password_never_expires; 24 | 'CannotChangePassword' = $cannot_change_password; 25 | 'Description' = $new_description; 26 | 'Enabled' = $enable_user_after_creation; 27 | 'UserPrincipalName' = $new_user_logon_name; 28 | 'AccountPassword' = (ConvertTo-SecureString -AsPlainText $new_password -Force); 29 | } 30 | 31 | ## Create the new user account 32 | New-ADUser -Name $new_name @params 33 | 34 | ## Mirror all the groups the original account was a member of 35 | $ad_account_to_copy.Memberof | % {Add-ADGroupMember $_ $new_samaccountname } 36 | 37 | ## Move the new user account into the assigned OU 38 | Get-ADUser $new_samaccountname| Move-ADObject -TargetPath $new_ou_DN -------------------------------------------------------------------------------- /java/cleanup.ps1: -------------------------------------------------------------------------------- 1 | $RegUninstallPaths = @( 2 | 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 3 | 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') 4 | $VersionsToKeep = @('Java 7 Update 5') 5 | 6 | Get-WmiObject Win32_Process | Where {$_.ExecutablePath -like '*Program FilesJava*'} | 7 | Select @{n='Name';e={$_.Name.Split('.')[0]}} | Stop-Process -Force 8 | 9 | get-process -Name *iexplore* | Stop-Process -Force -ErrorAction SilentlyContinue 10 | 11 | $UninstallSearchFilter = { ($_.GetValue('DisplayName') -like '*Java*') -and 12 | (($_.GetValue('Publisher') -eq 'Oracle') -or 13 | ($_.GetValue('Publisher') -eq 'Sun Microsystems, Inc.')) -and 14 | ($VersionsToKeep -notcontains $_.GetValue('DisplayName'))} 15 | 16 | foreach ($Path in $RegUninstallPaths) { 17 | if (Test-Path $Path) { 18 | Get-ChildItem $Path | Where $UninstallSearchFilter | 19 | Foreach { Start-Process 'C:\Windows\System32\msiexec.exe' "/x $($_.PSChildName) /qn" -Wait} 20 | } 21 | } 22 | 23 | New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null 24 | $ClassesRootPath = “HKCR:\InstallerProducts” 25 | Get-ChildItem $ClassesRootPath | 26 | Where { ($_.GetValue('ProductName') -like '*Java*7*') -or ($_.GetValue('ProductName') -like “Java*6*”)} | 27 | Foreach {Remove-Item $_.PsPath -Force -Recurse} 28 | 29 | 30 | $JavaSoftPath = 'HKLM:\SOFTWARE\JavaSoft' 31 | if (Test-Path $JavaSoftPath) { 32 | Remove-Item $JavaSoftPath -Force -Recurse 33 | } 34 | 35 | Remove-Item $env:ProgramfilesJava -Force -Recurse 36 | -------------------------------------------------------------------------------- /Software/Install-Software.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory)] 3 | [string[]]$Client, 4 | 5 | [Parameter(Mandatory)] 6 | [ValidateNotNullOrEmpty()] 7 | [string]$InstallerFilePath 8 | ) 9 | 10 | foreach ($c in $Client) { 11 | try { 12 | ## Perform numerous connection checks before copying everything over 13 | $clientMsg = "The client [$($c)] " 14 | if (-not (Test-Connection -ComputerName $c -Quiet -Count 1)) { 15 | throw "$clientMsg cannot be pinged" 16 | } elseif (-not (Test-Path "\\$c\c$")) { 17 | throw "$clientMsg 's admin share is unavailable" 18 | } else { 19 | Write-Verbose -Message "$clientMsg is ready to go!" 20 | } 21 | 22 | ## Copy the installer to the client 23 | Write-Verbose -Message "Copying installer to client..." 24 | Copy-Item -Path $InstallerFilePath -Destination "\\$c\c$" 25 | 26 | ## PS remoting connectivity needed to the client 27 | Write-Verbose -Message "Installing software on client..." 28 | Invoke-Command -ComputerName $c -ScriptBlock { 29 | $installerFileName = $using:InstallerFilePath | Split-Path -Leaf 30 | 31 | ## Execute the software installer 32 | Start-Process -NoNewWindow -Wait -FilePath "C:\$installerFileName" -ArgumentList '/silent /norestart' 33 | 34 | ## Cleanup what was copied to the client 35 | Remove-Item -Path "C:\$installerFileName" -Recurse 36 | } 37 | } catch { 38 | Write-Error -Message $_.Exception.Message 39 | } 40 | } -------------------------------------------------------------------------------- /RDP/Set-RdpSessionTimeout.ps1: -------------------------------------------------------------------------------- 1 | function Set-RdpSessionTimeout 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [string[]]$ComputerName, 9 | 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [ValidateSet('ActiveButIdle', 'Disconnected', 'Active')] 13 | [string]$SessionType, 14 | 15 | [Parameter(Mandatory)] 16 | [ValidateNotNullOrEmpty()] 17 | [ValidateRange(1, [int]::MaxValue)] 18 | [int]$Timeout, ## in seconds 19 | 20 | [Parameter()] 21 | [ValidateNotNullOrEmpty()] 22 | [pscredential]$Credential 23 | ) 24 | try 25 | { 26 | $baseRegKey = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' 27 | switch ($SessionType) 28 | { 29 | 'ActiveButIdle' { 30 | $valueName = 'MaxIdleTime' 31 | } 32 | 'Disconnected' { 33 | $valueName = 'MaxDisconnectionTime' 34 | } 35 | 'Active' { 36 | $valueName = 'MaxConnectionTime' 37 | } 38 | default 39 | { 40 | throw 'Unknown session type chosen.' 41 | } 42 | } 43 | $setParams = @{ 44 | 'Path' = $baseRegKey 45 | 'Name' = $valueName 46 | 'Value' = (($Timeout * 60) * 1000) 47 | } 48 | 49 | $icmParams = @{ 50 | 'ComputerName' = $ComputerName 51 | } 52 | if ($PSBoundParameters.ContainsKey('Credential')) 53 | { 54 | $icmParams.Credential = $Credential 55 | } 56 | Invoke-Command @icmParams -ScriptBlock { 57 | Set-ItemProperty @using:setParams 58 | Get-Service -Name termservice | Restart-Service -Force 59 | } 60 | } 61 | catch 62 | { 63 | $PSCmdlet.ThrowTerminatingError($_) 64 | } 65 | } -------------------------------------------------------------------------------- /Hyper-V/Remove-OnlineVM.ps1: -------------------------------------------------------------------------------- 1 | function Remove-OnlineVM 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function is a wrapper for the Hyper-V module's Remove-VM function gives you the option to force the VM 6 | to shutdown prior to removal. 7 | 8 | .PARAMETER VM 9 | A VM object from the Get-VM cmdlet that will be targeted to install Integaation Services on. 10 | 11 | .PARAMETER Server 12 | The Hyper-V host that the VM is running on. 13 | 14 | .PARAMETER Credential 15 | A optional PSCredential object to use if you'd like to authenticate with other credentials. 16 | 17 | .EXAMPLE 18 | PS> Get-VM SERVER1 | Remove-OnlineVM -Shutdown 19 | 20 | This example is shutting down the SERVER1 VM (if it's on) and then removes the VM. 21 | #> 22 | 23 | [CmdletBinding(SupportsShouldProcess)] 24 | param 25 | ( 26 | [Parameter(Mandatory, ValueFromPipeline)] 27 | [ValidateNotNullOrEmpty()] 28 | [Microsoft.HyperV.PowerShell.VirtualMachine[]]$VM, 29 | 30 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 31 | [ValidateNotNullOrEmpty()] 32 | [Alias('ComputerName')] 33 | [string]$Server, 34 | 35 | [Parameter()] 36 | [ValidateNotNullOrEmpty()] 37 | [pscredential]$Credential 38 | ) 39 | process 40 | { 41 | foreach ($v in $VM) 42 | { 43 | $vmName = $v.Name 44 | if ($PSCmdlet.ShouldProcess($vmName,'Remove VM')) 45 | { 46 | if ((Get-VM -ComputerName $Server -Name $vmName).State -eq 'Running') 47 | { 48 | Write-Verbose -Message "[$vmName)] is online. Shutting down now." 49 | $v | Stop-VM -Force 50 | } 51 | $v | Remove-VM -Force 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /PowerShell Internals/Get-WeekDay.ps1: -------------------------------------------------------------------------------- 1 | function Get-Weekday { 2 | <# 3 | .SYNOPSIS 4 | This function translate a loosely structured weekday reference to a structured Powershell 5 | [datetime] object. 6 | .PARAMETER DateReference 7 | An unstructured weekday string representing a date. Possible values are: 8 | 9 | $Weekday (ie. Monday, Tuesday, etc) - This will get the upcoming weekday 10 | next $Weekday (ie. Next Sunday, Next Tuesday, etc) - This will get the upcoming weekday 11 | last $Weekday (ie. Last Sunday, Last Tuesday, etc) - This will get the last weekday 12 | #> 13 | [CmdletBinding()] 14 | param ( 15 | [Parameter(Mandatory)] 16 | [ValidatePattern('sunday|monday|tuesday|wednesday|thursday|friday|saturday')] 17 | [string]$Weekday 18 | ) 19 | process { 20 | try { 21 | $Weekday = $Weekday.ToLower() 22 | ## Use regex in case user specified 'last' or 'next' 23 | $DesiredWeekDay = [regex]::Matches($Weekday, 'sunday|monday|tuesday|wednesday|thursday|friday|saturday').Value 24 | $Today = (Get-Date).Date 25 | if ($Weekday -match 'next') { 26 | ## The user wants next week's weekday 27 | $Range = 1..7 28 | } elseif ($Weekday -match 'last') { 29 | ## The user wants last week's weekday 30 | $Range = -1.. - 7 31 | } else { 32 | ## The user didn't specify so assuming they just want the upcoming weekday 33 | $Range = 1..7 34 | } 35 | $Range | foreach { 36 | $Day = $Today.AddDays($_); 37 | if ($Day.DayOfWeek -eq $DesiredWeekDay) { 38 | $Day.Date 39 | } 40 | } 41 | } catch { 42 | Write-Error $_.Exception.Message 43 | $false 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /User Profiles/Get-UserProfilePath.ps1: -------------------------------------------------------------------------------- 1 | function Get-UserProfilePath 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function find the folder path of a user profile based off of a number of different criteria. If no criteria is 6 | used, it will return all user profile paths. 7 | .EXAMPLE 8 | PS> .\Get-UserProfilePath -Sid 'S-1-5-21-350904792-1544561288-1862953342-32237' 9 | 10 | This example finds the user profile path based on the user's SID 11 | .EXAMPLE 12 | PS> .\Get-UserProfilePath -Username 'bob' 13 | 14 | This example finds the user profile path based on the username 15 | .PARAMETER Sid 16 | The user SID 17 | .PARAMETER Username 18 | The username 19 | #> 20 | [OutputType([string])] 21 | [CmdletBinding(DefaultParameterSetName = 'None')] 22 | param ( 23 | [Parameter(ParameterSetName = 'SID')] 24 | [string]$Sid, 25 | 26 | [Parameter(ParameterSetName = 'Username')] 27 | [string]$Username 28 | ) 29 | 30 | process 31 | { 32 | try 33 | { 34 | if ($Sid) 35 | { 36 | $WhereBlock = { $_.PSChildName -eq $Sid } 37 | } 38 | elseif ($Username) 39 | { 40 | $WhereBlock = { $_.GetValue('ProfileImagePath').Split('\')[-1] -eq $Username } 41 | } 42 | else 43 | { 44 | $WhereBlock = { $null -ne $_.PSChildName } 45 | } 46 | Get-ChildItem 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList' | Where-Object $WhereBlock | ForEach-Object { $_.GetValue('ProfileImagePath') } 47 | } 48 | catch 49 | { 50 | Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3' 51 | $PSCmdlet.ThrowTerminatingError($_) 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Group Policy/User Logon Scripts/Set-WinProfilePhotoFromAD.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | AD Photo to Windows Profile Photo Logon Script 3 | Dylan Bickerstaff - 2021 4 | ---------------------------------------------- 5 | This script retrieves the "thumbnailPhoto" 6 | LDAP attribute from Active Directory and sets 7 | the Windows 10 user profile picture to it. 8 | ---------------------------------------------- 9 | To use this script, create a GPO policy that 10 | runs this script at logon under the logged 11 | on user's context. Then create a computer 12 | security policy that allows "Everyone" full 13 | control on the following registry key: 14 | HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users 15 | #> 16 | 17 | $storePath = "C:\ProgramData\ADAccountPhotos\" 18 | 19 | $pVals = 20 | "Image1080", 21 | "Image192", 22 | "Image208", 23 | "Image240", 24 | "Image32", 25 | "Image40", 26 | "Image424", 27 | "Image448", 28 | "Image48", 29 | "Image64", 30 | "Image96" 31 | 32 | $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value 33 | $search = [System.DirectoryServices.DirectorySearcher]::new("objectSid=$sid") 34 | $result = $search.FindOne() 35 | $_ = New-Item -Path "$($storePath)$($sid)\" -ItemType Directory -Force 36 | [System.IO.File]::WriteAllBytes("$($storePath)$($sid)\photo.jpg", $($result.Properties.thumbnailphoto)) 37 | 38 | $key = New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\$sid" -Force 39 | foreach($val in $pVals) { 40 | $_ = New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\$sid" -Name $val -Value "$($storePath)$($sid)\photo.jpg" -Force 41 | } -------------------------------------------------------------------------------- /TFS/TFSClientFunctions.ps1: -------------------------------------------------------------------------------- 1 | function Add-ItemToTfs 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [ValidateScript({ Test-Path -Path $_ })] 9 | [string]$ItemPath, 10 | 11 | [Parameter()] 12 | [ValidateNotNullOrEmpty()] 13 | [ValidateScript({ Test-Path -Path $_ -PathType Leaf })] 14 | [string]$tfFilePath = 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe' 15 | 16 | ) 17 | $ErrorActionPreference = 'Stop' 18 | try 19 | { 20 | Write-Verbose -Message "Adding the item [$($Itempath)] into TFS" 21 | 22 | $null = & $tfFilePath add $Itempath 23 | 24 | if (Test-Path -Path $ItemPath -PathType Container) 25 | { 26 | ## Add the files inside the folder 27 | Get-ChildItem -Path $Itempath | ForEach-Object { $null = & $tfFilePath add $_.FullName } 28 | } 29 | } 30 | catch 31 | { 32 | Write-Error $_.Exception.Message 33 | } 34 | } 35 | 36 | function Submit-TfsChange 37 | { 38 | [CmdletBinding()] 39 | param 40 | ( 41 | [Parameter(Mandatory)] 42 | [ValidateNotNullOrEmpty()] 43 | [ValidateScript({ Test-Path -Path $_ })] 44 | [string]$ItemPath, 45 | 46 | [Parameter()] 47 | [ValidateNotNullOrEmpty()] 48 | [string]$Comment = 'New Checkin', 49 | 50 | [Parameter()] 51 | [ValidateNotNullOrEmpty()] 52 | [ValidateScript({ Test-Path -Path $_ -PathType Leaf })] 53 | [string]$tfFilePath = 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe' 54 | ) 55 | try 56 | { 57 | Write-Verbose -Message "Checking in [$($Itempath)] to TFS" 58 | $null = & $tfFilePath checkin $Itempath /recursive /comment:$Comment 59 | } 60 | catch 61 | { 62 | Write-Error $_.Exception.Message 63 | } 64 | } -------------------------------------------------------------------------------- /DSC/SetupDscPullServer.ps1: -------------------------------------------------------------------------------- 1 | configuration NewPullServer { 2 | param ( 3 | [string[]]$ComputerName = ‘localhost’ 4 | ) 5 | 6 | Import-DSCResource -ModuleName xPSDesiredStateConfiguration 7 | 8 | Node $ComputerName { 9 | WindowsFeature DSCServiceFeature { 10 | Ensure = “Present” 11 | Name = “DSC-Service” 12 | } 13 | 14 | xDscWebService PSDSCPullServer { 15 | Ensure = “Present” 16 | EndpointName = “PSDSCPullServer” 17 | Port = 8080 18 | PhysicalPath = “$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer” 19 | CertificateThumbPrint = “AllowUnencryptedTraffic” 20 | ModulePath = “$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules” 21 | ConfigurationPath = “$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration” 22 | State = “Started” 23 | DependsOn = “[WindowsFeature]DSCServiceFeature” 24 | } 25 | 26 | xDscWebService PSDSCComplianceServer { 27 | Ensure = “Present” 28 | EndpointName = “PSDSCComplianceServer” 29 | Port = 9080 30 | PhysicalPath = “$env:SystemDrive\inetpub\wwwroot\PSDSCComplianceServer” 31 | CertificateThumbPrint = “AllowUnencryptedTraffic” 32 | State = “Started” 33 | IsComplianceServer = $true 34 | DependsOn = (“[WindowsFeature]DSCServiceFeature”,”[xDSCWebService]PSDSCPullServer”) 35 | } 36 | } 37 | } 38 | 39 | NewPullServer -------------------------------------------------------------------------------- /User Profiles/Invoke-UserLogoff.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.0 5 | 6 | .GUID 947c787b-1e06-4937-8022-1d3d39f267b0 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | .PRIVATEDATA 32 | 33 | #> 34 | 35 | <# 36 | 37 | .DESCRIPTION 38 | A simple script to remotely log off users from one or more remote computers. 39 | 40 | #> 41 | 42 | [OutputType('void')] 43 | [CmdletBinding(SupportsShouldProcess)] 44 | param 45 | ( 46 | [Parameter()] 47 | [ValidateNotNullOrEmpty()] 48 | [string[]]$ComputerName, 49 | 50 | [Parameter()] 51 | [ValidateNotNullOrEmpty()] 52 | [string]$UserName 53 | ) 54 | 55 | $ErrorActionPreference = 'Stop' 56 | 57 | if (-not $PSBoundParameters.ContainsKey('ComputerName')) { 58 | $ComputerName = 'localhost' 59 | } 60 | 61 | foreach ($c in $ComputerName) { 62 | ## Find the user's session ID 63 | $compArgs = $null 64 | if ($PSBoundParameters.ContainsKey('ComputerName')) { 65 | $compArgs = "/server:$c" 66 | } 67 | $whereFilter = { '*' } 68 | if ($PSBoundParameters.ContainsKey('UserName')) { 69 | $whereFilter = [scriptblock]::Create("`$_ -match '$UserName'") 70 | } 71 | if ($sessions = ((quser $compArgs | Where-Object $whereFilter))) { 72 | $sessionIds = ($sessions -split ' +')[2] 73 | if ($PSCmdlet.ShouldProcess("UserName: $UserName", 'Logoff')) { 74 | $sessionIds | ForEach-Object { 75 | logoff $_ $compArgs 76 | } 77 | } 78 | } else { 79 | Write-Verbose -Message 'No users found matching criteria found.' 80 | } 81 | } -------------------------------------------------------------------------------- /SQL/BackupAllDB/sp.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | sp_configure 'show advanced options', '1' 4 | RECONFIGURE 5 | GO 6 | sp_configure 'xp_cmdshell', '1' 7 | RECONFIGURE 8 | GO 9 | 10 | CREATE PROCEDURE usp_backup 11 | @path VARCHAR(400), @retentionperiod TINYINT 12 | AS 13 | SET NOCOUNT ON 14 | DECLARE @date VARCHAR(100) 15 | DECLARE @dbname VARCHAR(50) 16 | DECLARE @bkup VARCHAR(500) 17 | DECLARE @retention VARCHAR(500) 18 | 19 | --Adding backslash 20 | IF SUBSTRING(REVERSE(@path),1,1) <> '\' 21 | SET @path=@path + '\' 22 | 23 | --Retention 24 | SET @date= CONVERT(VARCHAR(10),GETDATE()-@retentionperiod,112) 25 | SET @retention='EXEC master.dbo.xp_cmdshell ''dir /b "' +@path+'*'+@date+'*.bak"''' 26 | EXEC (@retention) 27 | 28 | SET @retention='EXEC master.dbo.xp_cmdshell ''del /Q "' +@path+'*'+@date+'*.bak"''' 29 | EXEC (@retention) 30 | 31 | --Backup Script 32 | SET @date= CONVERT(VARCHAR(10),GETDATE(),112) 33 | 34 | DECLARE bkup_cursor CURSOR FOR 35 | SELECT NAME FROM master.dbo.sysdatabases WHERE dbid <> 2 and DATABASEPROPERTYEX(name,'status') = 'ONLINE' 36 | and name NOT IN ('master','model','msdb','tempdb','ReportServer','ReportServerTempDB') 37 | 38 | OPEN bkup_cursor 39 | FETCH NEXT FROM bkup_cursor INTO @dbname 40 | 41 | IF @@FETCH_STATUS <> 0 42 | PRINT 'No database to backup...!!' 43 | 44 | WHILE @@FETCH_STATUS = 0 45 | BEGIN 46 | SET @bkup='BACKUP DATABASE ['+@dbname+'] TO DISK = '''+@path+@dbname+'_'+@date+'.bak'' WITH INIT' 47 | PRINT 'Processing '+@dbname+' Backup... **' 48 | EXEC (@bkup) 49 | PRINT 'Backed up to ' + @path+@dbname+'_'+@date+'.bak' 50 | PRINT '' 51 | 52 | FETCH NEXT FROM bkup_cursor INTO @dbname 53 | END 54 | 55 | CLOSE bkup_cursor 56 | DEALLOCATE bkup_cursor 57 | -------------------------------------------------------------------------------- /PowerShell Internals/PSRemoting.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | 3 | function Test-PsRemoting { 4 | <# 5 | .SYNOPSIS 6 | This function tests if PS remoting is enabled on a remote computer and (if used) will attempt 7 | to connect with a local username and password. 8 | .PARAMETER Computername 9 | The remote computer name 10 | .PARAMETER LocalCredential 11 | An optional credential object representing the remote computer's local username and password 12 | .PARAMETER DomainCredential 13 | If the remote computer and the executing computer are both domain-joined, this is an optional 14 | credential object representing a domain username and password to test against. By default, it 15 | will test against the currently logged on user. 16 | #> 17 | [CmdletBinding(DefaultParameterSetName = 'None')] 18 | param ( 19 | [Parameter(Mandatory, 20 | ValueFromPipeline, 21 | ValueFromPipelineByPropertyName)] 22 | [string[]]$Computername, 23 | [Parameter(Mandatory,ParameterSetName = 'LocalCredential')] 24 | [System.Management.Automation.PSCredential]$LocalCredential, 25 | [Parameter(Mandatory, ParameterSetName = 'DomainCredential')] 26 | [System.Management.Automation.PSCredential]$DomainCredential 27 | ) 28 | process { 29 | foreach ($Computer in $Computername) { 30 | try { 31 | if (!$LocalCredential -and !$DomainCredential) { 32 | ## Test remoting under the currently logged on user 33 | Invoke-Command -ComputerName $Computer -ScriptBlock { 1 } 34 | $true 35 | } elseif ($LocalCredential) { ## Test remoting with a local username and password 36 | 37 | } else { ## Test remoting with a domain username and password 38 | 39 | } 40 | } catch { 41 | [pscustomobject]@{ 'Computer' = $Computer; 'Result' = $false; 'Error' = $_.Exception.Message } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /SCCM/Connect-CmRemoteTools.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This script calls the SCCM console's remote tools clients (CmRcViewer.exe) to start a SCCM 4 | remote tools console from Powershell. 5 | .NOTES 6 | Created on: 12/9/2014 7 | Created by: Adam Bertram 8 | Filename: Connect-CmRemoteTools.ps1 9 | Requirements: An available SCCM 2012 site server and the SCCM console installed 10 | Permissions to connect to the remote computer 11 | .EXAMPLE 12 | PS> .\Connect-CmRemoteTools.ps1 -Computername MYCOMPUTER 13 | 14 | This example would bring up the SCCM remote tools console window connecting to the computer called MYCOMPUTER 15 | .PARAMETER Computername 16 | The name of the computer you'd like to use remote tools to connect to 17 | .PARAMETER 18 | The name of the SCCM site server holding the site database 19 | #> 20 | [CmdletBinding()] 21 | param ( 22 | [Parameter(Mandatory, 23 | ValueFromPipeline, 24 | ValueFromPipelineByPropertyName)] 25 | [ValidateScript({Test-Connection -ComputerName $_ -Quiet -Count 1})] 26 | [string]$Computername, 27 | [ValidateScript({ Test-Connection -ComputerName $_ -Quiet -Count 1 })] 28 | [string]$SiteServer = 'CONFIGMANAGER' 29 | ) 30 | 31 | begin { 32 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 33 | Set-StrictMode -Version Latest 34 | } 35 | 36 | process { 37 | try { 38 | ## Find the path of the admin console to get the path of the remote tools client 39 | if (!$env:SMS_ADMIN_UI_PATH -or !(Test-Path "$($env:SMS_ADMIN_UI_PATH)\CmRcViewer.exe")) { 40 | throw "Unable to find the SCCM remote tools exe. Is the console installed?" 41 | } else { 42 | $RemoteToolsFilePath = "$($env:SMS_ADMIN_UI_PATH)\CmRcViewer.exe" 43 | } 44 | 45 | & $RemoteToolsFilePath $Computername "\\$SiteServer" 46 | 47 | } catch { 48 | Write-Error $_.Exception.Message 49 | } 50 | } -------------------------------------------------------------------------------- /Random Stuff/Get-Weather.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 4 2 | 3 | function Get-WeatherForecast 4 | { 5 | [OutputType([pscustomobject])] 6 | [CmdletBinding()] 7 | param 8 | ( 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [ValidatePattern('^\d{5}$')] 12 | [int]$ZipCode, 13 | 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [int]$DaysOut = 7 17 | ) 18 | begin 19 | { 20 | $ErrorActionPreference = 'Stop' 21 | } 22 | process 23 | { 24 | try 25 | { 26 | $uri = 'http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl' 27 | $proxy = New-WebServiceProxy -uri $uri -namespace WebServiceProxy 28 | $latlon = $proxy.LatLonListZipCode($ZipCode) 29 | @($latlon).foreach({ 30 | $l = $_ 31 | $a = $l.dwml.latlonlist -split ',' 32 | $lat = $a[0] 33 | $lon = $a[1] 34 | $now = get-date -UFormat %Y-%m-%d 35 | $format = 'Item24hourly' 36 | $weather = $Proxy.NDFDgenByDay($lat,$lon,$now,$DaysOut,$format) 37 | for ($i = 0 ; $i -le $DaysOut - 1; $i++) { 38 | [pscustomobject]@{ 39 | “Date” = ((Get-Date).addDays($i)).tostring(“MM/dd/yyyy”) ; 40 | “maxTemp” = $weather.dwml.data.parameters.temperature[0].value[$i] ; 41 | “minTemp” = $weather.dwml.data.parameters.temperature[1].value[$i] ; 42 | “Summary” = $weather.dwml.data.parameters.weather.”weather-conditions”[$i].”Weather-summary” 43 | } 44 | } 45 | }) 46 | } 47 | catch 48 | { 49 | $PSCmdlet.ThrowTerminatingError($_) 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /TFS/New-TfsBuildTask.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][string]$FolderPath, 3 | [Parameter(Mandatory=$true)][string]$TfsUrl, 4 | [PSCredential]$Credential = (Get-Credential), 5 | [switch]$Overwrite = $false 6 | ) 7 | 8 | param( 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | [ValidateScript({ 12 | if (-not (Test-Path -Path $_ -PathType Container)) { 13 | throw "The folder '$($_)' is not available" 14 | } 15 | if (-not (Test-Path -Path "$_\task.json" -PathType Leaf)) { 16 | throw "The file task.json was not found inside of folder '$_'" 17 | } 18 | $true 19 | 20 | })] 21 | [string]$FolderPath 22 | ) 23 | 24 | function ZipFile { 25 | param($FolderPath) 26 | 27 | } 28 | 29 | # Load task definition from the JSON file 30 | $taskDefinition = (Get-Content $FolderPath\task.json) -join "`n" | ConvertFrom-Json 31 | 32 | # Zip the task content 33 | Write-Verbose 'Zipping task content...' 34 | $taskZipFilePath = ("{0}\..\{1}.zip" -f $FolderPath, $taskDefinition.id) 35 | Remove-Item $taskZipFilePath -ErrorAction SilentlyContinue 36 | 37 | Add-Type -AssemblyName "System.IO.Compression.FileSystem" 38 | [IO.Compression.ZipFile]::CreateFromDirectory($taskFolder, $taskZipFilePath) 39 | 40 | # Prepare to upload the task 41 | Write-Verbose "Uploading task content" 42 | $headers = @{ "Accept" = "application/json; api-version=2.0-preview"; "X-TFS-FedAuthRedirect" = "Suppress" } 43 | $taskZipItem = Get-Item $taskZip 44 | $headers.Add("Content-Range", "bytes 0-$($taskZipItem.Length - 1)/$($taskZipItem.Length)") 45 | $url = ("{0}/_apis/distributedtask/tasks/{1}" -f $TfsUrl, $taskDefinition.id) 46 | if ($Overwrite) { 47 | $url += "?overwrite=true" 48 | } 49 | 50 | # Actually upload it 51 | Invoke-RestMethod -Uri $url -Credential $Credential -Headers $headers -ContentType application/octet-stream -Method Put -InFile $taskZipItem 52 | -------------------------------------------------------------------------------- /Azure/Save-AzrWebApp.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module PSWebDeploy 2 | #requires -Version 4 3 | 4 | function Save-AzrWebApp 5 | { 6 | <# 7 | .SYNOPSIS 8 | This function saves all of the contents of an Azure web app to a local folder. 9 | 10 | .EXAMPLE 11 | PS> $publishSettings = Get-AzrWebAppPublishInfo -Name 'BDT002-biq' -ResourceGroup 'BDT002' 12 | PS> $msDeploySettings = @($publishSettings).where({ $_.publishMethod -eq 'MSDeploy' }) 13 | PS> $cred = New-Credential -UserName $msDeploySettings.userName -Password $msDeploySettings.userPWD 14 | PS> Save-AzrWebApp -Name bdt002-biq -TargetPath C:\WebAppDownloaded -Credential $cred 15 | 16 | .PARAMETER Name 17 | A mandatory string parameter representing the name of the Azure app service. To retrieve all available web apps 18 | use Get-AzureRmWebApp. 19 | .PARAMETER TargetPath 20 | A mandatory string parameter representing the local folder path. This folder must exist. 21 | 22 | .PARAMETER Credential 23 | A mandatory pscredential parameter containing the username and password with permission to read the web app's 24 | file contents via msdeploy. 25 | #> 26 | [OutputType([System.IO.FileInfo])] 27 | [CmdletBinding()] 28 | param 29 | ( 30 | [Parameter(Mandatory)] 31 | [ValidateNotNullOrEmpty()] 32 | [string]$Name, 33 | 34 | [Parameter(Mandatory)] 35 | [ValidateNotNullOrEmpty()] 36 | [string]$TargetPath, 37 | 38 | [Parameter(Mandatory)] 39 | [ValidateNotNullOrEmpty()] 40 | [pscredential]$Credential 41 | ) 42 | try 43 | { 44 | $syncParams = @{ 45 | SourcePath = 'wwwroot' 46 | TargetPath = $TargetPath 47 | ComputerName = "https://$Name.scm.azurewebsites.net:443/msdeploy.axd?site=$Name" 48 | Credential = $Credential 49 | 50 | } 51 | Sync-Website @syncParams 52 | Get-Item -Path $TargetPath 53 | } 54 | catch 55 | { 56 | $PSCmdlet.ThrowTerminatingError($_) 57 | } 58 | } -------------------------------------------------------------------------------- /DNS/Convert-DynamicDnsRecordToStatic.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | 4 | .NOTES 5 | Created on: 8/22/2014 6 | Created by: Adam Bertram 7 | Filename: 8 | Credits: 9 | Requirements: 10 | Todos: 11 | .EXAMPLE 12 | 13 | .EXAMPLE 14 | 15 | .PARAMETER PARAM1 16 | 17 | .PARAMETER PARAM2 18 | 19 | #> 20 | [CmdletBinding(DefaultParameterSetName = 'name')] 21 | [OutputType('System.Management.Automation.PSCustomObject')] 22 | param ( 23 | [Parameter(ParameterSetName = 'name', 24 | Mandatory, 25 | ValueFromPipeline, 26 | ValueFromPipelineByPropertyName)] 27 | [ValidateSet("Tom","Dick","Jane")] 28 | [ValidateRange(21,65)] 29 | [ValidateScript({Test-Path $_ -PathType 'Container'})] 30 | [ValidateNotNullOrEmpty()] 31 | [ValidateCount(1,5)] 32 | [ValidateLength(1,10)] 33 | [ValidatePattern()] 34 | [string]$Computername = 'DEFAULTVALUE' 35 | ) 36 | 37 | begin { 38 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 39 | Set-StrictMode -Version Latest 40 | try { 41 | 42 | } catch { 43 | Write-Error $_.Exception.Message 44 | } 45 | } 46 | 47 | process { 48 | try { 49 | Get-DnsServerResourceRecord -ComputerName dc01 -ZoneName domain.com | where { ($_.HostName -match '^U.*XA65') -and ($_.Hostname -notmatch 'VM') -and ($_.Hostname -notmatch '.domain.com$') } | select @{ n = 'Hostname'; e = { $_.Hostname } }, @{n = 'IpAddres s'; e = { $_.RecordData.IPv4Address.IPAddressToString } } 50 | $CitrixRecords | select -Skip 1 | % { try { Add-DnsServerResourceRecord -ZoneName domain.com -ComputerName dc01 -IPv4Address $_.IpAddress -Name $_.Hostname -A } catch { } } 51 | $CitrixRecords | % { Get-DnsServerResourceRecord -ComputerName dc01 -Name $_.Hostname -RRType A -ZoneName domain.com } 52 | 53 | } catch { 54 | Write-Error $_.Exception.Message 55 | } 56 | } 57 | 58 | end { 59 | try { 60 | 61 | } catch { 62 | Write-Error $_.Exception.Message 63 | } 64 | } -------------------------------------------------------------------------------- /Configuration Mangaement/Set-ServiceAccount.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Changes the account a service runs under 4 | .NOTES 5 | Created on: 11/28/2014 6 | Created by: Adam Bertram 7 | Filename: Set-ServiceAccount.ps1 8 | .EXAMPLE 9 | PS> .\Set-ServiceAccount.ps1 -ServiceName 'snmp' -Computername 'COMPUTER1','COMPUTER2' -Username someuser -Password password12 10 | 11 | This example changes the account the service snmp runs under to someuser on the computers COMPUTER1 and COMPUTER2 12 | .PARAMETER ServiceName 13 | One or more service names 14 | .PARAMETER Computername 15 | One or more remote computer names. This script defaults to the local computer. 16 | .PARAMETER Username 17 | The username to change on the service 18 | .PARAMETER Password 19 | The password of the username 20 | #> 21 | [CmdletBinding()] 22 | param ( 23 | [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] 24 | [string[]]$ServiceName, 25 | [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] 26 | [ValidateScript({Test-Connection -ComputerName $_ -Quiet -Count 1 })] 27 | [string[]]$Computername = 'localhost', 28 | [Parameter(Mandatory)] 29 | [string]$Username, 30 | [Parameter(Mandatory)] 31 | [string]$Password 32 | ) 33 | 34 | process { 35 | foreach ($Computer in $Computername) { 36 | foreach ($Service in $ServiceName) { 37 | try { 38 | Write-Verbose -Message "Changing service '$Service' on the computer '$Computer'" 39 | $s = Get-WmiObject -ComputerName $Computer -Class Win32_Service -Filter "Name = '$Service'" 40 | if (!$s) { 41 | throw "The service '$Service' does not exist" 42 | } 43 | $s.Change($null, $null, $null, $null, $null, $null, $Username, $Password) | Out-Null 44 | $s | Restart-Service -Force 45 | } catch { 46 | Write-Error -Message "Error: Computer: $Computer - Service: $Service - Error: $($_.Exception.Message)" 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-GPOs-Linked-To-Empty-OUs.ps1: -------------------------------------------------------------------------------- 1 | function convertDsnToPathFormat($sDsn) { 2 | $sDsn = $sDsn.Replace(',',''); 3 | $sDsn = $sDsn.Replace('OU=',''); 4 | $aDsn = $sDsn.Split(','); 5 | [array]::Reverse($aDsn); 6 | $sPath = $aDsn -join '/'; 7 | return '/' + $sPath; 8 | }##endfunction 9 | 10 | $aAllGpos = Get-GPOReport -all -ReportType XML; 11 | $aFilteredGpos = @(); 12 | $aLinkedOuGPos = @(); 13 | foreach ($xGpo in $aAllGpos) { 14 | $xGpo = ([xml]$xGpo).GPO; 15 | if (Test-Member $xGpo 'LinksTo') { ## GPO links to at least one OU 16 | $sGpoName = $xGpo.Name; 17 | if ($xGpo.LinksTo -is [array]) { ## Links to more than on OU 18 | $aLinkedOus = $xGpo.LinksTo | Select-Object SOMPath | % { $_.SOMPath } 19 | } else { 20 | $aLinkedOus = , @($xGpo.LinksTo.SOMPath); 21 | }##endif 22 | $aLinkedOuGPos += , @($sGpoName,$aLinkedOus); 23 | }##endif 24 | }##endforeach 25 | 26 | $aObjects = Get-ADObject -Filter "ObjectClass -eq 'user' -or ObjectClass -eq 'computer' -or ObjectClass -eq 'group' -or ObjectClass -eq 'organizationalUnit'"; 27 | 28 | $aOuDns = @(); 29 | foreach ($o in $aObjects) { 30 | $sDn = $o.DistinguishedName; 31 | if ($sDn -like '*OU=*') { 32 | $sOuDn = $sDn.Substring($sDn.IndexOf('OU=')); 33 | $aOuDns += $sOuDn; 34 | }##endif 35 | }##endforeach 36 | 37 | $a0CountOus = $aOuDns | Group-Object | Where-Object { $_.Count -eq 1 } | % { $_.Name }; 38 | $aFiltered0CountOUs = @(); 39 | foreach ($sOu in $a0CountOus) { 40 | if (!(Get-ADObject -Filter "ObjectClass -eq 'organizationalUnit'" | where { $_.DistinguishedName -like "*$sOu*" -and $_.DistinguishedName -ne $sOu })) { 41 | $aFiltered0CountOUs += convertDsnToPathFormat $sOu; 42 | }##endif 43 | }##endforeach 44 | 45 | foreach ($aGpo in $aLinkedOuGpos) { 46 | foreach ($i in $aFiltered0CountOUs) { 47 | if (($aGpo[1] -contains $i) -and ($aGpo[1] -notcontains '')) { 48 | $aGpo[0]; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /PowerShell Internals/Get-WeekdayFrom.ps1: -------------------------------------------------------------------------------- 1 | function Get-WeekdayFrom { 2 | <# 3 | .SYNOPSIS 4 | This function translate a loosely structured weekday reference to a structured Powershell 5 | [datetime] object. 6 | .PARAMETER Weekday 7 | An unstructured weekday string representing a date. Possible values are: 8 | 9 | $Weekday (ie. Monday, Tuesday, etc) - This will get the upcoming weekday 10 | next $Weekday (ie. Next Sunday, Next Tuesday, etc) - This will get the upcoming weekday 11 | last $Weekday (ie. Last Sunday, Last Tuesday, etc) - This will get the last weekday 12 | 13 | .PARAMETER FromDate 14 | A [datetime] object. Used to provide the desired weekday result relative to the date 15 | provided. 16 | #> 17 | [CmdletBinding()] 18 | param ( 19 | [Parameter(Mandatory)] 20 | [ValidatePattern('sunday|monday|tuesday|wednesday|thursday|friday|saturday')] 21 | [string]$Weekday, 22 | [datetime]$FromDate 23 | ) 24 | process { 25 | try { 26 | $Weekday = $Weekday.ToLower() 27 | ## Use regex in case user specified 'last' or 'next' 28 | $DesiredWeekDay = [regex]::Matches($Weekday, 'sunday|monday|tuesday|wednesday|thursday|friday|saturday').Value 29 | if ($FromDate) { 30 | $Today = (Get-Date -Date "$fromDate").Date 31 | } else { 32 | $Today = (Get-Date).Date 33 | } 34 | if ($Weekday -match 'next') { 35 | ## The user wants next week's weekday 36 | $Range = 1..7 37 | } elseif ($Weekday -match 'last') { 38 | ## The user wants last week's weekday 39 | $Range = -1.. - 7 40 | } else { 41 | ## The user didn't specify so assuming they just want the upcoming weekday 42 | $Range = 1..7 43 | } 44 | $Range | foreach { 45 | $Day = $Today.AddDays($_); 46 | if ($Day.DayOfWeek -eq $DesiredWeekDay) { 47 | $Day.Date 48 | } 49 | } 50 | } catch { 51 | Write-Error $_.Exception.Message 52 | $false 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /IIS/New-IISWebBinding.ps1: -------------------------------------------------------------------------------- 1 | function New-IISWebBinding 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [string]$ComputerName, 9 | 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [string]$WebsiteName, 13 | 14 | [Parameter(Mandatory)] 15 | [ValidateNotNullOrEmpty()] 16 | [ValidateSet('http', 'https')] 17 | [string]$Protocol, 18 | 19 | [Parameter(Mandatory)] 20 | [ValidateNotNullOrEmpty()] 21 | [int]$Port, 22 | 23 | [Parameter()] 24 | [ValidateNotNullOrEmpty()] 25 | [ipaddress]$IPAddress = '0.0.0.0', ## Default to accepting on all bound IPs 26 | 27 | [Parameter()] 28 | [ValidateNotNullOrEmpty()] 29 | [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, 30 | 31 | [Parameter()] 32 | [ValidateNotNullOrEmpty()] 33 | [pscredential]$Credential 34 | ) 35 | process 36 | { 37 | try 38 | { 39 | $IPAddress = $IPAddress.IPAddressToString 40 | $iisIp = $IPAddress 41 | if ($IPAddress -eq '0.0.0.0') 42 | { 43 | $iisIp = '*' 44 | } 45 | 46 | $sb = { 47 | Import-Module WebAdministration 48 | if (Get-WebBinding -Protocol $using:Protocol -Port $Port) 49 | { 50 | throw "There's already a binding with the protocol of [$($using:Protocol)] and port [$($using:Port)]" 51 | } 52 | New-WebBinding -Name $using:WebsiteName -IP $using:iisIp -Port $using:Port -Protocol $using:Protocol 53 | if ($using:Protocol -eq 'https') 54 | { 55 | $using:Certificate | New-Item "IIS:\SSLBindings\$using:IPAddress!$using:Port" 56 | } 57 | } 58 | 59 | $icmParams = @{ 60 | 'ComputerName' = $ComputerName 61 | 'ScriptBlock' = $sb 62 | } 63 | if ($PSBoundParameters.ContainsKey('Credential')) 64 | { 65 | $icmParams.Credential = $Credential 66 | } 67 | Invoke-Command @icmParams 68 | } 69 | catch 70 | { 71 | throw $_ 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Exchange/Get-AllRules-Forwarding.ps1: -------------------------------------------------------------------------------- 1 | $domains = Get-AcceptedDomain 2 | $mailboxes = Get-Mailbox -ResultSize Unlimited 3 | 4 | foreach ($mailbox in $mailboxes) { 5 | 6 | $forwardingRules = $null 7 | Write-Host "Checking rules for $($mailbox.displayname) - $($mailbox.primarysmtpaddress)" -foregroundColor Green 8 | $rules = get-inboxrule -Mailbox $mailbox.primarysmtpaddress 9 | 10 | $forwardingRules = $rules | Where-Object {$_.forwardto -or $_.forwardasattachmentto} 11 | 12 | foreach ($rule in $forwardingRules) { 13 | $recipients = @() 14 | $recipients = $rule.ForwardTo | Where-Object {$_ -match "SMTP"} 15 | $recipients += $rule.ForwardAsAttachmentTo | Where-Object {$_ -match "SMTP"} 16 | 17 | $externalRecipients = @() 18 | 19 | foreach ($recipient in $recipients) { 20 | $email = ($recipient -split "SMTP:")[1].Trim("]") 21 | $domain = ($email -split "@")[1] 22 | 23 | if ($domains.DomainName -notcontains $domain) { 24 | $externalRecipients += $email 25 | } 26 | } 27 | 28 | if ($externalRecipients) { 29 | $extRecString = $externalRecipients -join ", " 30 | Write-Host "$($rule.Name) forwards to $extRecString" -ForegroundColor Yellow 31 | 32 | $ruleHash = $null 33 | $ruleHash = [ordered]@{ 34 | PrimarySmtpAddress = $mailbox.PrimarySmtpAddress 35 | DisplayName = $mailbox.DisplayName 36 | RuleId = $rule.Identity 37 | RuleName = $rule.Name 38 | RuleDescription = $rule.Description 39 | ExternalRecipients = $extRecString 40 | } 41 | $ruleObject = New-Object PSObject -Property $ruleHash 42 | $ruleObject | Export-Csv C:\temp\externalrules.csv -NoTypeInformation -Append 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-Inactive-GPO-Settings.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # Script Name: Get-Inactive-GPO-Settings.ps1 4 | # Date: 8/2/2012 5 | # Author: Adam Bertram 6 | # Purpose: This script finds all GPOs in the current domain which have 7 | # either the user or computer configuration section enabled yet have no 8 | # settings enabled in that section. 9 | # 10 | ################################################################################ 11 | 12 | if (!(Get-Module 'GroupPolicy') -or !(Get-Module 'Internal')) { 13 | Write-Error 'One or more required modules not loaded'; 14 | return; 15 | }##endif 16 | 17 | $bRemediate = $false; 18 | 19 | ## Create an array of default Active Directory GPOs 20 | $aDefaultGpos = @('Default Domain Controllers Policy'); 21 | 22 | $aGposToRead = Get-GPOReport -ReportType XML -All; 23 | 24 | foreach ($sGpo in $aGposToRead) { 25 | $xGpo = ([xml]$sGpo).GPO; 26 | if ($aDefaultGpos -notcontains $xGpo.Name) { ## Do not report on default AD GPOs. We don't want to change these 27 | $o = New-Object System.Object; 28 | $o | Add-Member -type NoteProperty -Name 'GPO' -Value $xGpo.Name; 29 | if ($xGpo.User.Enabled -eq 'true' -and !(Test-Member $xGpo.User ExtensionData)) { 30 | $o | Add-Member -type NoteProperty -Name 'UnpopulatedLink' -Value 'User'; 31 | if ($bRemediate) { 32 | (Get-GPO $xGpo.Name).GPOStatus = 'UserSettingsDisabled'; 33 | echo "Disabled user settings on GPO $($xGpo.Name)"; 34 | } else { 35 | $o 36 | }##endif 37 | }##endif 38 | if ($xGpo.Computer.Enabled -eq 'true' -and !(Test-Member $xGpo.Computer ExtensionData)) { 39 | $o | Add-Member -type NoteProperty -Name 'UnpopulatedLink' -Value 'Computer' -Force; 40 | if ($bRemediate) { 41 | (Get-GPO $xGpo.Name).GPOStatus = 'ComputerSettingsDisabled'; 42 | echo "Disabled computer settings on GPO $($xGpo.Name)"; 43 | } else { 44 | $o 45 | }##endif 46 | }##endif 47 | }##endif 48 | }##endforeach 49 | -------------------------------------------------------------------------------- /ActiveDirectory/Get-Old-Computer-Accounts.ps1: -------------------------------------------------------------------------------- 1 | function findOldADComputers () { 2 | $aOldComputers = @(); 3 | $aAllAdComputers = Get-ADComputer -Filter * -Properties LastLogonDate,PasswordLastSet | Where { $_.Enabled -eq $true }; 4 | foreach ($oAdComputer in $aAllAdComputers) { 5 | if ($oAdComputer.lastLogonDate -ne $null) { 6 | if ($oAdComputer.lastLogonDate -lt [DateTime]::Now.Subtract([TimeSpan]::FromDays(60))) { 7 | if ($oAdComputer.PasswordLastSet -lt [DateTime]::Now.Subtract([TimeSpan]::FromDays(60))) { 8 | $aOldComputers += $oAdComputer.Name; 9 | }##endif 10 | }##endif 11 | }##endif 12 | }##endforeach 13 | return $aOldComputers; 14 | }##endfunction 15 | 16 | $sOldPcFilePath = 'C:\Users\abertram\desktop\projects\ad_cleanup\Get-Old-Ad-Accounts-Files\old_computer_accounts.txt'; 17 | $sOnlinePcFilePath = 'C:\Users\abertram\desktop\projects\ad_cleanup\Get-Old-Ad-Accounts-Files\online_pcs.txt'; 18 | 19 | if (Test-Path $sOnlinePcFilePath) { 20 | $aPastOnlinePcs = Get-Content $sOnlinePcFilePath; 21 | } else { 22 | $aPastOnlinePcs = @(); 23 | }##endif 24 | 25 | if (Test-Path $sOldPcFilePath) { 26 | Remove-Item $sOldPcFilePath -Force 27 | }##endif 28 | 29 | $aCurrentOldPcs = findOldAdComputers; 30 | 31 | $aDnsQueryResults = Get-DnsARecord $aCurrentOldPcs; 32 | foreach ($i in $aDnsQueryResults) { 33 | $sPc = $i[0]; 34 | $bResult = $i[1]; 35 | if ($bResult) { ## The PC has a DNS record 36 | if (!(Test-Ping $sPc)) { ## The PC is offline 37 | if ($aPastOnlinePcs -notcontains $sPc) { ## The PC has never been shown to be online 38 | Write-Debug "$sPc has a DNS record but is offline"; 39 | Add-Content $sOldPcFilePath $sPc; 40 | }##endif 41 | } else { 42 | Write-Debug "$sPc has a DNS record and is online"; 43 | if ($aPastOnlinePcs -notcontains $sPc) { 44 | Add-Content $sOnlinePcFilePath $sPc; 45 | }##endif 46 | }##endif 47 | } else { 48 | Write-Debug "$sPc has no DNS record" 49 | Add-Content $sOldPcFilePath $sPc; 50 | }##endif 51 | }##endforeach -------------------------------------------------------------------------------- /MDT/Install-Drivers.ps1: -------------------------------------------------------------------------------- 1 | Write-Host -NoNewLine "Enter the path to the MDT Deployment Share (E.g `"\\util01\mdt$`" or `"Z:\`"): " 2 | $share = Read-Host 3 | Write-Progress -Activity "Driver Scan..." -PercentComplete 0 -Status "Gathering list of devices on this PC..." 4 | $devices = (Get-PnpDevice).HardwareID; 5 | $devices_list = New-Object -TypeName "System.Collections.Generic.List[string]" 6 | foreach($device in $devices) { 7 | $devices_list.Add($device); 8 | } 9 | Write-Progress -Activity "Driver Scan..." -PercentComplete 0 -Status "Gathering list of drivers in the store..." 10 | $drivers = Select-Xml -Path (Join-Path -Path $share -ChildPath "\Control\Drivers.xml") -XPath "/drivers/driver" 11 | $count = 0 12 | $drivers_found = New-Object -TypeName "System.Collections.Generic.Dictionary[string, object]" 13 | foreach($driver in $drivers) { 14 | Write-Progress -Activity "Driver Scan..." -PercentComplete (($count / $drivers.Count) * 100) -Status "Scanning driver: $($driver.Node.Name)" 15 | foreach($hwid in $driver.Node.PNPId) { 16 | if($devices_list.Contains($hwid)) { 17 | if($drivers_found.ContainsKey($hwid)) { 18 | $added_driver = [System.Version]::new($drivers_found[$hwid].Version) 19 | $tobe_driver = [System.Version]::new($driver.Node.Version) 20 | if($added_driver.CompareTo($tobe_driver) -lt 0) { 21 | $drivers_found[$hwid] = $driver.Node 22 | } 23 | } else { 24 | $drivers_found.Add($hwid, $driver.Node); 25 | } 26 | } 27 | } 28 | $count++ 29 | } 30 | $count = 0 31 | foreach($driver in $drivers_found.Values) { 32 | Write-Progress -Activity "Driver Install..." -PercentComplete (($count / $drivers_found.Count) * 100) -Status "Installing driver: $($driver.Name)..." 33 | Start-Process -FilePath "pnputil.exe" -ArgumentList "/add-driver `"$(Join-Path -Path $share -ChildPath $driver.Source)`" /install" -WindowStyle Hidden -Wait 34 | $count++ 35 | } -------------------------------------------------------------------------------- /Desktop/New-ScreenShot.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 4 2 | 3 | function New-ScreenShot 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function take a screenshot of your computer and saves it to a file of your choosing. It will only capture a single 8 | screen on a multi-monitor setup. 9 | 10 | .EXAMPLE 11 | PS> New-ScreenShot -FilePath C:\Screenshot.bmp 12 | 13 | This example will capture a screenshot of your current screen and save it to a BITMAP file at C:\ScreenShot.bmp. 14 | 15 | .PARAMETER FilePath 16 | A mandatory parameter that specifies where you'd like the screenshot image to be saved. If a file is detected in this 17 | path, the function will not allow the capture to happen. There must be no file at this location. 18 | 19 | You may choose file extensions of JPG, JPEG and BMP. 20 | 21 | .OUTPUTS 22 | System.IO.FileInfo 23 | #> 24 | [OutputType([System.IO.FileInfo])] 25 | [CmdletBinding()] 26 | param 27 | ( 28 | [Parameter(Mandatory)] 29 | [ValidateNotNullOrEmpty()] 30 | [ValidateScript({ -not (Test-Path -Path $_ -PathType Leaf) })] 31 | [ValidatePattern('\.jpg|\.jpeg|\.bmp')] 32 | [string]$FilePath 33 | 34 | ) 35 | begin { 36 | $ErrorActionPreference = 'Stop' 37 | Add-Type -AssemblyName System.Windows.Forms 38 | Add-type -AssemblyName System.Drawing 39 | } 40 | process { 41 | try 42 | { 43 | # Gather Screen resolution information 44 | $Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen 45 | 46 | # Create bitmap using the top-left and bottom-right bounds 47 | $bitmap = New-Object System.Drawing.Bitmap $Screen.Width, $Screen.Height 48 | 49 | # Create Graphics object 50 | $graphic = [System.Drawing.Graphics]::FromImage($bitmap) 51 | 52 | # Capture screen 53 | $graphic.CopyFromScreen($Screen.Left, $Screen.Top, 0, 0, $bitmap.Size) 54 | 55 | # Save to file 56 | $bitmap.Save($FilePath) 57 | 58 | Get-Item -Path $FilePath 59 | } 60 | catch 61 | { 62 | $PSCmdlet.ThrowTerminatingError($_) 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /DNS/Get-ADDnsRecordACL.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This script retrieves the ACL from an Active Directory-integrated DNS record 4 | .NOTES 5 | Created on: 8/5/2014 6 | Created by: Adam Bertram 7 | Filename: Get-AdDnsRecordAcl.ps1 8 | .EXAMPLE 9 | PS> .\Get-AdDnsRecordAcl.ps1 -Hostname 'SERVER1' 10 | 11 | This example retrieves the ACL for the hostname SERVER1 inside the current forest-integrated 12 | DNS zone inside Active Directory 13 | .EXAMPLE 14 | PS> .\Get-AdDnsRecordAcl.ps1 -Hostname 'SERVER1' -AdDnsIntegration 'Domain' 15 | 16 | This example retrieves the ACL for the hostname SERVER1 inside the current domain-integrated 17 | DNS zone inside Active Directory 18 | .PARAMETER Hostname 19 | The hostname for the DNS record you'd like to see 20 | .PARAMETER DomainName 21 | The Active Directory domain name. This defaults to the current domain 22 | .PARAMETER 23 | This is the DNS integration type. This can either be Forest and Domain. 24 | 25 | #> 26 | [CmdletBinding()] 27 | [OutputType('System.DirectoryServices.ActiveDirectorySecurity')] 28 | param ( 29 | [Parameter(Mandatory, 30 | ValueFromPipeline, 31 | ValueFromPipelineByPropertyName)] 32 | [string[]]$Hostname, 33 | 34 | [Parameter(ValueFromPipeline, 35 | ValueFromPipelineByPropertyName)] 36 | [string]$DomainName = (Get-ADDomain).Forest, 37 | 38 | [ValidateSet('Forest', 'Domain')] 39 | [Parameter(ValueFromPipeline, 40 | ValueFromPipelineByPropertyName)] 41 | [string[]]$AdDnsIntegration = 'Forest' 42 | ) 43 | 44 | begin 45 | { 46 | $ErrorActionPreference = 'Stop' 47 | Set-StrictMode -Version Latest 48 | } 49 | 50 | process 51 | { 52 | try 53 | { 54 | $Path = "AD:\DC=$DomainName,CN=MicrosoftDNS,DC=$AdDnsIntegration`DnsZones,DC=$($DomainName.Split('.') -join ',DC=')" 55 | foreach ($Record in (Get-ChildItem -Path $Path)) 56 | { 57 | if ($Hostname -contains $Record.Name) 58 | { 59 | Get-Acl -Path "ActiveDirectory:://RootDSE/$($Record.DistinguishedName)" 60 | } 61 | } 62 | } 63 | catch 64 | { 65 | Write-Error $_.Exception.Message 66 | } 67 | } -------------------------------------------------------------------------------- /ActiveDirectory/TestSiteReplicationMod.ps1: -------------------------------------------------------------------------------- 1 | echo "Starting replication test..." 2 | echo "-----------" 3 | #Set-AdUser abertram -Server xxxx -Description "xxxxx" 4 | Set-ADAccountPassword abertramtest -NewPassword (ConvertTo-SecureString 'p@$$w0rd14' -AsPlainText -Force) -Reset -Server XXXX 5 | $passwordlastset = (Get-Aduser abertramtest -Properties passwordlastset -Server XXXX).passwordlastset 6 | Write-Host "Waiting for replication..." -ForegroundColor Yellow 7 | $i = 0 8 | do { 9 | $i++ 10 | sleep 1 11 | #} while ((Get-AdUser abertram -Properties description -Server DC01).description -ne "Keller Schroeder Vendor - Set on UAPDC01") 12 | } while ((Get-Aduser abertramtest -Properties passwordlastset -Server DC01).passwordlastset -ne $passwordlastset) 13 | 14 | Write-Host "Replication from XXXX from XXXX successful. Replication time: $i seconds ($($i / 60) minutes)" -ForegroundColor Green 15 | 16 | 17 | echo "Starting replication test..." 18 | echo "-----------" 19 | Write-Host "Waiting for replication from XXXXX to XXXX..." -ForegroundColor Yellow 20 | Set-ADAccountPassword XXXXX -NewPassword (ConvertTo-SecureString 'p@$$w0rd15' -AsPlainText -Force) -Reset -Server XXXX 21 | $passwordlastset = (Get-Aduser XXXX -Properties passwordlastset -Server DC01).passwordlastset 22 | $i = 0 23 | do { 24 | $i++ 25 | sleep 1 26 | } while ((Get-Aduser XXXXX -Properties passwordlastset -Server XXXXX).passwordlastset -ne $passwordlastset) 27 | 28 | Write-Host "Replication from XXXX from XXXXX successful. Replication time: $i seconds ($($i / 60) minutes)" -ForegroundColor Green 29 | 30 | 31 | Set-AdUser XXXXX -Server XXXX -Description "XXXXXX" 32 | 33 | echo '-----------' 34 | echo 'Checking last replication status between XXXX and XXXX sites...' 35 | echo "-----------" 36 | Get-ADReplicationLink -SiteName xxxxx | ? { $_.sourceserver -eq 'XXXX' } | select sourceserver,destinationserver,LastSuccessfulsync,lastsyncmessage 37 | Get-ADReplicationLink -SiteName xxxx | ? { $_.sourceserver -eq 'XXXX' } | select sourceserver,destinationserver,LastSuccessfulsync,lastsyncmessage 38 | -------------------------------------------------------------------------------- /ActiveDirectory/Get-AdDnsRecordAcl.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module ActiveDirectory 2 | 3 | <# 4 | .SYNOPSIS 5 | This script retrieves the ACL from an Active Directory-integrated DNS record 6 | .NOTES 7 | Created on: 8/5/2014 8 | Created by: Adam Bertram 9 | Filename: Get-AdDnsRecordAcl.ps1 10 | .EXAMPLE 11 | PS> .\Get-AdDnsRecordAcl.ps1 -Hostname 'SERVER1' 12 | 13 | This example retrieves the ACL for the hostname SERVER1 inside the current forest-integrated 14 | DNS zone inside Active Directory 15 | .EXAMPLE 16 | PS> .\Get-AdDnsRecordAcl.ps1 -Hostname 'SERVER1' -AdDnsIntegration 'Domain' 17 | 18 | This example retrieves the ACL for the hostname SERVER1 inside the current domain-integrated 19 | DNS zone inside Active Directory 20 | .PARAMETER Hostname 21 | The hostname for the DNS record you'd like to see 22 | .PARAMETER DomainName 23 | The Active Directory domain name. This defaults to the current domain 24 | .PARAMETER AdDnsIntegration 25 | This is the DNS integration type. This can either be Forest and Domain. 26 | 27 | #> 28 | [CmdletBinding()] 29 | [OutputType('System.DirectoryServices.ActiveDirectorySecurity')] 30 | param ( 31 | [Parameter(Mandatory, 32 | ValueFromPipeline, 33 | ValueFromPipelineByPropertyName)] 34 | [string[]]$Hostname, 35 | [Parameter(ValueFromPipeline, 36 | ValueFromPipelineByPropertyName)] 37 | [string]$DomainName = (Get-ADDomain).Forest, 38 | [ValidateSet('Forest','Domain')] 39 | [Parameter(ValueFromPipeline, 40 | ValueFromPipelineByPropertyName)] 41 | [string[]]$AdDnsIntegration = 'Forest' 42 | ) 43 | 44 | begin { 45 | $ErrorActionPreference = 'Stop' 46 | Set-StrictMode -Version Latest 47 | } 48 | 49 | process { 50 | try { 51 | $Path = "AD:\DC=$DomainName,CN=MicrosoftDNS,DC=$AdDnsIntegration`DnsZones,DC=$($DomainName.Split('.') -join ',DC=')" 52 | foreach ($Record in (Get-ChildItem -Path $Path)) { 53 | if ($Hostname -contains $Record.Name) { 54 | Get-Acl -Path "ActiveDirectory:://RootDSE/$($Record.DistinguishedName)" 55 | } 56 | } 57 | } catch { 58 | Write-Error $_.Exception.Message 59 | } 60 | } -------------------------------------------------------------------------------- /ActiveDirectory/PasswordExpirations/DebugExpirations.ps1: -------------------------------------------------------------------------------- 1 | $Date = Get-Date 2 | Import-Module ActiveDirectory 3 | 4 | $users = Get-Aduser -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress -SearchBase "CN=Users,DC=softeam,DC=local" -filter { (Enabled -eq 'True') } 5 | 6 | 7 | $maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge 8 | 9 | $resultArray = @() 10 | 11 | 12 | # Process Each User for Password Expiry 13 | foreach ($user in $users) 14 | { 15 | $Name = $user.Name 16 | $PasswordExpired = $user.PasswordExpired 17 | $PasswordNeverExpires = $user.PasswordNeverExpires 18 | 19 | 20 | $passwordSetDate = (Get-ADUser $user -properties * | ForEach-Object { $_.PasswordLastSet }) 21 | 22 | $PasswordPol = (Get-ADUserResultantPasswordPolicy $user) 23 | if (($PasswordPol) -ne $null) 24 | { 25 | $maxPasswordAgeCurrent = ($PasswordPol).MaxPasswordAge 26 | } 27 | else 28 | { 29 | $maxPasswordAgeCurrent = $maxPasswordAge 30 | } 31 | 32 | $expireson = $passwordsetdate + $maxPasswordAgeCurrent 33 | $today = (get-date) 34 | #Gets the count on how many days until the password expires and stores it in the $daystoexpire var 35 | $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days 36 | 37 | 38 | 39 | $temp = New-Object System.Object 40 | $temp | Add-Member -MemberType NoteProperty -Name "Name" -Value $Name 41 | $temp | Add-Member -MemberType NoteProperty -Name "PasswordExpired" -Value $PasswordExpired 42 | $temp | Add-Member -MemberType NoteProperty -Name "PasswordNeverExpires" -Value $PasswordNeverExpires 43 | $temp | Add-Member -MemberType NoteProperty -Name "daystoexpire" -Value $daystoexpire 44 | $temp | Add-Member -MemberType NoteProperty -Name "passwordSetDate" -Value $passwordSetDate 45 | $temp | Add-Member -MemberType NoteProperty -Name "maxPasswordAgeCurrent" -Value $maxPasswordAgeCurrent 46 | $temp | Add-Member -MemberType NoteProperty -Name "expireson" -Value $expireson 47 | 48 | $resultArray = $resultArray+ $temp 49 | 50 | 51 | } 52 | 53 | $resultArray | ft -------------------------------------------------------------------------------- /File-Folder Management/Remove-FileOlderThan.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | 3 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] 4 | <# 5 | .SYNOPSIS 6 | This is a simple script that allows you to specify one or more folder paths on a file system and remove "old" files by 7 | last write time. By default, it will look for all files recursively in a particular folder, check for the last time those 8 | files have been written to, verify that last write time is older than $DaysOld and if, so, remove them. 9 | 10 | .EXAMPLE 11 | PS> .\Remove-FileOlderThan.ps1 -FolderPath 'C:\Folder1','C:\Folder2' -DaysOld 30 -FileExtension 'doc' 12 | 13 | This example would recursively look through both the C:\Folder1 and C:\Folder2 folders for all *.doc files that have a 14 | last write time of 30 days or older. Once found, they are removed. 15 | 16 | .PARAMETER FolderPath 17 | One or more folder paths separated by a comma to look through. This is mandatory. 18 | 19 | .PARAMETER DaysOld 20 | The minimum number of days old a file must be in order to be classified as "old". This is mandatory. 21 | 22 | .PARAMETER FileExtension 23 | An optional parameter to only remove old files with a particular file extension. 24 | #> 25 | param ( 26 | [Parameter(Mandatory)] 27 | [ValidateNotNullOrEmpty()] 28 | [string[]]$FolderPath, 29 | 30 | [Parameter(Mandatory)] 31 | [ValidateNotNullOrEmpty()] 32 | [int]$DaysOld, 33 | 34 | [Parameter()] 35 | [ValidateNotNullOrEmpty()] 36 | [ValidateLength(1, 3)] 37 | [string]$FileExtension 38 | ) 39 | 40 | $Now = Get-Date 41 | 42 | $gciParams = @{ 43 | 'Recurse' = $true 44 | 'File' = $true 45 | } 46 | 47 | if ($PSBoundParameters.ContainsKey('FileExtension')) { 48 | $gciParams.Filter = "Extension -eq $FileExtension" 49 | } 50 | 51 | $LastWrite = $Now.AddDays(-$DaysOld) 52 | 53 | foreach ($path in $FolderPath) 54 | { 55 | $gciParams.Path = $path 56 | ((Get-ChildItem @gciParams).Where{ $_.LastWriteTime -le $LastWrite }).foreach{ 57 | if ($PSCmdlet.ShouldProcess($_.FullName, 'Remove')) 58 | { 59 | Remove-Item -Path $_.FullName -Force 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Security/EFS.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 4 -RunAsAdministrator 2 | 3 | function Enable-FileEncryption 4 | { 5 | <# 6 | .SYNOPSIS 7 | This function enables EFS file encryption on a file. 8 | 9 | .EXAMPLE 10 | PS> Get-Item -Path 'C:\File.txt' | Enable-FileEncryption 11 | 12 | This example finds the C:\File.txt with Get-Item, passes it through the pipeline to Enable-FileEncryption which will 13 | then EFS encrypt the file. 14 | 15 | .EXAMPLE 16 | PS> Get-ChildItem -Path 'C:\Folder' | Enable-FileEncryption 17 | 18 | This example will encrypt every folder in C:\Folder. 19 | 20 | .PARAMETER File 21 | A System.IO.FileInfo object that will be encrypted. 22 | #> 23 | [OutputType([void])] 24 | [CmdletBinding()] 25 | param 26 | ( 27 | [Parameter(Mandatory,ValueFromPipeline)] 28 | [ValidateNotNullOrEmpty()] 29 | [System.IO.FileInfo]$File 30 | ) 31 | begin { 32 | $ErrorActionPreference = 'Stop' 33 | } 34 | process { 35 | try 36 | { 37 | $File.Encrypt() 38 | } 39 | catch 40 | { 41 | $PSCmdlet.ThrowTerminatingError($_) 42 | } 43 | } 44 | } 45 | 46 | function Disable-FileEncryption 47 | { 48 | <# 49 | .SYNOPSIS 50 | This function disables EFS file encryption on a file. 51 | 52 | .EXAMPLE 53 | PS> Get-Item -Path 'C:\File.txt' | Disable-FileEncryption 54 | 55 | This example finds the C:\File.txt with Get-Item, passes it through the pipeline to Disable-FileEncryption which will 56 | then EFS decrypt the file. 57 | 58 | .EXAMPLE 59 | PS> Get-ChildItem -Path 'C:\Folder' | Disable-FileEncryption 60 | 61 | This example will decrypt every folder in C:\Folder. 62 | 63 | .PARAMETER File 64 | A System.IO.FileInfo object that will be decrypted. 65 | #> 66 | [OutputType([void])] 67 | [CmdletBinding()] 68 | param 69 | ( 70 | [Parameter(Mandatory, ValueFromPipeline)] 71 | [ValidateNotNullOrEmpty()] 72 | [System.IO.FileInfo]$File 73 | ) 74 | begin { 75 | $ErrorActionPreference = 'Stop' 76 | } 77 | process { 78 | try 79 | { 80 | $File.Decrypt() 81 | } 82 | catch 83 | { 84 | $PSCmdlet.ThrowTerminatingError($_) 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Chef/ConfigFileModFunctions.ps1: -------------------------------------------------------------------------------- 1 | function Get-ChefConfigItem 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function parses the appropriate config file path (either Chef solo or client) and returns a set of objects. 6 | 7 | .PARAMETER Name 8 | Optionally, if you'd like to only see a single item in the config file you can use this parameter. Else, it will return 9 | all configuration items. 10 | #> 11 | 12 | [CmdletBinding()] 13 | param 14 | ( 15 | [Parameter()] 16 | [ValidateNotNullOrEmpty()] 17 | [string]$Name 18 | ) 19 | ## Read the config file from disk 20 | $line = Get-Content -Path $ConfigFilePath | where { $_ -match $Name } 21 | if ($line) 22 | { 23 | foreach ($l in $line) 24 | { 25 | [pscustomobject]@{ 26 | 'Name' = $l.Split(' ')[0].Trim() 27 | 'Value' = ($l.Split(' ')[-1] -replace "'").Trim() 28 | } 29 | } 30 | } 31 | } 32 | 33 | function Set-ChefConfigItem 34 | { 35 | <# 36 | .SYNOPSIS 37 | This changes an existing configuration item in the chef solo or client configuration file. 38 | 39 | .PARAMETER Name 40 | You must specify a configuration item name to be changed. 41 | 42 | .PARAMETER Value 43 | You must specify a value of the configuration item to be changed. 44 | 45 | .EXAMPLE 46 | PS> Get-ChefConfigItem -Name log_level | Set-ChefConfigItem -Value 'info' 47 | 48 | This finds the current value of log_level and changes it to 'info' in the configuration file. 49 | #> 50 | 51 | [CmdletBinding()] 52 | param 53 | ( 54 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 55 | [ValidateNotNullOrEmpty()] 56 | [string]$Name, 57 | 58 | [Parameter(Mandatory)] 59 | [ValidateNotNullOrEmpty()] 60 | [string]$Value 61 | 62 | ) 63 | ## Create an array that contains each line of the configuration file that does not match the name 64 | $config = Get-Content -Path $ConfigFilePath | where { $_ -notmatch $Name } 65 | ## Add the name and value in the format Name 'Value' to the end of the file 66 | $config += "$Name '$Value'" 67 | ## Overwrite the existing config file with the new one. 68 | $config | Out-File $ConfigFilePath 69 | } -------------------------------------------------------------------------------- /PowerShell Internals/Enable-RemotePSRemoting.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | 4 | .NOTES 5 | Created on: 5/9/2014 3:46 PM 6 | Created by: Adam Bertram 7 | Organization: 8 | Filename: 9 | .DESCRIPTION 10 | 11 | .EXAMPLE 12 | 13 | .EXAMPLE 14 | 15 | .PARAMETER Computername 16 | The remote computer to enable PS remoting on 17 | 18 | #> 19 | [CmdletBinding()] 20 | param ( 21 | [Parameter(Mandatory = $True, 22 | ValueFromPipeline = $True, 23 | ValueFromPipelineByPropertyName = $True)] 24 | [string]$Computername, 25 | [Parameter(Mandatory = $False, 26 | ValueFromPipeline = $False, 27 | ValueFromPipelineByPropertyName = $False)] 28 | [string]$PsExecPath = 'C:\PsExec.exe' 29 | ) 30 | 31 | begin { 32 | ## http://www.leeholmes.com/blog/2009/11/20/testing-for-powershell-remoting-test-psremoting/ 33 | function Test-PsRemoting { 34 | param ( 35 | [Parameter(Mandatory = $true)] 36 | $computername 37 | ) 38 | 39 | try { 40 | $errorActionPreference = "Stop" 41 | $result = Invoke-Command -ComputerName $computername { 1 } 42 | } catch { 43 | return $false 44 | } 45 | 46 | ## I’ve never seen this happen, but if you want to be 47 | ## thorough…. 48 | if ($result -ne 1) { 49 | Write-Verbose "Remoting to $computerName returned an unexpected result." 50 | return $false 51 | } 52 | $true 53 | } 54 | 55 | if (!(Test-Ping $Computername)) { 56 | throw 'Computer is not reachable' 57 | } elseif (!(Test-Path $PsExecPath)) { 58 | throw 'Psexec.exe not found' 59 | } 60 | } 61 | 62 | process { 63 | if (Test-PsRemoting $Computername) { 64 | Write-Warning "Remoting already enabled on $Computername" 65 | } else { 66 | Write-Verbose "Attempting to enable remoting on $Computername..." 67 | & $PsExecPath "\\$Computername" -s c:\windows\system32\winrm.cmd quickconfig -quiet 68 | if (!(Test-PsRemoting $Computername)) { 69 | Write-Warning "Remoting was attempted but not enabled on $Computername" 70 | } else { 71 | Write-Verbose "Remoting successfully enabled on $Computername" 72 | } 73 | } 74 | } 75 | 76 | end { 77 | 78 | } -------------------------------------------------------------------------------- /Database-Datasets/GoogleSheets/roughcode.ps1: -------------------------------------------------------------------------------- 1 | 2 | $userName = 'adbertram@gmail.com' 3 | $password = 'Ilikegmail.' 4 | 5 | Add-Type -Path "C:\Program Files (x86)\Google\Google Data API SDK\Redist\Google.GData.Client.dll" 6 | Add-Type -Path "C:\Program Files (x86)\Google\Google Data API SDK\Redist\Google.GData.Extensions.dll" 7 | Add-Type -Path "C:\Program Files (x86)\Google\Google Data API SDK\Redist\Google.GData.Spreadsheets.dll" 8 | 9 | $service = New-Object Google.GData.Spreadsheets.SpreadsheetsService("TestGoogleDocs") 10 | $service.setUserCredentials($userName, $password) 11 | $query = New-Object Google.GData.Spreadsheets.SpreadsheetQuery 12 | $feed = $service.Query($query) 13 | 14 | $feed.Entries | 15 | foreach { 16 | #$_.Title.Text 17 | 18 | $_.Links | 19 | ? {$_.rel -eq "http://schemas.google.com/spreadsheets/2006#worksheetsfeed"} | 20 | % { 21 | $query = New-Object Google.GData.Spreadsheets.WorksheetQuery($_.Href) 22 | $feed = $service.Query($query) 23 | $feed.Entries | 24 | % { 25 | $_.Title.Text 26 | $_.Links | 27 | ? { $_.rel -eq "http://schemas.google.com/spreadsheets/2006#listfeed"} | 28 | % { 29 | $listQuery = New-Object Google.GData.Spreadsheets.ListQuery($_.Href) 30 | $feed = $service.Query($listQuery) 31 | "Worksheet has $($feed.Entries.Count) rows:" 32 | $feed.Entries | 33 | % { 34 | $_.Elements | 35 | % { 36 | Write-Host -NoNewline "$($_.value)`t" 37 | } 38 | Write-Host 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /File-Folder Management/Compare-Folder.ps1: -------------------------------------------------------------------------------- 1 | function Compare-Folder 2 | { 3 | [CmdletBinding()] 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [ValidateScript({ Test-Path -Path $_ -PathType Container })] 9 | [string]$ReferenceFolder, 10 | 11 | [Parameter(Mandatory)] 12 | [ValidateNotNullOrEmpty()] 13 | [ValidateScript({ Test-Path -Path $_ -PathType Container })] 14 | [string]$DifferenceFolder, 15 | 16 | [Parameter()] 17 | [ValidateNotNullOrEmpty()] 18 | [ValidatePattern('^\\')] 19 | [string]$ExcludeFilePath 20 | 21 | ) 22 | begin 23 | { 24 | $ErrorActionPreference = 'Stop' 25 | function Get-FileHashesInFolder 26 | { 27 | param ( 28 | [string]$Folder 29 | ) 30 | $files = Get-ChildItem -Path $Folder -Recurse -File 31 | foreach ($s in $files) 32 | { 33 | $selectObjects = @('Hash', @{ n = 'Path'; e = { $_.Path.SubString($Folder.Length) } }) 34 | Get-FileHash $s.Fullname | Select $selectObjects -ExcludeProperty Path 35 | } 36 | } 37 | } 38 | process 39 | { 40 | try 41 | { 42 | $refHashes = Get-FileHashesInFolder -Folder $ReferenceFolder 43 | $destHashes = Get-FileHashesInFolder -Folder $DifferenceFolder 44 | if ($PSBoundParameters.ContainsKey('ExcludeFilePath')) 45 | { 46 | $refHashes = $refHashes.Where({ $_.Path -ne $ExcludeFilePath }) 47 | $destHashes = $destHashes.Where({ $_.Path -ne $ExcludeFilePath }) 48 | } 49 | 50 | $refHashes.Where({ $_.Path -notin $destHashes.Path }).foreach({ 51 | [pscustomobject]@{ 52 | 'Path' = $_.Path 53 | 'Reason' = 'NotInDifferenceFolder' 54 | } 55 | }) 56 | $destHashes.Where({ $_.Path -notin $refHashes.Path }).foreach({ 57 | [pscustomobject]@{ 58 | 'Path' = $_.Path 59 | 'Reason' = 'NotInReferenceFolder' 60 | } 61 | }) 62 | $refHashes.Where({ $_.Hash -notin $destHashes.Hash -and $_.Path -in $destHashes.Path }).foreach({ 63 | [pscustomobject]@{ 64 | 'Path' = $_.Path 65 | 'Reason' = 'HashDifferent' 66 | } 67 | }) 68 | } 69 | catch 70 | { 71 | Write-Error $_.Exception.Message 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /DHCP/Get-DhcpLease.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 -Module DhcpServer 2 | 3 | [CmdletBinding(DefaultParameterSetName = 'Default')] 4 | param ( 5 | [Parameter()] 6 | [ValidateNotNullOrEmpty()] 7 | [string[]]$DhcpServer, 8 | 9 | [Parameter(ParameterSetName = 'HostName')] 10 | [ValidateNotNullOrEmpty()] 11 | [string[]]$HostName, 12 | 13 | [Parameter(ParameterSetName = 'MacAddress')] 14 | [ValidateNotNullOrEmpty()] 15 | [string[]]$MacAddress, 16 | 17 | [Parameter(ParameterSetName = 'IpAddress')] 18 | [ValidateNotNullOrEmpty()] 19 | [ipaddress[]]$IpAddress 20 | ) 21 | 22 | begin 23 | { 24 | $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop 25 | Set-StrictMode -Version Latest 26 | } 27 | 28 | process 29 | { 30 | try 31 | { 32 | if (-not $PSBoundParameters.ContainsKey('DhcpServer')) 33 | { 34 | if ($DhcpServer = Get-DhcpServerInDC) 35 | { 36 | $DhcpServer = $DhcpServer.DnsName 37 | } 38 | } 39 | 40 | @($DhcpServer).foreach({ 41 | 42 | try 43 | { 44 | $srv = $_ 45 | if (-not (Test-Connection -ComputerName $srv -Quiet -Count 1)) 46 | { 47 | throw "The DHCP server [$($srv)] is not available." 48 | } 49 | 50 | $leaseParams = @{ 51 | 'ComputerName' = $srv 52 | } 53 | 54 | if ($PSBoundParameters.ContainsKey('MacAddress')) { 55 | $leaseParams.ClientId = $MacAddress 56 | } 57 | 58 | @(Get-DhcpServerv4Scope -ComputerName $srv).foreach({ 59 | if ($PSBoundParameters.ContainsKey('Ipaddress')) { 60 | $leaseParams.IpAddress = $IpAddress 61 | } 62 | else 63 | { 64 | $leaseParams.ScopeId = $_.ScopeId 65 | } 66 | 67 | $leases = Get-DhcpServerv4Lease @leaseParams 68 | if ($PSBoundParameters.ContainsKey('HostName')) { 69 | @($leases).where({$_.Hostname -in $HostName}) 70 | } 71 | 72 | }) 73 | } 74 | catch 75 | { 76 | Write-Error -Message $_.Exception.Message 77 | } 78 | 79 | }) 80 | } 81 | catch 82 | { 83 | Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 84 | } 85 | } -------------------------------------------------------------------------------- /VMware/Backup-VM.ps1: -------------------------------------------------------------------------------- 1 | function Backup-VM 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function takes input from Get-VM, checks if a VM is online and if so, shuts it down. Once shut down, it will then export 6 | the VM to the path specified in the FolderPath parameter. It will then bring the VM back up when done. 7 | 8 | .EXAMPLE 9 | PS> Get-VM | Backup-VM -FolderPath C:\VMBackups 10 | 11 | This example backs up all VMs returned by Get-VM and create OVA files with the VM names in the C:\VMBackups folder. 12 | 13 | .PARAMETER VM 14 | A VM object that represents the VM to be backed up. This can be populated via Get-VM or by providing any number of 15 | VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl objects separated by a comma. 16 | 17 | .PARAMETER FolderPath 18 | The path to where the VM's OVA file will be created. 19 | 20 | .INPUTS 21 | VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl 22 | 23 | .OUTPUTS 24 | None. 25 | #> 26 | [CmdletBinding(SupportsShouldProcess)] 27 | param 28 | ( 29 | [Parameter(Mandatory, ValueFromPipeline)] 30 | [ValidateNotNullOrEmpty()] 31 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]] 32 | $VM, 33 | 34 | [Parameter(Mandatory)] 35 | [ValidateNotNullOrEmpty()] 36 | [ValidateScript({ Test-Path -Path $_ -PathType Container })] 37 | [string]$FolderPath 38 | ) 39 | process 40 | { 41 | foreach ($v in $VM) 42 | { 43 | $vmName = $v.Name 44 | if ($v.PowerState -eq 'PoweredOn') 45 | { 46 | if ($PSCmdlet.ShouldProcess($vmName, 'Shutdown VM')) 47 | { 48 | Write-Verbose -Message "[$($vmName)] is online. Shutting down." 49 | $null = Shutdown-VMGuest -VM $v -Confirm:$false 50 | while ((Get-VM -Name $vmName).PowerState -ne 'PoweredOff') { 51 | Start-Sleep -Seconds 1 52 | Write-Verbose -Message "Waiting for [$($vmName)] to shutdown." 53 | } 54 | Write-Verbose -Message "[$($vmName)] has shut down." 55 | } 56 | } 57 | #Export the VM in OVA format creating a file 58 | Export-VApp -Destination $FolderPath -VM $v -Format OVA 59 | 60 | $v | Start-VM 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /AWS/Elastic Beanstalk/New-AwsBeanstalkApp.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module AWSPowerShell 2 | 3 | <# 4 | .SYNOPSIS 5 | This script creates an AWS Elastic Beanstalk app with multiple environments for use in a CI/CD pipeline 6 | 7 | .EXAMPLE 8 | PS> .\New-AwsBeanstalkApp.ps1 -ApplicationName MyAWSApp -Description 'My app' -EnvironmentName 'Development','Stage','Production' -EnvironmentType '64bit Windows Server Core 2016 v1.2.0 running IIS 10.0' 9 | 10 | #> 11 | 12 | param ( 13 | [Parameter(Mandatory)] 14 | [ValidateNotNullOrEmpty()] 15 | [string]$ApplicationName, 16 | 17 | [Parameter(Mandatory)] 18 | [ValidateNotNullOrEmpty()] 19 | [string]$Description, 20 | 21 | [Parameter(Mandatory)] 22 | [ValidateNotNullOrEmpty()] 23 | [string]$EnvironmentType, 24 | 25 | [Parameter(Mandatory)] 26 | [ValidateNotNullOrEmpty()] 27 | [string[]]$EnvironmentName, 28 | 29 | [Parameter()] 30 | [ValidateNotNullOrEmpty()] 31 | [int]$WaitForEnvironmentCreation = 10 ## minutes 32 | ) 33 | 34 | if (-not ($ebApp = Get-EBApplication -ApplicationName $ApplicationName)) { 35 | $ebApp = New-EBApplication -ApplicationName $ApplicationName -Description $Description 36 | } else { 37 | Write-Verbose -Message "The BeanStalk application [$($ApplicationName)] already exists." 38 | } 39 | 40 | $params = @{ 41 | ApplicationName = $ApplicationName 42 | } 43 | $EnvironmentName | Where-Object { $_ -notin (Get-EBEnvironment -ApplicationName $ApplicationName | Select-Object -ExpandProperty EnvironmentName) } | ForEach-Object { 44 | $null = New-EBEnvironment @params -EnvironmentName $_ -SolutionStackName $EnvironmentType 45 | } 46 | 47 | $stopwatch = [system.diagnostics.stopwatch]::StartNew() 48 | while (($stopwatch.Elapsed.TotalMinutes -lt $WaitForEnvironmentCreation) -and (Get-EBEnvironment -ApplicationName MyAWSApp -EnvironmentName $EnvironmentName).where({ $_.Health -ne 'Green'})) { 49 | Write-Host 'Waiting for environments to be created...' 50 | Start-Sleep -Seconds 60 51 | } 52 | if ($stopWatch.Elapsed.TotalMinutes -gt $WaitForEnvironmentCreation) { 53 | Write-Error -Message 'The environment creation process timed out.' 54 | } else { 55 | Write-Verbose -Message 'Envrionment creation successful!' 56 | } 57 | $stopwatch.Stop() -------------------------------------------------------------------------------- /Inventorying-Reporting Tools/Get-ServerUptimeReport.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.0 5 | 6 | .GUID b918ed36-48fa-4577-b2bf-c4d9225cd095 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | .PRIVATEDATA 32 | 33 | #> 34 | 35 | <# 36 | .SYNOPSIS 37 | This is a script that reads a computer's event log for startup and shutdown events. Once found, it will then compare the 38 | times each of these events to come up with the total time the computer was down for. 39 | 40 | .DESCRIPTION 41 | This is a script that reads a computer's event log for startup and shutdown events. Once found, it will then compare the 42 | times each of these events to come up with the total time the computer was down for. 43 | 44 | .PARAMETER ComputerName 45 | One computer name you'd like to run the report on. 46 | #> 47 | 48 | [CmdletBinding()] 49 | param ( 50 | [Parameter()] 51 | [ValidateNotNullOrEmpty()] 52 | [string]$ComputerName = $env:COMPUTERNAME 53 | ) 54 | 55 | $filterHt = @{ 56 | 'LogName' = 'System' 57 | 'ID' = 6005 58 | } 59 | $StartEvents = Get-WinEvent -ComputerName $ComputerName -FilterHashtable $filterHt 60 | if (-not $StartEvents) { 61 | throw 'Unable to determine any start times' 62 | } 63 | $StartTimes = $StartEvents.TimeCreated 64 | 65 | ## Find all stop events 66 | $filterHt.ID = 6006 67 | $StopEvents = Get-WinEvent -ComputerName $ComputerName -FilterHashtable $filterHt -Oldest 68 | $StopTimes = $StopEvents.TimeCreated 69 | 70 | foreach ($startTime in $StartTimes) { 71 | $StopTime = $StopTimes | ? { $_ -gt $StartTime } | select -First 1 72 | if (-not $StopTime) { 73 | $StopTime = Get-Date 74 | } 75 | $output = [ordered]@{ 76 | 'Startup' = $StartTime 77 | 'Shutdown' = $StopTime 78 | 'Uptime (Days)' = [math]::Round((New-TimeSpan -Start $StartTime -End $StopTime).TotalDays, 2) 79 | 'Uptime (Min)' = [math]::Round((New-TimeSpan -Start $StartTime -End $StopTime).TotalMinutes, 2) 80 | } 81 | [pscustomobject]$output 82 | 83 | } 84 | -------------------------------------------------------------------------------- /Software/Get-MSIDatabaseProperties.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This function retrieves properties from a Windows Installer MSI database. 4 | .DESCRIPTION 5 | This function uses the WindowInstaller COM object to pull all values from the Property table from a MSI. 6 | .EXAMPLE 7 | Get-MsiDatabaseProperties 'MSI_PATH' 8 | .PARAMETER FilePath 9 | The path to the MSI you'd like to query 10 | #> 11 | [CmdletBinding()] 12 | param ( 13 | [Parameter(Mandatory=$True, 14 | ValueFromPipeline=$True, 15 | ValueFromPipelineByPropertyName=$True, 16 | HelpMessage='What is the path of the MSI you would like to query?')] 17 | [IO.FileInfo[]]$FilePath 18 | ) 19 | 20 | begin { 21 | $com_object = New-Object -com WindowsInstaller.Installer 22 | } 23 | 24 | process { 25 | try { 26 | $database = $com_object.GetType().InvokeMember( 27 | "OpenDatabase", 28 | "InvokeMethod", 29 | $Null, 30 | $com_object, 31 | @($FilePath.FullName, 0) 32 | ) 33 | 34 | $query = "SELECT * FROM Property" 35 | $View = $database.GetType().InvokeMember( 36 | "OpenView", 37 | "InvokeMethod", 38 | $Null, 39 | $database, 40 | ($query) 41 | ) 42 | 43 | $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null) 44 | 45 | $record = $View.GetType().InvokeMember( 46 | "Fetch", 47 | "InvokeMethod", 48 | $Null, 49 | $View, 50 | $Null 51 | ) 52 | 53 | $msi_props = @{} 54 | while ($record -ne $null) { 55 | $msi_props[$record.GetType().InvokeMember("StringData", "GetProperty", $Null, $record, 1)] = $record.GetType().InvokeMember("StringData", "GetProperty", $Null, $record, 2) 56 | $record = $View.GetType().InvokeMember( 57 | "Fetch", 58 | "InvokeMethod", 59 | $Null, 60 | $View, 61 | $Null 62 | ) 63 | } 64 | 65 | $msi_props 66 | 67 | } catch { 68 | throw "Failed to get MSI file properties the error was: {0}." -f $_ 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Hyper-V/Install-VMIntegrationServices.ps1: -------------------------------------------------------------------------------- 1 | function Install-VMIntegrationService 2 | { 3 | <# 4 | .SYNOPSIS 5 | This function remotely connects to a Hyper-V VM and installs Integration Services. 6 | 7 | .PARAMETER VM 8 | A VM object from the Get-VM cmdlet that will be targeted to install Integaation Services on. 9 | 10 | .PARAMETER Server 11 | The Hyper-V host that the VM is running on. 12 | 13 | .PARAMETER Credential 14 | A optional PSCredential object to use if you'd like to authenticate with other credentials. 15 | 16 | .EXAMPLE 17 | PS> Get-VM SERVER1 | Install-VMIntegrationServices 18 | 19 | This example installing Integration Services on the VM SERVER1. 20 | #> 21 | 22 | [CmdletBinding()] 23 | param 24 | ( 25 | [Parameter(Mandatory,ValueFromPipeline)] 26 | [ValidateNotNullOrEmpty()] 27 | [Microsoft.HyperV.PowerShell.VirtualMachine[]]$VM, 28 | 29 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 30 | [ValidateNotNullOrEmpty()] 31 | [Alias('ComputerName')] 32 | [string]$Server, 33 | 34 | [Parameter()] 35 | [ValidateNotNullOrEmpty()] 36 | [pscredential]$Credential 37 | ) 38 | process 39 | { 40 | foreach ($v in $VM) 41 | { 42 | $v = $v.Name 43 | Set-VMDvdDrive -ComputerName $Server -VMName $v -Path 'C:\Windows\System32\vmguest.iso' 44 | $DVDriveLetter = (Get-VMDvdDrive -ComputerName $Server -VMName $v).Id | Split-Path -Leaf 45 | $params = @{ 46 | 'ComputerName' = $v 47 | } 48 | if ($PSBoundParameters.ContainsKey('Credential')) { 49 | $params.Credential = $Credential 50 | } 51 | Write-Verbose -Message "Installing integration services on [$($v)] with DVD drive letter [$($DVDriveLetter)]" 52 | Invoke-Command @params -ScriptBlock { 53 | if ($ENV:PROCESSOR_ARCHITECTURE -eq 'AMD64') 54 | { 55 | $folder = 'amd64' 56 | } 57 | else 58 | { 59 | $folder = 'x86' 60 | } 61 | Start-Process -FilePath "$($using:DVDriveLetter):\support\$folder\setup.exe" -Args '/quiet /norestart' -Wait 62 | } 63 | 64 | Write-Verbose -Message "Restarting [$($v)]" 65 | Restart-Computer @params -Wait -For WinRM -Force 66 | Set-VMDvdDrive -ComputerName $Server -VMName $v -ControllerNumber 1 -ControllerLocation 0 -Path $null 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Desktop/Remove-Win10-Apps.ps1: -------------------------------------------------------------------------------- 1 | Write-Progress -Activity "Remove Apps" -Status "Looking for apps to remove..." -PercentComplete 0 2 | 3 | $PackagesToRemove = 4 | "Microsoft.3DBuilder", 5 | "Microsoft.Microsoft3DViewer", 6 | "Microsoft.BingFinance", 7 | "Microsoft.BingNews", 8 | "Microsoft.BingSports", 9 | "Microsoft.BingTranslator", 10 | "Microsoft.CommsPhone", 11 | "Microsoft.Getstarted", 12 | "Microsoft.Messaging", 13 | "Microsoft.MicrosoftOfficeHub", 14 | "Microsoft.MicrosoftSolitaireCollection", 15 | "Microsoft.Office.OneNote", 16 | "Microsoft.Office.Sway", 17 | "Microsoft.SkypeApp", 18 | "Microsoft.People", 19 | "Microsoft.WindowsAlarms", 20 | "Microsoft.WindowsCamera", 21 | "Microsoft.WindowsCommunicationsApps", 22 | "Microsoft.WindowsMaps", 23 | "Microsoft.WindowsPhone", 24 | "Microsoft.WindowsSoundRecorder", 25 | "Microsoft.XboxApp", 26 | "Microsoft.ZuneMusic", 27 | "Microsoft.ZuneVideo", 28 | "Microsoft.OneConnect", 29 | "Microsoft.WindowsFeedbackHub" 30 | 31 | $ProvisionPackagesToRemove = @() 32 | $AllUserPackagesToRemove = @() 33 | 34 | foreach($ProvisionedPackage in Get-AppxProvisionedPackage -Online) { 35 | foreach($PackageToRemove in $PackagesToRemove) { 36 | if($ProvisionedPackage.PackageName.Contains($PackageToRemove)) { 37 | $ProvisionPackagesToRemove += $ProvisionedPackage 38 | } 39 | } 40 | } 41 | 42 | foreach($AllUserPackage in Get-AppxPackage -AllUsers) { 43 | foreach($PackageToRemove in $PackagesToRemove) { 44 | if($AllUserPackage.PackageFullName.Contains($PackageToRemove)) { 45 | $AllUserPackagesToRemove += $AllUserPackage 46 | } 47 | } 48 | } 49 | 50 | $Total = $ProvisionPackagesToRemove.Count + $AllUserPackagesToRemove.Count 51 | $Progress = 0 52 | 53 | foreach($ProvisionedPackage in $ProvisionPackagesToRemove) { 54 | Write-Progress -Activity "Remove Apps" -Status ("Removing Provisioned App: " + $ProvisionedPackage.PackageName + "...") -PercentComplete (($Progress++ / $Total) * 100) 55 | $ProvisionedPackage | Remove-AppxProvisionedPackage -Online 56 | } 57 | 58 | foreach($AllUserPackage in $AllUserPackagesToRemove) { 59 | Write-Progress -Activity "Remove Apps" -Status ("Removing AllUsers App: " + $AllUserPackage.Name + "...") -PercentComplete (($Progress++ / $Total) * 100) 60 | $AllUserPackage | Remove-AppxPackage -AllUsers 61 | } -------------------------------------------------------------------------------- /ActiveDirectory/Get-Gpo-Setting.ps1: -------------------------------------------------------------------------------- 1 | $sDefaultGpoGuid = '{F6FE3FDE-4CD0-455D-B9BC-D134111BBF09}'; 2 | 3 | $sDefaultGpoGuid = "*$($sDefaultGpoGuid)*"; 4 | $ErrorActionPreference = "Stop"; 5 | #$aComputerGPOs = Get-ADObject -Filter {(ObjectClass -eq "groupPolicyContainer") -and (Name -eq '{F6FE3FDE-4CD0-455D-B9BC-D134111BBF09}')} 6 | $aComputerGPOs = Get-ADObject -Filter {(ObjectClass -eq "groupPolicyContainer")} 7 | #$aUserGPOs = Get-ADObject -Filter {(ObjectClass -eq "groupPolicyContainer") -and (gPCUserExtensionNames -like $sDefaultGpoGuid)} 8 | 9 | 10 | $test = @(); 11 | 12 | if ($aComputerGpos -ne $null) { 13 | $aReport = @() 14 | foreach ($oGpo in $aComputerGpos) { 15 | [XML]$xGpoReport = Get-GPOReport -Guid $oGpo.Name -ReportType XML; 16 | try { 17 | if (($xGpoReport.GPO.Computer.Enabled -eq 'true') -and (Test-Member $xGpoReport.GPO.Computer 'ExtensionData')) { 18 | $aSettings = @(); 19 | foreach ($oExt in $xGpoReport.GPO.Computer.ExtensionData) { 20 | $aSettings += $oExt.Extension.ChildNodes 21 | }##endforeach 22 | if ($aSettings.Count -ne 0) { 23 | echo '11111111' 24 | echo "======NAME:$($xGpoReport.GPO.Name)=========" 25 | $aSettings 26 | echo '22222222' 27 | foreach ($oSetting in $aSettings) { 28 | if ($oSetting.Name -match '^q\d+:RegistrySetting') { 29 | $xGpoReport.GPO.Name 30 | #$oSetting.ChildNodes 31 | #$sSetting = ($oSetting.ChildNodes).Item(0).InnerText 32 | #$sSetting 33 | #echo '22222222222222' 34 | #$sSetting = 'N/A - Actual setting is deeper in XML tree'; 35 | #$($oSetting.ChildNodes | Select-Object -ExpandProperty '#text')[0]; 36 | #echo '-----------start---------' 37 | #$oSetting.Name 38 | #$oSetting.ChildNodes 39 | #echo '-----------end---------' 40 | } elseif ($oSetting.Name -notmatch '^q\d+') { 41 | #$sSetting = $oSetting.Name; 42 | }##endif 43 | 44 | # $aReportItem = New-Object -TypeName PSObject -Property @{ 45 | # Name = $xGpoReport.GPO.Name 46 | # GUID = $oGpo.Name 47 | # SettingName = $sSetting 48 | # }##endnewobject 49 | # $aReportItem 50 | # $aReport += $aReportItem 51 | }##endforeach 52 | }##endif 53 | }##endif 54 | } catch { 55 | Write-Error $_.Exception 56 | }##endtrycatch 57 | }##endforeach 58 | }##endif 59 | 60 | $test | Select -Unique -------------------------------------------------------------------------------- /Software Updates/Get-MissingUpdatesViaMbsa.ps1: -------------------------------------------------------------------------------- 1 | function Get-MissingUpdates { 2 | [CmdletBinding()] 3 | [OutputType([System.Management.Automation.PSCustomObject])] 4 | param ( 5 | [Parameter(Mandatory, 6 | ValueFromPipeline, 7 | ValueFromPipelineByPropertyName)] 8 | [string]$ComputerName 9 | ) 10 | begin { 11 | function Get-32BitProgramFilesPath { 12 | if ((Get-Architecture) -eq 'x64') { 13 | ${ env:ProgramFiles(x86) } 14 | } else { 15 | $env:ProgramFiles 16 | } 17 | } 18 | 19 | function Get-Architecture { 20 | if ([System.Environment]::Is64BitOperatingSystem) { 21 | 'x64' 22 | } else { 23 | 'x86' 24 | } 25 | } 26 | 27 | $Output = @{ } 28 | } 29 | process { 30 | try { 31 | 32 | ## Remove any previous reports 33 | Get-ChildItem "$($Env:USERPROFILE)\SecurityScans\*" -Recurse -ea 'SilentlyContinue' | Remove-Item -Force -Recurse 34 | ## Run the report to create the output XML 35 | $ExeFilePath = "$(Get-32BitProgramFilesPath)\Microsoft Baseline Security Analyzer 2\mbsacli.exe" 36 | if (!(Test-Path $ExeFilePath)) { 37 | throw "$ExeFilePath not found" 38 | } 39 | & $ExeFilePath /target $ComputerName /wi /nvc /o %C% 2>&1> $null 40 | ## Convert the report to XML so I can use it 41 | ParseMbsaXml "$($Env:USERPROFILE)\SecurityScans\$($Computername.Split('.')[0]).mbsa" 42 | } catch { 43 | Write-Error "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 44 | } 45 | } 46 | } 47 | 48 | function ParseMbsaXml 49 | { 50 | [CmdletBinding()] 51 | param 52 | ( 53 | [Parameter(Mandatory)] 54 | [ValidateNotNullOrEmpty()] 55 | [string]$FilePath 56 | ) 57 | 58 | [xml]$ScanResults = Get-Content -Path $FilePath 59 | 60 | $UpdateSeverityLabels = @{ 61 | '0' = 'Other' 62 | '1' = 'Low' 63 | '2' = 'Moderate' 64 | '3' = 'Important' 65 | '4' = 'Critical' 66 | } 67 | 68 | $MissingUpdates = $ScanResults.SelectNodes("//Check[@Name='Windows Security Updates']/Detail/UpdateData[@IsInstalled='false']") 69 | foreach ($Update in $MissingUpdates) { 70 | $Ht = @{ } 71 | $Properties = $Update | Get-Member -Type Property 72 | foreach ($Prop in $Properties) { 73 | $Value = ($Update | select -expandproperty $Prop.Name) 74 | if ($Prop.Name -eq 'Severity') { 75 | $Value = $UpdateSeverityLabels[$Value] 76 | } 77 | $Ht[$Prop.Name] = $Value 78 | } 79 | [pscustomobject]$Ht 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /DSC/SQLServer/SQLServerStandalone.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 5 2 | 3 | Configuration SQLStandalone 4 | { 5 | param( 6 | [Parameter(Mandatory)] 7 | [ValidateNotNullOrEmpty()] 8 | [pscredential]$SetupCredential, 9 | 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [ValidatePattern('sxs$')] 13 | [string]$WindowsServerSource, 14 | 15 | [Parameter(Mandatory)] 16 | [ValidateNotNullOrEmpty()] 17 | [string]$SqlServerInstallSource, 18 | 19 | [Parameter(Mandatory)] 20 | [ValidateNotNullOrEmpty()] 21 | [string]$SysAdminAccount 22 | ) 23 | ## Download the xSQLServer module from the PowerShell Gallery 24 | Import-DscResource -Module xSQLServer 25 | 26 | ## Run this DSC configuration on the localhost (gathered from configuration data) 27 | Node $AllNodes.NodeName 28 | { 29 | ## Install a prerequisite Windows feature 30 | WindowsFeature "NET-Framework-Core" 31 | { 32 | Ensure = "Present" 33 | Name = "NET-Framework-Core" 34 | Source = $WindowsServerSource 35 | } 36 | 37 | ## Have DSC grab install bits from the SourcePath, install under the instance name with the features 38 | ## using the specified SQL Sys admin accounts. Be sure to install the Windows feature first. 39 | xSqlServerSetup 'SqlServerSetup' 40 | { 41 | DependsOn = "[WindowsFeature]NET-Framework-Core" 42 | SourcePath = $SqlServerInstallSource 43 | SetupCredential = $SetupCredential 44 | InstanceName = 'MSSQLSERVER' 45 | Features = 'SQLENGINE,FULLTEXT,RS,AS,IS' 46 | SQLSysAdminAccounts = $SysAdminAccount 47 | } 48 | 49 | ## Add firewall exceptions for SQL Server but run SQL server setup first. 50 | xSqlServerFirewall 'SqlFirewall' 51 | { 52 | DependsOn = '[xSqlServerSetup]SqlServerSetup' 53 | SourcePath = $SqlServerInstallSource 54 | InstanceName = 'MSSQLSERVER' 55 | Features = 'SQLENGINE,FULLTEXT,RS,AS,IS' 56 | } 57 | } 58 | } 59 | 60 | if (-not (Get-Module -Name xSqlServer -ListAvailable)) { 61 | Install-Module -Name 'xSqlServer' -Confirm:$false 62 | } 63 | 64 | SQLStandAlone -SetupCredential (Get-Credential) -WindowServerSource '' -SqlServerInstallSource '' -SysAdminAccount '' -ConfigurationData '.\ConfiguraitonData.psd1' 65 | Start-DscConfiguration –Wait –Force –Path '.\SQLStandalone' –Verbose -------------------------------------------------------------------------------- /mini-course/Get-ServerInformation.ps1: -------------------------------------------------------------------------------- 1 | $serversOuPath = 'OU=Servers,DC=powerlab,DC=local' 2 | $servers = Get-ADComputer -SearchBase $serversOuPath -Filter * | 3 | Select-Object -ExpandProperty Name 4 | 5 | $Header = @" 6 | 20 | "@ 21 | 22 | $report = foreach ($server in $servers) { 23 | $output = [ordered]@{ 24 | 'ServerName' = $null 25 | 'IPAddress' = $null 26 | 'OperatingSystem' = $null 27 | 'AvailableDriveSpace (GB)' = $null 28 | 'Memory (GB)' = $null 29 | 'UserProfilesSize (MB)' = $null 30 | 'StoppedServices' = $null 31 | } 32 | $getCimInstParams = @{ 33 | CimSession = (New-CimSession -ComputerName $server) 34 | } 35 | $output.ServerName = $server 36 | 37 | $userProfileSize = (Get-ChildItem -Path "\\$server\c$\Users\" -File -Recurse | Measure-Object -Property Length -Sum).Sum 38 | $output.'UserProfilesSize (MB)' = [math]::Round($userProfileSize / 1GB,1) 39 | 40 | $output.'AvailableDriveSpace (GB)' = Get-CimInstance @getCimInstParams -ClassName Win32_LogicalDisk | Select-Object -Property DeviceID, @{Name='FreeSpace'; Expression={ [Math]::Round(($_.Freespace / 1GB), 1) } } 41 | 42 | $output.'OperatingSystem' = (Get-CimInstance @getCimInstParams -ClassName Win32_OperatingSystem).Caption 43 | 44 | $output.'Memory (GB)' = (Get-CimInstance @getCimInstParams -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum /1GB 45 | 46 | $output.'IPAddress' = (Get-CimInstance @getCimInstParams -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'").IPAddress[0] 47 | 48 | $output.StoppedServices = (Get-Service -ComputerName $server | Where-Object { $_.Status -eq 'Stopped' } | Measure-Object).Count 49 | 50 | Remove-CimSession @getCimInstParams 51 | 52 | [pscustomobject]$output 53 | } 54 | 55 | $reportfinal = $report | ConvertTo-Html -Fragment 56 | ConvertTo-HTML -PreContent "

Server Information Report

" -PostContent $reportFINAL -Head $Header | Out-File ServerReport.html 57 | -------------------------------------------------------------------------------- /DHCP/Get-DhcpLease.Tests.ps1: -------------------------------------------------------------------------------- 1 | describe 'Get-DhcpLease' { 2 | 3 | mock 'Get-DhcpServerv4Scope' { 4 | [pscustomobject]@{ 'ScopeId' = '10.10.10.0' } 5 | } 6 | 7 | mock 'Get-DhcpServerv4Lease' { 8 | return $null 9 | } 10 | 11 | mock 'Get-DhcpServerInDc' { 12 | @( 13 | [pscustomobject]@{ 'DNSName' = 'SRV1' } 14 | [pscustomobject]@{ 'DNSName' = 'SRV2' } 15 | ) 16 | } 17 | 18 | it 'queries all DHCP servers in domain if no DHCP server passed' { 19 | 20 | @('SRV1', 'SRV2') 21 | { 22 | mock 'Test-Connection' { 23 | $true 24 | } -ParameterFilter { $Computername -eq $_ } 25 | 26 | & "$PSScriptRoot\Get-DhcpLease.ps1" 27 | 28 | Assert-MockCalled 'Test-Connection' 29 | } 30 | } 31 | 32 | it 'only queries DHCP server passed' { 33 | 34 | mock 'Test-Connection' { 35 | $true 36 | } -ParameterFilter { $Computername -eq 'SRV1' } 37 | 38 | & "$PSScriptRoot\Get-DhcpLease.ps1" -DhcpServer 'SRV1' 39 | 40 | Assert-MockCalled 'Test-Connection' 41 | 42 | } 43 | 44 | it 'limits leases to only those matching IP address' { 45 | 46 | mock 'Get-DhcpServerv4Lease' { 47 | return $null 48 | } -ParamterFilter { $IpAddress -eq '1.1.1.1' } 49 | 50 | & "$PSScriptRoot\Get-DhcpLease.ps1" -IpAddress '1.1.1.1' -DhcpServer 'SRV1' 51 | 52 | Assert-MockCalled 'Get-DhcpServerv4Lease' 53 | } 54 | 55 | it 'limits leases to only those matching hostname' { 56 | 57 | mock 'Get-DhcpServerv4Lease' { 58 | return [pscustomobject]@{ 'HostName' = 'SRV2' } 59 | } -ParamterFilter { $HostName -eq 'SRV2' } 60 | 61 | & "$PSScriptRoot\Get-DhcpLease.ps1" -HostName 'SRV2' -DhcpServer 'SRV1' 62 | 63 | Assert-MockCalled 'Get-DhcpServerv4Lease' 64 | 65 | } 66 | 67 | it 'limits leases to only those matching MAC address' { 68 | 69 | mock 'Get-DhcpServerv4Lease' { 70 | return $null 71 | } -ParamterFilter { $ClientId -eq '00:00' } 72 | 73 | & "$PSScriptRoot\Get-DhcpLease.ps1" -MacAddress '00:00' -DhcpServer 'SRV1' 74 | 75 | Assert-MockCalled 'Get-DhcpServerv4Lease' 76 | 77 | } 78 | 79 | it 'returns a non-terminating error if a DHCP server to be queried is offline' { 80 | 81 | mock 'Test-Connection' { 82 | return $false 83 | } -ParamterFilter {$ComputerName -eq 'SRV1'} 84 | 85 | & "$PSScriptRoot\Get-DhcpLease.ps1" -DhcpServer 'SRV1' -ev myErr -ea SilentlyContinue 86 | 87 | Assert-MockCalled 'Test-Connection' 88 | $myErr | should not be nullorempty 89 | 90 | 91 | } 92 | } -------------------------------------------------------------------------------- /Inventorying-Reporting Tools/Get-FreeHardDriveSpace.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This finds the total hard drive free space for one or multiple hard drive partitions 4 | .DESCRIPTION 5 | This finds the total hard drive free space for one or multiple hard drive partitions. It returns free space 6 | rounded to the nearest SizeOutputLabel parameter 7 | .PARAMETER DriveLetter 8 | This is the drive letter of the hard drive partition you'd like to query. By default, all drive letters are queried. 9 | .PARAMETER SizeOutputLabel 10 | In what size increments you'd like the size returned (KB, MB, GB, TB). Defaults to MB. 11 | .PARAMETER Computername 12 | The computername(s) you'd like to find free space on. This defaults to the local machine. 13 | .EXAMPLE 14 | PS C:\> Get-DriveFreeSpace -DriveLetter 'C','D' 15 | This example retrieves the free space on the C and D drive partition. 16 | #> 17 | [CmdletBinding()] 18 | [OutputType([array])] 19 | param 20 | ( 21 | [string[]]$Computername = 'localhost', 22 | [Parameter(ValueFromPipeline = $true, 23 | ValueFromPipelineByPropertyName = $true)] 24 | [ValidatePattern('[A-Z]')] 25 | [string]$DriveLetter, 26 | [ValidateSet('KB','MB','GB','TB')] 27 | [string]$SizeOutputLabel = 'MB' 28 | 29 | ) 30 | 31 | Begin { 32 | try { 33 | $WhereQuery = "SELECT FreeSpace,DeviceID FROM Win32_Logicaldisk" 34 | 35 | if ($PsBoundParameters.DriveLetter) { 36 | $WhereQuery += ' WHERE' 37 | $BuiltQueryParams = { @() }.Invoke() 38 | foreach ($Letter in $DriveLetter) { 39 | $BuiltQueryParams.Add("DeviceId = '$DriveLetter`:'") 40 | } 41 | $WhereQuery = "$WhereQuery $($BuiltQueryParams -join ' OR ')" 42 | } 43 | Write-Debug "Using WQL query $WhereQuery" 44 | $WmiParams = @{ 45 | 'Query' = $WhereQuery 46 | 'ErrorVariable' = 'MyError'; 47 | 'ErrorAction' = 'SilentlyContinue' 48 | } 49 | } catch { 50 | Write-Error $_.Exception.Message 51 | } 52 | } 53 | Process { 54 | try { 55 | foreach ($Computer in $Computername) { 56 | $WmiParams.Computername = $Computer 57 | $WmiResult = Get-WmiObject @WmiParams 58 | if ($MyError) { 59 | throw $MyError 60 | } 61 | foreach ($Result in $WmiResult) { 62 | if ($Result.Freespace) { 63 | [pscustomobject]@{ 64 | 'Computername' = $Computer; 65 | 'DriveLetter' = $Result.DeviceID; 66 | 'Freespace' = [int]($Result.FreeSpace / "1$SizeOutputLabel") 67 | } 68 | } 69 | } 70 | } 71 | } catch { 72 | Write-Error $_.Exception.Message 73 | } 74 | -------------------------------------------------------------------------------- /ActiveDirectory/FindUnusedUserAccounts.ps1: -------------------------------------------------------------------------------- 1 | ## Set a variable to give control over the script where to just find the users 2 | ## or find and also remove them. 3 | $remove_users_found = $false 4 | 5 | ## Set today's date as a variable now since this will not change (today) 6 | ## If this were in the Where-Object scriptblock the Get-Date cmdlet would be executed 7 | ## once for every user object that's retrieved 8 | $today_object = Get-Date 9 | 10 | ## Find the date in a string to write to the log 11 | $today_string = get-date -Format 'MM-dd-yyyy hh:mm tt' 12 | 13 | ## Create the Where-Object scriptblock ahead of time. This is done for easy reading 14 | ## The AD Filter is not used due to the complexity of the conditions 15 | $unused_conditions_met = { 16 | ## Ensure no built-in AD user objects are removed inadvertantly 17 | !$_.isCriticalSystemObject -and 18 | ## The account is disabled (account cannot be used) 19 | (!$_.Enabled -or 20 | ## The password is expired (account cannot be used) 21 | $_.PasswordExpired -or 22 | ## The account has never been used 23 | !$_.LastLogonDate -or 24 | ## The account hasn't been used for 60 days 25 | ($_.LastLogonDate.AddDays(60) -lt $today_object)) 26 | } 27 | 28 | ## Query all Active Directory user accounts with all of the conditions we defined above 29 | $unused_accounts = Get-ADUser -Filter * -Properties passwordexpired,lastlogondate,isCriticalSystemobject | Where-Object $unused_conditions_met | 30 | Select-Object @{Name='Username';Expression={$_.samAccountName}}, 31 | @{Name='FirstName';Expression={$_.givenName}}, 32 | @{Name='LastName';Expression={$_.surName}}, 33 | @{Name='Enabled';Expression={$_.Enabled}}, 34 | @{Name='PasswordExpired';Expression={$_.PasswordExpired}}, 35 | @{Name='LastLoggedOnDaysAgo';Expression={if (!$_.LastLogonDate) { 'Never' } else { ($today_object - $_.LastLogonDate).Days}}}, 36 | @{Name='Operation';Expression={'Found'}}, 37 | @{Name='On';Expression={$today_string}} 38 | 39 | ## Create the log file of what the script found 40 | $unused_accounts | Export-Csv -Path unused_user_accounts.csv -NoTypeInformation 41 | 42 | ## If set, remove all of the accounts found and append to the log 43 | if ($remove_users_found) { 44 | foreach ($account in $unused_accounts) { 45 | Remove-ADUser $account.Username -Confirm:$false 46 | Add-Content -Value "$($account.UserName),,,,,,Removed,$today_string" -Path unused_user_accounts.csv 47 | } 48 | } -------------------------------------------------------------------------------- /mini-course/Get-ServerInformation2.0.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [Parameter(Mandatory)] 4 | [string[]]$ComputerName, 5 | 6 | [Parameter(Mandatory)] 7 | [pscredential]$Credential 8 | ) 9 | 10 | $Header = @" 11 | 25 | "@ 26 | 27 | $scriptBlock = { 28 | $output = @{ 29 | 'ServerName' = (hostname) 30 | 'IPAddress' = $null 31 | 'OperatingSystem' = $null 32 | 'AvailableDriveSpace (GB)' = $null 33 | 'Memory (GB)' = $null 34 | 'UserProfilesSize (MB)' = $null 35 | 'StoppedServices' = $null 36 | } 37 | 38 | $userProfileSize = (Get-ChildItem -Path 'C:\Users' -File -Recurse | Measure-Object -Property Length -Sum).Sum 39 | $output.'UserProfilesSize (MB)' = [math]::Round($userProfileSize / 1GB, 1) 40 | 41 | $output.'IPAddress' = (Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'").IPAddress[0] 42 | 43 | $output.'OperatingSystem' = (Get-CimInstance -ClassName Win32_OperatingSystem).Caption 44 | 45 | $output.'Memory (GB)' = (Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum /1GB 46 | 47 | $output.'AvailableDriveSpace (GB)' = (Get-CimInstance -ClassName Win32_LogicalDisk | 48 | Select-Object -Property DeviceID, @{Name='FreeSpace'; Expression={ [Math]::Round(($_.Freespace / 1GB), 1) } } | 49 | Measure-Object -Property FreeSpace -Sum).Sum 50 | 51 | $output.'StoppedServices' = (Get-Service | Where-Object { $_.Status -eq 'Stopped' } | Measure-Object).Count 52 | 53 | [pscustomobject]$output 54 | } 55 | 56 | $icmParams = @{ 57 | ComputerName = $ComputerName 58 | ScriptBlock = $scriptBlock 59 | Credential = $Credential 60 | } 61 | 62 | $report = Invoke-Command @icmParams | Select-Object -Property * -ExcludeProperty 'RunspaceId','PSComputerName','PSShowComputerName' | ConvertTo-Html -Fragment 63 | 64 | ConvertTo-HTML -PreContent "

Server Information Report

" -PostContent $report -Head $Header | Out-File ServerReport.html 65 | Invoke-Item ServerReport.html 66 | -------------------------------------------------------------------------------- /Random Stuff/Invoke-WindowsDiskCleanup.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This script invokes the Windows Disk Cleanup utility, enables all rules and runs it. 4 | 5 | .EXAMPLE 6 | PS> .\Invoke-WindowsDiskCleanup.ps1 7 | 8 | #> 9 | 10 | Write-Log -Message 'Clearing CleanMgr.exe automation settings.' 11 | 12 | $getItemParams = @{ 13 | Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' 14 | Name = 'StateFlags0001' 15 | ErrorAction = 'SilentlyContinue' 16 | } 17 | Get-ItemProperty @getItemParams | Remove-ItemProperty -Name StateFlags0001 -ErrorAction SilentlyContinue 18 | 19 | $enabledSections = @( 20 | 'Active Setup Temp Folders' 21 | 'BranchCache' 22 | 'Content Indexer Cleaner' 23 | 'Device Driver Packages' 24 | 'Downloaded Program Files' 25 | 'GameNewsFiles' 26 | 'GameStatisticsFiles' 27 | 'GameUpdateFiles' 28 | 'Internet Cache Files' 29 | 'Memory Dump Files' 30 | 'Offline Pages Files' 31 | 'Old ChkDsk Files' 32 | 'Previous Installations' 33 | 'Recycle Bin' 34 | 'Service Pack Cleanup' 35 | 'Setup Log Files' 36 | 'System error memory dump files' 37 | 'System error minidump files' 38 | 'Temporary Files' 39 | 'Temporary Setup Files' 40 | 'Temporary Sync Files' 41 | 'Thumbnail Cache' 42 | 'Update Cleanup' 43 | 'Upgrade Discarded Files' 44 | 'User file versions' 45 | 'Windows Defender' 46 | 'Windows Error Reporting Archive Files' 47 | 'Windows Error Reporting Queue Files' 48 | 'Windows Error Reporting System Archive Files' 49 | 'Windows Error Reporting System Queue Files' 50 | 'Windows ESD installation files' 51 | 'Windows Upgrade Log Files' 52 | ) 53 | 54 | Write-Verbose -Message 'Adding enabled disk cleanup sections...' 55 | foreach ($keyName in $enabledSections) { 56 | $newItemParams = @{ 57 | Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\$keyName" 58 | Name = 'StateFlags0001' 59 | Value = 1 60 | PropertyType = 'DWord' 61 | ErrorAction = 'SilentlyContinue' 62 | } 63 | $null = New-ItemProperty @newItemParams 64 | } 65 | 66 | Write-Verbose -Message 'Starting CleanMgr.exe...' 67 | Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -NoNewWindow -Wait 68 | 69 | Write-Verbose -Message 'Waiting for CleanMgr and DismHost processes...' 70 | Get-Process -Name cleanmgr,dismhost -ErrorAction SilentlyContinue | Wait-Process 71 | 72 | # if (Test-Path $env:SystemRoot\Logs\CBS\DeepClean.log) { 73 | # if (Select-String -Path $env:SystemRoot\Logs\CBS\DeepClean.log -Pattern 'Total size of superseded packages:' -Quiet) { 74 | 75 | # } 76 | # } -------------------------------------------------------------------------------- /Exchange/SetSignatures/create_signatures.ps1: -------------------------------------------------------------------------------- 1 | $UserCredential = Get-Credential 2 | $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection 3 | Import-PSSession $Session -DisableNameChecking 4 | 5 | #set folder location for files, the folder must already exist 6 | $cur_path = Get-Location 7 | $mailboxes = Import-Csv "$($cur_path)\signatures_data.csv" 8 | 9 | $mailboxes | foreach { 10 | 11 | $template = "$($_.TEMPLATE)" 12 | 13 | $user = "$($_.USER)" 14 | $full_name = "$($_.NAME)" 15 | $role = "$($_.ROLE)" 16 | $tel = "$($_.TEL)" 17 | $cell = "$($_.CELL)" 18 | $skype = "$($_.SKYPE)" 19 | $mail = "$($_.MAIL)" 20 | 21 | if ($tel.trim() -ne '') { 22 | $tel=' - Tel: ' + $tel; 23 | } 24 | if ($cell.trim() -ne '') { 25 | $cell=' - Cell: ' + $cell; 26 | } 27 | if ($skype.trim() -ne '') { 28 | $skype=' - Skype: ' + $skype; 29 | } 30 | 31 | 32 | $template_file = "$($cur_path)\$template.html" 33 | $output_file_html = "$($cur_path)\data\$($user).html" 34 | 35 | $template_text = Get-Content -Path $template_file 36 | $template_text = $template_text -replace '%%NAME%%', $full_name 37 | $template_text = $template_text -replace '%%ROLE%%', $role 38 | $template_text = $template_text -replace '%%MAIL%%', $mail 39 | $template_text = $template_text -replace '%%TEL%%', $tel 40 | $template_text = $template_text -replace '%%CELL%%', $cell 41 | $template_text = $template_text -replace '%%SKYPE%%', $skype 42 | 43 | 44 | $template_file_txt = "$($cur_path)\$template.txt" 45 | $output_file_txt = "$($cur_path)\data\$($user).txt" 46 | 47 | $template_text_txt = Get-Content -Path $template_file_txt 48 | $template_text_txt = $template_text_txt -replace '%%NAME%%', $full_name 49 | $template_text_txt = $template_text_txt -replace '%%ROLE%%', $role 50 | $template_text_txt = $template_text_txt -replace '%%MAIL%%', $mail 51 | $template_text_txt = $template_text_txt -replace '%%TEL%%', $tel 52 | $template_text_txt = $template_text_txt -replace '%%CELL%%', $cell 53 | $template_text_txt = $template_text_txt -replace '%%SKYPE%%', $skype 54 | 55 | 56 | Set-Content -Path $output_file_html -Value $template_text 57 | Set-Content -Path $output_file_txt -Value $template_text_txt 58 | 59 | Write-Host "Now attempting to set signature for " $_.user 60 | set-mailboxmessageconfiguration -identity $_.user -signaturehtml (get-content $output_file_html) -signaturetext $txt_signature -autoaddsignature $true 61 | } -------------------------------------------------------------------------------- /PowerShell Internals/Wait-Action.ps1: -------------------------------------------------------------------------------- 1 | <#PSScriptInfo 2 | .VERSION 1.0 3 | .GUID 389989f2-626a-45cc-aa5c-2df2f93cee03 4 | .AUTHOR Adam Bertram 5 | .COMPANYNAME Adam the Automator, LLC 6 | .PROJECTURI https://github.com/adbertram/Random-PowerShell-Work/blob/master/PowerShell%20Internals/Wait-Action.ps1 7 | #> 8 | 9 | <# 10 | .SYNOPSIS 11 | A script to wait for an action to finish. 12 | 13 | .DESCRIPTION 14 | This script executes a scriptblock represented by the Condition parameter continually while the result returns 15 | anything other than $false or $null. 16 | 17 | .PARAMETER Condition 18 | A mandatory scriptblock parameter representing the code to execute to check the action condition. This code 19 | will be continually executed until it returns $false or $null. 20 | 21 | .PARAMETER Timeout 22 | A mandatory integer represneting the time (in seconds) to wait for the condition to complete. 23 | 24 | .PARAMETER ArgumentList 25 | An optional collection of one or more objects to pass to the scriptblock at run time. To use this parameter, 26 | be sure you have a param() block in the Condition scriptblock to accept these parameters. 27 | 28 | .PARAMETER RetryInterval 29 | An optional integer representing the time (in seconds) between the code execution in Condition. 30 | 31 | .EXAMPLE 32 | PS> Wait-Action -Condition { (Get-Job).State | where { $_ -ne 'Running' } -Timeout 10 33 | 34 | This example will wait for all background jobs to complete for up to 10 seconds. 35 | #> 36 | 37 | [OutputType([void])] 38 | [CmdletBinding()] 39 | param 40 | ( 41 | [Parameter(Mandatory)] 42 | [ValidateNotNullOrEmpty()] 43 | [scriptblock]$Condition, 44 | 45 | [Parameter(Mandatory)] 46 | [ValidateNotNullOrEmpty()] 47 | [int]$Timeout, 48 | 49 | [Parameter()] 50 | [ValidateNotNullOrEmpty()] 51 | [object[]]$ArgumentList, 52 | 53 | [Parameter()] 54 | [ValidateNotNullOrEmpty()] 55 | [int]$RetryInterval = 5 56 | ) 57 | try 58 | { 59 | $timer = [Diagnostics.Stopwatch]::StartNew() 60 | while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (& $Condition $ArgumentList)) { 61 | Start-Sleep -Seconds $RetryInterval 62 | $totalSecs = [math]::Round($timer.Elapsed.TotalSeconds,0) 63 | Write-Verbose -Message "Still waiting for action to complete after [$totalSecs] seconds..." 64 | } 65 | $timer.Stop() 66 | if ($timer.Elapsed.TotalSeconds -gt $Timeout) { 67 | throw 'Action did not complete before timeout period.' 68 | } else { 69 | Write-Verbose -Message 'Action completed before timeout period.' 70 | } 71 | } 72 | catch 73 | { 74 | Write-Error -Message $_.Exception.Message 75 | } -------------------------------------------------------------------------------- /Random Stuff/New-Employee.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter()] 3 | [ValidateNotNullOrEmpty()] 4 | [string]$CsvFilePath 5 | ) 6 | 7 | function New-CompanyAdUser { 8 | [CmdletBinding()] 9 | param 10 | ( 11 | [Parameter(Mandatory)] 12 | [ValidateNotNullOrEmpty()] 13 | [pscustomobject]$EmployeeRecord 14 | ) 15 | 16 | ## Generate a random password 17 | $password = [System.Web.Security.Membership]::GeneratePassword((Get-Random -Minimum 20 -Maximum 32), 3) 18 | $secPw = ConvertTo-SecureString -String $password -AsPlainText -Force 19 | 20 | ## Generate a first initial/last name username 21 | $userName = "$($EmployeeRecord.FirstName.Substring(0,1))$($EmployeeRecord.LastName))" 22 | 23 | ## Create the user 24 | $NewUserParameters = @{ 25 | GivenName = $EmployeeRecord.FirstName 26 | Surname = $EmployeeRecord.LastName 27 | Name = $userName 28 | AccountPassword = $secPw 29 | } 30 | New-AdUser @NewUserParameters 31 | 32 | ## Add the user to the department group 33 | Add-AdGroupMember -Identity $EmployeeRecord.Department -Members $userName 34 | } 35 | 36 | function New-CompanyUserFolder { 37 | [CmdletBinding()] 38 | param 39 | ( 40 | [Parameter(Mandatory)] 41 | [ValidateNotNullOrEmpty()] 42 | [pscustomobject]$EmployeeRecord 43 | ) 44 | 45 | $fileServer = 'FS1' 46 | 47 | $null = New-Item -Path "\\$fileServer\Users\$($EmployeeRecord.FirstName)$($EmployeeRecord.LastName)" -ItemType Directory 48 | 49 | } 50 | 51 | function Register-CompanyMobileDevice { 52 | [CmdletBinding()] 53 | param 54 | ( 55 | [Parameter(Mandatory)] 56 | [ValidateNotNullOrEmpty()] 57 | [pscustomobject]$EmployeeRecord 58 | ) 59 | 60 | ## Send an email for now. If we ever can automate this, we'll do it here. 61 | $sendMailParams = @{ 62 | 'From' = 'EmailAddress@gmail.com' 63 | 'To' = 'SomeOtherAddress@whatever.com' 64 | 'Subject' = 'A new mobile device needs to be registered' 65 | 'Body' = "Employee: $($EmployeeRecord.FirstName) $($EmployeeRecord.LastName)" 66 | 'SMTPServer' = 'smtpserver.something.local' 67 | 'SMTPPort' = '587' 68 | } 69 | 70 | Send-MailMessage @sendMailParams 71 | 72 | } 73 | 74 | function Read-Employee { 75 | [CmdletBinding()] 76 | param 77 | ( 78 | [Parameter()] 79 | [ValidateNotNullOrEmpty()] 80 | [string]$CsvFilePath = $CsvFilePath 81 | ) 82 | 83 | Import-Csv -Path $CsvFilePath 84 | 85 | } 86 | 87 | 88 | $functions = 'New-CompanyAdUser','New-CompanyUserFolder','Register-CompanyMobileDevice' 89 | foreach ($employee in (Read-Employee)) { 90 | foreach ($function in $functions) { 91 | & $function -EmployeeRecord $employee 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /WMI-CIM/Get-MyCimInstance.ps1: -------------------------------------------------------------------------------- 1 | function Get-MyCimInstance { 2 | <# 3 | .SYNOPSIS 4 | This function provides a way to query CIM and WinRM but with an automatic failover to DCOM. 5 | .PARAMETER Computername 6 | The name of the computer to query 7 | .PARAMETER Class 8 | The WMI class 9 | .PARAMETER Namespace 10 | The WMI namespace 11 | .PARAMETER Filter 12 | The WQL filter 13 | .PARAMETER Property 14 | If only a single property is needed in the output, specify that here. 15 | #> 16 | [CmdletBinding()] 17 | param ( 18 | [Parameter(Mandatory, ValueFromPipeline)] 19 | [string[]]$Computername, 20 | [Parameter(Mandatory)] 21 | [Alias('ClassName')] 22 | [string]$Class, 23 | [Parameter()] 24 | [string]$Namespace, 25 | [Parameter()] 26 | [string]$Filter, 27 | [Parameter()] 28 | [string]$Property 29 | ) 30 | process { 31 | ## We're depending on using the ErrorVariabl on a per cmdlet basis. 32 | $ErrorActionBefore = $ErrorActionPreference 33 | $ErrorActionPreference = 'SilentlyContinue' 34 | foreach ($Computer in $Computername) { 35 | try { 36 | ## Build the parameters for the WinRm query 37 | $Params = @{ 'Computername' = $Computer; 'Class' = $Class; 'ErrorAction' = 'SilentlyContinue' } 38 | if ($PsBoundParameters.Property) { 39 | $Params.Property = $PsBoundParameters.Property 40 | } 41 | if ($Filter) { 42 | $Params.Filter = $Filter 43 | } 44 | if ($Namespace) { 45 | $Params.Namespace = $Namespace 46 | } 47 | Write-Verbose "Attempting to query '$Computer' via WinRM" 48 | $Result = Get-CimInstance @Params -ev WinRmError 49 | if ($WinRmError) { 50 | Write-Verbose "Failed to query $Computer via WinRM. Attempting with DCOM" 51 | ## Build parameters for the DCOM query 52 | $GwmiParams = @{ 'Computername' = $Computer; 'Class' = $Class; 'ErrorAction' = 'SilentlyContinue' } 53 | if ($Filter) { 54 | $GwmiParams.Filter = $Filter 55 | } 56 | if ($Namespace) { 57 | $GwmiParams.Namespace = $Namespace 58 | } 59 | if ($Property) { 60 | $GwmiParams.Property = $Property 61 | } 62 | $Result = Get-WmiObject @GwmiParams -ev DcomError 63 | if ($DcomError) { 64 | throw 'Failed query via DCOM. Giving up.' 65 | } else { 66 | $ErrorActionPreference = $ErrorActionBefore 67 | $Result 68 | } 69 | } else { 70 | $ErrorActionPreference = $ErrorActionBefore 71 | $Result 72 | } 73 | } catch { 74 | $ErrorActionPreference = $ErrorActionBefore 75 | Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 76 | } 77 | } 78 | 79 | } 80 | } -------------------------------------------------------------------------------- /Azure/Set-Get-AzrDnsServerAddress.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module AzureRm.Compute 2 | #Requires -Version 4 3 | 4 | function Get-AzrDnsServerAddress 5 | { 6 | [CmdletBinding()] 7 | [OutputType('Microsoft.Azure.Commands.Network.Models.PSNetworkInterfaceDnsSettings')] 8 | param 9 | ( 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [string]$VMName, 13 | 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [string]$ResourceGroupName 17 | ) 18 | #region Find the VM 19 | if ($PSBoundParameters.ContainsKey('ResourceGroupName')) 20 | { 21 | $getParams = @{ 22 | 'ResourceGroupName' = $ResourceGroupName 23 | 'VMName' = $VMName 24 | } 25 | $vm = Get-AzureRmVM -VMName $VMName -ResourceGroupName $ResourceGroupName 26 | } 27 | else 28 | { 29 | if (-not ($vm = Get-AzureRmVM | Where-Object { $_.Name -eq $VMName })) 30 | { 31 | throw "The VM [$($VMName)] was not found." 32 | } 33 | } 34 | #endregion 35 | 36 | $vnic = $vm | Get-AzureRmNetworkInterface 37 | $vnic.DnsSettings.AppliedDnsServers 38 | } 39 | 40 | function Set-AzrDnsServerAddress 41 | { 42 | [CmdletBinding()] 43 | param 44 | ( 45 | [Parameter(Mandatory)] 46 | [ValidateNotNullOrEmpty()] 47 | [string]$VMName, 48 | 49 | [Parameter(Mandatory)] 50 | [ValidateNotNullOrEmpty()] 51 | [string[]]$IpAddress, 52 | 53 | [Parameter()] 54 | [ValidateNotNullOrEmpty()] 55 | [switch]$Restart, 56 | 57 | [Parameter()] 58 | [ValidateNotNullOrEmpty()] 59 | [string]$ResourceGroupName 60 | 61 | ) 62 | 63 | #region Find the VM 64 | if ($PSBoundParameters.ContainsKey('ResourceGroupName')) 65 | { 66 | $getParams = @{ 67 | 'ResourceGroupName' = $ResourceGroupName 68 | 'VMName' = $VMName 69 | } 70 | $vm = Get-AzureRmVM -VMName $VMName -ResourceGroupName $ResourceGroupName 71 | } 72 | else 73 | { 74 | if (-not ($vm = Get-AzureRmVM | Where-Object { $_.Name -eq $VMName })) 75 | { 76 | throw "The VM [$($VMName)] was not found." 77 | } 78 | } 79 | #endregion 80 | 81 | if ((Get-AzrDnsServerAddress -VMName $VMName) -ne $IpAddress) 82 | { 83 | Write-Verbose -Message 'Changing DNS settings...' 84 | $vnic = $vm | Get-AzureRmNetworkInterface 85 | $vnic.DnsSettings.DnsServers = $IpAddress 86 | $null = $vnic | Set-AzureRmNetworkInterface 87 | if (-not $Restart.IsPresent) 88 | { 89 | Write-Warning -Message 'vNIC has been updated but -Restart was not chosen. The VM will not see these new DNS servers until it has been restarted.' 90 | } 91 | else 92 | { 93 | Write-Verbose -Message 'Restarting VM after successful vNIC change...' 94 | $vm | Restart-AzureRmVM 95 | } 96 | } 97 | else 98 | { 99 | Write-Verbose -Message 'DNS settings are already set.' 100 | } 101 | } -------------------------------------------------------------------------------- /Azure/New-AzureNanoServer.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | 3 | #region Download Windows Server 2016 TP4 4 | 5 | 6 | 7 | #endregion 8 | 9 | #region Copy the Nano Server module and conversion script from the Server 2016 ISO 10 | 11 | 12 | 13 | #endregion 14 | 15 | Import-Module "$nanoFolderPath\NanoServerImageGenerator.psm1" 16 | New-NanoServerImage -MediaPath $winSrvDrivePath -BasePath $nanoFolderPath -TargetPath "$nanoFolderPath\Nano.vhd" -ComputerName NanoServer –GuestDrivers -AdministratorPassword p@$$w0rd1 17 | 18 | 19 | #region Add necessary packages to the Nano VHD 20 | 21 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-NanoServer-Compute-Package.cab 22 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-NanoServer-FailoverCluster-Package.cab 23 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-NanoServer-Guest-Package.cab 24 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-NanoServer-OEM-Drivers-Package.cab 25 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-NanoServer-Storage-Package.cab 26 | #Add-WindowsPackage –Path E:\ –PackagePath C:\NanoServer\Packages\Microsoft-OneCore-ReverseForwarders-Package.cab 27 | 28 | #endregion 29 | 30 | ## Sysprep the VHD 31 | 32 | #region Ensure Azure is setup in PowerShell 33 | 34 | Import-Module Azure 35 | Add-AzureAccount 36 | Select-AzureSubscription -Default $subscription 37 | 38 | #endregion 39 | 40 | #region Create storage account 41 | 42 | ## Check the Azure location 43 | Get-AzureLocation | select name 44 | 45 | ## Check if the affinity group is there 46 | $affinityGroup = 'somegroup' 47 | Get-AffinityGroup -Name $affinityGroup -ea Ignore 48 | 49 | New-AzureAffinityGroup -Name 'testgroup' -Location 'Central US' 50 | 51 | Get-AzureStorageAccount -Name 52 | New-AzureStorageAccount -StorageAccountName 'adamstorage123' -AffinityGroup testgroup 53 | 54 | Get-AzureStorageAccount | Format-Table -Property Label 55 | $storageAccountName = "jrprlabstor01" 56 | Get-AzureStorageContainer 57 | 58 | #endregion 59 | 60 | #region Add the Azure VHD 61 | $LocalVHD = "C:\NanoServer\NanoServer.vhd" 62 | 63 | $storageEndpoint = (Get-AzureStorageAccount -StorageAccountName adamstorage123).Endpoints[0].Trim('/') 64 | 65 | ## Azure location --> Azure affinity group --> Azure storage account --> Azure storage container 66 | Get-AzureStorageAccount | Get-AzureStorageContainer 67 | $imagesContainer = 'testcontainer' ## ????? 68 | 69 | $AzureVHD = "$storageEndpoint/$imagesContainer/nano.vhd" 70 | Add-AzureVhd -LocalFilePath $LocalVHD -Destination $AzureVHD 71 | 72 | 73 | Add-AzureVMImage -ImageName 'nano.vhd' -MediaLocation -OS 'Windows' 74 | 75 | #Identify the URL for the container in the storage account 76 | # we set in the previous command. 77 | 78 | #endregion 79 | 80 | -------------------------------------------------------------------------------- /Processes/Invoke-Program.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-Program { 2 | <# 3 | .SYNOPSIS 4 | This is a helper function that will invoke the SQL installers via command-line. 5 | 6 | .EXAMPLE 7 | PS> Invoke-Program -FilePath C:\file.exe -ComputerName SRV1 8 | 9 | #> 10 | [CmdletBinding()] 11 | [OutputType([System.Management.Automation.PSObject])] 12 | param 13 | ( 14 | [Parameter(Mandatory)] 15 | [ValidateNotNullOrEmpty()] 16 | [string]$FilePath, 17 | 18 | [Parameter(Mandatory)] 19 | [string]$ComputerName, 20 | 21 | [Parameter()] 22 | [ValidateNotNullOrEmpty()] 23 | [string]$ArgumentList, 24 | 25 | [Parameter()] 26 | [bool]$ExpandStrings = $false, 27 | 28 | [Parameter()] 29 | [ValidateNotNullOrEmpty()] 30 | [string]$WorkingDirectory, 31 | 32 | [Parameter()] 33 | [ValidateNotNullOrEmpty()] 34 | [uint32[]]$SuccessReturnCodes = @(0, 3010) 35 | ) 36 | begin { 37 | $ErrorActionPreference = 'Stop' 38 | } 39 | process { 40 | try { 41 | Write-Verbose -Message "Acceptable success return codes are [$($SuccessReturnCodes -join ',')]" 42 | 43 | $scriptBlock = { 44 | $VerbosePreference = $using:VerbosePreference 45 | 46 | $processStartInfo = New-Object System.Diagnostics.ProcessStartInfo; 47 | $processStartInfo.FileName = $Using:FilePath; 48 | if ($Using:ArgumentList) { 49 | $processStartInfo.Arguments = $Using:ArgumentList; 50 | if ($Using:ExpandStrings) { 51 | $processStartInfo.Arguments = $ExecutionContext.InvokeCommandWithCred.ExpandString($Using:ArgumentList); 52 | } 53 | } 54 | if ($Using:WorkingDirectory) { 55 | $processStartInfo.WorkingDirectory = $Using:WorkingDirectory; 56 | if ($Using:ExpandStrings) { 57 | $processStartInfo.WorkingDirectory = $ExecutionContext.InvokeCommandWithCred.ExpandString($Using:WorkingDirectory); 58 | } 59 | } 60 | $processStartInfo.UseShellExecute = $false; # This is critical for installs to function on core servers 61 | $ps = New-Object System.Diagnostics.Process; 62 | $ps.StartInfo = $processStartInfo; 63 | Write-Verbose -Message "Starting process path [$($processStartInfo.FileName)] - Args: [$($processStartInfo.Arguments)] - Working dir: [$($Using:WorkingDirectory)]" 64 | $null = $ps.Start(); 65 | if (-not $ps) { 66 | throw "Error running program: $($ps.ExitCode)" 67 | } else { 68 | $ps.WaitForExit() 69 | } 70 | 71 | # Check the exit code of the process to see if it succeeded. 72 | if ($ps.ExitCode -notin $Using:SuccessReturnCodes) { 73 | throw "Error running program: $($ps.ExitCode)" 74 | } 75 | } 76 | 77 | # Run program on specified computer. 78 | Write-Verbose -Message "Running command line [$FilePath $ArgumentList] on $ComputerName" 79 | 80 | Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptblock 81 | } catch { 82 | $PSCmdlet.ThrowTerminatingError($_) 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /Random Stuff/ScriptSharing.psm1: -------------------------------------------------------------------------------- 1 | #requires -Version 4 2 | 3 | Set-StrictMode -Version Latest 4 | 5 | function Send-ToGithub 6 | { 7 | [CmdletBinding()] 8 | param 9 | ( 10 | [Parameter(Mandatory)] 11 | [ValidateNotNullOrEmpty()] 12 | [string]$RepositoryName 13 | 14 | ) 15 | begin { 16 | $ErrorActionPreference = 'Stop' 17 | } 18 | process { 19 | 20 | } 21 | } 22 | 23 | function Set-GithubScript 24 | { 25 | [CmdletBinding()] 26 | param 27 | ( 28 | 29 | ) 30 | begin { 31 | $ErrorActionPreference = 'Stop' 32 | } 33 | process { 34 | 35 | } 36 | } 37 | 38 | function Send-ToTechnetScriptRepository 39 | { 40 | [CmdletBinding()] 41 | param 42 | ( 43 | 44 | ) 45 | begin { 46 | $ErrorActionPreference = 'Stop' 47 | } 48 | process { 49 | 50 | } 51 | } 52 | 53 | function Set-TechnetScriptRepositoryScript 54 | { 55 | [CmdletBinding()] 56 | param 57 | ( 58 | 59 | ) 60 | begin { 61 | $ErrorActionPreference = 'Stop' 62 | } 63 | process { 64 | try 65 | { 66 | 67 | } 68 | catch 69 | { 70 | Write-Error $_.Exception.Message 71 | } 72 | } 73 | } 74 | 75 | function Send-ToBlog 76 | { 77 | [CmdletBinding()] 78 | param 79 | ( 80 | 81 | ) 82 | begin { 83 | $ErrorActionPreference = 'Stop' 84 | } 85 | process { 86 | 87 | } 88 | } 89 | 90 | function Set-BlogScript 91 | { 92 | [CmdletBinding()] 93 | param 94 | ( 95 | 96 | ) 97 | begin { 98 | $ErrorActionPreference = 'Stop' 99 | } 100 | process { 101 | 102 | } 103 | } 104 | 105 | function Send-ToPoshCode 106 | { 107 | [CmdletBinding()] 108 | param 109 | ( 110 | 111 | ) 112 | begin { 113 | $ErrorActionPreference = 'Stop' 114 | } 115 | process { 116 | 117 | } 118 | } 119 | 120 | function Set-PoshCodeScript 121 | { 122 | [CmdletBinding()] 123 | param 124 | ( 125 | 126 | ) 127 | begin { 128 | $ErrorActionPreference = 'Stop' 129 | } 130 | process { 131 | 132 | } 133 | } 134 | 135 | function Send-ToPowerShellGallery 136 | { 137 | [CmdletBinding()] 138 | param 139 | ( 140 | 141 | ) 142 | begin { 143 | $ErrorActionPreference = 'Stop' 144 | } 145 | process { 146 | 147 | } 148 | } 149 | 150 | function Set-PowerShellGalleryScript 151 | { 152 | [CmdletBinding()] 153 | param 154 | ( 155 | 156 | ) 157 | begin { 158 | $ErrorActionPreference = 'Stop' 159 | } 160 | process { 161 | 162 | } 163 | } 164 | 165 | function Send-ScriptToCommunity 166 | { 167 | [CmdletBinding()] 168 | param 169 | ( 170 | [Parameter()] 171 | [ValidateNotNullOrEmpty()] 172 | [string[]]$Service = @('GitHub','TechnetScriptRepository','PoshCode','Blog') 173 | 174 | ) 175 | begin { 176 | $ErrorActionPreference = 'Stop' 177 | } 178 | process { 179 | try 180 | { 181 | 182 | } 183 | catch 184 | { 185 | Write-Error $_.Exception.Message 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /Networking/Test-NetworkPort.ps1: -------------------------------------------------------------------------------- 1 | 2 | <#PSScriptInfo 3 | 4 | .VERSION 1.0 5 | 6 | .GUID ee346973-6b67-4099-9191-cbcc169cf360 7 | 8 | .AUTHOR Adam Bertram 9 | 10 | .COMPANYNAME Adam the Automator, LLC 11 | 12 | .COPYRIGHT 13 | 14 | .TAGS 15 | 16 | .LICENSEURI 17 | 18 | .PROJECTURI 19 | 20 | .ICONURI 21 | 22 | .EXTERNALMODULEDEPENDENCIES 23 | 24 | .REQUIREDSCRIPTS 25 | 26 | .EXTERNALSCRIPTDEPENDENCIES 27 | 28 | .RELEASENOTES 29 | 30 | 31 | #> 32 | 33 | <# 34 | 35 | .DESCRIPTION 36 | A script to test if a TCP or UDP port is open. 37 | 38 | #> 39 | [CmdletBinding(DefaultParameterSetName = 'TCP')] 40 | [OutputType([System.Management.Automation.PSCustomObject])] 41 | param ( 42 | [Parameter(Mandatory)] 43 | [string]$ComputerName, 44 | 45 | [Parameter(Mandatory)] 46 | [int]$Port, 47 | 48 | [Parameter()] 49 | [ValidateSet('TCP', 'UDP')] 50 | [string]$Protocol = 'TCP', 51 | 52 | [Parameter(ParameterSetName = 'TCP')] 53 | [int]$TcpTimeout = 1000, 54 | 55 | [Parameter(ParameterSetName = 'UDP')] 56 | [int]$UdpTimeout = 1000 57 | ) 58 | process 59 | { 60 | if ($Protocol -eq 'TCP') 61 | { 62 | $TcpClient = New-Object System.Net.Sockets.TcpClient 63 | $Connect = $TcpClient.BeginConnect($ComputerName, $Port, $null, $null) 64 | $Wait = $Connect.AsyncWaitHandle.WaitOne($TcpTimeout, $false) 65 | if (!$Wait) 66 | { 67 | $TcpClient.Close() 68 | } 69 | else 70 | { 71 | $TcpClient.EndConnect($Connect) 72 | $TcpClient.Close() 73 | $result = $true 74 | } 75 | $TcpClient.Close() 76 | $TcpClient.Dispose() 77 | } 78 | elseif ($Protocol -eq 'UDP') 79 | { 80 | $UdpClient = New-Object System.Net.Sockets.UdpClient 81 | $UdpClient.Client.ReceiveTimeout = $UdpTimeout 82 | $UdpClient.Connect($ComputerName, $Port) 83 | $a = new-object system.text.asciiencoding 84 | $byte = $a.GetBytes("$(Get-Date)") 85 | [void]$UdpClient.Send($byte, $byte.length) 86 | #IPEndPoint object will allow us to read datagrams sent from any source. 87 | Write-Verbose "$($MyInvocation.MyCommand.Name) - Creating remote endpoint" 88 | $remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any, 0) 89 | try 90 | { 91 | #Blocks until a message returns on this socket from a remote host. 92 | Write-Verbose "$($MyInvocation.MyCommand.Name) - Waiting for message return" 93 | $receivebytes = $UdpClient.Receive([ref]$remoteendpoint) 94 | [string]$returndata = $a.GetString($receivebytes) 95 | If ($returndata) 96 | { 97 | $result = $true 98 | } 99 | } 100 | catch 101 | { 102 | Write-Error "$($MyInvocation.MyCommand.Name) - '$ComputerName' failed port test on port '$Protocol`:$Port' with error '$($_.Exception.Message)'" 103 | } 104 | $UdpClient.Close() 105 | $UdpClient.Dispose() 106 | } 107 | if ($result) 108 | { 109 | $true 110 | } 111 | else 112 | { 113 | $false 114 | } 115 | } -------------------------------------------------------------------------------- /SQL/UsefulQueries/missing indexes.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | SELECT db.[name] AS [DatabaseName] 4 | ,id.[object_id] AS [ObjectID] 5 | ,OBJECT_NAME(id.[object_id], db.[database_id]) AS [ObjectName] 6 | ,id.[statement] AS [FullyQualifiedObjectName] 7 | ,id.[equality_columns] AS [EqualityColumns] 8 | ,id.[inequality_columns] AS [InEqualityColumns] 9 | ,id.[included_columns] AS [IncludedColumns] 10 | ,gs.[unique_compiles] AS [UniqueCompiles] 11 | ,gs.[user_seeks] AS [UserSeeks] 12 | ,gs.[user_scans] AS [UserScans] 13 | ,gs.[last_user_seek] AS [LastUserSeekTime] 14 | ,gs.[last_user_scan] AS [LastUserScanTime] 15 | ,gs.[avg_total_user_cost] AS [AvgTotalUserCost] -- Average cost of the user queries that could be reduced by the index in the group. 16 | ,gs.[avg_user_impact] AS [AvgUserImpact] -- The value means that the query cost would on average drop by this percentage if this missing index group was implemented. 17 | ,gs.[system_seeks] AS [SystemSeeks] 18 | ,gs.[system_scans] AS [SystemScans] 19 | ,gs.[last_system_seek] AS [LastSystemSeekTime] 20 | ,gs.[last_system_scan] AS [LastSystemScanTime] 21 | ,gs.[avg_total_system_cost] AS [AvgTotalSystemCost] 22 | ,gs.[avg_system_impact] AS [AvgSystemImpact] -- Average percentage benefit that system queries could experience if this missing index group was implemented. 23 | ,gs.[user_seeks] * gs.[avg_total_user_cost] * (gs.[avg_user_impact] * 0.01) AS [IndexAdvantage] 24 | ,'CREATE INDEX [IX_' + OBJECT_NAME(id.[object_id], db.[database_id]) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(id.[equality_columns], ''), ', ', '_'), '[', ''), ']', '') + CASE 25 | WHEN id.[equality_columns] IS NOT NULL 26 | AND id.[inequality_columns] IS NOT NULL 27 | THEN '_' 28 | ELSE '' 29 | END + REPLACE(REPLACE(REPLACE(ISNULL(id.[inequality_columns], ''), ', ', '_'), '[', ''), ']', '') + '_' + LEFT(CAST(NEWID() AS [nvarchar](64)), 5) + ']' + ' ON ' + id.[statement] + ' (' + ISNULL(id.[equality_columns], '') + CASE 30 | WHEN id.[equality_columns] IS NOT NULL 31 | AND id.[inequality_columns] IS NOT NULL 32 | THEN ',' 33 | ELSE '' 34 | END + ISNULL(id.[inequality_columns], '') + ')' + ISNULL(' INCLUDE (' + id.[included_columns] + ')', '') AS [ProposedIndex] 35 | ,CAST(CURRENT_TIMESTAMP AS [smalldatetime]) AS [CollectionDate] 36 | FROM [sys].[dm_db_missing_index_group_stats] gs WITH (NOLOCK) 37 | INNER JOIN [sys].[dm_db_missing_index_groups] ig WITH (NOLOCK) ON gs.[group_handle] = ig.[index_group_handle] 38 | INNER JOIN [sys].[dm_db_missing_index_details] id WITH (NOLOCK) ON ig.[index_handle] = id.[index_handle] 39 | INNER JOIN [sys].[databases] db WITH (NOLOCK) ON db.[database_id] = id.[database_id] 40 | -- UNCOMMENT THIS ROW TO FILTER ON CURRENT DATABASE 41 | --WHERE db.[database_id] = DB_ID() 42 | --AND OBJECT_NAME(id.[object_id], db.[database_id]) = 'YourTableName' 43 | ORDER BY [IndexAdvantage] DESC 44 | OPTION (RECOMPILE); 45 | -------------------------------------------------------------------------------- /Azure/ConvertTo-AzureSize.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module virtualmachinemanager,AzureRM.Compute 2 | #Requires -Version 4 3 | 4 | function ConvertTo-AzureSize 5 | { 6 | <# 7 | .SYNOPSIS 8 | This function takes a VMM hardware profile name as input and attempts to find the closest matching Azure instance name 9 | based on a few rules. 10 | 11 | It will search for Azure instances that match the CPU count from the hardware profile and attempt to find the instance 12 | with the same or greater amount of memory as well. 13 | 14 | .EXAMPLE 15 | PS> ConvertTo-AzureSize -VMMHardwareProfile 'HWP-GP1' 16 | 17 | MaxDataDiskCount : 2 18 | MemoryInMB : 3584 19 | Name : Standard_D1_v2 20 | NumberOfCores : 1 21 | OSDiskSizeInMB : 1047552 22 | ResourceDiskSizeInMB : 51200 23 | RequestId : a6dfba3e-982d-47d9-a3c0-2c734f1545fa 24 | StatusCode : OK 25 | Memory : 3584 26 | CPUCount : 1 27 | 28 | .PARAMETER VmmHardwareProfile 29 | The name of the VMM hardware profile to query from VMM. This is mandatory. 30 | 31 | .PARAMETER AzureLocation 32 | The Azure location to search for available Azure instances. This defaults to 'WestUs'. 33 | #> 34 | [CmdletBinding()] 35 | [OutputType('Selected.Microsoft.Azure.Commands.Compute.Models.PSVirtualMachineSize')] 36 | param 37 | ( 38 | [Parameter(Mandatory)] 39 | [ValidateNotNullOrEmpty()] 40 | [string]$VmmHardwareProfile, 41 | 42 | [Parameter()] 43 | [ValidateNotNullOrEmpty()] 44 | [string]$AzureLocation = 'WestUS' 45 | 46 | ) 47 | process 48 | { 49 | try 50 | { 51 | if (-not ($hwProfile = Get-SCHardwareProfile | where { $_.Name -eq $VmmHardwareProfile })) 52 | { 53 | throw "Hardware profile not found: [$($VmmHardwareProfile)]" 54 | } 55 | 56 | ## Only select Azure instances with the same CPU count, with memory equal to or greater than the hardware profile 57 | ## and only Standard Azure instances choosing only the v2 'D' instances if that's the best match. Do not match 58 | ## any DS VMs. 59 | $whereFilter = { 60 | ($_.CPUCount -eq $hwProfile.CPUCount) -and 61 | ($_.Memory -ge $hwProfile.Memory) -and 62 | ($_.Name -match '^Standard_(?!DS?\d)\w+?\d+?|Standard_D\d+_v2$') 63 | } 64 | 65 | $azureProperties = @( 66 | '*', 67 | @{ Name = 'Memory'; Expression = { $_.MemoryInMb } }, 68 | @{ Name = 'CPUCount'; Expression = { $_.NumberOfCores } } 69 | ) 70 | 71 | $sizeParams = @{ 72 | 'Property' = $azureProperties 73 | 'Exclude' = 'Memory', 'NumberOfCores' 74 | } 75 | 76 | if (-not ($azureSize = (Get-AzureRmVMSize -Location $AzureLocation | select -Property $azureProperties).where($whereFilter))) 77 | { 78 | throw "No Azure server instances found that match hardware profile [$($VmmHardwareProfile)]" 79 | } 80 | else 81 | { 82 | $azureSize 83 | } 84 | } 85 | catch 86 | { 87 | Write-Error -Message $_.Exception.Message 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /Processes/Invoke-Process.ps1: -------------------------------------------------------------------------------- 1 | <#PSScriptInfo 2 | 3 | .VERSION 2.0 4 | 5 | .GUID b787dc5d-8d11-45e9-aeef-5cf3a1f690de 6 | 7 | .AUTHOR Adam Bertram 8 | 9 | .COMPANYNAME Adam the Automator, LLC 10 | 11 | .TAGS Processes 12 | 13 | #> 14 | 15 | <# 16 | 17 | .DESCRIPTION 18 | Invoke-Process is a simple wrapper function that aims to "PowerShellyify" launching typical external processes. There 19 | are lots of ways to invoke processes in PowerShell with Start-Process, Invoke-Expression, & and others but none account 20 | well for the various streams and exit codes that an external process returns. Also, it's hard to write good tests 21 | when launching external proceses. 22 | 23 | This function ensures any errors are sent to the error stream, standard output is sent via the Output stream and any 24 | time the process returns an exit code other than 0, treat it as an error. 25 | 26 | #> 27 | param() 28 | 29 | function Invoke-Process { 30 | [CmdletBinding(SupportsShouldProcess)] 31 | param ( 32 | [Parameter(Mandatory)] 33 | [ValidateNotNullOrEmpty()] 34 | [string]$FilePath, 35 | [string[]]$ArgumentList 36 | ) 37 | 38 | $ErrorActionPreference = 'Stop' 39 | 40 | try { 41 | $stdOutTempFile = "$env:TEMP\$(( New-Guid ).Guid)" 42 | $stdErrTempFile = "$env:TEMP\$(( New-Guid ).Guid)" 43 | 44 | $startProcessParams = @{ 45 | FilePath = $FilePath 46 | RedirectStandardError = $stdErrTempFile 47 | RedirectStandardOutput = $stdOutTempFile 48 | Wait = $true 49 | PassThru = $true 50 | NoNewWindow = $true 51 | } 52 | if ($PSCmdlet.ShouldProcess("Process [$($FilePath)]", "Run with args: [$($ArgumentList)]")) { 53 | if ($ArgumentList) { 54 | Write-Verbose -Message "$FilePath $ArgumentList" 55 | $cmd = Start-Process @startProcessParams -ArgumentList $ArgumentList 56 | } 57 | else { 58 | Write-Verbose $FilePath 59 | $cmd = Start-Process @startProcessParams 60 | } 61 | $stdOut = Get-Content -Path $stdOutTempFile -Raw 62 | $stdErr = Get-Content -Path $stdErrTempFile -Raw 63 | if ([string]::IsNullOrEmpty($stdOut) -eq $false) { 64 | $stdOut = $stdOut.Trim() 65 | } 66 | if ([string]::IsNullOrEmpty($stdErr) -eq $false) { 67 | $stdErr = $stdErr.Trim() 68 | } 69 | $return = [PSCustomObject]@{ 70 | Name = $cmd.Name 71 | Id = $cmd.Id 72 | ExitCode = $cmd.ExitCode 73 | Output = $stdOut 74 | Error = $stdErr 75 | } 76 | if ($return.ExitCode -ne 0) { 77 | throw $return 78 | } 79 | else { 80 | $return 81 | } 82 | } 83 | } 84 | catch { 85 | $PSCmdlet.ThrowTerminatingError($_) 86 | } 87 | finally { 88 | Remove-Item -Path $stdOutTempFile, $stdErrTempFile -Force -ErrorAction Ignore 89 | } 90 | } 91 | 92 | --------------------------------------------------------------------------------