Iterating a SharePoint 2010 Atom feed - powershell

SharePoint 2010 returns an Atom feed when using its REST API.
For example:
http://SERVER/Tasks/_vti_bin/listdata.svc/Tasks?$select=Id,Title,Status&$filter=UserId eq 1234&$orderby=Status asc
Results:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://SERVER/Tasks/_vti_bin/listdata.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Tasks</title>
<id>http://SERVER/Tasks/_vti_bin/listdata.svc/Tasks</id>
<updated>2015-04-23T19:03:12Z</updated>
<link rel="self" title="Tasks" href="Tasks" />
<entry m:etag="W/"22"">
<id>http://SERVER/Tasks/_vti_bin/listdata.svc/Tasks(4444)</id>
<title type="text">Lorem Ipsum</title>
<updated>2015-04-20T00:00:00-00:00</updated>
<author>
<name />
</author>
<link rel="edit" title="List" href="Tasks(4444)" />
<category term="Microsoft.SharePoint.DataService.TasksItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Title>Lorem Ipsum</d:Title>
<d:Status>Complete</d:Status>
<d:Id m:type="Edm.Int32">4444</d:Id>
</m:properties>
</content>
</entry>
...
</feed>
I'm hoping to list each <m:property> element as a row in Format-Table, but this code doesn't work:
...
[xml]$xml = Get-Url $url
$xml.feed.entry.content.properties | Format-Table -Property #{Label="Id"; Expression={$_.Id."#text"}},
#{Label="Title"; Expression={$_.Title}},
#{Label="Status"; Expression={$_.Status}}
I suspect this relates to the namespaces, but I'm not sure why. It would seem that PowerShell would be aware of this, given that it has already parse the XML.
In general, is there an easier way to work with Atom feeds?
** edit 0 **
Fixed name of Status field.
Would expect to see something like this:
Id Title Status
---------- ---------- ----------
8345 Lorem ipsu Active
4534 Ipsum lore Inactive
...
Instead, nothing is returned (no column header, no rows).
** edit 1 **
function Get-Url {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[String] $webUrl
)
begin { Write-Verbose "$($MyInvocation.MyCommand.Name)::Begin" }
process {
try {
$req = [System.Net.WebRequest]::Create($webUrl)
$req.Method ="GET"
# JSON
# $req.Accept = "application/json; odata=verbose"
# $req.ContentType = "application/json; charset=utf-8"
$req.ContentLength = 0
$req.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$resp = $req.GetResponse()
$reader = new-object System.IO.StreamReader($resp.GetResponseStream())
return $reader.ReadToEnd()
}
catch [Exception] {
Write-Host $_.Exception.ToString()
}
finally {
if ($reader -ne $null) {
$reader.Close()
}
}
}
end { Write-Verbose "$($MyInvocation.MyCommand.Name)::End" }
}

Related

How to consume a click-event in a Toast-Message?

