diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx
index eeb7f63896dd..d20b4cbe143d 100644
--- a/src/System.Private.CoreLib/Resources/Strings.resx
+++ b/src/System.Private.CoreLib/Resources/Strings.resx
@@ -159,10 +159,6 @@
The serialization stream contains no inner exceptions.
-
- (Inner Exception #{0})
- This text is prepended to each inner exception description during aggregate exception formatting
-
The ApplicationBase must be set before retrieving this property.
@@ -812,7 +808,7 @@
The value "{0}" is not of type "{1}" and cannot be used in this generic collection.
- Absolute path information is required.
+ Path "{0}" is not an absolute path.
An item with the same key has already been added.
@@ -2224,12 +2220,6 @@
Event {0} was called with a different type as defined (argument "{1}"). This may cause the event to be displayed incorrectly.
-
- --- End of inner exception stack trace ---
-
-
- --- End of stack trace from previous location ---
-
Exception of type '{0}' was thrown.
diff --git a/src/System.Private.CoreLib/shared/System/AggregateException.cs b/src/System.Private.CoreLib/shared/System/AggregateException.cs
index 46baebfddd6e..0526ee696b19 100644
--- a/src/System.Private.CoreLib/shared/System/AggregateException.cs
+++ b/src/System.Private.CoreLib/shared/System/AggregateException.cs
@@ -438,16 +438,12 @@ public override string ToString()
StringBuilder text = new StringBuilder();
text.Append(base.ToString());
- for (int i = 0; i < m_innerExceptions.Count; i++)
+ foreach (Exception ex in m_innerExceptions)
{
- if (m_innerExceptions[i] == InnerException)
+ if (object.ReferenceEquals(ex, InnerException))
continue; // Already logged in base.ToString()
- text.Append(Environment.NewLineConst + InnerExceptionPrefix);
- text.AppendFormat(CultureInfo.InvariantCulture, SR.AggregateException_InnerException, i);
- text.Append(m_innerExceptions[i].ToString());
- text.Append("<---");
- text.AppendLine();
+ text.Append(InnerExceptionToString(ex));
}
return text.ToString();
diff --git a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
index c241eed32df5..e2f0d928c864 100644
--- a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
+++ b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
@@ -95,11 +95,10 @@ public override string ToString()
{
string s = GetType().ToString() + ": " + Message;
- if (!string.IsNullOrEmpty(_fileName))
+ if (!string.IsNullOrEmpty(_fileName) && !Message.Contains(_fileName))
s += Environment.NewLineConst + SR.Format(SR.IO_FileName_Name, _fileName);
- if (InnerException != null)
- s += InnerExceptionPrefix + InnerException.ToString();
+ s += InnerExceptionToString(InnerException);
if (StackTrace != null)
s += Environment.NewLineConst + StackTrace;
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs
index b69dc670755e..8e28c6ea8dd6 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs
@@ -321,13 +321,6 @@ internal void ToString(TraceFormat traceFormat, StringBuilder sb)
sb.AppendFormat(CultureInfo.InvariantCulture, inFileLineNum, fileName, sf.GetFileLineNumber());
}
}
-
- // Skip EDI boundary for async
- if (sf.IsLastFrameFromForeignExceptionStackTrace && !isAsync)
- {
- sb.AppendLine();
- sb.Append(SR.Exception_EndStackTraceFromPreviousThrow);
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Exception.cs b/src/System.Private.CoreLib/shared/System/Exception.cs
index a437da1c33f2..12d2d1951959 100644
--- a/src/System.Private.CoreLib/shared/System/Exception.cs
+++ b/src/System.Private.CoreLib/shared/System/Exception.cs
@@ -5,6 +5,7 @@
using System.Collections;
using System.Diagnostics;
using System.Runtime.Serialization;
+using System.Text;
namespace System
{
@@ -12,8 +13,6 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial class Exception : ISerializable
{
- private protected const string InnerExceptionPrefix = " ---> ";
-
public Exception()
{
_HResult = HResults.COR_E_EXCEPTION;
@@ -128,10 +127,7 @@ public override string ToString()
s += ": " + message;
}
- if (_innerException != null)
- {
- s += Environment.NewLineConst + InnerExceptionPrefix + _innerException.ToString() + Environment.NewLineConst + " " + SR.Exception_EndOfInnerExceptionStack;
- }
+ s += InnerExceptionToString(InnerException);
string? stackTrace = StackTrace;
if (stackTrace != null)
@@ -142,6 +138,34 @@ public override string ToString()
return s;
}
+ // Returns the indented inner exception's ToString() prefixed, but not suffixed, with a newline.
+ // If there is no inner exception, returns empty string.
+ private protected string InnerExceptionToString(Exception? inner)
+ {
+ if (inner == null)
+ return "";
+
+ /* Format something like this to clearly separate from the containing exception
+ ________________________________________________________________________________________________
+ |_1.Interop+Crypto+OpenSslCryptographicException: error:25070067:DSO support routines:DSO_load:could not load the shared library
+ | at _1.Program.<>c.b__0_0() in C:\proj\30\ConsoleApp1\Program.cs:line 31
+ | at _1.Program.Wrap(Action cb) in C:\proj\30\ConsoleApp1\Program.cs:line 61
+ \________________________________________________________________________________________________
+
+ */
+ const string nl = Environment.NewLineConst;
+ string hundredUnderscores = new string('_', 100);
+
+ var sb = new StringBuilder();
+ sb.Append(nl + " ").Append(hundredUnderscores).Append(nl);
+ sb.Append(inner.ToString().Trim()); // Remove any trailing newline
+ sb.Replace("\r\n", "\n", nl.Length, sb.Length - nl.Length); // Normalize newlines except the first
+ sb.Replace("\n", nl + " |", nl.Length, sb.Length - nl.Length); // Indent each line, after the first
+ sb.Append(nl + " \\").Append(hundredUnderscores);
+
+ return sb.ToString();
+ }
+
protected event EventHandler? SerializeObjectState
{
add { throw new PlatformNotSupportedException(SR.PlatformNotSupported_SecureBinarySerialization); }
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileLoadException.cs b/src/System.Private.CoreLib/shared/System/IO/FileLoadException.cs
index f7ef7c4c050e..f944c64a1b05 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileLoadException.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileLoadException.cs
@@ -50,11 +50,10 @@ public override string ToString()
{
string s = GetType().ToString() + ": " + Message;
- if (!string.IsNullOrEmpty(FileName))
+ if (!string.IsNullOrEmpty(FileName) && !Message.Contains(FileName))
s += Environment.NewLineConst + SR.Format(SR.IO_FileName_Name, FileName);
- if (InnerException != null)
- s += Environment.NewLineConst + InnerExceptionPrefix + InnerException.ToString();
+ s += InnerExceptionToString(InnerException);
if (StackTrace != null)
s += Environment.NewLineConst + StackTrace;
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileNotFoundException.cs b/src/System.Private.CoreLib/shared/System/IO/FileNotFoundException.cs
index 48c513b7f374..01b780a71586 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileNotFoundException.cs
@@ -73,11 +73,10 @@ public override string ToString()
{
string s = GetType().ToString() + ": " + Message;
- if (!string.IsNullOrEmpty(FileName))
+ if (!string.IsNullOrEmpty(FileName) && !Message.Contains(FileName))
s += Environment.NewLineConst + SR.Format(SR.IO_FileName_Name, FileName);
- if (InnerException != null)
- s += Environment.NewLineConst + InnerExceptionPrefix + InnerException.ToString();
+ s += InnerExceptionToString(InnerException);
if (StackTrace != null)
s += Environment.NewLineConst + StackTrace;
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
index 9cd971e57176..d8ebff82c280 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
@@ -227,7 +227,7 @@ public static Assembly LoadFile(string path)
if (PathInternal.IsPartiallyQualified(path))
{
- throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(path));
+ throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, path), nameof(path));
}
string normalizedPath = Path.GetFullPath(path);
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/COMException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/COMException.cs
index 6b22d0263133..eca0145f88d3 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/COMException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/COMException.cs
@@ -58,11 +58,7 @@ public override string ToString()
s.Append(": ").Append(message);
}
- Exception? innerException = InnerException;
- if (innerException != null)
- {
- s.Append(Environment.NewLineConst + InnerExceptionPrefix).Append(innerException.ToString());
- }
+ s.Append(InnerExceptionToString(InnerException));
string? stackTrace = StackTrace;
if (stackTrace != null)
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
index b9bc042986e0..e2e7e26da6a4 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
@@ -66,11 +66,7 @@ public override string ToString()
s += ": " + message;
}
- Exception? innerException = InnerException;
- if (innerException != null)
- {
- s += Environment.NewLineConst + InnerExceptionPrefix + innerException.ToString();
- }
+ s += InnerExceptionToString(InnerException);
if (StackTrace != null)
s += Environment.NewLineConst + StackTrace;
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs
index c9d0c16b7ef4..39b533516f3b 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -299,7 +299,7 @@ public Assembly LoadFromAssemblyPath(string assemblyPath)
if (PathInternal.IsPartiallyQualified(assemblyPath))
{
- throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(assemblyPath));
+ throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, assemblyPath), nameof(assemblyPath));
}
lock (_unloadLock)
@@ -319,12 +319,12 @@ public Assembly LoadFromNativeImagePath(string nativeImagePath, string? assembly
if (PathInternal.IsPartiallyQualified(nativeImagePath))
{
- throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(nativeImagePath));
+ throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, nativeImagePath), nameof(nativeImagePath));
}
if (assemblyPath != null && PathInternal.IsPartiallyQualified(assemblyPath))
{
- throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(assemblyPath));
+ throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, assemblyPath), nameof(assemblyPath));
}
lock (_unloadLock)
@@ -394,7 +394,7 @@ protected IntPtr LoadUnmanagedDllFromPath(string unmanagedDllPath)
if (PathInternal.IsPartiallyQualified(unmanagedDllPath))
{
- throw new ArgumentException(SR.Argument_AbsolutePathRequired, nameof(unmanagedDllPath));
+ throw new ArgumentException(SR.Format(SR.Argument_AbsolutePathRequired, unmanagedDllPath), nameof(unmanagedDllPath));
}
return NativeLibrary.Load(unmanagedDllPath);
diff --git a/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
index cbffeabd4bfd..68a44508268a 100644
--- a/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
+++ b/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
@@ -443,7 +443,6 @@ internal void SetCurrentStackTrace()
// when it's retrieved.
var sb = new StringBuilder(256);
new StackTrace(fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.TrailingNewLine, sb);
- sb.AppendLine(SR.Exception_EndStackTraceFromPreviousThrow);
_remoteStackTraceString = sb.ToString();
}
}
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index a47e5a04a585..684220de3475 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -3801,7 +3801,7 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec,
{
StackSString name;
pSpec->GetFileOrDisplayName(0, name);
- pEx=new EEFileLoadException(name, pEx->GetHR(), NULL, pEx);
+ pEx=new EEFileLoadException(name, pEx->GetHR(), pEx);
AddExceptionToCache(pSpec, pEx);
PAL_CPP_THROW(Exception *, pEx);
}
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp
index 08ead4c98381..f1364097e15f 100644
--- a/src/vm/assemblynative.cpp
+++ b/src/vm/assemblynative.cpp
@@ -250,13 +250,13 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext
// Need to verify that this is a valid CLR assembly.
if (!pILImage->CheckILFormat())
- ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
+ THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue());
LoaderAllocator* pLoaderAllocator = NULL;
if (SUCCEEDED(pBinderContext->GetLoaderAllocator((LPVOID*)&pLoaderAllocator)) && pLoaderAllocator->IsCollectible() && !pILImage->IsILOnly())
{
// Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed
- ThrowHR(COR_E_BADIMAGEFORMAT, BFA_IJW_IN_COLLECTIBLE_ALC);
+ THROW_BAD_FORMAT(BFA_IJW_IN_COLLECTIBLE_ALC, pILImage.GetValue());
}
}
@@ -270,7 +270,7 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext
{
// ReadyToRun images are treated as IL images by the rest of the system
if (!pNIImage->CheckILFormat())
- ThrowHR(COR_E_BADIMAGEFORMAT);
+ THROW_BAD_FORMAT(COR_E_BADIMAGEFORMAT, pNIImage.GetValue());
pILImage = pNIImage.Extract();
pNIImage = NULL;
@@ -278,7 +278,7 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext
else
{
if (!pNIImage->CheckNativeFormat())
- ThrowHR(COR_E_BADIMAGEFORMAT);
+ THROW_BAD_FORMAT(COR_E_BADIMAGEFORMAT, pNIImage.GetValue());
}
}
#endif // FEATURE_PREJIT
diff --git a/src/vm/clrex.cpp b/src/vm/clrex.cpp
index b0dc916de1a3..89094cb8876f 100644
--- a/src/vm/clrex.cpp
+++ b/src/vm/clrex.cpp
@@ -1675,10 +1675,9 @@ OBJECTREF EETypeLoadException::CreateThrowable()
// EEFileLoadException is an EE exception subclass representing a file loading
// error
// ---------------------------------------------------------------------------
-EEFileLoadException::EEFileLoadException(const SString &name, HRESULT hr, void *pFusionLog, Exception *pInnerException/* = NULL*/)
+EEFileLoadException::EEFileLoadException(const SString &name, HRESULT hr, Exception *pInnerException/* = NULL*/)
: EEException(GetFileLoadKind(hr)),
m_name(name),
- m_pFusionLog(pFusionLog),
m_hr(hr)
{
CONTRACTL
@@ -1822,18 +1821,14 @@ OBJECTREF EEFileLoadException::CreateThrowable()
}
CONTRACTL_END;
- // Fetch any log info from the fusion log
- SString logText;
struct _gc {
OBJECTREF pNewException;
STRINGREF pNewFileString;
- STRINGREF pFusLogString;
} gc;
ZeroMemory(&gc, sizeof(gc));
GCPROTECT_BEGIN(gc);
gc.pNewFileString = StringObject::NewString(m_name);
- gc.pFusLogString = StringObject::NewString(logText);
gc.pNewException = AllocateObject(MscorlibBinder::GetException(m_kind));
MethodDesc* pMD = MemberLoader::FindMethod(gc.pNewException->GetMethodTable(),
@@ -1850,7 +1845,7 @@ OBJECTREF EEFileLoadException::CreateThrowable()
ARG_SLOT args[] = {
ObjToArgSlot(gc.pNewException),
ObjToArgSlot(gc.pNewFileString),
- ObjToArgSlot(gc.pFusLogString),
+ NULL,
(ARG_SLOT) m_hr
};
diff --git a/src/vm/clrex.h b/src/vm/clrex.h
index 3fafb05c88ee..8653b4897723 100644
--- a/src/vm/clrex.h
+++ b/src/vm/clrex.h
@@ -668,13 +668,11 @@ class EEFileLoadException : public EEException
private:
SString m_name;
- void *m_pFusionLog;
HRESULT m_hr;
-
public:
- EEFileLoadException(const SString &name, HRESULT hr, void *pFusionLog = NULL, Exception *pInnerException = NULL);
+ EEFileLoadException(const SString &name, HRESULT hr, Exception *pInnerException = NULL);
~EEFileLoadException();
// virtual overrides
@@ -698,12 +696,12 @@ class EEFileLoadException : public EEException
virtual Exception *CloneHelper()
{
WRAPPER_NO_CONTRACT;
- return new EEFileLoadException(m_name, m_hr, m_pFusionLog);
+ return new EEFileLoadException(m_name, m_hr);
}
private:
#ifdef _DEBUG
- EEFileLoadException() : m_pFusionLog(NULL)
+ EEFileLoadException()
{
// Used only for DebugIsEECxxExceptionPointer to get the vtable pointer.
// We need a variant which does not allocate memory.
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp
index d3fc6ea8db9b..09981ec96a7c 100644
--- a/src/vm/excep.cpp
+++ b/src/vm/excep.cpp
@@ -12380,20 +12380,25 @@ VOID ThrowBadFormatWorker(UINT resID, LPCWSTR imageName DEBUGARG(__in_z const ch
#ifndef DACCESS_COMPILE
SString msgStr;
- if ((imageName != NULL) && (imageName[0] != 0))
- {
- msgStr += W("[");
- msgStr += imageName;
- msgStr += W("] ");
- }
-
SString resStr;
if (resID == 0 || !resStr.LoadResource(CCompRC::Optional, resID))
{
- resStr.LoadResource(CCompRC::Error, MSG_FOR_URT_HR(COR_E_BADIMAGEFORMAT));
+ resStr.LoadResource(CCompRC::Error, MSG_FOR_URT_HR(BFA_BAD_IL)); // "Bad IL format."
}
msgStr += resStr;
+ if ((imageName != NULL) && (imageName[0] != 0))
+ {
+ SString suffixResStr;
+ if (suffixResStr.LoadResource(CCompRC::Optional, COR_E_BADIMAGEFORMAT)) // "The format of the file '%1' is invalid."
+ {
+ SString suffixMsgStr;
+ suffixMsgStr.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)suffixResStr, 0, 0, imageName);
+ msgStr.AppendASCII(" ");
+ msgStr += suffixMsgStr;
+ }
+ }
+
#ifdef _DEBUG
if (0 != strcmp(cond, "FALSE"))
{