cmdlets/StartCrawlingCommand.cs
namespace pscdp; using System.Management.Automation; using System.Diagnostics; using quickcrawl.core; // Assuming you have a CrawlerCore class in your project using quickcrawl; using Microsoft.Extensions.Logging; [Cmdlet(VerbsLifecycle.Start, "Crawling")] public class StartCrawlingCommand : PSCmdlet { [Parameter(Mandatory = true, Position = 0)] [ValidateNotNullOrEmpty] public string? Url; [Parameter(Mandatory =false, Position = 1)] public int Depth = 0; [Parameter(Mandatory = false, Position = 2)] public int MaxDegreeOfParallelism = 4; private QuickCrawler _crawler; private PSLogger _logger = new PSLogger(); private int _completed = 0; private int _total = 1; private readonly object _progressLock = new(); protected override void BeginProcessing() { base.BeginProcessing(); _crawler = new QuickCrawler(_logger); _crawler.ProgressChanged += OnProgressChanged; } protected override void ProcessRecord() { _crawler.StartCrawling(Url, maxDepth: Depth, maxDegreeOfParallelism: MaxDegreeOfParallelism); // we have to do this as powershell is syncronous and WriteProgess and otjer Write... can only be called from this method while (!_crawler.IsCompleted) { Thread.Sleep(200); int completed, total; lock (_progressLock) { completed = _completed; total = _total; } int percent = total == 0 ? 0 : (int)((double)completed / total * 100); WriteProgress(new ProgressRecord(1, "Crawling website", $"{completed}/{total} processed") { PercentComplete = percent }); } _crawler.BuildResultingGraph(); WriteObject(new Result(_crawler.Graph, _crawler.CapturedEvents), false); } protected override void EndProcessing() { base.EndProcessing(); WriteProgress(new ProgressRecord(1, "Crawling website", "Done") { RecordType = ProgressRecordType.Completed }); FlushLogs(); } protected override void StopProcessing() { base.StopProcessing(); _crawler?.StopCrawling(); } private void FlushLogs() { while (_logger.LogBuffer.TryDequeue(out var entry)) { switch (entry.Level) { case LogLevel.Debug: if (MyInvocation.BoundParameters.ContainsKey("Debug")) WriteDebug(entry.Message); break; case LogLevel.Information: if (MyInvocation.BoundParameters.ContainsKey("Verbose")) WriteVerbose(entry.Message); break; case LogLevel.Warning: if (MyInvocation.BoundParameters.ContainsKey("Verbose")) WriteWarning(entry.Message); break; case LogLevel.Error: if (MyInvocation.BoundParameters.ContainsKey("Debug")) WriteError(new ErrorRecord(entry.Exception ?? new Exception(entry.Message), "Error", ErrorCategory.NotSpecified, null)); break; } } } private void OnProgressChanged(int completed, int total) { lock (_progressLock) { _completed = completed; _total = total; } } } |