Author Posts

January 1, 2012 at 12:00 am

by scottbass at 2013-04-07 22:59:42

Hi,

Here is an excerpt from a script:

[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact="High"
)]
Param(
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$false,
ValueFromPipelineByPropertyName=$false
)]
[String[]] $dirs
)

...

foreach ($dir in $delsasdirs) {
if ($PSCmdlet.ShouldProcess(
"$dir","Remove-Item"))
{
try {
Remove-Item $dir.Fullname `
-Recurse `
-Verbose:($PSBoundParameters.Verbose -eq $true) `
-ErrorAction "Continue"
}
catch {
Write-Error "$_"
}
}
}

When I just run the script within a Powershell console window, all is well. Example invocations:

.\cleanwork.ps1 -dirs F:\SASWork, F:\SASUtil # directories are silently deleted
.\cleanwork.ps1 -dirs F:\SASWork, F:\SASUtil -debug # displays low level details of what directories are to be deleted
.\cleanwork.ps1 -dirs F:\SASWork, F:\SASUtil -confirm # requests confirmation on whether to delete the directory
.\cleanwork.ps1 -dirs F:\SASWork, F:\SASUtil -whatif # displays which directories would be deleted

However, this needs to be a scheduled task (Windows Server 2008), and I want any console input captured in a log, so the invocation string is:

powershell -ExecutionPolicy Unrestricted -Command ".\cleanwork.ps1 -dirs F:\SASWork, F:\SASUtil -debug > .\cleanwork.log 2>&1"
where the current directory is the directory containing the script.

When I run this invocation string, I'm always getting asked to confirm the deletion of the directories.

I'm thinking the issue is the interaction of ConfirmImpact and $ConfirmPreference. I've tried:

[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact="High"
)]

with values of "High", "Medium", and "Low", but I always get asked to confirm the Remove-Item command. This of course hangs the scheduled task.

Any thoughts?

Thanks,
Scott

by happysysadm at 2013-04-08 06:47:22

Hi Scott,

maybe it won't help you, but why don't you use the -Force parameter?

Carlo

by scottbass at 2013-04-08 17:51:27

Hi,

I've solved this issue. My problem was "overloading" the -debug switch.

I had this code to write diagnostic information to the console, to trace some internal logic:

if ($PSBoundParameters.Debug) {
$fmt=@{Expression={$_.ID};Label="SAS Process ID";width=20},@{Expression={"{0:X8}" -f $_.ID};Label="SAS Process ID (hex)";width=20}
$line="================================================================="
"SAS Work/Utility Directories Found:"
$allsasdirs | Format-Table -Property Fullname -AutoSize
$line
"SAS Process IDs:"
$pids | Format-Table $fmt -AutoSize
$line
"SAS Work/Utility Directories with Active SAS Process:"
$matchsasdirs | Format-Table -Property Fullname -AutoSize
$line
"SAS Work/Utility Directories to be deleted:"
$delsasdirs | Format-Table -Property Fullname -AutoSize
}

TBH, I'm not sure why testing the direct call of the script in the console window did not pick up this problem. Perhaps I just forgot to test the -debug switch in that scenario.

You can test this easily enough:

Remove-Item c:\temp\foo.txt -confirm
Remove-Item c:\temp\foo.txt -debug

I'm not sure why -debug gives the same behaviour as -confirm? Help about_commonparameters yields:

[quote] -Debug[:{$true | $false}]

Displays programmer-level detail about the operation performed by the
command. This parameter works only when the command generates
a debugging message. For example, this parameter works when a command
contains the Write-Debug cmdlet.

The Debug parameter overrides the value of the $DebugPreference
variable for the current command. Because the default value of the
$DebugPreference variable is SilentlyContinue, debugging messages
are not displayed by default.

Valid values:

$true (-Debug:$true). Has the same effect as -Debug.

$false (-Debug:$false). Suppresses the display of debugging
messages when the value of the $DebugPreference is not
SilentlyContinue (the default).[/quote]

So I guess it's setting $DebugPreference within the script, which propagates to the Remove-Item command.

Anyway, I added a switch parameter of -details and changed the above logic, and the problem went away. The end user can call the script with -details instead of -debug if they want to review the internal logic before deciding to actually execute this (potentially destructive) script.

Regards,
Scott