I have built a powershell script using the GUI .net framework that provides the user with a graphical interface to add alternate data streams (ADS) to files on a NTFS file system.
Below is the code I wrote for the powershell script:
<#
This script is a GUI featured way to add extended attributes to files
#>
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
#region begin GUI{
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '600,600'
$Form.text = "Add Extended Attributes"
$Form.TopMost = $false
# Add Extended Attributes Label
$mainLabel = New-Object system.Windows.Forms.Label
$mainLabel.text = "Add Extended Attributes"
$mainLabel.AutoSize = $true
$mainLabel.width = 25
$mainLabel.height = 10
$mainLabel.location = New-Object System.Drawing.Point(180,10)
$mainLabel.Font = 'Microsoft Sans Serif,18'
# text box for entering file path
$filePath = New-Object system.Windows.Forms.TextBox
$filePath.multiline = $false
$filePath.width = 300
$filePath.height = 20
$filePath.location = New-Object System.Drawing.Point(200,80)
$filePath.Font = 'Microsoft Sans Serif,10'
# label for the file path text box "File Path: "
$FilePathLabel = New-Object system.Windows.Forms.Label
$FilePathLabel.text = "File Path: "
$FilePathLabel.AutoSize = $true
$FilePathLabel.width = 25
$FilePathLabel.height = 10
$FilePathLabel.location = New-Object System.Drawing.Point(80,85)
$FilePathLabel.Font = 'Microsoft Sans Serif,10'
# Attributes Label
$idLabel = New-Object system.Windows.Forms.Label
$idLabel.text = "Attributes"
$idLabel.AutoSize = $true
$idLabel.width = 25
$idLabel.height = 10
$idLabel.location = New-Object System.Drawing.Point(80,150)
$idLabel.Font = 'Microsoft Sans Serif,12'
# Values Label
$valueLabel = New-Object system.Windows.Forms.Label
$valueLabel.text = "Value"
$valueLabel.AutoSize = $true
$valueLabel.width = 25
$valueLabel.height = 10
$valueLabel.location = New-Object System.Drawing.Point(300,150)
$valueLabel.Font = 'Microsoft Sans Serif,12'
# Checkbox for ID attribute
$fileId = New-Object System.Windows.Forms.CheckBox
$fileId.text = "Id"
$fileId.AutoSize = $true
$fileId.width = 104
$fileId.height = 20
$fileId.location = New-Object System.Drawing.Point(100,200)
$fileId.Font = 'Microsoft Sans Serif,10'
# Label for the ID checkbox
$idValue = New-Object system.Windows.Forms.TextBox
$idValue.multiline = $false
$idValue.width = 300
$idValue.height = 20
$idValue.location = New-Object System.Drawing.Point(202,200)
$idValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for Description attribute
$description = New-Object System.Windows.Forms.CheckBox
$description.text = "Description"
$description.AutoSize = $true
$description.width = 104
$description.height = 20
$description.location = New-Object System.Drawing.Point(100,250)
$description.Font = 'Microsoft Sans Serif,10'
# Label for the Description checkbox
$descriptionValue = New-Object system.Windows.Forms.TextBox
$descriptionValue.multiline = $false
$descriptionValue.width = 300
$descriptionValue.height = 20
$descriptionValue.location = New-Object System.Drawing.Point(202,250)
$descriptionValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for Type attribute
$type = New-Object System.Windows.Forms.CheckBox
$type.text = "Type"
$type.AutoSize = $true
$type.width = 104
$type.height = 20
$type.location = New-Object System.Drawing.Point(100,300)
$type.Font = 'Microsoft Sans Serif,10'
# Label for the type checkbox
$typeValue = New-Object system.Windows.Forms.TextBox
$typeValue.multiline = $false
$typeValue.width = 300
$typeValue.height = 20
$typeValue.location = New-Object System.Drawing.Point(202,300)
$typeValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for silo attribute
$silo = New-Object System.Windows.Forms.CheckBox
$silo.text = "Silo"
$silo.AutoSize = $true
$silo.width = 104
$silo.height = 20
$silo.location = New-Object System.Drawing.Point(100,350)
$silo.Font = 'Microsoft Sans Serif,10'
# Label for the silo checkbox
$siloValue = New-Object system.Windows.Forms.TextBox
$siloValue.multiline = $false
$siloValue.width = 300
$siloValue.height = 20
$siloValue.location = New-Object System.Drawing.Point(202,350)
$siloValue.Font = 'Microsoft Sans Serif,10'
# submitt button
$button = New-Object System.Windows.Forms.Button
$button.text = "Submit"
$button.AutoSize = $true
$button.location = New-Object System.Drawing.Point(250,500)
$button.Font = 'Microsoft Sans Serif,10'
$Form.controls.AddRange(@($mainLabel, $fileId,$filePath,$idLabel,$valueLabel,$FilePathLabel,$idValue,$descriptionValue,$description, $type, $typeValue, $silo, $siloValue, $button))
#region gui events {
function SubmitForm(){
if($fileId.checked -eq $true){
sc -path $filePath.Text -stream $fileId.text -value $idValue.Text
}
if($description.checked -eq $true){
sc -path $filePath.Text -stream $description.text -value $descriptionValue.text
}
if($type.checked -eq $true){
sc -path $filePath.Text -stream $type.text -value $typeValue.text
}
if($silo.checked -eq $true){
sc -path $filePath.Text -stream $silo.text -value $siloValue.text
}
[System.Windows.Forms.MessageBox]::Show("Successfully Added Attributes")
}
#Add Button event
$Button.Add_Click({SubmitForm})
#endregion events }
#endregion GUI }
# logic here
[void]$Form.ShowDialog()
Currently the user would have to actually run the powershell script from the root folder and then add the file path to the text input the GUI, along with the rest of the extended attributes. An example of what I currently have is below:
I would like the user to be able to right click on any file and have the form come up with the path of the file that was right clicked in windows explorer, instead of the path being manually entered by the individual making the updates to the alternate data streams. Something similar as how you would extract a file using zip7 (example below).
Can someone tell me if this is even possible? Should I be trying to tackle this problem in another language than using powershell?
You can do all this with Powershell.
First you want to create a script from your code and make input parameter for chosen folder. Like so:
param($FileName)
<#
This script is a GUI featured way to add extended attributes to files
#>
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
#region begin GUI{
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '600,600'
$Form.text = "Add Extended Attributes"
$Form.TopMost = $false
# Add Extended Attributes Label
$mainLabel = New-Object system.Windows.Forms.Label
$mainLabel.text = "Add Extended Attributes"
$mainLabel.AutoSize = $true
$mainLabel.width = 25
$mainLabel.height = 10
$mainLabel.location = New-Object System.Drawing.Point(180,10)
$mainLabel.Font = 'Microsoft Sans Serif,18'
# text box for entering file path
$filePath = New-Object system.Windows.Forms.TextBox
$filePath.multiline = $false
$filePath.width = 300
$filePath.height = 20
$filePath.location = New-Object System.Drawing.Point(200,80)
$filePath.Font = 'Microsoft Sans Serif,10'
$filePath.Text = $FileName
# label for the file path text box "File Path: "
$FilePathLabel = New-Object system.Windows.Forms.Label
$FilePathLabel.text = "File Path: "
$FilePathLabel.AutoSize = $true
$FilePathLabel.width = 25
$FilePathLabel.height = 10
$FilePathLabel.location = New-Object System.Drawing.Point(80,85)
$FilePathLabel.Font = 'Microsoft Sans Serif,10'
# Attributes Label
$idLabel = New-Object system.Windows.Forms.Label
$idLabel.text = "Attributes"
$idLabel.AutoSize = $true
$idLabel.width = 25
$idLabel.height = 10
$idLabel.location = New-Object System.Drawing.Point(80,150)
$idLabel.Font = 'Microsoft Sans Serif,12'
# Values Label
$valueLabel = New-Object system.Windows.Forms.Label
$valueLabel.text = "Value"
$valueLabel.AutoSize = $true
$valueLabel.width = 25
$valueLabel.height = 10
$valueLabel.location = New-Object System.Drawing.Point(300,150)
$valueLabel.Font = 'Microsoft Sans Serif,12'
# Checkbox for ID attribute
$fileId = New-Object System.Windows.Forms.CheckBox
$fileId.text = "Id"
$fileId.AutoSize = $true
$fileId.width = 104
$fileId.height = 20
$fileId.location = New-Object System.Drawing.Point(100,200)
$fileId.Font = 'Microsoft Sans Serif,10'
# Label for the ID checkbox
$idValue = New-Object system.Windows.Forms.TextBox
$idValue.multiline = $false
$idValue.width = 300
$idValue.height = 20
$idValue.location = New-Object System.Drawing.Point(202,200)
$idValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for Description attribute
$description = New-Object System.Windows.Forms.CheckBox
$description.text = "Description"
$description.AutoSize = $true
$description.width = 104
$description.height = 20
$description.location = New-Object System.Drawing.Point(100,250)
$description.Font = 'Microsoft Sans Serif,10'
# Label for the Description checkbox
$descriptionValue = New-Object system.Windows.Forms.TextBox
$descriptionValue.multiline = $false
$descriptionValue.width = 300
$descriptionValue.height = 20
$descriptionValue.location = New-Object System.Drawing.Point(202,250)
$descriptionValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for Type attribute
$type = New-Object System.Windows.Forms.CheckBox
$type.text = "Type"
$type.AutoSize = $true
$type.width = 104
$type.height = 20
$type.location = New-Object System.Drawing.Point(100,300)
$type.Font = 'Microsoft Sans Serif,10'
# Label for the type checkbox
$typeValue = New-Object system.Windows.Forms.TextBox
$typeValue.multiline = $false
$typeValue.width = 300
$typeValue.height = 20
$typeValue.location = New-Object System.Drawing.Point(202,300)
$typeValue.Font = 'Microsoft Sans Serif,10'
# Checkbox for silo attribute
$silo = New-Object System.Windows.Forms.CheckBox
$silo.text = "Silo"
$silo.AutoSize = $true
$silo.width = 104
$silo.height = 20
$silo.location = New-Object System.Drawing.Point(100,350)
$silo.Font = 'Microsoft Sans Serif,10'
# Label for the silo checkbox
$siloValue = New-Object system.Windows.Forms.TextBox
$siloValue.multiline = $false
$siloValue.width = 300
$siloValue.height = 20
$siloValue.location = New-Object System.Drawing.Point(202,350)
$siloValue.Font = 'Microsoft Sans Serif,10'
# submitt button
$button = New-Object System.Windows.Forms.Button
$button.text = "Submit"
$button.AutoSize = $true
$button.location = New-Object System.Drawing.Point(250,500)
$button.Font = 'Microsoft Sans Serif,10'
$Form.controls.AddRange(@($mainLabel, $fileId,$filePath,$idLabel,$valueLabel,$FilePathLabel,$idValue,$descriptionValue,$description, $type, $typeValue, $silo, $siloValue, $button))
#region gui events {
function SubmitForm(){
if($fileId.checked -eq $true){
sc -path $filePath.Text -stream $fileId.text -value $idValue.Text
}
if($description.checked -eq $true){
sc -path $filePath.Text -stream $description.text -value $descriptionValue.text
}
if($type.checked -eq $true){
sc -path $filePath.Text -stream $type.text -value $typeValue.text
}
if($silo.checked -eq $true){
sc -path $filePath.Text -stream $silo.text -value $siloValue.text
}
[System.Windows.Forms.MessageBox]::Show("Successfully Added Attributes")
}
#Add Button event
$Button.Add_Click({SubmitForm})
#endregion events }
#endregion GUI }
# logic here
[void]$Form.ShowDialog()
Next you would need to create registry reference for context menu item and powershell script according to it. Like so:
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
New-Item HKCR:\directory\shell\PowerShellScript
New-Item HKCR:\directory\shell\PowerShellScript\command
Set-ItemProperty 'HKCR:\directory\shell\PowerShellScript\command' -Name '(default)' -Value 'Powershell -WindowStyle Hidden -ExecutionPolicy Bypass -NoExit -File "C:\Test.ps1" "%L"'
Context menu item:
Chosen directory passed to script's input parameter: