Пример #1
0
        private object GetNodeChildrenDynamicParameters(SHiPSDirectory node)
        {
            var script     = Constants.ScriptBlockWithParam1.StringFormat(Constants.GetChildItemDynamicParameters);
            var parameters = PSScriptRunner.InvokeScriptBlock(null, node, _drive, script, PSScriptRunner.ReportErrors);

            return(parameters?.FirstOrDefault());
        }
Пример #2
0
        private static IEnumerable <IPathNode> ProcessResultsWithCache(
            ICollection <object> results,
            IProviderContext context,
            SHiPSDirectory node,
            SHiPSDrive drive)
        {
            //TODO: async vs cache
            //we could yield result right away but we need to save the all children in the meantime because
            //InvokeScript can be costly.So we need to cache the results first by completing the foreach before
            //returning to a caller.

            List <IPathNode> retval = new List <IPathNode>();

            //clear the child node list, get ready to get the refreshed ones
            node.Children?.Clear();

            foreach (var result in results.WhereNotNull())
            {
                // Making sure to obey the StopProcessing.
                if (context.Stopping)
                {
                    return(null);
                }
                node.AddAsChildNode(result, drive, retval);
            }

            // Mark the node visited once we sucessfully fetched data.
            node.ItemNavigated = true;

            return(retval);
        }
Пример #3
0
 internal ContainerNodeService(SHiPSDrive drive, object container, SHiPSDirectory parent)
 {
     _drive     = drive;
     _container = container as SHiPSDirectory;
     if (_container != null)
     {
         _container.Parent = parent;
     }
 }
Пример #4
0
 internal LeafNodeService(object leafObject, SHiPSDrive drive, SHiPSDirectory parent)
 {
     _shipsLeaf     = leafObject as SHiPSLeaf;
     _drive         = drive;
     _contentHelper = new ContentHelper(_shipsLeaf, drive);
     if (_shipsLeaf != null)
     {
         _shipsLeaf.Parent = parent;
     }
 }
Пример #5
0
        internal static IPathNode AddAsChildNode(this SHiPSDirectory parent, object child, SHiPSDrive drive, List <IPathNode> list)
        {
            var pNode = GetChildPNode(parent, child, drive, cache: true);

            if (pNode == null)
            {
                return(null);
            }

            //add to its child list
            parent.Children.GetOrCreateEntryIfDefault(pNode.Name, () => new List <IPathNode>()).Add(pNode);
            list.Add(pNode);
            return(pNode);
        }
Пример #6
0
        internal static IPathNode GetChildPNode(this SHiPSDirectory parent, object child, SHiPSDrive drive, bool addNodeOnly, bool cache)
        {
            if (child == null || parent == null)
            {
                return(null);
            }

            var pNode = child.ToPathNode(drive, parent);

            if (pNode != null)
            {
                if (string.IsNullOrWhiteSpace(pNode.Name))
                {
                    //let the program continue by logging warning only because one bad node should not stop the navigation.
                    drive.SHiPS.WriteWarning(Resources.Resource.NameWithNullOrEmpty.StringFormat(parent.Name));
                    // throw new InvalidDataException(Resources.Resource.NameWithNullOrEmpty.StringFormat(parent.Name));
                    return(null);
                }

                if (!cache)
                {
                    return(pNode);
                }
                //warning if nodes have the same name because "directory" cannot be the same name
                var existNode = parent.Children.Get(pNode.Name);
                var first     = existNode?.FirstOrDefault();
                if (first != null)
                {
                    if (addNodeOnly)
                    {
                        // replace the existing node
                        parent.Children.RemoveSafe(pNode.Name);
                        return(pNode);
                    }
                    if (first.GetNodeValue().IsCollection ||
                        (pNode is ContainerNodeService &&
                         !((ContainerNodeService)pNode).ContainerNode.IsLeaf))
                    {
                        drive.SHiPS.WriteWarning(
                            Resources.Resource.NodesWithSameName.StringFormat(
                                parent.Name.EqualsIgnoreCase(drive.RootNode.Name) ? "root" : parent.Name, pNode.Name));
                        return(null);
                    }
                }

                return(pNode);
            }

            return(null);
        }
Пример #7
0
        private static IEnumerable <IPathNode> ProcessResultsWithNoCache(
            ICollection <object> results,
            IProviderContext context,
            SHiPSDirectory node,
            SHiPSDrive drive)
        {
            foreach (var result in results.WhereNotNull())
            {
                // Making sure to obey the StopProcessing.
                if (context.Stopping)
                {
                    yield break;
                }

                var cnode = node.GetChildPNode(result, drive, false, cache: false);
                if (cnode != null)
                {
                    yield return(cnode);
                }
            }
        }
