Skip to content

Commit 10c11f2

Browse files
authored
fix: Fix missing Name in Get-ItemState default formatter (#153)
1 parent 727450c commit 10c11f2

File tree

9 files changed

+115
-40
lines changed

9 files changed

+115
-40
lines changed

MilestonePSTools/MilestonePSTools.Format.ps1xml

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,39 +72,32 @@
7272
<TableControl>
7373
<TableHeaders>
7474
<TableColumnHeader>
75-
<Label>Name</Label>
76-
<Width>25</Width>
75+
<Width>36</Width>
7776
</TableColumnHeader>
7877
<TableColumnHeader>
79-
<Label>ItemType</Label>
8078
<Width>10</Width>
8179
</TableColumnHeader>
8280
<TableColumnHeader>
8381
<Width>18</Width>
8482
</TableColumnHeader>
8583
<TableColumnHeader>
86-
<Label>Id</Label>
8784
<Width>36</Width>
8885
</TableColumnHeader>
8986
</TableHeaders>
9087
<TableRowEntries>
9188
<TableRowEntry>
9289
<TableColumnItems>
9390
<TableColumnItem>
94-
<ScriptBlock>
95-
($_ | Get-PlatformItem).Name
96-
</ScriptBlock>
91+
<PropertyName>Name</PropertyName>
9792
</TableColumnItem>
9893
<TableColumnItem>
99-
<ScriptBlock>
100-
[VideoOS.Platform.Kind]::DefaultTypeToNameTable[$_.FQID.Kind]
101-
</ScriptBlock>
94+
<PropertyName>ItemType</PropertyName>
10295
</TableColumnItem>
10396
<TableColumnItem>
10497
<PropertyName>State</PropertyName>
10598
</TableColumnItem>
10699
<TableColumnItem>
107-
<ScriptBlock>$_.FQID.ObjectId</ScriptBlock>
100+
<PropertyName>Id</PropertyName>
108101
</TableColumnItem>
109102
</TableColumnItems>
110103
</TableRowEntry>

MilestonePSTools/Public/VideoOS/Get-VmsVideoOSItem.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
# limitations under the License.
1414

1515
function Get-VmsVideoOSItem {
16-
[CmdletBinding()]
16+
[CmdletBinding(DefaultParameterSetName = 'GetItemByFQID')]
1717
[OutputType([VideoOS.Platform.Item])]
1818
[RequiresVmsConnection()]
1919
param(
20-
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'GetItemByFQID')]
20+
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'GetItemByFQID')]
2121
[VideoOS.Platform.FQID]
2222
$Fqid,
2323

@@ -29,7 +29,7 @@ function Get-VmsVideoOSItem {
2929
[guid]
3030
$Id,
3131

32-
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'GetItem')]
32+
[Parameter(Mandatory, ParameterSetName = 'GetItem')]
3333
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'GetItems')]
3434
[ArgumentCompleter([KindArgumentCompleter])]
3535
[KindNameTransform()]

docs/changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ hide:
77

88
## [vNext] unreleased
99

10+
### 🐛 Fixed
11+
12+
- **`Get-ItemState`** output was no longer populating names for `ItemState` records in the terminal output. Now item
13+
names are correctly retrieved, and `Name`, `ItemType`, and `Id` values are added to the `ItemState` object as note
14+
properties making them easy to access programmatically and not just showing the values in the terminal when displayed
15+
with the default formatter. We also will now hide `Event` items in the response, and `Server` item types without names
16+
as well. These all tend to be user-defined events, generic events, and built-in system events that aren't useful
17+
output.
18+
1019
## [25.2.21] 2026-01-14
1120

1221
### 🔄 Changed

docs/commands/en-US/Get-ItemState.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,16 @@ Gets the ItemState of all known items in the site
1414
## SYNTAX
1515

1616
```
17-
Get-ItemState [-CamerasOnly] [<CommonParameters>]
17+
Get-ItemState [-CamerasOnly] [[-Timeout] <TimeSpan>] [<CommonParameters>]
1818
```
1919

