コード例 #1
0
        public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
        {
            // A using expression is always allowed, it simply gets re-written to be a parameter
            HasUsingExpr = true;

            // Skip the children - the expression is evaluated before sending to the remote machine,
            // so it doesn't matter what we might find in the children.
            return(AstVisitAction.SkipChildren);
        }
コード例 #2
0
        /// <summary>
        /// Get using values as dictionary for the Foreach-Object parallel cmdlet.
        /// Ignore any using expressions that are associated with inner nested Foreach-Object parallel calls,
        /// since they are only effective in the nested call scope and not the current outer scope.
        /// </summary>
        /// <param name = "scriptBlock">Scriptblock to search.</param>
        /// <param name = "isTrustedInput">True when input is trusted.</param>
        /// <param name = "context">Execution context.</param>
        /// <param name = "foreachNames">List of foreach command names and aliases.</param>
        /// <returns>Dictionary of using variable map.</returns>
        internal static Dictionary <string, object> GetUsingValuesForEachParallel(
            ScriptBlock scriptBlock,
            bool isTrustedInput,
            ExecutionContext context,
            string[] foreachNames)
        {
            // Using variables for Foreach-Object -Parallel use are restricted to be within the
            // Foreach-Object -Parallel call scope. This will filter the using variable map to variables
            // only within the current (outer) Foreach-Object -Parallel call scope.
            var usingAsts = UsingExpressionAstSearcher.FindAllUsingExpressions(scriptBlock.Ast).ToList();
            UsingExpressionAst usingAst = null;
            var     usingValueMap       = new Dictionary <string, object>(usingAsts.Count);
            Version oldStrictVersion    = null;

            try
            {
                if (context != null)
                {
                    oldStrictVersion = context.EngineSessionState.CurrentScope.StrictModeVersion;
                    context.EngineSessionState.CurrentScope.StrictModeVersion = PSVersionInfo.PSVersion;
                }

                for (int i = 0; i < usingAsts.Count; ++i)
                {
                    usingAst = (UsingExpressionAst)usingAsts[i];
                    if (IsInForeachParallelCallingScope(usingAst, foreachNames))
                    {
                        var    value       = Compiler.GetExpressionValue(usingAst.SubExpression, isTrustedInput, context);
                        string usingAstKey = PsUtils.GetUsingExpressionKey(usingAst);
                        usingValueMap.TryAdd(usingAstKey, value);
                    }
                }
            }
            catch (RuntimeException rte)
            {
                if (rte.ErrorRecord.FullyQualifiedErrorId.Equals("VariableIsUndefined", StringComparison.Ordinal))
                {
                    throw InterpreterError.NewInterpreterException(
                              targetObject: null,
                              exceptionType: typeof(RuntimeException),
                              errorPosition: usingAst.Extent,
                              resourceIdAndErrorId: "UsingVariableIsUndefined",
                              resourceString: AutomationExceptions.UsingVariableIsUndefined,
                              args: rte.ErrorRecord.TargetObject);
                }
            }
            finally
            {
                if (context != null)
                {
                    context.EngineSessionState.CurrentScope.StrictModeVersion = oldStrictVersion;
                }
            }

            return(usingValueMap);
        }
