Wednesday 30 May 2012

SCCM: Package returning error 259 how-to resolve

After attempting to deploy namely "AutoDesk" to an environment, we came across an issue where the SCCM Advertisement was returning error 259 in the CAS logs on clients. After investigations it was found that setup.exe was executing then spawning other processes while the setup thread was killed. Hence the agent was misreporting the install even though it was eventually successful. This is a small script I wrote to be executed via the program in the package for installs such as this. You must change the:
-strLogLoc (To the actual msi installer log to be monitored)
-cMD (To the actual installer command line)
-The if InStr check for the text in the log that is displayed with the main thread exit code(should be right at the end of the log) in this instance for AutoDesk I have used "]: MainEngineThread is returning" when it parses this line and grabs the "last" character of the line(the error code in this instance)


Don't attempt to modify the script other than this if you are not sure what you are doing, however feel free to ask a question and I shall reply when I have time. Hope this helps people google tells me alot of people have not been able to resolve this.


Sean

On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = WScript.CreateObject("WScript.Shell")


strCmd = objShell.ExpandEnvironmentStrings("%comspec%")


strScriptPath = objFSO.GetParentFolderName(wscript.ScriptFullName)
strLogLoc = "c:\Windows\Temp\Autodesk Revit Architecture 2012 Install (en-us).log"
'wscript.echo strScriptPath
If not right(strScriptPath,1) = "\" Then
strScriptPath = strScriptPath & "\"
End If
'wscript.echo strScriptPath




cMD = strCmd & " /c " & strScriptPath & "\Image\Setup.exe /qb /I Image\AutoDeskRevit_20.12_86a.ini"
'wscript.echo strCmd
'wscript.echo cMD
'Return = objShell.Run(cMD,0,False)


'Loop to wait for the log to be created to we check to see when it is finished installing
bLogExist = 1
While bLogExist = 1
    If objFSO.FileExists(strLogLoc) Then
wscript.echo "log exists"
bLogExist = 0
Else
wscript.echo "Waiting for log"
' do nothing just leave bool to 1
End if
    wscript.sleep 30000 'check every 30 seconds for the log file then once found continue
Wend 




'now check the loop in a loop to check when the MainEngine Thread is finished then return error code
bLogCheck = 1
strMainEngineThreadCode = ""
strErrorCode = 999
While bLogCheck = 1
Set objFile = objFSO.OpenTextFile(strLogLoc, 1, False, -1)
i = 0


Do Until objFile.AtEndOfStream
Redim Preserve arrLines(i)
arrLines(i) = objFile.readline
i = i + 1
Loop

For l = UBound(arrLines)-200 to UBound(arrLines)
If InStr(arrLines(l), "]: MainEngineThread is returning") Then
'strMainEngineThreadCode = arrLines(l)
wscript.echo arrLines(l)
for a=1 to len(arrLines(l))
strErrorCode = right(left(arrLines(l),a),1)
Next
bLogCheck = 0
End If
Next
ObjFile.Close
If bLogCheck = 1 Then
wscript.echo "Autodesk still installing"
Else
wscript.echo "Autodesk install completed with error code: " & strErrorCode
End If
If bLogCheck = 1 Then 
wscript.sleep 30000 ' sleep for 30 seconds then check the log again
End If
Wend



wscript.quit strErrorCode

Tuesday 22 May 2012

SCCM - MP_GetAuth error 0x80040E4D after rebuilding secondary site

You may come across this error when rebuilding the secondary site servers in your hierarchy, when checking the MP_GetAuth log. If utilizing the computer account for db access to the site when the server is rebuilt it gets a new SID created in Active Directory. The MSSQL login when linking the login account utilizes this AD SID for authentication.

USE SMS_001 
DROP USER [DOM\DOMSCMSS001$] 
GO 
 
DROP LOGIN [DOM\DOMSCMSS001$] 
 
CREATE LOGIN [DOM\DOMSCMSS001$] 
FROM WINDOWS 
WITH 
DEFAULT_LANGUAGE=[English]; 
 
