How to get the real LastWriteTime of a directory? - windows

LastWriteTime of a Directory only updates if a new file is created,
not when one updates
PS>mkdir foo
PS>Get-Item ".\foo" | select -ExpandProperty lastwritetime
Friday, February 12, 2016 1:56:18 PM
PS>"hello" > .\foo\hello.txt
PS>Get-Item ".\foo" | select -ExpandProperty lastwritetime
Friday, February 12, 2016 1:56:53 PM
PS>"line 2" >> .\foo\hello.txt
PS>Get-Item ".\foo" | select -ExpandProperty lastwritetime
Friday, February 12, 2016 1:56:53 PM
PS>"a new file" >> .\foo\hello1.txt
PS>Get-Item ".\foo" | select -ExpandProperty lastwritetime
Friday, February 12, 2016 1:57:55 PM
How do I get the time when a directory changed ?

Related

Output bottom line in Powershell

I want to output the last entry of Get-Hotfix in PowerShell. How does it work?
Example:
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
DESKTOP-FU... Update KB5010472 NT-AUTORITÄT\SYSTEM 15.03.2022 00:00:00
DESKTOP-FU... Update KB5003791 06.10.2021 00:00:00
DESKTOP-FU... Security Update KB5011487 NT-AUTORITÄT\SYSTEM 14.03.2022 00:00:00
DESKTOP-FU... Update KB5007273 NT-AUTORITÄT\SYSTEM 02.01.2022 00:00:00
DESKTOP-FU... Security Update KB5011352 NT-AUTORITÄT\SYSTEM 09.02.2022 00:00:00
DESKTOP-FU... Security Update KB5005699 06.10.2021 00:00:00
I want to output the KB5005699 update to the console.
You can use Select-Object with the -Last 1 parameter to get the last object and -ExpandProperty HotFixID to get the Value of the HotFixID property:
Get-HotFix | Select-Object -Last 1 -ExpandProperty HotFixID
Another alternative would be to get the last object by the -1 index and use dot notation .HotFixID to get the Value:
(Get-HotFix)[-1].HotFixID

PS script not deleting file as scheduled task

Can someone help me understand why this scheduled script doesn't run as intended: The file is not reliably deleted at the start of the next day (runs correctly 3-4X out of 5 whether machine is powered on or out of sleep mode (S3). How to get it to always delete the previous day file?
$Path = "H:\foobar.txt"
if (Test-Path $Path) {Get-ChildItem $Path |
Where-Object { ($_.LastWriteTime).ToString() -lt ((get-date).AddDays(-1)).ToString() } |
Remove-Item -Force }
('{0:MMMM dd, yyyy h:mm:ss tt}' -f (Get-Date)) | Add-Content -Path $Path
EXIT
snippet from output showing carryover into next day:
April 27, 2020 9:31:18 PM
April 28, 2020 7:16:37 AM
April 28, 2020 5:31:45 PM
April 29, 2020 7:16:37 AM
April 29, 2020 11:17:02 PM
April 30, 2020 6:02:06 AM
April 30, 2020 6:17:02 PM
May 01, 2020 6:27:28 AM
May 01, 2020 7:17:02 AM
Seeing that the variable $Path contains the path to a single file, you could shorten the code like:
$Path = "H:\foobar.txt"
# try and get a FileInfo object from the file in the path
$file = Get-Item -Path $Path -ErrorAction SilentlyContinue
if ($file) {
# the file was found, check if it is older than yesterday (midnight)
if ($file.LastWriteTime -lt (Get-Date).AddDays(-1).Date) {
$file | Remove-Item -Force
}
}
# Add-Content will create the file if it does not yet exist
('{0:MMMM dd, yyyy h:mm:ss tt}' -f (Get-Date)) | Add-Content -Path $Path
Required of course is that the user running the scheduled task has write access to the H:\ path..

How to use curly braces path name in windows?