2020
## DESCRIPTION
2121

22-
Sends a MessageCommunication.ProvideCurrentStateRequest message and returns the response.
22+
The `Get-ItemState` cmdlet sends a "MessageCommunication.ProvideCurrentStateRequest" message and returns the response
23+
from the XProtect Event Server.
2324

24-
The ProvideCurrentStateResponse contains a flat collection of ItemState objects representing the state of all known items in the site.
25-
Each ItemState contains an FQID, and State property.
26-
The FQID.Kind and FQID.ObjectId can be used to determine what type of object the state represents, and the ID of that object.
27-
28-
Most of the time, you will probably only be interested in Camera objects, so you can filter the output with the -CamerasOnly switch.
25+
The `VideoOS.Platform.Messaging.ItemState` objects returned by this command have an `FQID` and `State` property, and
26+
using the `FQID` this command enriches the output by adding the item `Name`, `ItemType`, and `Id` as note properties.
2927

3028
REQUIREMENTS
3129

@@ -61,12 +59,27 @@ Parameter Sets: (All)
6159
Aliases:
6260

6361
Required: False
64-
Position: 1
62+
Position: Named
6563
Default value: False
6664
Accept pipeline input: False
6765
Accept wildcard characters: False
6866
```
6967
68+
### -Timeout
69+
Specifies a timeout period in the form of a TimeSpan. The default value is 60 seconds.
70+
71+
```yaml
72+
Type: TimeSpan
73+
Parameter Sets: (All)
74+
Aliases:
75+
76+
Required: False
77+
Position: 1
78+
Default value: None
79+
Accept pipeline input: False
80+
Accept wildcard characters: False
81+
```
82+
7083
### CommonParameters
7184
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
7285

docs/commands/en-US/Get-PlatformItem.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Gets a VideoOS.Platform.Item object representing a configuration item
1313

1414
## SYNTAX
1515

16-
### ByFQID
16+
### ByFQID (Default)
1717
```
18-
Get-PlatformItem [[-Fqid] <FQID>] [<CommonParameters>]
18+
Get-PlatformItem [-Fqid] <FQID> [<CommonParameters>]
1919
```
2020

2121
### BySearch
@@ -26,7 +26,7 @@ Get-PlatformItem [[-SearchText] <String>] [[-MaxResultCount] <Int32>] [[-Timeout
2626

2727
### ByKind
2828
```
29-
Get-PlatformItem [[-Kind] <Guid>] [<CommonParameters>]
29+
Get-PlatformItem [-Kind] <Guid> [<CommonParameters>]
3030
```
3131

3232
### ListAvailable
@@ -88,7 +88,7 @@ Type: FQID
8888
Parameter Sets: ByFQID
8989
Aliases:
9090

91-
Required: False
91+
Required: True
9292
Position: 1
9393
Default value: None
9494
Accept pipeline input: True (ByPropertyName, ByValue)
@@ -157,10 +157,10 @@ Type: Guid
157157
Parameter Sets: ByKind
158158
Aliases:
159159

160-
Required: False
160+
Required: True
161161
Position: 1
162162
Default value: 00000000-0000-0000-0000-000000000000
163-
Accept pipeline input: True (ByValue)
163+
Accept pipeline input: False
164164
Accept wildcard characters: False
165165
```
166166

docs/commands/en-US/Get-VmsVideoOSItem.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Gets `[VideoOS.Platform.Item]` objects of the specified Kind.
1212

1313
## SYNTAX
1414

15-
### GetItemByFQID
15+
### GetItemByFQID (Default)
1616
```
1717
Get-VmsVideoOSItem -Fqid <FQID> [<CommonParameters>]
1818
```
@@ -118,7 +118,7 @@ Aliases:
118118
Required: True
119119
Position: Named
120120
Default value: None
121-
Accept pipeline input: True (ByPropertyName)
121+
Accept pipeline input: True (ByPropertyName, ByValue)
122122
Accept wildcard characters: False
123123
```
124124

@@ -165,7 +165,7 @@ Aliases:
165165
Required: True
166166
Position: Named
167167
Default value: None
168-
Accept pipeline input: True (ByPropertyName)
168+
Accept pipeline input: False
169169
Accept wildcard characters: False
170170
```
171171

