private static async Task <int> ProcessExceptionAsync(Exception ex, CommandProcessorOptions options) { int retVal = (int)ToolExitCode.Unknown; Debug.Assert(ex != null, "exception should not be null!"); if (ex != null) { try { s_processingException = true; var agex = ex as AggregateException; if (agex != null) { foreach (var ax in agex.InnerExceptions) { retVal = await ProcessExceptionAsync(ax, options); } } else if (ex is BootstrapException bootstrapEx) { ToolConsole.WriteToolError(ex); retVal = bootstrapEx.ExitCode; } else if (ex is ProcessRunner.ProcessException rpe) { ToolConsole.WriteError(rpe, null); retVal = rpe.ExitCode; } else if (ex is ToolArgumentException ae) { ToolConsole.WriteToolError(ae); retVal = (int)ae.ExitCode; } else if (ex is ToolRuntimeException rt) { ToolConsole.WriteToolError(rt); retVal = (int)rt.ExitCode; } else if (ex is DcNS.InvalidDataContractException dce) { ToolConsole.WriteError(dce); retVal = (int)ToolExitCode.RuntimeError; } else if (Utils.IsUnexpected(ex)) { ToolConsole.WriteError(SR.ErrUnexpectedError); retVal = (int)ToolExitCode.RuntimeError; } else // (Exception e) { ToolConsole.WriteError(ex); retVal = (int)ToolExitCode.Unknown; } // don't log aggregate exceptions as the internal exceptions are already logged. if (agex == null) { string exMsg = null; if (options?.Logger != null) { exMsg = Utils.GetExceptionMessage(ex, true); await options.Logger.WriteErrorAsync(exMsg, logToUI : false).ConfigureAwait(false); } // Don't log telemetry if we're running from bootstrapper or connected service. // if options = null, it must be that a parsing exception occurred. if (options == null || options.ToolContext <= OperationalContext.Global) { exMsg = exMsg ?? Utils.GetExceptionMessage(ex, true); var telemetryClient = await AppInsightsTelemetryClient.GetInstanceAsync(CancellationToken.None).ConfigureAwait(false); telemetryClient.TrackError("Exception", exMsg); } } } catch { } } return(retVal); }
internal static async Task <int> MainAsync(string[] args, ILogger logger, CancellationToken cancellationToken) { int result = -1; CommandProcessorOptions options = null; WaitForDebugger(); try { options = await CommandProcessorOptions.ParseArgumentsAsync(args, logger, cancellationToken); ValidateUICulture(options); if (options.NoTelemetry == true) { AppInsightsTelemetryClient.IsUserOptedIn = false; } ToolConsole.Init(options); ToolConsole.WriteHeaderIf(options.NoLogo != true); ThrowOnValidationErrors(options); if (options.Help == true) { ToolConsole.WriteHelp(); result = (int)ToolExitCode.Success; } else { // Show early warnings var earlyWarnings = options.Warnings; foreach (string warning in earlyWarnings.Distinct()) { ToolConsole.WriteWarning(warning); } var operationMessage = (options.IsUpdateOperation ? "Update" : "Add") + " web service reference operation started!"; using (var safeLogger = await SafeLogger.WriteStartOperationAsync(options.Logger, operationMessage).ConfigureAwait(false)) { await options.ResolveAsync(cancellationToken).ConfigureAwait(false); ThrowOnValidationErrors(options); options.ProviderId = Tool.ToolName; options.Version = Tool.PackageVersion; foreach (string warning in options.Warnings.Distinct().Except(earlyWarnings)) { ToolConsole.WriteWarning(warning); } if (options.RequiresBoostrapping) { using (var bootstrapper = new SvcutilBootstrapper(options.CloneAs <SvcutilOptions>())) { await options.SetupBootstrappingDirectoryAsync(options.Logger, cancellationToken).ConfigureAwait(false); var bootstrapResult = await bootstrapper.BoostrapSvcutilAsync(options.KeepBootstrapDir, options.Logger, cancellationToken).ConfigureAwait(false); ToolConsole.WriteLine(bootstrapResult.OutputText); result = bootstrapResult.ExitCode; } } else { result = (int) await RunAsync(options, cancellationToken).ConfigureAwait(false); } if (IsSuccess(result)) { if (!File.Exists(options.OutputFile.FullName)) { await safeLogger.WriteMessageAsync("The process completed successfully but no proxy file was found!", logToUI : false); throw new ToolArgumentException(SR.ErrUnexpectedError); } else { await GenerateParamsFileAsync(options, options.Logger, cancellationToken); if (CanAddProjectReferences(options) && !await AddProjectReferencesAsync(options.Project, options, cancellationToken).ConfigureAwait(false)) { result = (int)ToolExitCode.InputError; } } // clean up only on success to allow to troubleshoot any problems on failure. options?.Cleanup(); } } } } catch (Exception e) { result = await ProcessExceptionAsync(e, options); } finally { try { // Don't log telemetry if we're running from bootstrapper or connected service. if (options?.ToolContext <= OperationalContext.Global) { var properties = new Dictionary <string, string>() { { "IsUpdate", (options?.IsUpdateOperation).ToString() }, { "TargetFramework", options?.TargetFramework?.FullName }, { "Parameters", options?.ToTelemetryString() }, { "ExitCode", result.ToString() }, { "RequiresBootstrapping", options?.RequiresBoostrapping.ToString() }, }; var telemetryClient = await AppInsightsTelemetryClient.GetInstanceAsync(cancellationToken).ConfigureAwait(false); telemetryClient.TrackEvent("ToolRun", properties); } } catch { } } return(result); }
public static async Task <AppInsightsTelemetryClient> GetInstanceAsync(CancellationToken cancellationToken) { if (s_instance == null) { try { if (!bool.TryParse(Environment.GetEnvironmentVariable(testModeVariable), out bool testMode)) { testMode = false; } lock (s_lockObj) { if (s_instance == null) { if (!IsUserOptedIn) { // If the user hasn't opted in return now with a null telemetry client to ensure we don't create any telemetry context. return(new AppInsightsTelemetryClient(null)); } TelemetryConfiguration config; try { config = TelemetryConfiguration.Active; } catch (InvalidOperationException) { config = new TelemetryConfiguration(); } config.TelemetryChannel.DeveloperMode = testMode; s_instance = new AppInsightsTelemetryClient(new TelemetryClient(config)); } } var telemetryClient = s_instance._telemetryClient; telemetryClient.InstrumentationKey = instrumentationKey; // Populate context with properties that are common and should be logged for all events. var context = telemetryClient.Context; context.Device.OperatingSystem = GetOperatingSystemString(); #if !NETCORE10 // Set the user id to a stable hash of the user's current username. Users with the same username // or those with hash collisions will show up as the same id. So the user id won't be perfectly unique. // However, it will give us some idea of how many different users are using the tool. context.User.Id = GetStableHashCode(Environment.UserName).ToString(); #endif // DebugLogger tracks telemetry when adding exceptions. We pass null for the logger to avoid the possibility of an endless cyclic call if something goes wrong in GetSdkVersionAsync. var sdkVersion = await ProjectPropertyResolver.GetSdkVersionAsync(System.IO.Directory.GetCurrentDirectory(), null /* logger */, cancellationToken).ConfigureAwait(false); context.Properties["SvcUtil.Version"] = Tool.PackageVersion; context.Properties["Dotnet.Version"] = string.IsNullOrEmpty(sdkVersion) ? "unknown" : sdkVersion; context.Properties["TestMode"] = testMode.ToString(); } catch (Exception ex) { #if DEBUG ToolConsole.WriteWarning(ex.Message); #endif s_isUserOptedIn = false; } } return(s_instance); }