/// <summary> /// Closes the stream. /// </summary> public void Close() { if (_writer == null || _stream == null) { return; } try { _writer.Flush(); _stream.Flush(); // By now the PS engine completes reading from its pipleline and have the stream ready for SetConent() _stream.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(_stream)) { // Read the entire content from the stream as a string text var content = reader.ReadToEnd(); // Invoke SetContent and pass in content and path to the script // Calling SHiPS based PowerShell provider '[object] SetContent([string]$content, [string]$path)' var script = Constants.ScriptBlockWithParam3.StringFormat(Constants.SetContent); PSScriptRunner.InvokeScriptBlock(_context, _node, _drive, script, PSScriptRunner.SetContentNotSupported, content, _context.Path); } } finally { _writer.Dispose(); _stream.Dispose(); _writer = null; _stream = null; } }
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()); }
private IEnumerable <IPathNode> GetNodeChildrenInternal(IProviderContext context) { //find the current parent node var item = this.ContainerNode; if (item == null || item.IsLeaf) { // WriteChildItem()/P2F can call us while 'dir -recurse' even if the node is set to leaflet. yield break; } // Set the ProviderContext as the DynamicParameters and Filter objects will be used in the // PowerShell module's GetChildItem(). // If dynamic parameters are used, then SHiPS is not using cache. // ProviderContext has to be set right now because context.NeedRefresh uses it. item.SHiPSProviderContext.Set(context); // The item is the parent node from where we can find its child node list. // We will find child nodes from the cache if GetChildItem() has been called already and NeedRefresh is false. // Otherwise, we will execute the scriptblock and then add the returned nodes to item's child list if (item.UseCache && item.ItemNavigated && !context.NeedRefresh(item, _drive)) { var list = item.Children.Values.SelectMany(each => each); foreach (var node in list) { // Making sure to obey the StopProcessing. if (context.Stopping) { yield break; } yield return(node); } } else { var script = Constants.ScriptBlockWithParam1.StringFormat(Constants.GetChildItem); var nodes = PSScriptRunner.InvokeScriptBlockAndBuildTree(context, item, _drive, script, PSScriptRunner.ReportErrors)?.ToList(); // Save the info of the node just visisted SHiPSProvider.LastVisisted.Set(context.Path, this, nodes); if (nodes == null || nodes.Count == 0) { yield break; } foreach (var node in nodes) { // Making sure to obey the StopProcessing. if (context.Stopping) { yield break; } yield return(node); } } }
public IContentReader GetContentReader(IProviderContext context) { // Calling GetContent() var script = Constants.ScriptBlockWithParam1.StringFormat(Constants.GetContent); var results = PSScriptRunner.InvokeScriptBlock(context, _node, _drive, script, PSScriptRunner.ReportErrors); // Expected a collection of strings returned from GetContent() and save it to a stream var stream = new ContentReader(results, context); return(stream); }
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); }
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); }