コード例 #3
0
        /// <summary>
        /// Remove the "Using" prefix for all UsingExpressionAsts that appear in the given script
        /// </summary>
        /// <param name="script">script text</param>
        /// <param name="allWorkflowVariables">all workflow variables/arguments that potentially can be referred by a using variable</param>
        /// <param name="usingVariables">names of the variables in the script that have the "Using" prefix</param>
        /// <returns>
        /// Return <para>script</para> if the script text is empty string or null
        /// Return <para>script</para> if there are errors when parsing the script text
        /// Return <para>script</para> if there is no UsingExpressionAst in the given script
        /// Return a new script text that has all the "Using" prefixes removed
        /// </returns>
        private static string RemoveUsingPrefix(string script, HashSet <string> allWorkflowVariables, out HashSet <string> usingVariables)
        {
            usingVariables = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            var usingAsts = GetUsingExpressionAsts(script);

            if (usingAsts == null || !usingAsts.Any())
            {
                return(script);
            }

            StringBuilder newScript   = null;
            int           startOffset = 0;

            foreach (Ast ast in usingAsts)
            {
                var usingAst = ast as UsingExpressionAst;
                if (usingAst == null)
                {
                    continue;
                }

                VariableExpressionAst variableAst = UsingExpressionAst.ExtractUsingVariable(usingAst);
                if (variableAst == null)
                {
                    continue;
                }

                if (newScript == null)
                {
                    newScript = new StringBuilder();
                }

                string varName    = variableAst.VariablePath.UserPath;
                string varSign    = variableAst.Splatted ? "@" : "$";
                bool   needPrefix = allWorkflowVariables.Contains(varName);
                string newVar     = needPrefix ? (varSign + VariablePrefix + varName) : (varSign + varName);

                // Add those variable names that potentially refer to workflow variables/arguments
                if (needPrefix && !usingVariables.Contains(varName))
                {
                    usingVariables.Add(varName);
                }

                newScript.Append(script.Substring(startOffset, variableAst.Extent.StartOffset - startOffset));
                newScript.Append(newVar);
                startOffset = variableAst.Extent.EndOffset;
            }

            if (newScript != null)
            {
                newScript.Append(script.Substring(startOffset));
                return(newScript.ToString());
            }

            return(script);
        }
コード例 #4
0
ファイル: PSThreadJob.cs プロジェクト: ajansveld/PSThreadJob
        /// <summary>
        /// This method creates a dictionary key for a Using expression value that is bound to
        /// a thread job script block parameter.  PowerShell version 5.0+ recognizes this and performs
        /// the correct Using parameter argument binding.
        /// </summary>
        /// <param name="usingAst">A using expression</param>
        /// <returns>Base64 encoded string as the key of the UsingExpressionAst</returns>
        private static string GetUsingExpressionKey(UsingExpressionAst usingAst)
        {
            string usingAstText = usingAst.ToString();

            if (usingAst.SubExpression is VariableExpressionAst)
            {
                usingAstText = usingAstText.ToLowerInvariant();
            }

            return(Convert.ToBase64String(Encoding.Unicode.GetBytes(usingAstText.ToCharArray())));
        }
コード例 #5
0
 internal static bool IsUsingExpressionInFunction(UsingExpressionAst usingExpr, Ast topLevelParent)
 {
     for (Ast ast = usingExpr.Parent; ast != null; ast = ast.Parent)
     {
         FunctionDefinitionAst ast2 = ast as FunctionDefinitionAst;
         if ((ast2 != null) && !ast2.IsWorkflow)
         {
             return(true);
         }
         if (ast == topLevelParent)
         {
             break;
         }
     }
     return(false);
 }
コード例 #6
0
        private List <VariableExpressionAst> GetUsingVariables(System.Management.Automation.ScriptBlock localScriptBlock)
        {
            List <UsingExpressionAst> source = new List <UsingExpressionAst>();

            foreach (Ast ast in UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(localScriptBlock.Ast).ToList <Ast>())
            {
                UsingExpressionAst usingExpr = ast as UsingExpressionAst;
                if (ScriptBlockToPowerShellConverter.IsUsingExpressionInFunction(usingExpr, localScriptBlock.Ast))
                {
                    ErrorRecord errorRecord = new ErrorRecord(new InvalidOperationException(AutomationExceptions.UsingVariableNotSupportedInFunctionOrFilter), "UsingVariableNotSupportedInFunctionOrFilter", ErrorCategory.InvalidOperation, ast);
                    base.ThrowTerminatingError(errorRecord);
                }
                else
                {
                    source.Add(usingExpr);
                }
            }
            return(source.Select <UsingExpressionAst, VariableExpressionAst>(new Func <UsingExpressionAst, VariableExpressionAst>(UsingExpressionAst.ExtractUsingVariable)).ToList <VariableExpressionAst>());
        }
