Skip to content

PowerShell

Microsoft PowerShell Scripts are the newest method of scripting in Microsoft Windows.

Here are a few of the scripts I have written that may be of use to the general public.

DiskSize

This script calculates the drive space for the drive where this script is running from.

<#    
.SYNOPSIS   
Script that calculates the drive space for the drive where this script is running from.

.DESCRIPTION 
This script first calculates the path where this script is running from.
It then get drive information for all drives and mount points whose names are contained in that path.
The results are sorted by the lengths of the drive names in descending order and the top one is returned.
This drive is the drive or mount point that is closest to the script's path.

.NOTES   
Name: DiskSize.ps1
Author: Mike Shook

Version: 1.0.0.1
Version Date: 03/20/2021

#>

#Clear-Host

########################################################
# From https://stackoverflow.com/questions/57530347/how-to-convert-value-to-kb-mb-or-gb-depending-on-digit-placeholders/57535324#57535324

$Shlwapi = Add-Type -MemberDefinition '
    [DllImport("Shlwapi.dll", CharSet=CharSet.Auto)]public static extern int StrFormatByteSize(long fileSize, System.Text.StringBuilder pwszBuff, int cchBuff);
' -Name "ShlwapiFunctions" -namespace ShlwapiFunctions -PassThru

Function Format-ByteSize([Long]$Size) {
    $Bytes = New-Object Text.StringBuilder 20
    $Return = $Shlwapi::StrFormatByteSize($Size, $Bytes, $Bytes.Capacity)
    If ($Return) {$Bytes.ToString()}
}
########################################################

# get the folder the script is currently running from
$fullPath = $MyInvocation.MyCommand.Path
$parentPath = ( Split-Path $fullPath -Parent ) + "\"

# get list of all drive and mountpoint names that are in the script's path

########################################################
# from http://www.bradleyschacht.com/checkmountpointsfreespacewithpowershel/
# gwmi win32_volume|where-object {$_.filesystem -match “ntfs”}|ft name,capacity,freespace
########################################################

$drives = gwmi win32_volume `
    | Where-Object { $parentPath -like "*" + $_.name + "*" } `
    | Select-Object name, @{Name = "name_length"; Expression = { $_.name.Length } }, @{Name = "capacity"; Expression = { Format-ByteSize $_.capacity } }, @{ Name = "freespace"; Expression = { Format-ByteSize $_.freespace } } 

# Find longest name as that will be the nearest drive to the script's path

$drive = $drives | Sort-Object -Property @{Expression = "name_length"; Descending = $True} | Select-Object -First 1

# If there were no drives, assume a UNC path or mapped drive

if( $drive.name -ne $null ){

    # output nearest drive information
    $drive | Format-Table -Property name, capacity, freespace

} else {

    # output message
    Write-Output "No information found. Is this script on a Mapped Drive or UNC Path?"

}
# set non-ISE powershell terminal to wait for keypress

If (!$psISE) {
    Read-Host "Press ENTER to Exit..."
}

EspnFantasyFootballLineup

This script calculates a ESPN Fantasy Football team's starting lineup for current week.

<#    
.SYNOPSIS   
Script that calculates a ESPN Fantasy Football team's starting lineup for current week.

.DESCRIPTION 
This script gets the roster data for an ESPN Fantasy Football team for the current week.
It then calculates for each player a value that represents that players starting value.
This value is meaningless EXCEPT for comparison with other player's values that play the same position.
It is then used to create the team's starting lineup for the week.
Then the values used, grouped by player position, are displayed.
Last, the final lineup for the week is displayed.
The calculation formula is found in the expression set for the '$comparisonValue' when the Base data is calculated.

.NOTES   
Name: EspnFantasyFootballLineup.ps1
Author: Mike Shook

Version: 1.5.0.7
Version Date: 10/25/2021
Version Notes: CHANGE: Change the comparison value to be calculated using the % Rostered in instead of % Started to overcome issues related to bye week statistics
               CHANGE: The Comparsion Value is now using the average of the Projected player points and 3 x their Average points to give more weight to their average

Version: 1.5.0.6
Version Date: 10/2/2021
Version Notes: ADD: Average player points to the Calculated Comparison by Position
               ADD: Player's Bye Week to the Calculated Comparison by Position
               ADD: Player's Bye Week Alert to the Calculated Lineup if the player has their Bye next week
               ADD: Player's acquisition type to the Calculated Comparison by Position
               CHANGE: The Comparsion Value is now using the average of the Projected player points and their Average points instead of just Projected
               CHANGE: All D/ST players are permanently 'ACTIVE'

Version: 1.4.0.5
Version Date: 9/27/2021
Version Notes: ADD: Added Actual total points for mid-week lookups to the Calculated Lineup