USE SMS_001 
CREATE USER [DOM\DOMSCMSS001$] FOR LOGIN [DOM\DOMSCMSS001$]; 
GO 
sp_addrolemember 'smsdbrole_MP',[DOM\DOMSCMSS001$] 
GO 
You can see that if checking the SID on the db vs the SID in AD(via adsiedit.msc) that the SID's will more than likely NOT match. If you are to run the above sql query changing as required it will first check the MSSQL cache for TokenAndPermUserStore. This is why the SID's are mismatched as the query found the SID in the cache NOT AD. In order to resolve the issue of the mismatched SID you are required to clear the TokenAndPermUserStore using DBCC.. You can check the current cache size by running the following sql query:

select name, count(*) from sys.dm_os_memory_cache_entries
      where name = 'TokenAndPermUserStore'
      group by name
      order by count(*) desc ;
GO

To clear the cache run the following sql query on the db:

DBCC FREESYSTEMCACHE ('TokenAndPermUserStore');

Then recreate the account on the db, everything should now be working fine

Monday 21 May 2012

SCCM - ClientAgent - Check installed correct

This is a quick script I wrote to ensure the agent was installing correctly on secondary servers. However should work anywhere, some slight modifications may be required. Also can be used in conjunction with a number of other scripts and checks.



CheckAgent()


Sub CheckAgent()
On Error Resume Next

strCmd = objShell.ExpandEnvironmentStrings("%comspec%")
objShell = WScript.CreateObject("WScript.Shell")
wscript.echo "Checking the state of the SMSAgent"
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Err.Clear
theService = "CcmExec"
bInstallClient = False
bReinstallClient = False
bServiceExists = False
Set colServiceList = objWMIService.ExecQuery("Select * from Win32_Service where Name = '" & theService & "'")
If (Err.Number = 0) And IsObject(colServiceList) Then
If colServiceList.Count > 0 Then
bServiceExists = True
'wscript.echo "SMSAgent Service Exists"
Else
bServiceExists = False
wscript.echo "ERROR service does not exist: " & theService
End If
If bServiceExists = True Then
Set oSMSClient = CreateObject("Microsoft.SMS.Client")
If Err.Number <> 0 Then
'Client is not installed correctly
bReinstallClient = True
Else
'wscript.echo "SMSAgent health seems to be fine"
bReinstallClient = False
End If
Else
bInstallClient = True
End If
If bReinstallClient = False And bServiceExists = True Then
site = UCase(oSMSClient.GetAssignedSite)
If Len(site) < 1 Then
'not assigned to a valid site
wscript.echo "SMSAgent not assigned to a valid site"
wscript.msgbox("Please check the SMSAgent the site is not assigned")
Else
'wscript.echo "SMSAgent seems to be working fine"
End If
End If
End If
If bInstallClient = True Then
wscript.echo "INSTALLING THE SMSAGENT PLEASE WAIT"
cMD = strCmd & " /c C:\windows\system32\ccmsetup\ccmsetup.exe"
Return = objShell.Run(cMD,1,True)
End If
If bReinstallClient = True Then
If FileMinsSinceModified("c:\windows\system32\ccmsetup\ccmsetup.log") < 15 Then
strMsg = "It seems ccmsetup was run in only" & vbCrLf & _
FileMinsSinceModified("c:\windows\system32\ccmsetup\ccmsetup.log") & " minutes ago.." & vbCrLf & _
"are you sure you wish to continue the CCMEXEC reinstall?" & vbCrLf & _
"this install may take some time if you continue"
return=wscript.msgbox(strMsg,4,"CONTINUE REINSTALL?")
If return = 6 Then
wscript.echo "UNINSTALLING THE SMSAGENT PLEASE WAIT"
cMD = strCmd & " /c C:\windows\system32\ccmsetup\ccmsetup.exe /uninstall"
Return = objShell.Run(cMD,1,True)
wscript.echo "INSTALLING THE SMSAGENT. DO NOT CLOSE THE CMD WINDOW!"
cMD = strCmd & " /c C:\windows\system32\ccmsetup\ccmsetup.exe"
Return = objShell.Run(cMD,1,True)
Else
wscript.echo "Reinstallation will not continue at this time.."
End If
Else
wscript.echo "UNINSTALLING THE SMSAGENT PLEASE WAIT"
cMD = strCmd & " /c C:\windows\system32\ccmsetup\ccmsetup.exe /uninstall"
Return = objShell.Run(cMD,1,True)
wscript.echo "INSTALLING THE SMSAGENT. DO NOT CLOSE THE CMD WINDOW!"
cMD = strCmd & " /c C:\windows\system32\ccmsetup\ccmsetup.exe"
Return = objShell.Run(cMD,1,True)
End If
End If
If bServiceExists = True And bReinstallClient = False and bInstallClient = False Then
wscript.echo "SMSAgent seems to be fine"
Else
wscript.echo "The SMSAgent had an issue, Check to see if it was installed or reinstalled"
End If
Set colServiceList = Nothing
Set oSMSClient = Nothing
On Error GoTo 0
End Sub


