Passing on variable to invoke-item - powershell

Looking for a solution. I have simple script that will browse to specific directory on network pc's.
However I'm not sure how to pass on $compname variable to invoke-item.
I'm running PS v2.0. With current script I'm getting error: Invoke-Item : Cannot find path '\\C$\Program Files\IBM\Lotus\Notes\Data' because it does not exist.
$dskbox = New-Object system.windows.Forms.TextBox
$dskbox.Width = 134
$dskbox.Height = 20
$dskbox.location = new-object system.drawing.point(24,41)
$dskbox.Font = "Microsoft Sans Serif,10,style=Bold"
$Title.controls.Add($dskbox)
$compname = $dskbox.Text
$Open = New-Object system.windows.Forms.Button
$Open.BackColor = "#23b14d"
$Open.Text = "Open"
$Open.ForeColor = "#ffffff"
$Open.Width = 163
$Open.Height = 51
$Open.location = new-object system.drawing.point(6,77)
$Open.Font = "Microsoft Sans Serif,10,style=Bold"
$Title.controls.Add($Open)
$Open.Add_Click({
ii "\\$compname\C$\Program Files\IBM\Lotus\Notes\Data"
})
[void]$Title.ShowDialog()
$Title.Dispose()

You set $compname when creating the textbox, which is obviously going to be empty at that point in time. You need to move it into the scriptblock:
$Open.Add_Click({
$compname = $dskbox.Text
ii "\\$compname\C$\Program Files\IBM\Lotus\Notes\Data"
})
Or you could just get rid of that variable entirely: ii "\\$($dskbox.Text)\C$\Program Files\IBM\Lotus\Notes\Data"

You can associate your $Open.add_Click($Open_OnClick) to a scriptblock and start invoke-item inside the scriptblock.
$dskbox = New-Object system.windows.Forms.TextBox
$dskbox.Width = 134
$dskbox.Height = 20
$dskbox.location = new-object system.drawing.point(24,41)
$dskbox.Font = "Microsoft Sans Serif,10,style=Bold"
$Title.controls.Add($dskbox)
$compname = $dskbox.Text
$Open = New-Object system.windows.Forms.Button
$Open.BackColor = "#23b14d"
$Open.Text = "Open"
$Open.ForeColor = "#ffffff"
$Open.Width = 163
$Open.Height = 51
$Open.location = new-object system.drawing.point(6,77)
$Open.Font = "Microsoft Sans Serif,10,style=Bold"
$Open.add_Click($Open_OnClick)
$Title.controls.Add($Open)
$Open_OnClick=
{
ii "\\$compname\C$\Program Files\IBM\Lotus\Notes\Data"
}
[void]$Title.ShowDialog()
$Title.Dispose()

Related

How can I uninstall Hotfix remotely with Powershell

