# Find all open Ports and report the local address, local port, remote address, remote port, and Owning Process$connections=Get-NetTCPConnection|sort-objectState,LocalAddress,OwningProcess|Where-Object{$_.LocalAddress-notlike'*:*'}$connections|Format-Table-AutoSizeLocalAddress,LocalPort,RemoteAddress,RemotePort,State,@{Label="Owning Process"Expression={(Get-Process-Id$_.OwningProcess)}}
Enumerate currently advertising mDNS services and instances
<# -----------------------------------------------------------
DNS-SD discovery (Bonjour) — Windows PowerShell
Enumerate all service types, browse instances, resolve Host/Port/TXT.
Similar to unix 'avahi-browse -at'
Requires: dns-sd.exe (Bonjour)
----------------------------------------------------------- #># Many dns-sd.exe commands (like dns-sd.exe -B) run forever in order to catch when devices announce/reannounce themselves# To make this script-friendly, we use this wrapper to run the dns-sd.exe command with a timeoutfunctionInvoke-DnsSdJob{[CmdletBinding()]param([Parameter(Mandatory)][string[]]$ArgArray,# e.g. @('-B','_services._dns-sd._udp','local')[int]$Seconds=5)# Resolve full path to dns-sd.exe for the child process$exe=(Get-Commanddns-sd.exe-ErrorActionStop).Source# Creates a background job that actually runs dns-sd.exe$job=Start-Job-ScriptBlock{param($exePath,$argsArray)# Run dns-sd.exe with proper argument array (string splitting/joining)&$exePath@argsArray}-ArgumentList$exe,$ArgArray# Wait up to $Seconds seconds (5 by default) then collect whatever has been output$null=Wait-Job-Id$job.Id-Timeout$Seconds$out=Receive-Job-Id$job.Id-Keep# If the job is still running, kill it cleanlyif((Get-Job-Id$job.Id).State-ne'Completed'){Stop-Job-Id$job.Id}Remove-Job-Id$job.Idreturn$out}# Extract service types like "_http._tcp" from textfunctionGet-DnsSdTypes{param([string]$Domain='local',[int]$Seconds=5)$out=Invoke-DnsSdJob-ArgArray@('-B','_services._dns-sd._udp',$Domain)$types=$out|ForEach-Object{$line=$_# Find protocol in “Service Type” column and instance label at the end of the lineif($line-match'(?im)_(?<proto>tcp|udp)\.local\.\s+(?<inst>_[A-Za-z0-9-]+)\s*$'){"$($matches['inst'])._$($matches['proto'])"}}|# Make sure the object returned is a valid objectWhere-Object{$_}|# Filter out browse helpers / non-browseable typesWhere-Object{$_-notmatch'^_(services|dns-sd|mdns|sub)\._'}|Sort-Object-Uniquereturn$types}# Extract instance names for a given typefunctionGet-DnsSdInstances{param([string]$Type,[string]$Domain='local',[int]$Seconds=6)$out=Invoke-DnsSdJob-ArgArray@('-B',$Type,$Domain)-Seconds$Seconds# Output looks something like this (includes space at beginning of line):# ' 9:45:55.660 Add 2 24 local. _smb._tcp. UNAS-Pro'# Sometimes entries will have "Rmv" in the A/R column, meaning Bonjour has told the browser that a previously # seen service is no longer present (service times out, interface goes away, app/device deregisters w/ goodbye)# Because of this, we want to exclude devices that have been removed (as long as it isn't present on *any* interface)# So we track instance by last-seen state (inst|type|domain|ifIndex)$byKey=@{}# Regex should capture any line that has a tcp/udp protocol, and capture the add/remove state (ar), interface (if), # domain (domain), service type (stype), protocol (proto), and instance name (inst) foreach($linein$out){if($line-match'^\s*\d{1,2}:\d{2}:\d{2}\.\d{3}\s+(?<ar>Add|Rmv)\s+\d+\s+(?<if>\d+)\s+(?<domain>\S+)\s+(?<stype>_[A-Za-z0-9-]+)\._(?<proto>tcp|udp)\.\s+(?<inst>.+)$'){# Get each value we'll be using for the composite key$inst=$matches['inst'].Trim()$stype=$matches['stype']$proto=$matches['proto']$domain=$matches['domain'].TrimEnd('.')$ifIdx=[int]$matches['if']# Builds a composite key string that looks something like this:# UNAS-Pro|_smb._tcp|local|2$key="$inst|$stype._$proto|$domain|$ifIdx"# If the value for the instance state is "Add", this adds "$true" at that key, and "$false" otherwise$byKey[$key]=($matches['ar']-eq'Add')}}# Collapse across interfaces: keep instance if any interface is still "Add"$alive=@{}foreach($kin$byKey.Keys){$parts=$k-split'\|',5$inst=$parts[0]# Builds grouping key ignoring interface (type|domain), like this:# _smb._tcp|local# We'll aggregate all interfaces under this one grouping key so that "Any interface alive = keep"$typeDom=$parts[1]+'|'+$parts[2]if($byKey[$k]){$alive["$inst|$typeDom"]=$true}elseif(-not$alive.ContainsKey("$inst|$typeDom")){$alive["$inst|$typeDom"]=$false}}# Only return the instance names of each valid object$alive.GetEnumerator()|Where-Object{$_.Value}|ForEach-Object{($_.Key-split'\|',3)[0]}|Sort-Object-Unique}# Resolve one instance to Host/Port/TXTfunctionResolve-DnsSdInstance{param([string]$Instance,[string]$Type,[string]$Domain='local',[int]$Seconds=5)# Get the instance, and if it it doesn't return anything, return early# Returns something like this:# Lookup 847848B29489._spotify-connect._tcp.local# 10:06:45.269 847848B29489._spotify-connect._tcp.local. can be reached at 847848B29489.local.:55145 (interface 24)# CPath=/zc VERSION=1.0 Stack=SP$out=Invoke-DnsSdJob-ArgArray@('-L',$Instance,$Type,$Domain)-Seconds$Secondsif(-not$out){return$null}$text=($out-join[System.Environment]::NewLine)# Get the hostname and port from the the output from the line that looks like:# 10:06:45.269 847848B29489._spotify-connect._tcp.local. can be reached at 847848B29489.local.:55145 (interface 24)$instanceHostname=$null;$port=$nullforeach($linein$text){if($line-match'can be reached at\s+(?<host>[^\s:]+)\.?:?(?<port>\d+)'){$instanceHostname=$matches['host'].TrimEnd('.')$port=[int]$matches['port']break}}# Find host IP by querying the instance for its A record. Returns something like:# Timestamp A/R Flags if Name T C Rdata# 10:12:54.818 Add 2 24 847848B29489.local. 1 1 192.168.10.217$hostIp=Invoke-DnsSdJob-ArgArray@('-Q',$InstanceHostname,'A')-Seconds$Secondsforeach($linein$hostIp){if($line-match'(Add|Rmv)\s+\d+\s+\d+\s+(?<hostname>\S+?)\.(?<domain>\S+?)\.\s+\d+\s+\d+\s(?<hostip>[\d\.]+)'){$hIp=$matches['hostip']break}}# Get TXT records (Can return multiple)$txtLines=@()foreach($linein$out){# Write-Host $lineif($line-match'^\s*TXT record:\s*(.+)$'){# Write-Verbose "Line Matched!"$txtLines+=$matches[1]continue}# Windows will usually print TXT records as an indented list of tokenselseif($line-match'^\s*(?:\S+=\S.*)(?:\s+\S+=\S.*)*\s*$'){$txtLines+=$matches[0].Trim()continue}}$txtRaw=($txtLines-join' ').Trim()# Parse records into a key/value map (handles quoted values)$txtKv=@{}if($txtRaw){# Tokenizes on spaces but preserves quoted segments: "key=val with spaces"$tokenRx='(?:"((?:[^"\\]|\\.)*)"|(\S+))'foreach($min[regex]::Matches($txtRaw,$tokenRx)){$token=if($m.Groups[1].Success){$m.Groups[1].Value}else{$m.Groups[2].Value}if($token-match'^(?<k>[^=]+)=(?<v>.*)$'){$txtKv[$matches['k']]=$matches['v']}else{#Boolean-style TXT string (Rare but allowed)$txtKv[$token]=$true}}}# Parse _adisk nested TXT (dkN= and sys=)$adisk=[PSCustomObject]@{System=@{}Disks=@()}# Parse system-wide options (sys=adVF=...,waMA=...)if($txtKv.ContainsKey('sys')){foreach($pin($txtKv['sys']-split'\s*,\s*')){if($p-match'^(?<k>[^=]+)=(?<v>.*)$'){$adisk.System[$matches.k]=$matches.v}}}# Parse per-disk entries (dk0=adVN=...,adVF=0x82[,adVU=uuid])foreach($kvin$txtKv.GetEnumerator()){if($kv.Key-match'^dk(?<idx>\d+)$'){$disk=@{Index=[int]$matches.idx}foreach($pin($kv.Value-split'\s*,\s*')){if($p-match'^(?<k>[^=]+)=(?<v>.*)$'){$disk[$matches.k]=$matches.v}}$adisk.Disks+=[pscustomobject]$disk}}# Create a print-friendly flattened txt string out of the parsed txt records$txtDisplay=($txtKv.GetEnumerator()|Sort-ObjectKey|ForEach-Object{$k=$_.Key$v=[string]$_.Value# Quote strings that contain spaces or quotesif($v-match'[\s"]'){$v='"'+($v-replace'"','\"')+'"'}"$k=$v"})-join' '# Build a friendly volumes string and SystemFlags string (only for _adisk._tcp)$adiskVolumes=$null$adiskSysFlags=$nullif($Type-eq'_adisk._tcp'-and$adisk.Disks.Count-gt0){$adiskVolumes=($adisk.Disks|ForEach-Object{$name=$_.adVN$flags=$_.adVFif($name){"{0} (flags {1})"-f$name,$flags}else{$null}}|Where-Object{$_})-join'; '}if($Type-eq'_adisk._tcp'-and$adisk.System.ContainsKey('adVF')){$adiskSysFlags=$adisk.System['adVF']}# Exit early if host, port, and txt are nullif(-not$instanceHostname-and-not$port-and$txtKv.Count-eq0){return$null}# Creates a custom PS object that represents the instance[PSCustomObject]@{Type=$TypeInstance=$InstanceDomain=$DomainHost=$instanceHostnameIP=$hIpPort=$portTXT=$txtDisplay# For tables/CSVTXTMap=$txtKv# For programmatic parsing#_adisk convenience, make sure all objects have these propertiesVolumes=if($Type-eq'_adisk._tcp'-and$adisk.Disks.Count){$adiskVolumes}else{$null}TMFlags=if($Type-eq'_adisk._tcp'-and$adisk.System['adVF']){$adiskSysFlags}else{$null}}}# Orchestrator - Discover everythingfunctionFind-DnsSd{[CmdletBinding()]param([string]$Domain='local',[int]$BrowseSeconds=5,# Timeout for -B calls[int]$ResolveSeconds=3# Timeout for -L calls)Write-Verbose"Enumerating service types in '$Domain'..."$types=Get-DnsSdTypes-Domain$Domain-Seconds$BrowseSeconds$all=New-ObjectSystem.Collections.Generic.List[object]# For each service (type) we find, get the instancesforeach($tin$types){Write-Verbose"Browsing $t ..."$instances=Get-DnsSdInstances-Type$t-Domain$Domain-Seconds$BrowseSeconds# Resolve each instance we findforeach($instin$instances){Write-Verbose"Resolving '$inst' ($t)..."$rec=Resolve-DnsSdInstance-Instance$inst-Type$t-Domain$Domain-Seconds$ResolveSecondsif($rec){$all.Add($rec)}}}# Output all instances as a list of objects$all}# Example usage# Individual function examples:# Get-DnsSdTypes -Seconds 10# Get-DnsSdInstances -Type _airplay._tcp -Seconds 6 -Verbose# Resolve-DnsSdInstance -Instance shellyplus2pm-10061cc9b44c -Type _shelly._tcp | Sort-Object Type, Instance | Format-Table -AutoSize# # 1) Discover Everything (Default timeout)$results=Find-DnsSd-ResolveSeconds2-Verbose# # 2) View results in a table$results|Format-Table-PropertyType,Instance,Host,Port,Volumes,TMFlags,TXT-Wrap-AutoSize# 3) Save to CSV# $results | Export-Csv -NoTypeInformation -Encoding UTF8 -Path ".\dns-sd-inventory.csv"
Command Prompt
Delete files older than X days
REM Windows batch file to delete all files in a specific folder older than x daysREM Based on script from https://www.howtogeek.com/131881/how-to-delete-files-older-than-x-days-on-windows/REM Get folder to clear out and time restrictionset/p "folder=Enter folder to clear out: "REM Check if folder existsifnotexist%folder%\*gotonotexistREM Enter how old in days the file must be to be deleted then lists the files in the folderREM If the input is invalid, catch it and quitset/p "UserInput=How old should the deleted files be (in days)? "set/a days=%UserInput%if%days%EQU0(echoDeletionFailed. CheckSyntax.
pausegotoquit)else(forfiles-p %folder%-s -m *.*-d -%days%-c "cmd /c echo @file"pause)REM Ask user if they want to delete the listed filesset/p "choice=Delete these files? [Y/N]: "if/I %choice%=="Y"gotodeletegotonodelete:nodeleteechoNotdeletingfiles.
gotoquit:deleteREM Delete files in specified folderechoDeletingfilesforfiles-p %folder%-s -m *.*-d -(Numberofdays)-c "cmd /c del @path"gotoquit:notexistechoFolderdoesnotexistgotoquit:quitpause