January 24 2012

Force SCCM optional advertisement to run



----------------------------------------------------------------------------
I use a maximum of one Google Ad per post to help offset some of my blog hosting costs.

----------------------------------------------------------------------------

I needed a script that was going to run tigger optional SCCM advertisement to run. Why? Because I was using Opalis to trigger multiple advertisements across multiple systems in a certain sequence. I had tried the SCCM Client Center Integration Pack for Opalis, however the Run Advertisements function didn’t seem to work. So my Opalis workbook simply calls the below script and passes it the SCCM package ID and program name (ie force_run.vbs PACKAGEID PROGRAMNAME). See below for VBScript:


' Purpose: Forces optional advertised programs that meet packageID and program name criteria to run
' Note: There must already be a SCCM advertisement in place
' Use: force_run.vbs PACKAGEID PROGRAMNAME (case sensitive)
' Author: blog.danovich.com.au

' Get input parameters
Dim Arg, packageID, programName
Set Arg = WScript.Arguments
packageID = Arg(0)
programName = Arg(1)
Set uiResource = CreateObject("UIResource.UIResourceMgr")
Set programList = uiResource.GetAvailableApplications

' Set flags for error tracking
flag_package = "notavailable"
flag_program = "notavailable"

' Match each given packageID and program name against applications available to the machine
For each p in programList
If p.PackageID = packageID then
flag_package = "available"
If p.Name = programName Then
uiResource.ExecuteProgram p.ID, p.PackageID,True
flag_program = "available"
Exit For
End If
End If
Next

' Give feedback if the given packageID or program name do not match available applications
If flag_package = "notavailable" then
wscript.echo packageID & " does not match any Package ID in available applications"
End If
If flag_program = "notavailable" and flag_package = "available" then
wscript.echo programName & " does not match any program name in available applications or is not associated with Package ID " & packageID
End If

' Give feedback if everything matches
If flag_program = "available" and flag_package = "available" then
wscript.echo "Program name " & programName & " from package ID " & packageID & " ran successfully."
End If

' Clean up
Set uiResource = Nothing
Set Arg = Nothing

 
 



----------------------------------------------------------------------------
I use a maximum of one Google Ad per post to help offset some of my blog hosting costs.

----------------------------------------------------------------------------

September 9 2009

Return distinguished name of a user

This handy script is an easy way to return the DN of a user based on the sAMAccountName (aka username) that you give it. You can also provide wildcards. Usage:

cscript DNname.vbs username

eg. cscript DNname.vbs john.citizen

Will return:
“CN=john.citizen,OU=Standard,OU=Users,DC=domain,DC=com”

eg. cscript DNname.vbs john*

Will return:
“CN=john.citizen,OU=Standard,OU=Users,DC=domain,DC=com”
“CN=john.peterson,OU=Standard,OU=Users,DC=domain,DC=com”

eg. cscript DNname.vbs *john*

Will return:
“CN=john.citizen,OU=Standard,OU=Users,DC=domain,DC=com”
“CN=john.peterson,OU=Standard,OU=Users,DC=domain,DC=com”
“CN=bill.johnson,OU=Standard,OU=Users,DC=domain,DC=com”

Script is:

 On Error Resume Next
Dim objConnection, objCommand, objRootDSE, strDNSDomain
Dim strFilter, strQuery, objRecordSet, objArgs
Set objArgs = Wscript.Arguments
if objArgs.Count = 0 then
 Wscript.Echo  “CN argument required. “”*”” or “”J*”” or etc..”
 WScript.Quit (1)
