enable Write-Verbose behavior in powershell script - powershell

In a powershell script file.ps1, I have
Write-Host "here is a host message"
Write-Verbose "here is a verbose message"
When file.ps1 is run in Windows Terminal using Powershell 7, not all messages are written to the console.
PS> .\file.ps1
here is a host message
I would like to be able to pass -Verbose so Write-Verbose is seen:
PS> .\file.ps1 -Verbose
here is a host message
here is a verbose message
What does script file.ps1 need to enable verbose messages?

You would need to add [cmdletbinding()] to your script to enable CommonParameters:
script.ps1
[cmdletbinding()]
param()
Write-Host "here is a host message"
Write-Verbose "here is a verbose message"
From host:
PS /> ./script.ps1 -Verbose
here is a host message
VERBOSE: here is a verbose message

If you can't edit the script, you can also user set the VerbosePrefrence to Continue in the shell that calls the script.
$VerbosePreference = "Continue"
This will enable Verbose output on all function you are goint to execute.
Check out Microsofts Help about Prefences.
There are many usefull more.
If you ike to enable Verbose Output for only a specific CmdLet, you can use $PSDefaultParameterValues to assign a default Parameter to this function:
$PSDefaultParameterValues.Add("MyCmdLet:Verbose",$true)
this would enable Verbose Output for "MyCmdLet".
However, be carefull when using $PSDefaultParameterValues, since you can really mess things up, especially if you call other script, since the default parameter values will there be affected aswell.

Related

How to generate comprehensive log file from PowerShell script

I am trying to write a migration/deployment script to deploy an application to an environment (DEV, QA, PROD) and I need to be able to fully log all output. This would include any status message I specifically put in the output stream (not a problem) as well as verbose output from all commands. For instance, if I'm calling Copy-Item, I want the full listing of each item copied.
I'm trying to figure out a way to do this throughout the entire script reliably. In other words, I don't want to rely on including -Verbose on every command (as it could be missed when someone else maintains the script in the future). I've been looking at things like $VerbosePreference as well as the possibility of calling my main cmdlet/function using -Verbose, with the hope being that either would apply to the entire script. But that appears to not be the case. While any Write-Verbose commands I use respect either approach, calls to Copy-Item only show the verbose listing if I specifically pass -Verbose to it. I'm really hoping I'm just missing something! Surely this is possible to do what I'm wanting!
Sample code:
function Main () {
[CmdletBinding()]
Param()
Begin {
Copy-Item C:\Temp\src\* -Destination C:\Temp\dest -Recurse -Force
Write-Output 'Main output'
Write-Verbose 'Main verbose'
Child
}
}
function Child () {
[CmdletBinding()]
Param()
Begin {
Copy-Item C:\Temp\src\* -Destination C:\Temp\dest -Recurse -Force
Write-Output 'Child output'
Write-Verbose 'Child verbose'
}
}
$VerbosePreference = 'SilentlyContinue'
Write-Output $VerbosePreference
Main
''
Main -Verbose
''
''
$VerbosePreference = 'Continue'
Write-Output $VerbosePreference
Main
''
Main -Verbose
Produces output:
SilentlyContinue
Main output
Child output
Main output
VERBOSE: Main verbose
Child output
VERBOSE: Child verbose
Continue
Main output
VERBOSE: Main verbose
Child output
VERBOSE: Child verbose
Main output
VERBOSE: Main verbose
Child output
VERBOSE: Child verbose
So, clearly $VerbosePreference and -Verbose are affecting the Write-Verbose, but that's about it. The Copy-Item is not displaying ANY output whatsoever (though it will if I specifically use -Verbose directly on that command).
Any thoughts? Am I going about this all wrong? Please help!
How about leveraging...
Tip: Create a Transcript of What You Do in Windows PowerShell
The PowerShell console includes a transcript feature to help you
record all your activities at the prompt. As of this writing, you
cannot use this feature in the PowerShell application. Commands you
use with transcripts include the following:
https://technet.microsoft.com/en-us/library/ff687007.aspx
... or the approaches provided / detailed here:
Enhanced Script Logging module (automatic console output captured to
file)
Automatically copy PowerShell console output to a log file (from
Output, Error, Warning, Verbose and Debug streams), while still
displaying the output at the console. Log file output is prepended
with date/time and an indicator of which stream originated the line
https://gallery.technet.microsoft.com/scriptcenter/Enhanced-Script-Logging-27615f85
Write-Log PowerShell Logging Function
The Write-Log PowerShell advanced function is designed to be a simple
logger function for other cmdlets, advanced functions, and scripts.
Often when running scripts one needs to keep a log of what happened
and when. The Write-Log accepts a string and a path to a log file and
ap
https://gallery.technet.microsoft.com/scriptcenter/Write-Log-PowerShell-999c32d0
* Update as per the OP comment*
See this discussion...
Powershell apply verbosity at a global level
where the -verbose flag is not supplied to the ni command. Is there a
way to set the Verbosity at a global PSSession level if I were to run
this script to force verbosity? The reason I ask is that I have a
group of about 60 scripts which are interdependent and none of these
supply -verbose to any commands they issue and I'd like to see the
entire output when I call the main entry point powershell script.
Powershell apply verbosity at a global level
Use PowerShell Default Parameter Values to Simplify Scripts
Changing default parameter values
When I was asked to write about my favorite Windows PowerShell 3.0
feature, my #1 $PSDefaultParameterValues came to mind immediately.
From my point of view, this was something I was looking for, for a
long time.
How does it work? With $PSDefaultParameterValues, you can define
(overwrite) default values of parameters for Windows PowerShell
cmdlets.
https://blogs.technet.microsoft.com/heyscriptingguy/2012/12/03/use-powershell-default-parameter-values-to-simplify-scripts/
See also:
Script Tracing and Logging
While Windows PowerShell already has the LogPipelineExecutionDetails
Group Policy setting to log the invocation of cmdlets, PowerShell’s
scripting language has plenty of features that you might want to log
and/or audit. The new Detailed Script Tracing feature lets you enable
detailed tracking and analysis of Windows PowerShell scripting use on
a system. After you enable detailed script tracing, Windows PowerShell
logs all script blocks to the ETW event log,
Microsoft-Windows-PowerShell/Operational. If a script block creates
another script block (for example, a script that calls the
Invoke-Expression cmdlet on a string), that resulting script block is
logged as well.
Logging of these events can be enabled through the Turn on PowerShell
Script Block Logging Group Policy setting (in Administrative Templates
-> Windows Components -> Windows PowerShell).
https://learn.microsoft.com/en-us/powershell/wmf/5.0/audit_script

