another technical blog...technically

Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Thursday, August 15, 2019

Morning routine with BluePrism and PowerShell

If you have deployed lots/tons of robots, you know that maintenance is the big elephant in the room.
Blue Prism scheduler is not so "friendly" and sometimes is not so responsive.

Lately I implemented some warmup scripts that simply restart SQL Server service at 00.00 AM and Blue Prism application server at 1:00AM. Resource PCs are rebooted as well at 2:00 AM.
Resource PCs are scheduled to start working at 3:00 AM even if nobody is at the office, but the problem come when the first colleague start to work at 7:00 AM.

Imagine you have something like 40 machines and you have to connect to each one and check if the schedule has started correctly... i know, it's a bit boring task.
The script i will show you is made of different subscript, according to your scenario you can use split it in more pieces.

Please note that in out project we have very complex schedule, every machine need to run different processes at different hours, with different cut-offs.
For every machine we have two schedule:
  1. The one with include login and then alternates different processes (eg. MACHINE01)
  2. Equal to the previous one without login (e.g. MACHINE01.Backup)
The script knows what machines are involved and their respective Backup schedule.
So at first, open as many RDP sessions as the involved machines, when all machines are visible and tiled on the screen, it starts to check (using telnet) what machines are running something.
If the machine running the script is equipped with Blue Prism, it will try lo launch the schedule using AutomateC.exe.

The code is quite self-explaining, so please have a look below and enjoy

# BEGIN Configs
$PATH_BUFFERFILE = "C:\temp\roboot.txt"
$PATH_AUTOMATEC = "C:\Program Files\Blue Prism Limited\Blue Prism Automate\AutomateC.exe"
$PATH_RDPFILES = "P:\Users\Varro\Desktop\RDP\"

$SCEHDULE_LASTCHECK = '20:30'

$RESOURCEPC_PORT = 8182
$RESOURCEPC_SCHEDULES = @{}
$RESOURCEPC_SCHEDULES.Add('MACHINE01_HOSTNAME','MACHINE01.Backup')
$RESOURCEPC_SCHEDULES.Add('MACHINE02_HOSTNAME','MACHINE02.Backup')
$RESOURCEPC_SCHEDULES.Add('MACHINE03_HOSTNAME','MACHINE03.Backup')
$RESOURCEPC_SCHEDULES.Add('MACHINE04_HOSTNAME','MACHINE04.Backup')
$RESOURCEPC_SCHEDULES.Add('MACHINE05_HOSTNAME','MACHINE05.Backup')
# END Configs

# BEGIN - Functions written by someone smarter than me
Function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '
  
  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd) 
}

Function Get-Telnet
{   Param (
        [Parameter(ValueFromPipeline=$true)]
        [String[]]$Commands = @("username","password","disable clipaging","sh config"),
        [string]$RemoteHost = "HostnameOrIPAddress",
        [string]$Port = "23",
        [int]$WaitTime = 1000,
        [string]$OutputPath = "\\server\share\switchbackup.txt"
    )
    #Attach to the remote device, setup streaming requirements
    $Socket = New-Object System.Net.Sockets.TcpClient($RemoteHost, $Port)
    If ($Socket)
    {   $Stream = $Socket.GetStream()
        $Writer = New-Object System.IO.StreamWriter($Stream)
        $Buffer = New-Object System.Byte[] 1024 
        $Encoding = New-Object System.Text.AsciiEncoding

        #Now start issuing the commands
        ForEach ($Command in $Commands)
        {   $Writer.WriteLine($Command) 
            $Writer.Flush()
            Start-Sleep -Milliseconds $WaitTime
        }
        #All commands issued, but since the last command is usually going to be
        #the longest let's wait a little longer for it to finish
        Start-Sleep -Milliseconds ($WaitTime * 4)
        $Result = ""
        #Save all the results
        While($Stream.DataAvailable) 
        {   $Read = $Stream.Read($Buffer, 0, 1024) 
            $Result += ($Encoding.GetString($Buffer, 0, $Read))
        }
    }
    Else     
    {   $Result = "Unable to connect to host: $($RemoteHost):$Port"
    }
    #Done, now save the results to a file
    $Result | Out-File $OutputPath
    return $Result
}
# END - Functions written by someone smarter than me