I made a powershell code that shows a toast-message with a "yes/no" option. Now I am looking for a way to handle that click-event properly. See below the code I have so far:
cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
# now lets define a toast-message:
$toastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
$xmlString = #"
<toast launch = "Test1" scenario='alarm'>
<visual>
<binding template="ToastGeneric">
<text>Title</text>
<text>Message</text>
</binding>
</visual>
<audio src="ms-winsoundevent:Notification.Looping.Alarm" />
<actions>
<action content="yes" arguments="yes" />
<action content="no" arguments="no" />
</actions>
</toast>
"#
$toastXml.LoadXml($XmlString)
$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
$appId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
$notify = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId)
$notify.Show($toast)
Here I need a way to wait for the event, when the users clicks the "yes/no" buttons in the toast (or the "x" to close all). It should work without an external DLL, but using e.g. "add_Activated" and an eventHandler like in this c# code:
https://github.com/david-risney/PoshWinRT/blob/master/PoshWinRT/EventWrapper.cs
I thought it should be similar like for the other cs-Wrapper from that PoshWinRT project, which I could finally convert into this:
# replacement for PoshWinRT - AsyncOperationWrapper:
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$asTaskGeneric = foreach($method in [System.WindowsRuntimeSystemExtensions].GetMethods()) {
if ($method.name -ne 'AsTask') {continue}
if ($method.GetParameters().Count -ne 1) {continue}
if ($method.GetParameters().ParameterType.Name -ne 'IAsyncOperation`1') {continue}
$method
break
}
function Await($WinRtTask, $ResultType) {
$asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
$netTask = $asTask.Invoke($null, #($WinRtTask))
$null = $netTask.Wait(-1)
$netTask.Result
}
# sample for async operation:
$null = [Windows.Storage.StorageFile, Windows.Storage, ContentType = WindowsRuntime]
$file = 'c:\windows\notepad.exe'
$info = await ([Windows.Storage.StorageFile]::GetFileFromPathAsync($file)) ([Windows.Storage.StorageFile])
$info
Unfortunately, the coding for that eventWrapper seesm to be a bit more tricky. These are the code-snippets that I could not bring to life, but they may point into the right direction:
$method = [Windows.UI.Notifications.ToastNotification].GetMethod('add_Activated')
$handler = [Windows.Foundation.TypedEventHandler[Windows.UI.Notifications.ToastNotification,System.Object]]::new($toast, $intPtr1)
$handler = [System.EventHandler]::new($toast, $intPtr2)
Especially the second IntPtr-parameter required for creating an eventHandler confuses me totally.
Any input is more than welcome. Many thanks.

Get recurring events from sharepoint (2010) with powershell + CAML

* EDIT: *
Managed to fetch the reccuring events.
How do I overcome the year limit?
<Value Type='DateTime'>
<Year/>
</Value>
I want to get all items, even 5 years ahead.
-------- Original ----------
I am trying to run a PowerShell script to export all events from a SharePoint-2010 calendar including recurring events.
I got references from
https://github.com/CompartiMOSS/SharePoint-PowerShell/blob/master/SharePoint/Administration/PS_HowToDoCAMLQuery.ps1
Expand Recurring Events from a Sharepoint Calendar over WebServices?
The script is running, but the recurring events are not showing.
What am I missing?
If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }
$host.Runspace.ThreadOptions = "ReuseThread"
#Definition of the function that allows to do the CAML query
function DoCAMLQuery
{
param ($sSiteCollection,$sListName)
try
{
$spSite=Get-SPSite -Identity $sSiteCollection
$spwWeb=$spSite.OpenWeb()
$splList = $spwWeb.Lists.TryGetList($sListName)
if ($splList)
{
$spqQuery = New-Object Microsoft.SharePoint.SPQuery
$spqQuery.Query =
"<GetListItems
xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
<listName>'Event Calendar'</listName>
<query>
<Query>
<Where>
<DateRangesOverlap>
<FieldRef Name='EventDate' />
<FieldRef Name='EndDate' />
<FieldRef Name='RecurrenceID' />
<FieldRef Name='fRecurrence' />
<FieldRef Name='RecurrenceData' />
<Value Type='DateTime'><Year/>
</Value>
</DateRangesOverlap>
</Where>
</Query>
</query>
<queryOptions>
<QueryOptions>
<ExpandRecurrence>TRUE</ExpandRecurrence>
</QueryOptions>
</queryOptions>
</GetListItems>"
$spqQuery.ExpandRecurrence = $true
$splListItems = $splList.GetItems($spqQuery)
$iNumber=1
foreach ($splListItem in $splListItems)
{
write-host "File # $iNumber - Name: " $splListItem.Name " ," "Title:" $splListItem["ows_LinkTitle"] -ForegroundColor Green
$iNumber+=1
}
}
$spSite.Dispose()
}
catch [System.Exception]
{
write-host -f red $_.Exception.ToString()
}
}
Start-SPAssignment –Global
#Calling the function
$sSiteCollection="http://sharepoint/"
$sListName="Compliance Events"
DoCamlQuery -sSiteCollection $sSiteCollection -sListName $sListName
Stop-SPAssignment –Global
Remove-PSSnapin Microsoft.SharePoint.PowerShell
Thanks!
S
Below sample script will return events from Now() till next two years.
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$siteURL="http://sp"
$site = Get-SPSite $siteURL
$web = $site.OpenWeb()
$splList = $web.Lists.TryGetList("MyCalendar")
$spqQuery = New-Object Microsoft.SharePoint.SPQuery
$spqQuery.Query = "<Where><DateRangesOverlap><FieldRef Name='EventDate' /><FieldRef Name='EndDate' /><FieldRef Name='RecurrenceID' /><Value Type='DateTime'><Now /></Value></DateRangesOverlap></Where>";
$spqQuery.ExpandRecurrence = $true
$splListItems = $splList.GetItems($spqQuery)
Write-Host $splListItems.Count
One thread for your reference

