SharePoint 2010 Service Application Groups

IMHO, Microsoft obviously rushed the release of SharePoint 2010 and there are quite a few unfinished areas at the very least in the UI.

Try to create more than one custom Service Application Group in Central admin for example. You just cant do it, as far as I can see.

The good news is, powershell SharePoint CmdLets allow you to fill this gap. I crafted this in a bit of a hurry, but it does the job.

$PSSnapin = Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
 
 
$AppProxyGroupFriendlyName = "New Custom Proxy group"
$ProxyDisplayNamesToAddToGroup = @(
                    "State Service Application Proxy",
                    "MyApp Taxonomy",
                    "Secure Store Service Proxy",
                    "Web Analytics Service Application",
                    "Application Discovery and Load Balancer Service Application Proxy_aa187b7a-cc28-448a-b232-4c9f0713d0bb",
                    "WSS Usage Application"
                    )
 
# Grab our new ApplicationProxyGroup
#
$appProxyGroup = get-SPServiceApplicationProxyGroup | where-object {$_.FriendlyName -eq $AppProxyGroupFriendlyName}
 
if(-not $appProxyGroup) {
    write-host "Creating" $AppProxyGroupFriendlyName
    New-SPServiceApplicationProxyGroup -Name $AppProxyGroupFriendlyName
}
 
 
 
# Get each of the application proxies to be used by this group
#
$ProxyDisplayNamesToAddToGroup | % {
    $thisProxy = $_
    $appProxy = Get-SPServiceApplicationProxy | where-object {$_.DisplayName -eq $thisProxy}
 
    if($appProxyGroup.Contains($appProxy)) {
        # Already present
        write-host $thisProxy "already present"
    }
    else {
        write-host "Adding" $thisProxy
        $appProxyGroup.Add($appProxy)
    }
}
 
# Show the proxies in the new group
#
$appProxyGroup = Get-SPServiceApplicationProxyGroup -Identity $AppProxyGroupFriendlyName
$appProxyGroup.DefaultProxies | Format-list -Property DisplayName

Script a backup of selected datasources Microsoft DPM 2010

Can be hard to work out this one, here is what worked for us.  Our requirement was to back up a selection of datasources from varying protection groups on a daily cycle.  The script below works the way we want, it is modified from a snipet we found ont there on google.

#####################################################################
# Any script which includes the next two lines can run DPM Scripts
# probably need to be running elevated though ...
add-pssnapin -name Microsoft.DataProtectionManager.PowerShell -ErrorAction SilentlyContinue
$Error.Clear()
 
# For try catch logic to work the way I expect
$errorActionPreference = 'Stop'
 
#####################################################################
 
#
# Variables you need to review
#
#####################################################################
# 
# The Dpm server we want to work with
#
$DpmServer="DPM2010.DOMAIN.COM" # enter here the name of your DPM server
$storage="Disk" # choose from Disk or Tape
$protectionType="LongTerm" # choose from LongTerm or ShortTerm
#
#
#
#####################################################################
 
function DoTheBackups([string] $dpmServer, [string] $pg, [string] $computerName,[string] $ds)
{
   $mypg = get-protectiongroup -dpmservername $dpmServer | where {$_.FriendlyName -ieq $pg}
 
   $myds = get-datasource -protectiongroup $mypg |
where {$_.Name -ieq $ds -and $_.ProductionServerName -ieq $computerName }
 
   if($myds) {
 
     write-host "`n`n" "Create recovery point for '$ds' on '$computername' to '$storage'"
 
     if ($storage -ieq "Tape") {
       try {
         $myjob = new-recoverypoint -datasource $myds -Tape -ProtectionType $protectionType
       }
       catch {
         write-host "`t" $_.Exception.Message
       }
   }
   else {
     try {
       $myjob = new-recoverypoint -datasource $myds -Disk -DiskRecoveryPointOption WithSynchronize
     }
     catch {
       write-host "`t" $_.Exception.Message
     }
   }
 
   if ($myJob) {
     $jobtype = $myjob.jobtype 
     write-host "`t`t" "Starting the process of $jobtype for tape backup"
 
     while (! $myjob.hascompleted ) 
     {
       write-host "`t`t`t" $myjob.Status
       start-sleep 5
     }
 
     if($myjob.Status -ne "Succeeded") 
     { 
       write-error "`t`t" "Job Failed" $pg $ds 
     }
     Else {
       Write-host "`t`t" "Job Succeeded" $pg $ds 
     }
  }
  else {
   write-host "Error creating new recovery point for '$ds' on '$computerName'"
  }
}
else {
   write-host "Data source '$ds' on protectiongroup '$pg' not found or not appropriate"
}
 
}
 
