Powershell LinkClicked event for a RichTextBox - powershell

Im using windows Windows.Forms.RichTextBox to redirect my powershell script output "$var".
Detect.Urls is already enabled and working, but unable to open them by clicking.
Can any one help me with the code for link click event handler in powershell script........
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Size(10,150)
$outputBox.Size = New-Object System.Drawing.Size(700,300)
$outputBox.MultiLine = $True
$outputBox.SelectionIndent = 8
$outputBox.SelectionHangingIndent = 3
$outputBox.SelectionRightIndent = 12
$outputBox.ScrollBars = "ForcedBoth"
$Form.Controls.Add($outputBox)
$outputBox.Text = $var
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

You have to handle click events by yourself
$outputBox.add_LinkClicked({
Start-Process -FilePath $_.LinkText
})
Will open link in the default browser when clicked.

This is how I do it with Powershell Studio...right click the control and add a new event...add the linkclicked event and then go to the script and add the following.
depending on what you want to be opened you may need to used something other than explorer, but the $_.linktext should have the link you want from the url. note if there are spaces you will have to something to replace them as the url will be broke at the first space it encounters.
$Linkclicked = $_.LinkText
explorer.exe $Linkclicked

Related

Powershell popup to list of usernames

I wish to have a powershell script that provides a popup message to a specific list of users. I need to use a list of relevant users in a spreadsheet with their network username and not use Active Directory. I have the powershell script to display a suitable message with a Warning icon and found to format the popup in a certain way I had to use a "FORM" and not a default popup messagebox. Although the following two lines for the Warning icon would not work in the form so had to use a picture box
$WarningIcon = New-Object ([System.Windows.MessageBoxImage]::Warning)
$Form.Controls.Add($WarningIcon)
The script for the form is as follows. There is probably a cleaner way of creating a form like this but I am quite new to Powershell!
Add-Type -AssemblyName System.Windows.Forms
$Form = New-Object system.Windows.Forms.Form
$Form.Width = 700
$Form.Height = 400
$Form.BackColor = "#DCDCDC"
$Form.Text = "System Restart Alert"
$Font = New-Object System.Drawing.Font("Ariel",30,
[System.Drawing.FontStyle]::Bold::Underline)
$FontB = New-Object System.Drawing.Font("Ariel",14,
[System.Drawing.FontStyle]::Bold)
$Picture = (get-item ("C:\FA_Files\Windows_Warning_Exclamation9.jpg"))
$img = [System.Drawing.Image]::Fromfile($Picture)
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Location = New-object System.Drawing.Size(160,30)
$pictureBox.Height = "100"
$pictureBox.Image = $img
$Form.controls.add($pictureBox)
$Label = New-Object System.Windows.Forms.Label
$Label.Location = "260,30"
$Label.Font = $Font
$Label.ForeColor = "Red"
$Label.Text = "WARNING!"
$Label.AutoSize = $True
$Form.Controls.Add($Label)
$LabelB = New-Object System.Windows.Forms.Label
$LabelB.Location = "100,130"
$LabelB.Font = $FontB
$LabelB.Text = "Due to essential maintenance system requires rebooting"
$LabelB.AutoSize = $True
$Form.Controls.Add($LabelB)
$LabelC = New-Object System.Windows.Forms.Label
$LabelC.Location = "100,160"
$LabelC.Font = $FontB
$LabelC.Text = "Please save all work immediately"
$LabelC.AutoSize = $True
$Form.Controls.Add($LabelC)
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = "300,280"
$okButton.Font = "$FontB"
$okButton.Size = "85,28"
$okButton.Text = "Okay"
$Form.Controls.Add($okButton)
$okButton.Add_Click = ({$Form.Close()})
$Form.ShowDialog()
I can retrieve a list of network usernames from the spreadsheet okay. Below is an image of the csv content
But I have googled a lot and cannot find a way of sending the popup to the list of usernames retrieved from the spreadsheet. So far I have tried the following where I have the form above set to the $msg varaiable and also tried having the form in another file and referencing that file in the $msg variable but it doesn't work
$csv = Import-csv "C:\FA_Files\NetNames.csv"
foreach($line in $csv)
{
$name = $line.("Name")
$netName = $line.("NetworkName")
#Echo "Name is $name and Network Name is $netName"
msg $netName $msg
}
It also has to be on the username and not the machine name.
How do I correct this please?
FWIW, msg.exe has replaced net /send in Windows, and is meant for sending messages to users, so I would begin by looking at the syntax for message.exe here. .
It has a /server: switch you can use to send a message to a remote host. So, take your user and computer name list and put them in a CSV file like this:
//MyInputFile.csv
ComputerName,UserName
Laptop01,BillG
Laptop02,StephenO
PC03,WayneH
Desktop04,JimA
You could use a short script like this to achieve your goal (or get you mostly there, at least 😁)
$Msg = "Put your message here"
$SpreadSheet = Import-CSV .\PathTo\MyInputFile.csv
ForEach ($row in $SpreadSheet){
"Sending message to \\$($row.ComputerName)\$($row.UserName) : $msg"
msg /server:$($row.ComputerName) $($row.UserName) $msg
}
You'll see an output like this in the console:
Sending message to \\Laptop01\BillG : Put your message here
Sending message to \\Laptop02\StephenO : Put your message here
Sending message to \\PC03\WayneH : Put your message here
Sending message to \\Desktop04\JimA : Put your message here
Sending message to \\localhost\* : Put your message here
Then your lucky user will see the following on their workstation.
If a computer can't be reached, the process will time out after five seconds or so and move on to the next one in the list.
All users that are a member of Active Directory by default receive read rights, this is by design as Active Directory is exactly the kind of system that should be relied on for the kind of functionality you desire... not sure why your ICT manager is so against the idea.
You cannot send a message to a user (with only the username), you must know the machine the user is logged into as well.
The only way I can think to achieve this is to iterate through every computer and query who is logged on and if the user matches your list then send a message to that computer. This would require reading a list of computers from AD or iterating through every available IP address on your local network(s).

