From 6f415dfa8d8dd10000a3ded83a9daa2b2ceb3850 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:27:58 -0400 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20fix(scripts):=20correct=20st?= =?UTF-8?q?ring=20interpolation,=20obsolete=20API,=20and=20ErrorActionPref?= =?UTF-8?q?erence=20scope=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Snippets\RemoteServerSessionLoop2.ps1: replace Enter-PSSession (interactive-only) with Invoke-Command -Session; fix string interpolation for \.ComputerName and \.State using \ subexpression syntax - DDI\DNS Reverse Lookup from CSV.ps1: replace obsolete GetHostbyAddress() with GetHostEntry() - Windows\Disable-Poshv2.ps1: fix \.Count not expanding in double-quoted string - AD Users\Set User EmailAddress from PrimaryAddress.ps1: fix \.Name not expanding in Write-Progress -Status string - DDI\Resolve-IPs.ps1: remove \Continue global assignment inside foreach loop; wrap DNS lookup in try/catch to suppress per-call errors without leaking preference scope Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...t User EmailAddress from PrimaryAddress.ps1 | 2 +- ...p from CSV and Add Column with Hostname.ps1 | 2 +- DDI/Resolve-IPs.ps1 | 7 +++++-- Snippets/RemoteServerSessionLoop2.ps1 | 18 +++++++++--------- Windows/Disable-Poshv2.ps1 | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Active Directory/AD Users/Set User EmailAddress from PrimaryAddress.ps1 b/Active Directory/AD Users/Set User EmailAddress from PrimaryAddress.ps1 index 650292a..8989c59 100644 --- a/Active Directory/AD Users/Set User EmailAddress from PrimaryAddress.ps1 +++ b/Active Directory/AD Users/Set User EmailAddress from PrimaryAddress.ps1 @@ -32,7 +32,7 @@ Write-Progress -Id 1 -Activity $MainScriptActivity -Status $MainScriptStatus -Pe foreach ($user in $users) { $i++ - Write-Progress -Id 2 -Activity $UserLoopActivity -Status "$i of $userCount - $user.Name" -PercentComplete ($i / $userCount * 100) -ParentId 1 + Write-Progress -Id 2 -Activity $UserLoopActivity -Status "$i of $userCount - $($user.Name)" -PercentComplete ($i / $userCount * 100) -ParentId 1 $addresses = $user | Select-Object -ExpandProperty ProxyAddresses If ($addresses) diff --git a/DDI/DNS Reverse Lookup from CSV and Add Column with Hostname.ps1 b/DDI/DNS Reverse Lookup from CSV and Add Column with Hostname.ps1 index 425d458..1b2f880 100644 --- a/DDI/DNS Reverse Lookup from CSV and Add Column with Hostname.ps1 +++ b/DDI/DNS Reverse Lookup from CSV and Add Column with Hostname.ps1 @@ -2,6 +2,6 @@ $file = "" $csv = Import-Csv $file foreach ($row in $csv) { $IP = $row.SourceIP - $row.SourceName = ([System.Net.DNS]::GetHostbyAddress($IP)).Hostname + $row.SourceName = ([System.Net.DNS]::GetHostEntry($IP)).Hostname } $csv | Export-Csv "results.csv" -NoTypeInformation diff --git a/DDI/Resolve-IPs.ps1 b/DDI/Resolve-IPs.ps1 index d767cd3..26b97d9 100644 --- a/DDI/Resolve-IPs.ps1 +++ b/DDI/Resolve-IPs.ps1 @@ -14,11 +14,14 @@ $ResultList = @() foreach ($IP in $ListOfIPs) { - $ErrorActionPreference = 'silentlycontinue' $Result = $null Write-Host "Resolving $IP" -ForegroundColor Green - $result = [System.Net.Dns]::gethostentry($IP) + try { + $result = [System.Net.Dns]::gethostentry($IP) + } catch { + $result = $null + } If ($Result) { $ResultList += "$IP," + [string]$Result.HostName diff --git a/Snippets/RemoteServerSessionLoop2.ps1 b/Snippets/RemoteServerSessionLoop2.ps1 index ef10d72..a0a6384 100644 --- a/Snippets/RemoteServerSessionLoop2.ps1 +++ b/Snippets/RemoteServerSessionLoop2.ps1 @@ -19,20 +19,20 @@ foreach ($server in $servers) { Try { Write-Information "Connecting to $server... " -InformationAction Continue - Enter-PSSession $session + # Enter-PSSession is interactive-only; use Invoke-Command to run code in the remote session. + Invoke-Command -Session $session -ScriptBlock { + <# + Code to be run on each remote server goes here. + #> + Write-Information 'Inner code.' -InformationAction Continue + } } Catch { - Write-Warning "Failed to enter the PSSession for $server. Skipping." -WarningAction Continue + Write-Warning "Failed to connect to $server. Skipping." -WarningAction Continue Continue } Write-Output $session.State - <# - Code to be run on each remote server go here. - #> - Write-Information 'Inner code.' -InformationAction Continue - #Cleanup and then show the current PSSession state. - Exit-PSSession Remove-PSSession $session - Write-Information "$session.ComputerName $session.State `n`n" -InformationAction Continue + Write-Information "$($session.ComputerName) $($session.State) `n`n" -InformationAction Continue } diff --git a/Windows/Disable-Poshv2.ps1 b/Windows/Disable-Poshv2.ps1 index 1357615..5d23569 100644 --- a/Windows/Disable-Poshv2.ps1 +++ b/Windows/Disable-Poshv2.ps1 @@ -11,7 +11,7 @@ $exclusions = @('', '', '') #Filtering out production servers as well as any SQL, Exchange, SharePoint (SPS), Telephony, rinf* servers, and any servers in the "Non Windows" OU. $servers = (Get-ADComputer -Filter 'OperatingSystem -like "Windows Server*" -and Enabled -eq "True" -and Name -notlike "*sps*"' ` -SearchBase 'DC=DOMAIN,DC=COM' -SearchScope Subtree).Name | Where-Object { $_ -notin $Exclusions } | Sort-Object -Write-Information "$servers.Count servers found." +Write-Information "$($servers.Count) servers found." foreach ($server in $servers) { if (Test-WSMan -ComputerName $server -ErrorAction Ignore) { From 2f86ff1376748207d1f14c5c365b29a2480f0a91 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:38:39 -0400 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=90=9B=20fix(scripts):=20address=20pr?= =?UTF-8?q?ior=20PR=20Copilot=20review=20follow-ups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make profile Prompt implementations null-safe when command history is empty - Add ShouldProcess support around New-gMSA Active Directory changes - Update stale remoting catch messages after replacing Enter-PSSession usage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Active Directory/Domain Services/DNSZonesRemote.ps1 | 2 +- .../Set DNS Server Zone Settings via Registry.ps1 | 2 +- Profile and Prompt/PSProfileBase.ps1 | 8 ++++++-- Windows/New-gMSA.ps1 | 10 +++++++--- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Active Directory/Domain Services/DNSZonesRemote.ps1 b/Active Directory/Domain Services/DNSZonesRemote.ps1 index 2ce8b65..6b37387 100644 --- a/Active Directory/Domain Services/DNSZonesRemote.ps1 +++ b/Active Directory/Domain Services/DNSZonesRemote.ps1 @@ -48,7 +48,7 @@ foreach ($srv in $servers) { } } } Catch { - Write-Host -ForegroundColor DarkYellow "Failed to enter the PSSession for $server. Skipping." + Write-Host -ForegroundColor DarkYellow "Failed to create or use the PSSession for $server. Skipping." Continue } Finally { if ($session) { diff --git a/Active Directory/Set DNS Server Zone Settings via Registry.ps1 b/Active Directory/Set DNS Server Zone Settings via Registry.ps1 index f1a92b4..79011d3 100644 --- a/Active Directory/Set DNS Server Zone Settings via Registry.ps1 +++ b/Active Directory/Set DNS Server Zone Settings via Registry.ps1 @@ -55,7 +55,7 @@ foreach ($srv in $servers) { } } } Catch { - Write-Host "Failed to enter the PSSession for $server. Skipping." -ForegroundColor DarkYellow + Write-Host "Failed to create or use the PSSession for $server. Skipping." -ForegroundColor DarkYellow Continue } Finally { if ($session) { diff --git a/Profile and Prompt/PSProfileBase.ps1 b/Profile and Prompt/PSProfileBase.ps1 index f596627..016df19 100644 --- a/Profile and Prompt/PSProfileBase.ps1 +++ b/Profile and Prompt/PSProfileBase.ps1 @@ -170,8 +170,10 @@ if ($IsPowerShellISE -or (-not (Get-Command -Name 'oh-my-posh' -ErrorAction Sile # Custom prompt function that shows admin status, command ID, command duration, and path. function Prompt { $LastCommand = Get-History -Count 1 -ErrorAction SilentlyContinue + $CommandId = if ($LastCommand) { $LastCommand.Id + 1 } else { 1 } + $DurationMilliseconds = if ($LastCommand) { [math]::Ceiling($LastCommand.Duration.TotalMilliseconds) } else { 0 } Write-Host "$AdminStatus " -ForegroundColor "$AdminStatusColor" -NoNewline - Write-Host "[$($LastCommand.Id +1)] $([math]::Ceiling($LastCommand.Duration.TotalMilliseconds))ms " -NoNewline -ForegroundColor White + Write-Host "[$CommandId] ${DurationMilliseconds}ms " -NoNewline -ForegroundColor White Write-Host "$FolderGlyph $($PWD.ToString() -ireplace [regex]::Escape($HOME),'~')" -ForegroundColor Yellow Write-Host '>' -NoNewline -ForegroundColor White return ' ' @@ -190,8 +192,10 @@ if ($IsPowerShellISE -or (-not (Get-Command -Name 'oh-my-posh' -ErrorAction Sile function Prompt { $LastCommand = Get-History -Count 1 -ErrorAction SilentlyContinue + $CommandId = if ($LastCommand) { $LastCommand.Id + 1 } else { 1 } + $DurationMilliseconds = if ($LastCommand) { [math]::Ceiling($LastCommand.Duration.TotalMilliseconds) } else { 0 } Write-Host "$AdminStatus " -ForegroundColor "$AdminStatusColor" -NoNewline - Write-Host "[$($LastCommand.Id +1)] $([math]::Ceiling($LastCommand.Duration.TotalMilliseconds))ms " -NoNewline -ForegroundColor White + Write-Host "[$CommandId] ${DurationMilliseconds}ms " -NoNewline -ForegroundColor White Write-Host "$FolderGlyph $($PWD.ToString() -ireplace [regex]::Escape($HOME),'~')" -ForegroundColor Yellow Write-Host '>' -NoNewline -ForegroundColor White return ' ' diff --git a/Windows/New-gMSA.ps1 b/Windows/New-gMSA.ps1 index e375e0e..8417183 100644 --- a/Windows/New-gMSA.ps1 +++ b/Windows/New-gMSA.ps1 @@ -37,6 +37,7 @@ Function New-gMSA { .OUTPUTS None #> + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory=$true)] [ValidateLength(1,15)] @@ -65,7 +66,10 @@ Function New-gMSA { Import-Module ActiveDirectory $Group = "MSA " + $gMSA $DNS = "$gMSA.$DomainDnsName" - New-ADGroup -Name $Group -GroupScope Global -DisplayName $Group -Description "Permission group for $gMSA" -Path $GroupPath -Credential $Credential - Add-ADGroupMember -Identity $Group -Members ($Servers | ForEach-Object {Get-ADComputer -Identity $_ -Credential $Credential}) -Credential $Credential - New-ADServiceAccount -Name $gMSA -DNSHostName $DNS -PrincipalsAllowedToRetrieveManagedPassword $Group -Path $ServiceAccountPath -Credential $Credential + + if ($PSCmdlet.ShouldProcess($gMSA, 'Create gMSA, retrieval group, and group membership')) { + New-ADGroup -Name $Group -GroupScope Global -DisplayName $Group -Description "Permission group for $gMSA" -Path $GroupPath -Credential $Credential + Add-ADGroupMember -Identity $Group -Members ($Servers | ForEach-Object {Get-ADComputer -Identity $_ -Credential $Credential}) -Credential $Credential + New-ADServiceAccount -Name $gMSA -DNSHostName $DNS -PrincipalsAllowedToRetrieveManagedPassword $Group -Path $ServiceAccountPath -Credential $Credential + } } From 6c22606b4db4a34ac0a1396c6b8c57a044f186a3 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:42:12 -0400 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20fix(scripts):=20address=20PR?= =?UTF-8?q?=2017=20Copilot=20review=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move PSSession creation into try/catch with terminating errors - Ensure PSSession cleanup runs from finally when remote execution fails - Use consistent PascalCase Result variable in Resolve-IPs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- DDI/Resolve-IPs.ps1 | 4 ++-- Snippets/RemoteServerSessionLoop2.ps1 | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/DDI/Resolve-IPs.ps1 b/DDI/Resolve-IPs.ps1 index 26b97d9..53c59e1 100644 --- a/DDI/Resolve-IPs.ps1 +++ b/DDI/Resolve-IPs.ps1 @@ -18,9 +18,9 @@ foreach ($IP in $ListOfIPs) { Write-Host "Resolving $IP" -ForegroundColor Green try { - $result = [System.Net.Dns]::gethostentry($IP) + $Result = [System.Net.Dns]::GetHostEntry($IP) } catch { - $result = $null + $Result = $null } If ($Result) { diff --git a/Snippets/RemoteServerSessionLoop2.ps1 b/Snippets/RemoteServerSessionLoop2.ps1 index a0a6384..f1afa6d 100644 --- a/Snippets/RemoteServerSessionLoop2.ps1 +++ b/Snippets/RemoteServerSessionLoop2.ps1 @@ -15,24 +15,26 @@ if ($session) { Remove-PSSession $session } #Loop through each server in the list, open a PowerShell remoting session, then show the name and status of the session. Skip (continue) to the next server if a connection fails. foreach ($server in $servers) { - $session = New-PSSession -ComputerName $server -Name $server -Credential $Creds + $session = $null Try { Write-Information "Connecting to $server... " -InformationAction Continue + $session = New-PSSession -ComputerName $server -Name $server -Credential $Creds -ErrorAction Stop # Enter-PSSession is interactive-only; use Invoke-Command to run code in the remote session. - Invoke-Command -Session $session -ScriptBlock { + Invoke-Command -Session $session -ErrorAction Stop -ScriptBlock { <# Code to be run on each remote server goes here. #> Write-Information 'Inner code.' -InformationAction Continue } } Catch { - Write-Warning "Failed to connect to $server. Skipping." -WarningAction Continue + Write-Warning "Failed to create or use the PSSession for $server. Skipping." -WarningAction Continue Continue + } Finally { + if ($session) { + # Cleanup and then show the current PSSession state. + Remove-PSSession $session -ErrorAction SilentlyContinue + Write-Information "$($session.ComputerName) $($session.State) `n`n" -InformationAction Continue + } } - Write-Output $session.State - - #Cleanup and then show the current PSSession state. - Remove-PSSession $session - Write-Information "$($session.ComputerName) $($session.State) `n`n" -InformationAction Continue }