#
# Define what we want this script to do
#
#####################################################################
function main()
{
connect-dpmserver $DpmServer | out-null
#
# Add lines here for each datasource you want to backup
#
DoTheBackups -dpmserver $DpmServer -pg "PG-Desktops" -computerName "Parsley.domain.com" -ds "User data"
DoTheBackups -dpmserver $DpmServer -pg "Protection Group 2 - XPTESTPC1" -computerName "XPTESTPC1.domain.com" -ds "C:\"
 
disconnect-dpmserver $DpmServer | out-null
}
#####################################################################
 
#
# Run the main script
#
#####################################################################
main
#####################################################################

Another powershell script, Information management policy via script to content types

This was hard to trackdown so I thought I would put it here for others to use.  Post the script below into a file e.g. SetPolicy.ps1
Export a policy from Site collection to an xml file, from say, your dev server, put the xml file and the script into the same folder on say, your production server

Fire up a powershell window as admin and run the script.

# SET THESE
#
$PortalUrl="http://server/webapp"
$manifestXml = get-content "Next_Update_Due_Policy.Xml"
# The manifest contains an ID
 
$policyFeatureId="af5f1adb-dca9-490a-9bae-b5f6238699c7"
# This is the ID from the manifest
 
#
# #####################################################
 
$wa = Get-SPWebApplication $Portalurl
$site = Get-SPSite -Identity $portalUrl
 
$contentTypes = @()
$contentTypes += "Content type 1"
$contentTypes += "Content type 2"
$contentTypes += "Content type 3"
 
# Create site collection policy
# Import XML into it
#
try {
[Microsoft.Office.RecordsManagement.InformationPolicy.PolicyCollection]::Add($site, $manifestXml)
write-host "Created site collection policy"
}
catch {
write-host $_.Exception.Message
}
$policyCatalog = new-object Microsoft.Office.RecordsManagement.InformationPolicy.PolicyCatalog($site)
$SiteCollpolicy = $policyCatalog.PolicyList[$policyFeatureId]
 
# Bind each content type to the policy we just created
#
$contentTypes % {
$thisContentType = $_
Write-host "Bind policy to" $thisContentType
$ctype = $site.RootWeb.ContentTypes[$thisCOntentType]
try {
[Microsoft.Office.RecordsManagement.InformationPolicy.Policy]::CreatePolicy($ctype, $SiteCollpolicy);
}
catch {
write-host $_.Exception.Message
}
}
$site.Dispose()
Write-host "Run timer jobs"
Get-SPTimerJob ?{$_.Name -match "PolicyUpdateProcessing"} ?{$_.Parent -eq $wa} Start-SPTimerJob
Get-SPTimerJob ?{$_.Name -match "DocIdEnable"} ?{$_.Parent -eq $wa} Start-SPTimerJob
Get-SPTimerJob ?{$_.Name -match "DocIdAssignment"} ?{$_.Parent -eq $wa} Start-SPTimerJob

So whats happening then;

  • Read the exported policy xml into a variable
  • Add the previously exported policy xml to a new SiteCollection policy
  • Get the site collection policy catalog
  • From there get the policy we just Added
  • Now for each content type in the earlier created array of content type names
  • Bind the policy to the content type
  • Finally run a few chosen timer jobs to make it all hang together

Enjoy.

Script the DCOM fix in SharePoint

I got fed up with fixing this so I put together a powershell script to sort
it all out for me.

You will need to install SetAcl and DcomPerm.

Paste the script below into a file e.g. FixDcom.ps1
Fire up a powershell window (As Administrator) and execute the script

As ever, all at your own risk.

$PortalSiteOwner="domain\username"
$PortalAccount="domain\username"
$SPFarmAccount="domain\username"
 
$SetAcl="WhereYouInstalledSetAcl.exe"
$backupFileName="$here\RegPerms-Dconfig.bak"
$RegKeyOwner="$PortalSiteOwner"
 
# SETACL
#
 
# Backup the existing perms
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}",
 "-ot", "reg", "-actn", "list", "-lst", "f:sddl;w:d,s,o,g;i:y;s:b",
 "-bckp", "$backupFileName"
& $SetAcl $args
 
 
 
 
# Take ownership
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "setowner", "-ownr", "n:$RegKeyOwner;s:n"
& $SetAcl $args
 
