A note on the scripts in this blog

Featured

When this Blog was migrated from Windows Live to WordPress some things did not translate well or at all. The most noticeable are “\”; that’s the “\” as in c:\ or in C:\Scripts\PS1. which just isn’t there anymore. They also put “the and sign” nbsp; in the place of spaces and tabs and `< and `> with the “and sign” gt and the “and sign” lt.

I don’t know why or how, but if you copy these scripts, you will need to check these very closely.

Thank you for your support.

Get SharePoint Site Owner and/or Site Admin

One of the things you might have to do as an admin in a large organization is to find out if a particular user is a SharePoint Site Owner and Admin. I had to do this when a long time SharePoint developer left the company.

They are not the same thing, no matter what you may read.
You can find a discusion on the difference here:

http://techtrainingnotes.blogspot.com/2008/03/sharepoint-site-administrator-vs-site.html

This script will sort through all the owners and members of the site admin group on a given server. It will locate your user if they are an Owner or an admin on any SharePoint site on that server.

It uses the SharePoint snapin and at least where I work, I need to run it as the Farm Administrator.
The output is a tab delimited file that opens up nicely in Excel.

 


Function SiteAdmin($site){
$siteUrl = $site.url
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication

foreach($site in $spWebApp.Sites)
{
    foreach($siteAdmin in $site.RootWeb.SiteAdministrators | where {$_.LoginName -Like $user})
		{
	  Add-Content -Path $strPath "`t`t$($siteAdmin.ParentWeb.Url) `t $($siteAdmin.DisplayName) `t $($siteAdmin.LoginName)"
		}
	}
}

Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
$user = Read-Host "Input user name or part thereof to find [Contoso\User*]"
$date = Get-Date
$comp = $env:computername
$strPath = $filename = "E:\Reports\users.txt"
IF(Test-Path $filename) { Remove-Item $strPath }
Add-Content -Path $strPath "$User Owner and\or Admin `t$comp `t$date`n"
Add-Content -Path $strPath "Site.Url `tSite Owner `tParentWeb Url `tSiteAdmin DisplayName `tSiteAdmin LoginName"

$Sites = Get-SPSite -Limit All
ForEach ($site in $Sites) {
	SiteAdmin($site)
	If ($site.owner -Like $user) {
	Add-Content -Path $strPath "$($Site.Url) `t $($Site.Owner)"
	}
	$site.Dispose()
}

 

My SharePoint 2010 Powershell tutorial for SharePoint 200 developers

Originally posted on Serge Luca's Blog (SharePoint MVP):

Here is an extract of the Powershell module of my  SharePoint 2010 for developers course.

 

1.1 lab.introduction to Powershell

In this lab, you will work out a number of exercises that have to do with Powershell.

In Lab1 you will discover the main Powershell concepts; in Lab 2, you will apply these concepts.

1.1.1 Lab 1.discovering Powershell

1. Start the Sharepoint 2010 Management Shell.

clip_image002

2. To get help, type:

Get-help

3. To see all the commands available, type :

4. To see how to use Get-Command, type get-help get-Command; you will notice the Noun option:

clip_image003

5. To get the list of all Sharepoint commands, type:

You will notice familiar cmdlets like Get-SPUser, Get- SPWeb, Get- SPSite,…

Sharepoint commands are organized as verb-noun like Enable-SPFeature.

You can type Get-Command –Noun SPFeature*or Get-Command –verb Enable.

6. In Powershell, there…

View original 1,291 more words

Get SharePoint Users and Groups Info

This script uses the SharePoint commands to gather all the users and groups with access to your Central Administration SP site.
It mails the report using SMTP and it will upload the report to a SharePoint site.
This script must be run as a Farm Administrator to get complete results.

It puts it out in a HTML format. It is usefull for those security audits that come up from time to time.
The is adapted from the code I found here which puts out the results in a quasi XML format.
:

