Showing posts with label SCCM. Show all posts
Showing posts with label SCCM. Show all posts

Tuesday, May 5, 2015

Find SCCM Device Variables Using Powershell

Sometimes you want a report of all the variables that computer/device will have when it runs the task sequence.

Here's a script that will report ...
a) device name
b) device assigned variables
c) Collection name with the assigned variables of which the device is a member.

It requires the SCCM console installed and you must provide the computer name in the command line.

The script will report back if the computer name is not valid and kill the powershell process.
For testing, run the script from a command prompt. i.e. powershell .\variables.ps1 computername

param (
    [Parameter(Mandatory=$true, HelpMessage="Computer Name",ValueFromPipeline=$true)] $strComputer
)
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
cls
import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')
CD SITENAME:\
$nl = [Environment]::NewLine
$tab = "`t" #tab
$count = -1 # Allows for Null
write-host Checking Computer Name
If(!$strComputer){
    [System.Windows.Forms.MessageBox]::Show("Error! - No Source Computer Entered")
    stop-process $pid -Force #End Powershell task
}
#Verify Names
$Verify =  Get-CMDevice -Name $strComputer | forEach{$_.name}
If(!$Verify){
    [System.Windows.Forms.MessageBox]::Show("No Record for "+ $strComputer)
    stop-process $pid -Force #End Powershell task
}
#Get-CMDeviceVariable -DeviceName <String>
# Find System Variables
write-host Checking System Variables
$Result = Get-CMDeviceVariable -DeviceName $strComputer
If(!$Result){
    #write-host $strComputer Not Found
    $strOutput = $strComputer
}
else{
    $Result = Get-CMDeviceVariable -DeviceName $strComputer | forEach{$_.Name + $tab + $_.Value} |Out-String
    $strOutput = $strComputer.toUpper() + " Assigned Device Variables"+ $nl + "Variable Name" +$tab +"Variable Value" +$nl + $Result
}
If($ErrCount -ge 1){
    [System.Windows.Forms.MessageBox]::Show("Error" + $ErrCount)
    stop-process $pid -Force #End Powershell task
}
$strOutput = $strOutput + $nl + $strComputer.toUpper() + " Assigned Collection Variables"
write-host Checking Collection Variables
#Find Collection Variables
$ResID = Get-CMDevice -Name $strComputer | forEach{$_.ResourceID}
$Collections = (Get-WmiObject -ComputerName "SCCM SERVER NAME" -Class sms_fullcollectionmembership -Namespace root\sms\site_SITENAME -Filter "ResourceID = '$($ResID)'").CollectionID
foreach($collection in $Collections){
    $CollName = Get-CMDeviceCollection -CollectionId $Collection | forEach{$_.name}
    write-host $CollName
    $CollVar = Get-CMDeviceCollectionVariable -CollectionName $CollName | forEach{$CollName + $tab + $_.Name + $tab + $_.Value} |Out-String
    If ($CollVar){
        $CollOutput = "Collection Name" +$tab + "Variable Name" + $tab + "Variable Value"
        $CollOutput = $CollOutPut + $nl + $CollVar
    }
}
$strOutput = $strOutput + $nl + $CollOutput
#[System.Windows.Forms.MessageBox]::Show($strOutput)
[IO.File]::WriteAllText('variables.txt', $strOutput)



More SCCM related posts

Friday, May 1, 2015

SCCM Boot Image with UltraVNC remote access

In preparing for a Universal Imaging Task sequence, the thought came across my mind, what if I want to see what's going on and the computer is 2 hours away?

Once the task sequence installs Windows, we have it install UltraVNC so after that point it is possible to remotely connect.  However what about before when the computer has booted from our PXE server and is running Windows PE.

Here is the quick and dirty version of how we can now VNC into a computer that has started up in Windows PE.



1) Create Standard WIM file using the Windows ADK and then before committing the changes...
1a) Created an 'xtras' folder on the root of the mount folder (I called it 'xtras' because it's always drive x: in our PE environment)

2) UltraVNC program with password protection
2a) Installed on test system running Windows 7 with any settings (i.e. password)
2b) Copied the UltraVNC found in Program Files to mount\xtras

3) Create Computername.vbs and copy into mount\xtras
3a) Basic script that extracts the IP address of the computer using WMI
3b) Disables the WinPE firewall - "wpeutil disablefirewall"
3c) Installs UltraVNC
3d) Popup message with IP address - only on screen for 90secs so that it does not prevent the task sequence from running.

