コード例 #1
0
        internal static string TrimDrive(this string path, SHiPSDrive drive)
        {
            if (string.IsNullOrWhiteSpace(path) || drive == null)
            {
                return(path);
            }

            //Donot strip end slash here before the match. Otherwise, we cannot make match to work and 'dir' will show nothing.
            var path1 = path;

            //match our current drive style like JT:\\  or C:\foo.ps1:\\  wheren 'C:\foo.ps1' is a drive root?
            var match = drive.DriveTrimRegex.Match(path1);

            if (match.Success)
            {
                path1 = match.Groups[2].Value;
            }
            else
            {
                // match regular drive style like E:\ or JT:?
                // This is needed when cd MyProvider\MyProvider::JT:\A\B\C
                // cd .. to B; cd .. to A; and then cd tab, show A
                var match3 = SHiPSProvider.WellFormatPathRegex.Match(path1);
                if (match3.Success)
                {
                    path1 = match3.Groups[2].Value;
                }
            }

            return(path1.TrimEnd('\\', '/'));
        }
コード例 #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
 /// <summary>
 /// Constructor for the content stream.
 /// </summary>
 /// <param name="context">A provider context.</param>
 /// <param name="drive">SHiPS based provider drive.</param>
 /// <param name="node">An object that is corresponding to the current node path.</param>
 public ContentWriter(IProviderContext context, SHiPSDrive drive, SHiPSBase node)
 {
     _drive   = drive;
     _node    = node;
     _context = context;
     _stream  = new MemoryStream();
     _writer  = new StreamWriter(_stream);
 }
コード例 #4
0
 internal ContainerNodeService(SHiPSDrive drive, object container, SHiPSDirectory parent)
 {
     _drive     = drive;
     _container = container as SHiPSDirectory;
     if (_container != null)
     {
         _container.Parent = parent;
     }
 }
コード例 #5
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;
     }
 }
コード例 #6
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);
                }
            }
        }
コード例 #7
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));
        }
コード例 #8
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();
            }
        }
コード例 #9
0
        /// <summary>
        /// Invokes a script block and updates the parent's children node list in the cached case.
        /// </summary>
        /// <param name="context">A ProviderContext object contains information that a PowerShell provider needs.</param>
        /// <param name="node">Node 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 ICollection <object> InvokeScriptBlock(
            IProviderContext context,
            SHiPSBase node,
            SHiPSDrive drive,
            string script,
            Action <string, IProviderContext, IEnumerable <ErrorRecord> > errorHandler,
            params string[] args)
        {
            try
            {
                var errors     = new ConcurrentBag <ErrorRecord>();
                var parameters = context?.GetSHiPSParameters();

                var results = CallPowerShellScript(
                    node,
                    drive.PowerShellInstance,
                    parameters,
                    script,
                    output_DataAdded,
                    (sender, e) => error_DataAdded(sender, e, errors),
                    args);


                if (errors.WhereNotNull().Any())
                {
                    if (context != null)
                    {
                        // report the error if there are any
                        errorHandler?.Invoke(node.Name, context, errors);
                        return(null);
                    }
                    else
                    {
                        // report the error if there are any
                        var error   = errors.FirstOrDefault();
                        var message = Environment.NewLine;
                        message += error.ErrorDetails == null ? error.Exception.Message : error.ErrorDetails.Message;
                        throw new InvalidDataException(message);
                    }
                }

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

                if (context != null && node.UseCache)
                {
                    if (node.IsLeaf)
                    {
                        ProcessResultsWithCache(results, context, node.Parent, drive, addNodeOnly: true);
                    }
                    else
                    {
                        ProcessResultsWithCache(results, context, node as SHiPSDirectory, drive, addNodeOnly: true);
                    }
                }
                return(results);
            }
            finally
            {
                //stop the running script
                drive.PowerShellInstance.Stop();
            }
        }
コード例 #10
0
        internal static IPathNode GetChildPNode(this SHiPSDirectory parent, object child, SHiPSDrive drive, 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 &&
                    (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);
        }
コード例 #11
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);
        }
コード例 #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 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);
        }
コード例 #14
0
ファイル: SHiPSPathResolver.cs プロジェクト: wgross/SHiPS
 internal PathResolver(SHiPSProvider provider, SHiPSDrive driveInfo)
 {
     _provider = provider;
     _drive    = driveInfo;
 }
コード例 #15
0
ファイル: ContentHelper.cs プロジェクト: yurko7/SHiPS
 internal ContentHelper(SHiPSBase node, SHiPSDrive drive)
 {
     _node  = node;
     _drive = drive;
 }
コード例 #16
0
ファイル: ContainerNodeService.cs プロジェクト: wgross/SHiPS
 internal ContainerNodeService(SHiPSDrive drive, object container)
 {
     _drive     = drive;
     _container = container as SHiPSDirectory;
 }