# MAIN
# 1. Close all RDP session
Get-Process | Where-Object { $_.Path -like "*mstsc*" } | Stop-Process -Force

# 2. Wait all RDP sessions are closed
Do {
    $rdpSessions = Get-Process | Where-Object { $_.Path -like "*mstsc*" }
    Start-Sleep -s 1
} While ($rdpSessions.Count -ne 0)

#3. Open RDP sessions
ForEach ($resourcePc in $RESOURCEPC_SCHEDULES.Keys) {   
    $arg = $PATH_RDPFILES + $resourcePc + ".rdp"
    Start-Process "mstsc" -ArgumentList """$arg"""
    Start-Sleep -s 1
}

#4. Wait all RDP sessions are opened
Do {
    $rdpSessions = Get-Process | Where-Object { $_.Path -like "*mstsc*" }
    Start-Sleep -s 2
} While ($rdpSessions.Count -ne $RESOURCEPC_SCHEDULES.Keys.Count)


#5. Wait to be logged in every RDP session the script opened, then click enter or something else
$process = Get-Process -Id $PID
Write-Host $process
Show-Process -Process $process -Maximize

$key = Read-Host "Press ENTER key when all are connected"

#6. Tile all RDP sessions vertically
$ShelleExp = New-Object -ComObject Shell.Application
$ShelleExp.TileVertically()

#7. Just deciding what to do according to the hour of the day (don't start if current time > 8.30 in this case or on weekend days)
$now = (Get-Date)
$nowDay = $now.DayOfWeek.value__
Write-Host "Today is $nowDay - $now.TimeOfDay"

if ($now.TimeOfDay -gt $SCEHDULE_LASTCHECK -And $nowDay -ne 6 -And $nowday -ne 7)
{
    Write-Host "Too late... maybe tomorrow" -BackgroundColor Red -ForegroundColor White
} 
else 
{

    #8. Checking if machines are working (using telnet to get those data)
    [System.Collections.ArrayList]$resourcePC_Problematic = @()
    foreach ($resourcePc in $RESOURCEPC_SCHEDULES.Keys)
    {
        Write-Host "Check $resourcePc machine" -ForegroundColor Yellow
        # Remove buffer file, call telnet and get message
        Remove-Item $PATH_BUFFERFILE -ErrorAction Ignore
        $telnetContent = Get-Telnet -RemoteHost $resourcePc -Port $RESOURCEPC_PORT -Commands "status" -OutputPath "$PATH_BUFFERFILE"
        Write-Host $telnetContent -ForegroundColor Yellow
        
        #9a. If contains running, something is running, so move on
        if ($telnetContent.Contains("RUNNING")) 
        { 
            Write-Host "$resourcePc is working" -ForegroundColor Green
        }
        #9b. If does not contains running, time to run the schedule
        else
        {
            $scheduleName = $resourcePc_Schedulazioni[$resourcePc]
            Write-Host "Run now scheduled task $scheduleName on $resourcePc" -BackgroundColor Red -ForegroundColor White
            $cmd = "cmd.exe /C ""$PATH_AUTOMATEC"" /sso /startschedule /schedule $scheduleName"
            Invoke-Expression -Command:$cmd
        }
        
        #9c. Clean it up
        Remove-Item $PATH_BUFFERFILE
        Write-Host 
        Write-Host 
    }

    #10. Check again all machines to check are running something, if not, write who's doing nothing
    foreach ($resourcePc in $RESOURCEPC_SCHEDULES.Keys)
    {
        Remove-Item $PATH_BUFFERFILE -ErrorAction Ignore
        $telnetContent = Get-Telnet -RemoteHost $resourcePc -Port $RESOURCEPC_PORT -Commands "status" -OutputPath "$PATH_BUFFERFILE"
        if (!$telnetContent.Contains("RUNNING")) 
        { 
            $resourcePC_Problematic.Add($resourcePc)
        }
    }

    Write-Host "Resource PC not booted: $resourcePC_Problematic" -BackgroundColor Red -ForegroundColor White
}