4) Create startup.cmd file in mount\xtras
4a) In that file, it runs wscript.exe %systemdrive%\xtras\computername.vbs

5) Once files have been copied to the mount\xtras folder, you can commit the changes to the WIM and proceed with importing it into SCCM.

6) Create at 'winpeshl.ini' file (See below)
6a) Save to... C:\Program Files\Microsoft Configuration Manager\OSD\bin\x64 or C:\Program Files\Microsoft Configuration Manager\OSD\bin\i386

7) Add Drivers and any extra components that you require

8) Distribute/update boot images.

'winpeshl.ini' file contents
[LaunchApps]
%SYSTEMDRIVE%\Windows\System32\wpeinit.exe
%SYSTEMDRIVE%\Windows\System32\wpeutil.exe, "initializenetwork"
%SYSTEMDRIVE%\xtras\startup.cmd
%SYSTEMDRIVE%\sms\bin\x64\TsBootShell.exe
computername.vbs example.
 'Extract Computer Details
'Version 3.01 WMI Query
'May 1, 2015
on error resume next
Dim oTaskSequence
'Create Objects
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2") 'Local computer WMI
Set objShell = CreateObject("WScript.Shell")
strQuery = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE MACAddress > ''"
Set colItems = objWMIService.ExecQuery( strQuery, "WQL", 48 )
For Each objItem In colItems
for each IP in ObjItem.IPAddress
If left(IP,4) = "192." then
strIP = IP & vbCRLF & strIP
end if
next
Next
StrInfo = "If you require any assistance..." & vbCRLF &_
"Please send this information to the IP department." & vbCRLF &_
vbCRLF & "IP Address: " & strIP
cmdFirewall = "wpeutil disablefirewall"
objShell.run cmdFirewall,0,1
cmdUltra = "%systemdrive%\xtras\UltraVnc\winvnc.exe -install"
'msgbox cmdUltra
ObjShell.run cmdUltra
objShell.Popup strInfo, 90, "Message Box Title"
References...

More SCCM related posts

Tuesday, March 31, 2015

Intel NUC and SCCM issues

We purchased a couple of the Intel NUC mini desktops (model NUC5i3RYK) for our custom Lync Room systems.

Deploying with Microsoft System Center Configuration Manager...

Same with any new system... the Window PE boot image needed new drivers for the Ethernet adapter. (In our case the 64 bit driver - e1d64x64.inf)

Created a driver pack for the Intel NUC system, however the drivers were not getting installed into the image by the "Apply Device Drivers" task.

Decided to try the "Apply Driver Package" and picked the Intel NUC package option to see what would happen.

Now the task sequence fails with...
This task sequence cannot be run because a package referenced by the task sequence could not be found. For more information, please contact your system administrator or helpdesk operator.

Using F8 and cmtrace to open the \windows\temp\SMSTS.log file and found this error message...
Failed to resolve selected task sequence dependencies. Code(0x80040104)

Found this website and updated the distribution points so that the source version number would not be '1' and now the task sequence is working and drivers are installing.

More SCCM related posts

Friday, March 6, 2015

SCCM Task Sequence User Verification

We know that Config Manager's Task Sequences run with a system account and can only be advertised to Device collections.

What if we wanted only certain people to have permission to re-image their computer?

This script will record the logged in username via wmi as a Task Variable.
If that account is a member of a specific domain group then the 'ValidUser' Task Variable will be set as True.

You can then use that 'ValidUser' Task Variable to allow groups or other commands/applications to run.



To test the sequence with the msgbox dialogs you will need the ServiceUI.exe file from the Microsoft Development kit.

'Find Logged in user
'Version 1.60
on error resume next
Dim objNetwork, objDomain, oTaskSequence
'msgbox "Testing"
'Create Objects
Set objNetwork = CreateObject("Wscript.Network")
Set objDomain = GetObject("LDAP://RootDSE")
Set oTaskSequence = CreateObject ("Microsoft.SMS.TSEnvironment")

' Obtain user information.
'strUserName = objNetwork.UserName
strcomputer = "."

Set objWMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 
Set colSessions = objWMI.ExecQuery ("Select * from Win32_ComputerSystem",,48) 
For Each objItem in colSessions 
if objItem.Username <> "" then
strUserName = Replace(Lcase(objItem.UserName),"prairiesouth","")
oTaskSequence("UserName") = replace(strUserName,chr(92),"")
'msgbox strUserName
else
strUserName = objNetwork.UserName
end if
next

