Fix/clean up command service 'command not found' paths. (#4544)
authorMike McLaughlin <mikem@microsoft.com>
Thu, 7 Mar 2024 20:38:14 +0000 (12:38 -0800)
committerGitHub <noreply@github.com>
Thu, 7 Mar 2024 20:38:14 +0000 (12:38 -0800)
Add command not found error message when managed hosting fails for
managed only commands.

Removed displaying ClassLoader address in !dumpassembly command.

Better SOS hosting error messages.

15 files changed:
src/Microsoft.Diagnostics.DebugServices.Implementation/CommandService.cs
src/Microsoft.Diagnostics.DebugServices/DiagnosticsException.cs
src/Microsoft.Diagnostics.ExtensionCommands/ClrMDHelper.cs
src/SOS/SOS.Extensions/HostServices.cs
src/SOS/SOS.Hosting/SOSLibrary.cs
src/SOS/Strike/exts.cpp
src/SOS/Strike/managedcommands.cpp
src/SOS/Strike/util.cpp
src/SOS/extensions/hostcoreclr.cpp
src/SOS/extensions/hostdesktop.cpp
src/SOS/inc/hostservices.h
src/SOS/lldbplugin/services.cpp
src/Tools/dotnet-dump/Analyzer.cs
src/Tools/dotnet-dump/Commands/SOSCommand.cs
src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/CommandServiceTests.cs

index 2c87c851418213acb0951e4261a9524d1ee25de5..07c7ef52a5d84e4e72ddb14d8aaa60867dcd7ef3 100644 (file)
@@ -41,11 +41,11 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// </summary>
         /// <param name="commandLine">command line text</param>
         /// <param name="services">services for the command</param>
-        /// <returns>true - found command, false - command not found</returns>
         /// <exception cref="ArgumentException">empty command line</exception>
-        /// <exception cref="DiagnosticsException">other errors</exception>
+        /// <exception cref="CommandNotFoundException">command not found</exception>
         /// <exception cref="CommandParsingException ">parsing error</exception>
-        public bool Execute(string commandLine, IServiceProvider services)
+        /// <exception cref="DiagnosticsException">other errors</exception>
+        public void Execute(string commandLine, IServiceProvider services)
         {
             string[] commandLineArray = CommandLineStringSplitter.Instance.Split(commandLine).ToArray();
             if (commandLineArray.Length <= 0)
@@ -53,7 +53,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                 throw new ArgumentException("Empty command line", nameof(commandLine));
             }
             string commandName = commandLineArray[0].Trim();
-            return Execute(commandName, commandLineArray, services);
+            Execute(commandName, commandLineArray, services);
         }
 
         /// <summary>
@@ -62,11 +62,11 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <param name="commandName">command name</param>
         /// <param name="commandArguments">command arguments/options</param>
         /// <param name="services">services for the command</param>
-        /// <returns>true - found command, false - command not found</returns>
         /// <exception cref="ArgumentException">empty command name or arguments</exception>
-        /// <exception cref="DiagnosticsException">other errors</exception>
+        /// <exception cref="CommandNotFoundException">command not found</exception>
         /// <exception cref="CommandParsingException ">parsing error</exception>
-        public bool Execute(string commandName, string commandArguments, IServiceProvider services)
+        /// <exception cref="DiagnosticsException">other errors</exception>
+        public void Execute(string commandName, string commandArguments, IServiceProvider services)
         {
             commandName = commandName.Trim();
             string[] commandLineArray = CommandLineStringSplitter.Instance.Split(commandName + " " + (commandArguments ?? "")).ToArray();
@@ -74,7 +74,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             {
                 throw new ArgumentException("Empty command name or arguments", nameof(commandArguments));
             }
-            return Execute(commandName, commandLineArray, services);
+            Execute(commandName, commandLineArray, services);
         }
 
         /// <summary>
@@ -83,11 +83,11 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <param name="commandName">command name</param>
         /// <param name="commandLineArray">command line</param>
         /// <param name="services">services for the command</param>
-        /// <returns>true - found command, false - command not found</returns>
         /// <exception cref="ArgumentException">empty command name</exception>