Read-Host "Premere ENTER to exit"
Share:

Friday, August 25, 2017

O365 team site external user issue

I love O365 because it enables (power) users to do whatever they want to. I saw people developing their own assets using Flow and Power Apps and share them across market units.
Moreover Team site evolved in something which is more user friendly, and people are able to create their own site for a project (mixing together Planner, SharePoint Online, OneDrive and other stuff) in order to include also external users and make them able to interact with them: this is common if the customer outsources lots of activities.
Lately i found a curious problem, i created a SharePoint group with also external users, after that i broke inheritance on some document library (customer does not want to allow everyone to see what's happening on the project site) and assign some custom permission to external users.
So i created custom groups and added people, and, even if O365 gave me no error, no user was added. I kept trying without results and, because i've to go on vacancy, i had to solve the problem easily.
At first time i read this link and then this other one by Microsoft and i set up this value as site collection sharing capability one.
Set-SPOSite -Identity https://contoso.sharepoint.com/sites/site1 -SharingCapability ExternalUserSharingOnly
I noticed that, if you face that problem, even if you are not able to accomplish the task using UI, you can do it using PowerShell, so, i created this small script that can help you to save your vacancy.
I have not found the root cause, meantime, have fun with this.
Before reading the other script, i wanna thank you Simone Anzaldi (Big up) who helped me with this problem.
# PARAM
$URL = "https://varrocorp.sharepoint.com/sites/Test"  

$USR = "admin@varrocorp.it"  
$PWD = "UsernamePassword"

$GROUPNAME = "Da Group"
$EXTERNALUSERNAME = "user@externaldomain.com"


# Import some libraries
Import-Module MSOnline
Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($URL)  

# Just converting plain text to secure string
$pwd = ConvertTo-SecureString -String $PWD -AsPlainText -Force
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($USR, $PWD)  
$ctx.credentials = $creds   

# Get root site details   
$web = $ctx.Site.RootWeb 

# Gets all site groups   
$groups = $web.SiteGroups
$ctx.Load($groups)  
$ctx.ExecuteQuery()  

# Get user info of the external user
$userInfo = $web.EnsureUser($EXTERNALUSERNAME)  
$ctx.Load($userInfo)  

# Get group by name and add the user
$group = $web.SiteGroups.GetByName($GROUPNAME) 
$addUser = $group.Users.AddUser($userInfo)  
$ctx.Load($addUser)  
$ctx.ExecuteQuery()  

# Paranoid check
$group = $web.SiteGroups.GetByName($GROUPNAME) 
$users = $group.Users  
$ctx.Load($users)  
$ctx.ExecuteQuery()  
foreach($user in $users){  
    Write-Host " " $user.Title  
}  
Share:

Wednesday, July 29, 2015

Deleting a host named site collection... for real

A simple problem: you have to delete a host named site collection in order to recreate it.
When you try to recreate it, you get an error: SharePoint says the site collection already exists... if you restart the machine you'll be able to recreate it.
What if you cannot restart the machine whenever you want (read production environment).
$variable = Get-SPSite "http://already.deleted.site"
$variable
You'll get an output like this


Now recreate the site collection without problems ;)

Friday, May 29, 2015

Azure SPFarm Manager 1.2 released

Since they changed something, i had to change something.
Here's the new verion, what's new? Nothing, simply MS changed something about image names and i have to readapt the Build script.
Now it works like a charm.
The old config.xml will not work anymore (only if you wanna BUILD another farm).
ImageFamily attribute was deprecated and now you have to use ImageLabel, please have a look to the new package ;) .
Download it here
Share:

