Graphic Interface in Powershell looks different in PowerGUI - powershell

My first question here, sorry if something is wrong in the way I posted.
Well, I'm new in developing graphic things in Powershell, and I needed to make a simple script to configure hostname, IP, etc and make it simple to end users (ugh).
I'm developing a simple graphic interface in PowerGUI, I'm on it for a couple of days, testing it exclusively inside PowerGUI, and it was not looking bad, but when I finally ran the script outside PowerGUI, just running it in Powershell, the graphics looks quite different than in PowerGUI, like positioning, borders, themes, etc. I was disappointing. I'll post screenshots and a bit of the code.
Inside PowerGUI
Outside
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
ipconfig -all | Out-File $env:SYSTEMDRIVE"\old_network.txt"
#INICIO Fontes da aplicação
$font = New-Object System.Drawing.Font("Segoe UI",8.5,[System.Drawing.FontStyle]::Regular)
$font_btn_concluir = New-Object System.Drawing.Font("Segoe UI",15,[System.Drawing.FontStyle]::Regular)
$font_l_instru = New-Object System.Drawing.Font("Segoe UI",12,[System.Drawing.FontStyle]::Regular)
$font_i_n_sala = New-Object System.Drawing.Font("Segoe UI",20,[System.Drawing.FontStyle]::Regular)
#FIM Fontes da aplicação
$form = New-Object Windows.Forms.Form
$form.Size = New-Object Drawing.Size #(800,600)
$form.StartPosition = "CenterScreen"
$form.Font = $font
#$form.ControlBox = $false
$form.MaximizeBox = $false
$form.MinimizeBox = $false
$form.Text = "Configuração Telesalas - UNIASSELVI"
$form.Icon = $icon
$form.FormBorderStyle = "FixedDialog
So, anyone have any clue why this happens?

Its Because of the version of your forms. powergui automatically call v4.0** form my system but powershell consol calls v2. you can test it by yourself after compiling check the consols.

Related

Random number generator not working after converting to Exe