This what I have so far it brings up a Syntax screen for wusa. I have confirmed that the Trim is working. If I leave out the remote computer name is works on the local computer. I will be adding this to a much larger script just trying to get this working before trying to add it.
<#
.NAME
Template
#>
$comp = "Remote Pc Name Goes Here"
$str = $Hotfix_TextBox.Text. Trim("K","B")
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(400,400)
$Form.text = "Form"
$Form.TopMost = $false
$gethotfix = New-Object system.Windows.Forms.Button
$gethotfix.text = "Get Hotfixes"
$gethotfix.width = 120
$gethotfix.height = 30
$gethotfix.location = New-Object System.Drawing.Point(100,81)
$gethotfix.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$removehotfix = New-Object system.Windows.Forms.Button
$removehotfix.text = "Remove Hotfix"
$removehotfix.width = 120
$removehotfix.height = 30
$removehotfix.location = New-Object System.Drawing.Point(100,120)
$removehotfix.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$Hotfix_TextBox = New-Object system.Windows.Forms.TextBox
$Hotfix_TextBox.Text = ""
$Hotfix_TextBox.multiline = $false
$Hotfix_TextBox.width = 174
$Hotfix_TextBox.height = 20
$Hotfix_TextBox.location = New-Object System.Drawing.Point(12,235)
$Hotfix_TextBox.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
<#
$Trimmed_TextBox = New-Object system.Windows.Forms.TextBox
#$Trimmed_TextBox.Text = "$str"
$Trimmed_TextBox.multiline = $false
$Trimmed_TextBox.width = 174
$Trimmed_TextBox.height = 20
$Trimmed_TextBox.location = New-Object System.Drawing.Point(12,265)
$Trimmed_TextBox.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
#>
$Form.controls.AddRange(#($gethotfix,$removehotfix,$Hotfix_TextBox))
$gethotfix.Add_Click({ GetHotfix })
$removehotfix.Add_Click({ RemoveHotfix })
#region Logic
function GetHotfix {$Hotfix_TextBox.Text = Get-Hotfix -Computername $comp |
Select-Object -ExpandProperty 'HotFixID'|
Out-GridView -Title 'Installed Hotfixes' -PassThru }
#$Hotfix_TextBox.Text. Trim("K","B")
#$Hotfix_TextBox.Text = "$str"
function RemoveHotfix{
#$Trimmed_TextBox.Text = "$str"
$comp = "dus-xtdfed9r386"
#Uninstall-HotFix -ComputerName $comp
wusa -computername /$comp | /uninstall | /kb:$str
}
#endregion
[void]$Form.ShowDialog()
This turned out to be a fiasco. Even when I could get it to work there are many KBs that cannot be removed, as well as we had policies that would not allow us to remove many others. Just not worth the effort. Perhaps someone with less strengent policies in place can do something with this. Have Fun.

Powershell GUI Issues

I know the code I have isn't quite correct in terms of the loop, at the ,moment, once I click the start button, thew window freezes and the form/buttons do not respond to any input, which I know is due to the infinite do while loop. This is my first Powershell GUI script and I have tried to find answers but so far unsuccessful.
I want the code to keep running in the form but allow the form to be movable and the stop button t close the GUI/script.
Here is an example of the code:
Set-ExecutionPolicy unrestricted
Add-Type -assembly System.Windows.Forms
#Form + Properties
$main_form = New-Object System.Windows.Forms.Form
$main_form.TopMost = $True
$main_form.Text ='Techs'
$main_form.Width = 300
$main_form.Height = 450
$main_form.AutoSize = $true
#Textbox1 + Properties
$TextBox1 = New-Object system.Windows.Forms.TextBox
$TextBox1.BackColor = "Black"
$TextBox1.multiline = $true
$TextBox1.width = 295
$TextBox1.height = 195
$TextBox1.location = New-Object System.Drawing.Point(05,30)
$TextBox1.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($Textbox1)
#Textbox2 + Properties
$TextBox2 = New-Object system.Windows.Forms.TextBox
$TextBox2.BackColor = "Black"
$TextBox2.multiline = $true
$TextBox2.width = 295
$TextBox2.height = 195
$TextBox2.location = New-Object System.Drawing.Point(05,225)
$TextBox2.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($Textbox2)
#Start Button + Properties
$buttonStart = New-Object system.Windows.Forms.Button
$buttonStart.text = "Start"
$buttonStart.Size = '80,20'
$buttonStart.location = '05, 05'
$buttonStart.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($buttonStart)
#Stop Button + Properties
$buttonStop = New-Object system.Windows.Forms.Button
$buttonStop.text = "Stop"
$buttonStop.Size = '80,20'
$buttonStop.location = '90, 05'
$buttonStop.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($buttonStop)
cls
$x=1
$TechArray = "1","2","3","4","5","6","7","8","9","10"
$url = "https://website/api/v3/techs/"
$tech_key = #{ 'authtoken' = '12345678-12AB-12AB-1111-1111'}
$buttonStart.Add_Click({
Do {
$TextBox1.Text=""
$TextBox2.Text=""
foreach ($Tech in $TechArray) {
$response = Invoke-RestMethod -Uri $url$Tech -Method get -Headers $tech_Key
if ($response.tech.is_online -eq "1")
{
$TextBox1.ForeColor = "Green"
$TextBox1.AppendText("`n`n Online - " + $response.tech.login_name + "`n`n")
}
else
{
$TextBox2.ForeColor = "Red"
$TextBox2.AppendText("`n`n Offline - " + $response.tech.login_name + "`n`n")
}
}
Start-Sleep -Seconds 5
}
while ($x -ne 0)
})
$main_form.ShowDialog()
You need to separate the fetching of the web call from your UI thread.
This means you need to create a separate thread to execute this as a background task.
In Powershell (Core) 7+ there is this cmdLet: Start-ThreadJob, but there is also a port of this in Powershell 5.1, which you can download from:
https://www.powershellgallery.com/packages/ThreadJob/2.0.3
As a sample proof of concept instead of this, which blocks the UI thread:
$buttonStart.Add_Click({
Write-Host "Hi"
Start-Sleep -Seconds 5
}
Try this one and you'll see that the window does not freeze anymore:
$buttonStart.Add_Click({
Start-ThreadJob -StreamingHost $Host -ScriptBlock {
Write-Host "Hi"
Start-Sleep -Seconds 5
}
})

Issue to create a dynamic Powershell Form, showing output data from the running the script

I have a question about a Powershell Form script that I can't quite get to work yet.
The code below does give the output I expect, but I can't manage to display the Form as it was during the initialization of 'establishing the connection'. The point is that we only want to start a program when there is connectivity with the router and the end user should also be able to see it that way, not just the end result.
Can anyone point me in the right direction to make the form dynamically show what's happening at the time when the script is running?
Ow, and also the 'Retry' ([System.Windows.Forms.DialogResult]::Retry)function does not do anything as expected... :(
#---------------------------------------------------------[Initialisations]--------------------------------------------------------
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#---------------------------------------------------------[Form]--------------------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$LocalRCForm = New-Object system.Windows.Forms.Form
$LocalRCForm.ClientSize = '480,300'
$LocalRCForm.text = "Status router connection"
$LocalRCForm.BackColor = "#F9F9F9"
$LocalRCForm.StartPosition = "CenterScreen"
$LocalRCForm.TopMost = $true
$LocalRCForm.SuspendLayout()
$Titel = New-Object system.Windows.Forms.Label
$Titel.text = "Status router connection"
$Titel.AutoSize = $true
$Titel.width = 25
$Titel.height = 10
$Titel.location = New-Object System.Drawing.Point(20,20)
$Titel.Font = 'Microsoft Sans Serif,14,style=Bold'
$Description = New-Object system.Windows.Forms.Label
$Description.text = "To start Security Desk, wait for an established connection"
$Description.AutoSize = $false
$Description.width = 450
$Description.height = 50
$Description.location = New-Object System.Drawing.Point(20,60)
$Description.Font = 'Microsoft Sans Serif,10'
$RCStatus = New-Object system.Windows.Forms.Label
$RCStatus.text = "Status:"
$RCStatus.AutoSize = $true
$RCStatus.width = 25
$RCStatus.height = 10
$RCStatus.location = New-Object System.Drawing.Point(20,115)
$RCStatus.Font = 'Microsoft Sans Serif,10,style=Bold'
$RCFound = New-Object system.Windows.Forms.Label
$RCFound.text = "Connecting to router..."
$RCFound.AutoSize = $true
$RCFound.width = 25
$RCFound.height = 10
$RCFound.location = New-Object System.Drawing.Point(100,115)
$RCFound.Font = 'Microsoft Sans Serif,10'
$RCDetails = New-Object system.Windows.Forms.Label
$RCDetails.text = "Router succesfully connected"
$RCDetails.AutoSize = $true
$RCDetails.width = 25
$RCDetails.height = 10
$RCDetails.location = New-Object System.Drawing.Point(20,150)
$RCDetails.Font = 'Microsoft Sans Serif,10,style=Bold'
$RCTestConnection = New-Object system.Windows.Forms.Label
$RCTestConnection.text = "Checking connection"
$RCTestConnection.AutoSize =
$RCTestConnection.width = 25
$RCTestConnection.height = 10
$RCTestConnection.location = New-Object System.Drawing.Point(100,115)
$RCTestConnection.Font = 'Microsoft Sans Serif,10'
$AddRCBtn = New-Object system.Windows.Forms.Button
$AddRCBtn.BackColor = "#ff7b00"
$AddRCBtn.text = "Ok"
$AddRCBtn.width = 150
$AddRCBtn.height = 30
$AddRCBtn.location = New-Object System.Drawing.Point(300,250)
$AddRCBtn.Font = 'Microsoft Sans Serif,10'
$AddRCBtn.ForeColor = "#000"
$AddRCBtn.DialogResult = [System.Windows.Forms.DialogResult]::Yes
$CloseBtn = New-Object system.Windows.Forms.Button
$CloseBtn.BackColor = "#ffffff"
$CloseBtn.text = "Close"
$CloseBtn.width = 90
$CloseBtn.height = 30
$CloseBtn.location = New-Object System.Drawing.Point(300,250)
$CloseBtn.Font = 'Microsoft Sans Serif,10'
$CloseBtn.ForeColor = "#000"
$CloseBtn.DialogResult = [System.Windows.Forms.DialogResult]::Retry
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$testConnection))
#-----------------------------------------------------------[Functions]------------------------------------------------------------
function AddRC {
$RCFound.ForeColor = "#000000"
$RCFound.Text = 'Connected to Router'
}
#---------------------------------------------------------[Script]--------------------------------------------------------
# Check if router is online
$routerIp = '1.1.1.1'
$testConnection = Test-Connection $routerIp
If ($testConnection) {
$RCFound.text = "Router Ready"
$RCFound.ForeColor = "#7ed321"
$AddRCBtn.text = "Run the program"
$CloseBtn.Visible = $false
$RCDetails.Visible = $true
}else{
$RCFound.text = "Router not found"
$RCFound.ForeColor = "#D0021B"
$CloseBtn.text = "Close"
$AddRCBtn.Visible = $false
$RCDetails.Visible = $false
}
$AddRCBtn.Add_Click({ AddRC })
$LocalRCForm.Add_Shown({$testConnection.Enabled = $true; $testConnection.Start()})
return $LocalRCForm.ShowDialog()
There is too much to say about your script so let's focus on your main issue:
Your script will only show the form once the connection is tested, so the form will never display the various steps.
To achieve your goal, you should put your main code in a function and run it once the form is displayed.
function funTestConnection {
$testConnection = Test-Connection $routerIp
If($testConnection) {
$RCFound.text = "Router Ready"
$RCFound.ForeColor = "#7ed321"
$AddRCBtn.text = "Run the program"
$CloseBtn.Visible = $false
$RCDetails.Visible = $true
} else {
$RCFound.text = "Router not found"
$RCFound.ForeColor = "#D0021B"
$CloseBtn.text = "Close"
$AddRCBtn.Visible = $false
$RCDetails.Visible = $false
}
}
Also, you are trying to add a control in your form that is not a control ($testConnection). I suppose you wanted to add $RCTestConnection instead (and don't forget to take care of it's position).
# Change this line:
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$testConnection))
# To this line:
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$RCTestConnection))
Again, you use the variable $testConnection but it neither have a property enabled or a method Start(). So this line makes no sense and after having put your main code in a function, it should be replaced as follow:
# Replace this line that has no meaning
$LocalRCForm.Add_Shown({$testConnection.Enabled = $true; $testConnection.Start()})
# By this line
$LocalRCForm.Add_Shown({funTestConnection})
About retrying if not connected, [System.Windows.Forms.DialogResult]::Retry is not a function, it's a constant value so you can't expect it to do anything.
For it to be taken into account, you should use it in a way or the other.
One example would be like this:
# This code
do { $returnDialog = $LocalRCForm.ShowDialog() }
while($returnDialog -eq [System.Windows.Forms.DialogResult]::Retry)
# instead of this line
return $LocalRCForm.ShowDialog()
Finally, your function AddRC has no real impact as the form is closed when it's called (just a remark).
With all that said, you will have a functional script but it needs quite some adjustments related to what messages and information are displayed during the process (button names, labels, etc.) but at least it should do what you're expecting.