See PowerShell Verbose output in Visual Studio Code

I am using Visual Studio Code 1.17.2 with the PowerShell extension (1.4.3). I have Write-Verbose statements in my code. When I run the PowerShell script, the Verbose output doesn't seem to go anywhere. How do I request that output be shown?
The simplest approach is to execute:
$VerbosePreference = 'Continue'
in the integrated PowerShell console before invoking your script (and executing $VerbosePreference = 'SilentlyContinue' later to turn verbose output back off, if needed).
From that point on:
running a script (starting it with (F5) or without (Ctrl+F5) the debugger)
highlighting a section of code and running the selection (F8)
will make Write-Verbose calls produce output.
If you want to preset $VerbosePreference = 'Continue' every time the integrated console starts, put that statement in the $PROFILE file:
If your VS Code-specific $PROFILE file already exists, simply run psedit $PROFILE from the integrated console.
If not, create the file first from the integrated console: New-Item -Type File $PROFILE
Verbose output by default it not shown, you need to declare [CmdletBinding()] in your function or script to enable the -Verbose parameter to be passed through in order have the option to display Verbose output.
You can 'cheat' though and pass -Verbose to Write-Verbose "Hello Verbose" -Verbose itself and that stream will appear in the console.
(Tested with your two matching versions for VSCode and Extension on Mac (PS6 Beta 8) and can see the verbose output).
function Test-Verbose {
# This enables the function to have '-Verbose'.
[CmdletBinding()]
param()
Write-Output "Hello output!"
# Will only be displayed if 'Test-Verbose' is passed '-Verbose'.
Write-Verbose "Hello verbose"
}
Test-Verbose -Verbose

Write-output when executing script in a wpf event script