#Function to send out email 
function sendMail($emailTo,$outFile) 
{ 
    $smtpServer = "smtp.org" #<-- Your SMTP mail server
    $emailFrom = "$machineName@yourdomain.com"  
    $subject = "$MachineName SharePoint Users Info - $date" 
    $body = "See Attached."  
	
	If ($outFile -eq $null) {
		# no attachement
		$body += $Results
        Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject  -Body $body -SmtpServer $smtpServer 
	}
	Else
	{
		# with $outfile as attachement
        Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject  -Body $body -Attachments $outFile -SmtpServer $smtpServer
    }
} 

function DisplayWeb #-web SPWeb -depth int -parentWeb SPWeb
{
   if($args[0].HasUniquePerm -eq "True")
  {
    $UserAccess = DetermineUserAccess $args[0] ($args[1] + 1)
  }
  

  if($args[0].Webs -ne $Null)
  {
    # RECURSIVELY SEARCH SUBWEBS
    foreach ($spSubWeb in $args[0].Webs)
    {
      $subWeb = DisplayWeb $spSubWeb ($args[1] + 2)
      $spSubWeb.Dispose()
    }
    # END CONTAINED SUBSITES ENTITY
   
  }

  # END SITE ENTITY
  Return $subWeb
}

function DisplayMissingParametersMessage
{
  #Write-Output "You are missing a parameter for 'Site URL'"
  $script:siteURL = Read-Host "Enter Site URL"
}
<#
This report must be run as a Farm Administrator to get complete results.
The report will mail itself to a person or group and upload the report file to a 
SharePoint site. ("http://sharepoint/Shared%20Documents")
:: Usage:
.\SP Security Report.ps1' "http://ServerName:51234" <-- Change the server name as appropriate.


#>
############
# MAIN
############

Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#IF MISSING PARM FOR SITE URL, ASK FOR INPUT TO FILL
if($args.length -eq 0)
{
  DisplayMissingParametersMessage
}

[string]$siteUrl = $args[0]
[string]$searchScope = $args[1]
[string]$userToFind = $args[2]

#Import-module active*
$server = $env:computername
$date = ( get-date ).ToString('MM-dd-yyyy')
$MachineName = $env:COMPUTERNAME
$u = @()
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication

#IF SEARCH SCOPE SPECIFIED FOR SITE, ONLY SEARCH SITE
if($searchScope -eq "-site")
{
  DisplaySiteCollection $rootSite 1
}
#ELSE SEARCH ENTIRE WEB APP
else
{
  #DisplayWebApplication $spWebApp 1
}

# Create Webpage Header
$z = "<!DOCTYPE html PUBLIC `"-//W3C//DTD XHTML 1.0 Strict//EN`"  `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$z = $z + "<html xmlns=`"http://www.w3.org/1999/xhtml`">"
$z = "<head><style>"
$z = $z + "TABLE{border-width: 2px;border-style: solid;border-color: black;border-collapse: collapse;}"
$z = $z + "TH{border-width: 2px;padding: 4px;border-style: solid;border-color: black;background-color:lightblue;text-align:left;font-size:14px}"
$z = $z + "TD{border-width: 1px;padding: 4px;border-style: solid;border-color: black;font-size:12px}"
$z = $z + "</style></head><body>"
$z = $z + "<H4>SharePoint Users Report for $env:COMPUTERNAME Central Admin $date</H4>"
$z = $z + "<table><colgroup><col/><col/><col/><col/><col/><col/><col/></colgroup>"
$z = $z + "<tr><th>Web App</th><th>Web</th><th>Site Collection</th><th>Site User</th><th>SPGroup</th><th>SPGroupMembers</th><th>Local Group</th></tr>"
$MainWebApp = $spWebApp
$MainDisplayWeb = DisplayWeb 
$subSite = @()

ForEach ($site in $SpWebApp){
$MainSiteCollection = @()
$a = $site.Sites 
	forEach ($a1 in $a) {
	$sSite = $a1.ToString().split("=")
		$SubSite = $subSite + $sSite[1]
	$MainSiteCollection = "$MainSiteCollection $sSite <br>"
	}
}

$z = $z + "<tr><td>$MainWebApp</td><td>$MainDisplayWeb</td><td>$MainSiteCollection</td><td></td></tr>"

