If you have used PowerShell ISE, you might have already noticed that you cannot search across all open script files and across open tabs. This becomes important when you are working with multiple files at the same time. So, this made me write a simple addon using WinForms. Now, before you think that you can do the same in very few lines of WPF — yes, I understand that but I am not yet comfortable with WPF in PowerShell. WinForms is always a winner when it comes to writing simple addons and it is probably the fastest way!
Now, let us look at the code:
$scriptBlock = {
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
$form1 = New-Object System.Windows.Forms.Form
$button3 = New-Object System.Windows.Forms.Button
$dataGridView1 = New-Object System.Windows.Forms.DataGridView
$button1 = New-Object System.Windows.Forms.Button
$textBox1 = New-Object System.Windows.Forms.TextBox
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
$handler_dataGridView1_CellDoubleClick=
{
if ($datagridview1.SelectedRows.Count) {
$row = $dataGridView1.SelectedRows[0]
if ($row.Cells[0].Value) {
$tab = $psISE.PowerShellTabs | ? { $_.DisplayName -eq $row.Cells[3].Value.ToString() }
$psise.PowerShellTabs.SetSelectedPowerShellTab($tab)
$file = $tab.Files | ? { $_.DisplayName -eq $row.Cells[0].Value }
$tab.Files.SetSelectedFile($file)
$file.Editor.SetCaretPosition($row.Cells[1].Value,1)
$file.Editor.SelectCaretLine()
$form1.Close()
}
}
}
$button1_OnClick=
{
$dataGridView1.Rows.Clear()
if ($textBox1.Text.Trim()) {
$pattern = $textBox1.Text
foreach ($tab in $psISE.PowerShellTabs) {
foreach ($file in $tab.Files) {
$result = $file.Editor.Text -split "`n" | Select-String -Pattern $textBox1.Text | Select Linenumber,Line
if ($result) {
if ($result.Count) {
foreach ($res in $result) {
$dataGridView1.Rows.Add($file.DisplayName,$res.LineNumber,$res.Line.Trim(),$tab.DisplayName)
}
} else {
$dataGridView1.Rows.Add($file.DisplayName,$result.LineNumber,$result.Line.Trim(),$tab.DisplayName)
}
}
}
}
} else {
[System.Windows.Forms.MessageBox]::Show("Enter something to search!")
}
}
$OnLoadForm_StateCorrection=
{
$form1.WindowState = $InitialFormWindowState
}
$form1.AcceptButton = $button1
$form1.CancelButton = $button3
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 227
$System_Drawing_Size.Width = 510
$form1.ClientSize = $System_Drawing_Size
$form1.ControlBox = $False
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.MaximizeBox = $False
$form1.MinimizeBox = $False
$form1.Name = "form1"
$form1.ShowIcon = $False
$form1.ShowInTaskbar = $False
$form1.Text = "Advanced ISE Search"
$form1.TopMost = $true
$form1.FormBorderStyle = 'Fixed3D'
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 287
$System_Drawing_Point.Y = 10
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 104
$button3.DataBindings.DefaultDataSourceUpdateMode = 0
$button3.DialogResult = 2
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 410
$System_Drawing_Point.Y = 195
$button3.Location = $System_Drawing_Point
$button3.Name = "button3"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 75
$button3.Size = $System_Drawing_Size
$button3.TabIndex = 5
$button3.Text = "Cancel"
$button3.UseVisualStyleBackColor = $True
$button3.add_Click($button3_OnClick)
$form1.Controls.Add($button3)
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 316
$System_Drawing_Point.Y = 195
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 75
$dataGridView1.AutoSizeColumnsMode = 16
$System_Windows_Forms_DataGridViewTextBoxColumn_1 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$System_Windows_Forms_DataGridViewTextBoxColumn_1.HeaderText = "Script Name"
$System_Windows_Forms_DataGridViewTextBoxColumn_1.Name = ""
$System_Windows_Forms_DataGridViewTextBoxColumn_1.Width = 111
$dataGridView1.Columns.Add($System_Windows_Forms_DataGridViewTextBoxColumn_1)|Out-Null
$System_Windows_Forms_DataGridViewTextBoxColumn_2 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$System_Windows_Forms_DataGridViewTextBoxColumn_2.HeaderText = "Line Number"
$System_Windows_Forms_DataGridViewTextBoxColumn_2.Name = ""
$System_Windows_Forms_DataGridViewTextBoxColumn_2.Width = 111
$dataGridView1.Columns.Add($System_Windows_Forms_DataGridViewTextBoxColumn_2)|Out-Null
$System_Windows_Forms_DataGridViewTextBoxColumn_3 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$System_Windows_Forms_DataGridViewTextBoxColumn_3.HeaderText = "Line"
$System_Windows_Forms_DataGridViewTextBoxColumn_3.Name = ""
$System_Windows_Forms_DataGridViewTextBoxColumn_3.Width = 110
$dataGridView1.Columns.Add($System_Windows_Forms_DataGridViewTextBoxColumn_3)|Out-Null
$System_Windows_Forms_DataGridViewTextBoxColumn_4 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$System_Windows_Forms_DataGridViewTextBoxColumn_4.HeaderText = "Tab Name"
$System_Windows_Forms_DataGridViewTextBoxColumn_4.Name = ""
$System_Windows_Forms_DataGridViewTextBoxColumn_4.Width = 111
$dataGridView1.Columns.Add($System_Windows_Forms_DataGridViewTextBoxColumn_4)|Out-Null
$dataGridView1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 39
$dataGridView1.Location = $System_Drawing_Point
$dataGridView1.Name = "dataGridView1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 150
$System_Drawing_Size.Width = 486
$dataGridView1.Size = $System_Drawing_Size
$dataGridView1.TabIndex = 3
$dataGridView1.SelectionMode = 'FullRowSelect'
$dataGridView1.MultiSelect = $false
$dataGridView1.add_CellDoubleClick($handler_dataGridView1_CellDoubleClick)
$form1.Controls.Add($dataGridView1)
$button1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 198
$System_Drawing_Point.Y = 10
$button1.Location = $System_Drawing_Point
$button1.Name = "button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 75
$button1.Size = $System_Drawing_Size
$button1.TabIndex = 1
$button1.Text = "Search"
$button1.UseVisualStyleBackColor = $True
$button1.add_Click($button1_OnClick)
$form1.Controls.Add($button1)
$textBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 12
$textBox1.Location = $System_Drawing_Point
$textBox1.Name = "textBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 160
$textBox1.Size = $System_Drawing_Size
$textBox1.TabIndex = 0
$textBox1.add_TextChanged($handler_textBox1_TextChanged)
$form1.Controls.Add($textBox1)
$InitialFormWindowState = $form1.WindowState
$form1.add_Load($OnLoadForm_StateCorrection)
$form1.ShowDialog()| Out-Null
}
$addonName = "Search _All Files"
$addonKey = "Ctrl+Alt+A"
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add($addonName,$scriptBlock,$addonkey) | Out-Null
Yes, the only side-effect of using WinForms — actually PrimalForms Community Edition — is the amount of code it generates. The actual logic for searching across and moving to desired location in ISE is just 10+ lines of code.
Anyway, all you have to do is, copy / paste the above code snippet in your ISE profile.
When you select Add-Ons -> Search All Files, you will see a dialog box similar to the one below:
Once you search for a keyword, you can double click the desired row to change the focus to the search result in the editor. This search supports RegEx as well.
If you want to see this in action, just watch the below video:





