CAML in Powershell with IN CLause - powershell

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>

Related

Add Click event to DataTable (powershell)

So I have a button that pulls this function to search for all the Install.Log files on a machine.
After loading the results, I want to have a double click event on the a row, where it will open the log file.
I am having a hard time adding a click event, and anytime I try to find something related to Datatables I find stuff about java. Any guidance or links would be appreciated.
Thanks in advace
TEST THE CODE FOR YOUR SELF BY RUNNING THIS IN PS ISE
$ComputerName = "your computer name here"
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = #'
<Window Name="Form"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Install Logs" Height="488.773" Width="797.65" Icon = "\\bconac01\ds-support\GS_IT\Tools\Test Tools (Alx)\Tool\icon.ico" ShowInTaskbar="False">
<Grid Margin="0,0,-8,-21">
<DataGrid Name="DataGrid1" HorizontalAlignment="Left" Height="368" VerticalAlignment="Top" Width="772" Margin="10,41,0,0"/>
<Label Content="Filter" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<TextBox Name="FilterTextBox" HorizontalAlignment="Left" Height="26" Margin="78,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="172"/>
</Grid>
</Window>
'#
#Read XAML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{$Software=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Some possible causes for this problem include: .NET Framework is missing PowerShell must be launched with PowerShell -sta, invalid XAML code was encountered."; exit}
# Store Form Objects In PowerShell
$xaml.SelectNodes("//*[#Name]") | ForEach-Object{
Set-Variable -Name ($_.Name) -Value $Software.FindName($_.Name)
Write-host $_.Name
}
$Fields = #(
'Name'
'LastWriteTime'
)
#$Services = Get-WmiObject -Computer ($prebox.text + $device.text) -Class Win32reg_AddRemovePrograms | Select-object -Property *
$Services = Get-ChildItem \\$ComputerName\c$\build\logs -Include *install* -recurse -ErrorAction Stop | Sort-Object LastWriteTime -Descending
# Add Services to a datatable
$Datatable = New-Object System.Data.DataTable
[void]$Datatable.Columns.AddRange($Fields)
foreach ($Service in $Services)
{
$Array = #()
Foreach ($Field in $Fields)
{
$array += $Service.$Field
}
[void]$Datatable.Rows.Add($array)
}
#$filter = "DisplayName LIKE 'B%'"
#$Datatable.DefaultView.RowFilter = $filter
# Create a datagrid object and populate with datatable
$DataGrid1.ItemsSource = $Datatable.DefaultView
$DataGrid1.CanUserAddRows = $False
$DataGrid1.IsReadOnly = $True
$DataGrid1.GridLinesVisibility = "None"
$DataGrid1.Add_CellMouseClick({gridClick})
function gridClick(){
$rowIndex = $DataGrid1.CurrentRow.Index
$columnIndex = $DataGrid1.CurrentCell.ColumnIndex
Write-Host $rowIndex
Write-Host $columnIndex
Write-Host $DataGrid1.Rows[$rowIndex].Cells[0].value
Write-Host $DataGrid1.Rows[$rowIndex].Cells[$columnIndex].value}
$FilterTextBox.Add_TextChanged({
$InputText = $FilterTextBox.Text
$filter = "Name LIKE '$InputText%'"
$Datatable.DefaultView.RowFilter = $filter
$DataGrid1.ItemsSource = $Datatable.DefaultView
$form.Controls.Add($DataGrid1)
$Software.Controls.Add($DataGrid1)
})
# Shows the form
$statusBar1.Text = "Done."
$Software.Add_Shown({$Software.Activate()})
$Software.ShowDialog() | out-null
--Things Ive tried that are suggested.
[
Ok. Here's a sample with gridview cell click event. You can add cell double click event with $DataGrid1.Add_CellMouseClick({gridClick})
hope this should help
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(900,600)
$DataGrid1 = New-Object System.Windows.Forms.DataGridView
$DataGrid1.Size=New-Object System.Drawing.Size(800,400)
$DataGrid1.Add_CellMouseClick({gridClick})
$form.Controls.Add($DataGrid1)
#Create an unbound DataGridView by declaring a column count.
$DataGrid1.ColumnCount = 4
$DataGrid1.ColumnHeadersVisible = $true
#Set the column header names.
$DataGrid1.Columns[0].Name = "Recipe"
$DataGrid1.Columns[1].Name = "Category"
$DataGrid1.Columns[2].Name = "Third COlumn"
$DataGrid1.Columns[3].Name = "Rating"
#Populate the rows.
$row1 = #("Meatloaf","Main Dish", "boringMeatloaf", "boringMeatloafRanking")
$row2 = #("Key Lime Pie","Dessert", "lime juice evaporated milk", "****")
$row3 = #("Orange-Salsa Pork Chops","Main Dish", "pork chops, salsa, orange juice", "****")
$row4 = #("Black Bean and Rice Salad","Salad", "black beans, brown rice", "****")
$row5 = #("Chocolate Cheesecake","Dessert", "cream cheese", "***")
$row6 = #("Black Bean Dip", "Appetizer","black beans, sour cream", "***")
$rows = #( $row1, $row2, $row3, $row4, $row5, $row6 )
foreach ($row in $rows){
$DataGrid1.Rows.Add($row)
}
function gridClick(){
$rowIndex = $DataGrid1.CurrentRow.Index
$columnIndex = $DataGrid1.CurrentCell.ColumnIndex
Write-Host $rowIndex
Write-Host $columnIndex
Write-Host $DataGrid1.Rows[$rowIndex].Cells[0].value
Write-Host $DataGrid1.Rows[$rowIndex].Cells[$columnIndex].value}
$form.ShowDialog()
As per your requirement here's one another sample I have created with WPF with PowerShell. You can bind the event using $WPFListView.Add_MouseDoubleClick({gridClick}) and to access the selected cell value using column like $WPFListView.SelectedValue.OriginalFileName
Try this as it is in PowerShell ISE. This is how it looks
##Sample DataTable
$tabName = "SampleTable"
#Create Table object
$table = New-Object system.Data.DataTable “$tabName”
#Define Columns
$col1 = New-Object system.Data.DataColumn OriginalFileName,([string])
$col2 = New-Object system.Data.DataColumn FileDescription,([string])
$col3 = New-Object system.Data.DataColumn FileVersionRaw,([string])
#Add the Columns
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
#Create a row
$row = $table.NewRow()
$row.OriginalFileName = "Test Log"
$row.FileDescription = "Test log data"
$row.FileVersionRaw = "v1.0"
$row1 = $table.NewRow()
$row1.OriginalFileName = "IIS Log"
$row1.FileDescription = "IIS Sys log"
$row1.FileVersionRaw = "v2.0"
$row2 = $table.NewRow()
$row2.OriginalFileName = "User Data"
$row2.FileDescription = "User data details"
$row2.FileVersionRaw = "v1.0"
$row3 = $table.NewRow()
$row3.OriginalFileName = "Sys Info"
$row3.FileDescription = "System Info Details"
$row3.FileVersionRaw = "v2.0"
#Add the row to the table
$table.Rows.Add($row)
$table.Rows.Add($row1)
$table.Rows.Add($row2)
$table.Rows.Add($row3)
##Sample DataTable
$inputXML = #"
<Window x:Class="FileVersionChecker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FileVersionChecker"
mc:Ignorable="d"
Title="FileVersionChecker" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="115*"/>
<ColumnDefinition Width="373*"/>
<ColumnDefinition Width="29*"/>
</Grid.ColumnDefinitions>
<ListView Name="ListView" Grid.Column="1" HorizontalAlignment="Left" Height="150" Margin="10,10,0,0" VerticalAlignment="Top" Width="350">
<ListView.View>
<GridView>
<GridViewColumn Header="OriginalFileName" DisplayMemberBinding ="{Binding 'OriginalFileName'}" Width="100"/>
<GridViewColumn Header="FileDescription" DisplayMemberBinding ="{Binding 'FileDescription'}" Width="100"/>
<GridViewColumn Header="FileVersionRaw" DisplayMemberBinding ="{Binding 'FileVersionRaw'}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
"#
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
try {
$Form = [Windows.Markup.XamlReader]::Load( $reader )
}
catch {
Write-Output "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
}
$xaml.SelectNodes("//*[#Name]") | ForEach-Object {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name)}
$WPFListView.ItemsSource = $table.DefaultView
$WPFListView.Add_MouseDoubleClick({gridClick})
function gridClick()
{
Write-Host ""
Write-Host "$($WPFListView.SelectedValue.OriginalFileName) , $($WPFListView.SelectedValue.FileDescription), $($WPFListView.SelectedValue.FileVersionRaw)"
}
$Form.ShowDialog() | out-null;