Why OpenFileDialog found if execute from ISE but not from cmd?

I have an GUI, I want to open a folder and select a file. When I execute my code from ISE, it works. but when I run from another environment with cmd, it shows some error
Exception calling "ShowDialog" with "0" arguument(S): "Creating an instance of the COM component with CLSID.....
Function Sel_File
{
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = "P:\Temp\MM"
$OpenFileDialog.Title = "Please Select File"
$OpenFileDialog.filter = “All files (*.*)| *.*”
If ($OpenFileDialog.ShowDialog() -eq "Cancel")
{
[System.Windows.Forms.MessageBox]::Show("No File Selected. Please select a file !", "Error", 0,
[System.Windows.Forms.MessageBoxIcon]::Exclamation)
} $Global:SelectedFile = $OpenFileDialog.SafeFileName
}
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.AutoSize = $true
$Form.text = "Auto GM Creation"
$Form.TopMost = $true
#----------------------
$ChooseML_L = New-Object system.Windows.Forms.Label
$ChooseML_L.text = "MLs"
$ChooseML_L.AutoSize = $true
$ChooseML_L.width = 25
$ChooseML_L.height = 10
$ChooseML_L.location = New-Object System.Drawing.Point(28,20)
$ChooseML_L.ForeColor = "#000000"
$SelectML = New-Object system.Windows.Forms.TextBox
$SelectML.AutoSize = $true
$SelectML.width = 150
$SelectML.height = 30
$SelectML.location = New-Object System.Drawing.Point(120,40)
$SelectML.Text = "Selected ML"
$ChooseML = New-Object System.Windows.Forms.Button
$ChooseML.text = "Select File"
$ChooseML.AutoSize = $true
$ChooseML.width = 90
$ChooseML.height = 20
$ChooseML.location = New-Object System.Drawing.Point(28,38)
$ChooseML.ForeColor = "#ffffff"
$ChooseML.BackColor = "#093c76"
$ChooseML.Add_Click({Sel_File
$SelectML.Text = $Global:SelectedFile
})
#----------
$Apply = New-Object system.Windows.Forms.Button
$Apply.BackColor = "#6996c8"
$Apply.text = "Apply"
$Apply.width = 99
$Apply.height = 30
$Apply.location = New-Object System.Drawing.Point(320,190)
#----------
$Cancel = New-Object system.Windows.Forms.Button
$Cancel.BackColor = "#6996c8"
$Cancel.text = "Cancel"
$Cancel.width = 98
$Cancel.height = 30
$Cancel.location = New-Object System.Drawing.Point(450,190)
$Cancel.Add_Click({$Form.Close()})
#-----------
$Prefix = New-Object system.Windows.Forms.Label
$Prefix.text = "Prefix"
$Prefix.AutoSize = $true
$Prefix.width = 25
$Prefix.height = 10
$Prefix.location = New-Object System.Drawing.Point(28,80)
$Prefix.ForeColor = "#000000"
$NB = New-Object system.Windows.Forms.RadioButton
$NB.text = "NB"
$NB.AutoSize = $true
$NB.BackColor = "#4a90e2"
$NB.width = 104
$NB.height = 20
$NB.location = New-Object System.Drawing.Point(28,100)
$DPC = New-Object system.Windows.Forms.RadioButton
$DPC.text = "DPC"
$DPC.AutoSize = $true
$DPC.BackColor = "#4a90e2"
$DPC.width = 104
$DPC.height = 20
$DPC.location = New-Object System.Drawing.Point(100,100)
$Form.Controls.AddRange(#($ChooseML, $Prefix, $ChooseML_L, $Apply, $Cancel, $SelectML, $NB, $DPC))
[void]$Form.ShowDialog()
This is my code updated. This is working using PS ISE, but I tried execute it from WinPE environment, It shows those error above.
Could anyone help me please. Thank you
this works ... but i think the use of LoadWithPartialName has been deprecated. i can't find the "new way" at this time, tho. [blush]
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") |
Out-Null
$SelectFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$SelectFileDialog.InitialDirectory = 'c:\temp'
$SelectFileDialog.Filter = 'Extensionless files (*)|*'
$SelectFileDialog.Title = 'Please select a file and then click [OK]'
$SelectFileDialog.ShowDialog() |
Out-Null
$SelectFileDialog.FileName
I believe it'll work if you remove | Out-Null from this line
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog | Out-Null
Just need to add this, it works well.
Thank you for all the contribution
$OpenFileDialog.AutoUpgradeEnabled =$false

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