Configuration Manager 1602 – Hotfix KB3155482

Hi Readers,

One of my customer upgraded their SCCM environment to version 1602.When done, in the SCCM console, a new update, KB3155482, showed up. image

I just did a right click right on it, and select Run Prerequisite Check.image

The problem is that nothing was progressing… After several hours, the sate of this update was still Checking Prerequisites. In the CCMUpdate.log file, nothing really interesting.image

How to force the system to execute this prerequisites check ? Go to SCCMInstallationFolder\Inboxes\hman.box and you will see the existence of a file named 2.ESC.image

Cut this file and paste it the folder SCCMInstallationFolder\Inboxes\hman.box\CFDimage

After a few seconds, you will see that this file will be removed.image

Wait about 15 min and go back to the SCCM Console. You will see now that the status changed to Prerequisite check passed.image

You could now do a right click and choose Install Update Pack.image

After about 15min, you will see a lot of activities in the CCMUpdate.log file, the installation of this KB is in fact in progress.image

At the end of the process, the system will request you to update the console.image

When done, you could see that this KB3155482 has been successfully installed.image

I hope this help Smile

Christopher

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Email this to someoneShare on TumblrPin on PinterestDigg thisShare on RedditFlattr the authorBuffer this pageShare on StumbleUpon
Posted in Configuration Manager | Leave a comment

AzureStack : How to create my first Market Place Item

Today we will focus on how to create our first Market Place Item for AzureStack.
The Microsoft Official documentation is available here: https://azure.microsoft.com/en-us/documentation/articles/azure-stack-marketplace/

At the end of this post, you will be able to download a working example.

