Tuesday, June 18, 2013

%systemdrive% in Powershell

I was just trying to write a script to manage IIS logs. I was able to get the log directory, but it comes back as  %SystemDrive%\inetpub\logs\LogFiles

Reading between the lines from a couple of posts, I found that I can use $env:SystemDrive in place of %SystemDrive%

So I can do something like this:
Import-Module WebAdministration
$website = Get-Website | Where-Object {$_.name -eq 'SharePoint - 443'}
$logfileDirectory = $website.logFile.directory -replace '%SystemDrive%', $env:SystemDrive
...

Wednesday, June 5, 2013

0x80070002 when adding web part using Powershell

I was adding a webpart using this powershell:
$webpart = New-Object Microsoft.SharePoint.WebPartPages.SilverlightWebPart
$wpm = $web.GetLimitedWebPartManager($page.Uri.OriginalString, "Shared")
$wpm.AddWebPart($webpart, 'Header', 0)

... and got this error:

Exception calling "AddWebPart" with "3" argument(s): "<nativehr>0x80070002</nativehr><nativestack></nativestack>"
At line:1 char:16
+ $wpm.AddWebPart <<<< ($webpart, 'Header', 0)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException


It turns out that my $page was the wrong one which was not checked out nor editable at the time.

Listing a page's web part zones

I have been trying to figure out a way to list all of a page's web part zones. There is not much documentation out there on this. Here's what I have been able to figure out. It is for a publishing web, but the procedure should be pretty much the same.

$myweburl
$mylayouttitle
$web = Get-SPWeb $myweburl
$pWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$layout = $pWeb.GetAvailablePageLayouts() | Where-Object {$_.Title -eq $mylayouttitle}
$layout.ListItem.Properties['vti_cachedzones']


And to list the webparts on a page:
$pageurl
$wpm = $web.GetLimitedWebPartManager($pageurl, 'Shared'
$wpm.WebParts | Format-Table -AutoSize WebBrowsableObject, ZoneId, ZoneIndex


There's also a post Determine which webpartzones are on a webpartpage that uses reflection to get at a private member however I have not gotten it to work.



Wednesday, April 17, 2013

Could not load the current My Site settings

I have a new SP2013 installation and going into the Setup My Sites, I get the error:
Could not load the current My Site settings

Doing a quick search, I came across this:


It turned out that my Search Service Application was broken as described here:

Unable to retrieve topology component health states. This may be because the admin component is not up and running

I just installed SP2013 RTM on Win2k8R2 SP1 and SQL2012 Enterprise on a separate Win2k8R2 SP1 server. I used Powershell to provision my Search as follows:


$ssi = Get-SPServiceInstance | Where-Object {$_.TypeName -eq 'SharePoint Server Search'}
Start-SPServiceInstance $ssi
WaitForServiceInstance $ssi.TypeName
$searchAdminAppPool = Get-SPServiceApplicationPool -Identity $AppPoolSearchAdmin
$searchQueryAppPool = Get-SPServiceApplicationPool -Identity $AppPoolSearchQuery
New-SPEnterpriseSearchServiceApplication -Name 'Search Service Application' -ApplicationPool $searchQueryAppPool -AdminApplicationPool $searchAdminAppPool
New-SPEnterpriseSearchServiceApplicationProxy -Name 'Search Service Application' -SearchApplication (Get-SPEnterpriseSearchServiceApplication 'Search Service Application')
Set-SPEnterpriseSearchService -ServiceAccount $searchServiceAccount -ServicePassword (ConvertTo-SecureString -AsPlainText -Force $password)

When I go into manage my Search Service Application, I get the following error:
Unable to retrieve topology component health states. This may be because the admin component is not up and running

Figuring that I may have been missing some steps in my Powershell script, I tried unprovisioning my Search Service Application and reprovisioning using Central Administration. Still the same problem. Time to do some searches. Here is what I found.

http://office.microsoft.com/en-ca/help/sharepoint-server-2013-known-issues-HA102919021.aspx
http://social.technet.microsoft.com/Forums/en-US/sharepointitpropreview/thread/50acc2b8-dd56-4d5a-a660-dffa325ef807/?prof=required
http://leonzandman.com/2012/11/08/return-of-the-search-application-topology-component-health-state-error/
http://www.mavention.nl/blog/sp2013-installation-lessons-learned-part-1

After doing a lot of reading and considering the various CUs, I went back to my servers to try some of the suggested solutions. Lo and behold, search is working now. The only things I can infer from this is:

  1. Central Administration is doing something to provision Search that is missing from my Powershell script
  2. Some process took its time to execute
  3. Possibly some random factors like memory, etc.


As much as I would like to know the real answer, it is working now, time to move onto next problem.


Friday, April 5, 2013

Managing assemblies with Powershell

A simple way to access assemblies and see what's in them. Still a work in progress. I hope to add more tricks to this post soon.

Load in the assembly
$assembly = [Reflection.Assembly]::LoadFile($assemblyPath)
or
$assembly = [Reflection.Assembly]::Load($assemblyName)

Get details on a type defined in the assembly
$type = $assembly.DefinedTypes | Where-Object {$_.Name -eq $typeName}
$type.DeclaredConstructors | ForEach-Object {$_.ToString()}
$type.DeclaredMethods | ForEach-Object {$_.ToString()}

To load the assembly for use
Add-Type -Path $assemblyPath #if assembly in file
or
Add-Type -AssemblyName $assemblyName #if assembly in GAC
For some reason $assemblyName must be the full name contrary to the documentation in Add-Type

Get all assemblies in current AppDomain
[AppDomain]::CurrentDomain.GetAssemblies() | Select-Object FullName | Sort-Object FullName

References:
System.Reflection.Assembly class
Add-Type cmdlet
AppDomain class


Windows Azure storage through Powershell

This is just a first stab at manipulating Windows Azure Storage via Powershell.

Get Microsoft.WindowsAzure.Storage.dll using NuGet 
  1. Navigate to this by first going to the Windows Azure Downloads site.
  2. Select .NET. 
  3. Select Client libraries under Resources.
  4. Instructions on how to download Windows Azure Storage are found here. 
Here is the code I'm using to download files from blob storage

Param (
    [Parameter(Mandatory=$true)] [String] $StorageAccountName,
    [Parameter(Mandatory=$true)] [String] $AccessKey,
    [Parameter(Mandatory=$true)] [String] $BlobFilename,
    [Parameter(Mandatory=$true)] [String] $LocalFilename,
    [String] $StorageAccountEndpoint = "http://$storageAccountName.blob.core.windows.net/"
)

Add-Type -Path '.\Microsoft.WindowsAzure.Storage.dll'

$BlobFilename = $BlobFilename.Replace('%20', ' ').Trim('/')
$storageCredentials = New-Object Microsoft.WindowsAzure.Storage.Auth.StorageCredentials($StorageAccountName, $AccessKey)
$blobClient = New-Object Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient($StorageAccountEndpoint, $storageCredentials)
$blob = $blobClient.GetBlobReferenceFromServer($BlobFilename)
$stream = New-Object System.IO.FileStream($LocalFilename, [System.IO.FileMode]::Create)
$blob.DownloadToStream($stream)
$stream.Close()