# Assign full control
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "ace", "-ace", "n:$RegKeyOwner;p:full"
& $SetAcl $args
 
# DCOMFIG
#
 
Write-Host "THIS WILL FAIL IF YOU DO NOT HAVE REGISTRY ACCESS TO"
Write-Host "HKCR:\AppID\{61738644-F196-11D0-9953-00C04FD919C1} REGISTRY KEY" 
 
$argz = @( "-al", "{61738644-F196-11D0-9953-00C04FD919C1}", "set" ,
 "__USER__HERE__" ,"permit", "level:l")
 
$argz[3] = "$SpfarmAccount"
& "$AssetsPath\dcomperm.exe" $argz
 
$argz[3] = "$PortalAccount"
& "$AssetsPath\dcomperm.exe" $argz
 
# Restore original permissions
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "restore", "-bckp", "$backupFileName"
& $SetAcl $args

So this is what it is doing;

  • Use SetAcl to make a backup of the registry permissions on the …919C1 registry key
  • Use SetAcl to take ownership of the …919C1 registry key
  • Use SetAcl to assign full control of the …919C1 registry key
  • Use Dcomperm to Grant local activation to SP Farm account
  • Use Dcomperm to grant loccal activation to Portal app pool account
  • Use SetAcl to restore the originla permissions to the … 919C1 registry key

Enjoy.

>Nice powershell to display Managed, crawled and mapped metadata properties in SharePoint 2010

>

So on your SharePoint server, paste the script below into powershell_ISE or a script file e.g. PropListing.ps1 and edit the $searchAppName variable to be the exact name of your search application.
image

Run the script and the output should explain itself.

image

$PSSnapin = Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$searchAppName = “Your name Enterprise Search Service Application”

$app = Get-SPEnterpriseSearchServiceApplication -identity $searchAppName

$cats = Get-SPEnterpriseSearchMetadataCategory -SearchApplication $app
$ManagedMapped = @{}