1. Create a new ARM template or pick one from Github (https://github.com/Azure/AzureStack-QuickStart-Templates) In this guide, I will use the following ARM Template: https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/101-simple-windows-vm/azuredeploy.json

2. Test the template in your Microsoft Azure Stack infrastructure to ensure that the resource can be deployed successfully.

3. Create a working folder (Example: C:\MyMarketPlaceItem).

4. In your working folder, save your template into a text file with the .json extension.clip_image002

5. Create a new empty file named manifest.json, copy/paste the following content and save it to your working folder.

{
    "$schema": "https://gallery.azure.com/schemas/2014-09-01/manifest.json#",
    "name": "MyMarketPlaceItem", // [A-Za-z0-9]+
    "publisher": "vNextLab", // [A-Za-z0-9]+
    "version": "1.0.1", // SemVer v2 Format - see http://semver.org/
    "displayName": "My first Market Place Item", // max of 256 characters / recommendation 80 characters
    "publisherDisplayName": "vNextLab", // max of 256 characters  / recommendation 30 characters
    "publisherLegalName": "VNEXT SPRL", // max of 256 characters 
    "summary": "this is my first market place itemthis is my first market item, this is my first market item", // 60 to 100 characters -->
    "longSummary": "Long Summary of my first market place itemLong Summary of my first market place itemLong Summary of my first market place itemLong Summary of my first market place item", // 140 to 256 characters
    "description": "Description of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place itemDescription of my first market place item", // 5000 to 50000 characters. Can contain HTML
    "properties": [
        /* optional. max of 10 properties
           displayName: max of 64 characters
           value: max of 64 characters */
        { "displayName": "Properties 1", "value": "Value1" }
    ],
    "uiDefinition": {
        "path": "UIDefinition.json" // required, path to file
    },
    "artifacts": [
        // you probably want an artifact, because this is where the link to your ARM deployment template goes!
        /* name: max of 256 characters, [A-Za-z0-9\-_]+
           type: Fragment, Template
           path: path to artifact
           isDefault: true|false */
      {
        "name": "AzureDeploy101VM",
        "type": "Template",
        "path": "azuredeploy.json",
        "isDefault": true } 
    ],
  "icons": {
    "small": "Images\\Small.png", // 40x40
    "medium": "Images\\Medium.png", // 90x90
    "large": "Images\\Large.png", // 115x115
    "wide": "Images\\Wide.png", // 255x115 Not supported in Azure Stack UI
    "hero": "Images\\hero.png" // 815x290 Not supported in Azure Stack UI
  },
    "links": [
        /* optional, but highly recommended, max of 10 links
           displayName: max of 64 characters
           uri: uri */
        { "displayName": "vNextLab", "uri": "http://www.vnext.be" }
    ],
    "screenshots": [ "Images\\Screenshot1.png" ], // 533x324
    "categories": [ "Compute" ] // Compute, Data + Storage,...
}

 

6. Modify the content to match with your package information.

7. Create a new empty file named UIDefinition.json, copy/paste the following content and save it into your working folder.

{
    "$schema": "https://gallery.azure.com/schemas/2015-02-12/UIDefinition.json#",
    "createDefinition": {
        "createBlade": {
            "name": "DeployFromTemplateBlade",
            "extension": "HubsExtension"
        }
    }
}

 

8. You have now 3 .json files in your working folder.clip_image004

9. In this folder, create a new folder named Images and created the 6 following images files.

NAME

WIDTH

HEIGHT

NOTES

Hero

815px

290px

Not yet applicable in Azure Stack

Wide

255px

115px

Not yet applicable in Azure Stack

Large

115px

115px

Always required.

Medium

90px

90px

Always required.

Small

40px

40px

Always required.

Screenshot(s)

533px

324px

Optional.

10. Your images folder should be similar to this: The T in the middle of my image is for “Temporary”
clip_image006

11. Download the Azure Gallery Packaging Tool: http://www.aka.ms/azurestackmarketplaceitem

12. Extract the files
clip_image008

13. Copy the folder AzureGalleryPackageGenerator to your C:\ drive
clip_image010

14. Start a new Command Prompt as administrator, go to the folder AzureGalleryPackageGenerator and run the following command:
AzureGalleryPackager.exe package -m C:\MyMarketPlaceItem\manifest.json -o C:\MyMarketPlaceItem
clip_image012

15. Confirm that an AZPKG file has been created in your working folder.
clip_image014

16. Open PowerShell ISE and copy/paste the following script.

########################
#Parameters
########################
import-module  AzureRm.AzureStackAdmin #First install D:\Dependencies\azure-powershell.msi from the ClientVM

#Provide your Azure Active Direcoty Admin account
[net.mail.mailaddress]$AadFullMailAddress="mas@vnextlab.be"

#Path to the Azure package your created
$PackagePath = "C:\MyMarketPlaceItem\vNextLab.MyMarketPlaceItem.1.0.1.azpkg"

#The script will create a new Resource Group to store your Market Place Item
$resourceGroupName = "MarketPlaceItems"

########################
#Script
########################
#Extract the package Name
$PackageName = (Get-Item $PackagePath).Name -replace '.azpkg',''

#Get the Azure AD GUID (Credit Menno Stevens)
$AadTenantId=(Invoke-WebRequest -Uri ('https://login.windows.net/'+($AadFullMailAddress.Host)+'/.well-known/openid-configuration')|ConvertFrom-Json).token_endpoint.Split('/')[3]

#Connection with your MAS Service Admin Credentials
Add-AzureRmEnvironment -Name 'Azure Stack' `
    -ActiveDirectoryEndpoint ("https://login.windows.net/$AadTenantId/") `
    -ActiveDirectoryServiceEndpointResourceId "https://azurestack.local-api/" `
    -ResourceManagerEndpoint ("https://api.azurestack.local/") `
    -GalleryEndpoint ("https://gallery.azurestack.local:30016/") `
    -GraphEndpoint "https://graph.windows.net/"
 
# Get Azure Stack Environment Information
$env = Get-AzureRmEnvironment 'Azure Stack'

# Authenticate to AAD with Azure Stack Environment
Add-AzureRmAccount -Environment $env -Verbose

# Get Azure Stack Environment Subscription
$Subscription = Get-AzureRmSubscription -SubscriptionName "Default Provider Subscription"  | Select-AzureRmSubscription
$SubscriptionID = $Subscription.Subscription.SubscriptionId

#Create the Resource Group
New-AzureRmResourceGroup -Name $resourceGroupName -Location local

#Adding the package to the Market Place
Add-AzureRMGalleryItem -SubscriptionId $SubscriptionID -ResourceGroup $resourceGroupName -Name $PackageName -Path $PackagePath  -Apiversion "2015-04-01" –Verbose

 

17. Modify the parameters to match with your package and MAS info.

18. Start Internet Explorer and add the following websites in the Trust Sites
*.microsoft.
*.microsoftonline.com
*.microsoftonline-p.com
clip_image016

19. Run the script in PowerShell ISE.

20. Provide your MAS Service Admin credentials when prompted and click on Sign In.
clip_image018

21. The script should give you the following output.
clip_image020

22. Connect to the MAS portal (As Service Admin or Tenant), go to New, Compute and you should see your new Market Place Item.
clip_image022

23. You could also browse the complete Market Place to see the details of your Package.
clip_image024

You could download the example here: https://www.vnext.be/wp-content/uploads/2016/02/MyMarketPlaceItem.zip

Cheers
Christopher

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Email this to someoneShare on TumblrPin on PinterestDigg thisShare on RedditFlattr the authorBuffer this pageShare on StumbleUpon
Posted in AzureStack | 1 Comment

#AzureStack: How to provide internet access to your Tenant VMs

Hi all,

As you are probably already aware, AzureStack went out to public preview last Friday. After you successfully deployed your first VM, you could start a RDP connection simply by clicking on the Connect button.image

When you are in your Tenant Virtual Machine, you could see that you don’t have internet access.image

The problem is coming from the DNS Resolution which doesn’t work.image

Go back to the AzureStack Portal, select the Resource group which your Virtual Machine is part of and click on the Virtual Network icon.image

In the Virtual Network blade, DNS Settings,you could see that the DNS Server are configured to Azure DNS Servers.image

Click on Custom DNS and set 192.168.100.2 as primary DNS Server. Click on save and restart your tenant Virtual Machines.image

I noticed that in some cases, this only works for newly created VMs in this existing Virtual Network and doesn’t work for the existing VMs. So the small trick for the existing VMs is to configure the DNS IP at the Network Card level.

To do this in the Virtual Network blade, under Connected Devices, select your server, click on DNS Server and there configure the DNS server IP address. Finally restart your Virtual Machine.image

So my advice will be to first configure the DNS Server settings, before creating your Virtual Machines

Christopher

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Email this to someoneShare on TumblrPin on PinterestDigg thisShare on RedditFlattr the authorBuffer this pageShare on StumbleUpon
Posted in AzureStack | Leave a comment

SCOM/OpsMgr: Databases Move / Failover PowerShell Script

It could happens that one day or another, you will have to move the Operations Manager (OperationsManager and OperationsManagerDW ) databases from one SQL instance to another one. The reason could be a SQL migration to another version of SQL or during a failover in case of a disaster recovery plan.

Microsoft published 2 TechNet Articles with all the steps that need to be performed when you have to move these two databases.
https://technet.microsoft.com/en-US/library/hh278848.aspx
https://technet.microsoft.com/en-US/library/hh268492.aspx

As you can see, there are a lot of manual actions like updating registry entries, SQL entries, SQL Reporting Datasources, Config File … that need to be done. Manual actions often means human errors and mistakes… and also, time consuming…

So to avoid all these problems, I decided to write a PowerShell that will take care of all these steps for us. The only prerequisites is to have already the 2 DBs restored to the new SQL instances and have the rights correctly assigned (like it was on the original SQL Instances).

Be really careful with this script, as it’s touching SQL, Registry, … it could easily break your SCOM infrastructure. Use it at your own risks and be sure to have a good backup before doing anything else.

you could download it from here: http://www.vnext.be/wp-content/uploads/2015/12/SCOMDBsFailOver.zip

<#

.Name: SCOMDBsFailOver.ps1
.Decription: Update SCOM registry/Databases records to point to the failover DBs 

.Version: 0.1
.Date: December 14th, 2015

.Author: Christopher.keyaert@inovativ.be

.Pre-requisites: Restore the OpsDB and DWDB DBS to the new SQL instances 
 and ensure that the security rights have been applied correctly

.MS TechNet Guide
https://technet.microsoft.com/en-US/library/hh278848.aspx
https://technet.microsoft.com/en-US/library/hh268492.aspx

#>

#Functions
Function GetSQLColumnName($OpsDBFailoverInstance,$OpsDBFailoverDB,$TableName,$ColumnNamePrefix)
    {
    $connectionString = "Server=$OpsDBFailoverInstance;Database=$OpsDBFailoverDB;Integrated Security=true;"
    $Fconnection = New-Object System.Data.SqlClient.SqlConnection
    $Fconnection.ConnectionString = $connectionString
    $Fconnection.Open()

    #Update the SQL Server Name for Application Performance
    $query = 'Select * from dbo.' + $TableName
    $command = $Fconnection.CreateCommand()
    $command.CommandText =  $query
    $result = $command.ExecuteReader()

    #Formating the Data
    $table = new-object "System.Data.DataTable"
    $table.Load($result)
    $result.close()

    $Fconnection.Close()

    $ColumnName = ($table | Get-Member | Where-Object {$_.Name -like "$ColumnNamePrefix*"}).Name

    Return $ColumnName
    }


#Parameters
$VerbosePreference = "Continue"
#$VerbosePreference = "SilentlyContinue"

$OpsDBFailoverInstance = 'SQL001\cloudos'
$OpsDBFailoverDB = 'OperationsManager'
$DWDBFailoverInstance = 'SQL001\cloudos'
$DWDBFailoverDB = 'OperationsManagerDW'

#Import the SCOM Module
Import-Module OperationsManager

$errorMessage = $null
Try {
    #Connection to SCOM Server
    $Connection = New-SCOMManagementGroupConnection -ComputerName "."
       
    }
catch{
     Write-Verbose $_
     exit
     }
     
Write-Verbose "Connected to SCOM MS"

#Get All SCOM MS and stopped the SCOM Services.
$RptURL = Get-SCOMReportingSetting | Select -ExpandProperty ReportingServerUrl
$SCOMMS = Get-SCOMManagementServer | where-object {$_.IsGateway -eq $false} | select DisplayName
$SCOMMS = $SCOMMS | % {$_.DisplayName}

################################
#Update the MS information
Write-Verbose "Stopping All SCOM Services + Registry update on All MS - Started"

Invoke-Command -ComputerName $SCOMMS -ScriptBlock {

   param($OpsDBFailoverDB,$OpsDBFailoverInstance,$DWDBFailoverDB,$DWDBFailoverInstance)

    #Stop the SCOM Service
    Get-Service HealthService,OMSDK,cshost | Stop-Service -PassThru | Set-Service -StartupType disabled
    
    #Update the registry keys - Part 1
    $registryPath = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup"
    
    #OpsDB Reg Keys
    New-ItemProperty -Path $registryPath -Name DatabaseName -Value $OpsDBFailoverDB -Force | Out-Null
    New-ItemProperty -Path $registryPath -Name DatabaseServerName -Value $OpsDBFailoverInstance -Force | Out-Null

    #DWDB Reg Keys
    New-ItemProperty -Path $registryPath -Name DataWarehouseDBName -Value $DWDBFailoverDB -Force | Out-Null
    New-ItemProperty -Path $registryPath -Name DataWarehouseDBServerName -Value $DWDBFailoverInstance -Force | Out-Null
    
    #Update the configuration File
    $setupKey = Get-Item -Path $registryPath
    $installDirectory = $setupKey.GetValue("InstallDirectory") 
    $ConfigurationFilePath = $installdirectory + 'ConfigService.config'

    #Backup the file
    Copy-Item $ConfigurationFilePath -Destination "$installdirectory\ConfigService.config.bkp" -Force
    
    #Update the value
    $xml = (Get-Content $ConfigurationFilePath)
    $xml.Config.Component.Instance.Category.Setting | where {$_.Name -eq 'ServerName'} | % {$_.value = $OpsDBFailoverInstance}
    $xml.Config.Component.Instance.Category.Setting | where {$_.Name -eq 'DatabaseName'} | % {$_.value = $OpsDBFailoverDB}
    $xml.Save($ConfigurationFilePath)


    #Update the registry keys - Part 2
    $registryPath = "HKLM:\SOFTWARE\Microsoft\System Center\2010\Common\Database"
   
    #OpsDB Reg Keys
    New-ItemProperty -Path $registryPath -Name DatabaseName -Value $OpsDBFailoverDB -Force | Out-Null
    New-ItemProperty -Path $registryPath -Name DatabaseServerName -Value $OpsDBFailoverInstance -Force | Out-Null

   
    } -ArgumentList $OpsDBFailoverDB,$OpsDBFailoverInstance,$DWDBFailoverDB,$DWDBFailoverInstance 

Write-Verbose "Stopping All SCOM Services + Registry update on All MS - Done"

################################
#Update the SQL DBs

Write-Verbose "Updating OpsDB Tables - Started"

#Initiate SQL Connection
$connectionString = "Server=$OpsDBFailoverInstance;Database=$OpsDBFailoverDB;Integrated Security=true;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()

#Update Table1
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$ManagementGroup' 'SQLServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$ManagementGroup' 'OperationalDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$ManagementGroup Set ' + "$ColumnName = '$OpsDBFailoverInstance'" + ", $ColumnName2 = '$OpsDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Update Table2
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$OpsMgrDB$AppMonitoring' 'MainDatabaseServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$OpsMgrDB$AppMonitoring' 'MainDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$OpsMgrDB$AppMonitoring Set ' + "$ColumnName = '$OpsDBFailoverInstance'" + ", $ColumnName2 = '$OpsDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()


#Clr Enalbed - Part1
$query = @'
sp_configure "show advanced options",1
reconfigure
'@

$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$result.close()

#Clr Enalbed - Part2
$query = @'
sp_configure 'clr enabled',1
reconfigure
'@
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$result.close()

#Enable SQL Broker
$query = @'
ALTER DATABASE OperationsManager SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE OperationsManager SET ENABLE_BROKER
ALTER DATABASE OperationsManager SET MULTI_USER
'@
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$result.close()

#Update DBName DW Info
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse' 'MainDatabaseServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse' 'MainDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$DataWarehouse Set ' + "$ColumnName = '$DWDBFailoverInstance'" + ", $ColumnName2 = '$DWDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Update App Monitoring DBName DW Info
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring' 'MainDatabaseServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring' 'MainDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring Set ' + "$ColumnName = '$DWDBFailoverInstance'" + ", $ColumnName2 = '$DWDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Update App Monitoring DBName DW Info
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring_Log' 'Post_MainDatabaseServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring_Log' 'Post_MainDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring_Log Set ' + "$ColumnName = '$DWDBFailoverInstance'" + ", $ColumnName2 = '$DWDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Update App Monitoring DBName DW Info
$ColumnName = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse_Log' 'Pre_MainDatabaseServerName_'
$ColumnName2 = GetSQLColumnName $OpsDBFailoverInstance $OpsDBFailoverDB 'MT_Microsoft$SystemCenter$DataWarehouse_Log' 'Pre_MainDatabaseName_'
$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MT_Microsoft$SystemCenter$DataWarehouse_Log Set ' + "$ColumnName = '$DWDBFailoverInstance'" + ", $ColumnName2 = '$DWDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Close the connection
$connection.Close()
Write-Verbose "Updating OpsDB Tables - Done"

################################
#Update the DW DB
Write-Verbose "Updating DWDB Tables - Started"

#Initiate SQL Connection
$connectionString = "Server=$DWDBFailoverInstance;Database=$DWDBFailoverDB;Integrated Security=true;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()

$command = $connection.CreateCommand()
$command.CommandText = 'Update dbo.MemberDatabase Set ' + "ServerName = '$DWDBFailoverInstance'" + ", DatabaseName = '$DWDBFailoverDB'"
$result = $command.ExecuteReader()
$result.close()

#Close the connection
$connection.Close()
Write-Verbose "Updating DWDB Tables - Done"

###############################
#Start All the SCOM Services
Write-Verbose "Starting All SCOM Services on All MS - Started"

Invoke-Command -ComputerName $SCOMMS -ScriptBlock {
    Get-Service HealthService,OMSDK,cshost | Set-Service -StartupType Automatic -PassThru | Start-Service 
    }

Write-Verbose "Starting All SCOM Services on All MS - Done"

################################
#Update the Reporting Server
Write-Verbose "Updating Reporting Server - Started"
Start-Sleep 10

$RptSrv = (($RptURL).split('/')[2]).split(':')[0]
$NewConnectionString =  "data source=$DWDBFailoverInstance;initial catalog=$DWDBFailoverDB;Integrated Security=SSPI"

$url = "$($RPTUrl)/reportservice2005.asmx?WSDL";
$ssrs = New-WebServiceProxy -uri $url -UseDefaultCredential

#Get the DataSource for the Reports and AppMonitoring 
$DSlist = $SSRS.ListChildren("/", $true) | Where-Object {$_.Type -eq "DataSource"}  

#Update the connectionString
Foreach($DS in $DSlist)  
 { 
  $Ref = $ssrs.GetDataSourceContents($DS.Path)
  $Ref.ConnectString = $NewConnectionString
  $ssrs.SetDataSourceContents($DS.Path,$ref)
 }

Invoke-Command -ComputerName $RptSrv -ScriptBlock {

   param($DWDBFailoverDB,$DWDBFailoverInstance)

   #Update the registry keys 
   $registryPath = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Reporting"
    
   #OpsDB Reg Keys
   New-ItemProperty -Path $registryPath -Name DWDBInstance -Value "$DWDBFailoverInstance" -Force | Out-Null
   New-ItemProperty -Path $registryPath -Name DWDBName -Value "$DWDBFailoverDB" -Force | Out-Null

   } -ArgumentList $DWDBFailoverDB,$DWDBFailoverInstance 

Write-Verbose "Updating Reporting Server - Done"


 

Cheers
Christopher

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Email this to someoneShare on TumblrPin on PinterestDigg thisShare on RedditFlattr the authorBuffer this pageShare on StumbleUpon
Posted in Operations Manager | Leave a comment

SCOM Agent–OS Recommended Hotfix (KB)

Hi Readers,

To ensure that the SCOM agent is performing well on all supported Windows OS, some time ago Microsoft released the following article:

System Center 2012 Operations Manager: recommended agent operating system fixes and updates https://support.microsoft.com/en-us/kb/2843219

Kevin Holman, a well known Microsoft SCOM Guru, is also maintaining his own list of OS Recommended Hotfix for the SCOM Agent. http://blogs.technet.com/b/kevinholman/archive/2009/01/27/which-hotfixes-should-i-apply.aspx

A few days ago, I saw a tweet from Reidar Johansen who just wrote a PowerShell script to check if all the OS Recommended Hotfix were installed on a given server. https://github.com/reijoh/scomscripts/blob/master/Check-RecommendedHotfixes.ps1

When I see that, I decided to re-use and add a few updates to his script :

  • Add all the KB from Microsoft Page
  • Add all the KB from Kevin Holman
  • Use Arrays to specify the required KBs per OS
  • Few minors optimization

My updated version of Johansen’s script is available below:

<#
Original Script: https://github.com/reijoh/scomscripts/blob/master/Check-RecommendedHotfixes.ps1

Modified by Christopher Keyaert (christopher@vnext.be)
Date: December 11th, 2015

Based on the KB list available https://support.microsoft.com/en-us/kb/2843219
Based on the KB list available http://blogs.technet.com/b/kevinholman/archive/2009/01/27/which-hotfixes-should-i-apply.aspx
#>

Function Check-HotfixInstalled
{
    param
    (
        [string]$HotfixID,
        [string]$ComputerName
    )
    $HF = $null
    $HF = Get-HotFix -ComputerName $ComputerName -ErrorAction SilentlyContinue -id $HotfixID
    If(!($HF))
    {
        $global:Description += "$ComputerName needs hotfix $HotfixID `r`n"
        $global:UpToDate = $False
    }
}


Function Check-ServicePackInstalled
{
    param
    (
        [string]$BuildNumber,
        [string]$Version,
        [string]$ComputerName
    )
    $CSDBuildNumber = Invoke-Command -ComputerName $ComputerName -ErrorAction SilentlyContinue -ScriptBlock {(Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue | select @{N='CSDBuildNumber'; E={$_.CSDBuildNumber}}).CSDBuildNumber}
    $CSDVersion = Invoke-Command -ComputerName $ComputerName -ErrorAction SilentlyContinue -ScriptBlock {(Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue | select @{N='CSDVersion'; E={$_.CSDVersion}}).CSDVersion}
    If($CSDBuildNumber -lt $BuildNumber -or $CSDVersion -lt $Version)
    {
        $global:Description += "$ComputerName needs $Version `r`n"
        $global:UpToDate = $False
    }
}


#Global Variables
$global:UpToDate = $True
$global:Description = $null

$ComputerName=$env:COMPUTERNAME

#KB Per OS and Role
$KB2003 = "KB955360", "KB981263", "KB933061", "KB968760", "KB982168", "KB980773" , "KB982167", "KB960718", "KB932370", "KB2484832" 
$KB2008 = "KB2553708", "KB2495300","KB2458331","KB968967","KB968936","KB973275","KB2812950","KB2484832","KB2163398","KB2622802","KB979458","KB2506143", "KB981263"
$KB2008R2 = "KB2470949","KB2618982","KB2775511","KB2878378","KB2617858","KB2494158","KB2734909","KB2618982","KB2622802", "KB2547244", "KB2692929"
$KB2008R2IIS = "KB2618982"
$KB2012 = "KB2790831", "KB2911101"
$KB2012R2 = "KB2911106"
$KB2012R2DC = "KB2955164", "KB2923126"
$KB2012R2DNS = "KB2954185", "KB2919394"

#Script
foreach($Computer in $ComputerName)
{
    $OSVersion = Invoke-Command -ComputerName $Computer -ErrorAction SilentlyContinue -ScriptBlock {[Environment]::OSVersion.Version.ToString(3)}
    $OSName = Invoke-Command -ComputerName $Computer -ErrorAction SilentlyContinue -ScriptBlock {(Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue | select @{N='OSName'; E={$_.ProductName}}).OSName}
    If($OSVersion.Length -ge 8)
    {
        If($OSName -match 'Server')
        {
            $OS = switch($OSVersion.Substring(0,3))
            {
                '5.0' {'2000'}
                '5.2' {'2003'}
                '6.0' {'2008'}
                '6.1' {'2008R2'}
                '6.2' {'2012'}
                '6.3' {'2012R2'}
                default
                {
                    If($OSVersion.Substring(0,4) -eq '10.0')
                    {
                        '2016TP'
                    }
                    else
                    {
                        $OSName
                    }
                }
            }
        }
    }
    switch($OS)
    {
        '2003'
        {
            Check-ServicePackInstalled -BuildNumber '5583' -Version 'Service Pack 2' -ComputerName $Computer
            foreach($kb in $KB2003)
                {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}            
        }

        '2008'
        {
            Check-ServicePackInstalled -BuildNumber '1621' -Version 'Service Pack 2' -ComputerName $Computer
            foreach($kb in $KB2008)
                {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}
        }

        '2008R2'
        {
            Check-ServicePackInstalled -BuildNumber '1130' -Version 'Service Pack 1' -ComputerName $Computer
            foreach($kb in $KB2008R2)
                {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}

            # Only check if IIS is installed
            If(Get-Service W3SVC -ComputerName $Computer -ErrorAction SilentlyContinue)
                {
                foreach($kb in $KB2008R2IIS)
                    {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}
                }
        }

        '2012'
        {
            foreach($kb in $KB2012)
                {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}           
        }

        '2012R2'
        {
            foreach($kb in $KB2012R2)
                {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}

            # Only check if DNS role is installed
            $DNSStartNumber = Invoke-Command -ComputerName $Computer -ErrorAction SilentlyContinue -ScriptBlock {(Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\DNS' -ErrorAction SilentlyContinue | select @{N='Start'; E={$_.Start}}).Start}
            If($DNSStartNumber -and $DNSStartNumber -ne 4)
                {
                 foreach($kb in $KB2012R2DNS)
                    {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}
                }

            # Only check if Domain Controller role
            If((Get-WMIObject -Class Win32_ComputerSystem -ComputerName $Computer -Namespace 'root\cimv2' -ErrorAction SilentlyContinue).DomainRole -ge 4)
                {
                 foreach($kb in $KB2012R2DC)
                    {Check-HotfixInstalled -HotfixID $KB -ComputerName $Computer}
                }
        }
    }
}


$global:UpToDate 
$global:Description

A PowerShell script, it’s already nice but a Management Pack is even better Smile So I quickly used MPAuthor from Silect to transform this PowerShell script to a SCOM Monitor.

Every 12 hours, this monitor checks all the Windows server where a SCOM Agent is installed to ensure that all the OS recommended hotfixes are installed. If this is not the case, the following alert is created:

  image

You could see the monitor state in the Health Explorer:
image

On a server where all the OS recommended Hotfixes are installed:
image

You could download the management pack from here: http://www.vnext.be/wp-content/uploads/2015/12/SCOMAgent.OSRecommendedKB.zip

Gentle Reminder, Use this Script/MP at your own risks Smile

Christopher

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Email this to someoneShare on TumblrPin on PinterestDigg thisShare on RedditFlattr the authorBuffer this pageShare on StumbleUpon
Posted in Operations Manager | 1 Comment