I have a script that I will run it in production env.
My question is there any way to collect all output from the scipt is launched?
Since you can redirect most streams when calling a .ps1 script (as I showed earlier), that script should be ok.
Just two remarks:
- if you are using PSv5 or higher, I would replace all Write-Host instances with Write-Information
- since Read-Host input is not echoed, I would avoid using that.
An alternative is to use the build-in prompt for mandatory parameters.
Param(
[Parameter(Mandatory=$true,
HelpMessage="Enter a value")]
[int]$Value
)
When running this, it will prompt with
That also allows you to run the script from another script or as a scheduled task.
You just the parameter along on the invocation of the script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Please see whether Start-Transcript (Microsoft.PowerShell.Host) - PowerShell | Microsoft Docs is what you are looking for.
André
It is not clear to me if you want to capture output from a script that is already running or from a script that you will start (and can change)?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
not sure if what I will explain can clarify what I would like to capture,
the script will start and ask for vcenter FQDN, login,password, and it will do some stuff like changing advanced parametres...
once the script is finished all what was done should be collected in output file
something like this:
29.06.2018 16:52:53 INFO Get script parameters K:\script\script.ps1
29.06.2018 16:52:53 INFO Get credential: admin@lab.local
29.06.2018 16:52:53 INFO Connect to vCenter server: vcenter1
29.06.2018 16:53:24 INFO Connect to vcenter done
29.06.2018 16:53:24 INFO ESXi Change
29.06.2018 16:53:41 INFO ESX NAME: ESXi1
29.06.2018 16:53:42 ERROR PARAMETER CHANGE FAILED: +details
29.06.2018 16:53:52 INFO ESX NAME: ESXi2
The Start-Transcript will capture all output, provided you set some preference variables in the script.
Also note that since PSv5, the input entered on Read-Host is NOT echoed to the transcript file anymore.
$DebugPreference = 'Continue'
$VerbosePreference = 'Continue'
$InformationPreference = 'Continue'
$test = Read-Host
Invoke-Expression -Command 'cmd /c echo stdoutCMD'
Write-Output 'Stdout'
Write-Warning -Message 'Warning'
Write-Debug -Message 'Debug'
Write-Verbose -Message 'Verbose'
Write-Information -MessageData 'Info'
Write-Host 'Console'
Write-Error -Message 'Error'
throw 'Exception'
Stop-Transcript
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you LucD
below is the script that I have created, it will include other lines for Hardening ESXi nodes, like what I have made in this script it collect the info into logs file, my question is :
could you please check the same to confirm if it's a right way to continue working on thius script like the structure that I'm using?
is there any smarter way to have something in the script to collect all output session?
$StartTime = Get-Date
if (-not (Test-Path '.\Reports-ESXi')) { New-Item -Path '.\Reports-ESXi' -ItemType Directory -Force | Out-Null }
$reportHardening= ".\Reports-ESXi"
if (-not (Test-Path '.\Reports-LOGs')) { New-Item -Path '.\Reports-LOGs' -ItemType Directory -Force | Out-Null }
$reportLOGs= ".\Reports-LOGs"
$dateF = Get-Date -UFormat "%d-%b-%Y_%H-%M-%S"
$PathESXi = "$reportHardening\$dateF"
$PathLOGs = "$reportLOGs\$dateF"
$LogFile = "$PathLOGs\Start-Script.log"
$dateF | Out-File $LogFile -Encoding "UTF8" -Force
function Reports-Module-Check ($m) {
# If module is imported say that and do nothing
if (Get-Module | Where-Object {$_.Name -eq $m}) {
write-host "Module $m " -f Magenta -NoNewLine
write-host "is already imported." -f Green
"$(Get-date) Module $m is already imported" | Out-File $LogFile -Append -Encoding "UTF8" -Force
} else {
# If module is not imported, but available on disk then import
Write-Warning "Module $m is NOT imported (must be installed before starting)."
"$(Get-date) Module $m is NOT imported (must be installed before starting)" | Out-File $LogFile -Append -Encoding "UTF8" -Force
if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $m}) {
Import-Module $m -Verbose
} else {
# If module is not imported, not available on disk, but is in online gallery then install and import
if (Find-Module -Name $m | Where-Object {$_.Name -eq $m}) {
Install-Module -Name $m -Force -Verbose -Scope CurrentUser
Import-Module $m -Verbose
} else {
# If module is not imported, not available and not in online gallery then abort
Write-Warning "Module $m not imported, not available and not in online gallery, exiting."
"$(Get-date) Module $m not imported, not available and not in online gallery, exiting." | Out-File $LogFile -Append -Encoding "UTF8" -Force
EXIT 1
}
}
}
}
Reports-Module-Check "CredentialManager"
Reports-Module-Check "VMware.PowerCLI"
function Reports-Folder-Check ($dir) {
if(!(Test-Path -Path $report\$dir )){
New-Item -ItemType directory -Path $report\$dir
Write-Host "New Reports-ESXi folder created" -f Magenta
"$(Get-date) New Reports-ESXi folder created" | Out-File $LogFile -Append -Encoding "UTF8" -Force
New-Item -Path $report\$dir -Name $dateF -ItemType "directory"
Write-Host "New Work folder created" -f Magenta
"$(Get-date) New Work folder created" | Out-File $LogFile -Append -Encoding "UTF8" -Force
}
else{
Write-Host "Reports-ESXi Folder already exists" -f Green
"$(Get-date) Reports-ESXi Folder already exists" | Out-File $LogFile -Append -Encoding "UTF8" -Force
New-Item -Path $report\$dir -Name $dateF -ItemType "directory"
Write-Host "New Work folder created" -f Magenta
"$(Get-date) New Work folder created" | Out-File $LogFile -Append -Encoding "UTF8" -Force
}
}
Reports-Folder-Check "Reports-ESXi"
#################################
# vSphere Targeting Variables #
#################################
$vCenterList = Read-Host 'Enter vCenter FQDN or IP'
$username = Read-Host 'Enter The vCenter Username'
$password = Read-Host 'Enter The vCenter Password' -AsSecureString
$vccredential = New-Object System.Management.Automation.PSCredential ($username, $password)
Since you can redirect most streams when calling a .ps1 script (as I showed earlier), that script should be ok.
Just two remarks:
- if you are using PSv5 or higher, I would replace all Write-Host instances with Write-Information
- since Read-Host input is not echoed, I would avoid using that.
An alternative is to use the build-in prompt for mandatory parameters.
Param(
[Parameter(Mandatory=$true,
HelpMessage="Enter a value")]
[int]$Value
)
When running this, it will prompt with
That also allows you to run the script from another script or as a scheduled task.
You just the parameter along on the invocation of the script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD
I got the first point to replace all Write-Host instances with Write-Information, unfortunately I'm totaly lost regarding the second point to avoid using Read-Host :smileyblush::smileyblush:
could you please assist me on this? as this is the first part of a long script that will be created and I prefere to devellop it in smart way and with good best practice
There are a couple of drawbacks with Read-Host as far as I'm concerned.
- the value you enter on a Read-Host prompt is not echoed to a Transcript file (since PSv5)
- Read-Host is intended for 'interactive' scripts. If you intend to use your script as a Scheduled Task or a background job (Start-Job), it is not too obvious to provide the replies to these Read-Host prompts.
The alternative is to replace those Read-Host lines with actual parameters to the script (Param line).
That way it is easy to provide values when running the script as a Scheduled Task or as a background job.
Even when you run your script interactively, you can still get prompted for a value if you define the parameter as Mandatory.
And you provide a meaningful prompt (after typing !? at the prompt) via the HelpMessage parameter on the param definition.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks for your help and clarification, for sure this script will be used interactively, never as a scheduled task or a background task
Thanks again for your help