diff --git a/src/System.Management.Automation/engine/COM/ComUtil.cs b/src/System.Management.Automation/engine/COM/ComUtil.cs index 44e307a69b5..a1fa5a0125a 100644 --- a/src/System.Management.Automation/engine/COM/ComUtil.cs +++ b/src/System.Management.Automation/engine/COM/ComUtil.cs @@ -411,41 +411,7 @@ internal static ComEnumerator Create(object comObject) // The passed-in COM object could already be a IEnumVARIANT interface. // e.g. user call '_NewEnum()' on a COM collection interface. var enumVariant = comObject as COM.IEnumVARIANT; - if (enumVariant != null) - { - return new ComEnumerator(enumVariant); - } - - // The passed-in COM object could be a collection. - var enumerable = comObject as IEnumerable; - var target = comObject as IDispatch; - if (enumerable != null && target != null) - { - try - { - var comTypeInfo = ComTypeInfo.GetDispatchTypeInfo(comObject); - if (comTypeInfo != null && comTypeInfo.NewEnumInvokeKind.HasValue) - { - // The COM object is a collection and also a IDispatch interface, so we try to get a - // IEnumVARIANT interface out of it by invoking its '_NewEnum (DispId: -4)' function. - var result = ComInvoker.Invoke(target, ComTypeInfo.DISPID_NEWENUM, - args: Array.Empty(), byRef: null, - invokeKind: comTypeInfo.NewEnumInvokeKind.Value); - enumVariant = result as COM.IEnumVARIANT; - if (enumVariant != null) - { - return new ComEnumerator(enumVariant); - } - } - } - catch (Exception) - { - // Ignore exceptions. In case of exception, no enumerator can be created - // for the passed-in COM object, and we will return null eventually. - } - } - - return null; + return enumVariant != null ? new ComEnumerator(enumVariant) : null; } } } diff --git a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs index 8466c6b1794..98b2cb74ccd 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs @@ -3291,17 +3291,28 @@ internal object GetNonEnumerableObject() internal static IEnumerator GetCOMEnumerator(object obj) { object targetValue = PSObject.Base(obj); + try + { + var enumerator = (targetValue as IEnumerable)?.GetEnumerator(); + if (enumerator != null) + { + return enumerator; + } + } + catch (Exception) + { + } // We use ComEnumerator to enumerate COM collections because the following code doesn't work in .NET Core - // IEnumerable enumerable = targetValue as IEnumerable; - // if (enumerable != null) + // IEnumerator enumerator = targetValue as IEnumerator; + // if (enumerator != null) // { - // var enumerator = enumerable.GetEnumerator(); + // enumerable.MoveNext(); // ... // } - // The call to 'GetEnumerator()' throws exception because COM is not supported in .NET Core. - // See https://github.com/dotnet/corefx/issues/19731 for more information. - // When COM support is back to .NET Core, we need to change back to the original implementation. + // The call to 'MoveNext()' throws exception because COM is not fully supported in .NET Core. + // See https://github.com/dotnet/runtime/issues/21690 for more information. + // When COM support is fully back to .NET Core, we need to change back to directly use the type cast. return ComEnumerator.Create(targetValue) ?? NonEnumerableObjectEnumerator.Create(obj); } diff --git a/test/powershell/engine/COM/COM.Basic.Tests.ps1 b/test/powershell/engine/COM/COM.Basic.Tests.ps1 index 7b1599a5d99..b69e2674fb8 100644 --- a/test/powershell/engine/COM/COM.Basic.Tests.ps1 +++ b/test/powershell/engine/COM/COM.Basic.Tests.ps1 @@ -49,6 +49,13 @@ try { $element | Should -Be $drives.Item($element.DriveLetter) } + It "Should be able to enumerate 'IADsMembers' object" { + $group = [ADSI]"WinNT://./Users,Group" + $members = $group.Invoke('Members') + $names = $members | ForEach-Object { $_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null) } + $names | Should -Contain 'INTERACTIVE' + } + It "ToString() should return method paramter names" { $shell = New-Object -ComObject "Shell.Application" $fullSignature = $shell.AddToRecent.ToString()