I’ve been working on a GUI program in Sapien Powershell Studio. This program deploys SSRS reports to a integrated SSRS and Sharepoint instance. While writing this I discovered that to upload the Files to sharepoint you must have the full path structure to where you are placing the file. Well turns out what sharepoint gives you when you are browsing to a subfolder is this very weird url with query strings in it. To ensure that I get what I want from my user and I know where to upload the file I had to write a function to parse the query string and return it to my calling function so I could upload properly. This article is about how i was able to get this to function.
First lets look at the query string I was dealing with:
So if we look at this query string closely we can see the real folder name for my Sharepoint site and location is after the RootFolder query string %2fsites%2fmysite%2fTest
So with that in mind I started looking for a way to parse this string and get out what I wanted after the RootFolder query string. So I attempted using string manipulation and several other methods. I kept thinking to myself there must be a better way. So I dug deeper and I found a #Csharp Class that deals with urls: [System.Web.HttpUtility]
Now that I have something to deal with urls. I sleuth around the class with Powershell until I found this function ParseQueryString. Now if I take my url and feed it to this class. To be able to use it I must add the type so that Powershell Can see it:
Add-Type -AssemblyName System.Web PS PS:\> [uri]$Url = 'http://servername/sites/mysite/Shared%20Documents/Forms/Allitems.aspx?RootFolder=%2fsites%2fmysite%2fTest&folderCTID=0x0120004845B289B9EC1E479DF75ADD1F150A9E' [System.Web.HttpUtility]::ParseQueryString($url) http://servername/sites/mysite/Shared Documents/Forms/Allitems.aspx?RootFolder
My return results don’t seem to be what I’m looking for. Since my return results contain two items which look to be an array. I’ll query them via index number:
PS PS:\> $a = ([System.Web.HttpUtility]::ParseQueryString($url)) PS PS:\> $a[0] /sites/mysite/Test
Interesting The results are in the first array member so this must be a hashtable of some sort?
PS PS:\> $a.gettype()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
False True HttpValueCollection System.Collections.Specialized.NameValueCollection
No it’s not a Hashtable but a specialized System.Collections.Specialized.NameValueCollection. Hmmm so how do i get the value I want out of the collection?
PS PS:\> $a | get-member -MemberType Properties
TypeName: System.String
Name MemberType Definition
—- ———- ———-
Length Property int Length {get;}
The only property it has is Length which doesn’t really give me what I want the actual text from the query string. So it must be a method that I need to use:
PS PS:\> $a | get-member -MemberType Method
TypeName: System.String
Name MemberType Definition
—- ———- ———-
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
CompareTo Method int CompareTo(System.Object value), int CompareTo(string strB), int IComparable.CompareTo(System.Object obj), int IComparable[string].CompareTo(string other)
Contains Method bool Contains(string value)
Hmm this variable now says its of type string and all the methods are string methods. After looking around for some time I finally tried somethings in ISE and I got to the method I was looking for: GetValues
So now I can attempt to see if I can get the values I want from this object:
PS PS:\> $a.GetValues('http://servername/sites/mysite/Shared Documents/Forms/Allitems.aspx?RootFolder')
Cool I got what i was looking for the value for RootFolder query string. Now I’m half way there. Now all that is needed is to construct the getValues method call to only get what I’m looking for RootFolder.
PS PS:\> $a.GetValues(($a.keys | Where-Object{$_ -like "*RootFolder*"}))</span>
Now I have the value I want so I can now create a function to return the url I need for my program. Here is the full Function:
function Format-SharepointUrl { param ( [parameter(Mandatory = $true)] [uri]$url ) add-type -assembly system.web $newUrl = $null [System.Collections.Specialized.NameValueCollection]$uCollection = [System.Web.Httputility]::ParseQuerySTring($url) if ($uCollection.GetValues(($ucollection.keys | ?{ $_ -like "*RootFolder*" }))) { $cUrl = $uCollection.GetValues(($ucollection.keys | ?{ $_ -like "*RootFolder*" })) $newUrl = "$($url.Scheme)://$($url.Host)$cUrl" } $newUrl }
I hope this helps someone ..
Until then keep scripting