Version: 1.3.0.4
Version Date: 9/17/2021
Version Notes: ADD: Actual player points for mid-week lookups to the Calculated Comparison by Position
               ADD: The Projected Points is now multiplied by a value based on player position during the Comparison value calculation.
                    This is done in an attempt to equalize the Comparison value across positions: QB=1, RB=1.5, WR=1.6, TE=2.5, K=3.2, D/ST=3.5
                    The average of the 2020 top 16 players average fantasy points for each position were used to create the multipliers.
Version: 1.2.0.3
Version Date: 12/13/2020
Version Notes: ADD: Ability to always have locked players marked with where they were when they played

Version: 1.1.0.2
Version Date: 10/21/2020
Version Notes: ADD: Output of the current and new projected total points

Version: 1.0.0.1
Version Date: 9/21/2020
Version Notes: First version

.VARIABLE $leagueId
The ID of the league the team is a member of.
It can be found in the url of your team page:
https://fantasy.espn.com/football/team?leagueId=76968740&teamId=13&seasonId=2020
                                                ^^^^^^^^

.VARIABLE $teamId
The ID of the team in the league.
It can be found in the url of your team page:
https://fantasy.espn.com/football/team?leagueId=76968740&teamId=13&seasonId=2020
                                                                ^^

.MODULE WriteAscii
The WriteAscii module is required for pretty team names in the output.
To install it run from elevated powershell: "Install-Module -Name WriteAscii"

#>

### User Variables #######################################
$leagueId = '76968740'
$teamId = '13'
##########################################################

### No user changes beyond this point ####################

### Setup Console ##########################################################################################################################

# Clear the host display and set height to match the Calculated Lineup Report

Clear-Host

If ($host.Name -eq 'ConsoleHost') {
    If (Get-Module -ListAvailable -Name WriteAscii) {
        $host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.size(150, 3000)
        $host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.size(150, 49)
    }
    else {
        $host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.size(150, 3000)
        $host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.size(150, 39)
    }
}

### Get Data ###############################################################################################################################

# Get basic data from ESPN for the current week

Write-Host "Getting basic data for ESPN Fantasy Football..." -ForegroundColor Yellow

$year = Get-Date -Format "yyyy"

$uriLeague = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/' + $year + '/segments/0/leagues/' + $leagueId

$GetLeagueSession = Invoke-WebRequest -Uri $uriLeague -Method GET -timeoutSec 360 -ErrorAction Stop

$league = $GetLeagueSession.Content | ConvertFrom-Json

$week = $league.scoringPeriodId

# Set paths to all temp files and delete any old ones

$pathRoot = $env:TEMP  + '\ESPN_FFL'
[void]( New-Item -ItemType Directory -Force -Path $pathRoot )

$path = $pathRoot + '\ESPN_FFL'

$filePro = $path + '_Pro_Teams.json'
$fileLeague = $path + '_' + $leagueId + '.json'
$fileTeamBase = $path + '_' + $leagueId + '_' + $teamId + '_' + $week
$fileTeam = $fileTeamBase + '.json'
$fileTeamCsv = $fileTeamBase + '_1_team.csv'
$fileComparisonCsv = $fileTeamBase + '_2_comparison.csv'
$fileSortedCsv = $fileTeamBase + '_3_sorted.csv'
$fileStartCsv = $fileTeamBase + '_4_start.csv'
$fileChangeCsv = $fileTeamBase + '_5_change.csv'
$fileCollection = $path + '*.*'

$currentProjected = 0
$newProjected = 0
$actual = 0
$weeksBack = 3

Remove-Item -Path $fileCollection -ErrorAction SilentlyContinue

# Write out the basic json data

$GetLeagueSession.Content | Out-File $fileLeague

# Get data from ESPN for pro teams

Write-Host "Getting data for the Professional Teams..." -ForegroundColor Yellow

$uriPro = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/' + $year + '?view=proTeamSchedules_wl'
$GetProSession = Invoke-WebRequest -Uri $uriPro -Method GET -timeoutSec 360 -ErrorAction Stop
$GetProSession.Content | Out-File $filePro
$jsonPro = $GetProSession.Content | ConvertFrom-Json
$hashProBye = @{}
foreach ($team in $jsonPro.settings.proTeams) {
    $hashProBye[$team.id] = $team.byeWeek
}

# Get the stats information from ESPN

Write-Host "Getting data for Team $teamId in League $leagueId..." -ForegroundColor Yellow

$uriStats = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/' + $year + '/segments/0/leagues/' + $leagueId + '?rosterForTeamId=' + $teamId + '&view=mRoster&view=mTeam&scoringPeriodId=' + $week
$GetSession = Invoke-WebRequest -Uri $uriStats -Method GET -timeoutSec 360 -ErrorAction Stop
$GetSession.Content | Out-File $fileTeam
$json = $GetSession.Content | ConvertFrom-Json

### Calculate ##############################################################################################################################

# Get the team information

$team = $json.teams[$teamId - 1]

$teamName = $team.location + ' ' + $team.nickname
$teamName = $teamName.ToUpper()

# Get the base data, calculate the comparison and write it out to a temp file

