SharePoint PowerShell list filter - powershell

hoping someone can guide on the code below:
*$CreatedDate = (Get-Date $CreatedDateTime)
$AddedDateTime = (Get-Date $CreatedDate.AddMinutes(190))
Write-Host "CD:" $CreatedDate
Write-Host "AD:" $AddedDateTime
$ItemsColl = $ReviewList.Items | where {($_['Created'] -ge $CreatedDate) -and ($_['Created'] -le $AddedDateTime)}*
this is suppose to return everything within a date range, i pass on created date, add 190 minutes to that date, and the return should be everything from a workflow task list that was created as a task.
this does bring some but is missing most of the items in the list, i was hoping for an opinion to see if there is any obvious mistakes or maybe a new way of doing this.
Thanks in advance
ok so here is the scenario, when someone sends a document for approval, this creates a new version of document (uk Time), then a task is created by system account (Swiss Time +1hr from uk). I have a function that exports all the metadata for each version of the document into a csv format. where i'm struggling is filtering the reviewer list where all the tasks for each reviewer are stored.
i have two functions in my script GetMetadata and GetReviews.
Get metadata gets all metadata for each versions of the document, where a status changes to review in progress it suggests that the document has gone for a review so therefore we have to look into reviews list to find this item and see who the review was and what the outcome is, however the document could have been reviews multiple times and therefore i need to pass in document name, and datetime of created to filter the list, but date and time of created in review is 1hr and so ahead.
Script:
# ******* Variables Section ******************
#Define these variables
$WebURL="http://site"
$ModuleList = "Library With Versions"
$ReportFile = "D:\Migration\Test\CSV\ItemsForum.csv"
$ReviewList = "Review Tasks"
# *********************************************
#delete file if exists
If (Test-Path $ReportFile)
{
Remove-Item $ReportFile
}
#Get the Web and List
$Web = Get-SPWeb $WebURL
$ReviewList = $web.Lists.TryGetList($ReviewList)
#Get reviewers from review list
function GetReviews($DocumentName, $CreatedDateTime)
{
$CreatedDate = Get-Date $CreatedDateTime
#add 80 minutes, this would be plus one hr to swiss time plus account for time it takes to create item
$AddedCreatedList = Get-Date $CreatedDate.AddMinutes(80)
#filter and get items where document name matches workflow related item (this works but it's missing a lot of items as er image)
$ItemsColl = $ReviewList.Items | where {$_['WorkflowLink'] -match $DocumentName -and $_['Created'] -ge $CreatedDate -and $_['Created'] -le $AddedCreatedList}
#$ItemsColl = $ReviewList.Items
Write-Host "Item Count: " $ItemsColl.Count
$itemIds = ""
if($ItemsColl.Count -gt 0)
{
foreach ($item in $ItemsColl)
{
Write-Host $relatedItemUrl
#$relatedItem = $relatedItemUrl -split ','
#$rit = $relatedItem[1].Trim()
$itemIds += $item.id
$itemIds += ";"
}
Write-Host $itemIds
$itemIds = $itemIds.TrimEnd(";")
}
return $itemIds
}
function GetMetadata{
$List = $web.Lists.TryGetList($ModuleList)
#Check if list exists
if($List -ne $null)
{
#Get all list items
$ItemsColl = $List.Items | where {$_['Module'] -match $ModuleName}
#add headings
Add-Content -Path $ReportFile -Value "Item ID, Status, File Name + Version, Created, Review ID"
#Loop through each item
foreach ($item in $ItemsColl)
{
if ($item['Module'])
{
#Write-Host $item['Module']
ForEach($version in $item.Versions)
{
#Add version label to file in format: [Filename]_v[version#].[extension]
$filesplit = $version['Name'].split(".")
$fullname = $filesplit[0]
$fileext = $filesplit[1]
#$FullFileName = $fullname+"_v"+$version.VersionLabel+"."+$fileext
$FullFileName ="V_"+$version.VersionLabel+" " + $version['Name']
#Get Modified By
$user = $version["Editor"]
$userObj = New-Object Microsoft.SharePoint.SPFieldUserValue($web, $user)
$modifiedBy = $userObj.User.DisplayName
#get and format modified date
$ModifiedDate = ($version['Modified'] -as [datetime]).DateTime
$ModifiedDateF = Get-Date $ModifiedDate -format "yyyy-MM-ddTHH:mm:ss.fffZ"
#Write-Host $ModifiedDateF
#get and format created date
$CreatedDate = ($version.Created -as [datetime]).DateTime
$CreatedDateF = Get-Date $CreatedDate -format "yyyy-MM-ddTHH:mm:ss.fffZ"
$ReviwerID = ""
#get reviewers
#if status matches an item get review list id
if($version['WFStatus'] -eq 'Review in progress'){
#pass document name and created
$ReviwerID = GetReviews $version['Name'].TrimEnd('.docx') $version.Created
}
#add data
$VersionData = "$($item.id),$($version['WFStatus']),$($FullFileName),$($CreatedDateF),$($ReviwerID)"
#Write to report
Add-Content -Path $ReportFile -Value $VersionData
}
}
}
}
}
GetMetadata
Write-Host "Version history has been exported successfully!"
Output:
Ouput