@@ -177,7 +177,7 @@ Aliases:
177177
Required: False
178178
Position: Named
179179
Default value: None
180-
Accept pipeline input: True (ByPropertyName)
180+
Accept pipeline input: False
181181
Accept wildcard characters: False
182182
```
183183

src/MilestonePSTools/DeviceCommands/GetItemState.cs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Collections.Concurrent;
1717
using System.Collections.ObjectModel;
1818
using System.Management.Automation;
19+
using System.Threading;
1920
using VideoOS.Platform;
2021
using VideoOS.Platform.Messaging;
2122

@@ -51,9 +52,12 @@ public class GetItemState : ConfigApiCmdlet
5152
/// <summary>
5253
/// <para type="description">Filter the ItemState results to Camera items</para>
5354
/// </summary>
54-
[Parameter(Position = 1)]
55+
[Parameter()]
5556
public SwitchParameter CamerasOnly { get; set; }
5657

58+
[Parameter(Position = 1)]
59+
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(60);
60+
5761
/// <summary>
5862
///
5963
/// </summary>
@@ -62,6 +66,7 @@ protected override void ProcessRecord()
6266
_itemStates = new BlockingCollection<ItemState>();
6367
MessageCommunication mc = null;
6468
object obj = null;
69+
CancellationTokenSource cts = null;
6570
try
6671
{
6772
MessageCommunicationManager.Start(Connection.CurrentSite.FQID.ServerId);
@@ -70,12 +75,40 @@ protected override void ProcessRecord()
7075
obj = mc.RegisterCommunicationFilter(ProvideCurrentStateResponse,
7176
new CommunicationIdFilter(MessageCommunication.ProvideCurrentStateResponse));
7277
mc.TransmitMessage(new Message(MessageCommunication.ProvideCurrentStateRequest), null, null, null);
73-
74-
foreach (var itemState in _itemStates.GetConsumingEnumerable())
78+
cts = new CancellationTokenSource(Timeout);
79+
foreach (var itemState in _itemStates.GetConsumingEnumerable(cts.Token))
7580
{
76-
WriteObject(itemState);
81+
// Ignore Event item states
82+
var kind = Kind.DefaultTypeToNameTable.ContainsKey(itemState.FQID.Kind)
83+
? Kind.DefaultTypeToNameTable[itemState.FQID.Kind].ToString()
84+
: "External";
85+
if (kind == "Event") continue;
86+
87+
var item = Configuration.Instance.GetItem(itemState.FQID);
88+
89+
// Ignore ItemState records where no corresponding item can be found
90+
// These are typically Generic Events or built-in system events
91+
if (item == null && kind == "Server") continue;
92+
93+
// Enrich the ItemState with helpful properties
94+
var psObj = PSObject.AsPSObject(itemState);
95+
psObj.Properties.Add(new PSNoteProperty("Name", item?.Name ?? "Not available"));
96+
psObj.Properties.Add(new PSNoteProperty("ItemType", kind));
97+
psObj.Properties.Add(new PSNoteProperty("Id", itemState.FQID.ObjectId));
98+
99+
WriteObject(psObj);
77100
}
78101
}
102+
catch (PipelineStoppedException)
103+
{
104+
throw;
105+
}
106+
catch (OperationCanceledException cancelledException)
107+
{
108+
WriteError(
109+
new ErrorRecord(
110+
cancelledException, $"The operation timed out after the Timeout delay of {Timeout}", ErrorCategory.OperationTimeout, null));
111+
}
79112
catch (Exception e)
80113
{
81114
WriteError(
@@ -84,6 +117,7 @@ protected override void ProcessRecord()
84117
}
85118
finally
86119
{
120+
cts?.Dispose();
87121
mc?.UnRegisterCommunicationFilter(obj);
88122
mc?.Dispose();
89123
MessageCommunicationManager.Stop(Connection.CurrentSite.FQID.ServerId);

src/MilestonePSTools/DeviceCommands/GetPlatformItem.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ namespace MilestonePSTools.DeviceCommands
4444
/// <para/><para/><para/>
4545
/// </example>
4646
/// </summary>
47-
[Cmdlet(VerbsCommon.Get, "PlatformItem")]
47+
[Cmdlet(VerbsCommon.Get, "PlatformItem", DefaultParameterSetName = "ByFQID")]
4848
[OutputType(typeof(Item))]
4949
[RequiresVmsConnection()]
5050
public class GetPlatformItem : ConfigApiCmdlet
5151
{
5252
/// <summary>
5353
/// <para type="description">VideoOS.Platform.FQID of a Milestone configuration Item</para>
5454
/// </summary>
55-
[Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "ByFQID")]
55+
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "ByFQID")]
5656
public FQID Fqid { get; set; }
5757

5858
/// <summary>
@@ -64,7 +64,7 @@ public class GetPlatformItem : ConfigApiCmdlet
6464
/// <summary>
6565
/// <para type="description">Specifies the GUID constant for the Kind of object you want to return</para>
6666
/// </summary>
67-
[Parameter(Position = 1, ValueFromPipeline = true, ParameterSetName = "ByKind")]
67+
[Parameter(Mandatory = true, Position = 1, ParameterSetName = "ByKind")]
6868
[ArgumentCompleter(typeof(KindArgumentCompleter))]
6969
[KindNameTransform()]
7070
public Guid Kind { get; set; }
@@ -125,7 +125,7 @@ protected override void ProcessRecord()
125125
{
126126
WriteError(
127127
new ErrorRecord(
128-
new MIPException($"GetItemsBySearch failed: {result.ToString()}"),
128+
new MIPException($"GetItemsBySearch failed: {result}"),
129129
"GetItemsBySearch Failed",
130130
ErrorCategory.InvalidResult,
131131
null));

src/MilestonePSTools/Utility/KindNameTransformAttribute.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
using System.Linq;
1818
using System.Management.Automation;
1919
using System.Reflection;
20+
using System.Text.RegularExpressions;
2021
using VideoOS.Platform;
22+
using VideoOS.Platform.Messaging;
2123

2224
namespace MilestonePSTools.Utility
2325
{
@@ -33,6 +35,11 @@ public KindNameTransformAttribute()
3335

3436
public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
3537
{
38+
if (inputData is PSObject psobject)
39+
{
40+
inputData = psobject.ImmediateBaseObject;
41+
}
42+
3643
if (inputData is Guid guid)
3744
{
3845
if (!Kind.DefaultTypeToNameTable.ContainsKey(guid))
@@ -42,6 +49,16 @@ public override object Transform(EngineIntrinsics engineIntrinsics, object input
4249
return guid;
4350
}
4451

52+
if (inputData is FQID fqid)
53+
{
54+
return fqid.Kind;
55+
}
56+
57+
if (inputData is ItemState itemState)
58+
{
59+
return itemState.FQID.Kind;
60+
}
61+
4562
if (inputData is string kindName)
4663
{
4764
return ConvertToGuid(kindName);
@@ -61,6 +78,15 @@ public override object Transform(EngineIntrinsics engineIntrinsics, object input
6178

6279
private Guid ConvertToGuid(string kindName)
6380
{
81+
// Input is a guid in string format
82+
if (Guid.TryParse(kindName, out var parsedGuid)) return parsedGuid;
83+
84+
// Input is FQID.ToString()
85+
var match = Regex.Match(kindName, @"Type:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$");
86+
if (match.Success)
87+
{
88+
return Guid.Parse(match.Groups["id"].Value);
89+
}
6490
var field = _fields.SingleOrDefault(f => f.FieldType == typeof(Guid) && f.Name.Equals(kindName, StringComparison.OrdinalIgnoreCase));
6591
if (field == null)
6692
{

0 commit comments

Comments
 (0)