ForEach ($entry in $team.roster.entries) {  
    $entry | Select-Object @{ Name = 'Name'; Expression = { $entry.playerPoolEntry.player.fullName } }, `
        @{ Name = 'ShortName'; Expression = { ($entry.playerPoolEntry.player.firstName).substring(0,1) + '. ' + $entry.playerPoolEntry.player.lastName } }, `
        @{ Name = 'Slot'; Expression = { $entry.lineupSlotId } }, `
        @{ Name = 'Aquisition'; Expression = { $entry.acquisitionType } }, `
        @{ Name = 'Locked'; Expression = { $entry.playerPoolEntry.lineupLocked } }, `
        @{ Name = 'Bye'; Expression = { $hashProBye[$entry.playerPoolEntry.player.proTeamId] } }, `
        @{ Name = 'Position'; Expression = {
                Switch ([int]$entry.playerPoolEntry.player.defaultPositionId) {
                    { ($_ -eq 1) } { 'QB'; Break }
                    { ($_ -eq 2) } { 'RB'; Break }
                    { ($_ -eq 3) } { 'WR'; Break }
                    { ($_ -eq 4) } { 'TE'; Break }
                    { ($_ -eq 5) } { 'K'; Break }
                    { ($_ -eq 16) } { 'D/ST'; Break } 
                    Default { '??' }
                }
            }
        }, `
        @{ Name = 'Multiplier'; Expression = {
                Switch ([int]$entry.playerPoolEntry.player.defaultPositionId) {
                    { ($_ -eq 1) } { '1'; Break }
                    { ($_ -eq 2) } { '1.5'; Break }
                    { ($_ -eq 3) } { '1.6'; Break }
                    { ($_ -eq 4) } { '2.5'; Break }
                    { ($_ -eq 5) } { '3.2'; Break }
                    { ($_ -eq 16) } { '3.5'; Break } 
                    Default { '1' }
                }
            }
        }, `
        @{ Name = 'defaultPositionId'; Expression = { [int]$entry.playerPoolEntry.player.defaultPositionId } }, `
        @{ Name = 'injured'; Expression = { $entry.playerPoolEntry.player.injured } }, `
        @{ Name = 'Status'; Expression = { 
            If ( [int]$entry.playerPoolEntry.player.defaultPositionId -eq 16 ) { 
                    'ACTIVE'
                } else {
                    $entry.playerPoolEntry.player.injuryStatus
                }
            }
        }, `
        @{ Name = 'Started'; Expression = { [single]$entry.playerPoolEntry.player.ownership.percentStarted } }, `
        @{ Name = 'Rostered'; Expression = { [single]$entry.playerPoolEntry.player.ownership.percentOwned } }, `
        @{ Name = 'Ranking'; Expression = { [int]$entry.playerPoolEntry.ratings.'0'.positionalRanking } }, `
        @{ Name = 'Points'; Expression = { 
                ForEach ($stat in $entry.playerPoolEntry.player.stats) { 
                    If ( ( $stat.seasonId -eq $year ) -and ( $stat.scoringPeriodId -eq $week ) -and ( $stat.statSourceId -eq '1' ) ) { 
                        $stat.appliedTotal
                    }
                }
            }
        }, `
        @{ Name = 'Actual'; Expression = {                
                ForEach ($stat in $entry.playerPoolEntry.player.stats) { 
                    If ( ( $stat.seasonId -eq $year ) -and ( $stat.scoringPeriodId -eq $week ) -and ( $stat.statSourceId -eq '0' ) ) { 
                        $stat.appliedTotal 
                    }
                }
            }
        }, `
        @{ Name = 'ActualAvg'; Expression = { 
                ForEach ($stat in $entry.playerPoolEntry.player.stats) { 
                    If ( ( $stat.seasonId -eq $year ) -and ( $stat.scoringPeriodId -eq '0' ) -and ( $stat.statSourceId -eq '0' ) ) { 
                        [single]$stat.appliedAverage
                    }
                }
            }
        }`
        | Export-Csv -Path $fileTeamCsv -NoTypeInformation -Append -Force
} 

# Load the base data, calculate the comparison, and write it out to a temp file

$comparisonTable = Import-Csv -Path $fileTeamCsv

ForEach ($player in $comparisonTable) {
    If ( [int]$player.slot -ne 20 ) { 
        $currentProjected = [single]$currentProjected + [single]$player.Points
        $actual = [single]$actual + [single]$player.Actual
    }
    $comparisonValue = ( ( ( [single]$player.Points + ( [single]$player.ActualAvg * 3 ) ) / 4 ) * [single]$player.Multiplier) + ([single]$player.Rostered / 6) - ( [single]$player.Ranking / 8)
    $comparisonOutValue = ( [single]$player.ActualAvg * [single]$player.Multiplier) + ([single]$player.Rostered / 6) - ( [single]$player.Ranking / 8)
    $player | Select-Object *, `
        @{ Name = 'Projected'; Expression = { [single]$currentProjected } }, ` 
        @{ Name = 'ComparisonOrig'; Expression = { If ( [single]$player.Points -ne '0' -AND $player.injured -eq $False ) { $comparisonValue } Else { $comparisonOutValue } } }, `
        @{ Name = 'Comparison'; Expression = { If ( $player.Locked -eq $True -AND $player.Slot -ne '20' ) { [single]'100' + $comparisonValue } ElseIf ( $player.Locked -eq $True -AND $player.Slot -eq '20' ) { [single]'-100' + $comparisonValue } ElseIf ( [single]$player.Bye -eq [single]$week ) { [single]'-100' + $comparisonValue } ElseIf ( [single]$player.Points -ne '0' -AND $player.injured -eq $False ) { $comparisonValue } Else { [single]'-100' } } }`
    | Export-Csv -Path $fileComparisonCsv -NoTypeInformation -Append -Force
}

# Load the comparison data, sort it by the positionId and Comparison, and write it out to a temp file

$sortedTable = Import-Csv -Path $fileComparisonCsv

$sortedTable | Sort-Object -Property @{Expression = { [int]$_.defaultPositionId }; Descending = $False }, `
@{Expression = { [single]$_.Comparison }; Descending = $True }`
| Export-Csv -Path $fileSortedCsv -NoTypeInformation -Force

# Load the sorted data, determine the start or bench status for each player, and write it out to a temp file

$startTable = Import-Csv -Path $fileSortedCsv

ForEach ($player in $startTable) {
    If ($player.defaultPositionId -ne $previousPositionId) { $rowCount = 1 } else { $rowCount = $rowCount + 1 }
    $previousPositionId = $player.defaultPositionId

    $player | Select-Object *, `
    @{ Name = 'rowCount'; Expression = { $rowCount } }, `
    @{ Name = 'Start ?'; Expression = {
            if ($_.defaultPositionId -eq 1 -and $rowCount -le 1) { 'START' } 
            elseif ($_.defaultPositionId -eq 2 -and $rowCount -le 2) { 'START' } 
            elseif ($_.defaultPositionId -eq 3 -and $rowCount -le 2) { 'START' }
            elseif ($_.defaultPositionId -eq 4 -and $rowCount -le 1) { 'START' }
            elseif ($_.defaultPositionId -eq 5 -and $rowCount -le 1) { 'START' }
            elseif ($_.defaultPositionId -eq 16 -and $rowCount -le 1) { 'START' }
            else { 'BENCH' }
        }
    }, `
    @{ Name = 'Bye Alert'; Expression = {
            if ([int]$_.Bye -eq ( [int]$week + 1 ) ) { 'NEXT WEEK' }             
            if ([int]$_.Bye -eq ( [int]$week ) ) { 'NOW' }
            else { '' }
        }
    }`
    | Export-Csv -Path $fileStartCsv -NoTypeInformation -Append -Force

}

# Load the start data, determine if a player is currently rostered incorrectly, and write it out to a temp file

$changeTable = Import-Csv -Path $fileStartCsv

ForEach ($player in $changeTable) {
    If ( $player.'Start ?' -eq 'START' ) { 
        $newProjected = [single]$newProjected + [single]$player.Points
    }
    $player | Select-Object *, `
        @{ Name = 'New'; Expression = { [single]$newProjected } }, `
        @{ Name = 'Change'; Expression = { If ($_.'Start ?' -eq 'START' -and $_.Slot -eq '20') { 'CHANGE' } 
            ElseIf ($_.'Start ?' -eq 'BENCH' -and $_.Slot -ne '20') { 'CHANGE' }
        } 
    }`
    | Export-Csv -Path $fileChangeCsv -NoTypeInformation -Append -Force

}

