PowerShell: Change the timestamp (Date created) of a folder or file
Asked Answered
T

3

18

For PowerShell commands on Windows 10, I encounter a strange behaviour.

To change a file's Date created, I use:

Get-ChildItem  C:\testFile1.txt | % {$_.CreationTime = '01/11/2005 06:00:36'}

To change a folder's Date created, I use:

Get-Item  C:\testFolder1 | % {$_.CreationTime = '01/11/2004 22:13:36'}

Those 2 commands work well on a regular basis on system partition C:\ or on desktop.

The story is different if the folder exists on an external USB flash drive.

(P.S. The command to change a file's timestamp still remains working on the external USB flash drive.)

Suppose I try to change the Date created of a folder (not file) on an external USB flash drive:

Get-Item  U:\testFolder1 | % {$_.CreationTime = '01/11/2002 06:00:36'}

I get this error message:

Exception setting "CreationTime": "The process cannot access the file 'U:\testFolder1' because it is being used by another process."
At line:1 char:31
+ ... et-Item  U:\testFolder1 | % {$_.CreationTime = '01/11/2002 06:00:36'}
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

Digging further, I realize that the process is Windows 10's File Explorer, which prevents me from changing the timestamp. As long as I don't open File Explorer, I can use PowerShell to change the Date created of a folder on the USB flash drive.

Is there anyway like .Dispose() to stop Windows 10's File Explorer from locking the folder without the need to close File Explorer every time?

Trembly answered 15/8, 2016 at 16:42 Comment(4)
You could try with Directory.SetCreationTime() directly: [System.IO.Directory]::SetCreationTime('U:\testFolder1', '01/11/2002 06:00:36')Roundel
Thanks Mathias but this is what I got:Trembly
PS U:\> [System.IO.Directory]::SetCreationTime('U:\testFolder1', '01/11/2000 06:00:36')Trembly
Exception calling "SetCreationTime" with "2" argument(s): "The process cannot access the file 'U:\testFolder1' because it is being used by another process." At line:1 char:1 + [System.IO.Directory]::SetCreationTime('U:\testFolder1', '01/11/2000 ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : IOExceptionTrembly
N
15

Please try the following command.

This also works on an external drive.

(Get-Item  "U:\testFolder1").LastWriteTime = '01/11/2002 06:00:36'
Niemeyer answered 26/5, 2021 at 10:13 Comment(0)
F
3

I have a function that I keep on hand that uses Handle.exe from SysInternals to find what process has a lock on a file, and then tries to kill that process's lock on the file.

Function Close-LockedFile{
Param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)][Object[]]$InputFile
)
Begin{
    $HandleApp = 'C:\localbin\Handle.exe'
    If(!(Test-Path $HandleApp)){Write-Host "Handle.exe not found at $HandleApp`nPlease download it from www.sysinternals.com and save it in the afore mentioned location.";break}
}
Process{
    $HandleOut = Invoke-Expression ($HandleApp+' '+$InputFile.Fullname)
    $Locks = $HandleOut |?{$_ -match "(.+?)\s+pid: (\d+?)\s+type: File\s+(\w+?): (.+)\s*$"}|%{
        [PSCustomObject]@{
            'AppName' = $Matches[1]
            'PID' = $Matches[2]
            'FileHandle' = $Matches[3]
            'FilePath' = $Matches[4]
        }
    }
    ForEach($Lock in $Locks){
        Invoke-Expression ($HandleApp + " -p " + $Lock.PID + " -c " + $Lock.FileHandle + " -y") | Out-Null
    }
    $InputFile
}
}

You should be able to pipe your files to that, and it will unlock any that have a lock, and then pass the file object down the pipe.

Featherbrain answered 15/8, 2016 at 17:51 Comment(3)
NOTE this is not accurate in that it does NOTHING to "try to kill the process". All this entire block of code does is this: "HANDLE.EXE -c" to attempt to have that utility forcibly close the FILE HANDLE - NOT THE PROCESS! Also note what handle.exe itself warns because you are NOT properly killing the app as you indicate with this function: "WARNING: Closing handles can cause application or system instability.". If you choose to use this function I would certainly enhance it first to get the process PID but then add the missing line to kill the PROCESS before closing the handle.Plethoric
@CollinChaffin I did not say that it killed the process, don't quote things out of context like that. I specifically stated "tries to kill that process's lock on the file". You do not always want to kill the process that has the file handle open, such as in the OP's case where it is Explorer.exe that had the file locked.Featherbrain
This article explains why force-closing handles is a bad idea. "And then you've traded temporary relief for long-term data corruption."Sinistrad
E
2

If the powershell runs in a constrained mode, things like

$file.LastWriteTime = (Get-Date) 

will fail with

Property setting is supported only on core types in this language mode.

This works.

Set-ItemProperty -Path $file -Name LastWriteTime -Value (Get-Date)
Evenfall answered 18/4, 2023 at 18:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.