If not lcase(strUserName) = "system" then
'Verifies not the System account.
strDomain = objDomain.Get("dnsHostName")
Set objUser = GetObject("WinNT://" & strDomain & "/" & strUserName)
For Each strGroup in objUser.Groups
If Lcase(strGroup.Name) = "help desk end users" or Lcase(strGroup.Name) = "information technology department" then
strValid = 1
oTaskSequence("UserGroup") = strGroup.Name
'msgbox strGroup.Name
exit for
end if
Next
else
strValid = 0
end if

If strValid = 1 then
oTaskSequence("ValidUser") = "True"
'msgbox strValid
Else
oTaskSequence("ValidUser") = "False"
'msgbox strValid
end if


More SCCM related posts

Monday, February 2, 2015

SCCM 2012 Hard Drive with Bad Blocks Baseline


This PowerShell script will detect systems where the main hard drive is developing bad blocks.
Or as I call it, the "Click of Death".

Continuing with my previous posts on SCCM 2012 baselines items...
http://gmnetadmin.blogspot.ca/2015/01/using-sccm-2012-compliance-settings-to.html

Same steps as Option 2 in the above mentioned post but using the discovery script below...
Changes...
  1. You can add more If statements or expand it use ElseIf to record bad blocks from other hard drives.
  2. Or change the text in the If statement to just '*bad block*' to count all bad blocks event entries.


#Version 1.00 Feb 2, 2015
#SCCM Baseline for Bad Block on C Drive
$AllEvents = 0

#Default Event Logs
$Provider = "Disk"
$HourChange = 24 
$TimeNow = [DateTime]::Now
$TimeChange = [DateTime]::Now.AddHours(-$HourChange)

#Check Event Log for errors
$EventLogNames = "System"

ForEach ($log in $EventLogNames){
    $entry = " " 
    #Search Event Logs
    
    $LogEntry = Get-WinEvent -LogName $log | Where-Object {$_.timeCreated -ge $TimeChange -and $_.ProviderName -eq $Provider}
        ForEach ($entry in $LogEntry){
            $EvLevel = "Level: `t" + $entry.LevelDisplayName + $nl
            $EvEventID = "EventID: `t" + $entry.ID + $nl
            $EvMessage = "Message: `t" + $entry.Message
            $EvSource = "Source: `t" + $entry.ProviderName + $nl
            $EvTime = "Time Created: `t" + $entry.TimeCreated + $nl
            #write-host $EvLevel + $EvEventID + $EvMessage + $EvSource +$EvTime + $nl

           If ($EvMessage -like '*The device, \Device\Harddisk0\DR0, has a bad block*'){
                $AllEvents += 1
            }
                        
        }

}
write-host $AllEvents


More SCCM related posts

Thursday, January 29, 2015

SCCM 2012 Task Sequence for Failing Hard Drive

Now that you have collections created based S.M.A.R.T diagnostics or Disk event log entries baselines for failing hard drives... (See previous post)

We can create a custom Task Sequence to notify the user of the problem, when they log onto the computer.

Optionally, you could also deploy this as an available task sequence, for end users to manually check hard drive status.

Here are my suggestions for the task sequence...

Name: Hard Drive Diagnostic
Progress notification text: "Please submit a help desk ticket if the hard drive reports as failing."  (or use the standard "Running: <Task sequence name>")
Suppress task sequence notifications - Optional
Maximum run time: 5 minutes
Run on any platform.

Sequence of Tasks... (Keep in mind that the "Name" is what the end user will see on the screen)
  1. Set Task Sequence Variable
    1. Name: Testing hard drive health. Please wait.
    2. Variable: HD Failure
    3. Value: True
    4. Options:Add a WMI query Condition
      1. WMI Namespace: root\wmi
      2. WQL Query: select * from MSStorageDriver_FailurePredictStatus Where PredictFailure = True
  2. Group 1:
    1. Name: Hard Drive Diagnostic Finished
    2. Options: Add a Task Sequence Variable
      1. Variable: HD Failure
      2. Condition: Equals
      3. Value: True
    3. Run Command Line (Under Group 1)
      1. Name: The hard drive is failing
      2. Command line: ping 127.0.0.1 -n 30
        1. Should last about 30 seconds on the screen
    4. Run Command Line (Under Group 1)
      1. Name: We recommend replacing the hard drive.
      2. Command line: ping 127.0.0.1 -n 30
        1. Should last about 30 seconds on the screen
  3. Group 2:
    1. Name: Hard drive Diagnostics Finished
    2. Options: Add a Task Sequence Variable
      1. Variable: HD Failure
      2. Condition: Not Exists
    3. Run Command Line (Under Group 1)
      1. Name: Hard drive passed diagnostics
      2. Command line: ping 127.0.0.1 -n 10
        1. Should last about 10 seconds on the screen.

