Skip to content

Commit

Permalink
Add output stream encoding selection
Browse files Browse the repository at this point in the history
  • Loading branch information
menees committed Oct 28, 2023
1 parent 44fcbdc commit 8a73f41
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 166 deletions.
14 changes: 11 additions & 3 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<_SkipUpgradeNetAnalyzersNuGetWarning>true</_SkipUpgradeNetAnalyzersNuGetWarning>

<!-- Make the assembly, file, and NuGet package versions the same. -->
<Version>4.8.3</Version>
<Version>4.9.0</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
Expand Down Expand Up @@ -58,15 +59,22 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Menees.Analyzers" Version="3.0.6">
<PackageReference Include="Menees.Analyzers" Version="3.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.507">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Meziantou.Polyfill" Version="1.0.26">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
1 change: 1 addition & 0 deletions src/MegaBuild/MegaBuild.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<!-- I picked these Windows API Code Pack packages because they were the first ones I found that were strongly-named. -->
<PackageReference Include="Windows7APICodePack-Core" Version="1.1.0">
<NoWarn>NU1701</NoWarn>
Expand Down
4 changes: 4 additions & 0 deletions src/MegaBuild/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace MegaBuild
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Menees.Windows.Forms;
Expand All @@ -21,6 +22,9 @@ internal static class Program
[STAThread]
private static int Main()
{
// Allow modern .NET builds to use all the code pages that .NET Framework builds can.
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

// I'm intentionally not setting TaskbarManager.Instance.ApplicationId. We want Windows
// to assign a default application ID to each executable path, so they can have their own
// private lists of recent files (just like we store in our .stgx files). Then it will also make
Expand Down
9 changes: 7 additions & 2 deletions src/MegaBuildSdk/Classes/CommandStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace MegaBuild
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.IO;
using System.Linq;
using Menees;
using Menees.Windows.Forms;

Expand All @@ -21,6 +22,8 @@ internal sealed class CommandStep : ExecutableStep
{
#region Private Data Members

private static readonly char[] InvalidPathCharacters = Path.GetInvalidPathChars();

private bool useShellExecute;
private RedirectStandardStreams redirectStreams;
private ProcessWindowStyle windowState = ProcessWindowStyle.Hidden;
Expand Down Expand Up @@ -197,8 +200,10 @@ public override void GetStepEditorControls(ICollection<StepEditorControl> contro

internal static bool HasBatchFileExt(string fileName)
{
string ext = Path.GetExtension(fileName).ToLower();
return ext == ".bat" || ext == ".cmd";
const StringComparison comparison = StringComparison.OrdinalIgnoreCase;
bool result = (fileName.EndsWith(".bat", comparison) || fileName.EndsWith(".cmd", comparison))
&& !fileName.Any(ch => InvalidPathCharacters.Contains(ch));
return result;
}

#endregion
Expand Down
27 changes: 27 additions & 0 deletions src/MegaBuildSdk/Classes/ExecutableStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace MegaBuild
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -39,6 +40,7 @@ public abstract class ExecutableStep : Step
private int timeoutMinutes = 10;
private TimeSpan totalTime;
private List<(OutputStyle Style, Regex Pattern)>? customOutputStyles;
private Encoding standardStreamEncoding;

#endregion

Expand All @@ -53,6 +55,7 @@ protected ExecutableStep(Project project, StepCategory category, StepTypeInfo in
: base(project, category, info)
{
this.supportFlags = supports;
this.standardStreamEncoding = Encoding.UTF8;
}

#endregion
Expand Down Expand Up @@ -183,6 +186,12 @@ public bool WaitForCompletion
set => this.SetValue(ref this.waitForCompletion, value);
}

public Encoding StandardStreamEncoding
{
get => this.standardStreamEncoding;
set => this.SetValue(ref this.standardStreamEncoding, value);
}

#endregion

#region Internal Properties
Expand Down Expand Up @@ -308,6 +317,7 @@ protected internal override void Load(XmlKey key)
this.Timeout = key.GetValue(nameof(this.Timeout), this.timeout);
this.TimeoutMinutes = key.GetValue(nameof(this.TimeoutMinutes), this.timeoutMinutes);
this.AutoColorErrorsAndWarnings = key.GetValue(nameof(this.AutoColorErrorsAndWarnings), this.autoColorErrorsAndWarnings);
this.StandardStreamEncoding = Encoding.GetEncoding(key.GetValue(nameof(this.StandardStreamEncoding), this.standardStreamEncoding.WebName));
if (this.MayRequireAdministrator)
{
this.IsAdministratorRequired = key.GetValue(nameof(this.IsAdministratorRequired), this.isAdministratorRequired);
Expand Down Expand Up @@ -336,6 +346,7 @@ protected internal override void Save(XmlKey key)
key.SetValue(nameof(this.Timeout), this.timeout);
key.SetValue(nameof(this.TimeoutMinutes), this.timeoutMinutes);
key.SetValue(nameof(this.AutoColorErrorsAndWarnings), this.autoColorErrorsAndWarnings);
key.SetValue(nameof(this.StandardStreamEncoding), this.standardStreamEncoding.WebName);
key.SetValue(nameof(this.IsAdministratorRequired), this.isAdministratorRequired);

if (this.customOutputStyles != null && this.customOutputStyles.Count > 0)
Expand Down Expand Up @@ -523,6 +534,22 @@ private ProcessStartInfo CreateProcessStartInfo(ExecuteCommandArgs args)
startInfo.RedirectStandardError = (args.RedirectStandardStreams & RedirectStandardStreams.Error) != 0;
this.DebugProperty("RedirectStandardError", startInfo.RedirectStandardError);

if (startInfo.RedirectStandardOutput)
{
startInfo.StandardOutputEncoding = this.StandardStreamEncoding;
}

if (startInfo.RedirectStandardError)
{
startInfo.StandardErrorEncoding = this.StandardStreamEncoding;
}
#if NET
if (startInfo.RedirectStandardInput)
{
startInfo.StandardInputEncoding = this.StandardStreamEncoding;
}
#endif

startInfo.WindowStyle = args.WindowStyle;
this.DebugProperty("WindowStyle", startInfo.WindowStyle);
if (args.WindowStyle == ProcessWindowStyle.Hidden)
Expand Down
Loading

0 comments on commit 8a73f41

Please sign in to comment.