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; }
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); }