Пример #1
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));
        }
Пример #2
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);
        }