Wednesday, February 5, 2014

Download all InfoPath within SharePoint Web Application using PowerShell

Below PowerShell script can be used to download/Backup all infoPath forms residing within a Web Application with a folder structure similar to the URL.

========================================================================

#Change below url to your web app URL
$SPWebApp = Get-SPWebApplication ('https://YourWebApplication.com/')
$destination = "d:\\temp\\InfoPathBackup\\"

"Site Name`tList Name`tUrl`tDocs`tLast Mod`tWF`tLive WF`tLive WF Names`tTemplate" > d:\temp\AllIPDocLibs.csv

#loop through each site in the site collection
 $cnt = $SPWebApp.Sites.count.toString()
  "Total Site collection -: $cnt "
foreach ($SPSite in $SPWebApp.Sites) #loop through all site collection
{
   $cnt = $SPSite.allwebs.count.toString()
  "Total number of Sites in collection -: $cnt "
   $SiteTitle = $SPSite.url.toString()
   "PROCESSING Site collection $SiteTitle"
 
$url = $SiteTitle
$req = [system.Net.WebRequest]::Create($url)
$req.UseDefaultCredentials = $true
try {
       $res = $req.GetResponse()
     } catch [System.Net.WebException] {
       $res = $_.Exception.Response
     }

if ( $res.StatusCode -eq "OK" )
{
  $ErrorActionPreference="SilentlyContinue"
   foreach($webs in $SPSite.allwebs)
   {
       
#use this for output
$webTitle = $webs.title.toString()
"PROCESSING site $webTitle"

#loop though each list in the current website
for($i=0;$i -ne $webs.lists.count;$i++)
{
$list = $webs.lists[$i]
#this is used for output and to make the code a little more readable
$listTitle = $list.toString()
$listUrl = $list.DefaultViewUrl
$listCount = $list.ItemCount

if( $list.BaseType -eq "DocumentLibrary"  -and
$list.BaseTemplate -eq "XMLForm")
{
$listModDate = $list.LastItemModifiedDate.ToShortDateString()
$listTemplate = $list.ServerRelativeDocumentTemplateUrl
$listWorkflowCount = $list.WorkflowAssociations.Count
$listLiveWorkflowCount = 0
$listLiveWorkflows = ""
foreach ($wf in $list.WorkflowAssociations)
{
if ($wf.Enabled)
{
$listLiveWorkflowCount++
if ($listLiveWorkflows.Length -gt 0)
{
$listLiveWorkflows = "$listLiveWorkflows, $($wf.Name)"
}
else
{
$listLiveWorkflows = $wf.Name
}
}
}
"$webTitle`t$listTitle`t$listUrl`t$listCount`t$listModDate`t$listWorkflowCount`t$listLiveWorkflowCount`t$listLiveWorkflows`t$listTemplate" >> d:\temp\AllIPDocLibs.csv
#Downloading file to local drive
#Ensure destination directory
        $destinationfolder = $destination + "/" + $listUrl.Substring(0,$listUrl.LastIndexOf("/"))
$file.Name = $listTemplate.Substring($listTemplate.LastIndexOf("/") + 1)
        if (!(Test-Path -path $destinationfolder))
        {
            $dest = New-Item $destinationfolder -type directory
      }
#Download file
$binary = $file.OpenBinary()
$stream = New-Object System.IO.FileStream($destinationfolder + "/" + $file.Name), Create
$writer = New-Object System.IO.BinaryWriter($stream)
$writer.write($binary)
$writer.Close()
}
}
$webs.Dispose()
    }
}
else
   {  Add-Content d:\temp\DeadSites.txt "`n $SiteTitle" } #dead or inaccessible sites encountered during loop.
    $SPSite.Dispose()
}
    [GC]::Collect()
#Dispose of the site object
$SPWebApp.Dispose()
"Done"
========================================================================

Get list of all InfoPath forms (with URL/Path) within a Web application-SharePoint using PowerShell

Below script helps to get list of infopath forms within a web application with their path/URL. Script also collects the names of dead/inaccessible sites (which the scripts encounters during the looping of all site collections within the web application) and outputs into a text file.

========================================================================
#change the URL to match web application where you would like to search InfoPath forms
$SPWebApp = Get-SPWebApplication ('http://yourwebapplication.com/') 

"Site Name`tList Name`tUrl`tDocs`tLast Mod`tWF`tLive WF`tLive WF Names`tTemplate" > d:\temp\AllIPDocLibs.csv

#Loop through each site in the site collection
 $cnt = $SPWebApp.Sites.count.toString()
  "Total Site collection -: $cnt "