CAML in Powershell with IN CLause

I'm using SP 2013 on-premises and I'm wanting to query a list for items by passing a number of IDs to the list and then returning only the Title field. This is executing in Powershell. I have the following that I am using as the ViewXml:
<View>
<ViewFields>
<FieldRef Name='Title'/>
</ViewFields>
<Query>
<Where>
<In>
<FieldRef Name='ID' />
<Values>
<Value Type='Counter'>1131</Value>
<Value Type='Counter'>478</Value>
<Value Type='Counter'>360</Value>
<Values>
</In>
</Where>
</Query>
</View>
I get the following when running $ctx.executeQuery();
Exception calling "ExecuteQuery" with "0" argument(s): "Cannot complete this action.
Please try again."
Here is the rest of the code minus the variable definitions and the bit where the client dlls are added
$pwd = Read-Host -Prompt "Enter password" -AsSecureString
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
$ctx.Credentials = New-Object System.Net.NetworkCredential($userId, $pwd)
$vFields = "<Value Type='Counter'>1131</Value><Value Type='Counter'>478</Value><Value Type='Counter'>360</Value>";
try{
$lists = $ctx.web.Lists ;
$list = $lists.GetByTitle($ListName);
$query = New-Object Microsoft.SharePoint.Client.CamlQuery;
$xmlCAML = "<View><ViewFields><FieldRef Name='Title'/></ViewFields><Query><Where><In><FieldRef Name='ID'/><Values>$vFields<Values></In></Where></Query></View>";
write-host $xmlCAML -ForegroundColor Yellow
$query.ViewXml = $xmlCAML
$listItems = $list.GetItems($query);
$ctx.load($listItems);
$ctx.executeQuery();
foreach($listItem in $listItems)
{
Write-Host "Title - " $listItem["Title"]
}
}
catch{
write-host "$($_.Exception.Message)" -foregroundcolor red
}
if you haven't already sorted this, it's just a single-keystroke fix, you've just failed to properly close the <Values>...</Values> element in your CAML. Needs to be:
<View>
<ViewFields>
<FieldRef Name='Title'/>
</ViewFields>
<Query>
<Where>
<In>
<FieldRef Name='ID' />
<Values>
<Value Type='Counter'>1131</Value>
<Value Type='Counter'>478</Value>
<Value Type='Counter'>360</Value>
</Values> <!-- <== Here :) -->
</In>
</Where>
</Query>
</View>

Access to REST Sharepoint data from another domain

