' ' Copyright (c) 2006 Microsoft Corporation. All rights reserved. ' ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ' ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO ' THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A ' PARTICULAR PURPOSE. ' ' Description: Helper class to support select-obj cmdlet's ' unique functionality. ' ' System namespaces needed Imports System Imports System.Collections.Generic Imports System.Collections Imports System.Text Imports System.Globalization Imports System.Threading Imports Microsoft.VisualBasic ' Windows PowerShell namespaces needed Imports System.Management.Automation Namespace Microsoft.Samples.PowerShell.Commands #Region "PSObject Comparer" ' ''' ''' Keeps the property value of inputObject. Because the value of ''' a non-existing property is null, isExistingProperty is needed ''' to distinguish whether a property exists and its value is null or ''' the property does not exist at all. ''' Friend Class ObjectCommandPropertyValue Private Sub New() End Sub 'New Friend Sub New(ByVal propVal As Object) myPropertyValue = propVal myIsExistingProperty = True End Sub 'New Friend ReadOnly Property PropertyValue() As Object Get Return myPropertyValue End Get End Property Friend ReadOnly Property IsExistingProperty() As Boolean Get Return myIsExistingProperty End Get End Property Private myPropertyValue As Object Private myIsExistingProperty As Boolean Friend Shared NonExistingProperty As New ObjectCommandPropertyValue() Friend Shared ExistingNullProperty As _ New ObjectCommandPropertyValue(Nothing) End Class 'ObjectCommandPropertyValue ''' ''' ''' Friend Class ObjectCommandComparer Implements IComparer ''' ''' Constructor that doesn't set any private field. ''' Necessary because compareTo can compare two objects by calling ''' ((ICompare)obj1).CompareTo(obj2) without using a key. ''' Friend Sub New(ByVal ascending As Boolean, _ ByVal cultureInfo As CultureInfo, _ ByVal caseSensitive As Boolean) Me.ascendingOrder = ascending Me.cultureInfo = cultureInfo If Me.cultureInfo Is Nothing Then Me.cultureInfo = Thread.CurrentThread.CurrentCulture End If Me.caseSensitive = caseSensitive End Sub 'New ''' ''' Check whether can be converted to an ''' PSObject and then check whehter the PSObject is null. ''' ''' ''' Private Shared Function IsValueNull(ByVal obj As Object) As Boolean Dim psObj As PSObject If (TypeOf obj Is PSObject) Then psObj = CType(obj, PSObject) Else psObj = Nothing End If ' obj is converted to an psobject and is found to be null.. If psObj Is Nothing Then Return obj Is Nothing End If If Nothing = psObj.ImmediateBaseObject Then Return obj Is Nothing End If Dim returnValue As Object = Nothing Do returnValue = psObj.ImmediateBaseObject If (TypeOf returnValue Is PSObject) Then psObj = CType(returnValue, PSObject) Else psObj = Nothing End If Loop While Not (psObj Is Nothing) AndAlso _ (Not (psObj.ImmediateBaseObject Is Nothing)) Return returnValue Is Nothing End Function 'IsValueNull ''' ''' Main method that will compare first and second by ''' their keys considering case and order ''' ''' ''' first object to extract value ''' ''' ''' second object to extract value ''' ''' ''' 0 if they are the same, less than 0 if first is smaller, ''' more than 0 if first is greater ''' Friend Function Compare(ByVal first As Object, _ ByVal second As Object) As Integer Implements IComparer.Compare ' This method will never throw exceptions, two null ' objects are considered the same If IsValueNull(first) AndAlso IsValueNull(second) Then Return 0 End If Dim firstPS As PSObject If (TypeOf first Is PSObject) Then firstPS = CType(first, PSObject) Else firstPS = Nothing End If If Not (firstPS Is Nothing) Then first = firstPS.BaseObject End If Dim secondPS As PSObject If (TypeOf second Is PSObject) Then secondPS = CType(second, PSObject) Else secondPS = Nothing End If If Not (secondPS Is Nothing) Then second = secondPS.BaseObject End If Try Return LanguagePrimitives.Compare(first, second, _ Not caseSensitive, cultureInfo) _ * IIf(ascendingOrder, 1, -1) Catch e1 As InvalidCastException Catch e2 As ArgumentException End Try ' Note that this will occur if the objects do not support ' IComparable. We fall back to comparing as strings. ' being here means the first object doesn't support ICompare ' or an Exception was raised with Compare Dim firstString As String = PSObject.AsPSObject(first).ToString() Dim secondString As String = PSObject.AsPSObject(second).ToString() Return String.Compare(firstString, secondString, _ Not caseSensitive, cultureInfo) * _ IIf(ascendingOrder, 1, -1) End Function 'Compare Friend Function Compare(ByVal first As ObjectCommandPropertyValue, _ ByVal second As ObjectCommandPropertyValue) As Integer If first.IsExistingProperty AndAlso second.IsExistingProperty Then Return [Compare](first.PropertyValue, second.PropertyValue) End If ' if first.IsExistingProperty, !second.IsExistingProperty; ' otherwise the first branch if would return. Regardless ' of key orders non existing property ' will be considered greater than others If first.IsExistingProperty Then Return -1 End If ' viceversa for the first.IsExistingProperty If second.IsExistingProperty Then Return 1 End If 'both are nonexisting Return 0 End Function 'Compare Private cultureInfo As CultureInfo = Nothing Private ascendingOrder As Boolean = True Private caseSensitive As Boolean = False End Class 'ObjectCommandComparer #End Region End Namespace