I have written a dice roller script. I have one with a single die and one with two dice. they both work in powershell, and the single die version works after converting to .exe using ps2exe. but the two die version runs as an exe but I get the following error "You cannot call a method on a null-valued expression"
Below is the 2 die script that gives the error after converting.
<#
.NAME
Random Dice Roller
#>
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Display1 = 1,2,3,4,5,6 | Get-Random
$Display2 = 1,2,3,4,5,6 | Get-Random
$LabelImage = [system.drawing.image]::FromFile("f:\psscripts\Die1.png")
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(400,300)
$Form.text = "Roll The Dice"
$Form.TopMost = $false
$Form.location = New-Object System.Drawing.Point(1,1)
$Form.StartPosition = "CenterScreen"
$Die1 = New-Object system.Windows.Forms.Label
$Die1.Text = "$Display1"
$Die1.AutoSize = $false
$Die1.width = 200
$Die1.height = 200
$Die1.location = New-Object System.Drawing.Point(1,1)
$Die1.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',150,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold))
$Die1.ForeColor = [System.Drawing.ColorTranslator]::FromHtml("#000000")
$Die1.BackgroundImage = $LabelImage
$Die2 = New-Object system.Windows.Forms.Label
$Die2.Text = "$Display2"
$Die2.AutoSize = $false
$Die2.width = 200
$Die2.height = 200
$Die2.location = New-Object System.Drawing.Point(200,1)
$Die2.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',150,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold))
$Die2.ForeColor = [System.Drawing.ColorTranslator]::FromHtml("#000000")
$Die2.BackgroundImage = $LabelImage
$Button1 = New-Object System.Windows.Forms.Button
$Button1.Location = New-Object System.Drawing.Size(175,220)
$Button1.Size = New-Object System.Drawing.Size(80,50)
$Button1.Text = "Roll Me"
$Button1.Add_Click({Roll})
$Form.controls.AddRange(#($Die1,$Die2,$Button1))
$Die.Add_Click({ Roll })
#region Logic
function Roll{
$Form.Close()
$Form.Dispose()
.\Dice.exe}
#endregion
[void]$Form.ShowDialog()
There are two possible causes here:
Note that there is no safety in wrapping you PowerShell script in an .exe file. In fact the PowerShell script is extracted in a temporary folder and executed from there which might be the cause of your issue (e.g. the relative .\Dice.exe location)
It is unwise to do a $Form.Dispose() from within a form function/event
Remove that from the function and put it outside the form, e.g.:
[void]$Form.ShowDialog(); $Form.Dispose()
(Or do not use the Dispose method at all as PowerShell will usually already takes care of that if you [void] the $From.)
What is your motive for creating an EXE?
An alternative might be to create a CMD file with a Batch bootstrap instead. Create a CMD file with the following code and include your script after this.
<# :
#ECHO OFF
SET f0=%~f0
PowerShell -NoProfile -ExecutionPolicy RemoteSigned -Command ".([scriptblock]::Create((get-content -raw $Env:f0)))"
PAUSE
GOTO :EOF
<#~#>
# Insert PowerShell script after this line.

How to allow Ctrl+A to select all in a Windows Form textbox (powershell)

I'm writing a .ps1 script with a windows forms GUI. When I run it from Powershell ISE, it allows the use of Ctrl+A to 'select all' in the text box. However when running the .ps1 outside of ISE, the action of CTRL+A does nothing.
Any idea what settings I can change on the text box to allow Ctrl+A?
The only threads I could find on this topic were for writing in other languages like C.
Currently what I have:
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(110,20)
$textbox.Add_KeyDown({
if ($_.KeyCode -eq "Enter") {$okButton.PerformClick()}
})
**$textbox.acceptstab = $true
$textbox.shortcutsenabled = $True**
$form.Controls.Add($textBox)
I can reproduce your issue here.
One option is to incorporate this answer - https://stackoverflow.com/a/29957334/3156906 - and call Application.EnableVisualStyles().
Your example then becomes (with an additional bit of set-up code to make it self-contained):
Add-Type -AssemblyName "System.Windows.Forms"
Add-Type -AssemblyName "System.Drawing"
[System.Windows.Forms.Application]::EnableVisualStyles()
$form = new-object System.Windows.Forms.Form
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(110,20)
$textbox.Add_KeyDown({
if ($_.KeyCode -eq "Enter") {$okButton.PerformClick()}
})
#$textbox.acceptstab = $true
#$textbox.ShortcutsEnabled = $true
$form.Controls.Add($textBox)
$form.ShowDialog()
You can then use Ctrl+A in the textbox to select the text.
You could manually write the Ctrl+A event to select the textbox content:
$textbox.Add_KeyDown({
if (($_.Control) -and ($_.KeyCode -eq 'A')) {
$textbox.SelectAll()
}
})

set a Powershell Data Entry to non Resizeable

I am programming Windows Powershell since 2 months and I haven't found anything about the resizeability of an input window. In Java there is something called 'setResizeable(true/false)' but I didn't find anything like that in the internet.
Thanks for your time and support :D
Set the FormBorderStyle property of the form to Sizable:
Add-type -AssemblyName System.Windows.Forms > $null
Add-Type -AssemblyName System.Drawing > $null
$Form = New-Object -TypeName System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size 250,400
$Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Sizable
$Form.ShowDialog()

Continuous Ping Powershell Form

OK so I am newer to using windows forms inside Powershell, and I am having a bit of trouble with the form being all laggy since there is a continuous ping running. Fundamentally all I need to do is display the IP address each time it runs a ping. I tried to search around and it seems like the proper way to do this is with a running job in the background?
I think the way this is currently written that the ping happens in the background but I'm not sure how to update the form (or if its even possible to make it visible to it?)
Here is a sample, any guidance with this would be greatly appreciated.
function global:ContinuousPing{
$global:job = start-job {
while($true){
$pingStatus = Test-Connection google.com -Count 1
$label.text = $pingStatus.IPV4Address.IPAddressToString
#[System.Windows.Forms.Application]::DoEvents()
start-sleep 1
}
}
}
Add-Type -AssemblyName System.Windows.Forms
$pingForm = New-Object System.Windows.Forms.Form
$label = New-Object System.Windows.Forms.Label
$button1 = New-Object System.Windows.Forms.Button
$ping = {
ContinuousPing
while($true){
Receive-Job $job
}
}
$label.Text = "Ping Status"
$button1.Location = New-Object System.Drawing.Point(100,10)
$button1.add_Click($ping)
$pingForm.Controls.Add($label)
$pingForm.Controls.Add($button1)
$pingForm.ShowDialog() | Out-Null
remove-job $job
You need to separate the GUI updating and the ping task. This is easy to in languages that are designed to have GUIs like C# winforms, If you tried it you would be surprised how much easier it is than trying to bend a GUI over PowerShell.
You can try the link Mathias posted, It will do what you require.

How to create a popup message in Powershell without buttons

I'm trying to create a message dialogue in Powershell where the user has no option to action on the message as that is the intention. So the message will have the X button grayed along with the buttons (not showing buttons are even better).
The closest I could reach was disabling the X via below code:
$wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
$wshell.Popup("Aborted",0,"ERROR!",48+4)
But cannot figure out disabling button part. Below MS articles were of little help as well:
http://blogs.technet.com/b/heyscriptingguy/archive/2006/07/27/how-can-i-display-a-message-box-that-has-no-buttons-and-that-disappears-after-a-specified-period-of-time.aspx
https://msdn.microsoft.com/en-us/library/x83z1d9f(v=vs.84).aspx
Referred to few other articles over net some even suggesting custom made buttons using HTML, or VB library. But not what I was looking for.
Any help/hint/suggestion would be deeply appreciated.
Regards,
Shakti
Dig into the .NET Windows.Forms namespace, you can make pretty much any kind of window you want with that:
https://msdn.microsoft.com/en-us/library/system.windows.forms.aspx
Here's a quick sample window w/ no buttons that can't be moved/closed by the user, but closes itself after 5 seconds:
Function Generate-Form {
Add-Type -AssemblyName System.Windows.Forms
# Build Form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Test"
$objForm.Size = New-Object System.Drawing.Size(220,100)
# Add Label
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(80,20)
$objLabel.Size = New-Object System.Drawing.Size(100,20)
$objLabel.Text = "Hi there!"
$objForm.Controls.Add($objLabel)
# Show the form
$objForm.Show()| Out-Null
# wait 5 seconds
Start-Sleep -Seconds 5
# destroy form
$objForm.Close() | Out-Null
}
generate-form
Using the script above as a launching point I'm attempting to make a function that will allow me to popup a please wait message run some more script then close the popup
Function Popup-Message {
param ([switch]$show,[switch]$close)
Add-Type -AssemblyName System.Windows.Forms
# Build Form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Test"
$objForm.Size = New-Object System.Drawing.Size(220,100)
# Add Label
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(80,20)
$objLabel.Size = New-Object System.Drawing.Size(100,20)
$objLabel.Text = "Hi there!"
$objForm.Controls.Add($objLabel)
If ($show)
{
$objForm.Show() | Out-Null
$global:test = "Show"
}
If ($close)
{
# destroy form
$objForm.Close() | Out-Null
$global:test = "Close"
}
}
I can then get the popup to display by:
Popup-Message -show
At this point I can see the $test variable as Show
But when I try to close the window with:
Popup-Message -close
But the popup window will not close
If I look at $test again it will show as Close
I'm assuming this has something to do with keeping the function in the Global Scope but I can't figure out how to do this with the form