Retrieving Credentials from the Secure Store Service

I hate that once you set the credentials in a Secure Store Service, you can’t see what they are in the GUI. So this script from Bob Guidinger is a fabulous solution. Thanks Bob! (I would have left a comment on your site, but it wouldn’t let me for some reason 😦 )

$context = Get-SPServiceContext -Site HTTPS://WEBAPP1

$provider = New-Object Microsoft.Office.SecureStoreService.Server.SecureStoreProvider
$provider.Context = $context

$marshal = [System.Runtime.InteropServices.Marshal]

try
{
    $apps = $provider.GetTargetApplications()
    foreach ($app in $apps)
    {
       Write-Output "`n$($app.Name)"
        Write-Output "$('-'*80)"
        try
        {
            $creds = $provider.GetCredentials($app.Name)
            foreach ($cred in $creds)
            {
                $ptr = $marshal::SecureStringToBSTR($cred.Credential)
                $str = $marshal::PtrToStringBSTR($ptr)

                Write-Output "$($cred.CredentialType): $($str)"
            }
        }
        catch
        {
            Write-Output "Error getting credentials!"
        }
        Write-Output "$('-'*80)"
    }
}
catch
{
    Write-Output "Error getting Target Applications."
}

$marshal::ZeroFreeBSTR($ptr)

Replace-RequestAccessEmail

Retrieve and update/change access request on all the sites/webs inside a web application that has my email as the access request. Some sites have a branch site managers email group that need to be used as well. Sourced from PowerShell script to update Access Request Email Address for multiple sites and webs and Windows PowerShell: Build a Better Function.

function Replace-RequestAccessEmail {
<#
.SYNOPSIS
Update Access Request containing Specified Email
.DESCRIPTION
Find all the Access Request Settings that have a specified email and replace it with either another account, another account and the Branch Site Managers email, or remove from string
.EXAMPLE
Replace the email address with a new address and the Branch Site Managers email
Replace-RequestAccessEmail -webapp "https://WEBAPP1" -email "Joe.Cool@email" -replace "SPADMIN@email" -SPSiteMgrs
.EXAMPLE
Removes the email address from the string
Replace-RequestAccessEmail -webapp "https://WEBAPP1" -email "Joe.Cool@email"
.PARAMETER webapp
Web Application to cycle through.
.PARAMETER email
Email in Access Request Setting to locate
.PARAMETER replace
(OPTIONAL) Email to use as replacement - leave off to have email removed from string.
.PARAMETER SPSiteMgrs
(OPTIONAL) Include to replace using Site Managers email based on Site Collection
#>
[CmdletBinding()]
param
(
[Microsoft.SharePoint.PowerShell.SPWebApplicationPipeBind]$webapp,
[string]$email,
[string]$replace,
[switch]$SPSiteMgrs
)
process {
$webapplication = Get-SPWebApplication -Identity $webapp
[string]$trimSites = $webapplication.URL
$trimSites = $trimSites + "sites/"
foreach($site in $webapplication.Sites)
{
foreach($web in $site.AllWebs)
{
if ($web.HasUniquePerm -and $web.RequestAccessEnabled)
{
if ($web.RequestAccessEmail -like "*$email*")
{
$siteCollection = $web.Site | %{$_.URL}
$siteCollection = $siteCollection.TrimStart($trimSites)
Write-Host "Site Collection: " $siteCollection
Write-Host "On Web" $web.Title ", URL" $web.URL
Write-Host "`tAccess requests go to :" $web.RequestAccessEmail
If($SPSiteMgrs.IsPresent)
{
If(!$replace.IsPresent)
{
#Default with Admin Account
$replace = "SPADMIN@EMAIL"
}
switch ($siteCollection)
{
"BRANCH_A" {$requestAccessEmail = "$replace; BRANCH_A.SPSiteMgr@EMAIL"}
"BRANCH_B" {$requestAccessEmail = "$replace; BRANCH_B.SPSiteMgr@EMAIL"}
"BRANCH_C" {$requestAccessEmail = "$replace; BRANCH_C.SPSiteMgr@EMAIL"}
default {$requestAccessEmail = "$replace"}
}
} else
{
$requestAccessEmail = $web.RequestAccessEmail
$reqeustAccessEmail = $requestAccessEmail.ToLower()
$email = $email.ToLower()
$requestAccessEmail = $requestAccessEmail.Replace($email,$replace)
}
# If the Request Access Email would be blank, set to SharePoint Admins Email
If ($requestAccessEmail -eq "")
{
$requestAccessEmail = "SPADMIN@EMAIL"
}
Write-Host "`t***Will Update Request Access Email to: "$requestAccessEmail "***"
$web.RequestAccessEmail = $requestAccessEmail
$web.Update()
}
}
} #end ForEachWeb
#Dispose of the site object
$site.Dispose()
} #end ForEachSite
} #end Process
} #endFunction

