Thursday, February 23, 2017

SCCM Copy Random members to a collection powershell script

This script will take a given source SCCM collection and randomly grab a percentage of that collection and add it to a destination collection


cd "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
Import-Module .\ConfigurationManager.psd1
cd CAS:

#$SrcCollectionName = 'source collection name'
#$DstCollectionName = 'destination collection name'


$SiteServer = 'siteservername'
$SiteCode = 'threelettersitecode'
$PercentToGet = 23
$UpdateCollectionMembership = $true

#uncomment this if you want/need to prompt for credentials
#$cred = Get-credential

[System.Collections.ArrayList]$DstItemList = @()
[System.Collections.ArrayList]$SrcItemList = @()

write-output "Going to clear out direct members of $DstCollectionName and then randomly collect $PercentToGet percent of the members of $SrcCollectionName and add them to $DstCollectionName "

#Gather collection ID and list of Items in src and dst collections
$SrcCollectionID = Get-CMDeviceCollection -Name $SrcCollectionName | Select CollectionID
$DstCollectionID = Get-CMDeviceCollection -Name $DstCollectionName | Select CollectionID
$SrcItemList = @(Get-CMDevice -CollectionId $SrcCollectionID.CollectionID | Select -Property Name, ResourceID)
$DstItemList = @(Get-CMDevice -CollectionId $DstCollectionID.CollectionID | Select -Property Name, ResourceID)

#clear out existing destination collection members
ForEach ($DstItem in $DstItemList)
 {
    $name = $DstItem.name
    $ID = $DstItem.ResourceID
    write-output "Removing $name with ID $ID from collection $DstCollectionName"
    Remove-CMDeviceCollectionDirectMembershipRule -CollectionName $DstCollectionName -ResourceId $ID -force
    }

#run update membership to update destination collection 
write-output "Triggering update membership for collection $DstCollectionName "
    $ID = $DstCollectionID.CollectionID
    Invoke-WmiMethod -Path "ROOT\SMS\Site_$($SiteCode):SMS_Collection.CollectionId='$ID'" -Name RequestRefresh -ComputerName $SiteServer 

#wait 4 minutes for the collection to update
write-output "Waiting 4 minutes for the update membership for collection $DstCollectionName "
start-sleep -s 240
 
#run update membership to update source collection as source collection may exclude previous destination collection
#this may not be necessary?
write-output "Triggering update membership for collection $SrcCollectionName "
    $ID = $SrcCollectionID.CollectionID
    Invoke-WmiMethod -Path "ROOT\SMS\Site_$($SiteCode):SMS_Collection.CollectionId='$ID'" -Name RequestRefresh -ComputerName $SiteServer 

#wait 4 minutes for the collection to update
write-output "Waiting 4 minutes for the update membership for collection $SrcCollectionName "
start-sleep -s 240

#Refresh contents for source collection arraylist
$SrcItemList = @(Get-CMDevice -CollectionId $SrcCollectionID.CollectionID | Select -Property Name, ResourceID)
 
#clear list of destination items to be used for input
Clear-variable DstItemList
[System.Collections.ArrayList]$DstItemList = @()

#Calc number of destination-bound items that we want to end up with
$DstNumberOfItems = ($SrcItemList).count * ($PercentToGet / 100)
$DstNumberOfItems = [math]::truncate($DstNumberOfItems)

write-output "Going to search for and add $PercentToGet Percent - $DstNumberOfItems items - to collection $DstCollectionName "

#go through source list and pick random items till we have enough
While ($NumberOfItems -ne $DstNumberOfItems)
 {
 $PickedItem = ($SrcItemList | Get-Random)
    $DstItemList += $PickedItem
 $SrcItemList.remove($PickedItem)
    $NumberOfItems = $DstItemList.count
 }

#add items to destination collection list
ForEach ($DstItem in $DstItemList)
 {
    $name = $DstItem.name
    $ID = $DstItem.ResourceID
    write-output "Adding $name with ID $ID to collection $DstCollectionName "
 Add-CMDeviceCollectionDirectMembershipRule -CollectionName $DstCollectionName -ResourceId $ID
 }

# trigger update collection membership if enabled in script
# this portion of the script is from:
# https://www.petervanderwoude.nl/post/update-collection-membership-in-configmgr-2012-via-powershell/

