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

Monday, September 19, 2016

Change password in nested RDP session

Just documenting two methods that work, since I'm tired of googling this every few months:

1. PowerShell command:
(New-Object -COM Shell.Application).WindowsSecurity()

2. On screen keyboard

- Start OSK in the session you want to change the password for
- Hold Ctrl+Alt on your physical keyboard
- Press Del on the OSK

Friday, September 27, 2013

Checking for changed properties of an SPWeb

The SPWeb object is one of the places where a lot of the SharePoint magic happens. Many changes performed through the UI or through features are persisted there. When refactoring behavior it's often useful to compare the state of the SPWeb object before and after an update. I've created a small powershell scrip to facilitate this. It reads all the properties of the SPWeb and all the properties in the property bag. It then pauses, allowing you to do whatever you have to. Then the script gets the properties again and outputs the differences. Let me know if it helps you.

Of course, all the regular legal stuff applies. Use at your own risk. I do not accept any liability for what happens when you run this script. And never, never, run a random script you've downloaded from the internet against a production environment without properly testing and examining it.


param(
 [string]$WebUrl = $(throw "WebUrl required.")
)
 
#Region [ Load Assemblies ]
$spNotFoundMsg = "SharePoint not found. Run this script from a SharePoint server that is part of the farm where you want to update your content types"
 
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") -eq $null)     { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server") -eq $null)    { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") -eq $null)      { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server") -eq $null)    { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles") -eq $null) { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Taxonomy") -eq $null)   { throw $spNotFoundMsg; }
 
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null)
{
   Write-Output "Loading Microsoft SharePoint Powershell Snapin"
   Add-PSSnapin "Microsoft.SharePoint.Powershell"
} 
#endregion 

$web = get-SPWeb $WebUrl

$oldProperties = $web.AllProperties.Clone()

$web | % { foreach ($property in $_.PSObject.Properties) { $oldProperties.Add("SPWeb." + $property.Name, $_.PSObject.properties[$property.Name].Value -as [string]) }}

$web.Dispose()

Write-Host "We have grabbed a copy of the properties as they are now. Make your change, and press any key to continue.."

While ($KeyInfo.VirtualKeyCode -Eq $Null) {
        $KeyInfo = $Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown")
}

$web = get-SPWeb $WebUrl

$newProperties = $web.AllProperties.Clone()
$web | % { foreach ($property in $_.PSObject.Properties) { $newProperties.Add("SPWeb." + $property.Name, $_.PSObject.properties[$property.Name].Value -as [string]) }}


$updates = 0
$additions = 0

foreach ($h in $newProperties.Keys) {
    
    $newValue = $newProperties.Item($h)

    if ($oldProperties.Keys.Contains($h))
    {
        $oldValue = $oldProperties.Item($h)
        if ($oldValue -ne $newValue)
        {
            $updates++
            Write-Host "`nFound an update in the property '$h'.`n'$oldValue'`nbecame`n'$newValue'"
        }
    }    
    else
    {
        $additions++
        Write-Host "`nFound an new property '$h', with the following value:`n'$newValue'"
    }
}
Write-Host "Found $updates updates and $additions additions"
$web.Dispose()

Monday, April 29, 2013

Fixing folders that have been converted into document sets

SharePoint 2010 saw the introduction of 'Document Sets'. In my opinion these are the greatest improvement in document management since the stapler. The concept is very simple; you create sets of documents. These sets have their own introduction page, where you can leave relevant info. Also, the documents in the set can share metadata properties and the set itself can have distinct properties which may or may not get pushed down to the documents in the set.

Under the hood, these document sets are nothing more than the old fashioned folders on steroids. This becomes clear when you change the content type for a folder. If you have enabled the document sets site feature, and added the document set content type to your library, you can change folders into document sets. This is especially useful in migration scenario's, if you were already using folders for the same purposes you now would like to use document sets for.

However, the result of this content type switch is not the same as when you create a new document set. Some properties do not update correctly. The resulting document set does not get its landing page and it doesn't get the pretty icon. The culprit is the ProgId property, which should be set to 'SharePoint.DocumentSet'. This property is used by SharePoint to launch the correct program when you open a document (such as a Word or Excel document).

