Example #1
0
        /// <summary>
        /// Create a Proxy Function for the command supplied.
        /// </summary>
        /// <param name="commandInfo"></param>
        /// <param name="debugStrings"></param>
        /// <returns></returns>
        internal static FunctionInfo CreateProxyFunction(CommandInfo commandInfo, List <string> debugStrings)
        {
            string         proxyCommandName = null;
            string         proxyCommand     = ProxyCommand.Create(new CommandMetadata(commandInfo));
            ScriptBlock    proxyScript      = ScriptBlock.Create(proxyCommand);
            ScriptBlockAst proxyScriptAst   = (ScriptBlockAst)proxyScript.Ast;

            string proxyScriptStr = proxyScriptAst.ParamBlock.ToString() + "; return $PSBoundParameters";

            proxyScriptStr = proxyScriptStr.Replace("\r\n", string.Empty);
            debugStrings.Add(proxyScriptStr);
            if (commandInfo.CommandType == CommandTypes.ExternalScript)
            {
                proxyCommandName = commandInfo.Name.Split('\\').LastOrDefault().Replace(".ps1", "IvAllhelper.ps1");
            }
            else
            {
                proxyCommandName = commandInfo.Name + "IvAllhelper";
            }

            debugStrings.Add(string.Format("Creating ProxyFunction {0}", proxyCommandName));

            try
            {
                PSObject proxyFunctionPSObj = ScriptBlock.Create("param($name, $script) New-Item -Path Function:Global:$name -Value $script -Erroraction Stop")
                                              .Invoke(proxyCommandName, proxyScriptStr).FirstOrDefault();
                debugStrings.Add(string.Format("Created proxy command {0}", proxyCommandName));

                return(proxyFunctionPSObj.BaseObject as FunctionInfo);
            }
            catch (ActionPreferenceStopException ae) when((ae.ErrorRecord.Exception is PSArgumentException) && ae.ErrorRecord.Exception.Message.EndsWith("already exists."))
            {
                //Todo: throwterminatingerror here
                debugStrings.Add("ProxyCommand Already Exsits");
                string removeProxyFunction = string.Format("Remove-Item -Path Function:{0} -Force", proxyCommandName);

                ScriptBlock.Create(removeProxyFunction).Invoke();
                throw new Exception(string.Format("Proxy function {0} already exists. It is present from a previous failure of Invoke-all, the script tried to remove it. " +
                                                  "Simply re-run your command to see if it works, if not, please manually remove the function using {1}", proxyCommandName, removeProxyFunction));
            }
        }
        /// <summary>
        /// Run some commands to demonstrate the script capabilities.
        /// </summary>
        private void RunCommands()
        {
            this.runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());
            this.runspace.Open();
            this.RunScript("$a=0;$a", "Assigning to a variable will work for a default InitialSessionState");
            this.runspace.Close();

            this.runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());
            this.runspace.InitialSessionState.LanguageMode = PSLanguageMode.RestrictedLanguage;
            this.runspace.Open();
            this.RunScript("$a=0;$a", "Assigning to a variable will not work in RestrictedLanguage LanguageMode");
            this.runspace.Close();

            this.runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());
            this.runspace.InitialSessionState.LanguageMode = PSLanguageMode.NoLanguage;
            this.runspace.Open();
            this.RunScript("10/2", "A script will not work in NoLanguage LanguageMode");
            this.runspace.Close();

            this.runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());
            this.runspace.Open();
            string scriptComment = "get-childitem with a default InitialSessionState will work since the standard \n" +
                                   "PowerShell cmdlets are included in the default InitialSessionState";

            this.RunScript("get-childitem", scriptComment);
            this.runspace.Close();

            InitialSessionState defaultSessionState = InitialSessionState.CreateDefault();

            defaultSessionState.Commands.Add(new SessionStateAliasEntry("dir2", "get-childitem"));
            this.runspace = RunspaceFactory.CreateRunspace(defaultSessionState);
            this.runspace.Open();
            this.RunScript("dir2", "An alias, like dir2, can be added to InitialSessionState");
            this.runspace.Close();

            defaultSessionState = InitialSessionState.CreateDefault();
            int commandIndex = GetIndexOfEntry(defaultSessionState.Commands, "get-childitem");

            defaultSessionState.Commands.RemoveItem(commandIndex);
            this.runspace = RunspaceFactory.CreateRunspace(defaultSessionState);
            this.runspace.Open();
            scriptComment = "get-childitem was removed from the list of commands so it\nwill no longer be found";
            this.RunScript("get-childitem", scriptComment);
            this.runspace.Close();

            defaultSessionState = InitialSessionState.CreateDefault();
            defaultSessionState.Providers.Clear();
            this.runspace = RunspaceFactory.CreateRunspace(defaultSessionState);
            this.runspace.Open();
            this.RunScript("get-childitem", "There are no providers so get-childitem will not work");
            this.runspace.Close();

            // Marks a command as private, and then defines a proxy command
            // that uses the private command.  One reason to define a proxy for a command is
            // to remove a parameter of the original command.
            // For a more complete sample of a proxy command, see the Runspace11 sample.
            defaultSessionState = InitialSessionState.CreateDefault();
            commandIndex        = GetIndexOfEntry(defaultSessionState.Commands, "get-childitem");
            defaultSessionState.Commands[commandIndex].Visibility = SessionStateEntryVisibility.Private;
            CommandMetadata getChildItemMetadata = new CommandMetadata(
                typeof(Microsoft.PowerShell.Commands.GetChildItemCommand));

            getChildItemMetadata.Parameters.Remove("Recurse");
            string getChildItemBody = ProxyCommand.Create(getChildItemMetadata);

            defaultSessionState.Commands.Add(new SessionStateFunctionEntry("get-childitem2", getChildItemBody));
            this.runspace = RunspaceFactory.CreateRunspace(defaultSessionState);
            this.runspace.Open();
            this.RunScript("get-childitem", "get-childitem is private so it will not be available");
            scriptComment = "get-childitem2 is is a proxy to get-childitem. \n" +
                            "It works even when get-childitem is private.";
            this.RunScript("get-childitem2", scriptComment);
            scriptComment = "This will fail. Unlike get-childitem, get-childitem2 does not have -Recurse";
            this.RunScript("get-childitem2 -Recurse", scriptComment);

            InitialSessionState cleanSessionState = InitialSessionState.Create();

            this.runspace = RunspaceFactory.CreateRunspace(cleanSessionState);
            this.runspace.Open();
            scriptComment = "A script will not work because \n" +
                            "InitialSessionState.Create() will have the default LanguageMode of NoLanguage";
            this.RunScript("10/2", scriptComment);
            this.runspace.Close();

            cleanSessionState = InitialSessionState.Create();
            cleanSessionState.LanguageMode = PSLanguageMode.FullLanguage;
            this.runspace = RunspaceFactory.CreateRunspace(cleanSessionState);
            this.runspace.Open();
            scriptComment = "get-childitem, standard cmdlets and providers are not present \n" +
                            "in an InitialSessionState returned from InitialSessionState.Create()";
            this.RunScript("get-childitem", scriptComment);
            this.runspace.Close();

            cleanSessionState = InitialSessionState.Create();
            cleanSessionState.Commands.Add(
                new SessionStateCmdletEntry(
                    "Get-ChildItem",
                    typeof(Microsoft.PowerShell.Commands.GetChildItemCommand),
                    null));
            cleanSessionState.Providers.Add(
                new SessionStateProviderEntry(
                    "FileSystem",
                    typeof(Microsoft.PowerShell.Commands.FileSystemProvider),
                    null));
            cleanSessionState.LanguageMode = PSLanguageMode.FullLanguage;
            this.runspace = RunspaceFactory.CreateRunspace(cleanSessionState);
            this.runspace.Open();
            scriptComment = "get-childitem and the FileSystem provider were explicitly added\n" +
                            "so get-childitem will work";
            this.RunScript("get-childitem", scriptComment);
            this.runspace.Close();

            Console.Write("Done...");
            Console.ReadLine();
        }
