Comprobación de Service Pack de SQL 2008

Microsoft.SQLServer.2008.ServicePackVersion (UnitMonitorType)

Este tipo de monitor comprueba que el Service Pack actual es superior o igual que el valor especificado.

Element properties:

RunAsMicrosoft.SQLServer.SQLProbeAccount
AccessibilityInternal
Support Monitor RecalculateFalse

Member Modules:

ID Module Type TypeId RunAs 
DataSource DataSource System.CommandExecuterPropertyBagSource Default
BadFilter ConditionDetection System.ExpressionFilter Default
GoodFilter ConditionDetection System.ExpressionFilter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Intervalo (s)
GoodValueint$Config/GoodValue$Nivel mínimo de Service Pack para SQL Server 2008
GoodValueR2int$Config/GoodValueR2$Nivel mínimo de Service Pack para SQL Server 2008 R2

Source Code:

<UnitMonitorType ID="Microsoft.SQLServer.2008.ServicePackVersion" Accessibility="Internal" RunAs="SQL!Microsoft.SQLServer.SQLProbeAccount">
<MonitorTypeStates>
<MonitorTypeState ID="ValueGood"/>
<MonitorTypeState ID="ValueBad"/>
</MonitorTypeStates>
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ComputerName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SQLServiceName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="GoodValue" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="GoodValueR2" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" ParameterType="int" Selector="$Config/IntervalSeconds$"/>
<OverrideableParameter ID="GoodValue" ParameterType="int" Selector="$Config/GoodValue$"/>
<OverrideableParameter ID="GoodValueR2" ParameterType="int" Selector="$Config/GoodValueR2$"/>
</OverrideableParameters>
<MonitorImplementation>
<MemberModules>
<DataSource TypeID="System!System.CommandExecuterPropertyBagSource" ID="DataSource">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<ApplicationName>%windir%\system32\cscript.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>//nologo $File/DetectServicePackVersion.js$ "$Config/SQLServiceName$" "$Config/ComputerName$" $Config/GoodValue$ $Config/GoodValueR2$</CommandLine>
<TimeoutSeconds>600</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>DetectServicePackVersion.js</Name>
<Contents><Script>var SQL_WMI_NAMESPACE = "ComputerManagement10";//#Include File:Common.js

var DEBUG = false;
var ManagementGroupName = "$Target/ManagementGroup/Name$";
var ManagementGroupID = "$Target/ManagementGroup/Id$";