Sample test script by SharePoint PowerShell, if your issue exists, provide more details for your script.
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$sourceWebURL = "http://sp:12001"
$sourceListName = "TestList"
$CreatedDate = Get-Date
$AddedDateTime = Get-Date $CreatedDate.AddMinutes(190)
$spSourceWeb = Get-SPWeb $sourceWebURL
$ReviewList = $spSourceWeb.Lists[$sourceListName]
$ItemsColl = $ReviewList.Items | where {($_['Created'] -ge $CreatedDate.AddMinutes(-10)) -and ($_['Created'] -le $AddedDateTime)}
Write-Host "CD:" $CreatedDate.AddMinutes(-10)
Write-Host "AD:" $AddedDateTime
$ItemsColl | ForEach-Object {
Write-Host $_['ID']
Write-Host $_['Title']
}
Update:
You could use PowerGUI editor to debug your script, the tool would help you find out most of logic issue.

Related

Increase Substring length dynamically

I am new to the community and need some help in Powershell.
I want the following code to dynamically check if the specific $sAMAccountName exists in an array or not.
If it exists, keep increasing the substring length by 1 and check the array again.
Instead of defining more variables like $sAMAccountName1 and $sAMaccountName2 (and so on) manualy.
$Nachname = "Nachname"
$Vorname = "Vorname"
$sAMAccountName = $Nachname+$Vorname.Substring(0,1)
$sAMAccountName1 = $Nachname+$Vorname.Substring(0,2)
$sAMAccountName2 = $Nachname+$Vorname.Substring(0,3)
$Array = #('NachnameV','NachnameVo','NachnameVor')
if($sAMAccountName -notin $Array){
Write-Host "$sAMAccountname does not exist :-)"
}
elseif($sAMAccountName1 -notin $Array){
Write-Host "$sAMAccountName1 does not exist :-)"
}
elseif($sAMAccountName2 -notin $Array){
Write-Host "$sAMAccountName2 does not exist :-)"
}
else{
Write-Host "$sAMAccountName2 does exist :-("
}
Thank you for your help.
Greetings,
PalimPalim
This may do what you need :
$Nachname = "Nachname"
$Vorname = "Vorname"
#$sAMAccountName = $Nachname+$Vorname
$Array = #('NachnameV','NachnameVo','NachnameVor')
$i = 0
do {
$i++
$sAMAccountName = $Nachname+$Vorname.Substring(0,$i)
write-host "i = $i"
write-host "account name = $sAMAccountName"
if($sAMAccountName -in $Array){
Write-Host "$sAMAccountName found"
}
} until ($sAMAccountName -notin $array)
Write-Host "$($Nachname+$Vorname.Substring(0,$i)) not found"
Where $i is used as an index which increases by 1 within the do until loop until the name being searched for no longer shows up in the array.
The write-host lines for i=$i and the account name aren't needed, but just let you see what the script is doing on each iteration round the loop, and can be removed.

Export and filter 365 Users Mailboxes Size Results Sort by Total Size form High to Low

