I recently discovered an issue with the CM client which can lead to the client (2012 R2 SP1 CU1 on Win 7 x64 in my case) repeatedly triggering a Group Policy update.  Seems like a House of Cards type of scenario which can quickly turn into the House of Horrors, so I figured best to share.   Essentially this can lead to the How to Melt a SUP scenario turning into how to Melt a DC.

This situation can occur if you are using Group Policy to set the WSUS/SUP server location for the Windows Update Agent and your SUP is unavailable.  As it turns out, the WSUS server URLs you use in group Policy are case sensitive.  You will want to ensure the URLs in your Group Policy settings match exactly what ConfigMgr is using.  In this case the GPO was configured with HTTP://SERVER.CONTOSO.COM:8530 and the client was using http://server.contoso.com:8530 from the ConfigMgr configuration.  When the Software Updates Assignment Evaluation cycle it triggered ({00000000-0000-0000-0000-000000000108} the client attempts to evaluate if the correct WSUS server is in use.  Not an issue so long as your SUP is available, however the client will begin throwing a ‘Scan failed with error = 0x80072ee2’ when it is unable to access the SUP.  

 SUPMeltdown

If your SUP goes down, and you are not aware when it does, you should ensure you are.  You should be using SCOM, or another monitoring system, to receive alerts.  The PowerShell script below provides a quick way to ensure that you receive and alert and automatically try to restart the WSUS App Pool.  This can be run as a Scheduled Task on your WSUS server to ensure the House of Cards is in fact still standing.

################## Check WSUS AppPool PS Script ######################

#
# Check the state of the WSUS Web Pool And restart it if it is not running
#

#Script Variables
$strLog = "c:\temp\WSUSAppPoolCheck.log"
$smtpServer = "This email address is being protected from spambots. You need JavaScript enabled to view it. ;
$smtpTo = "This email address is being protected from spambots. You need JavaScript enabled to view it.;

Function Write-Log{
Param ([string]$strToLog)
$now=Get-Date -format "dd-MMM-yyyy HH:mm:ss"
Write-Host "$now $strToLog"
Add-Content $($strLog) "$now $strToLog"
}

Function Send-Alert([string]$MsgBody) {
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpTo,"WSUS AppPool Alert",$MsgBody)
}

Write-Log "Starting WSUS AppPool check."

#Get the AppPool State
$APStatus = (Get-WebItemState 'IIS:\AppPools\WsusPool').Value

If ($APStatus -ne 'Started') {
#log state detection
Write-Log "The AppPool is stopped, attempting start."
#start the AppPool
Start-WebAppPool -Name "WSUSPool"
#Wait a tick or 2
Sleep -Seconds 5
#Validate successful start
$APStatusVerify = (Get-WebItemState 'IIS:\AppPools\WsusPool').Value
if ($APStatusVerify -ne "Started") {
#The AppPool is still not running!
Write-Log "AppPool still does not appear to be running, calling for help"
Send-Alert "The WSUS AppPool could not be restarted, please connect and investigate the issue."
} ELSE {
Write-Log "Successfully restarted the AppPool."
Send-Alert "The WSUS AppPool was not running and has been restarted."
}
} Else {
#Log current state
Write-Log "The AppPool is currently $APStatus"
}

############################### End Script #################################

Still testing if this issue exists in the latest CM build, but in the mean time, you have been warned.

https://connect.microsoft.com/ConfigurationManagervnext/feedback/details/2260694/wsus-server-urls-used-in-group-policy-are-case-sensitive-in-some-cases 

The most exciting part about last month's Lync 2013 update was the sheer number of questions about the Skype for Business branding on the first launch which I received from our pilot group.  If your organization is not yet using the Skype for Business interface, you may want to roll out a few registry changes to avoid all of the questions on this one.  These can be deployed with SCCM Compliance, GPO, all manner of scripting.  But here they are laid out in a universally common way that is easy to test.  Removing these keys will result in the first run overview appearing, so once you are ready to switch you can bring it on.

REG ADD HKCU\Software\Microsoft\Office\Lync /v EnableSkypeUI /t REG_BINARY /d "00000000" /f
REG ADD HKCU\Software\Microsoft\Office\15.0\Lync /v FirstRun /t REG_DWORD /d "1" /f

