Friday, January 27, 2012

ccmexec crashing on windows 2008 r2

UPDATE: looks like MS caved and released a hotfix.  I have not tried it yet, please let me know if you do and if it solves this problem: http://support.microsoft.com/kb/2724939/en-us

Hey all,
I have been tracking an issue for some time.  I have no fix but some things are becoming clear and I just found a good way to scope the problem, hence this post…

I am running Systems Center Configuration Manager 2007 SP2 R2 and I have been getting this error on some seemingly random set of my windows 2008 r2 servers:
Log Name:      Application
Source:        Application Error
Date:          1/27/2012 5:52:09 AM
Event ID:      1000
Task Category: (100)
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      xxxxxxxxxxxxxxxxx
Description:
Faulting application name: CcmExec.exe, version: 4.0.6487.2000, time stamp: 0x4ab33e4d
Faulting module name: ntdll.dll, version: 6.1.7601.17514, time stamp: 0x4ce7ba58
Exception code: 0xc0000005
Fault offset: 0x0009ce04
Faulting process id: 0x1d58
Faulting application start time: 0x01ccdcd93adaa8bf
Faulting application path: C:\Windows\SysWOW64\CCM\CcmExec.exe
Faulting module path: C:\Windows\SysWOW64\ntdll.dll
Report Id: f570d39f-48d4-11e1-b96c-6431504ea6e0

Notes from this page and especially the german write up here (translation here) were very helpful.   To briefly summarize, when you run resource explorer, you create an ETS performance trace called:  WDC.BE95A9B1-DE15-4B78-B923-A12AB70BE951.  You can verify this by running ‘logman query –ets’ or in server manager -> Diagnostics -> Performance -> Data Collector Sets -> Event Trace Sessions.

Apparently the sccm client dislikes this trace and will crash, in my case every 65 minutes.  Stopping the trace reportedly fixes it, I am still testing before I fully believe that.  I have not found it necessary to reboot/reinstall etc as are suggested elsewhere.  Stopping the trace will kill your Resource Monitor.

Next step would be looking into the trace to see if it is possible to adjust the trace.  Word is MS is refusing to fix it.

The only thing I have to add is that I am seeing a status message of 669 (2 in fact) each time this happens.  So in order to determine which machines this is happening on, run the report Status Messages -> All messages for a specific message ID and query for message ID 669.  Exported to excel (so I could mask server/site names more easily), it looks like this:
Record ID
Severity
Message ID
Component
Computer Name
Time
Site Code
1012608
Error
669
Advanced Client
SERVER--SCCM
1/27/2012 6:15:46 AM
SC2
1012605
Error
669
Advanced Client
SERVER--WEB3
1/27/2012 6:08:23 AM
SC1
1012607
Error
669
Advanced Client
SERVER--WEB3
1/27/2012 6:08:23 AM
SC1
1012602
Error
669
Advanced Client
SERVER--WEB2
1/27/2012 5:51:38 AM
SC1
1012604
Error
669
Advanced Client
SERVER--WEB2
1/27/2012 5:51:38 AM
SC1
1012601
Error
669
Advanced Client
SERVER--SQLA2
1/27/2012 5:50:07 AM
SC1
1012603
Error
669
Advanced Client
SERVER--SQLA2
1/27/2012 5:50:07 AM
SC1
1012599
Error
669
Advanced Client
SERVER--WEB1
1/27/2012 5:44:05 AM
SC2
1012600
Error
669
Advanced Client
SERVER--WEB1
1/27/2012 5:44:05 AM
SC2
1012596
Error
669
Advanced Client
SERVER--SQLA1
1/27/2012 5:32:24 AM
SC1
1012598
Error
669
Advanced Client
SERVER--SQLA1
1/27/2012 5:32:24 AM
SC1
1012591
Error
669
Advanced Client
SERVER--SQLA2
1/27/2012 5:24:14 AM
SC2
1012593
Error
669
Advanced Client
SERVER--SQLA2
1/27/2012 5:24:14 AM
SC2
1012590
Error
669
Advanced Client
SERVER--SQLB1
1/27/2012 5:21:40 AM
SC1
1012592
Error
669
Advanced Client
SERVER--SQLB1
1/27/2012 5:21:40 AM
SC1
1012584
Error
669
Advanced Client
SERVER--SCCM
1/27/2012 5:10:17 AM
SC2
1012585
Error
669
Advanced Client
SERVER--SCCM
1/27/2012 5:10:17 AM
SC2
1012577
Error
669
Advanced Client
SERVER--WEB3
1/27/2012 5:02:27 AM
SC1
1012583
Error
669
Advanced Client
SERVER--WEB3
1/27/2012 5:02:27 AM
SC1
1012574
Error
669
Advanced Client
SERVER--WEB2
1/27/2012 4:45:50 AM
SC1