Monday, December 8, 2014

Azure SPFarm Manager 1.1 released

You're asking yourself, why in the world, Varro is writing articles as fast as hell?
I got the flu and lots of drafts.
So here's a good new one, the new version of Azure SPFarm Manager.
Here's the changes.
  • No more BuildEnvironment.ps1 command, now it's named Build.ps1
  •  Deprovision.ps1 command: so now you can save you money deallocating and removing your VMs whenever you want (config are saved in the export folder)
  • Reprovision.ps1: so you can spend your money whenever you wake up your farm
  • No more Config.xml file needed: if you have more than one farm, you can create more config files (e.g.: development.xml, integration.xml), if you don't select an existing file, the old Config.xml would be used for you


Do you wanna more?
Mmm.. sorry thats'it for today.
Download the code from here

Howto to deal with workflow manager when it refuses to install

This is what happens when you come back from a vacancy week:
  • Your (personal) mobile phone rings (yep i don't have a enterprise one) and customer asks why workflow manager installer for SP2013 farm, literally, "doesn't work" 
  • You take tube and bus (with 30° C) to reach customer office
  • You skip launch to discover the problem
  • You came back to the office and you continue your work till late
  • You start thinking about opening a bar in Copacabana
As usual /mode joke off
Today i will talk about safest installation procedure of workflow manager on SP2013 farm. Customers, very often configure farm server doing stuffs as block incoming connections or setting locale in such strange ways.
This could cause Web Platform installer strange behaviours and mainly Service Bus installation failure with this error (which is related to Windows Fabric, a Service Bus dependency)
Error
When i tried to install Workflow Manager stuffs i got this error:
Event ID 11722 Product: Windows Fabric — Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action DoFabricSetup, location: C:Program FilesWindows abricbinFabricFabric.Code.1.0MSIHiddenAppLauncher.exe, command:FabricSetup /operation:install /gac
Like you can read on this blog post (a real life-saving one: http://blog.riccardocelesti.it/workflow-manager-setup-issue/) this is due to locale settings. Service Bus and its dependencies can be installed only with locale settings en-us, but the check will let you install this piece of sotware it's only on this registry key.

Solution
So i built this little script, which is helpful to install workflow manager flawlessy.
Write-Host "Getting sTimeFormat RegEx value ... " -NoNewLine;
$regVal =  Get-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\.DEFAULT\Control Panel\International" -Name "sTimeFormat"
Write-Host "DONE" -ForeGroundColor GREEN;

$oldFormat = $regVal.sTimeFormat;
Write-Host "Old time format was: $oldFormat" -BackgroundColor YELLOW -ForeGroundColor BLACK;

Write-Host "Setting sTimeFormat RegEx value ... " -NoNewLine;
Set-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\.DEFAULT\Control Panel\International" -Name "sTimeFormat" -value "h:mm:ss tt";
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Download web platform installer ... " -NoNewLine;
$source = "http://download.microsoft.com/download/7/0/4/704CEB4C-9F42-4962-A2B0-5C84B0682C7A/WebPlatformInstaller_amd64_en-US.msi";
$destination = "c:\WebPlatformInstaller_amd64_en-US.msi";
Invoke-WebRequest $source -OutFile $destination;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Installing web platform installer ... " -NoNewLine;
Start-Process c:\WebPlatformInstaller_amd64_en-US.msi -Wait;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Refreshing WebPI products ... " -NoNewLine;
Start-Process "C:\Program Files\Microsoft\Web Platform Installer\webpicmd" -ArgumentList '/offline','/Products:WorkflowManagerRefresh','/Path:c:/WorkflowManagerFiles' -Wait;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Installing workflow manager software ... " -NoNewLine;
Start-Process "C:\Program Files\Microsoft\Web Platform Installer\WebpiCmd.exe" -ArgumentList '/Install','/Products:WorkflowManagerRefresh','/XML:c:/WorkflowManagerFiles/feeds/latest/webproductlist.xml' -Wait;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Starting workflow manager configurator ... " -NoNewLine;
Start-Process "C:\Program Files\Workflow Manager\1.0\Microsoft.Workflow.Deployment.ConfigWizard.exe" -Wait;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Resetting sTimeFormat RegEx value to $oldFormat ... " -NoNewLine;
Set-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\.DEFAULT\Control Panel\International" -Name "sTimeFormat" -value $oldFormat;
Write-Host "DONE" -ForeGroundColor GREEN;

Write-Host "Cleaning files ... " -NoNewLine;
Remove-Item $destination;
Remove-Item "c:/WorkflowManagerFiles";
Write-Host "DONE" -ForeGroundColor GREEN;

Read-Host "Press any key to exit";
It could be done better, for example using powershell also for workflow manager configuration, maybe i'll do something similat for Azure SPFarm Manager.
Once you run the script, at first the sTimeFormat will be forced in the registry key, so installation could proceed on any locale configured SharePoint farm.



At the end the original value will be restored.
 And that's all, you can also download the code from here. Enjoy.

A simple script to log to verbose mode

Hi, this will be a quick post, just to show you a little PowerShell script (yeah, lately i'm in love with PowerShell) could be very helpful during bug hunting sessions.
When you run the script, the log level is raised to Verbose and a new SPLog file is created for this verbose log.
When you press a key, the log level is resetted to the default one, and a new SPLog file is created, so the penultimate log file is the one you need to examine.
This is the script: enjoy
$ver = $host | select version
if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} 
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) 
{
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}

Write-Host "Setting TraceSeverity and EventSeverity to Verbose"
Set-SPLogLevel -TraceSeverity Verbose -EventSeverity Verbose

Write-Host "Creating a new Log file"
New-SPLogFile

Read-Host "Press ENTER key to reset default log level"

Write-Host "Resetting TraceSeverity and EventSeverity"
clear-sploglevel

Write-Host "Creating a new Log file for resetted log"
new-splogfile

Read-Host "Press any key to exit ..."
Or maybe download it from here.
Share:

Friday, November 21, 2014

Provision a SharePoint 2013 farm with Azure and PowerShell

I begun to work on Azure one year ago in order to have a dev SharePoint 2013 to build some code since i don't have a powerful PC.
Reading below articles, i was able to create my personal farm
Step-by-Step: Build a FREE SharePoint 2013 Dev/Test Lab in the Cloud with Windows Azure Infrastructure Services - Part 1
Step-by-Step: Build a FREE SharePoint 2013 Dev/Test Lab in the Cloud with Windows Azure Infrastructure Services - Part 2
A colleague (codename Roller) asked me if it was possible to build the farm automagically using PowerShell, since there were amazing PowerShell Azure cmdlets.
<< Varro, why don't you do something like that? it would be so useful >>
<< Ok Roller, but it will take a lot of my free time, you'll give me money for this? >>
<< No >>
<< Ok Roller, i'll do it for you ... someday... in the future >>
That day is arrived.
/mode joke off
Since i need something simple and smart to build a SP2013 farm, i started surfing the web studying (and also stealing code) creating this wonderful script you can download clicking here.

Requirements
Once you downloaded the script on you PC you have to read the README (do it).
It explains what do you need to make script execution smooth (maybe).
  1. Enable PSRemoting on your PC: this will be useful to use CredSSP to invoke remote PowerShell script execution on Azure machine (it will avoid the double hop problem); since you have to allow PSRemoting to *.cloudapp.net you are future-powershell-experiments proof.
  2. Download Azure cmdlets
  3. Download your Azure account publish settings (have you got a Azure account uh?).
  4. Configure XML file
The zip contains a Config - example.xml

 
 
 
  
  
 
 
 
  
 
 
  
   
  
  
   
  
  
   
   
  
 

If you don't want to waste you time, simply change "MSDN subscription name" with your MSDN subscription name, passwords (substitute Password01 with your preferred one) and substitute "sharepointLab01" prefix with something else (please note that resulting vm name length must be less than 15 characters).
Note that if you are behind proxyes, firewall and other stuffs, you could have troubles.
Please take some minutes to read the FAQ below, since you'll need it, after thas warm-up phase, simply run BuildEnvironment.ps1

FAQ.
Q1: What is the average execution time of the batch script?
A1: The farm will be provisioned approximately in 1 hour, i could make it quicker, better, safer... but you have the code, make it better :) .