Пример #8
0
        internal static bool NeedRefresh(this IProviderContext context, SHiPSDirectory node, SHiPSDrive drive)
        {
            var myInvocationInfo     = GetMyInvocationInfo(context.CmdletProvider);
            var verbose              = false;
            var debug                = false;
            var force                = false;
            var usedDynamicParameter = false;

            if (myInvocationInfo == null)
            {
                return(false);
            }

            var boundParameters = myInvocationInfo.BoundParameters;

            if (boundParameters.Any())
            {
                object argument;

                if (boundParameters.TryGetValue("Force", out argument))
                {
                    force = ((SwitchParameter)argument).IsPresent;
                }
                if (!force && boundParameters.TryGetValue("Verbose", out argument))
                {
                    verbose = ((SwitchParameter)argument).IsPresent;
                }
                if (!verbose && !force && boundParameters.TryGetValue("Debug", out argument))
                {
                    debug = ((SwitchParameter)argument).IsPresent;
                }
                if (!verbose && !force && !debug)
                {
                    usedDynamicParameter = UsingDynamicParameter(boundParameters, node, drive);
                }
            }

            // If a user specify -force, -debug -verbose -filter or dynamic parameters, we do not use cache.
            return(force || debug || verbose || usedDynamicParameter);
        }
Пример #9
0
        private object GetNodeChildrenDynamicParameters(string methodName, SHiPSDirectory node)
        {
            var errors = new ConcurrentBag <ErrorRecord>();

            var parameters = PSScriptRunner.CallPowerShellScript(
                node,
                null,
                _drive.PowerShellInstance,
                null,
                methodName,
                PSScriptRunner.output_DataAdded,
                (sender, e) => PSScriptRunner.error_DataAdded(sender, e, errors));

            if (errors.WhereNotNull().Any())
            {
                var error   = errors.FirstOrDefault();
                var message = Environment.NewLine;
                message += error.ErrorDetails == null ? error.Exception.Message : error.ErrorDetails.Message;
                throw new InvalidDataException(message);
            }

            return(parameters != null?parameters.FirstOrDefault() : null);
        }
Пример #10
0
        internal static IPathNode ToPathNode(this object input, SHiPSDrive drive, SHiPSDirectory parent)
        {
            if (input == null)
            {
                return(null);
            }
            if (input is SHiPSDirectory)
            {
                return(new ContainerNodeService(drive, input, parent));
            }

            if (input is SHiPSLeaf)
            {
                return(new LeafNodeService(input));
            }

            // get or create a psobject on input
            var psobject = PSObject.AsPSObject(input);

            if (psobject == null)
            {
                return(null);
            }

            if (psobject.ImmediateBaseObject is SHiPSDirectory)
            {
                return(new ContainerNodeService(drive, psobject.ImmediateBaseObject, parent));
            }

            if (psobject.ImmediateBaseObject is SHiPSLeaf)
            {
                return(new LeafNodeService(psobject.ImmediateBaseObject));
            }

            return(new PSObjectNodeService(psobject));
        }
