Powershell script that searches network computers and sends back email

I need a Powershell script that will scan all computers on a network to find a file from a list of files and then send me an email telling me which computer has the file. I got this far

$computers = Get-ADComputer -filter *  | Select -Exp Name

$filenames = Get-Content "C:\filenamelist.txt"

foreach ($computer in $computers) {

foreach ($filename in $filenames) {
Get-ChildItem -Recurse -Force \\$computer\c$, \\$computer\d$ -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and  ( $_.Name -eq "$filename") } | Select-Object Name,Directory| Export-Csv C:\FoundFiles.csv -nti -append

___________________________________________________________________________________________________________________________________________
this will scan all computers on the network to finding files found from a file called filenamelist.txt. what i need help with is where to input the code for sending the email in order for it to only send an email if the file is actually found. If you could please test to see if my code works in the firstplace and then the email thing it would be much appreciated. Thanks to anyone who can help
Brady McDermottLearningAsked:
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.

footechCommented:
That code would be horribly slow, having to enumerate all files multiple times on each computer (once for each name in your list).
Not modifying your approach too much, this would be a little better.
$filenames = Get-Content "C:\filenamelist.txt"
$outfile = "C:\FoundFiles.csv"
Get-ADComputer -filter * | Select -Exp Name | ForEach-Object {
    $computer = $_
    Get-ChildItem -Recurse -Force \\$computer\c$, \\$computer\d$ -ErrorAction SilentlyContinue |
     Where-Object { ($_.PSIsContainer -eq $false) -and  ( $filenames -contains $_.Name ) } |
     Select-Object Name,Directory,@{n="Computer";e={$computer}}
} | Export-Csv $outfile -nti -append

If ( (Get-Item $outfile).Length -gt 0 )
{
    Send-MailMessage -To "a@example.com" -From "c@example.com" -Subject "found files" -Attachments $outfile -SmtpServer "smtp.example.com"
}

Open in new window


Making use of PS Remoting (fan-out) so that you don't have to process each machine in a serial fashion and all the drive data across the network would speed things up a lot.

Using the WMI class CIM_DataFile would be faster than Get-ChildItem.  An example of a function that makes use of it is at https://powershell.org/2013/01/29/find-files-with-wmi-and-powershell/
(I'll post it below).
Function Get-CIMFile {
#comment based help is here

[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="What is the name of the file?")]
[ValidateNotNullorEmpty()]
[alias("file")]
[string]$Name,
[ValidateNotNullorEmpty()]
[string]$Drive="C:",
[ValidateNotNullorEmpty()]
[string[]]$Computername=$env:computername,
[switch]$AsJob
)

<#
 strip off any trailing characters to drive parameter
 that might have been passed.
#>
If ($Drive.Length -gt 2) {
    $Drive=$Drive.Substring(0,2)
}

Write-Verbose "Searching for $Name on Drive $Drive on computer $Computername."

<#
Normally you might think to simply split the name on the . character. But
you might have a filename like myfile.v2.dll so that won't work. In a case
like this the extension would be everything after the last . and the filename
everything before.

So instead I'll use the substring method to "split" the filename string.
#>

#get the index of the last .
$index = $name.LastIndexOf(".")
#get the first part of the name
$filename=$Name.Substring(0,$index)
#get the last part of the name
$extension=$name.Substring($index+1)

$filter = "Filename='$filename' AND extension='$extension' AND Drive='$drive'"
Write-Verbose $filter

#get all instances of the file and write the WMI object to the pipeline
Get-WmiObject -Class CIM_Datafile -Filter $filter -ComputerName $Computername -Asjob:$AsJob
}

Open in new window


Some work would need to be done to adapt it to meet your exact needs.
1

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
footechCommented:
First code example shows a method for sending out the email only when a file is found (and includes improvements to the search).  Additional suggestions for improvement were also provided.
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.