Looping through a CSV column using powershell [duplicate] - powershell

This question already has answers here:
Read Column data from CSV
(1 answer)
Read a Csv file with powershell and capture corresponding data
(3 answers)
Closed 7 years ago.
I have a CSV file like below
Data,Name,Age
Test,T1,22
Test2,T2,23
Test3,T3,24
I want to do some processing like this
Foreach(header in CSvFile.Headers)
{
//Loop through the column data
}
EDIT : Displaying what I am looking for in real code.
Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
$SiteUrl = "http://www.dev.com"
$Web = Get-SPWeb $SiteUrl
$description = "Group with contribute access."
$permissionLevel = "Contribute"
foreach($groupName in **CSV.Headers**)
{
$web.SiteGroups.Add($groupName, $web.SiteUsers["Test\data"], $web.SiteUsers["Test\data"], $description)
$group = $web.SiteGroups[$groupName]
$loc = Get-Location
$Users = "Test\data"
$roleAssignment = new-object Microsoft.SharePoint.SPRoleAssignment($group)
$roleDefinition = $web.Site.RootWeb.RoleDefinitions[$permissionLevel]
$roleAssignment.RoleDefinitionBindings.Add($roleDefinition)
$web.RoleAssignments.Add($roleAssignment)
$web.Update()
foreach ($User in **groupName.columnData**) {
$Web.EnsureUser($User)
Set-SPUser -Identity $User -Web $SiteUrl -Group $group
}
}
$Web.Dispose();
Can some one please tell me how to achieve this in powershell.
Thanks

How about something like this:
$csvPath = "C:\temp\temp.csv"
$csv = Import-CSV $csvPath
$csvHeaders = ($csv | Get-Member -MemberType NoteProperty).name
foreach($header in $csvHeaders) {
...etc...

Related

Downloading SharePoint online list items' attachments locally will not allow me to open those files (seems the file are corrupted)

I have a SharePoint online list , and this list contain items with attachments. so i want to download all the list item attachems. so i wrote this PnP Power Shell sript:-
$ApprovalListItems = Get-PnPListItem -List "tickets" -PageSize 1000 -ScriptBlock { Param($items) $items.Context.ExecuteQuery()} | ForEach-Object {
$ctx = Get-PnPContext
$spSourceWeb= Get-PnPWeb
$ItemAttachmentURLPrefix = 'https://****.sharepoint.com/Lists/tickets/Attachments/'+$_['ID']+'/'
$attachmentCollection = ForEach-Object{Get-PnPProperty -ClientObject $_ -Property "AttachmentFiles"}
$AttachmentSeq = 0
ForEach($Attachment in $attachmentCollection)
{
Write-Host "`tDownloading Attachement: " $attachment $ItemAttachmentURLPrefix
$AttachmentSeq++
$AttachmentDataObj = "" | Select "Attachment Seq", "JDE Company", "Vendor Number", "Vendor Invoice Number", "Attachment Name", "Attachment System Name", "Job-run Date/Time Stamp"
Write-Host $Attachment.FileName
$file = Get-PnPFile -Url ($ItemAttachmentURLPrefix + $Attachment.FileName)
$bytes = (Get-PnPFile -Url ($ItemAttachmentURLPrefix + $Attachment.FileName)).OpenBinaryStream()
$name = "C:\Attachments\"+$Attachment.FileName
$fs = New-Object System.IO.StreamWriter($name, "OpenOrCreate")
$fs.Write($bytes, 0 , $bytes.Length)
$fs.Close()
$stream = $streamResult.Value
Write-Host $file.Name
Write-Host $stream.Name
}
}
but the files that will get saved can not be opened, for example this excel sheet will raise this error:-
while a pdf will raise this error:-
any advice what is wrong with my script?
Thanks
Use PnP PowerShell code in below format to download list item attachments to local folder:
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/dev -Interactive
$listitem = Get-PnPListItem -List Employee -Id 2
$attachments = ForEach-Object {Get-PnPProperty -ClientObject $listitem -Property "AttachmentFiles"}
$attachments | ForEach-Object { Get-PnPFile -Url $_.ServerRelativeUrl -FileName $_.FileName -Path "E:\SharePoint\Documents" -AsFile }
Source: Read items attachments and write them to local folder

export to csv powershell script using multiple foreach statements

I have following powershell script reading from csv and exporting to another csv. It's working in terms of basic functionality. Script below is currently exporting as such:
USERS
jdoe
mprice
tsmith
Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
# csv file name
[parameter(Mandatory=$false)][string]$CsvFilePath = ".\AllSiteCollectionsLocal.csv"
$csvItems = Import-Csv $CsvFilePath
$resultsarray = #()
$firstObject = New-Object PSObject
# iterate lines in csv
foreach($Item in $csvItems)
{
$site = new-object Microsoft.SharePoint.SPSite($Item.SiteCollection)
$web = $site.openweb()
$siteUsers = $web.SiteUsers
Write-Host $Item.SiteCollection -ForegroundColor Green
foreach($user in $siteUsers)
{
Write-Host $user.LoginName
$loginnames = #{
USERS = $user.LoginName
}
$resultsarray += New-Object PSObject -Property $loginnames
}
$web.Dispose()
$site.Dispose()
$resultsarray | export-csv -Path c:\temp\sitesandusers.csv -NoTypeInformation
}
I need to export as below. Note, I dont even need a header, but do need $Item.SiteCollection value to print out between each iteration of users under each site, so the outer foreach needs to print $Item.SiteCollection then the inner foreach would print $user.LoginName
http://test1.com
jdoe
mprice
http://test2.com
tsmith
I'm guessing you wanted to do parameters for your script to be called from elsewhere? As of now, your metadata attribute on $CsvFilePath are redundant to what PowerShell already does for you.
As for your question, you would just have to append $Item.SiteCollection to your PSObject. This too isn't needed as PowerShell streaming capabilities allow you to assign directly to a variable; so no need for += - which can be computationally expensive on larger lists slowing overall performance. Now we end up with:
Param (
[parameter(Mandatory=$false)]
[string]$CsvFilePath = ".\AllSiteCollectionsLocal.csv"
)
Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
$csvItems = Import-Csv $CsvFilePath
$variable = foreach($Item in $csvItems)
{
$site = new-object Microsoft.SharePoint.SPSite($Item.SiteCollection)
$web = $site.openweb()
$siteUsers = $web.SiteUsers
Write-Host -Object $Item.SiteCollection -ForegroundColor Green
Write-Output -InputObject $Item.SiteCollection
foreach($user in $siteUsers)
{
Write-Host -Object $user.LoginName
Write-Output -InputObject $user.LoginName
}
$null = $web.Dispose()
$null = $site.Dispose()
}
$variable | Out-File -FilePath 'c:\temp\sitesandusers.csv'
Bypassing $variable you can assign the output directly to the file placing the export outside the first foreach statement.
This requires the use of a sub-expression operator $() to wrap around the loop.
Also added a Param ( ) statement for your parameter declaration.
Didn't mess with the parameter attributes as it can show the Authors intentions regardless if it's needed or not.
Probably should add that, Write-Output will explicitly write to the success stream allowing the values to be assigned to the variable, whereas Write-Host writes to the information stream, so no object pollution (duplicates) occur.