I used to use paths like this ls {path1,path2}/* in Linux but in Windows PowerShell, I got the following error
At line:1 char:10
+ ls {path1,path2}/*
+ ~
Missing argument in parameter list.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingArgument
I tried dir {path1,path2}/* instead of ls {path1,path2}/* but the same error thrown!!
You should use the proper cmdlet/alias for the environment you are working in (consider on linux PowerShell Core ls refers to the system ls not the PoSh gci)
PowerShell allows wildcards *?(and ranges[0-2]) on multple levels, so this should do:
Get-ChildItem -Path some\verbose[12]\dir\* -Include *.ext1,*.ext2
In case the part of the path differs completely you'll have to supply an array:
Get-ChildItem -Path some\this\dir\*,some\that\dir\* -Include *.ext1,*.ext2
I think what you want is this:
ls path1,path2 -recurse
Path1 and Path2 will either need to be variables or quoted Strings.
Here is an example
PS C:\> ls "c:\temp\test1","c:\temp\test2" -recurse
Directory: C:\temp\test1
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/14/2019 10:29 AM test1subdir
Directory: C:\temp\test1\test1subdir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:29 AM 13 test1file.txt
Directory: C:\temp\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:30 AM 6 test2file.log
I know this may be crazy, but you can create a function that will nearly replicate what you are trying to do:
function new-ls {
param([Parameter(Position=0)]
[string]$Path,
[Parameter(Position=1)]
[string[]]$Includes)
$StrMatch = ($Path | sls -pattern "^(.*?){(.*?),(.*?)}(.*?)$" -allmatches).matches.groups.value
$NewPaths = #(($StrMatch[1] + $StrMatch[2] + $StrMatch[4]), ($StrMatch[1] + $StrMatch[3] + $StrMatch[4]))
ls $NewPaths -include $Includes -recurse
}
# Running the code
PS C:\temp> new-ls "c:\temp\{test1,test2}\*"
Directory: C:\temp\test1\test1subdir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:29 AM 13 test1file.txt
Directory: C:\temp\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:30 AM 6 test2file.log
PS C:\temp> new-ls "c:\temp\{test1,test2}\*" "*.txt"
Directory: C:\temp\test1\test1subdir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:29 AM 13 test1file.txt
PS C:\temp> new-ls "c:\temp\{test1,test2}\*" "*.txt","*.log"
Directory: C:\temp\test1\test1subdir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:29 AM 13 test1file.txt
Directory: C:\temp\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/14/2019 10:30 AM 6 test2file.log

powershell not seeing filesystem change - "cannot find path"

I wrote a powershell script that exports a bunch of files from a Dynamics NAV instance. It calls a perl script that I also wrote that then splits all of the files into individual objects and sticks them in subdirectories under a dir I create in perl. Then the powershell script attempts to copy the files to a different dir, and fails.
Powershell generates the dir name:
$datestamp = get-date -f MM-dd-yyyy_HH_mm_ss
$dumpdir = "\temp\nav_export\" + $env:username + "\" + $servicetier + "~" + $database + "~" + $datestamp;
Then powershell does a bunch of stuff that works fine, and calls the perl script ($servicetier and $database are defined earlier in the script):
& c:\navgit\split-objects.pl $servicetier $database $datestamp
perl proceeds to create the directory and split the files correctly:
use strict;
use warnings;
use File::Path qw(make_path remove_tree);
my $username = getlogin || getpwuid($<);
my $servicetier = $ARGV[0];
my $database = $ARGV[1];
my $datestamp = $ARGV[2];
undef #ARGV;
my $work_dir = "/temp/nav_export";
my $objects_dir = "$work_dir/$username/objects";
my $export_dir = "$work_dir/$username/$servicetier~$database~$datestamp";
print "Objects from $servicetier~$database being exported to $export_dir\n";
make_path("$export_dir/Page", "$export_dir/Codeunit", "$export_dir/MenuSuite", "$export_dir/Query", "$export_dir/Report", "$export_dir/Table", "$export_dir/XMLport");
chdir $objects_dir or die "Could not change to $objects_dir: $!";
<does all of the filehandling and parsing>
Control returns to the powershell script, which tries to finish with:
Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
But that throws the error:
Copy-Item : Cannot find path 'C:\temp\nav_export\danielj\cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50' because it does not exist.
At C:\navgit\nav-export.ps1:175 char:1
+ Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\temp\nav_exp...0-2015_19_26_50:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
The directory I'm trying to copy from does exist. But powershell doesn't see it! I added some code to list the contents of the parent dir:
Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
Write-Host "Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse"
$test = "C:\temp\nav_export\$env:username"
Get-ChildItem $test -Force
Copy-Item -Path \temp\nav_export\danielj\cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50 -Destination C:\Users\danielj\erp\ -Force -Recurse
Directory: C:\temp\nav_export\danielj
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/20/2015 6:32 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_18_32_33
d---- 1/20/2015 7:08 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_08_49
d---- 1/19/2015 1:07 PM cen-dev-erp-st1~JustFoodERP-PROTO~20150119-130747
d---- 1/20/2015 7:26 PM logs
d---- 1/20/2015 7:26 PM objects
-a--- 1/20/2015 7:26 PM 309 objects.bat
-a--- 1/20/2015 1:41 PM 436 soap_envelope.txt
If I do a directory listing from outside the script, there it is:
PS C:\Users\danielj\erp> $test = "C:\temp\nav_export\$env:username"
Get-ChildItem $test -Force
Directory: C:\temp\nav_export\danielj
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/20/2015 6:32 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_18_32_33
d---- 1/20/2015 7:08 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_08_49
d---- 1/20/2015 7:26 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50
d---- 1/19/2015 1:07 PM cen-dev-erp-st1~JustFoodERP-PROTO~20150119-130747
d---- 1/20/2015 7:26 PM logs
d---- 1/20/2015 7:26 PM objects
-a--- 1/20/2015 7:26 PM 309 objects.bat
-a--- 1/20/2015 1:41 PM 436 soap_envelope.txt
I've tried calling an external script from the main powershell script after perl is finished, and the results are the same.
Why would powershell not see the directory or files that were created by the perl script? And more importantly, how can I get it to do so?
Are you sure that everything proced in the exact order you assume it does ?
try to start your perl script like this :
& c:\navgit\split-objects.pl $servicetier $database $datestamp | Out-Null
It makes sure that your Perl part is terminated when the PowerShell execute the rest of your script.
I ended up just creating the directory in powershell in the first place. No reason it should have to have been created in the perl script.
It'd still be nice to know why it didn't work the way I'd have expected though.

Cmd/PowerShell/SQL server: Is there any way to see how long a windows service has been running?

So I managed to check if a sevice is running with sc query "ServiceName" | find "RUNNING" or net start | find "Service Name", or in SQL Server using xp_servicecontrol. Is there any way to see the uptime of a service? How can I see the uptime of a service?
As long as your service has it's own process name, this should work.
PowerShell_v4> (Get-Process lync).StartTime
Friday, October 17, 2014 11:46:04
If you're running under svchost.exe, i think you need to grab that from Event Log.
PowerShell_v4> (Get-WinEvent -LogName System | ? Message -match 'DHCPv6 client service is started' | select -First 1).TimeCreated
Friday, October 17, 2014 10:10:56
For Uptime, just compute time diff.
$Start = (Get-Process Outlook).StartTime
$Now = Get-Date
$Now - $Start | Format-Table Days, Hours, Minutes, Seconds -AutoSize
Days Hours Minutes Seconds
---- ----- ------- -------
0 0 2 8
or as a one-liner:
(Get-Date) - (Get-Process Outlook).StartTime | Format-Table Days, Hours, Minutes, Seconds -AutoSize
Days Hours Minutes Seconds
---- ----- ------- -------
0 0 2 8

Resources