Skip to content

Commit d24d261

Browse files
committed
[Xamarin.Android.Build.Tasks] Catch Exception when setting Console.InputEncoding
Context https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1130414 For some unknown reason the setting of `Console.InputEncoding` on a customers machine is throwing an IOException. This then causes Visual Studio to completely crash. ``` Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.IOException at System.IO.__Error.WinIOError(Int32, System.String) at System.IO.__Error.WinIOError() at System.Console.set_InputEncoding(System.Text.Encoding) at Xamarin.Android.Tasks.Aapt2Daemon.Aapt2DaemonStart() at System.Threading.ThreadHelper.ThreadStart_Context(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) at System.Threading.ThreadHelper.ThreadStart() ``` At this time we are still unsure as to what is causing the problem. But we should at least catch the exception to that Visual Studio does not crash. We need to figure out a way of reporting this issue somehow in the exception handler so we can get more data. Note: Not sure what is going on with the line ending changes :/
1 parent 4fed059 commit d24d261

File tree

1 file changed

+48
-18
lines changed

1 file changed

+48
-18
lines changed

src/Xamarin.Android.Build.Tasks/Utilities/Aapt2Daemon.cs

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
using System.IO;
66
using System.Text;
77
using System.Threading;
8+
using System.Reflection;
89
using Microsoft.Build.Framework;
910
using TPL = System.Threading.Tasks;
11+
using Xamarin.Android.Tools;
1012

1113
namespace Xamarin.Android.Tasks
1214
{
@@ -144,6 +146,33 @@ public void Stop ()
144146
pendingJobs.CompleteAdding ();
145147
}
146148

149+
private bool SetConsoleInputEncoding (Encoding encoding)
150+
{
151+
try {
152+
if (Console.InputEncoding != encoding) {
153+
Console.InputEncoding = encoding;
154+
return true;
155+
}
156+
} catch (IOException) {
157+
//In a DesignTime Build on VS Windows sometimes this exception is raised.
158+
//We should catch it, but there is nothing we can do about it.
159+
}
160+
return false;
161+
}
162+
163+
private bool SetProcessInputEncoding (ProcessStartInfo info, Encoding encoding)
164+
{
165+
Type type = info.GetType();
166+
PropertyInfo prop = type.GetRuntimeProperty("StandardInputEncoding");
167+
if (prop == null)
168+
prop = type.GetProperty("StandardInputEncoding", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
169+
if(prop?.CanWrite ?? false) {
170+
prop.SetValue(info, encoding, null);
171+
return true;
172+
}
173+
return false;
174+
}
175+
147176
private void Aapt2DaemonStart ()
148177
{
149178
ProcessStartInfo info = new ProcessStartInfo (Aapt2)
@@ -158,23 +187,24 @@ private void Aapt2DaemonStart ()
158187
WorkingDirectory = Path.GetTempPath (),
159188
StandardErrorEncoding = Encoding.UTF8,
160189
StandardOutputEncoding = Encoding.UTF8,
190+
// We need to FORCE the StandardInput to be UTF8 so we can use
191+
// accented characters. Also DONT INCLUDE A BOM!!
192+
// otherwise aapt2 will try to interpret the BOM as an argument.
161193
// Cant use this cos its netstandard 2.1 only
162194
// and we are using netstandard 2.0
163-
//StandardInputEncoding = Encoding.UTF8,
195+
//StandardInputEncoding = MonoAndroidHelper.UTF8withoutBOM,
164196
};
165-
// We need to FORCE the StandardInput to be UTF8 so we can use
166-
// accented characters. Also DONT INCLUDE A BOM!!
167-
// otherwise aapt2 will try to interpret the BOM as an argument.
168197
Process aapt2;
169-
lock (lockObject) {
170-
Encoding current = Console.InputEncoding;
198+
Encoding currentEncoding = Console.InputEncoding;
199+
lock (lockObject) {
171200
try {
172-
Console.InputEncoding = new UTF8Encoding (false);
201+
if (!SetProcessInputEncoding (info, MonoAndroidHelper.UTF8withoutBOM))
202+
SetConsoleInputEncoding (MonoAndroidHelper.UTF8withoutBOM);
173203
aapt2 = new Process ();
174204
aapt2.StartInfo = info;
175205
aapt2.Start ();
176206
} finally {
177-
Console.InputEncoding = current;
207+
SetConsoleInputEncoding (currentEncoding);
178208
}
179209
}
180210
try {
@@ -183,15 +213,15 @@ private void Aapt2DaemonStart ()
183213
bool errored = false;
184214
try {
185215
// try to write Unicode UTF8 to aapt2
186-
StreamWriter writer = aapt2.StandardInput;
187-
foreach (var arg in job.Commands)
188-
{
189-
writer.WriteLine (arg);
216+
using (StreamWriter writer = new StreamWriter (aapt2.StandardInput.BaseStream, MonoAndroidHelper.UTF8withoutBOM, bufferSize: 1024, leaveOpen: true)) {
217+
foreach (var arg in job.Commands) {
218+
writer.WriteLine (arg);
219+
}
220+
writer.WriteLine ();
221+
writer.Flush ();
190222
}
191-
writer.WriteLine ();
192-
writer.Flush ();
193223
string line;
194-
224+
195225
Queue<string> stdError = new Queue<string> ();
196226
while ((line = aapt2.StandardError.ReadLine ()) != null) {
197227
if (string.Compare (line, "Done", StringComparison.OrdinalIgnoreCase) == 0) {
@@ -201,8 +231,8 @@ private void Aapt2DaemonStart ()
201231
errored = true;
202232
continue;
203233
}
204-
// we have to queue the output because the "Done"/"Error" lines are
205-
//written after all the messages. So to process the warnings/errors
234+
// we have to queue the output because the "Done"/"Error" lines are
235+
//written after all the messages. So to process the warnings/errors
206236
// correctly we need to do this after we know if worked or failed.
207237
stdError.Enqueue (line);
208238
}
@@ -256,4 +286,4 @@ bool IsAapt2Warning (string singleLine)
256286
return false;
257287
}
258288
}
259-
}
289+
}

0 commit comments

Comments
 (0)