foreach ($SPSite in $SPWebApp.Sites) #loop through all site collection
{
   $cnt = $SPSite.allwebs.count.toString()
  "Total number of Sites in collection -: $cnt "
   $SiteTitle = $SPSite.url.toString()
   "Processing Site collection $SiteTitle"
   
$url = $SiteTitle
$req = [system.Net.WebRequest]::Create($url)
$req.UseDefaultCredentials = $true
try {
       $res = $req.GetResponse()
     } catch [System.Net.WebException] {
       $res = $_.Exception.Response
     }

if ( $res.StatusCode -eq "OK" )
{
  $ErrorActionPreference="SilentlyContinue"
   foreach($webs in $SPSite.allwebs)
   {
        
#use this for output
$webTitle = $webs.title.toString()
"PROCESSING site $webTitle"

#loop though each list in the current website
for($i=0;$i -ne $webs.lists.count;$i++)
{
$list = $webs.lists[$i]
#variables for output.
$listTitle = $list.toString()
$listUrl = $list.DefaultViewUrl
$listCount = $list.ItemCount

if( $list.BaseType -eq "DocumentLibrary"  -and
$list.BaseTemplate -eq "XMLForm")
{
$listModDate = $list.LastItemModifiedDate.ToShortDateString()
$listTemplate = $list.ServerRelativeDocumentTemplateUrl
$listWorkflowCount = $list.WorkflowAssociations.Count
$listLiveWorkflowCount = 0
$listLiveWorkflows = ""
foreach ($wf in $list.WorkflowAssociations)
{
if ($wf.Enabled)
{
$listLiveWorkflowCount++
if ($listLiveWorkflows.Length -gt 0)
{
$listLiveWorkflows = "$listLiveWorkflows, $($wf.Name)"
}
else 
{
$listLiveWorkflows = $wf.Name
}
}
}
"$webTitle`t$listTitle`t$listUrl`t$listCount`t$listModDate`t$listWorkflowCount`t$listLiveWorkflowCount`t$listLiveWorkflows`t$listTemplate" >> d:\temp\AllIPDocLibs.csv
}
}
$webs.Dispose()
    }
}
else
   {  Add-Content d:\temp\DeadSites.txt "`n $SiteTitle" }
    $SPSite.Dispose()
}
    [GC]::Collect()
#Dispose of the site object
$SPWebApp.Dispose()
"Done"
========================================================================

Find last login timestamp for service/user account from Active directory using PowerShell

Below script will be helpful in finding the last login timestamp of the users/service accounts used by SharePoint farm. This script helps us in identifying orphan accounts which can deleted or reused elsewhere.

Logic of this script is pretty simple. Read the XML file having list of Active directory accounts. Loop through each domain controller and check and compare for the value of lastlogin with other DC. the one with the highest value is the last login timestamp value for that account. Finally the output of this is stored in a txt file.
============PowerShell Script================================================
Import-Module ActiveDirectory

$Path = "D:\Sharepoint\Lastlogintimestamp\sharepointUsers.xml"
# load it into an XML object:
$xml = New-Object -TypeName XML
$xml.Load($Path)
# note: if your XML is malformed, you will get an exception here
# always make sure your node names do not contain spaces
$rsltObj = New-Object PSObject;
$results = @();
$hostname ="";
$user =$Null;
# simply traverse the XML nodes and loop through account names:
foreach ($node in $xml.Accounts.ChildNodes) 
{
$username = $node.InnerText;
write-host "Checking last login time for....  $username `n";
$dcs = Get-ADDomainController
  $time = 0
  foreach($dc in $dcs)
  { 
    $hostname = $dc.HostName
      $user = Get-ADUser $userName | Get-ADObject -Server $hostname -Properties lastLogon;
if( $user -ne $Null)
{
if($user.LastLogon -gt $time) 
{
   $time = $user.LastLogon
   $hostname = $dc.HostName
}
}
  }
$dt = [DateTime]::FromFileTime($time)
$rsltObj= "$username last logged on at: $dt authenticated by $hostname `n";
write-host $rsltObj;
$results += $rsltObj;
}
$results | Out-File C:\temp\SharePoint-Lastlogintimestamp.txt;
Write-host "Data saved in c:\temp\SharePoint-Lastlogintimestamp.txt";
========================================================================

===================XML File format========================================
<?xml version="1.0" encoding="UTF-8" ?>
<Accounts>
<Name>SP_Farm</Name>
<Name>SP_Service</Name>
<Name>SP_Search</Name>
</Accounts>
======================================================================
You can add more XML nodes to xml file to add more accounts which you would like to check.