You can go one of two ways in fixing an issue like this. You can create an event receiver which sets the property correctly when the change is made. This is the approach used in a project on codeplex, SharePoint 2010 Folder To Document Set Conversion Fix, by Robert R. Freeman. The main advantage of this solution is that it will fix the document set the moment you update it. A drawback is that you need to deploy custom code, which isn't always an option. Also, folders that have had their content type updated in the past are not fixed

A second solution is to just script it, and fix the document sets that are not functioning correctly in one go. For this you can use the script below.

Of course, all the regular legal stuff applies. Use at your own risk. I do not accept any liability for what happens when you run this script. And never, never, run a random script you've downloaded from the internet against a production environment without properly testing and examining it.

param(
 [string]$WebUrl = $(throw "WebUrl required."),
    [string]$ListName = $(throw "ListName required."),
    [bool]$disableEventFiring = $false
)

#Region [ Load Assemblies ]
$spNotFoundMsg = "SharePoint not found. Run this script from a SharePoint server that is part of the farm where you want to update your content types"

if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") -eq $null)     { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server") -eq $null)    { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") -eq $null)      { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server") -eq $null)    { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles") -eq $null) { throw $spNotFoundMsg; }
if ([Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Taxonomy") -eq $null)   { throw $spNotFoundMsg; }

$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null)
{
   Write-Output "Loading Microsoft SharePoint Powershell Snapin"
   Add-PSSnapin "Microsoft.SharePoint.Powershell"
} 
#endregion 


Start-SPAssignment -Global

$web = Get-SPWeb $WebUrl -EA 1 

$list = $web.Lists[$ListName]
if ($list -eq $null) { throw "List '$ListName' not found at '$WebUrl'" }

Write-Host "Found list '$ListName' at '$WebUrl'" -ForeGroundColor Green


if($disableEventFiring)
{
    Write-Host "Disabling event firing" -ForeGroundColor Yellow
    $myAss = [Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint");
    $type = $myAss.GetType("Microsoft.SharePoint.SPEventManager");
    $prop = $type.GetProperty([string]"EventFiringDisabled",[System.Reflection.BindingFlags] ([System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Static));
    $prop.SetValue($null, $true, $null);
}

$count = 0
$folderCollection = $list.Folders
foreach($folder in $folderCollection)
{
    if ($folder.ContentType.Id.ToString().StartsWith("0x0120D520"))
    {   
        if($folder.ProgId -ne "SharePoint.DocumentSet")
        {
            Write-Host "Found a document set to fix:" $folder.Title -ForeGroundColor Yellow
            
            $folder.ProgId = "SharePoint.DocumentSet"
            $folder.Update()
            $documentSet = [Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet]::GetDocumentSet($folder.Folder)
            $documentSet.Provision()
            
            Write-Host "Document set" $folder.Title "is fixed" -ForeGroundColor Green
            $count++
        }
    }
}

if ($count -eq 0)
{
    Write-Host "Found no document sets requiring an update!" -ForeGroundColor Yellow
}
else
{
    Write-Host "Updated $count document sets!" -ForeGroundColor Green
}

Stop-SPAssignment -Global


<#
.SYNOPSIS
Fix document sets in a SharePoint library

.DESCRIPTION
When manually updating the content type of a folder to a document set, not
all properties are propertly updated by SharePoint. This script fixes these
broken document sets. This script can be run more than once.

.PARAMETER WebUrl
Specifies the url the web hosting the document sets to fix

.PARAMETER ListName
Specifies the display name of the library holding the document sets 
to fix

.PARAMETER disableEventFiring
Optional parameter. Set to $True to prevent the update from firing 
events for event receivers. Can be useful in custom code scenario's

.INPUTS
None. You cannot pipe objects to DocumentSetFixer.ps1.

.OUTPUTS
None. DocumentSetFixer.ps1 does not generate any output.

.EXAMPLE
C:\PS> .\DocumentSetFixer.ps1 -WebUrl "http://mysitecollection/myweb" -ListName "Shared Documents"
Fix all documents sets in the library "Shared Documents" on the 
SharePoint web at "http://mysitecollection/myweb".

.EXAMPLE
C:\PS> .\DocumentSetFixer.ps1 -WebUrl "http://mysitecollection/myweb" -ListName "Shared Documents" -disableEventFiring $true
Fix all documents sets in the library "Shared Documents" on the 
SharePoint web at "http://mysitecollection/myweb". This fix will not 
trigger event receivers on the document sets.

.LINK
Developed by: http://www.vxcompany.com

#>

Rating