Powershell script: List files with specific change date (Amount if possible) - windows

For license porpuses I try to automate the counting process instead of having to login into every single server, go into directory, search a file name and count the results based on the change date.
Want I'm aiming for:
Running a powershell script every month that checks the directory "C:\Users" for the file "Outlook.pst" recursively. And then filters the result by change date (one month or newer). Then packing this into an email to send to my inbox.
I'm not sure if that's possible, cause I am fairly new to powershell. Would appreciate your help!

It is possible.
I dont know how to start a ps session on a remote computer, but I think the cmdlet Enter-PSSession will do the trick. Or at least it was the first result while searching for "open remote powershell session". If that does not work use the Invoke-Command as suggested by lit to get $outlookFiles as suggested below.
For the rest use this.
$outlookFiles = Get-ChildItem -Path "C:\Users" -Recurse | Where-Object { $_.Name -eq "Outlook.pst" }
Now you have all files that have this name. If you are not familiar with the pipe in powershell it redirects all objects it found with the Get-ChildItem to the next pipe section and here the Where-Object will filter the received objects. If the current object ($_) will pass the condition it is returned by the whole command.
Now you can filter these objects again to only include the latest ones with.
$latestDate = (Get-Date).AddMonths(-1)
$newFiles = $outlookFiles | Where-Object { $_.LastAccessTime -gt $latestDate }
Now you have all the data you want in one object. Now you only have to format this how you like it e.g. you could use $mailBody = $newFiles | Out-String and then use Send-MailMessage -To x#y.z -From r#g.b -Body $mailBodyto send the mail.

Related

Powershell - Checking # of files in a folder across a domain

So I'm trying to count the number of font files (that have different extensions) inside the local font folder of every computer in my domain at work to verify which computers have an up to date font installation using powershell.
So far I have
Write-Host ( Get-ChildItem c:\MyFolder | Measure-Object ).Count;
as a means of counting the files, I'm just at a loss on how exactly to replicate this and get a output that indicates the file count for the path for every computer on my domain (the file path is all the same for each)
How should I best proceed?
You will have to run the command against every computer. Assuming you have some sort of domain admin privelege and can access admin shares on all computers, you can use the c$ share.
The code below takes a list of computers in a single column CSV with no headers and runs the command against the admin share on each
$computers = Import-Csv -Path C:\computers.csv -Header Computer;
foreach($c in $computers)
{
Write-Host (Get-ChildItem "\\$($c.Computer)\c$\MyFolder" | Measure-Object).Count;
};

Adding values from multiple computers with custom headers in a single csv

I need to accomplish the scenario below and for that I have to create a couple of powershell scripts to accomplish it.
The environment: Windows servers and Windows clients
Scenario
1- Create a script to be run in a specific time every day (with Task Scheduler) on windows clients. This script will push the current computer's hostname and IP address to a csv file with a specific headers (let's call these "Hostnames" and "IP Address"). These header shouldn't be changed as these scripts run from multiple computers at that time and all computers' data should be appended to each header, not overwrite them as this operation continues.
2- From a server, (after 15 mins) as fetching this "computer" list (csv), there should be a ping check for each of them using their IP addresses. If pings are successful on these remote computers, it should say "This computer is up" next to the each computer name and its IP address. If pings are unsuccessful, it should say "This computer is down" next to the each computer name and its IP address. Above these "status" information, there should be another header (let's say "IsAlive"). This header should be added to the csv as well.
So with this setup, I could be able to learn which computers are UP at a specific time and after I trigger some actions them, I could be able to learn if they're still up or down.
To be honest, I couldn't take a long way for it. I started to write a script about the first step but I couldn't combine the headers with values adding under them.
$header="Hostname"
$outputfile="\\10.10.10.40\reports\upcomputers.csv"
Add-Content $outputfile -Value $header
$hostname >> $outputfile
If I use this script (even if with one header), it's adding "NULL" after each alphabet of hostname and it doesn't append the other hostname under the "Hostname" header.
Additionally, I have no idea where to start adding the third header (IsAlive) and add each Test-NetConnection query's output as checking their IP addresses. I request you to show me a way to start with this section as well.
Finally, my output should be like that;
For the first step;
For the second step;
Thank you for your help and information
Stated on the main body of the request
Stage 2:
The easy way of doing this using PSCustomobject. Please find the sample code below:
$outputcsv = "C:\PowerShell\pingstatus.csv"
$hostlist = import-csv "C:\PowerShell\hostlist.csv"
$result = foreach($line in $hostlist){
$pingtest = Test-Connection -ComputerName $line.Hostname -Quiet -Count 1 -ErrorAction SilentlyContinue
if($pingtest) {
$OutputMessage = "This computer is up"
}
else {
$OutputMessage = "This computer is down"
}
[pscustomobject][ordered]#{
HostName = $line.Hostname
IPAddress = $line.IPaddress
IsAlive = $OutputMessage
}
}
$result | Export-csv -Path $outputcsv -NoTypeInformation
The Hostname and IPAddress input will be taken as input.
Note: Your input csv file should contain Hostname IPaddress as header.
Stage1:
why not?
$outputfile="\\10.10.10.40\reports\upcomputers.csv"
$serverDetails = [PSCustomObject]#{
Hostname = "$env:COMPUTERNAME"
IPAddress = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | where {$_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null}).IPAddress | Select-Object -First 1
}
$serverDetails | Export-csv $outputfile -Append -NoTypeInformation
There are multiple ways to get IP address a computer, I used Get-WMIObject. You may use other simple ways like Test-Connection or Get-NetIPAddress.
To learn more: Please see
[PsCustomObject]: https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.3