More SCCM related posts

Using SCCM 2012 Compliance Settings to Determine Hard Drive Health

As long as your computer has S.M.A.R.T hard drive diagnostic capabilities, the following can be used to track hard drive failures.

Configuration Item(s) in SCCM 2012.


Option 1 - Using WQL query

Name - Hard Drive Predictive Failure
Platforms - All (Although, if they are virtual machines this will not work.)

Settings -
  • Name: Storage Driver Failure Prediction
  • Type: WQL Query
  • Data: String
  • Namespace: root\wmi
  • Class: MSStorageDriver_FailurePredictStatus
  • Property:PredictFailure
Compliance Rules
  • Name: Possible Hard Drive Failure is True
    • I named it this to remind me that "False" is the result we want.
  • Rule: Storage Driver Failure Prediction Equals False
  • Noncompliance severity: Critical


 Option 2 - Using PowerShell script to read system event log

This option will read the System event log and count any 'disk' source logs that are not Information level. 
Note: This will include issues with temporarily attached external hard drives or USB drives.

Name - Event Log Disk Errors
Platforms - All (This will work for servers and virtual machines)
Settings
  • Name: Report disk errors found in Event Log
  • Type: Script
  • Discovery script (See end of post)
    • Counts the events and writes that value.
Compliance Rules
  • Name: Disk error count
  • Rule: Less than 1 (That's a number one)
  • Noncompliance severity: Critical
Now that you have created the Configuration Items, you can add (one or both) to a Configuration Baseline and deploy them to your collections.

Once deployed create collections for the non compliant systems and then use that information in reports for your help desk or create a Task sequence that alerts the end user that the hard drive is may be failing.

Here's the PowerShell script...
- Updated Feb 3, 2015 to exclude '*Device\Harddisk1\DR1*' event logs.

#Version 2.30 Feb 3, 2015
#Designed for SCCM Baseline
$AllEvents = 0

#Default Event Logs
$Provider = "disk"
$HourChange = 24 #Up to you how far back you want to go
$TimeNow = [DateTime]::Now
$TimeChange = [DateTime]::Now.AddHours(-$HourChange)

#Check Event Log for errors
$EventLogNames = "System"

ForEach ($log in $EventLogNames){
    $entry = " "
    #Search Event Logs
   
    $LogEntry = Get-WinEvent -LogName $log | Where-Object {$_.timeCreated -ge $TimeChange -and $_.ProviderName -contains $Provider -and ($_.LevelDisplayName -eq 'Warning' -or $_.LevelDisplayName -eq 'Error' -or $_.LevelDisplayName -eq 'Critical')}
        ForEach ($entry in $LogEntry){
            $EvLevel = "Level: `t" + $entry.LevelDisplayName + $nl
            $EvEventID = "EventID: `t" + $entry.ID + $nl
            $EvMessage = "Message: `t" + $entry.Message + $nl
            $EvSource = "Source: `t" + $entry.ProviderName + $nl
            $EvTime = "Time Created: `t" + $entry.TimeCreated + $nl
            #write-host $EvLevel + $EvEventID + $EvMessage + $EvSource +$EvTime + $nl


            #If ($entry.LevelDisplayName -eq "Critical" -or $entry.LevelDisplayName -eq "Warning" -or $entry.LevelDisplayName -eq "Error"){
            If ($EvMessage.tostring() -like '*Device\Harddisk1\DR1*'){
                #nothing
            }
            ElseIf ($entry.LevelDisplayName -eq "Critical" -or $entry.LevelDisplayName -eq "Warning" -or $entry.LevelDisplayName -eq "Error"){
             $AllEvents += 1
            }
                       
        }

}
write-host $AllEvents



More SCCM related posts

Monday, January 12, 2015

Cleaning up CCMCache folder in SCCM 2012

One thing I have found with System Center Configuration Manager is that the client cache folder can take up a lot space on the hard drive.  Filled with updates or applications source files that no longer are needed.

Only way is to set the Cache size to smaller value using a vbs script (or powershell) that runs these commands...
set oUIResManager = createobject("UIResource.UIResourceMgr")
set oCache=oUIResManager.GetCacheInfo()
oCache.TotalSize=4096

However, if you were to install a program like AutoCAD that requires more than 4GB of cache storage, it would likely fail.

The PowerShell script listed at the bottom of this post (based on Kaido Järvemets posting at http://cm12sdk.net) will clean up the "old" content in ccmcache based on the LastReferenced WMI information. 

The '$ReferenceAge.Days -gt 30' section deletes anything not referenced in the last 30 days. 

The "#Change Cache size" section is optional and only included for reference.

The 'stop-process $pid -Force' command however is required as there have been cases where the PowerShell script fails to exit.

It can be run on a remote computer using the psexec program from Sysinternals.

Example.
copy the file over to hard drive of the remote system.
psexec.exe -s \\computername powershell -noprofile -file "c:\clear ccmcache.ps1"

Planned implementation... (other than manually running).

Compliance item for harddrives with less than x amount of free space that remediates with a PowerShell command.
or
Task sequence that runs every # of days.

$Today = Get-Date
$CacheInfoQuery = Get-WmiObject -Namespace Root\ccm\SoftMgmtAgent -Class CacheInfoEx
ForEach ($Item in $CacheInfoQuery) {
    $LastDate = [Management.ManagementDateTimeConverter]::ToDateTime($Item.LastReferenced)
    $CacheElementID = "{" + $Item.CacheID + "}"
    $ReferenceAge = $Today - $LastDate
    $FolderLocation = $item.location
   
    if ($ReferenceAge.Days -gt 30) {
        #Write-Host Found $CacheElementID Last referenced $LastDate That is $ReferenceAge ago in $FolderLocation -ForegroundColor Red
        #Based on
http://cm12sdk.net/?p=1526
  Write-Host Too old, deleting folder $FolderLocation -ForegroundColor Red
        $CMObject = New-Object -ComObject "UIResource.UIResourceMgr"
        $CMCacheObjects = $CMObject.GetCacheInfo()
        $CMCacheObjects.DeleteCacheElement($CacheElementID)
        }
    #Remove number sign from the next 2 lines to allow for more information
    #else {
  #Write-Host $FolderLocation was last referenced $LastDate  That is $ReferenceAge days ago  -ForegroundColor Green}
    }
#Change Cache size
$CacheQuery = Get-WmiObject -Namespace ROOT\CCM\SoftMgmtAgent -Class CacheConfig
$CacheQuery.Size = 1000
$CacheQuery.Put()
#Restart CcmExec service
Restart-Service -Name CcmExec

stop-process $pid -Force


More SCCM related posts

Friday, August 8, 2014

SCCM 2012 Clients with Random Software Update Install Failures

Yesterday (Aug. 7, 2014) our SCCM clients started randomly failing to install locally published software updates.  Then even the new RDS servers started failing to install Windows updates via SCCM.  Yet for some reason other clients would install updates

First thought was WSUS certificate issues or Group Policy settings...  Strike one and two.

Try again in the morning...

Of course they didn't magically fix themselves over night (when does that ever happen).

This morning no clients would install any updates.

Looking at the windows update logs on the client machines found error about communication with the endpoint at http .... /clientwebservice/client.asmx.

So the WSUS server was the problem...

Sure enough Windows Update Server Service errors - Event ID in the Application log 12002,12012,12032,12042,12052,12072.

Started with restarting the WSUS service and Window Internal database service... Strike three.

Still not out... maybe I'll just stop using baseball references...

Started looking at the System event log and found that WAS or WsusPool had failed, so onto an IIS investigation. 

Restarting the WSUSPool, it look promising... Wsus was starting... no errors, but then failed after maxing out the CPU for about 5 minutes.

Found one website that said there was no solution, had to rebuild the server from scratch.  That would be bad... very bad... At that point I thought of restoring the system from the day before it failed.

Kept searching the internet for nearly 2 hours and then finally came up with this process...

1) IIsreset /noforce

2) Restarted the Windows Internal database service

3) Deleted the preferences in %appdata%\Microsoft\MMC for WSUS

4) Opened WSUS management console and waited...

Everything was back to normal and actually the final solution is not that complicated.

As with all solutions... there is no guarantee.  It worked for me, it may not work for you.


More SCCM related posts