Have this question: how I can do REST calls to Sharepoint 2013/2016 REST api, from another host, lets say, another server, but within the same domain.
By default, CORS policy will deny any request that does not come from the same host.
I am trying to retrieve some information doing an AJAX REST request from another host.
Thanks!!
Enable SharePoint configure to enable cross domain access.
Below script is shared by Ingo Karstein here
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0
$localFarm = Get-SPFarm
$webapp = Get-SPWebApplication "http://sp:12001"
# Remove old web.config modifications of MyAuthenticationProvider
$oldMods = #();
$webapp.WebConfigModifications | ? { $_.Owner -eq "CrossSiteScripting" } | % {
$oldMods = $oldMods + $_
}
$oldMods | % {
$webapp.WebConfigModifications.Remove($_)
}
# update the Web Application and apply all existing web.config modifications - this executes the "remove" actions from above
$webapp.Update()
[Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications()
#Wait until web.config modifications finished by timer job
while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) {
Write-Host "." -NoNewline
Start-Sleep 1
}
# New web.config modifications for MyAuthenticationProvider
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Allow-Origin'][#value='http://wfm:13002']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
#0 = for the enum value "SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Allow-Origin' value='http://wfm:13002' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Request-Method'][#value='GET,POST,HEAD,OPTIONS']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Request-Method' value='GET,POST,HEAD,OPTIONS' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Request-Headers'][#value='Content-Type,Authorization']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Request-Headers' value='Content-Type,Authorization' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Allow-Credentials'][#value='true']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Allow-Credentials' value='true' />"
$webapp.WebConfigModifications.Add($myModification1)
$webapp.Update()
[Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications()
#Wait until web.config modifications finished by timer job
while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) {
Write-Host "." -NoNewline
Start-Sleep 1
}
My test result:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<input id="Button1" type="button" onclick="getListItems()" value="button" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
function getListItems() {
var dataEndPoint = "http://sp:12001/_api/web/lists/getbytitle('Versions')/items";
$.ajax({
url: dataEndPoint,
type: "GET",
headers: {
"Accept": "application/json;odata=verbose"
},
crossDomain: true,
xhrFields: { withCredentials: true },
success: function (data) {
alert(data.d.results.length);
},
error: function (response) {
alert("Error");
}
})
}
</script>
</body>
</html>

TFS 2017 - [ProjectName].setParameters.xml with powershell

I create a zip Package in my build then i deploy it to a diffrent machine i am pasing few Parameters in my parameters.xml
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<parameter name="WebSiteUserName" description="Please enter the username" defaultvalue="__WebSiteUserName__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/connectionStrings/add[#key='WebSiteUserName']/#value">
</parameterentry>
</parameter>
<parameter name="WebSiteUserPassword" description="Please enter the password" defaultvalue="__UserPassword__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/connectionStrings/add[#key='WebSiteUserPassword']/#value">
</parameterentry>
</parameter>
<parameter name="WebSiteDomain" description="Domiain" defaultvalue="__Domain__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='WebSiteDomain']/#value">
</parameterentry>
</parameter>
</parameters>
</parameters>
Then i run a powershell script
param(
[string]$paramsFilePath
)
Write-Verbose -Verbose "Entering script Replace-SetParameters.ps1"
Write-Verbose -Verbose ("Path to SetParametersFile: {0}" -f $paramsFilePath)
# get the environment variables
$vars = Get-ChildItem -path env:*
# read in the setParameters file
$contents = Get-Content -Path $paramsFilePath
# perform a regex replacement
$newContents = "";
$contents | % {
$line = $_
if ($_ -match "__(\w+[\.\w+]*)__") {
$setting = Get-ChildItem -path env:* | ? { $_.Name -eq $Matches[1] }
while ($setting) {
Write-Verbose -Verbose ("Replacing key {0} with value from environment" -f $setting.Name)
$line = $_ -replace "__(\w+[\.\w+]*)__", $setting.Value
}
}
$newContents += $line + [Environment]::NewLine
}
Write-Verbose -Verbose "Overwriting SetParameters file with new values"
Set-Content $paramsFilePath -Value $newContents
Write-Verbose " Assigning Parameters"
Write-Verbose -Verbose "Exiting script Replace-SetParameters.ps1"
It will go through the parameters file and replace the parameters token with the enviromental variable.
In my setParamaters.xml file The WebSiteUsername only gets changed
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name" value="Default Web Site/SomeWebsite" />
<setParameter name="WebSiteUserName" value="username" />
<setParameter name="WebSiteUserPassword" value="__UserPassword__" />
<setParameter name="Web.config Connection String" value="SomeValueForConnection" />
</parameters>
I dont know why this is happening. Any Thoughts?
I think you want to get the password from a TFS release definition environment.
You can´t access hidden fields with
$vars = Get-ChildItem -path env:secretVariable
There is a way but that´s only works in the context of a TFS VNext build or release extension.
In your case the only possibility of access is to set the variable as a script argument like this:
-paramsFilePath $(paramsFilePath) -password $(secretVariable)
In your script add the parameter like
param(
[string]$paramsFilePath,
[string]$password
)