コード例 #7
0
        /// <summary>
        /// Walks the using Ast to verify it is used within a foreach-object -parallel command
        /// and parameter set scope, and not from within a nested foreach-object -parallel call.
        /// </summary>
        /// <param name="scriptblockAst">Scriptblock Ast containing this using Ast</param>
        /// <param name="usingAst">Using Ast to check.</param>
        /// <returns>True if using expression is in current call scope.</returns>
        private static bool IsInForeachParallelCallingScope(
            Ast scriptblockAst,
            UsingExpressionAst usingAst)
        {
            Diagnostics.Assert(usingAst != null, "usingAst argument cannot be null.");

            /*
             *  Example:
             *  $Test1 = "Hello"
             *  1 | ForEach-Object -Parallel {
             *     $using:Test1
             *     $Test2 = "Goodbye"
             *     1 | ForEach-Object -Parallel {
             *         $using:Test1    # Invalid using scope
             *         $using:Test2    # Valid using scope
             *     }
             *  }
             */

            // Search up the parent Ast chain for 'Foreach-Object -Parallel' commands.
            Ast currentParent = usingAst.Parent;

            while (currentParent != scriptblockAst)
            {
                // Look for Foreach-Object outer commands
                if (currentParent is CommandAst commandAst &&
                    FindForEachInCommand(commandAst))
                {
                    // Using Ast is outside the invoking foreach scope.
                    return(false);
                }

                currentParent = currentParent.Parent;
            }

            return(true);
        }
コード例 #8
0
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     Console.WriteLine("Visited an UsingExpressionAst.");
     Console.WriteLine("    " + usingExpressionAst.ToString().Replace(Environment.NewLine, Environment.NewLine + "    "));
     return(AstVisitAction.Continue);
 }
コード例 #9
0
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     // TODO: add using expression explanation
     AstExplainer(usingExpressionAst);
     return(base.VisitUsingExpression(usingExpressionAst));
 }
コード例 #10
0
        public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
        {
            var expressionAst = VisitAst(usingExpressionAst.SubExpression);

            return(new UsingExpressionAst(usingExpressionAst.Extent, expressionAst));
        }
コード例 #11
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     Console.WriteLine("Visited an UsingExpressionAst.");
     return(usingExpressionAst);
 }
コード例 #12
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     throw new NotImplementedException();
 }
コード例 #13
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst) => null;
コード例 #14
0
        /// <summary>
        /// Check if the given UsingExpression is in a different scope from the previous UsingExpression that we analyzed.
        /// </summary>
        /// <remarks>
        /// Note that the value of <paramref name="usingExpr"/> is retrieved by calling 'UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow'.
        /// So <paramref name="usingExpr"/> is guaranteed not inside a workflow.
        /// </remarks>
        /// <param name="usingExpr">The UsingExpression to analyze.</param>
        /// <param name="topLevelParent">The top level Ast, should be either ScriptBlockAst or FunctionDefinitionAst.</param>
        /// <param name="sbClosestToPreviousUsingExpr">The ScriptBlockAst that represents the scope of the previously analyzed UsingExpressions.</param>
        private static bool HasUsingExpressionsInDifferentScopes(UsingExpressionAst usingExpr, Ast topLevelParent, ref ScriptBlockAst sbClosestToPreviousUsingExpr)
        {
            Diagnostics.Assert(topLevelParent is ScriptBlockAst || topLevelParent is FunctionDefinitionAst,
                               "the top level parent should be either a ScriptBlockAst or FunctionDefinitionAst");

            // Scan up the parents of a UsingExpression to check if it's in a nested function/filter/ScriptBlock
            Ast current = usingExpr;

            do
            {
                current = current.Parent;

                var sbAst = current as ScriptBlockAst;
                if (sbAst != null)
                {
                    // We find the closest parent ScriptBlockAst of the current UsingExpression, which represents the scope
                    // that the current UsingExpression is in.

                    if (sbClosestToPreviousUsingExpr == null)
                    {
                        // The current UsingExpression is the first one to be analyzed.
                        sbClosestToPreviousUsingExpr = sbAst;
                        return(false);
                    }

                    if (sbAst == sbClosestToPreviousUsingExpr)
                    {
                        // The current UsingExpression is in the same scope as the previous UsingExpression we analyzed.
                        return(false);
                    }

                    // The current UsingExpression is in a different scope from the previous UsingExpression we analyzed.
                    return(true);
                }

                var funcAst = current as FunctionDefinitionAst;
                if (funcAst != null)
                {
                    // The parent chain of the current UsingExpression reaches a FunctionDefinitionAst, then the UsingExpression
                    // must be in 'Parameters' property of this FunctionDefinitionAst.
                    // In this case, the 'Body' of this FunctionDefinitionAst represents the scope that the UsingExpression is in.

                    if (sbClosestToPreviousUsingExpr == null)
                    {
                        // The current UsingExpression is the first one to be analyzed.
                        sbClosestToPreviousUsingExpr = funcAst.Body;
                        return(false);
                    }

                    if (funcAst.Body == sbClosestToPreviousUsingExpr)
                    {
                        // The current UsingExpression is in the same scope as the previous UsingExpression we analyzed.
                        return(false);
                    }

                    // The current UsingExpression is in a different scope from the previous UsingExpression we analyzed.
                    return(true);
                }
            } while (current != topLevelParent);

            Diagnostics.Assert(false, "Unreachable Code. Top level parent is eitehr ScriptBlockAst or FunctionDefinitionAst, so it should return within the loop for sure.");
            // I don't think it's reachable, but if it happens, just assume there are UsingExpressions in different scopes.
            return(true);
        }
