DHB-Scripting Community Forum
»
Technical Advice
»
Scripting
»
PowerShell and Getting Basic FileInfo with a Timeout
Rank: Advanced Member
Groups: Registered
Joined: 7/1/2018(UTC) Posts: 64  Thanks: 1 times Was thanked: 6 time(s) in 6 post(s)
|
PowerShell and Getting Basic FileInfo with a Timeout
A few weeks ago I posted about starting a .NET Process with a Timeout through PowerShell that will redirect StdOut and StdErr. Today, I am going to build on that by demonstrating a practical example that does scale. I know I'm going to take some dings for using the older "dir" command instead of "Get-Item". I am totally prepared for that. At the end of the day, I'm working with PowerShell object data to fix issues instead of waiting for scripts to complete. When dealing with lots of endpoints, every second counts. The ability to shave 10 seconds off of a 20 second RPC timeout makes a big difference when dealing with 20K endpoints. Thread this out and it becomes incredibly fast.
This solution is a little different by mixing the old and the new. It is what I call a "hybrid" solution which is really starting to become our MO more than ever. I've said it many times, the true greatness of PowerShell is the ability to get to the answer many different ways. Below is mine.
Code:function Get-DirFileInfo
{
<#
.SYNOPSIS
Function to get file info from the "dir" command.
.DESCRIPTION
Function to get file info from the "dir" command. This function calls
Start-ProcessWaitTimeout so it will only wait as long as the timeout.
#>
param (
[Parameter(Mandatory=$true)]
[string]$Computer,
[Parameter(Mandatory=$true)]
[string]$FilePath
)
# Create the Object
$Obj = [PSCustomObject]@{
Computer = $Computer
Online = $null
FilePath = $FilePath
DirPath = $null
FileName = $null
Exists = $null
Size = $null
LastModifiedDate = $null
CmdResult = $null
}
# Change the Directory path to the UNC path
$Obj.DirPath = "\\$($Computer)\$($FilePath.Substring(0,$FilePath.LastIndexOf("\")).Replace(":","$"))"
# Set the File Name
$Obj.FileName = $FilePath.Split("\")[-1]
## CHECK PING STATUS - RETURN IF OFFLINE
$pingStatus = ping -n 1 -4 $computer
if ($?) {
if ($pingStatus -match "unreachable" -or $pingStatus -match "could not find host" -or $pingStatus -match "timed out") {
$Obj.Online = $false
Return $Obj
} else {
$Obj.Online = $true
}
} else {
$Obj.Online = $false
Return $Obj
}
# Setup the Command
$Cmd = "C:\Windows\System32\cmd.exe"
$CmdArgs = @("/c","dir","/-c","""$($Obj.DirPath)\$($Obj.FileName)""")
# Run the Command
$Obj.CmdResult = Start-ProcessWaitTimeout -Computer $Computer -CmdLine $Cmd -CmdLineArgs $CmdArgs -Timeout 10
# Loop throught the StdOut
foreach ($i in $Obj.CmdResult.ProcessStdOut.Split("`n")) {
if ($i -match "(?<Date>\d\d/\d\d/\d\d\d\d)\s+(?<Time>\d\d:\d\d\s\w\w)\s+(?<Size>.*)\s+($($Obj.FileName)).*") {
$Obj.Exists = $true
$Obj.LastModifiedDate = (Get-Date("$($Matches.Date) $($Matches.Time)"))
$Obj.Size = [int]$($Matches.Size)
}
}
# Return the Object
Return $Obj
}
# Example
Get-DirFileInfo -Computer "Computer1" -FilePath "C:\Program Files\7-Zip\7z.exe"
Follow Dustin Higgins on Twitter and Instagram Edited by user Monday, December 30, 2019 10:50:13 PM(UTC)
| Reason: Not specified
|
|
|
|
|
|
Rank: Newbie
Groups: Registered
Joined: 12/14/2019(UTC) Posts: 1  Location: California
|
Well, we know habits are hard to break, especially for us old guys, but still, why dir vs gci, I mean they are both just 3 chars, which I assume you chose dir because of habit or otherwise. ;-} Well, that and gci is still the PowerShelly way . Sure, sure, we all know, to be proper PowerShell citizens, when using scripts never use aliases or shorthand stuff, but, well, u know. ;-} Yet, I see what you are doing here and it's a good tip.
|
|
|
|
|
|
Rank: Advanced Member
Groups: Registered
Joined: 7/1/2018(UTC) Posts: 64  Thanks: 1 times Was thanked: 6 time(s) in 6 post(s)
|
I really appreciate the feeback and the discussion. I am using cmd.exe /c dir by design. That combined with the Start-ProcessWaitTimeout function deals gracefully (timeout and move on) with machines in bad states. That is the main reason. I have also tried PS jobs and wmi calls with timeouts. They don’t seem to handle the bad states gracefully. An example is that DNS has the incorrect name for a real computer. That typically results in an RPC timeout that would last ~20 seconds. It is usually not a big deal when there are not that many machines. Turning the 20 seconds into 5 or 10 seconds makes a big difference when dealing with 1000’s of machines. Honestly, gci for everything else. I totally agree. It is very different, however incredibly fast. The other thing I really like about it is that you start to see patterns in the data (mainly for housekeeping purposes).
|
|
|
|
|
|
DHB-Scripting Community Forum
»
Technical Advice
»
Scripting
»
PowerShell and Getting Basic FileInfo with a Timeout
Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.