@@ -1613,6 +1613,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
16131613 {
16141614 throw new ArgumentNullException ( "powershellVersion" ) ;
16151615 }
1616+ if ( ! IsPowerShellVersionSupported ( powershellVersion ) )
1617+ {
1618+ throw new ArgumentException ( "Invalid PowerShell version. Choose from 3.0, 4.0 or 5.0" ) ;
1619+ }
16161620 var keys = new List < string > ( ) ;
16171621 var keysCommon = new List < string > {
16181622 "RootModule" ,
@@ -1644,15 +1648,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
16441648 "HelpInfoURI" ,
16451649 "DefaultCommandPrefix" } ;
16461650 keys . AddRange ( keysCommon ) ;
1647- if ( powershellVersion . Equals ( new Version ( "5.0" ) ) )
1651+ if ( powershellVersion . Major == 5 )
16481652 {
16491653 keys . Add ( "DscResourcesToExport" ) ;
16501654 }
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- }
16561655 return keys ;
16571656 }
16581657
@@ -1666,15 +1665,50 @@ public static IEnumerable<string> GetDeprecatedModuleManifestKeys()
16661665 }
16671666
16681667 /// <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.
16701671 /// </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 )
16741675 {
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+ }
16781712 }
16791713
16801714 /// <summary>
@@ -1683,17 +1717,18 @@ public static bool IsModuleManifest(string filepath)
16831717 /// <param name="filepath">Path to module manifest</param>
16841718 /// <param name="powershellVersion">Version parameter with valid values: 5.0, 4.0 and 3.0</param>
16851719 /// <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 )
16871721 {
16881722 Token [ ] tokens ;
16891723 ParseError [ ] errors ;
16901724 if ( filepath == null )
16911725 {
16921726 throw new ArgumentNullException ( "filepath" ) ;
16931727 }
1694- if ( powershellVersion == null )
1728+ if ( powershellVersion != null
1729+ && ! IsPowerShellVersionSupported ( powershellVersion ) )
16951730 {
1696- throw new ArgumentNullException ( "powershellVersion" ) ;
1731+ return false ;
16971732 }
16981733 if ( ! Path . GetExtension ( filepath ) . Equals ( ".psd1" , StringComparison . OrdinalIgnoreCase ) )
16991734 {
@@ -1708,28 +1743,45 @@ public static bool IsModuleManifest(string filepath, Version powershellVersion)
17081743 {
17091744 return false ;
17101745 }
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 )
17171750 {
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" ) )
17241757 {
1725- if ( key . Equals ( pairKey . Value , StringComparison . OrdinalIgnoreCase ) )
1758+ var versionStrAst = map [ "PowerShellVersion" ] . Find ( x => x is StringConstantExpressionAst , false ) ;
1759+ if ( versionStrAst != null )
17261760 {
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+ }
17291769 }
17301770 }
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+ }
17311781 }
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 ) ) ;
17331785 }
17341786#endregion Methods
17351787 }
0 commit comments