コード例 #15
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     return(false);
 }
コード例 #16
0
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst ast)
 {
     return(DoNextAction(ast));
 }
コード例 #17
0
        private void ConvertCommand(CommandAst commandAst)
        {
            Command command = new Command(this.GetCommandName(commandAst.CommandElements[0]), false, this._createLocalScope);

            if (commandAst.Redirections.Count > 0)
            {
                PipelineResultTypes all;
                PipelineResultTypes output = PipelineResultTypes.Output;
                switch (commandAst.Redirections[0].FromStream)
                {
                case RedirectionStream.All:
                    all = PipelineResultTypes.All;
                    break;

                case RedirectionStream.Error:
                    all = PipelineResultTypes.Error;
                    break;

                case RedirectionStream.Warning:
                    all = PipelineResultTypes.Warning;
                    break;

                case RedirectionStream.Verbose:
                    all = PipelineResultTypes.Verbose;
                    break;

                case RedirectionStream.Debug:
                    all = PipelineResultTypes.Debug;
                    break;

                default:
                    all = PipelineResultTypes.Error;
                    break;
                }
                command.MergeMyResults(all, output);
            }
            this._powershell.AddCommand(command);
            foreach (CommandElementAst ast in commandAst.CommandElements.Skip <CommandElementAst>(1))
            {
                ExpressionAst exprAst = ast as ExpressionAst;
                if (exprAst != null)
                {
                    VariableExpressionAst variableAst = null;
                    UsingExpressionAst    ast4        = ast as UsingExpressionAst;
                    if (ast4 != null)
                    {
                        variableAst = ast4.SubExpression as VariableExpressionAst;
                        if ((variableAst != null) && variableAst.Splatted)
                        {
                            IDictionary parameters = this._usingValues[ast4.RuntimeUsingIndex] as IDictionary;
                            if (parameters != null)
                            {
                                this._powershell.AddParameters(parameters);
                            }
                            else
                            {
                                IEnumerable enumerable = this._usingValues[ast4.RuntimeUsingIndex] as IEnumerable;
                                if (enumerable != null)
                                {
                                    foreach (object obj2 in enumerable)
                                    {
                                        this._powershell.AddArgument(obj2);
                                    }
                                }
                                else
                                {
                                    this._powershell.AddArgument(this._usingValues[ast4.RuntimeUsingIndex]);
                                }
                            }
                        }
                        else
                        {
                            this._powershell.AddArgument(this._usingValues[ast4.RuntimeUsingIndex]);
                        }
                    }
                    else
                    {
                        variableAst = ast as VariableExpressionAst;
                        if ((variableAst != null) && variableAst.Splatted)
                        {
                            this.GetSplattedVariable(variableAst);
                        }
                        else
                        {
                            object expressionValue;
                            ConstantExpressionAst ast5 = ast as ConstantExpressionAst;
                            if ((ast5 != null) && LanguagePrimitives.IsNumeric(LanguagePrimitives.GetTypeCode(ast5.StaticType)))
                            {
                                string text = ast5.Extent.Text;
                                expressionValue = ast5.Value;
                                if (!text.Equals(ast5.Value.ToString(), StringComparison.Ordinal))
                                {
                                    expressionValue = ParserOps.WrappedNumber(expressionValue, text);
                                }
                            }
                            else
                            {
                                expressionValue = this.GetExpressionValue(exprAst);
                            }
                            this._powershell.AddArgument(expressionValue);
                        }
                    }
                }
                else
                {
                    this.AddParameter((CommandParameterAst)ast);
                }
            }
        }
