Grant Permissions to SharePoint List Items Using PowerShell

On our farm we manage a list of user profiles in a sharepoint list. Each of the list items (the profiles) have unique permissions. Each user has contribute rights to their own profile and all the profiles are assigned a group called "AllUsers", that every user belongs too, with READ permissions so other users may view it.

We discovered that a small percentage of the user profiles did not give the group "AllUsers" READ permissions. We discovered the cause of this issue was long since fixed but we needed a way to programmaticaly give each of these profiles the correct permissions. This is the PowerShell script I wrote in order to do this. You may adapt it to your needs.

# This script goes through all the items in a list, 
# if the list item does not inherit permissions and does not have the desired role assignment,
# it will then give the item that desired assignment
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
$url = "http://weburlhere"
$listName = "ListName"
$permissionLevel = "Read"
$groupName = "domainGroupName"
$web = Get-SPWeb $url
$list = $web.Lists[$listName]
$group = $web.EnsureUser($groupName) # I am using a group in this case but you can use a specific user instead.
$role = $web.RoleDefinitions[$permissionLevel]
$assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($group)
$assignment.RoleDefinitionBindings.Add($role)
$count = 0
foreach ($item in $list.Items) {
    # Check to see if the item inherits permissions
    if ($item.HasUniqueRoleAssignments -eq $FALSE) {
        Write-Output ("ID: " + $item.ID.ToString() +" | No change, permissions are inherited.")
    }
    elseif(($item.RoleAssignments | where{$_.Member.Name -eq $groupName} | Measure).Count -eq 0) {
        # Group isn't already assigned, so add the assignment.
        $item.RoleAssignments.Add($assignment)
        $item.Update()
        Write-Output ("ID: " + $item.ID.ToString() + " | " + $permissionLevel + " Permission GRANTED.")
        $count++
    }
}
$web.Dispose();
Write-Output ("Updated $count Items.")

I assume some of you may only want to add permissions to one list item instead of looping through all the list items in a list. This is a slimmed down version on how you would do that:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
$url = "http://weburlhere"
$listName = "ListName"
$permissionLevel = "Read"
$groupName = "domainGroupName"
$web = Get-SPWeb $url
$list = $web.Lists[$listName]
$group = $web.EnsureUser($groupName) # I am using a group in this case but you can use a specific user instead.
$role = $web.RoleDefinitions[$permissionLevel]
$assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($group)
$assignment.RoleDefinitionBindings.Add($role)
$items = $listItems | where {$_['ID'] -eq 1} # $items will only contain 1 item if 'ID' or whatever column you are searching for is unique
foreach ($item in $items) {
	$item.RoleAssignments.Add($assignment)
	$item.Update()     
}
$web.Dispose()