Function FileMinsSinceModified(filename)
On Error Resume Next
Dim daysold, fso, f, filespec_date
set fso = CreateObject("Scripting.FileSystemObject")
FileMinsSinceModified = 0
If fso.FileExists(UCase(filename)) Then
Set f = fso.GetFile(filename)
filespec_date = f.DateLastModified
Set f = Nothing
If IsDate(filespec_date) Then
minsold = DateDiff("n", filespec_date,Now())
FileMinsSinceModified = minsold 
Else
wscript.echo "WARNING: Not a valid date: " & filespec_date 
End If
Else
wscript.echo "The file does not exist: " & filename 
End If
End Function 

Thursday 17 May 2012

SCCM - MP GetAuth Check

Hi All.. This little function can be run on your site servers with the MP role installed, where it will check to ensure the server has access to the MSSQL DB. Obviously add FileExist paths or remove as required.

strMPState = MPGETAUTH()


Function MPGETAUTH()
On Error Resume Next
MPGETAUTH = "N/A"
i = 0 
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists("C:\Program Files\SMS\Logs\MP_GetAuth.log") Then
Set objFile = objFSO.OpenTextFile("C:\Program Files\SMS\Logs\MP_GetAuth.log", 1)
ElseIf objFSO.FileExists("C:\windows\system32\ccm\logs\MP_GetAuth.log") Then
Set objFile = objFSO.OpenTextFile("C:\windows\system32\ccm\logs\MP_GetAuth.log", 1)
ElseIf objFSO.FileExists("C:\Program Files\System Center Configuration Manager 2007\Logs\MP_GetAuth.log") Then
Set objFile = objFSO.OpenTextFile("Program Files\System Center Configuration Manager 2007\Logs\MP_GetAuth.log", 1)
Else
'wscript.echo "Cannot find MP_GetAuth.log"
MPGETAUTH = "NOFILE"
Exit Function
End If


Do Until objFile.AtEndOfStream
Redim Preserve arrLines(i)
arrLines(i) = objFile.readline
i = i + 1
Loop


For l = Ubound(arrLines)-20 to Ubound(arrLines) 


If InStr(arrLines(l),": 0x80004005") Then
'wscript.echo "DB NOT DEFINED IN MP"
MPGETAUTH = "DBNODEF"
Exit Function
ElseIf InStr(arrLines(l),": 0x80004001") Then
MPGETAUTH = "DBAUTH"
Exit Function
'wscript.echo "DB DEFINED IN MP BUT NO PERMISSION"
End If
Next
objFile.Close
End Function

SCCM - MSSQL Find Possible Broken Packages

I know one of the biggest things people come across as an SCCM administrator is trying to quickly identify sites where packages are broken. This query gives a basic rundown of identifying potential pain points in your package distribution:

