Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ import
DotnetWSLSecurityError,
EventBasedError,
EventCancellationError,
SuppressedAcquisitionError,
UtilizingExistingInstallPromise
SuppressedAcquisitionError
} from '../EventStream/EventStreamEvents';
import * as versionUtils from './VersionUtilities';

Expand Down Expand Up @@ -399,12 +398,18 @@ To keep your .NET version up to date, please reconnect to the internet at your s
{
if (error instanceof EventBasedError || error instanceof EventCancellationError)
{
error.message = `.NET Acquisition Failed: ${error.message}, ${error?.stack}`;
return error;
}
else
{
// Remove this when https://github.com/typescript-eslint/typescript-eslint/issues/2728 is done
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (error?.error?.message !== undefined) // DotnetAcquisitionError is a bad but common pattern where the error is included in the thrown object
{
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const convertedError = new EventBasedError(error?.constructor?.name ?? 'DotnetAcquisitionError', error?.error?.message, error?.stack);
return convertedError;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const newError = new EventBasedError('DotnetAcquisitionError', `.NET Acquisition Failed: ${error?.message ?? JSON.stringify(error)}`);
return newError;
Expand Down Expand Up @@ -455,9 +460,15 @@ To keep your .NET version up to date, please reconnect to the internet at your s

if (installerResult !== '0')
{
// For user-friendly exit codes, show only the interpreted message without verbose details
const interpretedMessage = WinMacGlobalInstaller.InterpretExitCode(installerResult);
const errorMessage = WinMacGlobalInstaller.IsUserFriendlyExitCode(installerResult)
? interpretedMessage
: `An error was raised by the .NET SDK installer. The exit code it gave us: ${installerResult}.
${interpretedMessage}`;

const err = new DotnetNonZeroInstallerExitCodeError(new EventBasedError('DotnetNonZeroInstallerExitCodeError',
`An error was raised by the .NET SDK installer. The exit code it gave us: ${installerResult}.
${WinMacGlobalInstaller.InterpretExitCode(installerResult)}`), install);
errorMessage), install);
context.eventStream.post(err);
throw err;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ We cannot verify our .NET file host at this time. Please try again later or inst
this.registry = registryReader ?? new RegistryReader(context, utilContext);
}

/**
* Determines if the given exit code has a user-friendly, self-contained error message
* that doesn't need additional technical details to be helpful to the user.
*/
public static IsUserFriendlyExitCode(code: string): boolean
{
return this.InterpretExitCode(code) !== '';
}

public static InterpretExitCode(code: string): string
{
const reportLogMessage = `Please provide your .NET Installer log (note our privacy notice), which can be found at %temp%.
Expand All @@ -98,23 +107,23 @@ This report should be made at https://github.com/dotnet/vscode-dotnet-runtime/is
case '5':
return `Insufficient permissions are available to install .NET. Please run the installer as an administrator.`;
case '67':
return `The network name cannot be found. ${reportLogMessage}`;
return `The network name cannot be found to install .NET. ${reportLogMessage}`;
case '112':
return `The disk is full. Please free up space and try again.`;
case '255':
return `The .NET Installer was terminated by another process unexpectedly. Please try again.`;
case '1260':
return `The .NET SDK is blocked by group policy. Can you please report this at https://github.com/dotnet/vscode-dotnet-runtime/issues`
return `The .NET SDK Install is blocked by group policy. Please contact your IT Admin to install .NET.`
case '1460':
return `The .NET SDK had a timeout error. ${reportLogMessage}`;
case '1603':
return `Fatal error during .NET SDK installation. ${reportLogMessage}`;
case '1618':
return `Another installation is already in progress. Complete that installation before proceeding with this install.`;
return `Another installation of .NET is already in progress. Complete that installation before proceeding with this install.`;
case '000751':
return `Page fault was satisfied by reading from a secondary storage device. ${reportLogMessage}`;
return `.NET Installer Failed: A page fault was satisfied by reading from a secondary storage device. ${reportLogMessage}`;
case '2147500037':
return `An unspecified error occurred. ${reportLogMessage}`;
return `.NET Installer Failed: An unspecified error occurred. ${reportLogMessage}`;
case '2147942405':
return `Insufficient permissions are available to install .NET. Please try again as an administrator.`;
case UNABLE_TO_ACQUIRE_GLOBAL_LOCK_ERR:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import
DotnetOfflineInstallUsed,
DotnetOfflineWarning,
DotnetUpgradedEvent,
DotnetVisibleWarningEvent,
DotnetVisibleWarningEvent
} from './EventStreamEvents';
import { EventType } from './EventType';
import { IEvent } from './IEvent';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,22 @@ ${fs.readdirSync(installerDownloadFolder).join(', ')}`);
}
}
}).timeout(standardTimeoutTime);

test('InterpretExitCode returns user-friendly messages for common exit codes', () =>
{
// Test exit code 5 - insufficient permissions
const exitCode5Message = WinMacGlobalInstaller.InterpretExitCode('5');
assert.equal(exitCode5Message, 'Insufficient permissions are available to install .NET. Please run the installer as an administrator.');
assert.isFalse(exitCode5Message.includes('report'), 'Exit code 5 should not ask for bug reports');
assert.isTrue(WinMacGlobalInstaller.IsUserFriendlyExitCode('5'), 'Exit code 5 should be marked as user-friendly');

// Test exit code 1 - generic failure (should include report message)
const exitCode1Message = WinMacGlobalInstaller.InterpretExitCode('1');
assert.isTrue(exitCode1Message.includes('report'), 'Exit code 1 should ask for bug reports');

// Test unknown exit code
const unknownCodeMessage = WinMacGlobalInstaller.InterpretExitCode('9999');
assert.equal(unknownCodeMessage, '', 'Unknown exit codes should return empty string');
assert.isFalse(WinMacGlobalInstaller.IsUserFriendlyExitCode('9999'), 'Unknown exit codes should not be marked as user-friendly');
});
});