PowerShell – .NET Core C# – Why is my PowerShell.Create() – Streams.Information.DataAdded not working
I work with PowerShell on daily basis for more then 10 years and today I’m proud to announce that I made a real beginner mistake .
If you execute a PowerShell script from .NET Core C# bij using the “using (PowerShell ps = PowerShell.Create())” syntax.
You can “stream” the events written to Error, Warning and Information streams from the executed PowerShell script, by attaching delegates, like:
string scriptContent = await File.ReadAllTextAsync(@”C:\Temp\Test.ps1″);
using (PowerShell ps = PowerShell.Create())
{
// Subscribe to events from some of the streams.
ps.Streams.Error.DataAdded += ErrorDataAdded;
ps.Streams.Warning.DataAdded += WarningDataAdded;
ps.Streams.Information.DataAdded += InformationDataAdded;
ps.Streams.Debug.DataAdded += DebugDataAdded;
ps.Streams.Verbose.DataAdded += VerboseDataAdded;
// Set execution policy to unrestricted
string initScript = “Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted; Get-ExecutionPolicy”; // The second command to know the ExecutionPolicy level after it has been set.
ps.AddScript(initScript);
// Specify the script code to run.
ps.AddScript(scriptContent);
// Add parameters to the script.
ps.AddParameter(“someParamter1”, @”Some value for Parameter1″);
// Execute the script and await the result.
PSDataCollection<PSObject> pipelineObjects = await ps.InvokeAsync().ConfigureAwait(false);
// Print the resulting pipeline objects to the console (this is the standard output stream).
foreach (var item in pipelineObjects)
{
Console.WriteLine(item.BaseObject.ToString());
}
}
If you use “Write-Output” in your PowerShell script it will end up in the “standard output stream” and will only be available in the C# code above after the script has executed.
If you use “Write-Information” in your PowerShell script it will end up in the “Information output stream” which will fire during the execution of the script in the C# code above.
So, if you want to see progress information during the execution of your PowerShell script use “Write-Information” and not “Write-output”.
private void DebugDataAdded(object sender, DataAddedEventArgs e)
{
PSDataCollection<DebugRecord> streamObjectsReceived = sender as PSDataCollection<DebugRecord>;
DebugRecord currentStreamRecord = streamObjectsReceived[e.Index];
Console.WriteLine($”DebugStreamEvent: {currentStreamRecord.Message}”);
}
private void ErrorDataAdded(object sender, DataAddedEventArgs e)
{
PSDataCollection<ErrorRecord> streamObjectsReceived = sender as PSDataCollection<ErrorRecord>;
ErrorRecord currentStreamRecord = streamObjectsReceived[e.Index];
Console.WriteLine($”ErrorStreamEvent: {currentStreamRecord.Exception}”);
}
private void InformationDataAdded(object sender, DataAddedEventArgs e)
{
PSDataCollection<InformationRecord> streamObjectsReceived = sender as PSDataCollection<InformationRecord>;
InformationRecord currentStreamRecord = streamObjectsReceived[e.Index];
Console.WriteLine($”InfoStreamEvent: {currentStreamRecord.MessageData}”);
}
private void VerboseDataAdded(object sender, DataAddedEventArgs e)
{
PSDataCollection<VerboseRecord> streamObjectsReceived = sender as PSDataCollection<VerboseRecord>;
VerboseRecord currentStreamRecord = streamObjectsReceived[e.Index];
Console.WriteLine($”VerboseStreamEvent: {currentStreamRecord.Message}”);
}
private void WarningDataAdded(object sender, DataAddedEventArgs e)
{
PSDataCollection<WarningRecord> streamObjectsReceived = sender as PSDataCollection<WarningRecord>;
WarningRecord currentStreamRecord = streamObjectsReceived[e.Index];
Console.WriteLine($”WarningStreamEvent: {currentStreamRecord.Message}”);
}
How to add parameters to a PowerShell script and call it from .NET Core
If you need to run a PowerShell script from .NET Core and this script accepts parameters, then you can call it like:
.NET Core C#
string scriptContent = await File.ReadAllTextAsync(@”C:\Temp\Test.ps1″);
using (PowerShell ps = PowerShell.Create())
{
// Subscribe to events from some of the streams.
ps.Streams.Error.DataAdded += ErrorDataAdded;
ps.Streams.Warning.DataAdded += WarningDataAdded;
ps.Streams.Information.DataAdded += InformationDataAdded;
ps.Streams.Debug.DataAdded += DebugDataAdded;
ps.Streams.Verbose.DataAdded += VerboseDataAdded;
// Set execution policy to unrestricted
string initScript = “Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted; Get-ExecutionPolicy”; // The second command to know the ExecutionPolicy level after it has been set.
ps.AddScript(initScript);
// Specify the script code to run.
ps.AddScript(scriptContent);
// Add parameters to the script.
ps.AddParameter(“someParamter1”, @”Some value for Parameter1″);
// Execute the script and await the result.
PSDataCollection<PSObject> pipelineObjects = await ps.InvokeAsync().ConfigureAwait(false);
// Print the resulting pipeline objects to the console (this is the standard output stream).
foreach (var item in pipelineObjects)
{
Console.WriteLine(item.BaseObject.ToString());
}
}
PowerShell script (“C:\Temp\Test.ps1”)
param ($someParameter1 = “Some default value for this parameter)
Write-Information “Script called with $($someParameter1)”
How to redirect dotnet build output to the information stream of the calling PowerShell script
If you execute a PowerShell script from .NET Core and this script contains a call to “dotnet build” you probably want to capture the progress of the dotnet build process.
You can do this by redirecting / piping the output of the dotnet build process to the Write-Information cmd-let:
dotnet build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile | Write-Information
How to fix Windows 10 Explorer error – Failed to enumerate objects in the container. Access is denied.
Changing the owner of the folder to the account I was signed in with, solved my problem. Even though the Windows 10 Explorer told me I was the owner of the folder.
https://recoverit.wondershare.com/partition-tips/failed-to-enumerate-objects-in-the-container.html
After that I was able to add permissions for the IIS_IUSERS account to that folder.
This was necessary to allow an IIS application pool access to the files in the folder.
How to fix overflow issues with css flex layout
It turns out that min-height is important for correctly scrolling flexboxes:
See https://moduscreate.com/blog/how-to-fix-overflow-issues-in-css-flex-layouts/
Set min-height: 0; on flex child element that should overflow.
Use NgNonBindable if you want to blog about Angular code
https://ngrefs.com/latest/templates/ngnonbindable