Blowfelt82
asked on
Add logging to form generated by powershell script.
I have a powershell script which includes a 'WriteToLog' function which basically just writes data to the output stream using the 'Write-Output' cmdlet. This used to work without any issue, however I have since introduced a custom form which is built by the script and displayed using the 'ShowDialog' cmdlet - once the form is displayed any calls to the 'WriteToLog' function do not seem to work any more?
Note: I have proven that the form is calling the 'WriteToLog' function successfully, but the 'Write-Output' is no longer working as expected. I reckon this is because the output is being sent to the output stream of the form and not the calling script but this is a complete guess.
So any ideas how I can dynamically get the output from a generated form in Powershell.
I assume this is because the
Note: I have proven that the form is calling the 'WriteToLog' function successfully, but the 'Write-Output' is no longer working as expected. I reckon this is because the output is being sent to the output stream of the form and not the calling script but this is a complete guess.
So any ideas how I can dynamically get the output from a generated form in Powershell.
I assume this is because the
Can you post the script and point out where it stops outputting (if possible)?
ASKER
Unfortunately the script is on a secure server and I have no way of copying the scripts - sorry to be so unhelpful! I will try and get a rough draft of the code up ASAP.
ASKER
Ok here is a very rough draft of the problem - at least recreates the problem I am facing:
On my environment the log outputs Test 1 and Test 2 which are both outside the 'scope' of the GUI button event handler, this is correct. But the other tests originating from within the event handler code and/or the function it calls are not output? I have added the 'Writing to Log' message to prove that the Log function is being called correctly - which it is... Just looks as though the Write-Output cmdlet does not work correctly (or how I would like) when called via the GUI's event handler. Hopefully that should be enough - let me know if not!
Function Log
{
[CmdletBinding()]
Param ([Parameter(Mandatory=$true)][AllowEmptyString()][string]$LogMessage)
Process{
Write-Host "Writing to Log:"
Write-Output $LogMessage
}
}
$objAForm = New-Object System.Windows.Forms.Form
$objBForm = New-Object System.Windows.Forms.Form
Function TestFunction()
{
Log "Test: In Function"
}
Function GenerateForm
{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# define WinForm object size variables
$frmASizeHeight = 180
$frmASizeWidth = 250
$objATreeViewHeight = 250
$objATreeViewWidth = 250
$objANextButtonX = 127
$objANextButtonY = 115
$objACancelButtonX = 37
$objACancelButtonY = 115
$objAButtonDimX = 80
$objAButtonDimY = 24
$returnValue = 0
# create a Windows Form object
$objAForm.Text = "FORM 1"
$objAForm.Size = New-Object System.Drawing.Size($frmASizeWidth, $frmASizeHeight)
$objAForm.KeyPreview = $True
$objAForm.ControlBox = $True
# Buttons
$objACancelButton = New-Object System.Windows.Forms.Button
$objACancelButton.Location = New-Object System.Drawing.Size($objACancelButtonX, $objACancelButtonY)
$objACancelButton.Size = New-Object System.Drawing.Size($objAButtonDimX,$objAButtonDimY)
$objACancelButton.FlatStyle = "Flat"
$objACancelButton.Text = "Cancel"
$objACancelButton.Add_Click(
{
$objAForm.Close() | Out-Null
})
Log "Test 1"
$objANextButton = New-Object System.Windows.Forms.Button
$objANextButton.Location = New-Object System.Drawing.Size($objANextButtonX, $objANextButtonY)
$objANextButton.Size = New-Object System.Drawing.Size($objAButtonDimX,$objAButtonDimY)
$objANextButton.FlatStyle = "Flat"
$objANextButton.Text = "Next"
$objANextButton.Add_Click(
{
TestFunction
Log "Test 2"
})
Log "Test 3"
$objAForm.Controls.Add($objACancelButton)
$objAForm.Controls.Add($objANextButton)
# Display form
[void]$objAForm.ShowDialog()
}
GenerateForm
On my environment the log outputs Test 1 and Test 2 which are both outside the 'scope' of the GUI button event handler, this is correct. But the other tests originating from within the event handler code and/or the function it calls are not output? I have added the 'Writing to Log' message to prove that the Log function is being called correctly - which it is... Just looks as though the Write-Output cmdlet does not work correctly (or how I would like) when called via the GUI's event handler. Hopefully that should be enough - let me know if not!
ASKER
Edit the above should read: Test 1 and Test 3
Ah, I see. You'll need to set a variable since that is not in the stream.
ASKER
Could you provide an example with the code above, not sure exactly what is involved
Here's a rudimentary example.
Function Log
{
[CmdletBinding()]
Param ([Parameter(Mandatory=$true)][AllowEmptyString()][string]$LogMessage)
Process{
Write-Host "Writing to Log:"
$LogMessage
}
}
$objAForm = New-Object System.Windows.Forms.Form
$objBForm = New-Object System.Windows.Forms.Form
Function TestFunction()
{
Log "Test: In Function"
}
Function GenerateForm
{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# define WinForm object size variables
$frmASizeHeight = 180
$frmASizeWidth = 250
$objATreeViewHeight = 250
$objATreeViewWidth = 250
$objANextButtonX = 127
$objANextButtonY = 115
$objACancelButtonX = 37
$objACancelButtonY = 115
$objAButtonDimX = 80
$objAButtonDimY = 24
$returnValue = 0
# create a Windows Form object
$objAForm.Text = "FORM 1"
$objAForm.Size = New-Object System.Drawing.Size($frmASizeWidth, $frmASizeHeight)
$objAForm.KeyPreview = $True
$objAForm.ControlBox = $True
# Buttons
$objACancelButton = New-Object System.Windows.Forms.Button
$objACancelButton.Location = New-Object System.Drawing.Size($objACancelButtonX, $objACancelButtonY)
$objACancelButton.Size = New-Object System.Drawing.Size($objAButtonDimX,$objAButtonDimY)
$objACancelButton.FlatStyle = "Flat"
$objACancelButton.Text = "Cancel"
$objACancelButton.Add_Click(
{
$objAForm.Close() | Out-Null
})
Log "Test 1"
$objANextButton = New-Object System.Windows.Forms.Button
$objANextButton.Location = New-Object System.Drawing.Size($objANextButtonX, $objANextButtonY)
$objANextButton.Size = New-Object System.Drawing.Size($objAButtonDimX,$objAButtonDimY)
$objANextButton.FlatStyle = "Flat"
$objANextButton.Text = "Next"
$objANextButton.Add_Click(
{
TestFunction
$global:testResults = Log "Test 2"
})
Log "Test 3"
$objAForm.Controls.Add($objACancelButton)
$objAForm.Controls.Add($objANextButton)
# Display form
[void]$objAForm.ShowDialog()
}
GenerateForm
#results of test 2
Write-Output $testResults
ASKER
Unfortunately I am not sure this solution is what I need, the logging is only updated when the form is closed - and only handles a single line of output. I need a way to dynamically log from the event handler if possible?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for your help, not the way I wanted it to work but managed to get logging working by using a global variable to capture the GUI input and then perform the processing outside of the form scripting as per your recommendation. Thanks for your help.