예제 #1
0
파일: SHiPSDrive.cs 프로젝트: yurko7/SHiPS
        private void InitializeRoot()
        {
            // Module.Type
            Match match = ModuleAndTypeRegex.Match(_rootInfo);

            if (!match.Success)
            {
                // Handling a case like: myModule#Test\FamilyTree#Austin
                match = TryExcludeFQProviderPath(_rootInfo);
                if (match == null)
                {
                    _provider.ThrowError(Resources.Resource.InvalidRootFormat.StringFormat(_rootInfo), ErrorId.InvalidRootFormat);
                    return;
                }
            }

            //first we need to make sure the module is loaded
            var moduleCommand = "import-module {0}; get-module {0} -verbose".StringFormat(match.Groups[1],
                                                                                          match.Groups[1]);

            _provider.WriteVerbose(moduleCommand);


            //get the module
            var module = _provider.SessionState.InvokeCommand.InvokeScript(moduleCommand, null).FirstOrDefault();

            if (module == null || !(module.BaseObject is PSModuleInfo))
            {
                // The reason that not using _provider.WriteError() here is because it is not terminatoring process
                // at this time, mearning the drive is actually gets created but not usable.
                //_provider.WriteError()
                _provider.ThrowError(Resources.Resource.CannotGetModule.StringFormat(match.Groups[1]), ErrorId.CannotGetModule);
                return;
            }

            //create powershell instance and load the modules currently referenced
            var moduleBaseObj = (PSModuleInfo)module.BaseObject;
            var modulePath    = Path.Combine((moduleBaseObj).ModuleBase, (moduleBaseObj).Name.TrimEnd() + ".psd1");

            if (!File.Exists(modulePath))
            {
                _provider.WriteWarning(Resources.Resource.FileNotExist.StringFormat(modulePath));
                modulePath = moduleBaseObj.Path;
                _provider.WriteWarning(Resources.Resource.Trying.StringFormat(modulePath));
            }

            _provider.WriteVerbose(modulePath);

            //create the instance of root module
            var createRootInstance = string.Format(CultureInfo.InvariantCulture,
                                                   @"using module '{0}'; $mod=get-module {1}; &($mod){{[{2}]::new('{2}')}}", modulePath, match.Groups[1], match.Groups[2]);

            _provider.WriteVerbose(createRootInstance);

            //ifdef #newrunspace
            PowerShellInstance = CreatePowerShellObject(_provider.Host, modulePath);
            PowerShellInstance.AddScript(createRootInstance);

            var errors = new ConcurrentBag <ErrorRecord>();

            var rootPsObject = PSScriptRunner.CallPowerShellScript(createRootInstance, PowerShellInstance, (sender, e) => PSScriptRunner.error_DataAdded(sender, e, errors));

            //var rootPsObject = PowerShellInstance.Invoke().FirstOrDefault();
            if (rootPsObject == null || !rootPsObject.Any())
            {
                var message = Resources.Resource.CannotCreateInstance.StringFormat(match.Groups[2], modulePath, match.Groups[2], match.Groups[2]);
                if (errors.WhereNotNull().Any())
                {
                    var error = errors.FirstOrDefault();
                    message += Environment.NewLine;
                    message += error.ErrorDetails == null ? error.Exception.Message : error.ErrorDetails.Message;
                }

                _provider.ThrowError(message, ErrorId.CannotCreateInstance);

                return;
            }

            var node = rootPsObject.FirstOrDefault().ToNode();

            if (node == null)
            {
                _provider.ThrowError(Resources.Resource.InvalidRootNode, ErrorId.NotContainerNode);
            }

            if (string.IsNullOrWhiteSpace(node.Name))
            {
                _provider.ThrowError(Resources.Resource.NameWithNullOrEmpty.StringFormat(string.IsNullOrWhiteSpace(node.Name) ? "root" : node.Name), ErrorId.NodeNameIsNullOrEmpty);
            }

            if (node.IsLeaf)
            {
                _provider.ThrowError(Resources.Resource.InvalidRootNodeType.StringFormat(Constants.Leaf), ErrorId.RootNodeTypeMustBeContainer);
            }

            RootNode = node;

            RootPathNode = new ContainerNodeService(this, node, null);

            // Getting the Get-ChildItem default parameters before running any commands. It will be used for checking
            // whether a user is passing in any dynamic parameters.
            _getChildItemDefaultParameters = GetChildItemDefaultParameters;
        }
예제 #2
0
        private IPathNode GetNodeObjectFromPath(IProviderContext context, ContainerNodeService parent, string pathName, bool force)
        {
            var parentNode = parent?.ContainerNode;

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

            // Check if the node has been dir'ed
            // Here we do not need to add NeedRefresh check because:
            // For cd (set-location), there is no -force, i.e., NeedRefresh is always false. This means for cached cases,
            // a user needs to do 'dir -force' to get fresh data.
            // For dir case, path in ResolvePath() is pointing to the parent path, e.g., dir c:\foo\bar\baz.txt,
            // the path is poing to c:\foo\bar even if baz.txt just gets created. Thus ResolvePath() only needs to resolve
            // the parent path and the GetChildItem() will check NeedRefresh to get fresh data.
            if (!force && parentNode.UseCache && parentNode.ItemNavigated)
            {
                var nodes = parentNode.Children.Where(each => pathName.EqualsIgnoreCase(each.Key)).Select(item => item.Value)
                            .FirstOrDefault();

                if (nodes != null && nodes.Any())
                {
                    return(nodes.FirstOrDefault());
                }
                else
                {
                    // If a childitem exists and cached, but none of them matches what specified in the 'pathName',
                    // we will return null, because
                    //
                    // dir         --- Assuming displays a long list of child items. So user does
                    // dir a[tab]  --- a user wants to see any child items start with 'a'. This may be no child item starts with a.
                    //                 so we do not need to go out fetching again if cache misses.
                    //
                    // caveat:
                    // dir foobar  --- if a user expects foobar child item exists, and cache misses, SHiPS is not going out fetch
                    //                 automatically, unless -force
                    // By removing the else block, SHiPS will go out fetching for data if cache misses. But dir a[tab] will be slow.
                    return(null);
                }
            }

            var children = PSScriptRunner.InvokeScriptBlock(context, parentNode, _drive)?.ToList();

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

            foreach (var node in children)
            {
                // Making sure to obey the StopProcessing.
                if (context.Stopping)
                {
                    return(null);
                }

                //add it to its child list
                if (node != null)
                {
                    if (pathName.EqualsIgnoreCase(node.Name))
                    {
                        return(node);
                    }
                }
            }
            return(null);
        }