Creating and displaying a custom object in a custom object [duplicate]

This question already has answers here:
Unexpected ConvertTo-Json results? Answer: it has a default -Depth of 2
(2 answers)
Closed 2 years ago.
My goal was to create a collection of objects (SharePoint sites) with in each object another collection of objects (Lists in that sites). After writing the code below I thought I succeeded but I don't know how to access the Lists objects.
$sites = #()
foreach ($s in $Subsites){
Connect-PnPOnline -Url $s.Url
$Lists = Get-PnPList
$ctx = Get-PnPContext
$web = $ctx.web
$ctx.Load($web)
$ctx.ExecuteQuery()
$listsCollection = #()
foreach ($list in $Lists) {
$props = #{
ListName = $list.Title
ListItems = $list.ItemCount
LastDeletedDate = $list.LastItemDeletedDate
LastModifiedDate = $list.LastItemUserModifiedDate
}
$listObj = New-Object -TypeName PSObject -Property $props
$listsCollection += $listObj
}
$props = #{
SiteName = $s.Title
LastModified = $web.LastItemUserModifiedDate
URL = $web.Url
Lists = $listsCollection
}
$webObj = New-Object -TypeName PSObject -Property $props
$sites += $webObj
}
After running the code I can access the site information like I expected to do
$sites[0].SiteName gives me: "My site name"
And I can see the list information in the object too but it seems to me that it is only string information and not real objects.
$sites[0].Lists gives me:
#{LastDeletedDate=06/12/2019 09:24:57; LastModifiedDate=06/12/2019 09:27:30; ListName=MyList1; ListItems=6}
#{LastDeletedDate=04/19/2019 12:48:14; LastModifiedDate=04/19/2019 12:48:14; ListName=MyList2; ListItems=0}
but I can't acces ListName by using $sites[0].Lists[0].ListName . Get-Member gives me just one property Length. The TypeName of the object is System.String. I tried several other things like using other ways to create a CustomObject and using select -ExpandProperty or Key and Value but no succes either.
Sorry, I didn't include the intermediate steps I used. In that steps I output the $sites object with $sites | ConvertTo-Json | Out-File .\sites.json and later on I import it again with Get-Content .\stes.json | ConvertFrom-Json. After adding the Depth parameter with ConvertToJson -Depth 5 as suggested by AdminOfThings it worked perfectly