Maybe I am the only one that has and will run into this, but in the event you are having strange issues with Task Sequence editing, read on.  Occasionally we were receiving general WMI errors that a TS was locked, on occasion we hit apply while editing and then pressed OK before the screen refreshed, suddenly the task sequence would be blank.  Then last Sunday while making a routine update to our production client image the sequence blanked out again.  After a little digging through the TaskSequenceProvider.log they was a myriad of errors....

Failed to load dynamic properties for class "SMS_TaskSequence_ApplyNetworkSettingsAction" from XML into WMI 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)
Failed to load node Apply Network Settings from XML into WMI 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)
Failed to load children steps for node "PostInstall" from XML 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)
Failed to load children steps for node "Execute Task Sequence" from XML 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)
Failed to load children steps for node "" from XML 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)
Failed to load XML for the task sequence into WMI 0x80070542 (2147943746) TaskSequenceProvider 4/12/2015 10:36:48 AM 840 (0x0348)

The CM Console would only throw a generic WMI failure error on occasion.  After doing a little research and looking into this further I read an article which pointed to KB3023562 as the culprit.  Downloaded the patch and applied it (which was a surprise to me as we had already installed it previously).  After a reboot the issue has completely gone away.

http://www.microsoft.com/en-us/download/details.aspx?id=45628

Internet Explorer 11 comes with this great new feature, Enterprise Mode, and it saves the day when it comes to most browser related upgrade issues. At least in my case it did a really good job of mitigating them. Unfortunately for me the documentation didn't do a great job of showing me how to make sense of it all,  especially when it came to how I was supposed to collect all the data from the web endpoint in the 'enable' key. (https://msdn.microsoft.com/en-us/library/dn640699.aspx) Basically you can put a URL in the 'enable' registry key which instructs the browser to post some data to a URL when ever a user enables, or disables, enterprise mode. That is great! Well wait, what do we need to setup to collect the data again?

