diff --git a/src/Microsoft.SqlTools.Credentials/Program.cs b/src/Microsoft.SqlTools.Credentials/Program.cs
index b34bad42..9f66db5e 100644
--- a/src/Microsoft.SqlTools.Credentials/Program.cs
+++ b/src/Microsoft.SqlTools.Credentials/Program.cs
@@ -19,28 +19,36 @@ namespace Microsoft.SqlTools.Credentials
///
internal static void Main(string[] args)
{
- // read command-line arguments
- CommandOptions commandOptions = new CommandOptions(args);
- if (commandOptions.ShouldExit)
+ try
{
- return;
+ // read command-line arguments
+ CommandOptions commandOptions = new CommandOptions(args);
+ if (commandOptions.ShouldExit)
+ {
+ return;
+ }
+
+ // turn on Verbose logging during early development
+ // we need to switch to Normal when preparing for public preview
+ Logger.Initialize(minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging);
+ Logger.Write(LogLevel.Normal, "Starting SqlTools Credentials Provider");
+
+ // set up the host details and profile paths
+ var hostDetails = new HostDetails(
+ name: "SqlTools Credentials Provider",
+ profileId: "Microsoft.SqlTools.Credentials",
+ version: new Version(1, 0));
+
+ SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
+ CredentialsServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext);
+
+ serviceHost.WaitForExit();
+ }
+ catch (Exception e)
+ {
+ Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e));
+ Environment.Exit(1);
}
-
- // turn on Verbose logging during early development
- // we need to switch to Normal when preparing for public preview
- Logger.Initialize(minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging);
- Logger.Write(LogLevel.Normal, "Starting SqlTools Credentials Provider");
-
- // set up the host details and profile paths
- var hostDetails = new HostDetails(
- name: "SqlTools Credentials Provider",
- profileId: "Microsoft.SqlTools.Credentials",
- version: new Version(1, 0));
-
- SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
- CredentialsServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext);
-
- serviceHost.WaitForExit();
}
}
}
diff --git a/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs b/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs
index fa6dedf8..6b515a17 100644
--- a/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs
+++ b/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs
@@ -73,6 +73,24 @@ namespace Microsoft.SqlTools.Utility
Logger.isInitialized = true;
+ // Create the log directory
+ string logDir = Path.GetDirectoryName(logFilePath);
+ if (!string.IsNullOrWhiteSpace(logDir))
+ {
+ if (!Directory.Exists(logDir))
+ {
+ try
+ {
+ Directory.CreateDirectory(logDir);
+ }
+ catch (Exception)
+ {
+ // Creating the log directory is a best effort operation, so ignore any failures.
+ }
+ }
+ }
+
+
// get a unique number to prevent conflicts of two process launching at the same time
int uniqueId;
try
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Program.cs b/src/Microsoft.SqlTools.ServiceLayer/Program.cs
index 13bab0b6..15d5e3ae 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Program.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Program.cs
@@ -6,6 +6,7 @@ using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
+using System.IO;
namespace Microsoft.SqlTools.ServiceLayer
{
@@ -19,26 +20,39 @@ namespace Microsoft.SqlTools.ServiceLayer
///
internal static void Main(string[] args)
{
- // read command-line arguments
- CommandOptions commandOptions = new CommandOptions(args);
- if (commandOptions.ShouldExit)
+ try
{
- return;
+ // read command-line arguments
+ CommandOptions commandOptions = new CommandOptions(args);
+ if (commandOptions.ShouldExit)
+ {
+ return;
+ }
+
+ string logFilePath = "sqltools";
+ if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory))
+ {
+ logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath);
+ }
+
+ // turn on Verbose logging during early development
+ // we need to switch to Normal when preparing for public preview
+ Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging);
+ Logger.Write(LogLevel.Normal, "Starting SQL Tools Service Host");
+
+ // set up the host details and profile paths
+ var hostDetails = new HostDetails(version: new Version(1, 0));
+
+ SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
+ ServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext);
+
+ serviceHost.WaitForExit();
+ }
+ catch (Exception e)
+ {
+ Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e));
+ Environment.Exit(1);
}
-
- // turn on Verbose logging during early development
- // we need to switch to Normal when preparing for public preview
- Logger.Initialize(minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging);
- Logger.Write(LogLevel.Normal, "Starting SQL Tools Service Host");
-
- // set up the host details and profile paths
- var hostDetails = new HostDetails(version: new Version(1, 0));
-
- SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
- ServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext);
-
- serviceHost.WaitForExit();
}
-
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs
index 57eda1a9..59888389 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs
@@ -5,6 +5,7 @@
using System;
using System.Globalization;
+using System.IO;
namespace Microsoft.SqlTools.ServiceLayer.Utility
{
@@ -31,28 +32,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
// Extracting arguments and properties
arg = arg.Substring(1).ToLowerInvariant();
string argName = arg;
- string argProperty = "";
- int splitIndex = arg.IndexOf(' ');
- if (splitIndex > 0)
- {
- argName = arg.Substring(0, splitIndex);
- argProperty = arg.Substring(splitIndex + 1);
- }
switch (argName)
{
case "-enable-logging":
EnableLogging = true;
break;
+ case "-log-dir":
+ SetLoggingDirectory(args[++i]);
+ break;
case "-locale":
- SetLocale(argProperty);
+ SetLocale(args[++i]);
break;
case "h":
case "-help":
ShouldExit = true;
return;
default:
- ErrorMessage += String.Format("Unknown argument \"{0}\" with property \"{1}\"" + Environment.NewLine, argName, argProperty);
+ ErrorMessage += String.Format("Unknown argument \"{0}\"" + Environment.NewLine, argName);
break;
}
}
@@ -81,6 +78,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
///
public bool EnableLogging { get; private set; }
+ ///
+ /// Gets the directory where log files are output.
+ ///
+ public string LoggingDirectory { get; private set; }
+
///
/// Whether the program should exit immediately. Set to true when the usage is printed.
///
@@ -102,6 +104,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
"Microsoft.SqlTools.ServiceLayer.exe " + Environment.NewLine +
" Options:" + Environment.NewLine +
" [--enable-logging]" + Environment.NewLine +
+ " [--log-dir **] (default: current directory)" + Environment.NewLine +
" [--help]" + Environment.NewLine +
" [--locale **] (default: 'en')" + Environment.NewLine,
ErrorMessage);
@@ -109,6 +112,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
}
}
+ private void SetLoggingDirectory(string loggingDirectory)
+ {
+ if (string.IsNullOrWhiteSpace(loggingDirectory))
+ {
+ return;
+ }
+
+ this.LoggingDirectory = Path.GetFullPath(loggingDirectory);
+ }
+
private void SetLocale(string locale)
{
try
@@ -124,10 +137,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
// Setting our internal SR culture to our global culture
SR.Culture = CultureInfo.CurrentCulture;
}
- catch(Exception ex)
+ catch (CultureNotFoundException)
{
- // Warn user of invalid locale, and fall back to english
- Console.WriteLine(ex);
+ // Ignore CultureNotFoundException since it only is thrown before Windows 10. Windows 10,
+ // along with macOS and Linux, pick up the default culture if an invalid locale is passed
+ // into the CultureInfo constructor.
}
}
}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs
index 9400ee43..a8f4a07a 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs
@@ -212,7 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost
public void SrStringsTestWithEnLocalization()
{
string locale = "en";
- var args = new string[] { "--locale " + locale };
+ var args = new string[] { "--locale", locale };
CommandOptions options = new CommandOptions(args);
Assert.Equal(SR.Culture.Name, options.Locale);
Assert.Equal(options.Locale, locale);
@@ -225,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost
public void SrStringsTestWithEsLocalization()
{
string locale = "es";
- var args = new string[] { "--locale " + locale };
+ var args = new string[] { "--locale", locale };
CommandOptions options = new CommandOptions(args);
Assert.Equal(SR.Culture.Name, options.Locale);
Assert.Equal(options.Locale, locale);
diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs
index 0ba99322..3771c05a 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs
@@ -4,6 +4,7 @@
//
using Microsoft.SqlTools.ServiceLayer.Utility;
+using System.IO;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
@@ -68,6 +69,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
Assert.False(options.EnableLogging);
Assert.False(options.ShouldExit);
+ Assert.True(string.IsNullOrWhiteSpace(options.LoggingDirectory));
Assert.Equal(options.Locale, string.Empty);
}
@@ -76,7 +78,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
[InlineData("es")]
public void LocaleSetWhenProvided(string locale)
{
- var args = new string[] {"--locale " + locale};
+ var args = new string[] {"--locale", locale};
CommandOptions options = new CommandOptions(args);
// Asserting all options were properly set
@@ -86,10 +88,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
}
[Fact]
- public void ShouldExitSetWhenInvalidLocale()
+ public void ShouldExitNotSetWhenInvalidLocale()
{
string locale = "invalid";
- var args = new string[] { "--locale " + locale };
+ var args = new string[] { "--locale", locale };
CommandOptions options = new CommandOptions(args);
// Asserting all options were properly set
@@ -109,5 +111,18 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
Assert.False(options.ShouldExit);
Assert.Equal(options.Locale, string.Empty);
}
+
+ [Fact]
+ public void LoggingDirectorySet()
+ {
+ string logDir = Directory.GetCurrentDirectory();
+ var args = new string[] { "--log-dir", logDir };
+ CommandOptions options = new CommandOptions(args);
+
+ // Asserting all options were properly set
+ Assert.NotNull(options);
+ Assert.False(options.ShouldExit);
+ Assert.Equal(options.LoggingDirectory, logDir);
+ }
}
}