Script to remove specific Files from particular machine

Hi All,
As per the below thread, I got a superb script to remove files from specific locations. the only downside to this one is that if there are multiple files on the same host and the machine is offline, each and every file it checks if machine is offline and then update machine offline status. Can it be changed to detect if the machine is offline once, then other consecutive entries it should directly mark as machine offline:

https://www.experts-exchange.com/questions/28514537/Delete-files-from-file-path-against-corresponding-machine-which-are-listed-in-a-CSV.html

Script:
# CSV Needs Header row - Host,Path,Status
$csvPath = "C:\RemoveFiles.csv"
$csv = Import-Csv $csvPath
$csv | ForEach-Object {
    $computer = $_.Host
    $path = $($_.Path) -replace [char]34,""
    $status = $_.Status
    $props = @{
        "Host" = $computer;
        "Path" = $path;
        "Status" = $status
    }
    $obj = New-Object -TypeName PSObject -Property $props
      Write-Host ""
      if ($status -eq "") {
        if (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
            $dollarShare = $path -replace ":","$"
            $uncPath = "\\$computer\$dollarShare"
            if (Test-Path -Path $uncPath) {
                $deleted = $true
                try {
                    Remove-Item -Path $uncPath -Force
                } catch {
                    $deleted = $false
                    $obj.Status = "Could not delete"
                    Write-Host "Unable to remove file on $($computer.ToUpper()) from $($path)"
                }
                if ($deleted) {
                    $obj.Status = "Deleted"
                    Write-Host "Successfully removed file on $($computer.ToUpper()) from $($path)"
                }
            } else {
                $obj.Status = "Missing"
                Write-Host "Missing file on $($computer.ToUpper()) from $($path)"
            }
        } else {
            Write-Host "Host $($computer.ToUpper()) is offline"
                  $obj.Status = "Machine Offline"
        }
    } else {
        Write-Host "File Already Deleted on $($computer.ToUpper()) from $($path)"
    }
      Write-Host ""
    Write-Output $obj
} | Export-Csv -Path $csvPath -Force -NoTypeInformation
qgmasterAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

yo_beeDirector of Information TechnologyCommented:
I am looking at your script and it looks like it should skip the machines.
2017-12-28_8-52-43.pngWhat is happening or maybe I am not understanding what you are looking to adjust.

Can you post an example of the csv output you would like to see?
0
oBdACommented:
Try this:
# CSV Needs Header row - Host,Path,Status
$CsvPath = "C:\RemoveFiles.csv"
$Csv = Import-Csv -Path $CsvPath
$Csv | Group-Object -Property Host | ForEach-Object {
	Write-Host "Processing $($_.Name.ToUpper()) ..." -ForegroundColor White
	If (Test-Connection -ComputerName $_.Name -Count 1 -Quiet) {
		$_.Group | ForEach-Object {
			If ('Deleted', 'Missing' -contains $_.Status) {
				Write-Host "Already processed '$($_.Path)' on $($_.Host.ToUpper())" -ForegroundColor White
			} Else {
				$UncPath = "\\$($_.Host)\$($_.Path.Replace("$([char]34)", '').Replace(':', '$'))"
				If (Test-Path -Path $UncPath) {
					Try {
						Remove-Item -Path $UncPath -ErrorAction Stop
						$_.Status = 'Deleted'
						Write-Host "Removed '$($_.Path)' on $($_.Host.ToUpper())" -ForegroundColor Green
					} Catch {
						Write-Host "Unable to remove '$($_.Path)' on $($_.Host.ToUpper())" -ForegroundColor Red
						$_.Status = 'Could not delete'
					}
				} Else {
					Write-Host "Could not find '$($_.Path)' on $($_.Host.ToUpper())" -ForegroundColor Yellow
					$_.Status = 'Missing'
				}
			}
			$_
 		}
	} Else {
		Write-Host "$($_.Name.ToUpper()) is offline" -ForegroundColor Red
		$_.Group | ForEach-Object {
			$_.Status = 'Machine Offline'
			$_
		}
	}
	Write-Host ''
} | Export-Csv -Path $CsvPath -Force -NoTypeInformation

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
oBdACommented:
Sorry, but yo_bee's comment doesn't really help here.
The issue is not that the machines aren't skipped; qgmaster already pointed out that there is a connection check in place.
The issue is that the csv can contain the same computer name multiple times, with a different path to delete in each row.
In the original script, each line in the csv is processed, and for each line, the respective computer pinged - multiple times if there are multiple files to delete for that machine, even if this computer has already been determined to not respond. This slows things down considerably if the machine is offline and the script has to wait for the (lost) ping multiple times.
Pseudo code:
ForEach (<Row>) {
	If (Test-Connection <Row.Host>) {
		<delete file>
	} Else {
		<mark offline>
	}
}

Open in new window

In other words, a csv like this
OfflinePC,File1
OfflinePC,File2
OfflinePC,File3
would be processed like this:
(Row with File1) Test-Connection OfflinePC fails
(Row with File2) Test-Connection OfflinePC fails
(Row with File3) Test-Connection OfflinePC fails
where the second and third ping are obviously unnecessary.
This is what qgmaster was aiming at with "Can it be changed to detect if the machine is offline once, then other consecutive entries it should directly mark as machine offline"

The script in https:#a42417643 solves this by grouping the rows by computers first and then processing each group depending on whether the computer responds.
Pseudo code:
ForEach (<Computer>) {
	If (Test-Connection <Computer>) {
		ForEach (<File On This Computer>) {
			<delete file>
		}
	} Else {
		<mark offline>
	}
}

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.