Bulk disable local accounts found in text/csv file

I am in need to disable about 250 local user accounts based on input in a text file or CSV-file and then export the result into a CSV file.
I have searched the net quiet a bit but I'm unable to find anything i can tailor togheter.
Here is what I've tried;
This is one I tried:
$Workdir = 'C:\scripts\'
$Output = $Workdir + 'Disabled-UserReport.csv'
$InputFile = $Workdir + 'Users_To_Disable.csv'
$Servers = 'LOCALHOST'
Import-CSV $InputFile | ForEach-Object {
$Server = $_ ([ADSI]"WinNT://$Server").Children | ? {$_.SchemaClassName -eq 'user'} | % { $User.UserFlags[0] = $User.UserFlags[0] -bor 0x2 $User.SetInfo() }
}| Export-CSV -Encode UTF8 -Path C:\scripts\Disabled-Users.csv
This is try two:
$Servers = 'LOCALHOST'
$Username = Import-CSV "C:\scripts\Users_To_Disable.csv"
$Username | FOREACH {
$Server = $_
$objGroup = [ADSI]("WinNT://$env:ComputerName/User")
$objGroup.PSBase.Invoke("Add",$objUser.PSBase.Path)
$User.description = $description
<#$User.userflags = $DisableUser#>
$User.setinfo()
} | Export-CSV -Encode UTF8 -Path C:\scripts\Disabled-Users.csv
I know there is something very wrong with both scripts....and as you can see I'm a noob learning PS whenever I get the time :)
It would be great if it works in PS2. But required to work with PS4.
Any help is appreciated!
Yes I finally managed last week.... Thank you!
Code if some other newbies want. It disabled accounts based on inputs from a textfile and also sets the accounts to Password Never Expire and Password Cannot Be Changed;
$EnableUser = 512
$DisableUser = 2
$PasswordNotExpire = 65536
$PasswordCantChange = 64
$users = Get-Content -path "C:\Users_To_Disable.txt"
$computer = $env:COMPUTERNAME
Foreach($user in $users){ $user = [ADSI]"WinNT://$computer/$user"
$user.userflags = $DisableUser+$PasswordNotExpire+$PasswordCantChange
#$user.Userflags = $EnableUser+$PasswordNotExpire+$PasswordCantChange
$user.setinfo()
}
Sorry, this isn't an answer, and I'm about to leave work, but did you see this article? http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/22/use-powershell-to-enable-or-disable-a-local-user-account.aspx
That might help. I apologize if it doesn't.
This isn't your answer but it is a high hit in google for disabling local user accounts in PowerShell. Here is what I assembled using your answer
function user-enable()
{
param([string] $username, [boolean] $enabled)
$disableFlag = 2
$enableFlag = 512
$flag = if ($enabled) {$enableFlag} else {$disableFlag} # powershell turnary lol
$computername = $env:COMPUTERNAME
$user = [adsi]"WinNT://$computername/$username"
$user.userflags = $flag
$user.setinfo()
}
user-enable -username "packer" -enabled $false

Delete Navigation Node with Powershell from SharePoint Quicklaunch in all sites in a site collection

I'm trying to write a powershell script to go through all the sub sites in a site collection and remove a node that is no longer required.
I've placed my script below - but I'm getting an error on Get-SPWeb : The pipeline has been stopped - I'm thinking I may need to set a parameter to stop the pipe being closed? Any help is awesome!
$site = Get-SPSite http://sitecollurl
$site | get-spweb -limit all | foreach-object{
$webURL = $_.url
$web = Get-SPWeb $webURL
$navigationNodes = $web.Navigation.QuickLaunch
ForEach ($Node in $NavigationNodes)
{
if($node.Title -eq "My User Profile")
{
$node.Delete()
}
}
$web.Dispose()
}
I just came across this issue so thought I would share, note in my case it was to remove all QuickLaunch menu Items titled "Libraries" if it had no children:
Get-SPSite http://sitecollectionurl | get-spweb -limit all | foreach-object{
$webURL = $_.url
$web = Get-SPWeb $webURL
$pubWeb = [Microsoft.Sharepoint.Publishing.PublishingWeb]::GetPublishingWeb($Web)
$qlNav = $pubWeb.Navigation.CurrentNavigationNodes
$qlHeading = $qlNav | where { $_.Title -eq "Libraries" }
$qlLibraries = $qlHeading.Children
if($qlLibraries.Count -eq 0)
{
$qlHeading.delete()
}
else
{
$qlLibraries | Select Title,ID
$count = $qlLibraries.Count
write-host "Other Libraries are listed on $url. Count = $count"
}
$pubWeb.Update()
$web.Dispose
}
Obviously replace http://sitecollectionurl with your own site collection URL, and libraries with whatever title you are trying to remove.
Dan