Q2: The script is someway interactive?
A2: No, you will be prompted to proceed to WinRM quick configuration just one time, when provisioning SharePoint VM, click y and everything will be fine


Q3: I noticed the script sometimes stop itself and give me some error, what i have to do?
A3: Simply solve the errors and re-run the script: already done steps will be bybassed if possible

Q4: I received this error: "Connecting to remote server failed with the following message: The client cannot connect to the destination specified in the request blablabla" what i have to do?
A4: Just keep calm and re-run the script. This error means the script is unable to connect to the VM, so if you're ok with firewall, proxyes and other security stuffs, the connection simply failed, try again.
If the problem persists, try something more rude, delete the VM giving problems and re-run the scipt.

Q5: Are there some built-in users?
A5: Yes sir, SPFarm, which is also the farm admin and SPServiceApp

Q6:What about the service application?
A6: The script provisions User Profile, Managed Metadata and Search service applications, but you can do che quick wizard whenever you want if you need more

Happy ending (hope so)
Download the code from here and have fun. 

Remember, this is not production software, it's something i use for me, myself and i, so i cannot ensure you everything is gonna be fine, even if i provisioned some farm with this, but if i'll save you time with this... come on offer me a beer ;) .

In loving memory of Roller

Wednesday, July 30, 2014

