Pass parameter to powershell from a windows form file browser - windows

I am trying to pass a parmeter from a windows form dialogue serach box to another script, but cant seem to pull the parameter out from when a user chooses a file. the parameter should be the full file location of a font which a user would like to install. any help would be appreciated, the below script is the forma and the script the parameter needs to go throuh is at the bottom.
cls
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#Windows form settings
$objForm = New-Object System.Windows.Forms.Form
$objForm.Icon = $Icon
$objForm.Text = "Font Installer"
$objForm.Size = New-Object System.Drawing.Size(350,350)
$objForm.StartPosition = "CenterScreen"
$objForm.FormBorderStyle = "FixedDialog"
$objForm.BackgroundImage = $Image
$objForm.BackgroundImageLayout = "None"
#Browse for file
$d = New-Object Windows.Forms.OpenFileDialog
$d.initialDirectory = $initialDirectory
$d.filter = "All files (*.*)| *.*"
$d.ShowHelp = $true
$d.InitialDirectory = "c:\"
$d.Title = "Choose your Font"
$d.FileName
$d.filter = " Font Files (*.ttf; *.fon; *.fnt; *.ttc; *.otf; *.mmm; *.pbf; *.pfm)| *.ttf; *.fon; *.fnt; *.ttc; *.otf; *.mmm; *.pbf; *.pfm"
#Browse Button
$button1 = New-Object system.Windows.Forms.Button
$button1.Text = "Select Font"
$button1.Add_Click({$d.ShowDialog( )})
$button1.Location = New-Object System.Drawing.Size(100,120)
$button1.Size = New-Object System.Drawing.Size(150,23)
$objForm.controls.add($button1)
#Install Button
$run = New-Object System.Windows.Forms.Button
$run.Location = New-Object System.Drawing.Size(100,170)
$run.Size = New-Object System.Drawing.Size(150,100)
$run.Text = "Install"
$Font1 = New-Object System.Drawing.Font("Arial Black",19, [System.Drawing.FontStyle]::regular)
$run.Font = $Font1
$run.BackColor ="green"
#invoke expression - open install script and sent the parameter to it
$run.Add_Click({
Invoke-Expression "& `"c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1`" $d.filename";
})
$objForm.Controls.Add($run)
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
the script which should get the parameter is named testparam.ps1 and code is below:
param(
[string] $path = ""
)
Write-Host "this is a test the parameter is $path"

Try changing the Add handler to:
$run.Add_Click({
if($d.filename)
{
$path = $d.filename
c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1 "'$path'"
}
})

try just this:
$run.Add_Click({ c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1 $($d.filename);})

Related

How to make a Windows toast notification have a button that launches another Powershell script

I have this function in Powershell that shows a toast notification in Windows 10.
What I want is to make the toast notification have a button that when clicked runs another Powershell function passing to it that $GenericParameter.
function Send-Preference-Changed-Toast {
Param([Parameter()]$GenericParameter)
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
$Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
$RawXml = [xml] $Template.GetXml()
($RawXml.toast.visual.binding.text|Where-Object {$_.id -eq "1"}).AppendChild($RawXml.CreateTextNode("setting changed")) > $null
($RawXml.toast.visual.binding.text|Where-Object {$_.id -eq "2"}).AppendChild($RawXml.CreateTextNode("Restart for the change to take effect")) > $null
# Add on click behavior to call another Powershell function
$SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument
$SerializedXml.LoadXml($RawXml.OuterXml)
$Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml)
$Toast.Tag = "Task Scheduler"
$Toast.Group = "Task Scheduler"
$Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)
$Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Task Scheduler")
$Notifier.Show($Toast);
}
Is it possible to do so? If yes, how? If not, what other alternatives do I have?

Oracle update statement using PowerShell

I'm trying to run a simple Oracle UPDATE statement using powershell and OracleDataAdapter.
I got stuck in the execution part..
please advise on how to proceed from here...
$userName1="user1"
$password1="password1"
$Server1="(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_exm)(PORT=1234)))(CONNECT_DATA=(SERVICE_NAME=exmp)))"
#configure path to installation path of oracle client:
$AssemblyFile = "D:\app\client\product\12.1.0\client_1\ODP.NET\bin\4\Oracle.DataAccess.dll"
$ConnectionString = "User ID=$userName1;Password=$password1;Data Source=$Server1;Persist Security Info=True"
Write-Output "ConnectionString: $ConnectionString">> $LogFile
$CommandText = "UPDATE TEST SET id =333 WHERE ID = 3;"
Write-Output $CommandText
[Reflection.Assembly]::LoadFile($AssemblyFile) | Out-Null
$OracleConnection = New-Object -TypeName Oracle.DataAccess.Client.OracleConnection
$OracleConnection.ConnectionString = $ConnectionString
$OracleConnection.Open()
$OracleCommand = New-Object -TypeName Oracle.DataAccess.Client.OracleCommand
$OracleCommand1 = New-Object -TypeName Oracle.DataAccess.Client.OracleCommand
$OracleCommand.CommandText = $CommandText
$OracleCommand.Connection = $OracleConnection
$OracleDataAdapter = New-Object -TypeName Oracle.DataAccess.Client.OracleDataAdapter
$OracleDataAdapter.UpdateCommand = $OracleCommand
# How do I execute?
$OracleDataAdapter.Dispose()
$OracleCommand.Dispose()
$OracleConnection.Close()

powershell script creates Windows 10 notification and it disappears after popup

the following powershell script successfully creates a notification but after the little popup retracts it doesn't show on the Notification Center, any way to leave it in the notification center until the user dismisses it ?
param([String]$prodName)
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] > $null
$ToastTemplate = '
<toast launch="app-defined-string">
<visual>
<binding template="ToastGeneric">
<text>'+$prodName+'</text>
</binding>
</visual>
</toast>'
Write-Output $ToastTemplate;
$currTime = (Get-Date).AddSeconds(10);
"currTime : " + $currTime
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
$xml.LoadXml($toastXml.OuterXml)
$schedNotification = New-Object Windows.UI.Notifications.ToastNotification($xml)
$schedNotification.SuppressPopup = $True
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($prodName)
$notifier.Show($schedNotification)
$schedNotification = New-Object Windows.UI.Notifications.ScheduledToastNotification($xml, $currTime)
$notifier.AddToSchedule($schedNotification)
If you show your notification like this:
CreateToastNotifier("PowerShellAppId")
Then in your "Settings \ System \ Notifications & Actions", there should register new app named "PowerShellAppId".
Edit it, and select option "Show notifications in action center". If you run your script again, message should leave in notification panel.
In your example you have $prodName as AppID. So each time, you run script with different prodName, Windows will register it as separate entry, and you will have to set registry flag ("Show notifications in action center") again.
You can do it using PowerShell like this:
Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\$prodName" -Name "ShowInActionCenter" -Type Dword -Value "1"
Consider using constant app name, something like NotificationManager to simplify things.

which class or method to use from windows forms namespace to show the name of running script using powershell in a form class

I have a powershell script which calls for a progress bar in a form showing execution of some batch files. Which class or method should be used from windows forms namespace to show the name of running batch script using powershell in a form class.
In the code below, in installationScriptsHome folder there are bunch of batch and vbs files, while those scripts are being called i want to show the name of the running script over the progress bar to show which script is running or may be some customised name\message with each script.
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$ScriptsHome = Get-Item 'c:\installationScriptsHome\*'
# Init Form
$Form = New-Object System.Windows.Forms.Form
$Form.width = 1000
$Form.height = 200
$Form.Text = "**OSP Installation in Progress**"
# Init ProgressBar
$ProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProgressBar.Maximum = $ScriptsHome.Count
$ProgressBar.Minimum = 0
$ProgressBar.Location = new-object System.Drawing.Size(10,70)
$ProgressBar.size = new-object System.Drawing.Size(967,10)
$Form.Controls.Add($ProgressBar)
# Add_Shown action
$ShownFormAction = {
$Form.Activate()
foreach ($b in $ScriptsHome) {
$ProgressBar.Increment(1)
Start-Process $b.FullName -Wait -WindowStyle Hidden
}
$Form.Dispose()
}
$Form.Add_Shown($ShownFormAction)
# Show Form
$Form.ShowDialog()
Thanks in advance.
Use the Label class (MSDN page).
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Point(140,20)
$Label.Size = New-Object System.Drawing.Size(280,20)
# put this in the foreach ($b in $ScriptsHome) { loop
$Label.Text = "$($b.Name)"
Useful link: MSDN System.Windows.Forms NameSpace

How can I present the user with a list of printers to choose from in my PowerShell Script?

I'm making a script which assists the end user with printer problems. At one point, the user needs to be able to select from a list of printers on the network to decide which one needs maintenance. I'm trying to integrate this via a list box, but I haven't quite been able to get it to function. Here is the script as it stands (It currently uses read-host to allow the user to type in a printer name.)
net stop spooler
Remove-Item C:\Windows\System32\spool\PRINTERS\* -Force
net start spooler
get-printer
$PrinterName = Read-Host 'Please Type In The Name Of The Printer Above That You Are Having Problems With'
$PrinterInstance = [wmi]"\\.\root\cimv2:Win32_Printer.DeviceID='$PrinterName'"
try{
$PrinterInstance.PrintTestPage()
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("I found a problem that I was able to fix. Please try to print again.",0,"Printer Helper",0x1)
}
catch
{
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("Printer Fixer can not solve your problem, please enter a new ticket.",0,"Printer Helper",0x1)
}
Here is the "list box" code that I want to implement.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a Computer"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$x=$objListBox.SelectedItem;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$objForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$objListBox.SelectedItem;$objForm.Close()})
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please select a computer:"
$objForm.Controls.Add($objLabel)
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(260,20)
$objListBox.Height = 80
[void] $objListBox.Items.Add("atl-dc-001")
[void] $objListBox.Items.Add("atl-dc-002")
[void] $objListBox.Items.Add("atl-dc-003")
[void] $objListBox.Items.Add("atl-dc-004")
[void] $objListBox.Items.Add("atl-dc-005")
[void] $objListBox.Items.Add("atl-dc-006")
[void] $objListBox.Items.Add("atl-dc-007")
$objForm.Controls.Add($objListBox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
I tried replacing the hard coded values with $objListBox.Items.Add(Get-WMIObject -Class Win32_Printer | Select Name | ft -auto)
but wmi.object[] is all that appears in the list box. What am I doing wrong?
Using forms is very heavy-handed for something like this.
My recommendation is to use Out-GridView.
It provides a sortable, searchable, filterable list in a pop-up window. But it also lets the user select one or more items and those become the output of the cmdlet.
$printerSelection = $printerList | Out-GridView -OutputMode Single

Resources