Beispiel #1
0
        internal static PowerShell Convert(ScriptBlockAst body,
                                           ReadOnlyCollection <ParameterAst> functionParameters,
                                           bool isTrustedInput,
                                           ExecutionContext context,
                                           Dictionary <string, object> variables,
                                           bool filterNonUsingVariables,
                                           bool?createLocalScope,
                                           object[] args)
        {
            ExecutionContext.CheckStackDepth();

            if (args == null)
            {
                args = Array.Empty <object>();
            }

            // Perform validations on the ScriptBlock.  GetSimplePipeline can allow for more than one
            // pipeline if the first parameter is true, but Invoke-Command doesn't yet support multiple
            // pipelines in a PowerShell (it just grabs the last command directly.)  The rest of this
            // code properly supports multiple pipelines, so it should just work to change the false to true
            // if/when Invoke-Command can support multiple pipelines.
            string errorId;
            string errorMsg;

            body.GetSimplePipeline(true, out errorId, out errorMsg);
            if (errorId != null)
            {
                throw new ScriptBlockToPowerShellNotSupportedException(errorId, null, errorMsg);
            }

            var checker = new ScriptBlockToPowerShellChecker {
                ScriptBeingConverted = body
            };

            if (functionParameters != null)
            {
                foreach (var parameter in functionParameters)
                {
                    parameter.InternalVisit(checker);
                }
            }

            body.InternalVisit(checker);

            // When the context is null (or they haven't supplied any variables), throw, but only if we really need the
            // context (basically, if we have some variable reference to resolve).
            if (context == null && (checker.HasUsingExpr || checker.UsesParameter) && (variables == null))
            {
                throw new PSInvalidOperationException(AutomationExceptions.CantConvertScriptBlockWithNoContext);
            }

            try
            {
                var converter = new ScriptBlockToPowerShellConverter {
                    _context = context, _createLocalScope = createLocalScope
                };

                if (checker.HasUsingExpr)
                {
                    converter._usingValueMap = GetUsingValues(body, isTrustedInput, context, variables, filterNonUsingVariables).Item1;
                }

                if (checker.UsesParameter)
                {
                    // If any parameters are used, we create a new scope and bind the parameters.

                    var newScope = context.EngineSessionState.NewScope(false);
                    context.EngineSessionState.CurrentScope             = newScope;
                    context.EngineSessionState.CurrentScope.ScopeOrigin = CommandOrigin.Internal;

                    var locals =
                        MutableTuple.MakeTuple(Compiler.DottedLocalsTupleType, Compiler.DottedLocalsNameIndexMap);

                    // Get the parameter metadata for the script block.
                    // If 'functionParameters' is not null, then the ScriptBlockAst is actually the body of a FunctionDefinitionAst, and it doesn't have a ParamBlock.
                    // If 'functionParameters' is null, then the ScriptBlockAst may have parameters defined in its ParamBlock.
                    bool usesCmdletBinding = false;
                    var  parameters        = functionParameters != null
                                         ? Compiler.GetParameterMetaData(functionParameters, true, ref usesCmdletBinding)
                                         : ((IParameterMetadataProvider)body).GetParameterMetadata(true, ref usesCmdletBinding);

                    object[] remainingArgs = ScriptBlock.BindArgumentsForScriptblockInvoke(
                        (RuntimeDefinedParameter[])parameters.Data, args, context, false, null, locals);
                    locals.SetAutomaticVariable(AutomaticVariable.Args, remainingArgs, context);
                    newScope.LocalsTuple = locals;
                }

                foreach (var pipeline in body.EndBlock.Statements.OfType <PipelineAst>())
                {
                    converter._powershell.AddStatement();
                    converter.ConvertPipeline(pipeline, isTrustedInput);
                }

                return(converter._powershell);
            }
            finally
            {
                if (checker.UsesParameter)
                {
                    context.EngineSessionState.RemoveScope(context.EngineSessionState.CurrentScope);
                }
            }
        }
Beispiel #2
0
        internal static PowerShell Convert(ScriptBlockAst body, IEnumerable <ParameterAst> functionParameters, ExecutionContext context, Dictionary <string, object> variables, bool filterNonUsingVariables, bool?createLocalScope, object[] args)
        {
            string     str;
            string     str2;
            PowerShell shell;

            ExecutionContext.CheckStackDepth();
            if (args == null)
            {
                args = ScriptBlock.EmptyArray;
            }
            body.GetSimplePipeline(false, out str, out str2);
            if (str != null)
            {
                throw new ScriptBlockToPowerShellNotSupportedException(str, null, str2, new object[0]);
            }
            ScriptBlockToPowerShellChecker visitor = new ScriptBlockToPowerShellChecker {
                ScriptBeingConverted = body
            };

            if (functionParameters != null)
            {
                foreach (ParameterAst ast in functionParameters)
                {
                    ast.InternalVisit(visitor);
                }
            }
            body.InternalVisit(visitor);
            if (((context == null) && (visitor.HasUsingExpr || visitor.UsesParameter)) && (variables == null))
            {
                throw new PSInvalidOperationException(AutomationExceptions.CantConvertScriptBlockWithNoContext);
            }
            try
            {
                ScriptBlockToPowerShellConverter converter = new ScriptBlockToPowerShellConverter {
                    _context          = context,
                    _createLocalScope = createLocalScope
                };
                if (visitor.HasUsingExpr)
                {
                    converter._usingValues = GetUsingValues(body, context, variables, filterNonUsingVariables);
                }
                if (visitor.UsesParameter)
                {
                    SessionStateScope scope = context.EngineSessionState.NewScope(false);
                    context.EngineSessionState.CurrentScope             = scope;
                    context.EngineSessionState.CurrentScope.ScopeOrigin = CommandOrigin.Internal;
                    MutableTuple locals            = MutableTuple.MakeTuple(Compiler.DottedLocalsTupleType, Compiler.DottedLocalsNameIndexMap);
                    bool         usesCmdletBinding = false;
                    object[]     objArray          = ScriptBlock.BindArgumentsForScripblockInvoke((RuntimeDefinedParameter[])((IParameterMetadataProvider)body).GetParameterMetadata(true, ref usesCmdletBinding).Data, args, context, false, null, locals);
                    locals.SetAutomaticVariable(AutomaticVariable.Args, objArray, context);
                    scope.LocalsTuple = locals;
                }
                foreach (PipelineAst ast2 in body.EndBlock.Statements.OfType <PipelineAst>())
                {
                    converter._powershell.AddStatement();
                    converter.ConvertPipeline(ast2);
                }
                shell = converter._powershell;
            }
            finally
            {
                if (visitor.UsesParameter)
                {
                    context.EngineSessionState.RemoveScope(context.EngineSessionState.CurrentScope);
                }
            }
            return(shell);
        }