Пример #11
0
        /// <summary>
        /// Invokes a PowerShell script block; Removes the existing child node list before adding new ones.
        /// </summary>
        /// <param name="context">A ProviderContext object contains information that a PowerShell provider needs.</param>
        /// <param name="node">ContainerNode object that is corresponding to the current path.</param>
        /// <param name="drive">Current drive that a user is in use.</param>
        /// <param name="script">PowerShell script to be run.</param>
        /// <param name="errorHandler">Action for handling error cases.</param>
        /// <param name="args">Arguments passed into the script block.</param>
        /// <returns></returns>
        internal static IEnumerable <IPathNode> InvokeScriptBlockAndBuildTree(
            IProviderContext context,
            SHiPSDirectory node,
            SHiPSDrive drive,
            string script,
            Action <string, IProviderContext, IEnumerable <ErrorRecord> > errorHandler,
            params string[] args)
        {
            var progressId      = 1;
            var activityId      = Resource.RetrievingData;
            int percentComplete = 1;
            var desciption      = (Resource.FetchingData).StringFormat(node.Name ?? "");
            int waittime        = 1000; // 1s

            CancellationTokenSource cts = new CancellationTokenSource();
            var progressTracker         = new ProgressTracker(progressId, activityId, desciption, node.BuiltinProgress);

            try
            {
                ICollection <object> results = new List <object>();

                var errors                = new ConcurrentBag <ErrorRecord>();
                var parameters            = context.GetSHiPSParameters();
                var usingDynamicParameter = parameters.BoundParameters.UsingDynamicParameter(node, drive);

                //PowerShell engine hangs if we call like this in default runspace
                //var task = Task.Factory.StartNew(() =>
                //{
                //    results = node.GetChildItem();

                //}, cts.Token);


                var task = Task.Factory.StartNew(() =>
                {
                    results = CallPowerShellScript(
                        node,
                        drive.PowerShellInstance,
                        parameters,
                        script,
                        output_DataAdded,
                        (sender, e) => error_DataAdded(sender, e, errors),
                        args);
                }, cts.Token);


                var stop = task.Wait(waittime, cts.Token);

                if (!stop && !cts.Token.IsCancellationRequested && !context.Stopping)
                {
                    progressTracker.Start(context);
                }

                while (!stop && !cts.IsCancellationRequested && !context.Stopping)
                {
                    stop = task.Wait(waittime, cts.Token);
                    progressTracker.Update(++percentComplete, context);
                }

                progressTracker.End(context);

                if (errors.Count > 0)
                {
                    // Cleanup child items only if the user type '-force'.
                    if (context.Force)
                    {
                        //remove the cached child nodes for the failed node
                        node.Children?.Clear();

                        //remove the node from its parent's children list so that it won't show again when a user types dir -force
                        node.Parent?.Children.RemoveSafe(node.Name);
                    }

                    // report the error if there are any
                    errorHandler?.Invoke(node.Name, context, errors);
                    //do not yield break here as we need to display the rest of outputs
                }

                if (results == null || !results.Any())
                {
                    // Just because result is null, it does not mean that the call fails because the command may
                    // return nothing.
                    context.WriteDebug(Resource.InvokeScriptReturnNull.StringFormat(node.Name, context.Path));

                    if (errors.Count == 0)
                    {
                        // do not mark the node visited if there is an error. e.g., if login to azure fails,
                        // we should not cache so that a user can dir again once the cred resolved.
                        node.ItemNavigated = true;
                    }

                    //clear the child node list as the current node has null or empty children (results)
                    if (context.Force)
                    {
                        node.Children?.Clear();
                    }
                    return(Enumerable.Empty <IPathNode>());
                }

                // Add the node list to the cache if needed
                return((node.UseCache && !usingDynamicParameter) ? ProcessResultsWithCache(results, context, node, drive, addNodeOnly: false) : ProcessResultsWithNoCache(results, context, node, drive));
            }
            finally
            {
                if (!cts.IsCancellationRequested)
                {
                    cts.Cancel();
                }
                cts.Dispose();

                progressTracker.End(context);

                // We complete the call. Reset the node parameters.
                node.SHiPSProviderContext.Clear();

                //stop the running script
                drive.PowerShellInstance.Stop();
            }
        }
Пример #12
0
        internal static bool UsingDynamicParameter(this Dictionary <string, object> boundParameters, SHiPSDirectory node, SHiPSDrive drive)
        {
            if (node.SHiPSProviderContext.DynamicParameters == null)
            {
                return(false);
            }

            var usingDynamicParameter = false;
            var filter = false;

            if (boundParameters != null && boundParameters.Any())
            {
                var defaultParameters = drive.GetChildItemDefaultParameters;
                usingDynamicParameter = boundParameters.Keys.Any(each => !defaultParameters.ContainsIgnoreCase(each));

                object argument;
                if (!usingDynamicParameter && boundParameters.TryGetValue("Filter", out argument))
                {
                    filter = !string.IsNullOrWhiteSpace((string)argument);
                }
            }

            return(usingDynamicParameter || filter);
        }
Пример #13
0
        internal static ICollection <object> CallPowerShellScript(
            SHiPSDirectory node,
            IProviderContext context,
            System.Management.Automation.PowerShell powerShell,
            SHiPSParameters parameters,
            string methodName,
            EventHandler <DataAddedEventArgs> outputAction,
            EventHandler <DataAddedEventArgs> errorAction)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            try
            {
                powerShell.Clear();

                var input = new PSDataCollection <object>();
                input.Complete();

                var output = new PSDataCollection <object>();

                if (outputAction != null)
                {
                    output.DataAdded += outputAction;
                }

                //register events
                if (errorAction != null)
                {
                    powerShell.Streams.Error.DataAdded += errorAction;
                }

                // Calling the following throws 'Unable to cast object of type 'System.Management.Automation.Language.FunctionMemberAst' to
                // type 'System.Management.Automation.Language.FunctionDefinitionAst'.
                //output = node.GetChildItem();

                //make script block
                powerShell.AddScript("[CmdletBinding()] param([object]$object)  $object.{0}()".StringFormat(methodName));
                powerShell.AddParameter("object", node);


                if (parameters != null)
                {
                    if (parameters.Debug)
                    {
                        powerShell.AddParameter("debug");
                    }
                    if (parameters.Verbose)
                    {
                        powerShell.AddParameter("verbose");
                    }
                }

                powerShell.Invoke(null, output, new PSInvocationSettings());

                return(output.Count == 0 ? null : output);
            }
            finally
            {
                powerShell.Streams.Error.DataAdded -= errorAction;
            }
        }
Пример #14
0
 internal ContainerNodeService(SHiPSDrive drive, object container)
 {
     _drive     = drive;
     _container = container as SHiPSDirectory;
 }