Write-Host “Categories”
$cats | % {
$cat = $_
Write-host “`t” $cat.name

$crawledprops = $cat.GetAllCrawledProperties()
Write-host “`t`t” “Crawled properties”
$crawledprops | % {
$crawledProperty = $_
Write-Host “`t`t`t” $crawledProperty.name

$mappedManagedProps = $crawledProperty.GetMappedManagedProperties()

if($mappedManagedProps.Count -gt 0) {
Write-Host “`t`t`t`t” “Mapped to managed property(s)”
$mappedManagedProps | % {
$mappedManagedProperty = $_
Write-Host “`t`t`t`t`t” $mappedManagedProperty.name
if(-not $ManagedMapped.ContainsKey($mappedManagedProperty.name)) {
# record this prop for later
$ManagedMapped.Add($mappedManagedProperty.name,$mappedManagedProperty)
}
}
}
}

}
# Find unmapped managed properties
Write-host “Listing of unMapped Managed properties”
Write-host “————————————–”

$allManProps = $app.GetManagedProperties()
$allManProps | % {
$allprop = $_
if(-not $ManagedMapped.ContainsKey($allprop.name)) {
Write-host “`t” $allProp.name
}
}

 

No warranties implied or otherwise Smile

>Generating an AD hiararchy from powershell

>I had occasion to create an AD hiarachy via script and felt it would be a good place to start my powershell learning curve. What I produced, while not the most elegant code in the powershell world, none the less does what it says on the tin. You may find it usefull.

No warranty whatsoever of course 🙂 As ever Im happy to mail the code to interested people, just mail Me

Xml file describing the hiarachy to create . This xml file describes one OU, two USERS and two GROUPS. It creates the OU and then the GROUPS then the USERS then adds Groups to groups and users to groups.

<xml>
<!–
This section describes the Active directory domain and a few locations
–>
<ad>
<domain path=”LDAP://ou=SomeOuToStartIn,dc=domain,dc=com” />
</ad>

<!–
This section lists any OU’s to be created
–>
<ous>
<ou name=”testingou” ouadspath=”LDAP://ou=SomeOuToStartIn,dc=domain,dc=com” />
</ous>

<!–
This section describes users and groups to create
and the groups users and or groups should be added to
–>
<accounts>

<group name=”group1″ grouppath=”LDAP://ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
<group name=”group2″ grouppath=”LDAP://ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />

<user name=”testinguser1″ password=”p@55w0rd0″ userpath=”LDAP://ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
<user name=”testinguser2″ password=”p@55w0rd1″ userpath=”LDAP://ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />

<membership location=”LDAP://cn=group2,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com”>
<memberof>
<group location=”LDAP://cn=group1,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
</memberof>
</membership>

<membership location=”LDAP://cn=testinguser1,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” >
<memberof>
<group location=”LDAP://cn=group2,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
</memberof>
</membership>

<membership location=”LDAP://cn=testinguser2,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com”>
<memberof>
<group location=”LDAP://cn=group1,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
<group location=”LDAP://cn=group2,ou=testingou,ou=SomeOuToStartIn,dc=domain,dc=com” />
</memberof>
</membership>

</accounts>
</xml>

Powershell script to create the hiarachy


## script to create ad OU’s, Groups and users
# and to add those users to predefined groups
#
#
Param ( $Filename = “accounts.xml”)

function reportStatus([string] $status)
{ Write-Debug -message $status}

function createOu{
param([string]$ouname, [string]$ouadspath)
Write-Debug -message $ouname
Write-Debug -message $ouadspath
$objDomain = [ADSI]$ouadspath
$objOU = $objDomain.Create(“organizationalUnit”, “ou=” + $ouname)
$objOU.SetInfo()
}

function createGroup{
param([string]$acname, [string]$GroupPath)
Write-Debug -message $acname;
Write-Debug -message $GroupPath;
$objOU = [ADSI]$GroupPath
$objGroup = $objOU.Create(“group”, “cn=” + $acname)
$objGroup.Put(“sAMAccountName”, $acname)
$objGroup.SetInfo()
}

function createUser{
param([string]$acname, [string]$UserPath, [string] $password)
Write-Debug -message $acname;
Write-Debug -message $UserPath;
$ADs_UF_NORMAL_ACCOUNT = 512
$objOU = [ADSI]$UserPath
$objUser = $objOU.Create(“user”, “cn=” + $acname)
$objUser.Put(“sAMAccountName”, $acname)
$objUser.SetInfo()
$objUser.SetPassword($password)
$objUser.SetInfo()
$objUser.userAccountControl = $ADs_UF_NORMAL_ACCOUNT
$objUser.SetInfo()
}

function addAccountToGroup([string] $aclocation, [string] $glocation){
Write-Debug -Message “$aclocation $glocation”
$group = [ADSI]$glocation
$account = [ADSI]$aclocation
$group.Add($account.psbase.Path)
$group.SetInfo()
}

# main code entry point
#
# read the xml file containing account information
#
$xml = new-object System.Xml.XmlDocument
$xml.Load($Filename)
# the AD node has the LDAP path we will connect to
#
$AdNode = $xml.SelectSingleNode(“xml/ad/domain”)
if($AdNode -eq $null) { return }

$AdPath = $AdNode.GetAttribute(“path”)
reportStatus (“Connecting to : ” + $AdPath)
# Create any required OU’s
#
$OuNode = $AdNode = $xml.SelectSingleNode(“xml/ous”)
if($OuNode -eq $null) { return }

reportStatus(“Create OU’s”)
foreach($ou in $OuNode.SelectNodes(“ou”)){
$ouname = $Ou.GetAttribute(“name”)
$ouadspath = $Ou.GetAttribute(“ouadspath”)
createOu $ouname $ouadspath
}

# Account creation
#
$AcNode = $AdNode = $xml.SelectSingleNode(“xml/accounts”)
if($AcNode -eq $null) { return }

# Process groups
#
reportStatus(“Create Accounts: Groups”)
foreach($ac in $AcNode.SelectNodes(“group”)){
$acname = $ac.GetAttribute(“name”)
$GroupPath = $ac.GetAttribute(“grouppath”)
createGroup $acname $GroupPath
}

# Process Users
#
reportStatus(“Create Accounts: User”)
foreach($ac in $AcNode.SelectNodes(“user”)){
$acname = $ac.GetAttribute(“name”)
$UserPath = $ac.GetAttribute(“userpath”)
$Password = $ac.GetAttribute(“password”)
createUser $acname $UserPath $password
}

# Process memberships
#
reportStatus(“Create Memberships”)
$membnode = $xml.SelectNodes(“xml/accounts/membership”)
if($membnode -eq $null) { return }

foreach($ac in $membnode){
$aclocation = $ac.GetAttribute(“location”)
$gpsnode = $ac.SelectSingleNode(“memberof”)

foreach($grp in $gpsnode.SelectNodes(“group”)) {
$glocation = $grp.GetAttribute(“location”)
addAccountToGroup $aclocation $glocation
}
}