コード例 #18
0
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     this.HasUsingExpr = true;
     return(AstVisitAction.SkipChildren);
 }
コード例 #19
0
 public virtual object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     VisitElement(usingExpressionAst.SubExpression);
     return(usingExpressionAst);
 }
コード例 #20
0
ファイル: VisitorBase.cs プロジェクト: altrive/PSCodeAnalyzer
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst ast)
 {
     return(AstVisitAction.Continue);
 }
コード例 #21
0
        public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
        {
            var newUsingExpr = VisitElement(usingExpressionAst.SubExpression);

            return(new UsingExpressionAst(usingExpressionAst.Extent, newUsingExpr));
        }
コード例 #22
0
 public static UsingExpressionAst Update(this UsingExpressionAst ast, ExpressionAst expressionAst = null)
 {
     return(new UsingExpressionAst(
                ast.Extent,
                expressionAst?.Clone() ?? ast.SubExpression?.Clone()));
 }
コード例 #23
0
        /// <summary>
        /// Walks the using Ast to verify it is used within a foreach-object -parallel command
        /// and parameter set scope, and not from within a nested foreach-object -parallel call.
        /// </summary>
        /// <param name="usingAst">Using Ast to check.</param>
        /// <param name-"foreachNames">List of foreach-object command names.</param>
        /// <returns>True if using expression is in current call scope.</returns>
        private static bool IsInForeachParallelCallingScope(
            UsingExpressionAst usingAst,
            string[] foreachNames)
        {
            /*
             *  Example:
             *  $Test1 = "Hello"
             *  1 | ForEach-Object -Parallel {
             *     $using:Test1
             *     $Test2 = "Goodbye"
             *     1 | ForEach-Object -Parallel {
             *         $using:Test1    # Invalid using scope
             *         $using:Test2    # Valid using scope
             *     }
             *  }
             */
            Diagnostics.Assert(usingAst != null, "usingAst argument cannot be null.");

            // Search up the parent Ast chain for 'Foreach-Object -Parallel' commands.
            Ast currentParent      = usingAst.Parent;
            int foreachNestedCount = 0;

            while (currentParent != null)
            {
                // Look for Foreach-Object outer commands
                if (currentParent is CommandAst commandAst)
                {
                    foreach (var commandElement in commandAst.CommandElements)
                    {
                        if (commandElement is StringConstantExpressionAst commandName)
                        {
                            bool found = false;
                            foreach (var foreachName in foreachNames)
                            {
                                if (commandName.Value.Equals(foreachName, StringComparison.OrdinalIgnoreCase))
                                {
                                    found = true;
                                    break;
                                }
                            }

                            if (found)
                            {
                                // Verify this is foreach-object with parallel parameter set.
                                var bindingResult = StaticParameterBinder.BindCommand(commandAst);
                                if (bindingResult.BoundParameters.ContainsKey("Parallel"))
                                {
                                    foreachNestedCount++;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (foreachNestedCount > 1)
                {
                    // This using expression Ast is outside the original calling scope.
                    return(false);
                }

                currentParent = currentParent.Parent;
            }

            return(foreachNestedCount == 1);
        }
コード例 #24
0
 /// <summary/>
 public virtual AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst) => DefaultVisit(usingExpressionAst);
コード例 #25
0
 public override ExpressionAst VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 => VisitExpression(base.VisitUsingExpression(usingExpressionAst));
コード例 #26
0
        private static object[] GetUsingValues(Ast body, ExecutionContext context, Dictionary <string, object> variables, bool filterNonUsingVariables)
        {
            List <Ast> list = UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(body).ToList <Ast>();

            object[]           objArray          = new object[list.Count];
            HashSet <string>   set               = ((variables != null) && filterNonUsingVariables) ? new HashSet <string>() : null;
            UsingExpressionAst usingExpr         = null;
            Version            strictModeVersion = null;

            try
            {
                if (context != null)
                {
                    strictModeVersion = context.EngineSessionState.CurrentScope.StrictModeVersion;
                    context.EngineSessionState.CurrentScope.StrictModeVersion = PSVersionInfo.PSVersion;
                }
                for (int i = 0; i < objArray.Length; i++)
                {
                    usingExpr = (UsingExpressionAst)list[i];
                    if (IsUsingExpressionInFunction(usingExpr, body))
                    {
                        throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException), usingExpr.Extent, "UsingVariableNotSupportedInFunctionOrFilter", AutomationExceptions.UsingVariableNotSupportedInFunctionOrFilter, new object[] { usingExpr });
                    }
                    object obj2 = null;
                    if (variables != null)
                    {
                        VariableExpressionAst subExpression = usingExpr.SubExpression as VariableExpressionAst;
                        if (subExpression == null)
                        {
                            throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException), usingExpr.Extent, "CantGetUsingExpressionValueWithSpecifiedVariableDictionary", AutomationExceptions.CantGetUsingExpressionValueWithSpecifiedVariableDictionary, new object[] { usingExpr.Extent.Text });
                        }
                        string userPath = subExpression.VariablePath.UserPath;
                        if (((userPath != null) && variables.TryGetValue(userPath, out obj2)) && (set != null))
                        {
                            set.Add(userPath);
                        }
                    }
                    else
                    {
                        obj2 = Compiler.GetExpressionValue(usingExpr.SubExpression, context, (IList)null);
                    }
                    objArray[i] = obj2;
                    usingExpr.RuntimeUsingIndex = i;
                }
            }
            catch (RuntimeException exception)
            {
                if (exception.ErrorRecord.FullyQualifiedErrorId.Equals("VariableIsUndefined", StringComparison.Ordinal))
                {
                    throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException), usingExpr.Extent, "UsingVariableIsUndefined", AutomationExceptions.UsingVariableIsUndefined, new object[] { exception.ErrorRecord.TargetObject });
                }
                if (exception.ErrorRecord.FullyQualifiedErrorId.Equals("UsingVariableNotSupportedInFunctionOrFilter", StringComparison.Ordinal) || exception.ErrorRecord.FullyQualifiedErrorId.Equals("CantGetUsingExpressionValueWithSpecifiedVariableDictionary", StringComparison.Ordinal))
                {
                    throw;
                }
            }
            finally
            {
                if (context != null)
                {
                    context.EngineSessionState.CurrentScope.StrictModeVersion = strictModeVersion;
                }
            }
            if (set != null)
            {
                foreach (string str2 in variables.Keys.ToArray <string>())
                {
                    if (!set.Contains(str2))
                    {
                        variables.Remove(str2);
                    }
                }
            }
            return(objArray);
        }
