diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs
index 798b5ca4d8d..3f4e20fb3a2 100644
--- a/src/System.Management.Automation/engine/InitialSessionState.cs
+++ b/src/System.Management.Automation/engine/InitialSessionState.cs
@@ -1309,7 +1309,7 @@ public void Add(T item)
}
///
- ///
+ /// Add items to this collection.
///
///
public void Add(IEnumerable items)
@@ -1326,6 +1326,27 @@ public void Add(IEnumerable items)
}
}
+ ///
+ /// Special add for TypeTable type entries that removes redundant file entries.
+ ///
+ internal void AddTypeTableTypesInfo(IEnumerable items)
+ {
+ if (typeof(T) != typeof(SessionStateTypeEntry)) { throw new PSInvalidOperationException(); }
+
+ lock (_syncObject)
+ {
+ foreach (var element in items)
+ {
+ var typeEntry = element as SessionStateTypeEntry;
+ if (typeEntry.TypeData != null)
+ {
+ // Skip type file entries.
+ _internalCollection.Add(element);
+ }
+ }
+ }
+ }
+
///
/// Get enumerator for this collection.
///
@@ -3851,7 +3872,12 @@ internal void UpdateTypes(ExecutionContext context, bool updateOnly)
context.TypeTable = typeTable;
Types.Clear();
- Types.Add(typeTable.typesInfo);
+
+ // A TypeTable contains types info along with type file references used to create the types info,
+ // which is redundant information. When resused in a runspace the ISS unpacks the file types again
+ // resulting in duplicate types and duplication errors when processed.
+ // So use this special Add method to filter all types files found in the TypeTable.
+ Types.AddTypeTableTypesInfo(typeTable.typesInfo);
return;
}
diff --git a/test/powershell/Common/TestTypeFile.ps1xml b/test/powershell/Common/TestTypeFile.ps1xml
new file mode 100644
index 00000000000..6e22c9cf3dc
--- /dev/null
+++ b/test/powershell/Common/TestTypeFile.ps1xml
@@ -0,0 +1,13 @@
+
+
+
+
+ System.Array
+
+
+ Counts
+ Length
+
+
+
+
diff --git a/test/powershell/engine/InitialSessionState.Tests.ps1 b/test/powershell/engine/InitialSessionState.Tests.ps1
index 85b1bec4fd1..547bbddbcfb 100644
--- a/test/powershell/engine/InitialSessionState.Tests.ps1
+++ b/test/powershell/engine/InitialSessionState.Tests.ps1
@@ -54,4 +54,75 @@ Describe "InitialSessionState capacity" -Tags CI {
$ps.AddScript('New-Alias -Name a5000 -Value f1; a5000').Invoke() | Should Be "fn f1"
$ps.Streams.Error | Should Be $null
}
-}
\ No newline at end of file
+}
+
+##
+## A reused InitialSessionState created from a TypeTable should not have duplicate types.
+##
+Describe "TypeTable duplicate types in reused runspace InitialSessionState TypeTable" -Tags 'Feature' {
+
+ Context "No duplicate types test" {
+
+ BeforeAll {
+
+ $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml"))
+ [initialsessionstate] $iss = [initialsessionstate]::Create()
+ $iss.Types.Add($typeTable)
+ [runspace] $rs1 = [runspacefactory]::CreateRunspace($iss)
+
+ # Process TypeTable types from ISS
+ $rs1.Open()
+
+ # Get processed ISS from runspace.
+ $issReused = $rs1.InitialSessionState.Clone()
+ $issReused.ThrowOnRunspaceOpenError = $true
+
+ # Create new runspace with reused ISS.
+ $rs2 = [runspacefactory]::CreateRunspace($issReused)
+ }
+
+ AfterAll {
+
+ if ($rs1 -ne $null) { $rs1.Dispose() }
+ if ($rs2 -ne $null) { $rs2.Dispose() }
+ }
+
+ It "Verifies that a reused InitialSessionState object created from a TypeTable object does not have duplicate types" {
+
+ { $rs2.Open() } | Should Not Throw
+ }
+ }
+
+ Context "Cannot use shared TypeTable in ISS test" {
+
+ BeforeAll {
+
+ # Create default ISS and add shared TypeTable.
+ $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml"))
+ [initialsessionstate] $iss = [initialsessionstate]::CreateDefault2()
+ $iss.Types.Add($typeTable)
+ $iss.ThrowOnRunspaceOpenError = $true
+ [runspace] $rs = [runspacefactory]::CreateRunspace($iss)
+ }
+
+ AfterAll {
+
+ if ($rs -ne $null) { $rs.Dispose() }
+ }
+
+ It "Verifies that shared TypeTable is not allowed in ISS" {
+
+ # Process TypeTable types from ISS.
+ $errorId = ""
+ try
+ {
+ $rs.Open()
+ throw "No Exception!"
+ }
+ catch
+ {
+ $_.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should Be "ErrorsUpdatingTypes"
+ }
+ }
+ }
+}