I have a script that accepts lots of parameters and is fairly big. I've been asked to build a GUI for executing the script, so users can easily execute the script without making mistakes. So the idea was that the GUI script collects all the parameters, and then executes the script.
The "main" script uses write-output and start-transcript for logging to the shell and to a file. This also works.
But when I execute the script from the GUI script I'm not getting every output to the shell or to the log. I figured that this is because of write-output because Write-Host does work, but everywhere I go I hear people say that you shouldn't use write-host (for instance: https://youtu.be/SSJot1ycM70?t=24m1s).
So how do I get this to work?
Currently I use this to execute the script from the gui:
& $PSscriptroot\guitest2.ps1 -switchparam1:$localvar1 -switchparam2:$localvar2 -stringparam $localvar3
I have tried to run a new instance of powershell via cmd, but I don't seem to get this to work. I have also no idea how to "send" the parameters to the script this way.
Invoke-Expression 'cmd /c powershell.exe -file C:\...\script.ps1 -paramters.
or
Invoke-Expression 'cmd /c powershell.exe -command {C:\..\script.ps1 -paramters..}
The two scripts below do exactly what I want. But when I execute the script in a wpf event (ie after the start button has been pressed) the second script only shows the write-warning, write-error and write-host output, so not the write-output.
script1:
#gui script
$boolean = $true
$string = "test"
& $PSscriptroot\script2.ps1 -switch:$boolean -string $string
script2:
param(
[switch]$switch,
[string]$string
)
Start-Transcript
write-output "output"
write-host "host"
$a = "Variable"
$a
write-error "error"
Write-Warning "warning"
Write-Debug "debug"
Stop-Transcript
EDIT:
did some more testing. Apparently write-output completely doesn't work when called in a wpf event. For example:
$wpf.startButton.Add_Click({
write-output "This message is not shown"
})
Not sure if this is a bug or not
Write-Output passes an object through the pipeline to another command. Essentially the statement
Write-Output <expression>
is in many cases exactly identical to
<expression>
Other Write-* cmdlets behave a bit differently. In your case you have an event handler, which has no return value anyway. Your example is the same as
"This message is not shown"
or even
return "This message is not shown"
As the string is part of the return value of that script block, which no one ever looks at.
If you want output in the host application, use Write-Host. That's what it's for. Write-Output is something you rarely, if ever, need in a script.

Pass argument into Powershell

I have a powershell script that completes some tasks in Active Directory and MS Exchange. I need to pass in the Active Directory username from our call logging system. Having the Call log system pass the argument is simple.
The problem i am facing is having powershell read the argument into a variable.
I will provide a proof of concept example.
Here is a sample command passing the argument into powershell.
C:\Users\UserName\Desktop\Test.ps1 -ADusername "Hello World"
Here is the sample script:
Param([string]$adusername)
$adusername
pause
I am Expecting the following output:
Hello World
Press Enter to continue...:
This is the actual output:
Press Enter to continue...:
Just wrapping my head around this core concept will help me immensely. I was unable to find any examples or tutorials that worked when applied to my scenario. I apologize if this is a duplicate post, couldnt find anything on this site as well.
EDIT: per request, this is my full script: http://pastebin.com/ktjpLQek
I think you will have much better luck if you avoid trying to use params and call the script exactly that way.
It is possible, but paramaters work better if you either inline the scriptfile like:
. .\scriptFile.ps1
function "Hello World"
Staying closer to what you are doing however, you should be using $args and calling PowerShell (the exe directly)
If you call your scriptfile like: (I used the runbox)
powershell c:\Path\Folder\Script.ps1 "Hello World!"
and then replace your Param([string]$adusername) with:
$adUserName = $args[0]
write-host $adUserName
Additionally, this should work for you (to dissect):
Param([string]$ad)
Write-Host $args[0]
Write-Host $ad
Read-Host
pause
Call the script with the path,
powershell c:\Path\Folder\Script.ps1 "Hello World!" $ad = "JSmith"
If this does not work, you should ensure that your execution policy is set correctly. Get-ExecutionPolicy will tell you the current level. For testing you can set it very low with Set-ExecutionPolicy unrestricted
Add the following to the top of your script.
Param(
[Parameter(Mandatory=$true)]
[string]$Euser
)
Write-Host "Deactivating $EUser"
Calling example after cd to the script directory
.\ScriptName.ps1 -Euser "FOO" # Tab auto completion works
The following in a new script works for me.
Param([string]$servers)
"You chose $servers"
PS C:\scripts> .\Untitled1.ps1 "this test"
You chose this test
PS C:\scripts>

Powershell script support for -verbose

I'm creating a .ps1 script which invokes Write-Verbose. I would like to be able to enable/disable these.
I was hoping that I could pass the -Verbose flag when invoking the script and everything would just work. Unfortunately this doesn't seem to be the case.
The verbose messages are not written out to the host. I looked around a bit and found Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!
But this is from 2007 and the PS team member stated that they were looking for built in support in PS v2.
Anybody have any updates on this or do we have to use the same technique described in that blog post?
Here is an example of the current behavior.
I created a simple script,ex01.ps1, with the following.
Write-Host "line 1"
Write-Verbose "line 2"
Write-Host "line 3"
I first executed the script with .\ex01.ps1, and only 1 & 2 were printed as expected. Then I executed it with .\ex01.ps1 -verbose, and got the same result. I was expecting all 3 lines to be printed the second time.
In order to have the Verbose switch you need to specify the CmdletBinding attribute in your script. To add support for the Confirm and WhatIf switches, add the SupportsShouldProcess attribute and call the ShouldProcess method in the script:
## content of .\ex01.ps1 ##
[CmdletBinding(SupportsShouldProcess=$true)]
Param()
Write-Host "line 1"
Write-Verbose "line 2"
Write-Host "line 3"
if($PSCmdlet.ShouldProcess($env:COMPUTERNAME,'Remove X'))
{
"do something"
}
###########################
PS > .\ex01.ps1
line 1
line 3
PS > .\ex01.ps1 -Verbose
line 1
VERBOSE: line 2
line 3
PS > .\ex01.ps1 -WhatIf
line 1
line 3
What if: Performing operation "Remove X" on Target "PC1".
i'm a powershell beginner but this just tripped me up:
if your script doesn't have any parameters the verbose switch won't be passed through. just put this at the top of your script:
[CmdletBinding()]
Param()
so your script would be:
[CmdletBinding()]
Param()
Write-Host "line 1"
Write-Verbose "line 2"
Write-Host "line 3"
You shoul have a look to Advanced Functions : With Advanced functions you can take advantage of the common -verbose parameter. Simply output your verbose output this way:
Write-Verbose "Text of debug"
And when the shell's $VerbosePreference variable isn't set to "SilentlyContinue" ("Continue" will enable the output), you'll see your verbose output.
This Windows IP Pro Article Part1 and spcialy Part2 discribes what else you can do with advanced functions. You can also find a step by step guide in A guide to PowerShell’s Advanced Functions