use SMS_000
go

Select R.PackageID,
      s1.Name,
      R.SiteCode,
      R.ServerNALPath,
      s1.SourceVersion as "ActualSourceVersion",
      R.SourceVersion as "SiteSourceVersion",
      R.State,
      R.SummaryDate,
      R.InstallStatus
      from dbo.v_PackageStatusDistPointsSumm as r
            full join dbo.v_Package
                  as s1 on s1.PackageID = r.PackageID
      where R.State <> 0
GO

Stop logon scripts running on servers


This small script I created around Feb 2011 to stop administrators with logonscripts assigned to the Active Directory profile from running(which I’m sure you know can cause havoc)
Just place it as high up the standard logon script as possible so this runs before anything else(Obviously you can modify to run on specific servers etc if need be)

' Stop-server-logon-script
' Sean Wright v1.0 08/02/11
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
    osnamed = objOperatingSystem.Caption
    res = InStr(UCase(osnamed), "SERVER")
    if res > 0 then
        wscript.echo "YOUR ON A SERVER LOGON SCRIPT WILL NOT RUN!!"
        wscript.quit
    end if
Next

SCCM - ClientAgent - Check Site Assignment

This script subroutine will quickly check the SMSAgent(ccmexec.exe) site assignment to ensure it is assigned to the correct SiteCode. This version is written for a multi-hierarchy site configuration. Modify/extend as required.

Sub CheckSite()
On Error Resume Next


        wscript.echo "Checking site assignment"
Dim oSMSClient, Site, objSysInfo, domain, strSiteCode
Set objSysInfo = CreateObject("ADSystemInfo")
domain = ucase(objSysInfo.DomainDNSName)
Set objSysInfo = Nothing
If Len(domain) < 0 Then
            domain = GetDomain
End If 
wscript.echo "Computer Domain: " & domain 
Set oSMSClient = CreateObject("Microsoft.SMS.Client")
If Err.Number <> 0 Then
strMsg = "SMSAgent is not installed correctly or not running." & vbCrLf & _
"Object Microsoft.SMS.Client does not exist"
wscript.MsgBox(strMsg)
Err.Clear
Exit Sub
End If
Site = ucase(oSMSClient.GetAssignedSite)
If Len(Site) < 1 Then
wscript.echo "The machine is not assigned to a valid sitecode"
                strSiteCode = FindSiteCode(domain)
wscript.echo "Should be set to " & strSiteCode
If strSiteCode = "999" Then
strMsg = "Site code could not be found correctly for domain"
                        wscript.msgbox(strMsg)
Exit Sub
End If
oSMSClient.SetAssignedSite(strSiteCode)
If Err.Number <> 0 Then
strMsg "Site reassign failed with error: " & Err.Number
wscript.msgbox(strMsg)
Err.Clear
Else
wscript.echo "Site reassignment successful"
End If
Else
  wscript.echo "Site: " & Site
End If
  mgmt =  oSMSClient.GetCurrentManagementPoint
wscript.echo "Mgmt Point: " & mgmt
Set oSMSClient = Nothing
End Sub
Function FindSiteCode(dom)
On Error Resume Next
Dim FQDN
FQDN = ".blah.com"
Select Case dom
Case "0" & FQDN
FindSiteCode="000"
Case "1" & FQDN
FindSiteCode="001"
Case "2" & FQDN
FindSiteCode="002"
Case "3" & FQDN
FindSiteCode="003"
Case "4" & FQDN
FindSiteCode="004"
Case "5" & FQDN
FindSiteCode="005"
Case "6" & FQDN
FindSiteCode="006"
Case "7" & FQDN
FindSiteCode="007"
Case "8" & FQDN
FindSiteCode="008"
Case "9" & FQDN
FindSiteCode="009"
Case "10" & FQDN
FindSiteCode="010"
Case Else
FindSiteCode="999"
' site cannot be found for the domain
  End Select
End Function