powershellalternate-data-stream

Run GUI powershell script by right clicking on a file


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:

enter image description here

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).

enter image description here

Can someone tell me if this is even possible? Should I be trying to tackle this problem in another language than using powershell?


Solution

  • 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:

    enter image description here

    Chosen directory passed to script's input parameter:

    enter image description here