What is the most efficient way on getting a list of files utilizing get-childitem

I have created a list of PowerShell commands for getting over 500,000 rows of directories. The goal is to get a list of the files in each of the directories specified in the PowerShell command. My syntax works perfectly if I run a small batch, but there are definitely performance issues when running them in a bulk manner. One thing I noticed is that if I run all these 500,000 rows together, I get extremely high usage (about 12GB and using 97% of memory) and it takes a while for me to even begin to generate a CSV file. Please see my code listed below on what I am using
I was thinking I can get a list of the directories I need to use into a CSV. And researching around here, I can use a CSV as a variable and a foreach. But I am stumped on putting all that together.
Get-ChildItem -Path \\MYIP\ARCHIVE\ArchiveVolumes\UniqueID\ -Exclude *.wav*,*.md5*,*.abc, -Recurse |
Select-Object FullName |
Add-Member -MemberType NoteProperty -Name Myfield -Value 123456 -PassThru |
Export-Csv -Append -Path C:\mypath\fileslist.csv -Encoding ascii -NoType
I'm hoping that I can better utilize what I am running here as I am still learning powershell. Any ideas?

Remote Powershell parsing

Im trying to retrieve a parsed list of different information regarding remote executables within a windows domain, permissions are take care of and the individual Powershell commands are working, my issue is outputting this recursive list on a file (putting all together properly):
My desired Output (per computer):
computer_name.csv # Filename
$application1Name.exe, $application1Version, $application1LastModifiedDateMMDDYY, $application1MD5HASH
$application2Name.exe, $application2Version, $application2LastModifiedDateMMDDYY, $application2MD5HASH
...
So far I have all the pieces:
#A way to recursive retrieve executables from a given remote path (Name + LastModified):
get-childitem \\192.168.X.X\C$\defaultPath\FoldersAndSubfoldersWithExecutables\ - Include *.exe -Recurse | ForEach-Object {$_.Name, $_.LastWriteTime} > C:\LOCALPATH\output.txt
#A way to retrieve the version info from remote executables (Version):
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("\\192.168.X.X\C$\defaultPath\application1.exe").FileVersion
#A way to retrieve the MD5 Hash from remote executable files (MD5HASH):
get-FileHash \\192.168.X.X\C$\defaultPath\application1.exe -Algorithm MD5 | ForEach-Object { $_.Hash }
My issue is building this script structure to accomodate the desired output listed above, I have a list of IP address to loop this script thru but Im having issues connecting the dots..
Thanks!
Each operation you listed can be executed within the ForEach-Object loop, and a resultant csv string containing all the necessary data points can be built using string interpolation.
Get-ChildItem \\192.168.x.x\C$\defaultPath\FoldersAndSubfoldersWithExes\ -Include *.exe -Recurse | ForEach-Object {
$Name = $_.Name
$LastWriteTime = $_.LastWriteTime
$Version =[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.FullName).FileVersion
$Hash = (Get-FileHash $_.FullName -Algorithm MD5).Hash
"$Name, $Version, $LastWriteTime, $Hash"
} | Out-File computerName.csv

Extract hostnames from Perfmon blg with Powershell

I'm writing a script which will automate the extraction of data from .blg Perfmon logs.
I've worked out the primary Import-Counter commands I will need to use to get the data out, but am trying to parametrise this so that I can do it for each machine in the log file (without having to open the log up in Perfmon, which can take 15 minutes or sometimes more, and is the reason I'm writing this script), and find out what each hostname is.
The script I have does the job, but it still takes a minute to return the data I want, and I wondered if there was a simpler way to do this, as I'm not too familiar with Powershell?
Here's what I have:
$counters = Import-Counter -Path $log_path$logfile -ListSet * | Select-Object paths -ExpandProperty paths
$svrs = #()
# for each line in the list of counters, extract the name of the server and add it to the array
foreach ($line in $counters) {
$svrs += $line.split("\")[2]
}
# remove duplicates and sort the list of servers
$sorted_svrs = $svrs | sort -unique
foreach ($svr in $sorted_svrs) {
Write-Host $svr
}
I'm just printing the names for the moment, but they'll go into an array in the proper script, and then I'll run my Import-Counter block with each of these hosts parametrised in.
Just wondered if there was a better way of doing this?
$sorted_svrs=Import-Counter "$log_path$logfile" -Counter "\\*\physicaldisk(_total)\% disk time" | %{$_.countersamples.path.split("\")[2]} | sort -Unique

Resources