Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 1 addition & 35 deletions src/System.Management.Automation/engine/COM/ComUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<object>(), 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
7 changes: 7 additions & 0 deletions test/powershell/engine/COM/COM.Basic.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down