If ($UpdateCollectionMembership)
    {
 write-output "Triggering update membership for collection $DstCollectionName "
    $ID = $DstCollectionID.CollectionID
    Invoke-WmiMethod -Path "ROOT\SMS\Site_$($SiteCode):SMS_Collection.CollectionId='$ID'" -Name RequestRefresh -ComputerName $SiteServer
 
 #wait 4 minutes for the collection to update
 write-output "Waiting 4 minutes for the update membership for collection $DstCollectionName "
 start-sleep -s 240
 
    write-output "Triggering update membership for collection $SrcCollectionName "
    $ID = $SrcCollectionID.CollectionID
    Invoke-WmiMethod -Path "ROOT\SMS\Site_$($SiteCode):SMS_Collection.CollectionId='$ID'" -Name RequestRefresh -ComputerName $SiteServer


    }

Wednesday, February 1, 2017

Expired Files Deletion Script

This is a script that checks through a list of folders based on a standard set of folders at multiple sites and purges old files. Nothing too fancy here.

# Script to look at folders and delete old items

$logfile = "c:\folder\logfilename.txt"
$date = get-date
$allfilestodelete

# Set variables for the timeframes used to determine stale files
$1wlimit = ($date).AddDays(-8)
$1mlimit = ($date).AddDays(-32)
$6mlimit = ($date).AddDays(-187)
$1ylimit = ($date).AddDays(-366)

# Test Log File Path, create a log file if it doesn't exist
    $logfilePath = (Test-Path $logFile)
    if (($logFilePath) -ne "True")
    {
        # Create File
        New-Item $logfile -ItemType File
        Add-Content $logfile "Log file created $date "
    }

Add-Content $logfile "AutoDelete script starting to run on: $(get-date) "

# This is the prefixes that we will use to mate with the suffixes to set all the folders that we are looking at
$siteuncprefixes = "\\server1\share\","\\server2\share\","\\server3\share\"

# These are the suffixes, so we will end up with \\server1\share\foldername\1weekfolder, 
# \\server1\share\foldername\1monthfolder and so on...
$1wuncsuffix = "foldername\1weekfolder"
$1muncsuffix = "foldername\1monthfolder"
$6muncsuffix = "foldername\6monthsfolder"
$1yuncsuffix = "foldername\1yearfolder"

# Main loop to look at each site's folders and check for stale files
foreach ($site in $siteuncprefixes){

        Add-Content $logfile "Scanning $site for expired files at $(get-date) "

  $currentpath = $site + $1wuncsuffix
        #Add-Content $logfile "Scanning $currentpath for 1 week expired files at $(get-date) "
  $1wfilestodelete = Get-ChildItem -Path $currentpath -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.lastwriteTime -lt $1wlimit -and $_.creationtime -lt $1wlimit }
  
  $currentpath = $site + $1muncsuffix
        #Add-Content $logfile "Scanning $currentpath for 1 month expired files at $(get-date) "
  $1mfilestodelete = Get-ChildItem -Path $currentpath -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.lastwriteTime -lt $1mlimit -and $_.creationtime -lt $1wlimit }

  $currentpath = $site + $6muncsuffix
        #Add-Content $logfile "Scanning $currentpath for 6 month expired files at $(get-date) "
  $1mfilestodelete = Get-ChildItem -Path $currentpath -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.lastwriteTime -lt $6mlimit -and $_.creationtime -lt $1wlimit }
  
  $currentpath = $site + $1yuncsuffix
        #Add-Content $logfile "Scanning $currentpath for 1 year expired files at $(get-date) "
  $1yfilestodelete = Get-ChildItem -Path $currentpath -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.lastwriteTime -lt $1ylimit -and $_.creationtime -lt $1wlimit }

  $allfilestodelete = $allfilestodelete + $1wfilestodelete + $1mfilestodelete + $6mfilestodelete + $1yfilestodelete

}

# Count the total number of files and write to the log file
$count = $allfilestodelete.fullname.count
Add-Content $logfile "Found $count expired files to delete at all sites: "

# Write to the log all items to be deleted
$allfilestodelete | select-object -property fullname, lastwritetime | Ft -autosize | out-string -width 4096 | add-content $logfile

# Delete expired files
$allfilestodelete.fullname | Remove-Item -Force

# Write to the log file that it's done
Add-Content $logfile "AutoDelete script finished runing on: $(get-date) "