Powershell script IE Automatic Login opens another Login tab

I have a script for Internet Explorer Login which works fine. But I want to go further because after the first login, Internet Explorer opens a new tab, with another Login form. So $IE.visible = $False does not work for the second tab, which opens automatically, and also I dont know how to give focus to the second tab to input other credentials and also put it on invisible.
$variablePass = $variablePass.Text
$username = "testUser"
$username2 = "testUser2"
$password = "testPass" + $variablePass
$password2 = "testPass2"
$ie = New-Object -com InternetExplorer.Application
$ie.visible = $false
$ie.Height = 720
$ie.Width = 1280
$ie.navigate("https://mylink.com")
while($ie.ReadyState -ne 4) {start-sleep -m 100}
#This one work fine
$ie.document.getElementById("username").value = "$username"
$ie.document.getElementById("password").value = "$password"
$ie.document.getElementById("btnSubmit").click()
# Here comes the problem, after IE reach mylink.com and do the login script, the a new tab pop up with another login form
$ie.document.getElementById("username").value = "$username2"
$ie.document.getElementById("password").value = "$password2"
$ie.document.getElementById("loginBtn").click()
So, how do I do the second Login form to work. Preferably in invisible mode, I mean $IE.visible = $False
Are you able to change the configuration of IE to prevent this from happening?
https://helpdeskgeek.com/how-to/force-ie-to-open-link-in-new-tab/
You could manually configure IE, or use PowerShell to edit the registry to force that specific configuration...

Add Button to NotifyIcon

I want to see a little notification icon to indicate that the script I wrote is still active (both the script and displying the icon works). But I need a button within the context menu of the icon to stop the script immediately. And that's the part where my problem is:
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objContextMenu = New-Object System.Windows.Forms.ContextMenu
$ExitMenuItem = New-Object System.Windows.Forms.MenuItem
$ExitMenuItem.add_Click({
echo stoped
$continue = $False
$objNotifyIcon.visible = $False
})
$objContextMenu.MenuItems.Add($ExitMenuItem) | Out-Null
$objNotifyIcon.ContextMenu = $objContextMenu
$objNotifyIcon.Visible = $True
The script itself is longer, this is just the relevant part. If I run it from PowerShell ISE it works just fine. When I run it from a .bat file with
powershell .\myscript.ps1
the context menu is not working anymore.
This is just a wild guess, but try running the script in Single Thread Apartment mode:
powershell -STA -File .\myscript.ps1

powershell get handle on new window

We are trying to use Powershell to automate some testing on our site.
We have hit a problem when we issue the click event on an anchor which opens a new tab.
We need to get a handle on the new tab and then continue processing by clicking the print button on the new tab.
How could this be done using Powershell?
set-executionpolicy remotesigned
$ie = new-object -com "InternetExplorer.Application"
$ie.navigate("xxxxx.com")
$ie.visible = $true
$doc = $ie.document
While ($ie.Busy) {Sleep 10}
$doc -eq $null
$tb1 = $doc.getElementByID("username")
$tb2 = $doc.getElementByID("password")
$tb1.value = "xxxxxxxxxxx"
$tb2.value = "xxxxxxxxxxx"
$btn = $ie.document.getelementsbytagname("input")|where{$_.name -eq "Submit"}
$btn.click()
$ie.navigate("xxxxx.com/admin/reports.html#")
$link = $ie.Document.getElementsByTagName('A') | where-object {$_.innerText -eq 'All Photos'}
$link.click()
<<<<<<<<<<< it's here where a new tab is open and we need to get a handle on the new page to be able to click the print button >>>>>>>>>>>
$popupHandle = $ie.openwindow.winrefs[$targetName]
$btn = $popupHandle.document.getelementsbytagname("input")|where{$_.name -eq "print"}
$btn.click()
We are new to Powershell so any help would be appreciated.
Thanks
Richard
Try opening your new tab using $ie.navigate2 and 0x0800 to put it in a new foreground tab. That will automatically focus you on the new tab allowing you to grab the print button.
e.g.
# Setting page to new foreground tab here
$newTabPage = $ie.navigate2("www.xxxx.com",0x0800)
Similarly, you can use 0x1000 to open the page in a new background tab, which will open the new tab but not automatically bring it to focus.
# Setting page to new background tab here
$newTabPage = $ie.navigate2("www.xxxx.com",0x1000)