Example #3
0
        /// <summary>
        /// This sample uses the ProxyCommand class to create a proxy command that
        /// calls an existing cmdlet, but restricts the set of available parameters.
        /// The proxy command is then added to an intial session state that is used to
        /// create a contrained runspace. This means that the user can access the cmdlet
        /// through the proxy command.
        /// </summary>
        /// <remarks>
        /// This sample demonstrates the following:
        /// 1. Creating a CommandMetadata object that describes the metadata of an
        ///    existing cmdlet.
        /// 2. Modifying the cmdlet metadata to remove a parameter of the cmdlet.
        /// 3. Adding the cmdlet to an initial session state and making it private.
        /// 4. Creating a proxy function that calls the existing cmdlet, but exposes
        ///    only a restricted set of parameters.
        /// 6. Adding the proxy function to the initial session state.
        /// 7. Calling the private cmdlet and the proxy function to demonstrate the
        ///    constrained runspace.
        /// </remarks>
        private static void Main()
        {
            // Create a default intial session state. The default inital session state
            // includes all the elements that are provided by Windows PowerShell.
            InitialSessionState iss = InitialSessionState.CreateDefault();

            // Add the get-proc cmdlet to the initial session state.
            SessionStateCmdletEntry cmdletEntry = new SessionStateCmdletEntry("get-proc", typeof(GetProcCommand), null);

            iss.Commands.Add(cmdletEntry);

            // Make the cmdlet private so that it is not accessable.
            cmdletEntry.Visibility = SessionStateEntryVisibility.Private;

            // Set the language mode of the intial session state to NoLanguge to
            //prevent users from using language features. Only the invocation of
            // public commands is allowed.
            iss.LanguageMode = PSLanguageMode.NoLanguage;

            // Create the proxy command using cmdlet metadata to expose the
            // get-proc cmdlet.
            CommandMetadata cmdletMetadata = new CommandMetadata(typeof(GetProcCommand));

            // Remove one of the parameters from the command metadata.
            cmdletMetadata.Parameters.Remove("Name");

            // Generate the body of a proxy function that calls the original cmdlet,
            // but does not have the removed parameter.
            string bodyOfProxyFunction = ProxyCommand.Create(cmdletMetadata);

            // Add the proxy function to the initial session state. The name of the proxy
            // function can be the same as the name of the cmdlet, but to clearly
            // demonstrate that the original cmdlet is not available a different name is
            // used for the proxy function.
            iss.Commands.Add(new SessionStateFunctionEntry("get-procProxy", bodyOfProxyFunction));

            // Create the constrained runspace using the intial session state.
            using (Runspace myRunspace = RunspaceFactory.CreateRunspace(iss))
            {
                myRunspace.Open();

                // Call the private cmdlet to demonstrate that it is not available.
                try
                {
                    using (PowerShell powershell = PowerShell.Create())
                    {
                        powershell.Runspace = myRunspace;
                        powershell.AddCommand("get-proc").AddParameter("Name", "*explore*");
                        powershell.Invoke();
                    }
                }
                catch (CommandNotFoundException e)
                {
                    System.Console.WriteLine(
                        "Invoking 'get-proc' failed as expected: {0}: {1}",
                        e.GetType().FullName,
                        e.Message);
                }

                // Call the proxy function to demonstrate that the -Name parameter is
                // not available.
                try
                {
                    using (PowerShell powershell = PowerShell.Create())
                    {
                        powershell.Runspace = myRunspace;
                        powershell.AddCommand("get-procProxy").AddParameter("Name", "idle");
                        powershell.Invoke();
                    }
                }
                catch (ParameterBindingException e)
                {
                    System.Console.WriteLine(
                        "\nInvoking 'get-procProxy -Name idle' failed as expected: {0}: {1}",
                        e.GetType().FullName,
                        e.Message);
                }

                // Call the proxy function to demonstrate that it calls into the
                // private cmdlet to retrieve the processes.
                using (PowerShell powershell = PowerShell.Create())
                {
                    powershell.Runspace = myRunspace;
                    powershell.AddCommand("get-procProxy");
                    List <Process> processes = new List <Process>(powershell.Invoke <Process>());
                    System.Console.WriteLine(
                        "\nInvoking the get-procProxy function called into the get-proc cmdlet and returned {0} processes",
                        processes.Count);
                }

                // Close the runspace to release resources.
                myRunspace.Close();
            }

            System.Console.WriteLine("Hit any key to exit...");
            System.Console.ReadKey();
        }