SP2010 Delete list items after CAML Query

I want to delete list items from my CAML query but currently cannot using a foreach loop.
What would be the best way to delete the items after the CAML query?
$Query = New-Object Microsoft.SharePoint.SPQuery
$Query.Query = "
<Where>
<Leq>
<FieldRef Name='Created' />
<Value Type='DateTime'>
<Today OffsetDays='-30' />
</Value>
</Leq>
</Where>
<OrderBy>
<FieldRef Name='Created' Ascending='False' />
</OrderBy>"
#Get List Items matching the query
$ListItems = $oList.GetItems($Query)
write-host "Number of items retrieved:" $ListItems.Count;
foreach($ListItem in $ListItems)
{
write-host "Deleting"+ $listItem.ID + $listItem.Name + $listItem["Created"];
#$ListItem.delete();
}
Please delete list item in foreach loop like this:
$spweb = get-spweb http://sp/sites/devtest
$oList = $spweb.Lists.TryGetList("List2")
if ($oList)
{
$query = New-Object Microsoft.SharePoint.SPQuery
$query.Query = "
<Where>
<Leq>
<FieldRef Name='Created' />
<Value Type='DateTime'>
<Today OffsetDays='-30' />
</Value>
</Leq>
</Where>
<OrderBy>
<FieldRef Name='Created' Ascending='False' />
</OrderBy>"
$ListItems = $oList.GetItems($Query)
Write-host "Number of items retrieved:" $ListItems.Count;
foreach($item in $ListItems)
{
Write-Host "Deleting Item - $($item.Id)"
$oList.GetItemById($item.Id).delete()
}
}

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

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
)

Iterating a SharePoint 2010 Atom feed

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" }
}