HTA writing to a <span> from a text file

I am trying to write data from a text file to a in an HTA.
I'm running a powershell script inside of the HTA, using VBscript for the input buttons
Get-TSSession -computername ismeta | where { $_.username -eq 'amis5235'} | format-table windowstationname,username,state,sessionid | out-file C:\windows\temp\PSTerminalServices.txt
I'm going to be using a for each loop for about 60 servers
Then I was hoping to write the output to a within the HTA, kind of like a streamer in VB or stacking a string the VBscript, something like:
strHTML = strHTML & "Running Process = " & objProcess.Name & " PID = " & objProcess.ProcessID & " Description = " & objProcess.Description & "<br>"
but it seems there should be a simpler way to do this.
I think this minimal HTA will solve your problem. It runs a command line and reads the output stream, one line every 1/10 second, then pushes the results into a textarea. You may want to alter your Powershell script to return the process details to STDOUT, but it will probably work.
<script language="Javascript">
var E, LineWriteTimerID
function execWithStatus(cmdLine){//Can't run minimized with Exec. Can't capture StdOut/StdErr with Run.
E = new ActiveXObject("WScript.Shell").Exec(cmdLine);
LineWriteTimerID = window.setInterval("writeOutLine()",100);//pause for 100ms
E.StdIn.Close();//must close input to complete a ps command
}
function writeOutLine(){
if(E.StdOut.AtEndOfStream) window.clearTimeout(LineWriteTimerID);
if(!E.StdErr.AtEndOfStream) txtResults.value += "ERROR: " + E.StdErr.ReadAll() + "\n";
if(!E.StdOut.AtEndOfStream) txtResults.value += E.StdOut.ReadLine() + "\n";
}
</script>
<textarea id=txtCmd style="width:90%" rows=1>
powershell.exe -noninteractive -command ls c:\windows\system32\drivers\etc\</textarea>
<button onclick="execWithStatus(txtCmd.value)">Run</button>
<br><textarea id=txtResults style="width:100%" rows=20></textarea>
Save this code as an .HTA file, change the contents of the txtCmd textarea to be your command line, and give it a try. Good Luck!
Ok Here is the way I use.
On the theorical point of view it consist in building an interface with Windows Forms and then put PowerSell code behind event.
On technical point of view two solutions :
1) Use visual studio free edition to build interface in C# and then a conversion tool to create the associate PowerShell source (french article here)
2) you can download freely (you just need to register) Sapiens PrimalFormsCE.exe (Community Edition)
This tool allow you create a form and then to generate Powershell associete code.
You can also build forms from crash here is a peace of sample code :
Add-Type -AssemblyName system.Windows.Forms
# Create the form
$form = New-Object Windows.Forms.Form
$form.Text = "Test Saisie"
$form.Size = New-Object System.Drawing.Size(250,154)
# Create EntryFiel
$TB_Saisie = New-Object System.Windows.Forms.TextBox
$TB_Saisie.Location = New-Object System.Drawing.Point(50,31)
$TB_Saisie.Size = New-Object System.Drawing.Size(150,32)
# Create "Ok" Button
$PB_Ok = New-Object System.Windows.Forms.Button
$PB_Ok.Text = "Ok"
$PB_Ok.Location = New-Object System.Drawing.Point(50,62)
$PB_Ok.Size = New-Object System.Drawing.Size(50,32)
$PB_Ok.DialogResult = [System.Windows.Forms.DialogResult]::OK
# Create "Cancel" Button
$PB_Cancel = New-Object System.Windows.Forms.Button
$PB_Cancel.Text = "Cancel"
$PB_Cancel.Location = New-Object System.Drawing.Point(150,62)
$PB_Cancel.Size = New-Object System.Drawing.Size(50,32)
$PB_Cancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
# Add controls to the form
$form.Controls.Add($PB_Ok)
$form.Controls.Add($PB_Cancel)
$form.Controls.Add($TB_Saisie)
# Message loop
$Res = $form.ShowDialog()
If ($Res -eq [System.Windows.Forms.DialogResult]::OK)
{
Write-Host ("Accepted : {0}" -f $TB_Saisie.Text)
}
else
{
Write-Host "Cancel"
}