コード例 #27
0
        /// <summary>
        /// Collect values for UsingExpressions, in the form of a dictionary and an array.
        ///  - The dictionary form is used when the remote server is PSv5 and later version for handling UsingExpression in Invoke-Command/Start-Job
        ///  - The array form is used when the remote server is PSv3 and PSv4 for handling UsingExpression in Invoke-Command.
        /// </summary>
        /// <remarks>
        /// We still keep the array-form using values because we want to avoid any breaking changes when running Invoke-Command
        /// targeting PSv3 or PSv4 remote end -- if UsingExpressions are all in the same scope, then we still pass an array of using
        /// values to the remote end; otherwise, we will handle UsingExpression as if the remote end is PSv2.
        /// </remarks>
        /// <returns>
        /// A tuple of the dictionary-form and the array-form using values.
        /// If the array-form using value is null, then there are UsingExpressions used in different scopes.
        /// </returns>
        private static Tuple <Dictionary <string, object>, object[]> GetUsingValues(Ast body, bool isTrustedInput, ExecutionContext context, Dictionary <string, object> variables, bool filterNonUsingVariables)
        {
            Diagnostics.Assert(context != null || variables != null, "can't retrieve variables with no context and no variables");

            var usingAsts                  = UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow(body).ToList();
            var usingValueArray            = new object[usingAsts.Count];
            var usingValueMap              = new Dictionary <string, object>(usingAsts.Count);
            HashSet <string> usingVarNames = (variables != null && filterNonUsingVariables) ? new HashSet <string>() : null;

            // Used to check if the PSv3/PSv4 way of handling UsingExpression can continue to be used.
            bool           hasUsingExprInDifferentScope = false;
            ScriptBlockAst sbClosestToPreUsingExpr      = null;

            UsingExpressionAst usingAst         = null;
            Version            oldStrictVersion = null;

            try
            {
                if (context != null)
                {
                    oldStrictVersion = context.EngineSessionState.CurrentScope.StrictModeVersion;
                    context.EngineSessionState.CurrentScope.StrictModeVersion = PSVersionInfo.PSVersion;
                }

                for (int i = 0; i < usingAsts.Count; ++i)
                {
                    usingAst = (UsingExpressionAst)usingAsts[i];
                    object value = null;

                    // This happens only when GetUsingValues gets called outside the ScriptBlockToPowerShellConverter class
                    if (!hasUsingExprInDifferentScope && HasUsingExpressionsInDifferentScopes(usingAst, body, ref sbClosestToPreUsingExpr))
                    {
                        // If there are UsingExpressions in different scopes, the array-form using values will not be useful
                        // even if the remote end is PSv3 or PSv4, because the way we handle using expression in PSv3 and PSv4
                        // doesn't support UsingExpression in different scopes. In this case, we will set the array-form using
                        // value to be null before return.
                        //
                        // Note that this check only affect array-form using value. In PSv5, we change the way to handle UsingExpression
                        // on both client and server sides. The dictionary-form using values is used and UsingExpression in different
                        // scope is supported.
                        hasUsingExprInDifferentScope = true;
                    }

                    if (variables != null)
                    {
                        var variableAst = usingAst.SubExpression as VariableExpressionAst;
                        if (variableAst == null)
                        {
                            throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException),
                                                                           usingAst.Extent, "CantGetUsingExpressionValueWithSpecifiedVariableDictionary", AutomationExceptions.CantGetUsingExpressionValueWithSpecifiedVariableDictionary, usingAst.Extent.Text);
                        }

                        string varName = variableAst.VariablePath.UserPath;
                        if (varName != null && variables.TryGetValue(varName, out value) && usingVarNames != null)
                        {
                            usingVarNames.Add(varName);
                        }
                    }
                    else
                    {
                        value = Compiler.GetExpressionValue(usingAst.SubExpression, isTrustedInput, context);
                    }

                    // Collect UsingExpression value as an array
                    usingValueArray[i] = value;

                    // Collect UsingExpression value as a dictionary
                    string usingAstKey = PsUtils.GetUsingExpressionKey(usingAst);
                    usingValueMap.TryAdd(usingAstKey, value);
                }
            }
            catch (RuntimeException rte)
            {
                if (rte.ErrorRecord.FullyQualifiedErrorId.Equals("VariableIsUndefined", StringComparison.Ordinal))
                {
                    throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException),
                                                                   usingAst.Extent, "UsingVariableIsUndefined", AutomationExceptions.UsingVariableIsUndefined, rte.ErrorRecord.TargetObject);
                }
                else if (rte.ErrorRecord.FullyQualifiedErrorId.Equals("CantGetUsingExpressionValueWithSpecifiedVariableDictionary", StringComparison.Ordinal))
                {
                    throw;
                }
            }
            finally
            {
                if (context != null)
                {
                    context.EngineSessionState.CurrentScope.StrictModeVersion = oldStrictVersion;
                }
            }

            if (usingVarNames != null)
            {
                string[] keys = variables.Keys.ToArray();
                foreach (string key in keys)
                {
                    if (!usingVarNames.Contains(key))
                    {
                        variables.Remove(key);
                    }
                }
            }

            if (hasUsingExprInDifferentScope)
            {
                usingValueArray = null;
            }

            return(Tuple.Create(usingValueMap, usingValueArray));
        }
コード例 #28
0
 public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     throw new NotImplementedException(); //VisitUsingExpression(usingExpressionAst);
 }
コード例 #29
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     // $using:true should be safe - it's silly to write that, but not harmful.
     return(usingExpressionAst.SubExpression.Accept(this));
 }
コード例 #30
0
 public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
 {
     throw new UnexpectedElementException();
 }