Archived
Bundle SsmsMin directly into extension (#5450)
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
||||
"version": "15.0.18120.0",
|
||||
"downloadFileNames": {
|
||||
"Windows_64": "SsmsMin-15.0.18120.0-win-x64.zip",
|
||||
"Windows_86": "SsmsMin-15.0.18120.0-win-x86.zip"
|
||||
},
|
||||
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
||||
"executableFiles": [
|
||||
"SsmsMin.exe"
|
||||
]
|
||||
}
|
||||
@@ -7,16 +7,13 @@ import * as nls from 'vscode-nls';
|
||||
import * as path from 'path';
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { IConfig, ServerProvider } from 'service-downloader';
|
||||
import { Telemetry } from './telemetry';
|
||||
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getConfiguration } from './utils';
|
||||
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes } from './utils';
|
||||
import { ChildProcess, exec } from 'child_process';
|
||||
|
||||
const baseConfig = require('./config.json');
|
||||
const localize = nls.loadMessageBundle();
|
||||
let exePath: string;
|
||||
let runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
|
||||
|
||||
const runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
|
||||
|
||||
interface SmoMapping {
|
||||
action: string;
|
||||
@@ -69,38 +66,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
||||
// This is for Windows-specific support so do nothing on other platforms
|
||||
if (process.platform === 'win32') {
|
||||
Telemetry.sendTelemetryEvent('startup/ExtensionActivated');
|
||||
|
||||
let config: IConfig = JSON.parse(JSON.stringify(baseConfig));
|
||||
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
|
||||
config.proxy = getConfiguration('http').get('proxy');
|
||||
config.strictSSL = getConfiguration('http').get('proxyStrictSSL') || true;
|
||||
|
||||
const serverdownloader = new ServerProvider(config);
|
||||
const installationStart = Date.now();
|
||||
|
||||
try {
|
||||
let downloadedExePath = await serverdownloader.getOrDownloadServer();
|
||||
const installationComplete = Date.now();
|
||||
|
||||
// Don't register the command if we couldn't find the EXE since it won't be able to do anything
|
||||
if (downloadedExePath) {
|
||||
exePath = downloadedExePath;
|
||||
} else {
|
||||
throw new Error('Could not find SsmsMin.exe after downloading');
|
||||
}
|
||||
|
||||
// Register the commands now that we have the exePath to run the tool with
|
||||
registerCommands(context);
|
||||
|
||||
Telemetry.sendTelemetryEvent('startup/ExtensionStarted', {
|
||||
installationTime: String(installationComplete - installationStart),
|
||||
beginningTimestamp: String(installationStart)
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
Telemetry.sendTelemetryEvent('startup/ExtensionInitializationFailed');
|
||||
console.error(`Error Initializing Admin Tool Extension for Windows - ${err}`);
|
||||
}
|
||||
exePath = path.join(context.extensionPath, 'ssmsmin', 'ssmsmin.exe');
|
||||
registerCommands(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,11 +137,6 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
|
||||
* @param urn The URN to pass to SsmsMin
|
||||
*/
|
||||
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
|
||||
if (!exePath) {
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noExeError', 'Unable to find SsmsMin.exe.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connectionContext.connectionProfile) {
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||
return;
|
||||
@@ -210,15 +172,15 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
return;
|
||||
}
|
||||
|
||||
let urn: string = await buildUrn(connectionContext.connectionProfile.serverName, oeNode);
|
||||
const urn: string = await buildUrn(connectionContext.connectionProfile.serverName, oeNode);
|
||||
let password: string = connectionContext.connectionProfile.password;
|
||||
|
||||
if (!password || password === '') {
|
||||
let creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id);
|
||||
const creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id);
|
||||
password = creds[azdata.ConnectionOptionSpecialType.password];
|
||||
}
|
||||
|
||||
let params: LaunchSsmsDialogParams = {
|
||||
const params: LaunchSsmsDialogParams = {
|
||||
action: action,
|
||||
server: connectionContext.connectionProfile.serverName,
|
||||
database: connectionContext.connectionProfile.databaseName,
|
||||
@@ -227,12 +189,11 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
urn: urn
|
||||
};
|
||||
|
||||
let args = buildSsmsMinCommandArgs(params);
|
||||
const args = buildSsmsMinCommandArgs(params);
|
||||
|
||||
Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
|
||||
|
||||
// This will be an async call since we pass in the callback
|
||||
let proc: ChildProcess = exec(
|
||||
const proc: ChildProcess = exec(
|
||||
/*command*/ `"${exePath}" ${args}`,
|
||||
/*options*/ undefined,
|
||||
(execException, stdout, stderr) => {
|
||||
@@ -288,7 +249,7 @@ export async function buildUrn(serverName: string, node: azdata.objectexplorer.O
|
||||
}
|
||||
else if (node.metadata && node.nodeType !== 'Folder') {
|
||||
// SFC URN expects Name and Schema to be separate properties
|
||||
let urnSegment = node.metadata.schema && node.metadata.schema !== '' ?
|
||||
const urnSegment = node.metadata.schema && node.metadata.schema !== '' ?
|
||||
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}' and @Schema='${doubleEscapeSingleQuotes(node.metadata.schema)}']` :
|
||||
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}']`;
|
||||
urnNodes = [urnSegment].concat(urnNodes);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
'use strict';
|
||||
import * as vscode from 'vscode';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import { PlatformInformation } from 'service-downloader/out/platform';
|
||||
|
||||
import * as Utils from './utils';
|
||||
|
||||
@@ -37,23 +36,8 @@ export function filterErrorPath(line: string): string {
|
||||
|
||||
export class Telemetry {
|
||||
private static reporter: TelemetryReporter;
|
||||
private static userId: string;
|
||||
private static platformInformation: PlatformInformation;
|
||||
private static disabled: boolean;
|
||||
|
||||
public static getPlatformInformation(): Promise<PlatformInformation> {
|
||||
if (this.platformInformation) {
|
||||
return Promise.resolve(this.platformInformation);
|
||||
} else {
|
||||
return new Promise<PlatformInformation>(resolve => {
|
||||
PlatformInformation.getCurrent().then(info => {
|
||||
this.platformInformation = info;
|
||||
resolve(this.platformInformation);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable telemetry reporting
|
||||
*/
|
||||
@@ -122,13 +106,7 @@ export class Telemetry {
|
||||
properties = {};
|
||||
}
|
||||
|
||||
// Augment the properties structure with additional common properties before sending
|
||||
Promise.all([this.getPlatformInformation()]).then(() => {
|
||||
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
||||
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
||||
|
||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||
});
|
||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
@@ -22,25 +20,6 @@ export function getPackageInfo(packageJson: any): IPackageInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration for a extensionName
|
||||
* @param extensionName The string name of the extension to get the configuration for
|
||||
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
||||
*/
|
||||
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
||||
if (typeof resource === 'string') {
|
||||
try {
|
||||
resource = this.parseUri(resource);
|
||||
} catch (e) {
|
||||
resource = undefined;
|
||||
}
|
||||
} else if (!resource) {
|
||||
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
|
||||
resource = null;
|
||||
}
|
||||
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes all single-quotes (') by prefixing them with another single quote ('')
|
||||
* ' => ''
|
||||
|
||||
Reference in New Issue
Block a user