Search code examples
powershellpropertieswmimetadatantfs

Powershell: NTFS paths in file metadata with New-ItemProperty, Set-ItemProperty?


I'm interested in adding a property to my files under a certain scope that contains their current locations in my file system, in order to track file movement. I would think that this could be done with New-ItemProperty, with a command similar to the following:

Get-ChildItem -recurse | foreach { New-ItemProperty -Path $.FullName -Name "OriginalLocation" -PropertyType string -Value $.FullName }

However, when I try this, I'm spammed with the following error:

New-ItemProperty : Cannot use interface. The IDynamicPropertyCmdletProvider interface is not implemented by this provider.

After some searching, it appears that New-ItemProperty is all but useless except for working with the registry. Fine. Windows has myriad other file properties I should be able to hijack in order to get this done. "Label" and "Tags" come to mind. So let's try setting those via Set-ItemProperty instead.

Set-ItemProperty : Property System.String Label=D:\test\file.txt does not exist.

It appears I need to create these properties after all. Is this a shortcoming of New-ItemProperty? Maybe setting properties such as this on arbitrary items is some WMI thing I don't know about?


Solution

  • Here is my solution using the redirections ('<' & '>') that allow to manipulate alternate data stream in CMD.EXE. It works in Powershell without any extentions

    # AlternateDataStream.ps1
    
    $scriptBlockSetStream = {cmd /C `"echo $($Args[0])`>$($Args[1]):$($Args[2])`"}
    $scriptBlockGetStream = {cmd /C `"more `<$($Args[0]):$($Args[1])`"}
    
    $streamName = "NativeFilePath"
    $File = "C:\Temp\ADSTest\toto.txt"
    $streamContent = Split-Path -Path $File -Parent
    
    # Set the data stream
    Invoke-Command -ScriptBlock $scriptBlockSetStream  -ArgumentList $streamContent,$File,$streamName
    # Get the Data Stream
    $res = Invoke-Command -ScriptBlock $scriptBlockGetStream  -ArgumentList $File,$streamName
    $res