# Load the change data, set some variables used in the reports and clear the host display

$finalTable = Import-Csv -Path $fileChangeCsv

$width = $Host.UI.RawUI.BufferSize.Width
$lineThin = '-' * ( $width - 1 )
$lineThick = '=' * ( $width - 1 )

### Output #################################################################################################################################
Clear-Host

# Output the Calculated Comparison report

If (Get-Module -ListAvailable -Name WriteAscii) {
    Write-Ascii -InputObject $team.location -ForegroundColor Cyan
    Write-Ascii -InputObject $team.nickname -ForegroundColor Cyan
    Write-Output ' '
    Write-Host "$year WEEK $week CALCULATED COMPARISON BY POSITION" -ForegroundColor Cyan
} 
Else {
    Write-Host "$teamName $year WEEK $week CALCULATED COMPARISON BY POSITION" -ForegroundColor Cyan
}

Write-Host ''
Write-Host 'The Comparison value is calculated using this formula:' -ForegroundColor Cyan
Write-Host '     ( ( ( "Projected" + ( "Average" * 3 ) ) / 4 ) * "Multiplier" ) + ( "% Rostered" / 6 ) - ( "Position Rank" / 8 )' -ForegroundColor Cyan

Write-Output $finalTable | Sort-Object -Property @{ Expression = { [int]$_.defaultPositionId }; Descending = $False }, `
@{ Expression = { [single]$_.Comparison }; Descending = $True }`
| Format-Table -GroupBy Position -Wrap -Property @{Name = 'Name'; Expression = { $_.ShortName } }, `
    Aquisition, `
    @{Name = 'Injury Status'; Expression = { $_.Status } }, `
    @{Name = 'Bye'; Expression = { $_.Bye } }, `
    @{Name = 'Projected'; Expression = { [math]::Round($_.Points, 2) } }, `
    @{Name = 'Actual'; Expression = { [math]::Round($_.Actual, 2) } }, `
    @{Name = 'Average'; Expression = { [math]::Round($_.ActualAvg, 2) } }, `
    Multiplier, `
    @{Name = '% Started'; Expression = { [math]::Round($_.Started, 2) } }, `
    @{Name = '% Rostered'; Expression = { [math]::Round($_.Rostered, 2) } }, `
    @{Name = 'Position Rank'; Expression = { [math]::Round($_.Ranking) } }, `
    @{Name = 'Comparison'; Expression = { [math]::Round($_.ComparisonOrig, 2) } }, `
    'Start ?', `
    Change

# Output separator lines

Write-Output ' '
Write-Host $lineThick -ForegroundColor Red
Write-Output ' '

# Output the Calculated Lineup report

If (Get-Module -ListAvailable -Name WriteAscii) {
    Write-Ascii -InputObject $team.location -ForegroundColor Green
    Write-Ascii -InputObject $team.nickname -ForegroundColor Green
    Write-Host ' '
    Write-Host "↑ Scroll up to see the Calculated Comparison By Position information ↑" -ForegroundColor Cyan
    Write-Output ' '
    Write-Host "$year WEEK $week CALCULATED LINEUP" -ForegroundColor Green
} 
Else {
    Write-Host "↑ Scroll up to see the Calculated Comparison By Position information ↑" -ForegroundColor Cyan
    Write-Output ' '
    Write-Host "$teamName $year Week $week Calculated Lineup:" -ForegroundColor Green
}

Write-Output $finalTable | Sort-Object -Property @{ Expression = { $_.'Start ?' }; Descending = $True }, `
@{ Expression = { [single]$_.defaultPositionId }; Descending = $False }`
| Format-Table -Property Position, `
    Name, `
    'Bye Alert', `
    @{Name = 'Injury Status'; Expression = { $_.Status } }, `
    Locked, `
    Change ` `
    -GroupBy 'Start ?' `
    -Wrap

$currentProjected = [math]::Round($currentProjected, 2)
Write-Output "Current Projected Total: $currentProjected"
$newProjected = [math]::Round($newProjected, 2)
Write-Output "New Projected Total:     $newProjected"
$actual = [math]::Round($actual, 2)
Write-Output "Actual Total:            $actual"

Write-Host $lineThin -ForegroundColor Red


### Exit ###################################################################################################################################

# set non-ISE powershell terminal to wait for keypress

If (!$psISE) {
    Read-Host "Press ENTER to Exit..."
}

FolderListBuild

This script uses Get-ChildItem and Measure-Object to query a folder and retreive all of its sub-folders and the counts of files and folders in each.

<#    
.SYNOPSIS   
Script that returns a list of sub-folders of an input folder

.DESCRIPTION 
This script uses Get-ChildItem and Measure-Object to query a folder and retreive all of its sub-folders and the counts of files and folders in each.

.PARAMETER QueryPath
The full path to the folder that will have its sub-folders listed

.PARAMETER OutputPath
The full path to the folder that will have the folder list

.NOTES   
Name: FolderListBuild.ps1
Author: Mike Shook
DateCreated: 07/14/2018 
DateUpdated: 5/22/2020
Version: 1.1.0

.EXAMPLE
    .\FolderListBuild.ps1 -QueryPath "C:\FolderToList" -OutputPath "C:\FolderToPutListIn"

#>

param (                        
    [string[]] $QueryPath = "$home\Documents", `
    [string[]] $OutputPath = "$home\Desktop"
)