There are a few posts out in the interwebs that describe how to do this already.  Some people use a web page to write to a text file, and Microsoft even released a way for us to collect this data with ConfigMgr (https://msdn.microsoft.com/en-us/library/dn833204.aspx). Great problem solved!  Well unfortunately ConfigMgr may not be everywhere I need it, or maybe I don't want to collect all this data in my 'already too big for my own good' CM database.  I thought I would share what I have done to make my life a little easier when someone asks "who is using enterprise mode and for which URLs?".  So let's setup an IIS site with a page that collects the data and then writes the data into a database for us. Basically we setup IIS, setup the database, then drop an aspx file into our website to write the data to the database for us. **Small disclaimer here: I am a systems admin and not an application developer. So please test this, use the appropriate data locations, and please change the passwords.  Also, let me know what i messed up!**

First off, we need a web server. For the purpose of this article I setup Server 2012 R2 with SQL Express as a starting point. Next I ran the following commands to setup the IIS Role on the server.

DISM /online /enable-feature /featurename:NetFx4 /all
DISM /online /enable-feature /featurename:IIS-WebServerRole
DISM /online /enable-feature /featurename:IIS-ASPNET45 /all
DISM /online /enable-feature /featurename:WCF-HTTP-Activation

Next, lets make a directory for our IIS site and database, then create and configure the IIS site using the commands below.

::Make our web dir
mkdir c:\ie11em
::Make our SQL dir
mkdir c:\sql
::Stop the Default IIS site
c:\windows\system32\inetsrv\appcmd stop site /site.name:"Default Web Site"
::Create our IE11EM IIS site
c:\windows\system32\inetsrv\appcmd.exe add site /name:IE11EM /id:2 /physicalPath:c:\ie11em /bindings:http/*:80:
::Enable windows auth (so we can capture user names)
c:\windows\system32\inetsrv\appcmd set config /section:windowsAuthentication /enabled:true
::Disabled Anonymous Auth
c:\windows\system32\inetsrv\appcmd set config /section:anonymousAuthentication /enabled:false

Now to setup the database, lets open up SQL Management Studio and run the following script.  This will also create the SQL auth account for the webpage to write to the database.  You will need to enable SQL auth on your SQL instance prior to running this, in SQL Mgmt Studio right click on your server name and select properties.  Then select the Security node, and set the Server Authentication option to 'SQL Server and Windows Authentication mode'.  (aka Mixed Mode)  Then restart you sql instance for the changes to take effect.

/************************** Start IE11EM.SQL **************************/
USE [master]
GO
/****** Object: Database [IE11EntModeDB] ******/
CREATE DATABASE [IE11EntModeDB]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'IE11EntModeDB', FILENAME = N'c:\SQL\IE11EntModeDB.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'IE11EntModeDB_log', FILENAME = N'c:\SQL\IE11EntModeDB_log.ldf' , SIZE = 1024KB , MAXSIZE = 8GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [IE11EntModeDB] SET COMPATIBILITY_LEVEL = 110
GO

USE [IE11EntModeDB]
GO

/****** Object: User [svc.ie11entmode] ******/
CREATE LOGIN [svc.ie11entmode] WITH PASSWORD = '[email protected]!';
GO
CREATE USER [svc.ie11entmode] FOR LOGIN [svc.ie11entmode] WITH DEFAULT_SCHEMA=[dbo]
GO
ALTER ROLE [db_datareader] ADD MEMBER [svc.ie11entmode]
GO
ALTER ROLE [db_datawriter] ADD MEMBER [svc.ie11entmode]
GO
/****** Object: Table [dbo].[IEEntMode] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[IEEntMode](
[key] [int] IDENTITY(1,1) NOT NULL,
[Source] [nvarchar](128) NULL,
[Url] [nvarchar](2048) NULL,
[Mode] [nvarchar](5) NULL,
[User] [nvarchar](64) NULL,
[TimeStamp] [datetime] NOT NULL CONSTRAINT [DF_IEEntMode_TimeStamp] DEFAULT (getdate()),
CONSTRAINT [PK_IEEntMode] PRIMARY KEY CLUSTERED
(
[key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object: View [dbo].[vwIE11EnterpriseModeCountSummary] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [dbo].[vwIE11EnterpriseModeCountSummary]
AS
SELECT Url, Mode, COUNT(Mode) AS tCount
FROM dbo.IEEntMode
WHERE (Url <> '')
GROUP BY Url, Mode


GO
/****** Object: View [dbo].[vwIE11EnterpriseModeDomainDetail] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [dbo].[vwIE11EnterpriseModeDomainDetail]
AS
SELECT LEFT(Url, CHARINDEX('/', Url, 9) - 1) AS Domain, Mode
FROM dbo.IEEntMode
WHERE (Url <> '')
GO

USE [master]
GO

ALTER DATABASE [IE11EntModeDB] SET READ_WRITE
GO
/************************** End IE11EM.SQL **************************/

Alright, almost there. The last step is to place the aspx page in our web directory. Save the code below as ie11em.aspx into the c:\ie11em directory created earlier.  Make certain to substitute your server's name in the connection string where you see "%YourServerNameHere%" listed.

/************************** Start ie11em.aspx **************************/

<html><head><title>IEEM Logging</title></head><body>

<%
'Dim objFSO, objTextFile, csvFile

Response.write("'" & Request.ServerVariables("REMOTE_HOST") & "','" & Request.ServerVariables("AUTH_USER") & "','" & Request.Form("URL") & "','" & Request.Form("EnterpriseMode") & "'")

Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection("Server=%YourServerNameHere%; Database=IE11EntModeDB; User Id=Svc.ie11entmode; [email protected]!";)

Dim cmd As New System.Data.SqlClient.SqlCommand
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "INSERT IEEntMode ([Source],[User],[Url],[Mode]) VALUES ('" & Request.ServerVariables("REMOTE_HOST") & "','" & Request.ServerVariables("AUTH_USER") & "','" & Request.Form("URL") & "','" & Request.Form("EnterpriseMode") & "')"
cmd.Connection = sqlConnection1

sqlConnection1.Open()
cmd.ExecuteNonQuery()
sqlConnection1.Close()

cmd = Nothing
sqlConnection1 = Nothing

%>
</body></html>

You can now test your IE 11 data collection site by putting "https://%YourServerNameHere%/ieem.aspx" in your browser.  If everything is working you will see '192.168.1.24','domain\username','','' appear in the browser, where 192.168.1.24 is the IP of the system you opened the browser on, and the domain\username is the user you are logged in with.  Since we are not passing the same variable strings the browser does, you will see blanks in the last 2 values.  Once you plug this URL value in the registry key to enable Enterprise Mode you will also see the URL passed from the browser, and a binary On or Off value.  (HKLM\Software\Policies\Microsoft\Internet Explorer\Main\EnterpriseMode enable="https://%YourServerNameHere%/ieem.aspx")  

Once you have updated the registry, restarted IE, and you have enabled Enterprise Mode on a few sites.  Use the query below to see the data you are collecting.

SELECT [key],[Source],[Url],[Mode],[User] ,[TimeStamp] FROM [dbo].[IEEntMode]

Next up in part 2:  A few SSRS reports to rollup the data and a runbook to rollout the sitelist to, you guessed it, the website above.

Until next time, cheers!

It is almost that time, another Java runtime will go end of life in just over a month.  This means we have only a month left to finish the Java upgrade we have already started, right?  Well I have lived through a few of these Java events over the years and they really don't seem to get any easier, or even ever really end.  In fact I am seriously considering removing Java from users systems.  The one only issue is, who is actually using it for work related purposes?  That has always been the million dollar question to me.

Turns out if you pay for Java support there are some tools that can help you determine this sort of thing.  So where does that leave the rest of us that maybe are not as fortunate as the aforementioned minority?  Well fortunately for us, Oracle did us all a small favor late last year and built-in some usage tracking mechanisms into the JRE's we are already be using.  Turns out "Usage Tracker is available in Oracle Java SE Advanced and Oracle Java SE Suite versions 1.4.2_35 and later, 5.0u33 and later, 6u25 and later, 7 and later, and 8 and later.".  (http://docs.oracle.com/javacomponents/usage-tracker/overview/index.html)  Think of this as software metering for Java plug-ins and VMs which run on your systems, it logs each users data into a log file in their user profile.

I just had to try this so I followed the instructions, dropped the usagetracker.properties file in the correct directory and then fired up a browser and ran a few Java plugins.  All of the data was right there, in a little txt file in my user profile.  So now what?  Turns out there are a few catches to all of this logs.

  • A properties file must be in the appropriate directory for each JRE if you want to log data.  For better or worse, maybe some machines have more than one JRE installed.
  • The default delimiter in their tracking file was a comma.  Typically this is great, until I noticed there are no text qualifiers in the data elements. Formatting nightmares.
  • The log files are stored in the user's profiles by default.  Typically a system should only have one user, but this is not always the case either.  So we need to aggregate the data together.

So based on my own initial assessment I came up with a few functional requirements on how I would want a data collection to work for this.

  • Enabling logging for all JRE's installed on the system.
  • Use a delimiter character that would be less likely to show up in the command line options very often, I chose a carrot '^' for this.
  • Enumerate all of the user profiles and centrally store the data on the system.

Based on how Java usage tracking works, and how I wanted to see it work, I setup a PowerShell compliance script that performs the following actions.

  • Logs all data associated to the script to the CM client logs directory (CM_JavaUsageLogging.log) when logging is enabled.  This is the default, this can be disabled by changing $LoggingEnable to $false at the top of the compliance script.
  • Query the registry for installed JRE's and creates the usagetracking.properties file in the lib/management folder to enabled logging for all instances.
  • Merge all of the data from all of the tracking logs on the system and add the user which executed the vm or plug-in to the dataset.
  • Creates a CM_JavaUsageTracking WMI class to store the data centrally on the system.  Then we can pull it off with hardware inventory!
  • Only add the new entries on subsequent executions.  The data in WMI can be inventoried.  (MOF below)

jutci

The cab located here can be downloaded, tested, and used to get you started on your way.  Please note this is a work in progress, so I will update this file with the new changes once they are ready.  If you have any feedback (it is welcome) on the compliance script please let me know at This email address is being protected from spambots. You need JavaScript enabled to view it..  This has been tested with PowerShell 2.0 and above, but as always test it first to veriy everything works in your environment.

The data in WMI can be inventoried!  So after running this script on a system, connect to it and add the CM_JavaUsageTracking to hardware inventory in CM, now you have Java software metering in a sense.  This is still a work in progress, here are a few more items I still want to add and cleanup.

  • The compliance rule is stating non-compliant even though the script appears to complete.
  • Add a day count rolling history feature so data older than 'x' number of days is removed from WMI and not edited.  This would allow a limit per system on the collected data.
  • Test and validate support for 64-bit JREs, I have 99% 32-bit so this was my priority.

For those of you concerned about how much space this will require in your cm database, I checked and in my case 30 days of data from approximately 2500 systems was a table around 50 MB.  This will vary greatly depending on how much Java plugins are in use in your environment.  Data is now being collected and I can sit back and see which sites users are using and determine what I am going to do about it. 

Happy data spelunking!

  • 1
  • 2