@@ -1613,6 +1613,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
1613
1613
{
1614
1614
throw new ArgumentNullException ( "powershellVersion" ) ;
1615
1615
}
1616
+ if ( ! IsPowerShellVersionSupported ( powershellVersion ) )
1617
+ {
1618
+ throw new ArgumentException ( "Invalid PowerShell version. Choose from 3.0, 4.0 or 5.0" ) ;
1619
+ }
1616
1620
var keys = new List < string > ( ) ;
1617
1621
var keysCommon = new List < string > {
1618
1622
"RootModule" ,
@@ -1644,15 +1648,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
1644
1648
"HelpInfoURI" ,
1645
1649
"DefaultCommandPrefix" } ;
1646
1650
keys . AddRange ( keysCommon ) ;
1647
- if ( powershellVersion . Equals ( new Version ( "5.0" ) ) )
1651
+ if ( powershellVersion . Major == 5 )
1648
1652
{
1649
1653
keys . Add ( "DscResourcesToExport" ) ;
1650
1654
}
1651
- else if ( ! powershellVersion . Equals ( new Version ( "4.0" ) )
1652
- && ! powershellVersion . Equals ( new Version ( "3.0" ) ) )
1653
- {
1654
- throw new ArgumentException ( "Invalid PowerShell version. Choose from 3.0, 4.0 or 5.0" ) ;
1655
- }
1656
1655
return keys ;
1657
1656
}
1658
1657
@@ -1666,15 +1665,50 @@ public static IEnumerable<string> GetDeprecatedModuleManifestKeys()
1666
1665
}
1667
1666
1668
1667
/// <summary>
1669
- /// Checks if a given file is a valid PowerShell module manifest
1668
+ /// Get a mapping between string type keys and StatementAsts from module manifest hashtable ast
1669
+ ///
1670
+ /// This is a workaround as SafeGetValue is not supported on PS v5 and below.
1670
1671
/// </summary>
1671
- /// <param name="filepath">Path to module manifest</param>
1672
- /// <returns>true if given filepath points to a module manifest, otherwise false </returns>
1673
- public static bool IsModuleManifest ( string filepath )
1672
+ /// <param name="hast">Hashtable Ast obtained from module manifest</param>
1673
+ /// <returns>A dictionary that maps string keys to values of StatementAst type </returns>
1674
+ private static Dictionary < string , StatementAst > GetMapFromHashtableAst ( HashtableAst hast )
1674
1675
{
1675
- // 4.0 and 3.0 contain the same keys. Hence, compare only with 4.0.
1676
- return IsModuleManifest ( filepath , new Version ( "5.0" ) )
1677
- || IsModuleManifest ( filepath , new Version ( "4.0" ) ) ;
1676
+ var map = new Dictionary < string , StatementAst > ( StringComparer . OrdinalIgnoreCase ) ;
1677
+ foreach ( var pair in hast . KeyValuePairs )
1678
+ {
1679
+ var key = pair . Item1 as StringConstantExpressionAst ;
1680
+ if ( key == null )
1681
+ {
1682
+ return null ;
1683
+ }
1684
+ map [ key . Value ] = pair . Item2 ;
1685
+ }
1686
+ return map ;
1687
+ }
1688
+
1689
+ /// <summary>
1690
+ /// Checks if the version is supported
1691
+ ///
1692
+ /// PowerShell versions with Major 5, 4 and 3 are supported
1693
+ /// </summary>
1694
+ /// <param name="version">PowerShell version</param>
1695
+ /// <returns>true if the given version is supported else false</returns>
1696
+ public static bool IsPowerShellVersionSupported ( Version version )
1697
+ {
1698
+ if ( version == null )
1699
+ {
1700
+ throw new ArgumentNullException ( "version" ) ;
1701
+ }
1702
+
1703
+ switch ( version . Major )
1704
+ {
1705
+ case 5 :
1706
+ case 4 :
1707
+ case 3 :
1708
+ return true ;
1709
+ default :
1710
+ return false ;
1711
+ }
1678
1712
}
1679
1713
1680
1714
/// <summary>
@@ -1683,17 +1717,18 @@ public static bool IsModuleManifest(string filepath)
1683
1717
/// <param name="filepath">Path to module manifest</param>
1684
1718
/// <param name="powershellVersion">Version parameter with valid values: 5.0, 4.0 and 3.0</param>
1685
1719
/// <returns>true if given filepath points to a module manifest, otherwise false</returns>
1686
- public static bool IsModuleManifest ( string filepath , Version powershellVersion )
1720
+ public static bool IsModuleManifest ( string filepath , Version powershellVersion = null )
1687
1721
{
1688
1722
Token [ ] tokens ;
1689
1723
ParseError [ ] errors ;
1690
1724
if ( filepath == null )
1691
1725
{
1692
1726
throw new ArgumentNullException ( "filepath" ) ;
1693
1727
}
1694
- if ( powershellVersion == null )
1728
+ if ( powershellVersion != null
1729
+ && ! IsPowerShellVersionSupported ( powershellVersion ) )
1695
1730
{
1696
- throw new ArgumentNullException ( "powershellVersion" ) ;
1731
+ return false ;
1697
1732
}
1698
1733
if ( ! Path . GetExtension ( filepath ) . Equals ( ".psd1" , StringComparison . OrdinalIgnoreCase ) )
1699
1734
{
@@ -1708,28 +1743,45 @@ public static bool IsModuleManifest(string filepath, Version powershellVersion)
1708
1743
{
1709
1744
return false ;
1710
1745
}
1711
- var validKeys = GetModuleManifestKeys ( powershellVersion ) ;
1712
- var allKeys = validKeys . Concat ( GetDeprecatedModuleManifestKeys ( ) ) ;
1713
-
1714
- // check if all the keys in hast.keyvaluepairs are present in keys
1715
- int matchCount = 0 ;
1716
- foreach ( var pair in hast . KeyValuePairs )
1746
+ var map = GetMapFromHashtableAst ( hast ) ;
1747
+ var deprecatedKeys = GetDeprecatedModuleManifestKeys ( ) ;
1748
+ IEnumerable < string > allKeys ;
1749
+ if ( powershellVersion != null )
1717
1750
{
1718
- var pairKey = pair . Item1 as StringConstantExpressionAst ;
1719
- if ( pairKey == null )
1720
- {
1721
- break ;
1722
- }
1723
- foreach ( var key in allKeys )
1751
+ allKeys = GetModuleManifestKeys ( powershellVersion ) ;
1752
+ }
1753
+ else
1754
+ {
1755
+ Version version = null ;
1756
+ if ( map . ContainsKey ( "PowerShellVersion" ) )
1724
1757
{
1725
- if ( key . Equals ( pairKey . Value , StringComparison . OrdinalIgnoreCase ) )
1758
+ var versionStrAst = map [ "PowerShellVersion" ] . Find ( x => x is StringConstantExpressionAst , false ) ;
1759
+ if ( versionStrAst != null )
1726
1760
{
1727
- matchCount ++ ;
1728
- break ;
1761
+ try
1762
+ {
1763
+ version = new Version ( ( versionStrAst as StringConstantExpressionAst ) . Value ) ;
1764
+ }
1765
+ catch
1766
+ {
1767
+ // we just ignore if the value is not a valid version
1768
+ }
1729
1769
}
1730
1770
}
1771
+ if ( version != null
1772
+ && IsPowerShellVersionSupported ( version ) )
1773
+ {
1774
+ allKeys = GetModuleManifestKeys ( version ) ;
1775
+ }
1776
+ else
1777
+ {
1778
+ // default to version 5.0
1779
+ allKeys = GetModuleManifestKeys ( new Version ( "5.0" ) ) ;
1780
+ }
1731
1781
}
1732
- return matchCount == hast . KeyValuePairs . Count ;
1782
+
1783
+ // check if the keys given in module manifest are a proper subset of Keys
1784
+ return map . Keys . All ( x => allKeys . Concat ( deprecatedKeys ) . Contains ( x , StringComparer . OrdinalIgnoreCase ) ) ;
1733
1785
}
1734
1786
#endregion Methods
1735
1787
}
0 commit comments