End If
cn = objArgs(0)
Set objConnection = CreateObject(“ADODB.Connection”)
Set objCommand = CreateObject(“ADODB.Command”)
objConnection.Provider = “ADsDSOOBject”
objConnection.Open “Active Directory Provider”
Set objCommand.ActiveConnection = objConnection
Set objRootDSE = GetObject(“LDAP://RootDSE“)
strDNSDomain = objRootDSE.Get(“defaultNamingContext”)
strBase = “<LDAP://” & strDNSDomain & “>”
strFilter = “(&(objectCategory=person)(objectClass=user)(sAMAccountName=” & cn & “))”
strAttributes = “distinguishedName”
strQuery = strBase & “;” & strFilter & “;” & strAttributes & “;subtree”
objCommand.CommandText = strQuery
objCommand.Properties(“Page Size”) = 99999
objCommand.Properties(“Timeout”) = 300
objCommand.Properties(“Cache Results”) = False
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    strDN = objRecordSet.Fields(“distinguishedName”)
    Wscript.Echo “””” & strDN & “”””
    objRecordSet.MoveNext
Loop
objConnection.Close
Set objConnection = Nothing
Set objCommand = Nothing
Set objRootDSE = Nothing
Set objRecordSet = Nothing

March 12 2009

Balance mailboxes across databases – Exchange 2007

There is a fantastic script on Kurtdepauw’s blog (http://kurtdepauw.wordpress.com/2007/11/10/dbbalancer-load-balance-your-exchange-mailbox-databases/) to assist in evenly balancing your Exchange 2007 databases so they are of similar size.

I have customized it slightly and highlight the 2 lines below as useful modifications:

Line 78 – added ‘| Where-Object {$_.Name -notlike “Archive Storage Group”}’ – this is very useful if you want to exclude certain databases from being touched by the balancing script

$DBs = Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Where-Object {$_.Name -notlike "Archive Storage Group"}

Line 130 – added -PreserveMailboxSizeLimit switch – you will need to add this so that you can move mailboxes that exceed the database default limits

Move-Mailbox -Identity $Mailboxes[$intRandomMailbox] -TargetDatabase $Global:strSmallestDB.Split(";")[0] -PreserveMailboxSizeLimit -Confirm:$false

———-

Update 04/11/2009

I’ve been alerted that the link to Kurtdepauw’s blogis broken. I’ve posted the entire code below:

# DBBalancer Version 1.1
# Written by BoerLowie (sammybog@gmail.com)
# Modified by www.danovich.com.au - 12/03/2009 - www.danovich.com.au
#
# This script is used to maintain a balance between your different Exchange 2007 Mailbox Databases
#
# Configuration/Installation
# --------------------------
#
# To install the application, just place the script and the config file in C:Program FilesDBBalancer
#
# The configuration is stored in DBBalancer.xml  Use the line below as a reference XML Config file (just paste it in notepad and save it as DBBalancer.xml
#
# <Objs Version="1.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj RefId="RefId-0"><TN RefId="RefId-0"><T>Deserialized.System.Collections.Hashtable</T><T>Deserialized.System.Object</T></TN><DCT><En><S N="Key">ThresholdInGB</S><I32 N="Value">5</I32></En><En><S N="Key">MailboxServer</S><S N="Value">S-BE-KI-EX</S></En></DCT></Obj></Objs>
#
# You can run the script in foreground or schedule it.  To schedule it, create a task using the following command line:
#
# PowerShell.exe -PSConsoleFile "C:Program FilesMicrosoftExchange ServerBinexshell.psc1" -Command "C:DBBalancerDBBalancer.ps1"
#
# Make sure your account is at least an Exchange Server Administrator on the Mailbox Server.
#
# The following values are used in the xml file:
#  - ThresholdInGB:  The script will start to balance you databases if the difference between the biggest
#                    DB and the smallest DB exceeds this value.  This should be set to something like 5 GB.
#  - MailboxServer:  The MailboxServer to balance.  The script can be run from every machine with Exchange 2007 Management Tools
#                    installed on, so it needs to know which Mailbox Server it needs to connect to.  The script will balance all DB's on this
#                    mailbox server.
#
# Processing
# ----------
#
# The script will move a RANDOM mailbox from the Biggest DB to the Smallest DB until all DB are within the Threshold limit.  So if you
# set the Threshold to 5 GB, all DB's will be equally loaded with a maximum difference of 5 GB.
# Only one mailbox at a time will be moved to minimize user downtime.
#
# Logging
# -------
#
# You can follow the progress of the script in the Application Log.  Look for events of Source DBBalancer.
# Every mailbox move will be listed in the eventviewer.
#
# When all Mailbox Databases are balanced, the following will be displayed in the Event Viewer:
#  All Mailbox databases are balanced within the Threshold limit.

$ErrorActionPreference = "SilentlyContinue"

$Global:hshParameters = @{}
$Global:strBiggestDB = ""
$Global:strSmallestDB = ""
$Global:blnExecute = $True

Function Start-Init
{
$Global:hshParameters = Import-Clixml "C:Exchange_Maintenance_ScriptsDBBalancerDBBalancer.xml"
$Global:objEventLog = New-Object System.Diagnostics.EventLog("Application")
$Global:objEventLog.MachineName = "."
$Global:objEventLog.Source = "DBBalancer"
$Global:objEventLog.WriteEntry("Application Started." + [System.Environment]::NewLine + [System.Environment]::NewLine + `
"Target Mailbox Server :" + $Global:hshParameters.MailboxServer + [System.Environment]::NewLine + `
"Threshold in GB :" + $Global:hshParameters.ThresholdInGB)
}

Function Check-Prerequisites
{
If ((Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Measure-Object).Count -gt 1)
{
Return $true
}
Else
{
Return $false
}
}

Function Get-BiggestandSmallestDB
{
Process
{
$DBs = Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Where-Object {$_.Name -notlike "Archive Storage Group"}
$blnFirstRun = $true
foreach ($DB in $DBs)
{
$lonDBSize = (Get-MailboxStatistics -Database $DB.Identity | Measure-Object -Property TotalItemSize -Sum).Sum
If ($blnFirstRun -eq $true)
{
$Global:strBiggestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
$Global:strSmallestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
$blnFirstRun = $false
}
Else
{
If ($lonDBSize -lt $strSmallestDB.Split(";")[1])
{
$Global:strSmallestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
}
If ($lonDBSize -gt $strBiggestDB.Split(";")[1])
{
$Global:strBiggestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
}
}
}
}
}

Function Check-Threshold
{
If (([Long]$Global:strBiggestDB.Split(";")[1] - [Long]$Global:strSmallestDB.Split(";")[1]) -gt ($Global:hshParameters.ThresholdInGB * 1000000000))
{
Return $True
}
Else
{
Return $False
}
}

Function Do-MainLoop
{
While ($Global:blnExecute -eq $True)
{
Get-BiggestandSmallestDB
If (Check-Threshold -eq $True)
{
[Long]$lonDataToMove = ([Long]$Global:strBiggestDB.Split(";")[1] - [Long]$Global:strSmallestDB.Split(";")[1]) / 2
$Mailboxes = Get-Mailbox -Database $Global:strBiggestDB.Split(";")[0] -ResultSize "Unlimited"
$intRandomMailbox = New-Object System.Random
$intRandomMailbox = $intRandomMailbox.Next(0, ($Mailboxes.Count - 1))
$Global:objEventLog.WriteEntry("Moving " + $Mailboxes[$intRandomMailbox] + " from database " + $Global:strBiggestDB.Split(";")[0] + `
" to database " + $Global:strSmallestDB.Split(";")[0] + "." + [System.Environment]::NewLine + [System.Environment]::NewLine + `
"The mailbox has a size of " + ((Get-MailboxStatistics -Identity $Mailboxes[$intRandomMailbox]).TotalItemSize) + "ytes.")
Move-Mailbox -Identity $Mailboxes[$intRandomMailbox] -TargetDatabase $Global:strSmallestDB.Split(";")[0] -PreserveMailboxSizeLimit -Confirm:$false
}
Else
{
$Global:blnExecute = $False
}
}
Return $True
}

Start-Init
If (Check-Prerequisites -eq $true)
{
If (Do-MainLoop -eq $True)
{
$Global:objEventLog.WriteEntry("All Mailbox databases are balanced within the Threshold limit.")
}
}
Else
{
$Global:objEventLog.WriteEntry("Prerequisites check failed.  You probably have only 1 Mailbox Database and therefor we can't move mailboxes around.")
}