Howto solve Workflow suspended with HTTP 401 and survive to a demo

Today... demo day...
Objectives:
  •     Show the customer what he/she is paying for
  •     Satisfy customer
  •     Sell change requests
  •     Earn project bonus
So, basically, let's take another demo roundtrip and let's test all the process.
Wow everything works fine, why don't we start the workflow?
Wow... Why execution failed?

RequestorId: dbaf8233-b7f4-cc8e-0000-000000000000. Details: An unhandled exception occurred during the execution of the workflow instance. Exception details: System.ApplicationException: HTTP 401 {"error":{"code":"-2147024891, System.UnauthorizedAccessException","message":{"lang":"en-US","value":"Access denied. You do not have permission to perform this action or access this resource."}}} {"Transfer-Encoding":["chunked"],"X-SharePointHealthScore":["2"],"SPRequestGuid":["dbaf8233-b7f4-cc8e-84d2-34863a603d9b"],"request-id":["dbaf8233-b7f4-cc8e-84d2-34863a603d9b"],"X-FRAME-OPTIONS":["SAMEORIGIN"],"MicrosoftSharePointTeamServices":["15.0.0.4551"],"X-Content-Type-Options":["nosniff"],"X-MS-InvokeApp":["1; RequireReadOnly"],"Cache-Control":["max-age=0, private"],"Date":["Fri, 25 Jul 2014 14:01:50 GMT"],"Server":["Microsoft-IIS\/8.0"],"WWW-Authenticate":["NTLM"],"X-AspNet-Version":["4.0.30319"],"X-Powered-By":["ASP.NET"]} at Microsoft.Activities.Hosting.Runtime.Subroutine.SubroutineChild.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

Wow... Why my bonus it's flying away?
Don't worry about it, the solution it's simple, even if the situation is frustrating.
The problem can be solved using central admin, look for Refresh trusted security token services metadata feed and run it now. Then make an iisreset.
If you are a lazy one use this small PowerShell
Get-SPTimerJob "RefreshMetadataFeed" | Start-SPTimerJob
And now, let's go on with demo, and with the bonus :) .

