Welcome to MSDN Blogs Sign in | Join | Help

There are a couple of known issues with Windows Server 2003 SP1 that affect SMS 2003 that were resolved in SP2 for Windows 2003 that SMS admins should know about:

  • The first issue that is pretty well known is an issue where the SMS Services crash immediately after starting up - this issue is documented here
  • A customer upgrading to SP3 for SMS recently reported another issue which I was able to confrim as well.  During a site reset (which can be kicked off manually, is automatically kicked off by service pack install, and may be kicked off by applying SMS hotfixes) memory use of the executive climbes dramatically, and depending on how many packages and/or BITS-enabled DPs can actually crash the SMS_Executive service.  Unfortunately once this happens the service will start over and crash again without intervention.  This appears to be caused by a problem in the IIS provider with ADSI and fortunately is not an issue after applying Windows 2003 SP2.  I should note there are several hotfixes available for the IIS provider for ADSI SP1 that are for similar scenarios but as of this posting none of them appear to address the specific problem encountered with SMS and it's management of BITS-enabled DPs.

For custom inventory classes there is delgrp, but for custom attributes that were added to the discovery tables via DDR there isn't a tool out there.  Here is a sample stored procedure that should do the trick - as always when directly editing the database be sure to make a backup before hand. Before running queries or procedures like this that modify the discovery tables be sure to shut down the SMS services on the site server, close any open admin UI instances, and shut down WMI on the provider server.

So, for example to remove a property named "SomePropertyName" from the System discovery class:

sp_RemoveDiscoveryProperty 'SomePropertyName', 'System'

SET QUOTED_IDENTIFIER OFF

IF OBJECT_ID ( 'sp_RemoveDiscoveryProperty', 'P' ) IS NOT NULL
DROP PROCEDURE sp_RemoveDiscoveryProperty;
GO
CREATE PROCEDURE sp_RemoveDiscoveryProperty
@propName varchar(255),
@discArchName varchar(255)
AS
BEGIN
DECLARE @columnName varchar(255)
DECLARE @archBase varchar(255)
DECLARE @discArchKey int

select @archBase = BaseTableName, @discArchKey = DiscArchKey from DiscoveryArchitectures where DiscArchName = @discArchName
IF @archBase = NULL
BEGIN
PRINT "Architecture '" + @discArchName + "' not found, aborting..."
RETURN (-1)
END
select @columnName = ColumnName from DiscPropertyDefs where DiscArchKey = @discArchKey and PropertyName = @propName

IF @columnName = NULL
BEGIN
PRINT "The property '" + @propName + "' was not found in the DiscPropertyDefs table, aborting..."
RETURN (-1)
END

PRINT "Removing property '" + @propName + "' from the DiscPropertyDefs table."
delete DiscPropertyDefs where DiscArchKey = @discArchKey and ColumnName = @columnName

PRINT "Removing column '" + @columnName + "' from the '" + @archBase + "' table."
EXECUTE ("alter table " + @archBase + " DROP COLUMN " + @columnName)

PRINT "Recreating the resource view for architecture '" + @discArchName + "'"
EXEC sp_CreateResourceView @discArchKey
END

 

So you have created an application or script that requires a policy evaluation before it can continue, how can you tell that the policy evaluation request has completed? 

Fortunately there are events provided via WMI that can tell you when policy evalution is complete.  Thats how the Policy Spy tool from the SMS 2003 Toolkit events tab works.

To illustrate with wbemtest:

  • On a test client, open wbemtest, connect to the root\ccm\events namespace.
  • choose "Notification Query" button
  • use this query: "SELECT * FROM CCM_PolicyAgent_Event"
  • while the dialog with the query results is running go to the control panel applet
    and refresh policy.
  • wait a few minutes for the query results to come in as the events are generated.

Check here for an example of how to do subscribe to WMI event notifications with VBScript.

When adding history with a response in MOM 2005 if you set up the response to run after duplicate alert suppression the update to the alert is lost.  This is because the alert instance is stored to the database during duplicate alert suppression and any subsequent changes made to the instance are abandoned.

It is possible to workaround this limitation with a managed code response, by retrieving and editing the alert instance that was stored during alert suppression, here is a sample:


using System;
using System.Collections.Generic;
using System.Text;

// Include namespaces for MOM SDK
using Microsoft.EnterpriseManagement.Mom;
using Microsoft.EnterpriseManagement.Mom.Runtime;

// This sample shows how to use a Managed code response to add history to an alert
// after duplicate suppression has taken place (the alert is committed to the database)
// ====================================================================================

namespace Sample
{
    public class SampleClass
    {
        public static void ManagedResponseEntry(Context currentContext)
        {
            // Get the alert we want to modify from the response context
            // =========================================================
            Guid alertId = currentContext.Alert.Id;

            // Get the same alert via SDK
            // ==========================
            Alert alertInstance = findAlert(alertId);
            if (alertInstance != null)
            {
                AddToHistory(alertInstance, "The quick brown fox jumped over the lazy dog's back");
            }            
        }

        public static void AddToHistory(Alert alertInstance, string textToAdd)
        {
            if(!string.IsNullOrEmpty(textToAdd))
            {
                alertInstance.AddAlertHistoryComment(textToAdd);
                alertInstance.Update();
            }            
        }

        public static Alert findAlert(Guid alertId)
        {            
            // Connect
            // =======
            Administration mom = Administration.GetAdministrationObject();
            if (mom != null)
            {
                // Retrieve alert
                // ==========================================================
                AlertQuery aq = mom.GetAlertQueryObject();
                
                // Create a query expression to only retrieve the alert we
                // want to update.
                // ========================================================
                AlertQueryExpression alertQueryExpression = new AlertQueryExpression();
                
                alertQueryExpression.ExpressionOperator = QueryExpression.ExpressionOperatorType.Equals;
                alertQueryExpression.LeftExpression = new AlertColumnNameExpression(AlertColumnNameExpression.ColumnName.Id);
                alertQueryExpression.RightExpression = new ValueExpression(alertId.ToString());
                
                AlertsCollection ac = aq.GetAlerts(alertQueryExpression);

                // Find alert with matching GUID
                // =============================
                foreach (Alert alert in ac)
                {
                    if (alert.Id == alertId)
                    {
                        return alert;
                    }
                }
            }

            // No matching alert was found!
            // ============================
            return null;
        }
    }
}
Code using the approach illustrated in the above sample could be in a MCR, or put in EXE form for use from other response types.
 
Page view tracker