According to the ever handy SystemCenterCentral:
Message ID 669: This message is caused when SCCM component raised an exception but failed to handle it. We should further investigate this problem.
So this could easily be from something else but this crash seems to be the primary (only) error I am seeing in my sites that is sending this message.

Please respond if you have any more details to add…

Update: Feb 1, 2012.  It looks like we are not getting any fixes to this in sccm 2007.  It is fixed in 2012 and, despite the product not being released, MS has decided this is good enough.  The options are to not run resource manager, accept the crashes, or (if you don't care about asset intelligence and CAL reports), to rename %WINDIR%\syswow64\ccm\ccm_caltrack.dll to ccm_caltrack.ThisFileSux.  I have done this to a few machines and it seems to solve the problem.


Tuesday, October 25, 2011

Exporting songs in Windows Media Player by star rating

So, I used this some forever ago to move song ratings from iTunes to Windows Media Player with a powershell function.  Now I wanted to export the ratings to a file so I have that list outside of wmp.  Annoyingly, i didn't see a way to export the song list, saving the playlist just saved the search terms.  Meh, powershell to the rescue, yet again...

This function will export the name of all files w/ ‘-starcount’ stars.  Could be trivially modified to export other details.


function get-playlistbyStars {
      param ($starcount = $(throw "need -starcount")
           )
     
      #get WMP
      $wmp = New-object -COM WMPlayer.OCX
      $WMPLibrary= $wmp.mediaCollection
      #set vars
      $rated = 0
      $processed = 0
      $added = 0
      $unrated = 0
      $1star = 0
      $2star = 0
      $3star = 0
      $4star = 0
      $5star = 0
      $defstar = 0
      $ctr = 0
      $allsongs = $WMPLibrary.getall()
      $colOut = @()
      for ($i = 0; $i -lt $allsongs.count; $i++) {
            $processed++
            $song = $allsongs.Item($i)
            if (@(".jpg",".png") -notcontains ([System.IO.FileInfo]$song.sourceURL).Extension ) {
                  switch ($song.getiteminfo("UserRating")) {
                        "0" {
                              $unrated++
                              if ($starcount -eq 0) {
                                    $colOut += $song.sourceURL
                              }
                        }    
                        "1" {
                              $1star++
                              $rated++
                              if ($starcount -eq 1) {
                                    $colOut += $song.sourceURL
                              }
                        }
                        "25" {
                              $2star++
                              $rated++
                              if ($starcount -eq 2) {
                                    $colOut += $song.sourceURL
                              }
                        }
                        "50" {
                              $3star++
                              $rated++
                              if ($starcount -eq 3) {
                                    $colOut += $song.sourceURL
                              }
                        }
                        "75" {
                              $4star++
                              $rated++
                              if ($starcount -eq 4) {
                                    $colOut += $song.sourceURL
                              }
                        }
                        "99" {
                              $5star++
                              $rated++
                              if ($starcount -eq 5) {
                                    $colOut += $song.sourceURL
                              }
                        }
                        default {
                              #so I have something to query for random nums
                              $defstar++
                              if ($starcount -eq 42) {
                                    $colOut += $song.sourceURL
                              }

                        }
                  }
                  #so I have something to watch
                  $ctr++
                  if ($ctr%500 -eq 0) { Write-verbose $ctr}

            }
      }

      #output results
      Write-verbose "Processed:  $processed"
      Write-verbose "Rated:  $rated"
      Write-verbose "Added:  $added"
      Write-verbose "1:  $1star "
      Write-verbose "2:  $2star "
      Write-verbose "3:  $3star"
      Write-verbose "4:  $4star "
      Write-verbose "5:  $5star"
      Write-verbose "def:  $defstar"
     
      $colOut
}
     
get-playlistbyStars 3 | out-file –filepath .\3starsongs.txt


Friday, October 14, 2011

SQL and Powershell: Attach all database mdf files in a directory

Hey all,
I didn’t find this elsewhere on the web and I needed it. Since I actually had to do work, i figure I should give it out and spare somebody else that pain.
As part of a failover plan, I am synchronizing directories of sql files. In a failover, I am going to need to bring up a group of databases in a specific directory. The script below will take in a directory name and a SQL instance. It will get all the .mdf files in the directory and compare them against the database files attached to the SQL instance. Any files that are not attached already are attached, extrapolating the filename from the .mdf file. The MAJOR ASSUMPTION here is that you want to name your Database the same name as the .mdf file (without the .mdf). Several of my dbs have multiple files so I read the .mdf to get all the files it knows about. Another major ASSUMPTION is that you are replicating to/attaching from the same file paths on your new server.
I use my out-log function. if you don’t want to use it, replace out-log with write-host in the below script.

function AttachMDFsInDir {
      param (
            $dir = $( throw "Must specify -dir" ),
            $instance  = $( throw "Must specify -instance" ),
            $verbosity = 1 # for the out-log function.
            )
      out-log "Starting AttachMDFsInDir with dir: $dir and inst: $instance"
      $srv = new-Object Microsoft.SqlServer.Management.Smo.Server($instance)
      out-log "Connected to $($srv.Name)"
     
      #get a list of all attached database file names
      $colAttachedMDFs = @()
      foreach ($db in $srv.Databases ) {
            foreach ($fg in $db.Filegroups) {
                  foreach ($file in $fg.Files) {
                        out-log "Adding to `$colattachedMDFs: $($file.Filename)" 2
                        $colAttachedMDFs += $file.Filename
                  }
            }
      }
      out-log "Found $($colAttachedMDFs.count) mdfs attached in $instance"         
                 
      #foreach mdf in $groupSQLDir
      $colMDFsToAttach = @()
      foreach ($mdf in dir "$dir\*.mdf") {
            if (-not ($colAttachedMDFs -contains $mdf)) {
                  out-log "Adding to `$colMDFsToAttach: $($mdf.Fullname)" 2
                  $colMDFsToAttach += $mdf.FullName
            }
      }
      Remove-Variable mdf
      Remove-Variable file
     
      out-log "Found $($colMDFsToAttach.count) mdf(s) in the directory that are unattached"           

      foreach ($mdf in $colMDFsToAttach) {
            #determine name to restore as from mdf file name.
            $DBNameFromFile = ([System.IO.FileInfo]$mdf).Basename
            out-log "Named the db $DBNameFromFile based on the mdf: $mdf"

            #get list of files
            $colDBFiles = $srv.EnumDetachedDatabaseFiles($mdf)
            out-log "$mdf specifies $($coldbfiles.count) files to attach."
            out-log $colDBFiles 2
           
            #add to collection
            $files = new-object system.collections.specialized.stringcollection
            foreach ($file in $colDBFiles) {
                  $files.Add($file)
            }
            out-log "Ready to attach db: $DBNameFromFile w/ $($files.count) files."
            #attach database
            $srv.AttachDatabase($DBNameFromFile,$files)
      }
}


As a corollary to the above, i needed to check which of my dbs on the running servers did not have the same name as their .mdf. you can use this loop.

$instances = @("SERV\Inst1","Serv\INST2") )
foreach ($instance in $instances) {
      $srv = new-Object Microsoft.SqlServer.Management.Smo.Server($instance)
      ""
      "------------------------"
      $srv.Name
      "------------------------"
     
      foreach ($db in $srv.Databases ) {
            foreach ($fg in $db.Filegroups) {
                  foreach ($file in $fg.Files) {
                        $Fileinf = [System.IO.FileInfo]$file.filename
                        if ($Fileinf.extension -eq ".mdf" ) {
                              if ($Fileinf.BaseName -eq $db.name) {
                                    #"File: $($Fileinf.Basename) matches $($db.name)"
                              } else {
                                    "Filename: $($Fileinf.Basename) DOES NOT MATCH DB Name: $($db.name)"
                              }
                        }
                  }
            }
      }
 }

analytics