Continuing from my previous question:
I have Powershell script that exports Mailboxes Size Results to CSV file.
The Results contain "Total Size" column that display results, and follow by Name.
However, i want the exported CSV file to filter and display only "greater then" 25GB Results, from high to low.
Like that:
Now, there is the traditional way to use excel to filter to Numbers in the CSV results- after the powershell export.
But, i want to have it in the CSV file, so i do not have to do it over and over again.
Here's the script:
Param
(
[Parameter(Mandatory = $false)]
[switch]$MFA,
[switch]$SharedMBOnly,
[switch]$UserMBOnly,
[string]$MBNamesFile,
[string]$UserName,
[string]$Password
)
Function Get_MailboxSize
{
$Stats=Get-MailboxStatistics -Identity $UPN
$IsArchieved=$Stats.IsArchiveMailbox
$ItemCount=$Stats.ItemCount
$TotalItemSize=$Stats.TotalItemSize
$TotalItemSizeinBytes= $TotalItemSize –replace “(.*\()|,| [a-z]*\)”, “”
$TotalSize=$stats.TotalItemSize.value -replace "\(.*",""
$DeletedItemCount=$Stats.DeletedItemCount
$TotalDeletedItemSize=$Stats.TotalDeletedItemSize
#Export result to csv
$Result=#{'Display Name'=$DisplayName;'User Principal Name'=$upn;'Mailbox Type'=$MailboxType;'Primary SMTP Address'=$PrimarySMTPAddress;'IsArchieved'=$IsArchieved;'Item Count'=$ItemCount;'Total Size'=$TotalSize;'Total Size (Bytes)'=$TotalItemSizeinBytes;'Deleted Item Count'=$DeletedItemCount;'Deleted Item Size'=$TotalDeletedItemSize;'Issue Warning Quota'=$IssueWarningQuota;'Prohibit Send Quota'=$ProhibitSendQuota;'Prohibit send Receive Quota'=$ProhibitSendReceiveQuota}
$Results= New-Object PSObject -Property $Result
$Results | Select-Object 'Display Name','User Principal Name','Mailbox Type','Primary SMTP Address','Item Count',#{Name = 'Total Size'; Expression = {($_."Total Size").Split(" ")[0]}},#{Name = 'Unit'; Expression = {($_."Total Size").Split(" ")[1]}},'Total Size (Bytes)','IsArchieved','Deleted Item Count','Deleted Item Size','Issue Warning Quota','Prohibit Send Quota','Prohibit Send Receive Quota' | Export-Csv -Path $ExportCSV -Notype -Append
}
Function main()
{
#Check for EXO v2 module inatallation
$Module = Get-Module ExchangeOnlineManagement -ListAvailable
if($Module.count -eq 0)
{
Write-Host Exchange Online PowerShell V2 module is not available -ForegroundColor yellow
$Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No
if($Confirm -match "[yY]")
{
Write-host "Installing Exchange Online PowerShell module"
Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
}
else
{
Write-Host EXO V2 module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet.
Exit
}
}
#Connect Exchange Online with MFA
if($MFA.IsPresent)
{
Connect-ExchangeOnline
}
#Authentication using non-MFA
else
{
#Storing credential in script for scheduling purpose/ Passing credential as parameter
if(($UserName -ne "") -and ($Password -ne ""))
{
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword
}
else
{
$Credential=Get-Credential -Credential $null
}
Connect-ExchangeOnline -Credential $Credential
}
#Output file declaration
$ExportCSV=".\MailboxSizeReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
$Result=""
$Results=#()
$MBCount=0
$PrintedMBCount=0
Write-Host Generating mailbox size report...
#Check for input file
if([string]$MBNamesFile -ne "")
{
#We have an input file, read it into memory
$Mailboxes=#()
$Mailboxes=Import-Csv -Header "MBIdentity" $MBNamesFile
foreach($item in $Mailboxes)
{
$MBDetails=Get-Mailbox -Identity $item.MBIdentity
$UPN=$MBDetails.UserPrincipalName
$MailboxType=$MBDetails.RecipientTypeDetails
$DisplayName=$MBDetails.DisplayName
$PrimarySMTPAddress=$MBDetails.PrimarySMTPAddress
$IssueWarningQuota=$MBDetails.IssueWarningQuota -replace "\(.*",""
$ProhibitSendQuota=$MBDetails.ProhibitSendQuota -replace "\(.*",""
$ProhibitSendReceiveQuota=$MBDetails.ProhibitSendReceiveQuota -replace "\(.*",""
$MBCount++
Write-Progress -Activity "`n Processed mailbox count: $MBCount "`n" Currently Processing: $DisplayName"
Get_MailboxSize
$PrintedMBCount++
}
}
#Get all mailboxes from Office 365
else
{
Get-Mailbox -ResultSize Unlimited | foreach {
$UPN=$_.UserPrincipalName
$Mailboxtype=$_.RecipientTypeDetails
$DisplayName=$_.DisplayName
$PrimarySMTPAddress=$_.PrimarySMTPAddress
$IssueWarningQuota=$_.IssueWarningQuota -replace "\(.*",""
$ProhibitSendQuota=$_.ProhibitSendQuota -replace "\(.*",""
$ProhibitSendReceiveQuota=$_.ProhibitSendReceiveQuota -replace "\(.*",""
$MBCount++
Write-Progress -Activity "`n Processed mailbox count: $MBCount "`n" Currently Processing: $DisplayName"
if($SharedMBOnly.IsPresent -and ($Mailboxtype -ne "SharedMailbox"))
{
return
}
if($UserMBOnly.IsPresent -and ($MailboxType -ne "UserMailbox"))
{
return
}
Get_MailboxSize
$PrintedMBCount++
}
}
#Open output file after execution
If($PrintedMBCount -eq 0)
{
Write-Host No mailbox found
}
else
{
Write-Host `nThe output file contains $PrintedMBCount mailboxes.
if((Test-Path -Path $ExportCSV) -eq "True")
{
Write-Host `nThe Output file available in $ExportCSV -ForegroundColor Green
$Prompt = New-Object -ComObject wscript.shell
$UserInput = $Prompt.popup("Do you want to open output file?",`
0,"Open Output File",4)
If ($UserInput -eq 6)
{
Invoke-Item "$ExportCSV"
}
}
}
#Disconnect Exchange Online session
Disconnect-ExchangeOnline -Confirm:$false | Out-Null
}
. main
How can i achieve that?
It's a bit of an unfortunate scenario, but if you're outputting the results to the file on each iteration, you have 2 options:
At the end of the script, read the output file, filter the >25gb mailboxes, sort the objects, then output again
Instead of writing the user mailbox to the file each user, save to a
variable instead. At the end, filter, sort, then export to file
Without going too far into the code...
Option 1
Might be simplest, as you're working off two input sizes already. After you've retrieved all mailboxes and gotten all statistics, read the exported csv file and filter + sort the data. Then, export the info back to the file, overwriting. Something like
$tempImport = Import-CSV $exportCSV | Where-Object {($_.'Total Size' -ge 25) -and ($_.Unit -eq "GB")} | Sort-Object 'Total Size' -descending
$tempImport | Export-CSV $exportCSV -noTypeInformation
PowerShell may not like overwriting a file read-in on the same command, hence the saving as a temp variable.
Option 2
Create a live variable storing all mailbox data, and write the information at the end of the script instead of opening the file to append data each iteration. Then, at the end of the script, filter and sort before exporting.
$global:largeMailboxes = #() # definition to allow reading through all functions
Then, instead of exporting to CSV each time, add the result to the above variable
$tvar = $null
$tvar = $Results | Select-Object 'Display Name','User Principal Name','Mailbox Type','Primary SMTP Address','Item Count',#{Name = 'Total Size'; Expression = {($_."Total Size").Split(" ")[0]}},#{Name = 'Unit'; Expression = {($_."Total Size").Split(" ")[1]}},'Total Size (Bytes)','IsArchieved','Deleted Item Count','Deleted Item Size','Issue Warning Quota','Prohibit Send Quota','Prohibit Send Receive Quota'
$global:largeMailboxes += $tvar
#
# Alternatively, only add the mailbox if it's larger than 25GB, to avoid adding objects you don't care about
if ($TotalItemSizeinBytes -ge 26843545600) # This is 25 GB, better to make a variable called $minSize or such to store this in, in case you want to change it later.
{
# Above code to add to global variable
}
Once all mailboxes have been added, sort the object
$global:largeMailboxes = $global:largeMailboxes | Sort-Object 'Total Size' -descending
Then export as needed
$global:largeMailboxes | Export-CSV $exportCSV -NoTypeInformation

Powershell - Make a menu out of text file

In my adventure trying to learn Powershell, I am working on an extension on a script I have made. The idea is to make script there by adding ".iso" files into a folder. It will use that content in a menu so that I later can use it to select an iso file for a WM in Hyper-V
This is my version of how it will get the content in the first place
Get-ChildItem -Path C:\iso/*.iso -Name > C:\iso/nummer-temp.txt
Add-Content -Path C:\iso/nummer.txt ""
Get-Content -Path C:\iso/nummer-temp.txt | Add-Content -Path C:\iso/nummer.txt
When this code is run it will send an output like what i want. But my question is how do I use this output in a menu?
This is the best practice way to do so in powershell :
#lets say your .txt files gets this list after running get-content
$my_isos = $('win7.iso','win8.iso','win10.iso')
$user_choice = $my_isos | Out-GridView -Title 'Select the ISO File you want' -PassThru
#waiting till you choose the item you want from the grid view
Write-Host "$user_choice is going to be the VM"
I wouldn't try to make it with System.windows.forms utilities as i mentioned in my comment, unless you want to present the form more "good looking".
If you don't want to go for a graphical menu, but rather a console menu, you could use this function below:
function Show-Menu {
Param(
[Parameter(Position=0, Mandatory=$True)]
[string[]]$MenuItems,
[string] $Title
)
$header = $null
if (![string]::IsNullOrWhiteSpace($Title)) {
$len = [math]::Max(($MenuItems | Measure-Object -Maximum -Property Length).Maximum, $Title.Length)
$header = '{0}{1}{2}' -f $Title, [Environment]::NewLine, ('-' * $len)
}
# possible choices: digits 1 to 9, characters A to Z
$choices = (49..57) + (65..90) | ForEach-Object { [char]$_ }
$i = 0
$items = ($MenuItems | ForEach-Object { '{0} {1}' -f $choices[$i++], $_ }) -join [Environment]::NewLine
# display the menu and return the chosen option
while ($true) {
cls
if ($header) { Write-Host $header -ForegroundColor Yellow }
Write-Host $items
Write-Host
$answer = (Read-Host -Prompt 'Please make your choice').ToUpper()
$index = $choices.IndexOf($answer[0])
if ($index -ge 0 -and $index -lt $MenuItems.Count) {
return $MenuItems[$index]
}
else {
Write-Warning "Invalid choice.. Please try again."
Start-Sleep -Seconds 2
}
}
}
Having that in place, you call it like:
# get a list if iso files (file names for the menu and full path names for later handling)
$isoFiles = Get-ChildItem -Path 'D:\IsoFiles' -Filter '*.iso' -File | Select-Object Name, FullName
$selected = Show-Menu -MenuItems $isoFiles.Name -Title 'Please select the ISO file to use'
# get the full path name for the chosen file from the $isoFiles array
$isoToUse = ($isoFiles | Where-Object { $_.Name -eq $selected }).FullName
Write-Host "`r`nYou have selected file '$isoToUse'"
Example:
Please select the ISO file to use
---------------------------------
1 Win10.iso
2 Win7.iso
3 Win8.iso
Please make your choice: 3
You have selected file 'D:\IsoFiles\Win8.iso'

Update SharePoint list field using powershell based on Date comparison

I am currently try to update SharePoint field (Dropdown field called Overdue to Yes if the dateFormat field is equal or less than current date. At this stage, it does not change the value. Is there anything that i missed. Please refer the code i have below. Thanks
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date (Get-Date) -format dd/MM/yyyy;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = Get-Date $deadline -format dd/MM/yyyy;
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
$item.Update()
}
}
$SPWeb.Dispose();
I think you need to supply an index/numerical numerical value for the choice. See the blog post here.
As it mentions you could do:
$item["Overdue"] = 0; #assuming 0 == YES
Or
$item["Overdue"] = $list.Fields["Overdue"].GetFieldValue("YES");
New code for the datetime logic
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = [datetime]$deadline
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
Write-Debug $item["Overdue"]
$item.Update()
}
}
$SPWeb.Dispose();
if the Overdue column is a yes/no field (Boolean) I guess You can either do like Dana V suggested, so:
$item["Overdue"] = 0
or
$item["Overdue"] = $true

Monitor Azure Files in Storage Account for event : file creation

I know I could use System.IO.FileSystemWatcher in a Powershell script to detect when a file is created in Azure files (in my storage account). Is there a better way to detect a file being created than this method ?
I can't seem to find any logs that I could perhaps parse ?
Thanks
This could do you if you really didn't want to use the FileSystemWatch
$Files = Get-ChildItem -file -Recurse "C:\Temp"
$IfOlderThan = 60
$NewlyCreated = #()
$OldCreated = #()
$Count = 0
Foreach ($file in $files){
if($file.CreationTime -gt (Get-Date).AddMinutes(-$IfOlderThan)){
$NewlyCreated += $file
} Else {
$OldCreated += $file
}
}
Write-Host "Found " -NoNewline;Write-host $($NewlyCreated.Count) -NoNewline -ForegroundColor Green; Write-Host " file\s that have been created in the last $IfOlderThan minutes"
$NewlyCreated | select Name, Fullname, CreationTime