-        /// <exception cref="DiagnosticsException">other errors</exception>
+        /// <exception cref="CommandNotFoundException">command not found</exception>
         /// <exception cref="CommandParsingException ">parsing error</exception>
-        private bool Execute(string commandName, string[] commandLineArray, IServiceProvider services)
+        /// <exception cref="DiagnosticsException">other errors</exception>
+        private void Execute(string commandName, string[] commandLineArray, IServiceProvider services)
         {
             if (string.IsNullOrEmpty(commandName))
             {
@@ -104,7 +104,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                         {
                             if (group.Execute(commandLineArray, services))
                             {
-                                return true;
+                                return;
                             }
                         }
                         if (handler.FilterInvokeMessage != null)
@@ -120,9 +120,12 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             }
             if (messages.Count > 0)
             {
-                throw new CommandNotFoundException(string.Concat(messages.Select(s => s + Environment.NewLine)));
+                throw new CommandNotFoundException(messages);
+            }
+            else
+            {
+                throw new CommandNotFoundException(commandName);
             }
-            return false;
         }
 
         /// <summary>
index fa5d9c85cdcbb91ad01d693b8ea771da16b4f1a7..af10b2cb204f86b18beaae9f3853949eb8e3e63f 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
+using System.Linq;
 
 namespace Microsoft.Diagnostics.DebugServices
 {
@@ -31,15 +33,13 @@ namespace Microsoft.Diagnostics.DebugServices
     /// </summary>
     public class CommandNotFoundException : DiagnosticsException
     {
-        public const string NotFoundMessage = $"Unrecognized SOS command";
-
-        public CommandNotFoundException(string message)
-            : base(message)
+        public CommandNotFoundException(string command)
+            : base($"Unrecognized SOS command '{command}'")
         {
         }
 
-        public CommandNotFoundException(string message, Exception innerException)
-            : base(message, innerException)
+        public CommandNotFoundException(IEnumerable<string> messages)
+            : base(string.Join(Environment.NewLine, messages))
         {
         }
     }
index 1d87e10de319d6c6ea2119634b1248949561d8be..c676f5d2ae6eed80218c58f79a7226ba0c8823eb 100644 (file)
@@ -19,7 +19,18 @@ namespace Microsoft.Diagnostics.ExtensionCommands
         [ServiceExport(Scope = ServiceScope.Runtime)]
         public static ClrMDHelper TryCreate([ServiceImport(Optional = true)] ClrRuntime clrRuntime)
         {
-            return clrRuntime != null ? new ClrMDHelper(clrRuntime) : null;
+            try
+            {
+                if (clrRuntime != null)
+                {
+                    return new ClrMDHelper(clrRuntime);
+                }
+            }
+            catch (NotSupportedException ex)
+            {
+                Trace.TraceError(ex.ToString());
+            }
+            return null;
         }
 
         private ClrMDHelper(ClrRuntime clr)
index c5c042ce555ebbd83472f0b502acffc35e572e71..65b57c1fc08907cb63c5d1caa693f8741e7f5268 100644 (file)
@@ -345,7 +345,8 @@ namespace SOS.Extensions
         private int DispatchCommand(
             IntPtr self,
             string commandName,
-            string commandArguments)
+            string commandArguments,
+            bool displayCommandNotFound)
         {
             if (string.IsNullOrWhiteSpace(commandName))
             {
@@ -353,25 +354,23 @@ namespace SOS.Extensions
             }
             try
             {
-                if (_commandService.Execute(commandName, commandArguments, commandName == "help" ? _contextService.Services : _servicesWithManagedOnlyFilter))
-                {
-                    return HResult.S_OK;
-                }
-                else
-                {
-                    // The command was not found or supported
-                    return HResult.E_NOTIMPL;
-                }
+                _commandService.Execute(commandName, commandArguments, string.Equals(commandName, "help", StringComparison.OrdinalIgnoreCase) ? _contextService.Services : _servicesWithManagedOnlyFilter);
             }
             catch (Exception ex)
             {
+                if (!displayCommandNotFound && ex is CommandNotFoundException)
+                {
+                    // Returning E_NOTIMPL means no managed command or it filtered away so execute the C++ version if one
+                    return HResult.E_NOTIMPL;
+                }
                 Trace.TraceError(ex.ToString());
                 IConsoleService consoleService = Services.GetService<IConsoleService>();
                 // TODO: when we can figure out how to deal with error messages in the scripts that are displayed on STDERROR under lldb
                 //consoleService.WriteLineError(ex.Message);
                 consoleService.WriteLine(ex.Message);
+                return HResult.E_FAIL;
             }
-            return HResult.E_FAIL;
+            return HResult.S_OK;
         }
 
         private void Uninitialize(
@@ -450,7 +449,8 @@ namespace SOS.Extensions
         private delegate int DispatchCommandDelegate(
             [In] IntPtr self,
             [In, MarshalAs(UnmanagedType.LPStr)] string commandName,
-            [In, MarshalAs(UnmanagedType.LPStr)] string commandArguments);
+            [In, MarshalAs(UnmanagedType.LPStr)] string commandArguments,
+            bool displayCommandNotFound);
 
         [UnmanagedFunctionPointer(CallingConvention.Winapi)]
         private delegate void UninitializeDelegate(
index c8d4fc70af44189bde3f9e91cf4fe562c2ad17c9..d7bed24b2ef955bffe4734c8ca24550e38509a21 100644 (file)
@@ -192,12 +192,12 @@ namespace SOS.Hosting
             SOSCommandDelegate commandFunc = SOSHost.GetDelegateFunction<SOSCommandDelegate>(_sosLibrary, command);
             if (commandFunc == null)
             {
-                throw new CommandNotFoundException($"{CommandNotFoundException.NotFoundMessage} '{command}'");
+                throw new CommandNotFoundException(command);
             }
             int result = commandFunc(client, arguments ?? "");
             if (result == HResult.E_NOTIMPL)
             {
-                throw new CommandNotFoundException($"{CommandNotFoundException.NotFoundMessage} '{command}'");
+                throw new CommandNotFoundException(command);
             }
             if (result != HResult.S_OK)
             {
index 2d519030636a82736029bb8b1611e7adc58458fa..eba9fa9bbc0bb4ed8fbf0ba5e30821b92b1f1d8e 100644 (file)
@@ -209,7 +209,7 @@ ExecuteCommand(PCSTR commandName, PCSTR args)
         IHostServices* hostServices = GetHostServices();
         if (hostServices != nullptr)
         {
-            return hostServices->DispatchCommand(commandName, args);
+            return hostServices->DispatchCommand(commandName, args, /* displayCommandNotFound */ false);
         }
     }
     return E_NOTIMPL;
@@ -231,37 +231,44 @@ void
 DACMessage(HRESULT Status)
 {
     ExtOut("Failed to load data access module, 0x%08x\n", Status);
-    if (GetHost()->GetHostType() == IHost::HostType::DbgEng)
+    if (g_pRuntime->GetRuntimeConfiguration() >= IRuntime::ConfigurationEnd)
     {
-        ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
-        ExtOut("            2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
-        ExtOut("                in the version directory or on the symbol path\n");
-        ExtOut("            3) or, if you are debugging a dump file, verify that the file\n");
-        ExtOut("                %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
-        ExtOut("            4) you are debugging on a platform and architecture that supports this\n");
-        ExtOut("                the dump file. For example, an ARM dump file must be debugged\n");
-        ExtOut("                on an X86 or an ARM machine; an AMD64 dump file must be\n");
-        ExtOut("                debugged on an AMD64 machine.\n");
-        ExtOut("\n");
-        ExtOut("You can run the command '!setclrpath <directory>' to control the load path of %s.\n", GetDacDllName());
-        ExtOut("\n");
-        ExtOut("Or you can also run the debugger command .cordll to control the debugger's\n");
-        ExtOut("load of %s. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
-        ExtOut("If that succeeds, the SOS command should work on retry.\n");
-        ExtOut("\n");
-        ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
-        ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
+        ExtOut("Unknown runtime type. Command not supported.\n");
     }
     else
     {
-        if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+        if (GetHost()->GetHostType() == IHost::HostType::DbgEng)
         {
-            ExtOut("You can run the debugger command 'setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+            ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
+            ExtOut("            2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
+            ExtOut("                in the version directory or on the symbol path\n");
+            ExtOut("            3) or, if you are debugging a dump file, verify that the file\n");
+            ExtOut("                %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
+            ExtOut("            4) you are debugging on a platform and architecture that supports this\n");
+            ExtOut("                the dump file. For example, an ARM dump file must be debugged\n");
+            ExtOut("                on an X86 or an ARM machine; an AMD64 dump file must be\n");
+            ExtOut("                debugged on an AMD64 machine.\n");
+            ExtOut("\n");
+            ExtOut("You can run the command '!setclrpath <directory>' to control the load path of %s.\n", GetDacDllName());
+            ExtOut("\n");
+            ExtOut("Or you can also run the debugger command .cordll to control the debugger's\n");
+            ExtOut("load of %s. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
             ExtOut("If that succeeds, the SOS command should work on retry.\n");
+            ExtOut("\n");
+            ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
+            ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
         }
         else
         {
-            ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+            if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+            {
+                ExtOut("You can run the debugger command 'setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+                ExtOut("If that succeeds, the SOS command should work on retry.\n");
+            }
+            else
+            {
+                ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+            }
         }
     }
     ExtOut("\n");
index a255795cd9a4fbca3f7b089b980b134ee21306ef..e0a5cbf055500f94f740f66cda66d928c0cc5bd5 100644 (file)
@@ -7,12 +7,13 @@
 
 HRESULT ExecuteManagedOnlyCommand(PCSTR commandName, PCSTR args)
 {
-    HRESULT hr = ExecuteCommand(commandName, args);
-    if (hr == E_NOTIMPL)
+    IHostServices* hostServices = GetHostServices();
+    if (hostServices != nullptr)
     {
-        ExtErr("Unrecognized command '%s'\n", commandName);
+        return hostServices->DispatchCommand(commandName, args, /* displayCommandNotFound */ true);
     }
-    return hr;
+    ExtErr("Unrecognized command '%s' because managed hosting failed or was disabled. See !sethostruntime command for details.\n", commandName);
+    return E_NOTIMPL;
 }
 
 DECLARE_API(DumpStackObjects)
index 9fa4c8d86e46ffe929e8d34ece43a41d4f841492..4d4e0d8c33c71a7fb8f0360e4a5134ff2a06cbb7 100644 (file)
@@ -1507,7 +1507,6 @@ HRESULT FileNameForModule(const DacpModuleData* const pModuleData, __out_ecount(
 
 void AssemblyInfo(DacpAssemblyData *pAssembly)
 {
-    ExtOut("ClassLoader:        %p\n", SOS_PTR(pAssembly->ClassLoader));
     if ((ULONG64)pAssembly->AssemblySecDesc != NULL)
         ExtOut("SecurityDescriptor: %p\n", SOS_PTR(pAssembly->AssemblySecDesc));
     ExtOut("  Module\n");
index 43ca023e54d183c5e3a81a5c5b73404dc27c9c0b..002ec7dc832596c411a3862309b0b826549efa9d 100644 (file)
@@ -397,7 +397,7 @@ static HRESULT ProbeInstallationMarkerFile(const char* const markerName, std::st
 
     if (getline(&line, &lineLen, locationFile) == -1)
     {
-        TraceError("Unable to read .NET installation marker at %s\n", markerName);
+        TraceError("SOS_HOSTING: Unable to read .NET installation marker at %s\n", markerName);
         free(line);
         return E_FAIL;
     }
@@ -467,7 +467,7 @@ static HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntime
     if (g_hostRuntimeDirectory == nullptr)
     {
 #if defined(HOST_FREEBSD)
-        TraceError("Hosting on NetBSD not supported\n");
+        TraceError("SOS_HOSTING: FreeBSD not supported\n");
         return E_FAIL;
 #else
 
@@ -490,7 +490,7 @@ static HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntime
         ArrayHolder<CHAR> programFiles = new CHAR[MAX_LONGPATH];
         if (GetEnvironmentVariableA("PROGRAMFILES", programFiles, MAX_LONGPATH) == 0)
         {
-            TraceError("PROGRAMFILES environment variable not found\n");
+            TraceError("SOS_HOSTING: PROGRAMFILES environment variable not found\n");
             return E_FAIL;
         }
         std::string windowsInstallPath(programFiles);
@@ -504,7 +504,7 @@ static HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntime
 
         if (Status != S_OK)
         {
-            TraceError("Error: Failed to find runtime directory\n");
+            TraceError("SOS_HOSTING: Failed to find runtime directory\n");
             return E_FAIL;
         }
 
@@ -521,7 +521,7 @@ static HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntime
 
         if (hostRuntimeVersion.Major == 0)
         {
-            TraceError("Error: Failed to find a supported runtime within %s\n", hostRuntimeDirectory.c_str());
+            TraceError("SOS_HOSTING: Failed to find a supported runtime within %s\n", hostRuntimeDirectory.c_str());
             return E_FAIL;
         }
 
@@ -548,7 +548,7 @@ static HRESULT InitializeNetCoreHost()
     Dl_info info;
     if (dladdr((PVOID)&InitializeNetCoreHost, &info) == 0)
     {
-        TraceError("Error: dladdr() failed getting current module directory\n");
+        TraceError("SOS_HOSTING: Failed to get SOS module directory with dladdr()\n");
         return E_FAIL;
     }
     sosModulePath = info.dli_fname;
@@ -556,7 +556,7 @@ static HRESULT InitializeNetCoreHost()
     ArrayHolder<char> szSOSModulePath = new char[MAX_LONGPATH + 1];
     if (GetModuleFileNameA(g_hInstance, szSOSModulePath, MAX_LONGPATH) == 0)
     {
-        TraceError("Error: Failed to get SOS module directory\n");
+        TraceError("SOS_HOSTING: Failed to get SOS module directory\n");
         return HRESULT_FROM_WIN32(GetLastError());
     }
     sosModulePath = szSOSModulePath;
@@ -580,7 +580,7 @@ static HRESULT InitializeNetCoreHost()
         void* coreclrLib = dlopen(coreClrPath.c_str(), RTLD_NOW | RTLD_LOCAL);
         if (coreclrLib == nullptr)
         {
-            TraceError("Error: Failed to load %s\n", coreClrPath.c_str());
+            TraceError("SOS_HOSTING: Failed to load runtime module %s\n", coreClrPath.c_str());
             return E_FAIL;
         }
         initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
@@ -589,7 +589,7 @@ static HRESULT InitializeNetCoreHost()
         HMODULE coreclrLib = LoadLibraryA(coreClrPath.c_str());
         if (coreclrLib == nullptr)
         {
-            TraceError("Error: Failed to load %s\n", coreClrPath.c_str());
+            TraceError("SOS_HOSTING: Failed to load runtime module %s\n", coreClrPath.c_str());
             return E_FAIL;
         }
         initializeCoreCLR = (coreclr_initialize_ptr)GetProcAddress(coreclrLib, "coreclr_initialize");
@@ -598,7 +598,7 @@ static HRESULT InitializeNetCoreHost()
 
         if (initializeCoreCLR == nullptr || createDelegate == nullptr)
         {
-            TraceError("Error: coreclr_initialize or coreclr_create_delegate not found\n");
+            TraceError("SOS_HOSTING: coreclr_initialize or coreclr_create_delegate not found in %s\n", coreClrPath.c_str());
             return E_FAIL;
         }
 
@@ -607,7 +607,7 @@ static HRESULT InitializeNetCoreHost()
         size_t lastSlash = sosModuleDirectory.rfind(DIRECTORY_SEPARATOR_CHAR_A);
         if (lastSlash == std::string::npos)
         {
-            TraceError("Error: Failed to parse sos module name\n");
+            TraceError("SOS_HOSTING: Failed to parse SOS module name\n");
             return E_FAIL;
         }
         sosModuleDirectory.erase(lastSlash);
@@ -642,25 +642,24 @@ static HRESULT InitializeNetCoreHost()
         char* exePath = minipal_getexepath();
         if (!exePath)
         {
-            TraceError("Could not get full path to current executable\n");
+            TraceError("SOS_HOSTING: Could not get full path to current executable\n");
             return E_FAIL;
         }
 
         void* hostHandle;
         unsigned int domainId;
         hr = initializeCoreCLR(exePath, "sos", ARRAY_SIZE(propertyKeys), propertyKeys, propertyValues, &hostHandle, &domainId);
-
         free(exePath);
         if (FAILED(hr))
         {
-            TraceError("Error: Fail to initialize coreclr %08x\n", hr);
+            TraceError("SOS_HOSTING: Fail to initialize hosting runtime '%s' %08x\n", coreClrPath.c_str(), hr);
             return hr;
         }
 
         hr = createDelegate(hostHandle, domainId, ExtensionsDllName, ExtensionsClassName, ExtensionsInitializeFunctionName, (void**)&g_extensionsInitializeFunc);
         if (FAILED(hr))
         {
-            TraceError("Error: Fail to create host ldelegate %08x\n", hr);
+            TraceError("SOS_HOSTING: Fail to create hosting delegate %08x\n", hr);
             return hr;
         }
     }
@@ -674,7 +673,7 @@ static HRESULT InitializeNetCoreHost()
     }
     if (FAILED(hr))
     {
-        TraceError("Extension host initialization FAILED %08x\n", hr);
+        TraceError("SOS_HOSTING: Extension host initialization FAILED %08x\n", hr);
         return hr;
     }
     return hr;
index af1cdd3abf72a9ea5243b4aded6084a87f4c9095..40281155865ad241ec1eb68f325b8f652ef7f0d4 100644 (file)
@@ -35,13 +35,13 @@ HRESULT InitializeDesktopClrHost()
     ArrayHolder<WCHAR> wszSOSModulePath = new WCHAR[MAX_LONGPATH + 1];
     if (GetModuleFileNameW(g_hInstance, wszSOSModulePath, MAX_LONGPATH) == 0)
     {
-        TraceError("Error: Failed to get SOS module directory\n");
+        TraceError("SOS_HOSTING: Failed to get SOS module directory\n");
         return HRESULT_FROM_WIN32(GetLastError());
     }
     ArrayHolder<WCHAR> wszManagedModulePath = new WCHAR[MAX_LONGPATH + 1];
     if (wcscpy_s(wszManagedModulePath.GetPtr(), MAX_LONGPATH, wszSOSModulePath.GetPtr()) != 0)
     {
-        TraceError("Error: Failed to copy module name\n");
+        TraceError("SOS_HOSTING: Failed to copy module name\n");
         return E_FAIL;
     }
     WCHAR* lastSlash = wcsrchr(wszManagedModulePath.GetPtr(), DIRECTORY_SEPARATOR_CHAR_W);
@@ -51,7 +51,7 @@ HRESULT InitializeDesktopClrHost()
     }
     if (wcscat_s(wszManagedModulePath.GetPtr(), MAX_LONGPATH, ExtensionsDllNameW) != 0)
     {
-        TraceError("Error: Failed to append SOS module name\n");
+        TraceError("SOS_HOSTING: Failed to append SOS module name\n");
         return E_FAIL;
     }
     if (g_clrHost == nullptr)
@@ -59,7 +59,7 @@ HRESULT InitializeDesktopClrHost()
         hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
         if (FAILED(hr) && hr != RPC_E_CHANGED_MODE)
         {
-            TraceError("Error: CoInitializeEx failed. %08x\n", hr);
+            TraceError("SOS_HOSTING: CoInitializeEx failed. %08x\n", hr);
             return hr;
         }
         // Loads the CLR and then initializes the managed debugger extensions.
@@ -67,26 +67,26 @@ HRESULT InitializeDesktopClrHost()
         hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (PVOID*)&metaHost);
         if (FAILED(hr) || metaHost == nullptr)
         {
-            TraceError("Error: CLRCreateInstance failed %08x\n", hr);
+            TraceError("SOS_HOSTING: CLRCreateInstance failed %08x\n", hr);
             return hr;
         }
         ReleaseHolder<ICLRRuntimeInfo> runtimeInfo;
         hr = metaHost->GetRuntime(CLR_VERSION, IID_ICLRRuntimeInfo, (PVOID*)&runtimeInfo);
         if (FAILED(hr) || runtimeInfo == nullptr)
         {
-            TraceError("Error: ICLRMetaHost::GetRuntime failed %08x\n", hr);
+            TraceError("SOS_HOSTING: ICLRMetaHost::GetRuntime failed %08x\n", hr);
             return hr;
         }
         hr = runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*)&g_clrHost);
         if (FAILED(hr) || g_clrHost == nullptr)
         {
-            TraceError("Error: ICLRRuntimeInfo::GetInterface failed %08x\n", hr);
+            TraceError("SOS_HOSTING: ICLRRuntimeInfo::GetInterface failed %08x\n", hr);
             return hr;
         }
         hr = g_clrHost->Start();
         if (FAILED(hr))
         {
-            TraceError("Error: ICLRRuntimeHost::Start failed %08x\n", hr);
+            TraceError("SOS_HOSTING: ICLRRuntimeHost::Start failed %08x\n", hr);
             g_clrHost->Release();
             g_clrHost = nullptr;
             return hr;
@@ -96,14 +96,14 @@ HRESULT InitializeDesktopClrHost()
     hr = g_clrHost->ExecuteInDefaultAppDomain(wszManagedModulePath.GetPtr(), ExtensionsClassNameW, ExtensionsInitializeFunctionNameW, wszSOSModulePath.GetPtr(), (DWORD *)&ret);
     if (FAILED(hr)) 
     {
-        TraceError("Error: ICLRRuntimeHost::ExecuteInDefaultAppDomain failed %08x\n", hr);
+        TraceError("SOS_HOSTING: ICLRRuntimeHost::ExecuteInDefaultAppDomain failed %08x\n", hr);
         g_clrHost->Release();
         g_clrHost = nullptr;
         return hr;
     }
     if (ret != 0)
     { 
-        TraceError("Error: InitializeSymbolReader failed %08x\n", ret);
+        TraceError("SOS_HOSTING: Extension initialization failed %08x\n", ret);
         g_clrHost->Release();
         g_clrHost = nullptr;
         return ret;
index 74f18156099d061f43fae6aa4608453d3d4cc9f7..03afb0b550a421798362609885d44354130c9a5f 100644 (file)
@@ -77,10 +77,12 @@ public:
     /// </summary>
     /// <param name="commandName">command name</param>
     /// <param name="arguments">command arguments</param>
+    /// <param name="displayCommandNotFound">if true, display command not found error message; if false, return E_NOTIMPL</param>
     /// <returns>error code</returns>
     virtual HRESULT STDMETHODCALLTYPE DispatchCommand( 
         PCSTR commandName,
-        PCSTR arguments) = 0;
+        PCSTR arguments,
+        bool displayCommandNotFound) = 0;
 
     /// <summary>
     /// Uninitialize the extension infrastructure
index f340a069ad714d98f1b8e13d6d2d001c814994a9..54c430d20d3cfcc8de1bd6a3ce3920a97b2abbcc 100644 (file)
@@ -2153,6 +2153,7 @@ public:
         IHostServices* hostservices = GetHostServices();
         if (hostservices == nullptr)
         {
+            g_services->Output(DEBUG_OUTPUT_ERROR, "Unrecognized command '%s' because managed hosting failed or was disabled. See sethostruntime command for details.\n", m_commandName);
             result.SetStatus(lldb::eReturnStatusFailed);
             return false;
         }
@@ -2166,7 +2167,7 @@ public:
             }
         }
         g_services->FlushCheck();
-        HRESULT hr = hostservices->DispatchCommand(m_commandName, commandArguments.c_str());
+        HRESULT hr = hostservices->DispatchCommand(m_commandName, commandArguments.c_str(), /* displayCommandNotFound */ true);
         if (hr != S_OK)
         {
             result.SetStatus(lldb::eReturnStatusFailed);
@@ -2999,7 +3000,7 @@ LLDBServices::ExecuteCommand(
     if (hostservices != nullptr)
     {
         g_services->FlushCheck();
-        HRESULT hr = hostservices->DispatchCommand(commandName, commandArguments.c_str());
+        HRESULT hr = hostservices->DispatchCommand(commandName, commandArguments.c_str(), /* displayCommandNotFound */ false);
         if (hr != E_NOTIMPL)
         {
             result.SetStatus(hr == S_OK ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusFailed);
index 2a2b5defcff5c2aff7179f80724d23f863587386..55b0abc93860e129989585141b56ac2828fc3eaa 100644 (file)
@@ -137,10 +137,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
                 {
                     foreach (string commandLine in command)
                     {
-                        if (!_commandService.Execute(commandLine, contextService.Services))
-                        {
-                            throw new CommandNotFoundException($"{CommandNotFoundException.NotFoundMessage} '{commandLine}'");
-                        }
+                        _commandService.Execute(commandLine, contextService.Services);
                         if (_consoleService.Shutdown)
                         {
                             break;
@@ -157,10 +154,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
 
                     _consoleService.Start((string prompt, string commandLine, CancellationToken cancellation) => {
                         _fileLoggingConsoleService.WriteLine("{0}{1}", prompt, commandLine);
-                        if (!_commandService.Execute(commandLine, contextService.Services))
-                        {
-                            throw new CommandNotFoundException($"{CommandNotFoundException.NotFoundMessage} '{commandLine}'");
-                        }
+                        _commandService.Execute(commandLine, contextService.Services);
                     });
                 }
             }
index 8a93d496f51b5b449cc8700958e064e59c4d3d51..d7bdc5fb7a7243c4757a50240b3283651642de87 100644 (file)
@@ -39,15 +39,18 @@ namespace Microsoft.Diagnostics.Tools.Dump
                 command = "help";
                 arguments = null;
             }
-            if (CommandService.Execute(command, arguments, Services))
+            try
             {
-                return;
+                CommandService.Execute(command, arguments, Services);
             }
-            if (SOSHost is null)
+            catch (CommandNotFoundException)
             {
-                throw new CommandNotFoundException($"{CommandNotFoundException.NotFoundMessage} '{command}'");
+                if (SOSHost is null)
+                {
+                    throw;
+                }
+                SOSHost.ExecuteCommand(command, arguments);
             }
-            SOSHost.ExecuteCommand(command, arguments);
         }
     }
 }
index 34f018693f7efb41bf2b099458c8d7f0442f5053..ce504124fb5f52dd281c4dfe8cb040e09edfec9b 100644 (file)
@@ -67,7 +67,7 @@ namespace Microsoft.Diagnostics.DebugServices.UnitTests
             TestCommand2.Invoked = false;
             TestCommand3.FilterValue = false;
             TestCommand3.Invoked = false;
-            Assert.True(commandService.Execute("testcommand", testDump.Target.Services));
+            commandService.Execute("testcommand", testDump.Target.Services);
             Assert.True(TestCommand1.Invoked);
             Assert.False(TestCommand2.Invoked);
             Assert.False(TestCommand3.Invoked);
@@ -85,7 +85,7 @@ namespace Microsoft.Diagnostics.DebugServices.UnitTests
             TestCommand2.Invoked = false;
             TestCommand3.FilterValue = false;
             TestCommand3.Invoked = false;
-            Assert.True(commandService.Execute("testcommand", testDump.Target.Services));
+            commandService.Execute("testcommand", testDump.Target.Services);
             Assert.False(TestCommand1.Invoked);
             Assert.True(TestCommand2.Invoked);
             Assert.False(TestCommand3.Invoked);
@@ -98,7 +98,7 @@ namespace Microsoft.Diagnostics.DebugServices.UnitTests
             TestCommand2.Invoked = false;
             TestCommand3.FilterValue = true;
             TestCommand3.Invoked = false;
-            Assert.True(commandService.Execute("testcommand", "--foo 23", testDump.Target.Services));
+            commandService.Execute("testcommand", "--foo 23", testDump.Target.Services);
             Assert.False(TestCommand1.Invoked);
             Assert.False(TestCommand2.Invoked);
             Assert.True(TestCommand3.Invoked);
@@ -118,7 +118,7 @@ namespace Microsoft.Diagnostics.DebugServices.UnitTests
             TestCommand3.Invoked = false;
             try
             {
-                Assert.False(commandService.Execute("testcommand", testDump.Target.Services));
+                commandService.Execute("testcommand", testDump.Target.Services);
             }
             catch (DiagnosticsException ex)
             {