Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public sealed class WriteProgressCommand : PSCmdlet
/// </summary>
[Parameter(
Position = 0,
Mandatory = true,
HelpMessageBaseName = HelpMessageBaseName,
HelpMessageResourceId = "ActivityParameterHelpMessage")]
public string Activity { get; set; }
Expand Down Expand Up @@ -96,7 +95,29 @@ protected override
void
ProcessRecord()
{
ProgressRecord pr = new(Id, Activity, Status);
ProgressRecord pr;
if (string.IsNullOrEmpty(Activity))
{
if (!Completed)
{
ThrowTerminatingError(new ErrorRecord(
new ArgumentException("Missing value for mandatory parameter.", nameof(Activity)),
"MissingActivity",
ErrorCategory.InvalidArgument,
Activity));
return;
}
else
{
pr = new(Id);
pr.StatusDescription = Status;
}
}
else
{
pr = new(Id, Activity, Status);
}

pr.ParentActivityId = ParentId;
pr.PercentComplete = PercentComplete;
pr.SecondsRemaining = SecondsRemaining;
Expand Down
27 changes: 25 additions & 2 deletions src/System.Management.Automation/engine/ProgressRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ class ProgressRecord
this.status = statusDescription;
}

/// <summary>
/// Initializes a new instance of the ProgressRecord class and defines the activity Id.
/// </summary>
/// <param name="activityId">
/// A unique numeric key that identifies the activity to which this record applies.
/// </param>
public
ProgressRecord(int activityId)
{
if (activityId < 0)
{
// negative Ids are reserved to indicate "no id" for parent Ids.

throw PSTraceSource.NewArgumentOutOfRangeException(nameof(activityId), activityId, ProgressRecordStrings.ArgMayNotBeNegative, "activityId");
}

this.id = activityId;
}

/// <summary>
/// Cloning constructor (all fields are value types - can treat our implementation of cloning as "deep" copy)
/// </summary>
Expand Down Expand Up @@ -488,9 +507,13 @@ internal static ProgressRecord FromPSObjectForRemoting(PSObject progressAsPSObje
/// <returns>This object as a PSObject property bag.</returns>
internal PSObject ToPSObjectForRemoting()
{
PSObject progressAsPSObject = RemotingEncoder.CreateEmptyPSObject();
// Activity used to be mandatory but that's no longer the case.
// We ensure the string has a value to maintain compatibility with older versions.
string activity = string.IsNullOrEmpty(Activity) ? " " : Activity;

progressAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ProgressRecord_Activity, this.Activity));
PSObject progressAsPSObject = RemotingEncoder.CreateEmptyPSObject();

progressAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ProgressRecord_Activity, activity));
progressAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ProgressRecord_ActivityId, this.ActivityId));
progressAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ProgressRecord_StatusDescription, this.StatusDescription));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe "Write-Progress DRT Unit Tests" -Tags "CI" {
It "Should be able to throw exception when missing mandatory parameters" {
{ Write-Progress $null } | Should -Throw -ErrorId 'ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.WriteProgressCommand'
}

It "Should be able to throw exception when running Write-Progress with bad percentage" {
{ Write-Progress -Activity 'myactivity' -Status 'mystatus' -percent 101 } |
Should -Throw -ErrorId 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.WriteProgressCommand'
Expand Down Expand Up @@ -33,4 +29,8 @@ Describe "Write-Progress DRT Unit Tests" -Tags "CI" {
{ Write-Progress -Activity $activity -Status ('b' * ([console]::WindowWidth + 1)) -Id 1 } | Should -Not -Throw
Write-Progress -Activity $activity -Id 1 -Completed
}

It 'Should be able to complete a progress record with no activity specified' {
{ Write-Progress -Completed } | Should -Not -Throw
}
}