function EscapeConnStringValue(connStringValue) {
return '"' + connStringValue.replace(/"/g, '""') + '"';
}

function EscapeWQLString(wqlString) {
return wqlString.replace(/'/g, "\\'");
}

function BuildConnectionString(server, database) {
var dataSource = BuildServerName(server);
return "Data Source=" + EscapeConnStringValue(dataSource) + ";Initial Catalog=" + EscapeConnStringValue(database) + ";Integrated Security=SSPI";
}

function BuildConnectionStringWithPort(server, database, tcpPort) {

var dataSource = server;
if ((tcpPort != "") &amp;&amp; (tcpPort != "0")) {
dataSource = dataSource + "," + tcpPort;
}
return "Data Source=" + EscapeConnStringValue(dataSource) + ";Initial Catalog=" + EscapeConnStringValue(database) + ";Integrated Security=SSPI";
}

function ConcatinateServerName(server, tcpPort) {
var dataSource = server;
if ((tcpPort != "") &amp;&amp; (tcpPort != "0")) {
dataSource = dataSource + "," + tcpPort;
}
return dataSource;
}
function BuildServerName(strServer) {
var tcp = "";
var ip = "";
var pathArray = strServer.split("\\");
var instanceName = "MSSQLSERVER";
if (pathArray.length &gt; 1) {
instanceName = pathArray[1];
}

var serverName = strServer;

var oWMI = new WMIProvider("root\\Microsoft\\SqlServer\\" + SQL_WMI_NAMESPACE);
var oQuery = oWMI.ExecQuery("SELECT * FROM ServerNetworkProtocolProperty WHERE ProtocolName = 'Tcp' AND InstanceName = '" + EscapeWQLString(instanceName) + "' AND PropertyName = 'ListenOnAllIPs'");

if (oQuery.Count &gt; 0) {
var e = new Enumerator(oQuery);
e.moveFirst();
var isListenAll = e.item();
if (isListenAll.PropertyNumVal == 1) {
oQuery = oWMI.ExecQuery("SELECT * FROM ServerNetworkProtocolProperty WHERE ProtocolName = 'Tcp' AND InstanceName = '" + EscapeWQLString(instanceName) + "' AND IPAddressName = 'IPAll' AND (PropertyName = 'TcpPort' OR PropertyName = 'TcpDynamicPorts') AND PropertyStrVal != ''");
if (oQuery.Count &gt; 0) {
e = new Enumerator(oQuery);
e.moveFirst();
tcp = e.item().PropertyStrVal;
if ((tcp != "0") &amp;&amp; (tcp != "")) {
serverName = serverName + "," + tcp;
}
}
}
else {
oQuery = oWMI.ExecQuery("SELECT * FROM ServerNetworkProtocolProperty WHERE ProtocolName = 'Tcp' AND InstanceName = '" + EscapeWQLString(instanceName) + "' AND IPAddressName != '' AND PropertyName = 'Enabled' AND PropertyNumVal = 1");
if (oQuery.Count &gt; 0) {
var ipAddressName = oQuery.ItemIndex(0).IPAddressName;
oQuery = oWMI.ExecQuery("SELECT * FROM ServerNetworkProtocolProperty WHERE ProtocolName = 'Tcp' AND InstanceName = '" + EscapeWQLString(instanceName) + "' AND IPAddressName = '" + EscapeWQLString(ipAddressName) + "' AND (PropertyName = 'TcpPort' OR PropertyName = 'TcpDynamicPorts') AND PropertyStrVal != ''");
if (oQuery.Count &gt; 0) {
var e = new Enumerator(oQuery);
e.moveFirst();
tcp = e.item().PropertyStrVal;
}
oQuery = oWMI.ExecQuery("SELECT * FROM ServerNetworkProtocolProperty WHERE ProtocolName = 'Tcp' AND InstanceName = '" + EscapeWQLString(instanceName) + "' AND IPAddressName = '" + EscapeWQLString(ipAddressName) + "' AND PropertyName = 'IpAddress' AND PropertyStrVal != ''");
if (oQuery.Count &gt; 0) {
var e = new Enumerator(oQuery);
e.moveFirst();
ip = e.item().PropertyStrVal;
}
if (ip != "") {
serverName = ip;
}
if (tcp != "") {
serverName = serverName + "," + tcp;
}
}
}
}
return serverName;
}

function CheckConnectionTarget (dbConnection, serverName, instanceName) {
var destinationTestQuery = "select SERVERPROPERTY('MachineName') as ServerName, @@servicename as InstanceName";
var queryResult = dbConnection.ExecuteQuery(destinationTestQuery);
queryResult.MoveFirst();
if (!queryResult.EOF) {
var queryServerName = queryResult("ServerName").Value.toUpperCase();
var queryInstanceName = queryResult("InstanceName").Value.toUpperCase();
var serverNameWithoutDomain = serverName;
var dotPosition = serverName.indexOf(".");
if (dotPosition &gt; -1) {
serverNameWithoutDomain = serverName.substring(0, dotPosition);
}
if (serverNameWithoutDomain.toUpperCase() == queryServerName &amp;&amp; instanceName.toUpperCase() == queryInstanceName) {
return;
}
}
throw new Exception("Connection target check failed: connected to " + serverName + "\\" + instanceName + ", but got " + queryServerName + "\\" + queryInstanceName + ".");
};

function SmartConnect (serverName, databaseName, tcpPort, machineName, instanceName) {
var dbMasterConnection;
var connectionString;
//try to use SQL server browser
connectionString = BuildConnectionStringWithPort(serverName, databaseName, "");
try {
dbMasterConnection = new ADODB(connectionString, "sqloledb", 10);
CheckConnectionTarget(dbMasterConnection, machineName, instanceName);
} catch (e) {
//use original tcp port and try to connect again
connectionString = BuildConnectionStringWithPort(serverName, databaseName, tcpPort);
try {
dbMasterConnection = new ADODB(connectionString, "sqloledb", 10);
CheckConnectionTarget(dbMasterConnection, machineName, instanceName);
} catch (eInt) {
//get fresh tcp port and try to connect again
connectionString = BuildConnectionString(serverName, databaseName);
dbMasterConnection = new ADODB(connectionString, "sqloledb", 30);
CheckConnectionTarget(dbMasterConnection, machineName, instanceName);
}
}
return dbMasterConnection;
};

Function.prototype.setAlias = function (name) {
this.getAlias = function () {
return name;
};
};
Error.prototype.toString = function () {
if (this.message) {
var parts = [];
parts.push(this.message);
parts.push('\n');

if (this.number) {
parts.push("Error Number : ");
parts.push(this.number);
parts.push('\n');
parts.push("Error Code : ");
parts.push(this.number &amp; 0xFFFF);
parts.push('\n');
parts.push("Win32 Facility : ");
parts.push((this.number &gt;&gt; 16 &amp; 0x1FFF));
parts.push('\n');
}
if (this.description) {
parts.push("Error Description : ");
parts.push(this.description);
}
parts.push('\n');
return parts.join('');
}
else {
return this.toString();
}
};
var Exception = function (message, innerException) {
arguments.callee.setAlias('Exception.constructor');
this.message = message;
this.innerException = innerException;

var parts = [];
var collectArguments = function (caller) {
parts.push('(');
for (var i = 0; i &lt; caller.length; i++) {
if (typeof (caller[i]) != 'undefined') {
parts.push(caller[i] === null ? 'null' : (typeof (caller[i].toString) === 'undefined' ? 'object' : caller[i].toString()));
parts.push(',');
}
}
parts.pop();
parts.push(')');
parts.push(',\n');
};
var collectCallStack = function (caller) {
arguments.callee.setAlias('Exception.collectCallStack');
parts.push(caller.callee.getAlias ? caller.callee.getAlias() : 'anonymous');
collectArguments(caller);
var nextCaller = caller.caller;
if (nextCaller)
collectCallStack(nextCaller);
};
collectCallStack(arguments);
this.callStack = parts.join('');

this.toString = function () {
arguments.callee.setAlias('Exception.toStringFull');
var parts = [];
parts.push(this.message);
parts.push('\n');
if (this.innerException) {

parts.push('Inner exception: \n');
parts.push("Error Number : ");
parts.push(this.innerException.number);
parts.push('\n');
parts.push("Error Code : ");
parts.push(this.innerException.number &amp; 0xFFFF);
parts.push('\n');
parts.push("Win32 Facility : ");
parts.push((this.innerException.number &gt;&gt; 16 &amp; 0x1FFF));
parts.push('\n');
parts.push("Error Description : ");
parts.push(this.innerException.description);
parts.push('\n');
}
parts.push('Call stack:');
parts.push(this.callStack);
return parts.join('');;
};
};
var OpsMgrAPI = function () {
arguments.callee.setAlias('MOMAPI.constructor');
var scriptAPI;
try {
scriptAPI = new ActiveXObject('MOM.ScriptAPI');
}
catch (e) {
throw new Exception("Application cannot create MOM.ScriptAPI ActiveX object.", e);
}
this.ScriptAPI = scriptAPI;
};
var MessageType = {
Error: 1,
Warning: 2,
Information: 4
};
var Logger = function () {
arguments.callee.setAlias('Logger.constructor');
var opsMgrAPI = new OpsMgrAPI();

this.LogError = function (eventId, message) {
arguments.callee.setAlias('Logger.LogError');
opsMgrAPI.ScriptAPI.LogScriptEvent("Management Group: " + ManagementGroupName + ". Script: " + WScript.ScriptName, eventId, MessageType.Error, message);
};
this.LogError2 = function (instanceName, eventId, message) {
arguments.callee.setAlias('Logger.LogError2');
opsMgrAPI.ScriptAPI.LogScriptEvent("Management Group: " + ManagementGroupName + ". Script: " + WScript.ScriptName + ". Instance: " + instanceName, eventId, MessageType.Error, message);
};
this.LogWarning = function (eventId, message) {
arguments.callee.setAlias('Logger.LogWarning');
opsMgrAPI.ScriptAPI.LogScriptEvent("Management Group: " + ManagementGroupName + ". Script: " + WScript.ScriptName, eventId, MessageType.Warning, message);
};
this.LogInformation = function (eventId, message) {
arguments.callee.setAlias('Logger.LogInformation');
opsMgrAPI.ScriptAPI.LogScriptEvent("Management Group: " + ManagementGroupName + ". Script: " + WScript.ScriptName, eventId, MessageType.Information, message);
};
this.LogDebug = function (eventId, message) {
if (DEBUG) {
arguments.callee.setAlias('Logger.LogDebug');
opsMgrAPI.ScriptAPI.LogScriptEvent("Management Group: " + ManagementGroupName + ". Script: " + WScript.ScriptName, eventId, MessageType.Information, message);
}
};
this.LogCustomInfo = function (param1, eventId, message) {
arguments.callee.setAlias('Logger.LogCustomInfo');
opsMgrAPI.ScriptAPI.LogScriptEvent(param1, eventId, MessageType.Information, message);
};
};
var ADODB = function (connectionString, provider, connectionTimeout) {
arguments.callee.setAlias('ADODB.constructor');
if (!connectionString)
throw new Exception("Connection string cannot be null or empty string");
this.provider = provider ? provider : "sqloledb";
this.connectionTimeout = connectionTimeout ? connectionTimeout : 30;

var connection;
try {
connection = new ActiveXObject("ADODB.Connection");
}
catch (e) {
throw new Exception("Can't create ActiveXObject 'ADODB.Connection'", e);
}

connection.Provider = this.provider;
connection.ConnectionTimeout = this.connectionTimeout;
connection.ConnectionString = connectionString;
try {
connection.Open();
}
catch (e) {
throw new Exception("Can't connect to SQL Server. Connection string : '" + connectionString + "'", e);
}

this.ExecuteQuery = function (query) {
arguments.callee.setAlias('ADODB.ExecuteQuery');
var dbSet;
try {
dbSet = connection.Execute(query);
}
catch (e) {
throw new Exception("Can't execute query '" + query + "'", e);
}
return dbSet;
};
this.Close = function () {
arguments.callee.setAlias('ADODB.Close');
try {
if (connection) {
connection.Close();
}
}
catch (e) {
throw new Exception("Can't close connection.", e);
}
};
};
var Registry = function () {
arguments.callee.setAlias('Registry.constructor');
var registry;
try {
registry = new ActiveXObject("WScript.Shell");
}
catch (e) {
throw new Exception("Can't create ActiveXObject 'WScript.Shell'", e);
}

this.Write = function (key, value, type) {
arguments.callee.setAlias('Registry.Write');
try {
if (type) {
registry.RegWrite(key, value, type);
}
else {
registry.RegWrite(key, value);
}
}
catch (e) {
throw new Exception("Can't write value '" + value.toString() + "' by registry key '" + key.toString() + "'.", e);
}
};
this.Read = function (key) {
arguments.callee.setAlias('Registry.Read');
var value;
try {
value = registry.RegRead(key);
}
catch (e) {
throw new Exception("Can't read value from registry key '" + key.toString() + "'.", e);
}
return value;
};
this.IsKeyExists = function (key) {
arguments.callee.setAlias('Registry.IsKeyExists');
var result = false;
try {
value = registry.RegRead(key);
result = true;
}
catch (e) {
result = false;
}
return result;
};
this.Delete = function (key) {
arguments.callee.setAlias('Registry.Delete');
var value;
try {
value = registry.RegDelete(key);
}
catch (e) {
throw new Exception("Can't delete registry key '" + key.toString() + "'.", e);
}
return value;
};
};
var WMIProvider = function (wmiNamespace, computerName) {
arguments.callee.setAlias('WMIProvider.constructor');
this.wmiNamespace = wmiNamespace;
this.computerName = (!computerName) ? computerName : ".";
var SWbemLocator;
try {
SWbemLocator = new ActiveXObject("WbemScripting.SWbemLocator");
}
catch (e) {
throw new Exception("Cannot create 'WbemScripting.SWbemLocator' object.", e);
}
this.SWbemLocator = SWbemLocator;

var wmiService;
try {
wmiService = this.SWbemLocator.ConnectServer(this.computerName, this.wmiNamespace);
}
catch (e) {
throw new Exception("Cannot connect to WMI of computer '" + this.computerName + "' by namespace '" + this.wmiNamespace + "'.", e);
}
this.WMIService = wmiService;

this.ExecQuery = function (query) {
arguments.callee.setAlias('WMIProvider.ExecQuery');
var result = null;
try {
result = this.WMIService.ExecQuery(query, "WQL", 0x0);
}
catch (e) {
throw new Exception("Cannot execute WMI query '" + query + "'.", e);
}
return result;
};
};
//#Include File:DetectServicePackVersion.js

function SQL2008Helper(computerName, service) {
arguments.callee.setAlias('SQL2008Helper');

var serviceName = service;

var wmiProvider = new WMIProvider("root\\Microsoft\\SQLServer\\ComputerManagement10", computerName);

var escape = function escape(str) {
arguments.callee.setAlias('escape');

return str.replace("\\", "\\\\").replace("'", "\\'");
}

var getVersion = function getVersion() {
arguments.callee.setAlias('getVersion');

var result = wmiProvider.ExecQuery("SELECT PropertyStrValue FROM SQLServiceAdvancedProperty WHERE ServiceName = '" + escape(serviceName) + "' AND PropertyName = 'VERSION'");
if (result.Count &gt; 0) {
// return result.ItemIndex(0).PropertyStrValue; // This code doesn't work in Windows 2003 or less

var e = new Enumerator(result);
e.moveFirst();
return e.item().PropertyStrValue;
} else {
throw new Exception("Can't get SQLServiceAdvancedProperty.VERSION property from WMI.");
}
}

var getServicePack = function getServicePack() {
arguments.callee.setAlias('getServicePack');

var result = wmiProvider.ExecQuery("SELECT PropertyNumValue FROM SQLServiceAdvancedProperty WHERE ServiceName = '" + escape(serviceName) + "' AND PropertyName = 'SPLEVEL'");
if (result.Count &gt; 0) {
// return parseInt(result.ItemIndex(0).PropertyNumValue); // This code doesn't work in Windows 2003 or less

var e = new Enumerator(result);
e.moveFirst();
return parseInt(e.item().PropertyNumValue);
} else {
throw new Exception("Can't get SQLServiceAdvancedProperty.SPLEVEL property from WMI.");
}
}

var version = getVersion();
this.servicePack = getServicePack();

var getMajorAndMinorVersion = function getMajorAndMinorVersion() {
arguments.callee.setAlias('getMajorAndMinorVersion');

var match = /(\d+)\.(\d+)/.exec(version);
return {
major: parseInt(match[1]),
minor: parseInt(match[2])
}
}

this.isSQL2008 = function isSQL2008() {
arguments.callee.setAlias('isSQL2008');

var ver = getMajorAndMinorVersion();
return ver.major == 10 &amp;&amp; (ver.minor &gt;= 0 &amp;&amp; ver.minor &lt; 50);
}

this.isSQL2008R2 = function isSQL2008R2() {
arguments.callee.setAlias('isSQL2008R2');

var ver = getMajorAndMinorVersion();
return ver.major == 10 &amp;&amp; ver.minor &gt;= 50;
}
}

function needSQLServerUpgrade(computerName, serviceName, minimalServicePackLevelSQL2008, minimalServicePackLevelSQL2008R2) {
arguments.callee.setAlias('needSQLServerUpgrade');

var sqlHelper = new SQL2008Helper(computerName, serviceName);

if (sqlHelper.isSQL2008()) {
return sqlHelper.servicePack &lt; minimalServicePackLevelSQL2008;
} else if (sqlHelper.isSQL2008R2()) {
return sqlHelper.servicePack &lt; minimalServicePackLevelSQL2008R2;
} else {
throw new Exception("Unknown SQL Server version. Expected SQL Server 2008 or SQL Server 2008 R2.");
}
}

function main(computerName, serviceName, minimalServicePackLevelSQL2008, minimalServicePackLevelSQL2008R2) {
arguments.callee.setAlias('main');

var opsMgrAPI = new OpsMgrAPI();

var propertyBag = opsMgrAPI.ScriptAPI.CreatePropertyBag();

var needUpgrade = needSQLServerUpgrade(computerName, serviceName, minimalServicePackLevelSQL2008, minimalServicePackLevelSQL2008R2) ? "1" : "0";
propertyBag.AddValue("NeedUpgrade", needUpgrade);

opsMgrAPI.ScriptAPI.Return(propertyBag);
}

function returnStub() {
arguments.callee.setAlias('returnStub');

var opsMgrAPI = new OpsMgrAPI();
var propertyBag = opsMgrAPI.ScriptAPI.CreatePropertyBag();
propertyBag.AddValue("NeedUpgrade", "");
opsMgrAPI.ScriptAPI.Return(propertyBag);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
var MAX_SP_LEVEL = 9;
var PARAMETER_CHECK_FAILED_EVENT_ID = 4002;


var args = WScript.Arguments;

var serviceName = args(0);
var computerName = args(1);
var minimalServicePackLevelSQL2008 = parseInt(args(2));
var minimalServicePackLevelSQL2008R2 = parseInt(args(3));

var logger = new Logger();

if (minimalServicePackLevelSQL2008 &lt; 0 || minimalServicePackLevelSQL2008 &gt; MAX_SP_LEVEL)
{
logger.LogError(PARAMETER_CHECK_FAILED_EVENT_ID, "GoodValue parameter must be non-negative and less than " + (MAX_SP_LEVEL + 1));
WScript.Quit();
}

if (minimalServicePackLevelSQL2008R2 &lt; 0 || minimalServicePackLevelSQL2008R2 &gt; MAX_SP_LEVEL)
{
logger.LogError(PARAMETER_CHECK_FAILED_EVENT_ID, "GoodValueR2 parameter must be non-negative and less than " + (MAX_SP_LEVEL + 1));
WScript.Quit();
}

try {
main(computerName, serviceName, minimalServicePackLevelSQL2008, minimalServicePackLevelSQL2008R2);
}
catch (e) {
logger.LogError(4001, e.toString());
returnStub();
}
</Script></Contents>
<Unicode>1</Unicode>
</File>
</Files>
</DataSource>
<ConditionDetection TypeID="System!System.ExpressionFilter" ID="GoodFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Integer">Property[@Name='NeedUpgrade']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Integer">0</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
<ConditionDetection TypeID="System!System.ExpressionFilter" ID="BadFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Integer">Property[@Name='NeedUpgrade']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Integer">1</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<RegularDetections>
<RegularDetection MonitorTypeStateID="ValueGood">
<Node ID="GoodFilter">
<Node ID="DataSource"/>
</Node>
</RegularDetection>
<RegularDetection MonitorTypeStateID="ValueBad">
<Node ID="BadFilter">
<Node ID="DataSource"/>
</Node>
</RegularDetection>
</RegularDetections>
</MonitorImplementation>
</UnitMonitorType>