I am just trying to make a simple IP/Hostname checker. The one part I am struggling with is getting it to ping each item from a list. It only shows the result of the first, or last one.
I have tried adding items from the text box into an array and pinging them that way, and it had the same results.
Here is my Current Code.
[System.Windows.Forms.Application]::EnableVisualStyles()
function ping-list{
$IPStatus.Text = ""
$names = #($IPList.text)
$Names | ForEach-Object{
if (Test-Connection -ComputerName $_ -Count 1){
$IPStatus.Text += "$_ is Online"
Write-Host "$_ is Online"
}
else{
$IPStatus.Text += "$_ is Offline"
Write-Host "$_ is Offline"
}
}
}
$Pinger = New-Object system.Windows.Forms.Form
$Pinger.ClientSize = '657,557'
$Pinger.text = "Pinger"
$Pinger.TopMost = $false
$IPStatus = New-Object system.Windows.Forms.TextBox
$IPStatus.multiline = $true
$IPStatus.width = 234
$IPStatus.height = 498
$IPStatus.enabled = $true
$IPStatus.location = New-Object System.Drawing.Point(408,45)
$IPStatus.Font = 'Microsoft Sans Serif,10'
$IPStatus.Text = "Ready"
$IPList = New-Object system.Windows.Forms.TextBox
$IPList.multiline = $true
$IPList.width = 234
$IPList.height = 498
$IPList.enabled = $true
$IPList.location = New-Object System.Drawing.Point(15,45)
$IPList.Font = 'Microsoft Sans Serif,10'
$IPList.Text = #("127.0.0.1")
$PingButton = New-Object system.Windows.Forms.Button
$PingButton.text = "button"
$PingButton.width = 60
$PingButton.height = 30
$PingButton.location = New-Object System.Drawing.Point(298,240)
$PingButton.Font = 'Microsoft Sans Serif,10'
$PingButton.Add_Click({ping-list})
$Pinger.controls.AddRange(#($IPStatus,$IPList,$PingButton))
$Pinger.Add_Shown( {$Pinger.Activate()})
$Pinger.ShowDialog()
$IPList.text gets all the text in the textbox.
Instead use Lines
function ping-list{
$IPStatus.Text = ""
$Names = #($IPList.Lines)
$Names | ForEach-Object{
if (Test-Connection -ComputerName $_ -Count 1){
$IPStatus.Text += "$_ is Online`r`n"
Write-Host "$_ is Online"
}
else{
$IPStatus.Text += "$_ is Offline`r`n"
Write-Host "$_ is Offline"
}
}
}
Related
TLDR:
How can I make a generated variable, and then call that variable later within a Add_click.
I am sure some kind of serialization of each Object/button I make is what is needed.
I am building a small tool that reads from a csv to create a button, and function.
the csv looks something like
Name Type Link Script
Powershell App C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Empty
FixXYZ Fix Empty -ScriptStuffHere-
The tool will then make a button with the Name, (work in progress to filter apps and fixes), and when you click the button, if its an app will do start ($link) and if its a fix it will run that script.
My issue is I have it making the button and giving them names, and the name of the button stays, but the function does not.
full code:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
#=======================================================
$Form = New-Object system.Windows.Forms.Form
$Form.text = "Form"
$Form.TopMost = $false
$Form.ClientSize = New-Object System.Drawing.Point(760,400)
$Form.minimumSize = New-Object System.Drawing.Size(760,400)
$Form.maximumSize = New-Object System.Drawing.Size(760,400)
$GetCSV = import-csv "C:\File.csv"
$Details = $GetCSV.Name
$DeviceList = $GetCSV
$Count = $DeviceList.Lines.Count
$ObjectNumber = -1
Write-Host "Total Entries:" $Count
$x = 0 #up down
$z = 0 #left right
$Names = #($DeviceList.Lines)
$Names | ForEach-Object{
$ObjectNumber += 1
Write-Host "Object:" $ObjectNumber
$x += 0
$z += 120
if($z -eq 720){
$x += 120
$z = 0
Write-Host "New Row"}
Write-Host "x" $x
Write-Host "z" $z
$ButtonLabel = ($GetCSV[$ObjectNumber]).Name
set-Variable -Name "var$ObjectNumber" -Value ($GetCSV[$ObjectNumber] | Select Name, Type, Link, Script, File, FileSource)
Write-Host "Name: " (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Name
Write-Host "Type: " (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Type
Write-Host "Link: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link
Write-Host "Script: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).Script
Write-Host "File: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).File
Write-Host =========================
$_ = New-Object system.Windows.Forms.Button
$_.text = $ButtonLabel
$_.width = 100
$_.height = 100
$_.location = New-Object System.Drawing.Point($z,$x)
$_.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$_.Add_Click({ Start (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link})
$Form.Controls.Add($_)
}
[void]$Form.ShowDialog()
I am very certain my issue is coming from
$_.Add_Click({Start (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link})
I know the issue is with $ObjectNumber because that number is getting +1 each time the ForEach is gone through, so when I click a button, its taking "var$OjbectNumber" as its Last number. Clicking the button works, but all buttons open the last entries link.
The answer was using a unused property to throw my desired call back variable in.
So in this case, i have a folder with with programs, the button will be made, and set the $Button.Text (its name) as the name of the .exe, and then it sets the $Button.Tag as the file path, so when I go do the button.Add_Click , I just call the Button.Tag as it will have the path of my Exe.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '580,400'
$Form.Text = "Test"
$Form.TopMost = $false
$Form.FormBorderStyle = 'Fixed3D'
$Form.MaximizeBox = $false
$Form.minimumSize = New-Object System.Drawing.Size(580,400)
$Form.maximumSize = New-Object System.Drawing.Size(580,400)
#Place Holder Form Junk Above
#Reset these on Run
$Global:x = 10 #Reset up down
$Global:z = 10 #Reset left right
$Global:ObjectNumber = -1 #Reset Object Count
Function Make-Button([string] $ToolName, [string] $ToolPath, [string] $SetZ, [string] $SetX){
$Button = New-Object system.Windows.Forms.Button
$Button.text = $ToolName
$Button.width = 120
$Button.height = 120
$Button.location = New-Object System.Drawing.Point($SetZ,$SetX)
$Button.Font = New-Object System.Drawing.Font('Franklin Gothic',10)
$Button.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$Button.FlatAppearance.BorderSize = 0
$Button.ForeColor = [System.Drawing.ColorTranslator]::FromHtml("#ffffff")
$Button.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#515582")
$Button.tag = $ToolPath #<- this is where the answer was. Throwing my desired callback into an unused property of the the Button. in this case, i used _.Tag
$Button.Add_Click{start $this.tag}
$Form.Controls.AddRange(#($Button))
Write-Host "$ToolName"
Write-Host "$ToolPath"
Write-Host "$SetZ"
Write-Host "$SetX"
}
function Get-Position{
switch ($Global:ObjectNumber) {
-1{$Global:ObjectNumber += 1
Write-Host "Object:" $Global:ObjectNumber
$Global:x = 0
$Global:z += 0}
Default{$Global:ObjectNumber += 1
Write-Host "Object:" $Global:ObjectNumber
$Global:x += 0
$Global:z += 140}
}#end switch
if($Global:z -eq 570){ #Make New Row
$Global:x += 140
$Global:z = 10
Write-Host "New Row"
}
}
$Tools = Get-ChildItem "C:\WINDOWS\system32" -Filter *.exe
$Count = ( $Tools | Measure-Object ).Count;
Write-Host "Entries:" $Count
$Names = #($Tools) #Put Tools in Array
$Names | ForEach-Object{
Get-Position
Make-Button ($_.Name).replace(".exe","") ($_.FullName) ($z) ($x)
}
#End Form
$Test.Add_Shown( {$Test.Activate()})
$Test.ShowDialog()
[void]$Form.ShowDialog()
Continuing from my comment...
A small refactor to get this to show where things are
Clear-Host
Add-Type -AssemblyName System.Windows.Forms,
PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.text = 'Form'
$Form.TopMost = $false
$Form.ClientSize = New-Object System.Drawing.Point(760,400)
$Form.minimumSize = New-Object System.Drawing.Size(760,400)
$Form.maximumSize = New-Object System.Drawing.Size(760,400)
$GetCSV = Import-Csv -LiteralPath 'D:\Scripts\File.csv'
$Details = $GetCSV.Name
$DeviceList = $GetCSV
$Count = $DeviceList.Count
$ObjectNumber = -1
"Total Entries: $Count`n`n"
$ObjDown = 0
$ObjRight = 0
$DeviceList.Name |
ForEach-Object{
$ObjectNumber += 1
"`nObject: $ObjectNumber"
$x = 0
$ObjRight = 120
if($ObjRight -eq 720)
{
$x = 120
$ObjRight = 0
'New Row'
}
"x $x"
"z $ObjRight"
$ButtonLabel = ($GetCSV[$ObjectNumber]).Name
set-Variable -Name $("var$ObjectNumber") -Value ($GetCSV[$ObjectNumber] |
Select Name, Type, Link, Script, File, FileSource)
("Name: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Name)")
("Type: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Type)")
("Link: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Link)")
("Script: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Script)")
("File: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).File)")
$PSitem = New-Object system.Windows.Forms.Button
$PSitem.text = $ButtonLabel
$PSitem.width = 100
$PSitem.height = 100
$PSitem.location = New-Object System.Drawing.Point($ObjRight,$x)
$PSitem.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$PSitem.Add_Click({
$(Get-Variable -Name $("var$ObjectNumber") -ValueOnly)
})
$Form.Controls.Add($PSitem)
}
#[void]$Form.ShowDialog()
Here is an example I gave as an answer to another post to dynamically create UX/UI elements and assign a form event, though not using an external file, it's the same concept.
How to create multiple button with PowerShell?
Add tooltip and form event, like so...
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(381,316)
$Form.text = "Auto Button UI"
$Form.TopMost = $false
$Form.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#c9f6fe")
$i = 0
Get-Variable -Name 'Button*' |
Remove-Variable
$objTooltip = New-Object System.Windows.Forms.ToolTip
$objTooltip.InitialDelay = 100
1..3 |
foreach{
$CurrentButton = $null
$CurrentButton = New-Object System.Windows.Forms.Button
$CurrentButton.Location = "$(50+100*$i), 275"
$CurrentButton.Text = $PSItem
$CurrentButton.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
New-Variable "Button$PSitem" $CurrentButton
$objTooltip.SetToolTip(
$CurrentButton,
"Execute action assigned to $($CurrentButton.Text)"
)
$CurrentButton.add_click(
{
[System.Windows.Forms.MessageBox]::
Show(
"$($CurrentButton.Text)", $($CurrentButton.Text), [System.Windows.Forms.MessageBoxButtons]::
OKCancel, [System.Windows.Forms.MessageBoxIcon]::Information
)
})
$i++
$form.Controls.Add($CurrentButton)
}
[void]$Form.ShowDialog()
Yet, though it adds the event to each button element, the message text is the last one passed. Unless explicitly called as in the example from the link.
To adapt the second example in the answer already provided here so that the message text is not just the last one passed, you can change the reference within the event to the instance this.text rather than the iteratively updated $CurrentButton.text
$CurrentButton.add_click(
{
[System.Windows.Forms.MessageBox]::
Show(
"$($this.Text)", $($this.Text), [System.Windows.Forms.MessageBoxButtons]::
OKCancel, [System.Windows.Forms.MessageBoxIcon]::Information
)
})
Credit to jrv https://social.technet.microsoft.com/Forums/ie/en-US/09ff4141-6222-4bff-b8a9-a1253e0d378a/powershell-form-procedurally-creating-buttons?forum=ITCG
Full code with serialization of button object and event:
Clear-Host
Add-Type -AssemblyName System.Windows.Forms,
PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(381,316)
$Form.text = "Auto Button UI"
$Form.TopMost = $false
$Form.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#c9f6fe")
$i = 0
Get-Variable -Name 'Button*' |
Remove-Variable
$objTooltip = New-Object System.Windows.Forms.ToolTip
$objTooltip.InitialDelay = 100
1..3 |
foreach{
$CurrentButton = $null
$CurrentButton = New-Object System.Windows.Forms.Button
$CurrentButton.Location = "$(50+100*$i), 275"
$CurrentButton.Text = $PSitem
$CurrentButton.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
New-Variable "Button$PSitem" $CurrentButton
$objTooltip.SetToolTip(
$CurrentButton,
"Execute action assigned to $($CurrentButton.Text)"
)
$CurrentButton.add_click(
{
[System.Windows.Forms.MessageBox]::
Show(
"$($this.Text)", $($this.Text), [System.Windows.Forms.MessageBoxButtons]::
OKCancel, [System.Windows.Forms.MessageBoxIcon]::Information
)
})
$i++
$form.Controls.Add($CurrentButton)
}
[void]$Form.ShowDialog()
I have an issue with my PS script including a listview.
I need to check the content of 6 directorys and show the content in 6 different columns :
The issue is that i can't get a correct visual, they are all in the same column
Here is my code :
$Form = New-Object Windows.Forms.Form
$Form.Text = "New Test"
$Form.Width = 1550
$Form.Height = 800
$Listview = New-Object System.Windows.Forms.ListView
$Listview.Location = New-Object System.Drawing.Size(15,10)
$Listview.Size = New-Object System.Drawing.Size(550,10)
$Listview.AutoResizeColumns([System.Windows.Forms.ColumnHeaderAutoResizeStyle]::ColumnContent)
$Listview.View = "Details"
$Listview.FullRowSelect = $true
$Listview.GridLines = $true
$Listview.Height = 650
$Listview.Width =1500
$Listview.AllowColumnReorder = $true
$Listview.Sorting = [System.Windows.Forms.SortOrder]::None
#[void]$Listview.Columns.Add('Null',0)
[void]$Listview.Columns.Add('Scripts',150)
[void]$Listview.Columns.Add('Applications',150)
[void]$Listview.Columns.Add('Systems',500)
[void]$Listview.Columns.Add('Databases',100)
[void]$Listview.Columns.Add('Datas',150)
[void]$Listview.Columns.Add('Backups',500)
$oButton = New-Object Windows.Forms.Button
$oButton.Text = "List"
$oButton.Top = 700
$oButton.Left = 350
$oButton.Width = 150
$oButton.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$a = (Get-ChildItem "C:\Scripts\").Name
$b = (Get-ChildItem "C:\Applications\").Name
$c = (Get-ChildItem "C:\Systems\").Name
$d = (Get-ChildItem "C:\Databases\").Name
$e = (Get-ChildItem "C:\Datas\").Name
$f = (Get-ChildItem "C:\Backups\").Name
$Entry = New-Object System.Windows.Forms.ListViewItem($_.Null)
foreach($mp in $a){
$Entry1 = New-Object System.Windows.Forms.ListViewItem($_.Scripts)
$Listview.Items.Add($mp)
}
foreach($mp1 in $b){
$Entry2 = New-Object System.Windows.Forms.ListViewItem($_.Applications)
$Listview.Items.Add($Entry2).SubItems.Add($mp1)
}
foreach($mp2 in $c){
$Entry3 = New-Object System.Windows.Forms.ListViewItem($_.Systems)
$Listview.Items.Add($Entry3).SubItems.Add($mp2)
}
foreach($mp3 in $d){
$Entry4 = New-Object System.Windows.Forms.ListViewItem($_.Databases)
$Listview.Items.Add($Entry4).SubItems.Add($mp3)
}
foreach($mp4 in $e){
$Entry5 = New-Object System.Windows.Forms.ListViewItem($_.Datas)
$Listview.Items.Add($Entry5).SubItems.Add($mp4)
}
foreach($mp5 in $f){
$Entry6 = New-Object System.Windows.Forms.ListViewItem($_.Backup)
$Listview.Items.Add($Entry6).SubItems.Add($mp5)
}
$Form.Add_Shown({$Form.Activate()})
$Form.controls.add($oButton)
$Form.controls.add($Listview)
$Form.ShowDialog()
I tried a lot of change but im still blocked
Thanks in advance for you help
Regards
I want to check an existing file, if the process still waiting for the file, it will display a GUI window. After the file is exist, the window will close automatically.
I tried this code, the window can not close, even the file already exist.
Checking the file:
$SN = "708TSTA"
$MAC = "2E5961370"
function Find {
$n = 0
while (-not (Get-ChildItem -Name "D:\SERVER\" | Where-Object {$_ -like "*$SN-$MAC*"})) {
Start-Sleep -s 1
D:\Auto\GUI.ps1
$n++
(Get-ChildItem -Name "D:\SERVER\" | Where-Object {$_ -like "*$SN-$MAC*"})
Write-Host "Attempt no $n"
}
Write-Host ">>Flag found after $n attempts"
return $true
}
if (Find) {
Write-Host "Found"
}
GUI.ps1:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '578,400'
$Form.Text = "Form"
$Form.BackColor = "#c1daf7"
$Form.WindowState = 'Maximized'
$Form.FormBorderStyle = "FixedDialog"
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Text = "UNDER PROCESS"
$Label1.AutoSize = $true
$Label1.Width = 25
$Label1.Height = 10
$Label1.Location = New-Object System.Drawing.Point(600,300)
$Label1.Font = 'Microsoft Sans Serif,30,style=Bold,Underline'
$Label1.ForeColor = "#d0021b"
$Label2 = New-Object System.Windows.Forms.Label
$Label2.Text = "WAITING"
$Label2.AutoSize = $true
$Label2.Width = 25
$Label2.Height = 10
$Label2.Location = New-Object System.Drawing.Point(770,500)
$Label2.Font = 'Microsoft Sans Serif,20,style=Bold'
$Label2.ForeColor = "#fb0505"
$Check = Get-ChildItem -Name "D:\SERVER\" | Where-Object {$_ -like "*$SN-$MAC*"}
if($Check) {
Write-Host "File Exist"
$Form.Close()
}
$Form.Controls.AddRange(#($Label1,$Label2))
[void]$Form.ShowDialog()
Instead of doing Start-Sleep inside the GUI, it is better to use a timer so the form stays responsive.
I changed the code of the GUI.ps1 (not the way it looks) like this:
Param (
[string]$Path = '*.*',
[string]$MaxAttempts = 5
)
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
# set things up for the timer
$script:nAttempts = 0
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000 # 1 second
$timer.Add_Tick({
$global:Result = $null
$script:nAttempts++
$file = Get-Item -Path $Path
if ($file) {
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $file.FullName
Attempts = $script:nAttempts
}
$timer.Dispose()
$Form.Close()
}
elseif ($script:nAttempts -ge $MaxAttempts) {
$global:Result = [PSCustomObject]#{
Exists = $false
FileName = ''
Attempts = $script:nAttempts
}
$timer.Dispose()
$Form.Close()
}
})
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '578,400'
$Form.Text = "Form"
$Form.BackColor = "#c1daf7"
$Form.WindowState = 'Maximized'
$Form.FormBorderStyle = "FixedDialog"
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Text = "UNDER PROCESS"
$Label1.AutoSize = $true
$Label1.Width = 25
$Label1.Height = 10
$Label1.Location = New-Object System.Drawing.Point(600,300)
$Label1.Font = 'Microsoft Sans Serif,30,style=Bold,Underline'
$Label1.ForeColor = "#d0021b"
$Label2 = New-Object System.Windows.Forms.Label
$Label2.Text = "WAITING"
$Label2.AutoSize = $true
$Label2.Width = 25
$Label2.Height = 10
$Label2.Location = New-Object System.Drawing.Point(770,500)
$Label2.Font = 'Microsoft Sans Serif,20,style=Bold'
$Label2.ForeColor = "#fb0505"
$Form.Controls.AddRange(#($Label1,$Label2))
# start the timer as soon as the dialog is visible
$Form.Add_Shown({ $timer.Start() })
[void]$Form.ShowDialog()
# clean up when done
$Form.Dispose()
And to call it from your other script, use:
$SN = "708TSTA"
$MAC = "2E5961370"
function Test-FileExists {
$file = Get-Item -Path "D:\*$SN-$MAC*"
if ($file) {
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $file.FullName
Attempts = 1
}
}
else {
& "D:\GUI.ps1" -Path "D:\*$SN-$MAC*" -MaxAttempts 3
}
}
# call the function that can call the GUI.ps1 script
Test-FileExists
# check the Global result object
if ($global:Result.Exists) {
Write-Host "File '$($global:Result.FileName)' Exists. Found after $($global:Result.Attempts) attempts." -ForegroundColor Green
}
else {
Write-Host "File not found after $($global:Result.Attempts) attempts." -ForegroundColor Red
}
Update
As per your comments, I understand that the calling script should show the form (which does nothing more that show on screen) AND is responsible for closing it after the file has been found.
The code below should do what you ask by defining the $Form as a global variable and by using the .Show() method of the form instead of ShowDialog():
GUI.ps1
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$global:Form = New-Object System.Windows.Forms.Form
$global:Form.ClientSize = '578,400'
$global:Form.Text = "Form"
$global:Form.BackColor = "#c1daf7"
$global:Form.WindowState = 'Maximized'
$global:Form.FormBorderStyle = "FixedDialog"
$global:Form.ControlBox = $false # hide sizing and close buttons
$global:Form.TopMost = $true
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Text = "UNDER PROCESS"
$Label1.AutoSize = $true
$Label1.Width = 25
$Label1.Height = 10
$Label1.Location = New-Object System.Drawing.Point(600,300)
$Label1.Font = 'Microsoft Sans Serif,30,style=Bold,Underline'
$Label1.ForeColor = "#d0021b"
$Label2 = New-Object System.Windows.Forms.Label
$Label2.Text = "WAITING"
$Label2.AutoSize = $true
$Label2.Width = 25
$Label2.Height = 10
$Label2.Location = New-Object System.Drawing.Point(770,500)
$Label2.Font = 'Microsoft Sans Serif,20,style=Bold'
$Label2.ForeColor = "#fb0505"
$global:Form.Controls.AddRange(#($Label1,$Label2))
# don't use ShowDialog() here because it will block the calling script
$global:Form.Show()
the calling script
function Test-FileExists {
[CmdletBinding()]
param (
[parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[string]$Path,
[string]$Pattern = '*.*'
)
$nAttempts = 1
$file = Get-ChildItem -Path $Path -Filter $Pattern -File | Select-Object -First 1
if (!$file) {
# show the GUI
& "D:\GUI.ps1"
do {
Start-Sleep -Seconds 1
$nAttempts++
Write-Verbose "Attempt No. $nAttempts"
$file = Get-ChildItem -Path $Path -Filter $Pattern -File | Select-Object -First 1
} until ($file)
# clean up the form
$global:Form.Dispose()
$global:Form = $null
}
Write-Verbose "File '$($file.FullName)' Exists. Found after $nAttempts attempt(s)."
return $true
}
$SN = "708TSTA"
$MAC = "2E5961370"
# call the function that can call the GUI.ps1 script
if (Test-FileExists -Path 'D:\SERVER\SHARE' -Pattern "*$SN-$MAC*" -Verbose) {
Write-Host "Found"
}
Hope that helps
I currently have a script that queries our AD for the users' AD attribute "Department".
Right now, the script will run "successfully" but all output for Textbox2 goes to the console instead of TextBox2.
If I change my function Get-CCUsers to be a query without variables, like Get-ADUser -Filter "Department -eq 19330" (we use numbers for our departments) then the output shows in TextBox2 as I want it to.
How can I get my function to populate TextBox2?
BTW, this script was cobbled together with my limited understanding, and there may well be superfluous or nonsense lines in here.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Howard Center Profile Migration'
$form.Size = New-Object System.Drawing.Size(800,650)
$form.StartPosition = 'CenterScreen'
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please enter the Cost Center # in the space below:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(100,20)
$form.Controls.Add($textBox)
$RunButton = New-Object System.Windows.Forms.Button
$RunButton.Location = New-Object System.Drawing.Point(75,120)
$RunButton.Size = New-Object System.Drawing.Size(75,23)
$RunButton.Text = 'RUN'
#$RunButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
<#$RunButton.Add_Click({
#add here code triggered by the event
$TextBox2.Text = Get-Process | Format-Table -Property ProcessName, Id, CPU -AutoSize | Out-String
})
#>
$form.AcceptButton = $RunButton
$form.Controls.Add($RunButton)
$label2 = New-Object System.Windows.Forms.Label
$label2.Location = New-Object System.Drawing.Point(10,70)
$label2.Size = New-Object System.Drawing.Size(280,20)
$label2.Text = 'When you are ready click the Run button below'
$form.Controls.Add($label2)
$TextBox2 = New-Object system.windows.Forms.TextBox
$TextBox2.Text = ""
$TextBox2.Multiline = $true
$TextBox2.BackColor = "#013686"
$TextBox2.ScrollBars = "Both"
$TextBox2.Width = 750
$TextBox2.Height = 450
$TextBox2.location = new-object system.drawing.point(10,150)
$TextBox2.Font = "Microsoft Sans Serif,10"
$TextBox2.ForeColor = "#ffffff"
$Form.controls.Add($TextBox2)
$form.Topmost = $true
function Get-CCUsers {
Write-Host "The textbox text is $textbox.Text"
$dept = $textBox.Text
$deptUsers = Get-ADUser -Filter "Department -eq $dept"
ForEach ($user in $deptUsers) {
IF ( ((get-aduser $user).enabled) -eq $True ) {
$UHomeDir = (Get-ADUser $user -Properties HomeDirectory).HomeDirectory
$UProfPath = (Get-ADUser $user -Properties ProfilePath).ProfilePath
Write-Host "$user, $UHomeDir, $UProfPath"
}
}
}
$RunButton.Add_Click({
$TextBox2.Text = Get-CCUsers
})
$TextBox2.Add_TextChanged({
$TextBox2.SelectionStart = $TextBox2.Text.Length
$TextBox2.ScrollToCaret()
})
$form.Add_Shown({$Form.Update()})
$result = $form.ShowDialog()
$global:x = $textBox.Text
# $x
# if ($result -eq [System.Windows.Forms.DialogResult]::OK)
#{
#}
I have made your script working changing the 'Get-CCUSers' function
function Get-CCUsers {
Write-Host "The textbox text is $textbox.Text"
$dept = $textBox.Text
$deptUsers = Get-ADUser -Filter "Department -eq '$dept'"
$res = #()
ForEach ($user in $deptUsers) {
IF ( ((get-aduser $user).enabled) -eq $True ) {
$UHomeDir = (Get-ADUser $user -Properties HomeDirectory).HomeDirectory
$UProfPath = (Get-ADUser $user -Properties ProfilePath).ProfilePath
$res += "$user, $UHomeDir, $UProfPath"
}
}
return $res
}
In short:
I removed the Write-Host (the output was actually redirected to stdout)
I added a $res in the function initialized as array
In the ForEach loop, results are added as items in the array
The $res is returned by the function, and then used $RunButton
I've created a form and dynamically added CheckBoxes and CheckBox names. How can I programmatically check one particular CheckBox from the Get-LicenseDetails function? Missing bracket has been added.
import-module MSOnline
Function Get-LicenseDetails {
Param ($upn)
$licenses = Get-MsolUser -UserPrincipalName $upn
ForEach ($license in $licenses.Licenses) {
If ($license.AccountSkuId -like '*ENTERPRISEPACK') {
$serviceName = $serviceStatus.ServicePlan.ServiceName
$checkBox.Checked = $true
}
}
}
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$System_Drawing_Point = New-Object System.Drawing.Point
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object Windows.Forms.Form
$form.Text = "Office 365 Licensing"
$form.Name = "Form1"
$form.Size = New-Object Drawing.Size #(316, 510)
#SEARCH BUTTON
$searchBtn = New-Object System.Windows.Forms.Button
$System_Drawing_Point.X = 226
$System_Drawing_Point.Y = 38
$searchBtn.Location = $System_Drawing_Point
$searchBtn.add_click({Get-LicenseDetails "user.name#domain.com"})
$searchBtn.Size = New-Object System.Drawing.Size(67, 23)
$searchBtn.Text = "Click Me"
$form.Controls.Add($searchBtn)
#CHECKBOXES
$y = 80
$Services = (Get-MsolAccountSku | Where-Object {$_.SkuPartNumber -eq "ENTERPRISEPACK"}).ServiceStatus.ServicePlan.ServiceName
ForEach ($service in $Services) {
$checkbox = New-Object System.Windows.Forms.CheckBox
$checkbox.Text = $service
$checkbox.Name = "CheckBox_$service"
$checkbox.Size = New-Object System.Drawing.Size(260,17)
$checkbox.Location = New-Object System.Drawing.Size(10,$y)
$y += 25
$form.Controls.Add($checkbox)
}
$drc = $form.ShowDialog()
First of all, you are missing a square Bracket where you load the System.Drawing Assembly.
You could access the CheckBox in the Get-LicenseDetails bei either passing them to the function or by accessing them using $global:. However, I wouldn't pass GUI elements to that function. Instead I would create a model (new object) and pass that to the Get-LicenseDetails method.
OK, I've figured it out. I used these lines in the function:
$checkBoxName = "CheckBox_" + $serviceName
$checkbox = $form.Controls | Where-Object {$_.name -eq $checkBoxName}
$checkbox.Checked = $true