SharePoint Red X for Images

I use images in wiki pages all the time. Suddenly, when I went to my wiki posts, I was seeing a red X instead of my images. I had a co-worker browse the site and they were able to see the image. Then I discovered, if I changed my host file to point from one Web Front End to the other, one WFE would give me images the other wouldn’t.

WFE 1

WFE 2

These images are in the content database. There should be no reason for one WFE to serve the image while the other doesn’t. Except, we use  BLOB caching. I went into the offending server’s blob cache directory and found the image files (do not just delete the root folder!) and deleted them. Alternately, I could have flushed the blob cache. After an IISRESET, the WFE served up the images again.

I needed to delete the Temporary Internet files on my local machine as well to once again see the images.

Get AD Group Member Users

Script pulls data from a group on the Exchange Domain and looks up user information in the Users domain. User name and email address are output to CSV file.

# -----------------------------------------------------------------------------
# Script: Get-ADGroupMemberUsers.ps1
# Author: Heather Van De Sande
# Date: 01/08/2013
# Keywords: PowerShell, Active Directory
# Comments: Recursively pull users from an Exchange Group and retrieve User information
#            from User Domain
# -----------------------------------------------------------------------------
Import-module ActiveDirectory
# Useful for finding the server information for below variables
#Get-ADDomain -Identity "exch.corp.xx.com"
#Get-ADDomain -Identity "user.corp.xx.com" 
$strExchangeServer = "EXCHSV-DC1.EXCH.CORP.XX.COM"
$strUserServer = "USERSV-DC1.USER.CORP.XX.COM"
$strOutPutCSVFile = "C:\Temp\HR_All_Staff.csv"
$strParentGroupName = "HR All Staff"

$strParentGroupID = Get-ADGroup -Filter {Name -eq $strParentGroupName} -Server $strExchangeServer | Select DistinguishedName
$strMembers = Get-ADGroupMember -Identity $strParentGroupID.DistinguishedName -Server $strExchangeServer -Recursive
$strUsers = @()
foreach ($strMember in $strMembers){
    $strUsers += Get-ADUser -Identity $strMember.DistinguishedName -Server $strUserServer -Properties DisplayName,EmailAddress | Select DisplayName,EmailAddress
}
$strUsers | Export-Csv -Path $strOutPutCSVFile -NoTypeInformation

Copy Attachments between Lists

This is probably not the most elegant solution, but since the lists in question only had 65 items with attachments, coming up with an elegant code solution would take more time than this “brute” method.

Using the Designer, the attachments can be found in the All Files > Lists > LISTNAME > Attachments folder. The folders are by the item ID.

I created a spreadsheet to correlate the Item ID in the old list to the Item ID in the new list. So I would know that the attachment for Joe Cool in the first list (Item ID 12) would now be Item ID 76 in the new list. Now for the brute method: Open Designer for both lists in two windows. In the new list, if it doesn’t already exist, create a folder with the name of the new item number (in this example it’s 76). Then you can just drag and drop the documents between folders.

Copy Users between SharePoint Groups

I had a situation where I needed to create a new site and copy over specific groups from the old site. The groups had already been created using another script. Thanks to Justin Kobel (the smartest person I personally know) for helping me with this script.

$allGroups = (“Eastern Mountain Contributors”, “Eastern Mountain Visitors”, “Salt River Contributors”, “Salt River Visitors”)
$fromWeb = ‘https://WEBAPP/sites/SITEA&#8217;
$toWeb = ‘https://WEBAPP/sites/SITEB&#8217;
foreach ($group in $allGroups){
Write-Host “Group: $group”
$users = Get-SPUser -Web $fromWeb -Group $group | Select-Object LoginName
foreach ($user in $users){
New-SPUser –UserAlias $user.LoginName –web $toWeb
Set-SPUser -Identity $user.LoginName -Group $group -Web $toWeb
}
}