$QueryPathClean = $QueryPath.Split("\",[System.StringSplitOptions]::RemoveEmptyEntries) -join '\' -replace '`',''

$folder_path = $QueryPathClean.Split("\")[-1]
$root_path = $QueryPathClean.Substring(0,$QueryPathClean.Length-$folder_path.Length)
$root_path = $root_path.Split("\",[System.StringSplitOptions]::RemoveEmptyEntries) -join '\'

$folders_file_final_path = "$OutputPath\FolderListBuild_$folder_path"
$folders_file_temp_path = "$folders_file_final_path\temp"
$folders_file_temp_full = "$folders_file_temp_path\folders.csv"

Write-Output "$(Get-Date): Start"
Write-Output "$(Get-Date): Query Path: $QueryPath"
Write-Output "$(Get-Date): Query Path Clean: $QueryPathClean"
Write-Output "$(Get-Date): Output Path: $OutputPath"
Write-Output "$(Get-Date): Root Path: $root_path"
Write-Output "$(Get-Date): Folder: $folder_path"

Write-Output "$(Get-Date): Create folders if they don't exist"

if (!(Test-Path $folders_file_final_path))
{
  New-Item -ItemType Directory -Force -Path $folders_file_final_path
}

if (!(Test-Path $folders_file_temp_path))
{
  New-Item -ItemType Directory -Force -Path $folders_file_temp_path
}

$folders_stream = New-Object IO.StreamWriter $folders_file_temp_full

Write-Output "$(Get-Date): Open Temp Folders File: ""$folders_file_temp_full"""

Write-Output "$(Get-Date): Get Root Information for ""$root_path\$folder_path"""
$result_root = Get-ChildItem -LiteralPath "$root_path\" -Filter "$folder_path" -Directory `
    | Select-Object FullName, `
        @{Name="FileCount";Expression={(Get-ChildItem -LiteralPath $_.FullName -File | Measure-Object).Count }}, `
        @{Name="DirectoryCount";Expression={(Get-ChildItem -LiteralPath $_.FullName -Directory | Measure-Object).Count }} `
    | ConvertTo-Csv -NoTypeInformation

Write-Output "$(Get-Date): Output Root Information for ""$root_path\$folder_path"""
$result_root | ForEach-Object { $folders_stream.WriteLine($_) }

Write-Output "$(Get-Date):   Get Children of Root ""$root_path\$folder_path"""
$result_children = Get-ChildItem -LiteralPath "$root_path\$folder_path" -Name -Directory

Write-Output "$(Get-Date):   Loop Children of Root ""$root_path\$folder_path"""
$result_children | ForEach-Object {
    Write-Output "$(Get-Date):     Get Folder Information for ""$root_path\$folder_path\$_"""
    $result_folder = Get-ChildItem -LiteralPath "$root_path\$folder_path" -Filter $_ -Directory `
        | Select-Object FullName, `
            @{Name="FileCount";Expression={(Get-ChildItem -LiteralPath $_.FullName -File | Measure-Object).Count }}, `
            @{Name="DirectoryCount";Expression={(Get-ChildItem -LiteralPath $_.FullName -Directory | Measure-Object).Count }} `
        | ConvertTo-Csv -NoTypeInformation `
        | Select-Object -Skip 1 

    Write-Output "$(Get-Date):       Output Folder Information for ""$root_path\$folder_path\$_"""
    $result_folder | ForEach-Object { $folders_stream.WriteLine($_) }

    Write-Output "$(Get-Date):       Get Folder Information for children of ""$root_path\$folder_path\$_"""
    $result = Get-ChildItem -LiteralPath "$root_path\$folder_path\$_" -Directory -Recurse `
        | Select-Object FullName, `
            @{Name='FileCount';Expression={(Get-ChildItem -LiteralPath $_.FullName -File | Measure-Object).Count }}, `
            @{Name='DirectoryCount';Expression={(Get-ChildItem -LiteralPath $_.FullName -Directory | Measure-Object).Count }} `
        | ConvertTo-Csv -NoTypeInformation `
        | Select-Object -Skip 1

    Write-Output "$(Get-Date):         Output Folder Information for children of ""$root_path\$folder_path\$_"""
    $result | ForEach-Object { $folders_stream.WriteLine($_) }
}

Write-Output "$(Get-Date):   Close Temp Folders File"
$folders_stream.Close()
$folders_stream.Dispose()

Write-Output "$(Get-Date):   Copy Temp Folders File to Final"
Copy-Item -LiteralPath $folders_file_temp_full -Destination $folders_file_final_path -Force

Write-Output "$(Get-Date):   Delete Temp Folder"
Remove-Item -LiteralPath $folders_file_temp_path -Recurse -Force

Write-Output "$(Get-Date): Finish"

GetInstalledSoftware

Script that returns the installed software on the local computer and saves the list to a file.

<#    
.SYNOPSIS   
Script that returns the installed software on the local computer and saves the list to a file.

.DESCRIPTION 
This script reads the System Registry to gather a formatted list of installed software,
then displays it and also saves it to a file on the user's desktop.

.NOTES   
Name: GetInstalledSoftware.ps1
Author: Mike Shook
DateCreated: 07/11/2021 
DateUpdated: 07/11/2021
Version: 1.0.0

.EXAMPLE
    .\GetInstalledSoftware.ps1

#>

$savePath = "$env:USERPROFILE\Desktop"
$computerName = "$env:computername"
$listFile = $computerName + "_AllProgramsListFile.txt"

$software = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* `
    | Sort-Object -Property DisplayName `
    | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate, InstallSource `
    | Format-Table

Write-Output $software
Write-Output $software | Out-File "$savePath\$listFile" -Encoding ASCII
Write-Host "  ** $savePath\$listFile SAVED!" -Foreground Green

GetScheduledTasks

This script uses the Schedule.Service COM-object to query a list of remote computers in order to gather a formatted list of properties of the task.

<#    
.SYNOPSIS   
Script that returns scheduled tasks from a list of computers

.DESCRIPTION 
This script uses the Schedule.Service COM-object to query a list of remote computers in order to gather a formatted list of properties of the task.

.PARAMETER ComputerNames
The computers that will be queried by this script, local administrative permissions are required to query this information

.CREDITS
https://gallery.technet.microsoft.com/scriptcenter/Get-Scheduled-tasks-from-3a377294
https://gallery.technet.microsoft.com/scriptcenter/Ping-Multiple-Servers-ba915a7c
https://techibee.com/powershell/powershell-get-scheduled-tasks-list-from-windows-72008-computers/1647

.NOTES   
Name: GetScheduledTasks.ps1
Author: Mike Shook
DateCreated: 02/04/2020 
DateUpdated: 02/04/2020
Version: 1.0.0

.EXAMPLE
    .\GetScheduledTasks.ps1 -ComputerNames "server01,server02"

#>

param (                        
    [string[]] $ComputerNames = $env:computername
)

$objNotFound = New-Object PSObject

#function to get all scheduled task folder details.
function Get-TaskSubFolders {
    [CmdletBinding()]
    param(
        $FolderRef
    )
    $ArrFolders = @()
    try {
        $folders = $folderRef.GetFolders(1)
        if ($folders) {
            foreach ($folder in $folders) {
                $ArrFolders = $ArrFolders + $folder
                if ($folder.GetFolders(1)) {
                    Get-TaskSubFolders -FolderRef $folder
                }
            }
        }
    } catch {} finally {}
    return $ArrFolders
}

#function to build the error message.
function Return-Error {
    param(
        $computer,
        $type
    )
    Add-Member -InputObject $objNotFound -MemberType NoteProperty -Name ComputerName -Value "$computer ERROR: $type"
    $objNotFound
}

#MAIN 

foreach ($Computer in $ComputerNames) {
    if (Test-Connection -ComputerName $Computer -Count 2 -Quiet) {
        $SchService = New-Object -ComObject Schedule.Service
        $ErrorActionPreference = "SilentlyContinue"
        $SchService.Connect($Computer)
        $ErrorActionPreference = "Continue"
        if ($SchService.Connected) {            
            $Rootfolder = $SchService.GetFolder("\")
            $folders = @($RootFolder)
            $folders += Get-TaskSubFolders -FolderRef $RootFolder
            $foldersCount = $folders | Measure-Object
            if ($foldersCount.Count -gt 1) {
                foreach ($folder in $folders) {
                    $tasks = $folder.gettasks(1)
                    $tasks | Select-Object @{ Name = 'ComputerName'; Expression = { ($SchService.TargetServer) } },`
                         @{ Name = 'TaskName'; Expression = { ($_.Name) } },`
                         @{ Name = 'TaskFolder'; Expression = { ($Folder.Path) } },`
                         @{ Name = 'State'; Expression = { switch ($_.State) { 0 { 'Unknown' } 1 { 'Disabled' } 2 { 'Queued' } 3 { 'Ready' } 4 { 'Running' } Default {'Unknown'} } } },`
                         @{ Name = 'IsEnabled'; Expression = { ($_.Enabled) } },`
                         LastRunTime,`
                         LastTaskResult,`
                         NumberOfMissedRuns,`
                         NextRunTime,`
                         Definition,`
                         @{ Name = 'RegistrationInfo_Author'; Expression = { ([xml]$_.xml).Task.RegistrationInfo.Author } },`
                         @{ Name = 'RegistrationInfo_Date'; Expression = { ([xml]$_.xml).Task.RegistrationInfo.Date } },`
                         @{ Name = 'RegistrationInfo_Description'; Expression = { ([xml]$_.xml).Task.RegistrationInfo.Description } },`
                         @{ Name = 'UserId'; Expression = { ([xml]$_.xml).Task.Principals.Principal.UserID} },`
                         @{ Name = 'Triggers'; Expression = { ([xml]$_.Xml).Task.Triggers.InnerXml } },`
                         @{ Name = 'Actions'; Expression = { ([xml]$_.Xml).Task.Actions.InnerXml } },`
                         @{ Name = 'Xml'; Expression = { ($_.Xml) } }
                }
            } else {
                Return-Error $SchService.TargetServer "Can't retrieve Scheduled Tasks"
            }
        } else {
            Return-Error $Computer "Can't connect"
        }
    } else {
        Return-Error $Computer "Can't ping"
    }
}

JsonToCsv

This script converts a JSON file into a PowerShell object, then retreives desired values from the members of a sub-object.

<#    
.SYNOPSIS   
Script that converts a specific JSON file to a CSV file of the same name.

.DESCRIPTION 
This script converts a JSON file into a PowerShell object, then retrieves desired values from the members of a sub-object.
Also, JSON escaped codes for newline characters are replaced by their literal strings so that Export-Csv doesn't actually put newline characters in the output.

.PARAMETER JsonFile
The file that will be converted by this script

.NOTES   
Name: JsonToCsv.ps1
Author: Mike Shook
Date Created: 07/12/2015 
Date Updated: 06/27/2020
Version: 1.2.0

.EXAMPLE
    .\JsonToCsv.ps1 "C:\data_file.json"

#>

param (                        
    [string[]] $JsonFile = "$home\Desktop\data_file.json"
)

$CsvFile = $JsonFile -replace '.json', '.csv'

Remove-Item -Path $CsvFile -Force -ErrorAction SilentlyContinue

ForEach ($object in (Get-Content -Path $JsonFile -Raw | ConvertFrom-Json).reflections) {
    $object | select @{ Name = 'data_server_http_accept'; Expression = {$object.data.server.http_accept -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_http_accept_encoding'; Expression = {$object.data.server.http_accept_encoding -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_http_accept_language'; Expression = {$object.data.server.http_accept_language -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_https'; Expression = {$object.data.server.https -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_remote_addr'; Expression = {$object.data.server.remote_addr -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_request_method'; Expression = {$object.data.server.request_method -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_request_time'; Expression = {$object.data.server.request_time -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_name'; Expression = {$object.data.server.server_name -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_port'; Expression = {$object.data.server.server_port -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_protocol'; Expression = {$object.data.server.server_protocol -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_about'; Expression = {$object.links.about -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_openapi'; Expression = {$object.links.openapi -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_swaggerhub'; Expression = {$object.links.swaggerhub -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_wadl'; Expression = {$object.links.wadl -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_describedby'; Expression = {$object.links.describedby -replace '[\r]','\r' -replace '[\n]','\n' }}`
     | Export-Csv -Path "$CsvFile" -NoTypeInformation -Append -Delimiter ',' -Encoding UTF8
}

XmlToCsv

This script converts a XML file into a PowerShell object, then retreives desired values from the members of a sub-object.

<#    
.SYNOPSIS   
Script that converts a specific XML file to a CSV file of the same name.

.DESCRIPTION 
This script converts a XML file into a PowerShell object, then retrieves desired values from the members of a sub-object.
Also, XML newline characters are replaced by their literal strings so that Export-Csv doesn't actually put newline characters in the output.

.PARAMETER XmlFile
The file that will be converted by this script

.NOTES   
Name: XmlToCsv.ps1
Author: Mike Shook
Date Created: 05/17/2015 
Date Updated: 06/27/2020
Version: 1.2.0

.EXAMPLE
    .\XmlToCsv.ps1 "C:\data_file.xml"

#>

param (                        
    [string[]] $XmlFile = "$home\Desktop\data_file.xml"
)

$CsvFile = $XmlFile -replace '.xml', '.csv'

Remove-Item -Path $CsvFile -Force -ErrorAction SilentlyContinue

[xml]$XmlDocument = Get-Content -Path $XmlFile

ForEach ($object in $XmlDocument.reflections) {
    $object | select @{ Name = 'data_server_http_accept'; Expression = {$object.data.server.http_accept -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_http_accept_encoding'; Expression = {$object.data.server.http_accept_encoding -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_http_accept_language'; Expression = {$object.data.server.http_accept_language -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_https'; Expression = {$object.data.server.https -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_remote_addr'; Expression = {$object.data.server.remote_addr -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_request_method'; Expression = {$object.data.server.request_method -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_request_time'; Expression = {$object.data.server.request_time -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_name'; Expression = {$object.data.server.server_name -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_port'; Expression = {$object.data.server.server_port -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'data_server_server_protocol'; Expression = {$object.data.server.server_protocol -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_about'; Expression = {$object.links.about -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_openapi'; Expression = {$object.links.openapi -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_swaggerhub'; Expression = {$object.links.swaggerhub -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_wadl'; Expression = {$object.links.wadl -replace '[\r]','\r' -replace '[\n]','\n' }},`
        @{ Name = 'links_describedby'; Expression = {$object.links.describedby -replace '[\r]','\r' -replace '[\n]','\n' }}`
     | Export-Csv -Path "$CsvFile" -NoTypeInformation -Append -Delimiter ',' -Encoding UTF8
}

ValidateActiveDirectoyPassword

This script validates a user's Active Directory password.

<#    
.SYNOPSIS   
Script that validates a user's Active Directory password.

.NOTES   
Name: ValidateActiveDirectoyPassword.ps1
Author: Mike Shook

Version: 1.0.0.1
Version Date: 07/20/2021

Source: https://serverfault.com/questions/276098/check-if-user-password-input-is-valid-in-powershell-script
#>

#Read credentials
$cred = Get-Credential 
$UserName = $cred.username
$Password = $cred.GetNetworkCredential().password

# Get current domain using logged-on user's credentials
$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $UserName, $Password)

if ($domain.name -eq $null) {
    write-host "Authentication failed - please verify your username and password."
}
else {
    write-host "Successfully authenticated with domain $domain.name"
}
Back to top