ForEach ($site in $SubSite){
$siteUser = @()
$u1 = @()
$SPGroups = @()
$MainSPGroupMembers = @()
$rSite = New-Object Microsoft.SharePoint.SPSite($site)
$x = $rSite.rootweb
$x1 = $x.users

ForEach ($i in $x1) { 
$u = $i.UserLogin
$u2 = $u.ToString().split(".")
$u1 = "$u1  $u2 <br>"
$siteUser = "$u1<br>"
 }
foreach($group in $rsite.RootWeb.SiteGroups)
{	
    $b = $group.Name 
    $sGroup = $b.ToString().split(".")
	$SPGroup = $sGroup[0]
	$SPGroups = ($SPGroup)
	$LocalGrp = @()
	$lgn = @()
	$lgm = @()
	$MemberName = @()
	$x1 = @()
	$x = $null
	foreach ($user in $group.Users)
    {    
		$D = $user.UserLogin
			$D1 = $D.ToString().split(".")
			$D2 = $D.ToString().split("\")
			$SPGroupMembers = "$D1"
			$MainSPGroupMembers = ("$MainSPGroupMembers $SPGroupMembers <br>")
		If ($User.IsDomainGroup) {
			$x = $user
			$lgn = $x
			$x1 = $x1 + $x 
			forEach ($x2 in $x1) {
			$Lgm = $Null
			$y = $Null
			$gName = $x2.ToString().split("\")
			$groupName = $gName[1]
			  #BEGIN - CODE ADAPTED FROM SCRIPT CENTER SAMPLE CODE REPOSITORY
			  #http://www.microsoft.com/technet/scriptcenter/scripts/powershell/search/users/srch106.mspx
			  #GET AD GROUP FROM DIRECTORY SERVICES SEARCH
			  $strFilter = "(&(objectCategory=Group)(name="+($groupName)+"))"
			  $objDomain = New-Object System.DirectoryServices.DirectoryEntry
			  $objSearcher = New-Object System.DirectoryServices.DirectorySearcher
			  $objSearcher.SearchRoot = $objDomain
			  $objSearcher.Filter = $strFilter
				$colProplist = ("name","member")
				foreach ($i in $colPropList)
					{
					$catcher = $objSearcher.PropertiesToLoad.Add($i)
					}
						$colResults = $objSearcher.FindAll()

				#END - CODE ADAPTED FROM SCRIPT CENTER SAMPLE CODE REPOSITORY
				  foreach ($objResult in $colResults)
				  {
					foreach ($member in $objResult.Properties.member)
					{
					  $indMember = [adsi] "LDAP://$member"
					    $y = $domain + ($indMember.Name) 
						$Lgm = ("$Lgm <tr><td>$y</td></tr>")
						}
					 }
			}	
			$LocalGrp = ("$LocalGrp <TABLE><td><strong>$lgn</strong></td><td>$Lgm</td></tr></TABLE>")
			}
	}
	$lgnlgm = $Localgrp
	$z = $z + "<tr><td></td><td>$site</td><td></td><td>$siteUser</td><td>$SPGroups</td><td>$MainSPGroupMembers</td><td>$lgnlgm</td><tr>"
	}
	$rSite.Dispose()
}

# Create Table
$surl = $siteUrl.ToString().split("/")
$s = "CA"
# $s = $surl[2]
# $s = ($s -replace ":", "-") 
$MainWebApp = $spWebApp
$MainDisplayWeb = DisplayWeb
$z = $z + "</table></body></html>"

# Adjust Path
$OutFileName = ("G:\Reports\" + $server + "-" + $s + "-SharePoint Security Report-" + $date + ".html")
#
Out-File -FilePath $OutFileName -InputObject $z -Encoding ASCII	
#End Table
$OutFileItem = Get-Item -Path $OutFileName
Write-Host " Report available here: $OutFileItem" -Foregroundcolor Yellow
sendMail user@yourmai.com $OutFileItem #<--- Change email address

# upload the report to a SharePoint site
$userName = Read-Host "Enter your username"
$password = Read-Host "Enter your password"
 
 $path = "G:\Reports"; #<--- Change directory
 $destination = "http://sharepoint/Shared Documents"; 
 $securePasssword = ConvertTo-SecureString $password -AsPlainText -Force;
 $credentials = New-Object System.Management.Automation.PSCredential ($userName, $securePasssword);
 #$credentials = [System.Net.CredentialCache]::DefaultCredentials; 
 $webclient = New-Object System.Net.WebClient;
 $webclient.Credentials = $credentials; 
 Get-ChildItem $path | Where-Object {$_.Extension -eq ".html"} | 
 ForEach-Object { $webclient.UploadFile($destination + "/" + $_.Name, "PUT", $_.FullName); 
 }
#CLEANUP
$rootSite.Dispose()

Get the SSL Certs by Web Site

I need to check several Web servers for sites that might have an expiring certification.
This pulls the information and adds it to an Excel Spreadsheet.
Note that this only works on 2008 servers.

$date = Get-Date
$rDate = (Get-Date -format "MM-dd-yyyy")
$strPath = "C:\Scripts\PS1\serverinfo-$rDate.xlsx" 
$xl = New-Object -comobject Excel.Application 
$xl.Visible = $True
$xl.DisplayAlerts = $False

$wb = $a.Workbooks.Add() 
$ws = $b.Worksheets.Item(1) 
$ws.Name = $rDate
$ws.Cells.Item(1,1) = "Machine Name" 
$ws.Cells.Item(1,2) = "FriendlyName" 
$ws.Cells.Item(1,3) = "NotAfter" 
$ws.Cells.Item(1,4) = "Issuer" 

$xRow = 2
$cert = dir IIS:\SslBindings | ? {$_.Port -eq 443} | Select *
foreach ($i in $cert) { 
$x = $i.thumbprint
$y = get-item cert:\LocalMachine\My\$x
$FN = $y.FriendlyName
$NA = $y.NotAfter
$IS = $y.Issuer
$ws.Cells.Item($xRow,1) =$comp 
$ws.Cells.Item($xRow,2) =$FN 
$ws.Cells.Item($xRow,3) =$NA 
$ws.Cells.Item($xRow,4) =$IS 
$xRow++
}

This version pulls the info and puts it into a Tab delimited file. I had to run this on each individule server
due to some restriction in my enviroment.

$comp = $env:computername
$strPath = "C:\Scripts\PS1\Certificates\$comp-CertInfo.csv"  # <-- You might want to point this at a share
$date = Get-Date
$rDate = (Get-Date -format "MM-dd-yyyy")
IF(Test-Path $strPath) { Remove-Item $strPath }
Add-Content -Path $strPath "Certificate Inventory `t$rDate`n"
Add-Content -Path $strPath "Machine Name`tFriendlyName `tNotAfter `tIssuer"

$OS = Get-WmiObject Win32_OperatingSystem
$osVer = $os.version
If ($osVer -like "6*") {
$cert = dir IIS:\SslBindings | ? {$_.Port -eq 443} | Select *
foreach ($i in $cert) { 
$x = $i.thumbprint
$y = get-item cert:\LocalMachine\My\$x
$FN = $y.FriendlyName
$NA = $y.NotAfter
$IS = $y.Issuer
Add-Content -Path $strPath "$comp `t$FN `t$NA `t$IS `n";
	}
}
Notepad $strPath

Automates a SharePoint 2010 installation

###### Start Posh Script ######## 

<#
.Script Name
New-SPInstallation.ps1 

.SYNOPSIS
Automates a SharePoint 2010 installation.

.DESCRIPTION
The script automates a SharePoint 2010 installation.
Requires that the binaries are installed on the server.

.PARAMETER databaseName
Name of the configuration database.

.PARAMETER databaseServer
Name of the database server.

.PARAMETER centralAdminDatabase
Name of the Central Administration content database.

.PARAMETER port
Port to use.

.PARAMETER windowsAuthProvider
NTLM or Kerberos, default set to NTLM.

.PARAMETER userName
Farm Administrator account in the format ‘domain\username’.

.PARAMETER password
Pasword for the Farm Administrator account.

.PARAMETER passPhrase
Farm password, used to add new machines to the farm.
#>

param(
[string]$databaseName,
[string]$databaseServer,
[string]$centralAdminDatabase,
[string]$port,
[string]$windowsAuthProvider = "NTLM",
[string]$userName,
[string]$password,
[string]$passPhrase
)
Add-PSSnapin Microsoft.SharePoint.Powershell
$Host.Runspace.ThreadOptions = "ReuseThread"

# Converting password strings to secure strings
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$securePassPhrase = ConvertTo-SecureString -String $passPhrase -AsPlainText -Force

# Creating a PSCredential object
$psCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName, $securePassword

# New Configuration Database
New-SPConfigurationDatabase -DatabaseName $databaseName -DatabaseServer $databaseServer -AdministrationContentDatabaseName $centralAdminDatabase -Passphrase $securePassPhrase -FarmCredentials $psCredentials

# Install help files
Install-SPHelpCollection -All

# Install services
Install-SPService

# Install Features
Install-SPFeature -AllExistingFeatures

# Create a new Central Administration
New-SPCentralAdministration -Port $port -WindowsAuthProvider $windowsAuthProvider

# Copy shared application data
Install-SPApplicationContent

###### End Posh Script ######## 

We can run this script by typing the following:

New-SPInstallation.ps1 -databaseName “My config DB” `
-databaseServer “SqlServer01″ `
-centralAdminDatabase “My Admin_ContentDB” -port 5057 `
-username “ps\admin” `
-password “SecretP@assword” -passphrase “JoinDoain”

Using Central ISE Snippet Repository

Using Central ISE Snippet Repository

In a previous tip we illustrated that ISE code snippets (press CTRL+J to view them) are plain ps1xml-files that you can manage in File Explorer. By default, the PowerShell 3.0 ISE editor loads snippets from your private cache folder.

Imagine you and your colleagues set up a network drive to share useful snippets. Instead of manually checking this folder and manually copying the snippets from this folder onto your local machine, you can also tell the ISE editor to load the snippets directly from the central repository. Here is a sample:

 

$snippetPath = Join-Path (Split-Path $profile.CurrentUserCurrentHost) "Snippets"

$snippetPath

Get-ChildItem -Path $snippetPath -Filter *.ps1xml |

ForEach-Object {

$psise.CurrentPowerShellTab.Snippets.Load($_.FullName)

This sample loads the snippets from your private local folder, so it shows what ISE does by default. Simply assign another path to $snippetPath to load the snippets from another folder. This could be your central team repository, and it could also be a USB stick you are carrying around with you that holds your favorite snippets.

As it turns out, this is the code executed behind the scenes by Import-IseSnippet. In fact, all *-IseSnippet commands are functions, and you can view the source code like this:

$path = "$pshome\modules\ise\ise.psm1"

ise $path

http://powershell.com/cs/blogs/tips/archive/2013/05/07/using-central-ise-snippet-repository.aspx

Accessing Latest Log File Entries

Sometimes you may just be interested in the last couple of entries in a log file. Here’s a simple yet fast way of outputting only the last x lines from a text log:
# Show last 5 lines of windowsupdate.log file

$logs = Get-Content -Path $env:windir\windowsupdate.log -ReadCount 0
$logs[-5..-1]

This example would return only the last (newest) five lines from the windowsupdate.log file.
It’s pretty fast because Get-Content uses –ReadCount 0, reading in even large text files very fast. The result is a text array with the text lines read in. In the example, only the last 5 lines are output (index -5 through -1). However, $logs will hold the complete log file content which may take considerable memory. So in PowerShell 3.0, there is a more efficient approach:
# Show last 5 lines of windowsupdate.log file

Get-Content -Path $env:windir\windowsupdate.log -ReadCount 0 -Tail 5

Here, only the number of lines specified with –Tail are returned, so there is no need for a text array to store all the other text lines found in the log file.

From: “Powershell Tip Of The Day”

http://powershell.com/cs/blogs/tips/archive/2013/04/26/accessing-latest-log-file-entries.aspx