Tuesday, March 5, 2013

Get site content types and site columns using PowerShell

Lately i'm working to a feasibility study for a intranet migration from SharePoint 2010 to SharePoint 2013.
During this project, i needed to know what are content types and fields were involved in the 2010 custom solution, in order to map them in SharePoint 2013 ones.
My boss asked me to do this A.S.A.P., so i developed a powershell script capable of retrieving these data and put them in CSV files, so i can import them with excel and do further analysis.
The script output is a set of three CSV files:
  1. Site content types
  2. Site columns
  3. Mapping between content types and fields
Here is the code for PowersShell 3.0:
##
## 20130214, from Varro with love
##

Add-PSSnapin Microsoft.SharePoint.PowerShell

## Variables
$WEB_APPLICATION_URL = "http://teamsite"
$CTS_FILE_PATH = "c:\Users\Administrator\Desktop\2013_TeamSite_ContentTypes.csv"
$FIELDS_FILE_PATH = "c:\Users\Administrator\Desktop\2013_TeamSite_Fields.csv"
$CT_FIELDS_FILE_PATH = "c:\Users\Administrator\Desktop\2013_TeamSite_CTs_And_Fields.csv"


## Initialization
echo "Initializing variables"
'"CT Name","CT Description","CT ID","CT Group","CT Parent ID"' | Out-File $CTS_FILE_PATH;
'"Field Title","Field Description","Field Internal Name","Field ID","Field Group","Field Type"' | Out-File $FIELDS_FILE_PATH;
'"CT Name","Field Title","CT ID","Field ID"' | Out-File $CT_FIELDS_FILE_PATH;

$AllContentTypes = @();
$AllFields = @();


## Go with the code
echo "Entering web application $WEB_APPLICATION_URL" 

$webApplication = Get-SPWebApplication -identity $WEB_APPLICATION_URL

ForEach ($siteCollection in $webApplication.Sites)
{
    ForEach($subSite in $siteCollection.AllWebs)
    {
        $subsiteUrl = $subsite.Url;

        echo "Extracting info from $subSiteUrl";

        $contentTypes = $subSite.ContentTypes;

        ForEach ($contentType in $contentTypes)
        {
            If (!$AllContentTypes.Contains($contentType.Id))
            {
                $AllContentTypes += $contentType.Id;

                # Let's write on Content types CSV
                '"' + $contentType.Name + '","' + $contentType.Description + '","' + $contentType.Id + '","' + $contentType.Group + '","' + $contentType.Parent.Id + '"' | Out-File $CTS_FILE_PATH -Append
           
                ForEach ($field in $contentType.Fields)
                {
                    If (!$AllFields.Contains($field.Id))
                    {
                        $AllFields += $field.Id;

                         # Let's write on Fields CSV
                        '"' + $field.Title + '","' + $field.Description + '","' + $field.Id + '","' + $field.Group + '","' + $field.Type + '","' | Out-File $FIELDS_FILE_PATH -Append;
                    }

                    '"' + $contentType.Name + '","' + $field.Title + '","' + $contentType.Id + '","' + $field.Id + '","' | Out-File $CT_FIELDS_FILE_PATH -Append;
                }
            }
        }
    }
}

echo "See you space cowboy";
If you need to run this script in PowerShell 2.0, you just need to change these rows
If (!$AllContentTypes.Contains($contentType.Id))
...
   If (!$AllFields.Contains($field.Id))
with these ones:
$alreadyInCT = $AllContentTypes -contains $contentType.Id;
If (!$alreadyInCT)
...         
   $alreadyInFields = $AllFields -contains $field.Id;               
   If (!$alreadyInFields)
Please feel free to reuse, comment and share.
Share:

Me, myself and I

My Photo
I'm just another IT guy sharing his knowledge with all of you out there.
Wanna know more?