I'm attempting to change the field contents for multiple entries in a list. So far I've gotten to the point that I can edit the list, add columns really, but can't find anything on how to edit the field text. Here is what I have currently:
EDIT:
I've found a bunch of info for 2010 which isn't applicable but I've updated the code to almost get there. I'm getting 'null array' errors when I connect to the list now. I'm hopeful because I'm able to connect, but still can't get the field to change. I've updated my if statement as well to what is I believe a better format.
#Load necessary module to connect to SPOService
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null
#Login Information for script
$User = "user#email.com"
$Pass = "password"
$creds = New-Object System.Management.Automation.PSCredential($User, (ConvertTo-SecureString $Pass -AsPlainText -Force));
#Connect to SharePoint Online service
Write-Host "Logging into SharePoint online service." -ForegroundColor Green
Connect-SPOService -Url https://site-admin.sharepoint.com -Credential $creds
#Get the Necessary List
Write-Host "Getting the required list." -ForegroundColor Green
$WebUrl = 'https://site.sharepoint.com/'
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$List = $Context.Web.Lists.GetByTitle("VacationRequestForm")
#Edit existing list items
$items = $List.items
foreach($item in $items)
{
if($item["Export Flag"] -eq "New")
{
Write-Host "Changing export flags to Complete." -ForegroundColor Green
$item["Export Flag"] = "Complete"
$item.Update()
}
}
Write-Host "Your changes have now been made." -ForegroundColor Green
I am guessing you have trimmed the script since you are missing things like defining $context and such. You don't have any ExecuteQuery() calls.
MSDN doc on SP 2013 CSOM List Item tasks, which has C# examples of what you need and can be translated to PowerShell.
It generally looks like you have everything but if you could include your whole script I can try and run your script directly.
EDIT: with the updates here is the code that you need
#Load necessary module to connect to SPOService
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null
#Login Information for script
$User = "user#email.com"
$Pass = "password"
$WebUrl = "https://site.sharepoint.com/"
#Connect to SharePoint Online service
Write-Host "Logging into SharePoint online service." -ForegroundColor Green
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$Context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User, (ConvertTo-SecureString $Pass -AsPlainText -Force))
#Get the Necessary List
Write-Host "Getting the required list." -ForegroundColor Green
$List = $Context.Web.Lists.GetByTitle("VacationRequestForm")
$Query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(100);
$Items = $List.GetItems($Query);
$Context.Load($Items);
$Context.ExecuteQuery();
#Edit existing list items
foreach($item in $Items)
{
if($item["Export_x0020_Flag"] -eq "New")
{
Write-Host "Changing export flags to Complete for Id=$($item.Id)." -ForegroundColor Green
$item["Export_x0020_Flag"] = "Complete"
$item.Update()
$Context.ExecuteQuery();
}
}
Write-Host "Your changes have now been made." -ForegroundColor Green
You had a space in your Export Flag name and SharePoint will not have that in the name of the field. By default it will replace that with a _x0020_ string. This value will be based on the first name of the field. So if you change this field name in the future, you will still refer to it as 'Export_x0020_Flag' in this script. I am doing the .ExecuteQuery() for each update but you could do this once at the end of the loop. There is also the limit of 100 records in the query. If you only want records with "New" you should change the CamlQuery to just pull those records back.
Related
This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 5 months ago.
I wrote a script that allows me to query the whole Azure database park:
#$ErrorActionPreference = 'SilentlyContinue'
# Connect to Azure
$azureAccount = Connect-AzAccount
# Get Azure Access Token (we will use this to query the databasees)
#$azureToken = Get-AzAccessToken -ResourceUrl https://database.windows.net
$access_token = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
# Queries will be picked up from here
$folderPath = '.\Queries'
# Choose how to format each date ("yyyy-MM-dd") or ("yyyy-MM-dd HH:mm:ss")
$DateTime = (Get-Date).ToString("yyyy-MM-dd")
# List Azure Sunscriptions
Get-Azsubscription | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.Name)"; $a++}
$SubscriptionChoice = Read-Host -Prompt "Copy/paste the name of the Subscription that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
# Iterate into subscriptoins and print names
foreach ($gs in $SubscriptionChoice) {
Select-Azsubscription -Subscription "$gs" | Out-Null
Write-Host "Let's browse into Azure Sunscription: " -NoNewline
Write-Host (Get-AzContext).Subscription.Name -ForegroundColor green
# Fins all Azure SQL Server
Get-AzSqlServer | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.ServerName)"; $a++}
$SqlServerChoice = Read-Host -Prompt "Copy/paste the name of the SQL Server that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
if ($SqlServerChoice = "All"){
$SqlServerChoice = Get-AzSqlServer
}
Foreach ($server in $SqlServerChoice){
$DatabaseChoice = Get-AzSqlDatabase -ServerName $server.ServerName -ResourceGroupName $server.ResourceGroupName | Where-Object DatabaseName -NE "master"
Foreach ($database in $DatabaseChoice){
(Get-ChildItem $folderPath | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} ).Foreach{
Invoke-Sqlcmd -ServerInstance $server.FullyQualifiedDomainName -Database $database.DatabaseName -AccessToken $access_token -InputFile $psitem.FullName | Export-Csv -Path ".\Results\$psitem.csv" -Append -NoTypeInformation
write-host "Executing $psitem on $database.DatabaseName"
}
}
}
}
However each time the query is executed against a database the Write-Hosts returns:
Executing DTU_to_vCore.sql on Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Here a picture:
This Write-Hosts comes from the line:
write-host "Executing $psitem on $database.DatabaseName"
In which you can find the two variables:
$psitem : which is the name of the file that contains the query
$database.DatabaseName : which should be the database name but instead of printing the database name is printing Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Why one of the two variable is not interpreted?
You need to encapsulate your variable property in a subexpression operator $().
write-host "Executing $psitem on $($database.DatabaseName)"
This is because only simple variables get expanded in an expandable string.
References
Only simple variable references can be directly embedded in an
expandable string. Variables references using array indexing or member
access must be enclosed in a subexpression.
Source: about_Quoting_Rules
Subexpression operator $( )
Returns the result of one or more statements. For a single result,
returns a scalar. For multiple results, returns an array. Use this
when you want to use an expression within another expression. For
example, to embed the results of command in a string expression.
PS> "Today is $(Get-Date)"
Today is 12/02/2019 13:15:20
PS> "Folder list: $((dir c:\ -dir).Name -join ', ')"
Folder list: Program Files, Program Files (x86), Users, Windows
Source: about_Operators
I wrote a script to list all vendors in the azure ad to check if they are working or not. the script find the logged in users for the past day and if there is a record it should print, if there is no record and the vendor did not logged in or work it should print no login records. but my script is not working well any one can help?
###########################Here is the code ##################
#get azure ad users
$AzADUsers = get-azureaduser
#start for loop
foreach ($user in $AzADUsers){
#list attributes
$dp = $user.DisplayName
$company = $user.CompanyName
# list of contractors/vendors who didn't log in during the day.
if ($company -eq "Vendor Resource - companyname1" -or $company -eq "Vendor Resource - companyname2" -or $company -eq "Vendor Resource - companyname3") {
#check if they logged in the past 24 hours
$SetDate = (Get-Date).AddDays(-1);
$SetDate = Get-Date($SetDate) -format yyyy-MM-dd
$AllSiginLogs = Get-AzureADAuditSignInLogs -Filter "createdDateTime gt $SetDate"
$LoginRecord = $AllSiginLogs | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}
else{
$lastLogin = 'no login record | Sick'
}
Write-Host "Last logon time : " $lastLogin $dp $company
Write-Host " "
}
}
in addition to our discussion:
Currently you loop through the $AzAdUsers and query foreach the SignInLogs. But you do not filter the SignInLogs for the specific user, you query all the time the same information and select the latest entry from that log, but it has no relation to the current user.
You have to filter the SignInLog for the specific user, e.g.:
$AllSiginLogs = Get-AzureADAuditSignInLogs -filter "Id eq '$($user.Id)' and createdDateTime gt $SetDate"
After that you could do:
$attrsht = #{
userId=$User.id
DisplayName=$user.displayname
LastSignIn=$LoginRecord.CreatedDateTime
}
new-object -typename psobject -property $attrsht
Btw. the AzModule will be replaced by the microsoft.graph modules. So it might be the right time to do the switch, which you have to do in any case until 2024.
If you do so, you can directly get the lastSignInDateTime from the user object:
#Switch to beta API
select-mgprofile -name beta
$lastSignIn = get-mguser -userId $user.id -Property signinactivity
$lastSignIn.LastSignInDateTime
In regards to you latest comment:
once again, if you want to know the last signInDateTime for a specific user you have to filter for that user id. if you filter by companyname you will probably get several users back and then you have to loop over this array of users and query the signInLog foreach user. the problem you are facing is that you miss to specify consistensylevel and countvariable, e.g.:
$company = "MyCompanyName"
$users = Get-MgUser -filter "companyname eq '$company'" -ConsistencyLevel eventual -CountVariable $null -property Id,CompanyName,DisplayName
select-mgprofile -Name beta
$lastSignInDateTime = #(
foreach ($user in $users){
$LoginRecord = get-mguser -userId $user.id -Property signinactivity
$attrsht = #{
userId=$User.id
DisplayName=$user.displayname
CompanyName=$user.CompanyName
LastSignIn=$LoginRecord.signinactivity.LastSignInDateTime
}
new-object -typename psobject -property $attrsht
}
)
You need to have the MgGraph module installed to run the above mentioned cmdlets -> install-module microsoft.graph
More information in regards to consistensylevel:
https://devblogs.microsoft.com/microsoft365dev/build-advanced-queries-with-count-filter-search-and-orderby/
When I try to add the device looping through a txt file, it says its already a member. When I check the members in the group, nothing changes. From what I've researched, this is due to hybrid setup with on-prem and Azure AD, but I would like to add the devices to the Azure group.
$azgroup = "myGroup"
$machines = get-content ".\deviceList.txt"
write-host "Getting Object ID of group.." -ForegroundColor Green
$objid = (get-azureadgroup -Filter "DisplayName eq '$azgroup'" ).objectid
write-host "Getting group members (We dont want duplicates!).." -ForegroundColor Cyan
$members = Get-AzureADGroupMember -ObjectId $objid -all $true | select displayname
foreach ($machine in $machines) {
$refid = Get-AzureADDevice -Filter "DisplayName eq '$machine'"
$result = ""
$result = ($members -match $machine)
if($result -eq ""){
try{
Write-host "Adding " $refid.displayname -ForegroundColor Cyan
Add-AzureADGroupMember -ObjectId $objid -RefObjectId $refid.objectid[0]
}
catch{
write-host "An error occured for " $refid.displayname -ForegroundColor Red
}
}
else
{
write-host $machine " is already a member" -ForegroundColor Green
}
}
I tried treating the specific ObjectID as an array but neither worked to add to Azure AD group
Add-AzureADGroupMember -ObjectId $objid -RefObjectId $refid.objectid[0]
If the AzureAD module doesn't work within a hybrid infrastructure, is there any way to bulk add devices to a group in Azure AD?
Here is the working solution. Ok so due to each device having more than one reference IDs, I just treated like an array. This is the part of my code I had to change:
[String]$refid = (Get-AzureADDevice -Filter "DisplayName eq '$machine'")[0].ObjectId
I misplaced the my index ([0]) and placed it after the property, not before it. Then I made sure it outputed a string for good measure, although you can check this with the .gettype() method. Because the on-premise DC and Azure sync, you can use these Device reference IDs interchangeably. It also didnt help outputting a custom error at first, thats what I get for copy-pasting part of someone else's code...
I'm new to Powershell. I'm trying to automate a few things. My biggest obstacle right now is trying to get a failed Test-Connection to export into Excel with a -Foreground color. Green for "Online" and red for "Offline."
Another issue, it does ping a computer offline, it writes to the Computer Pane as multiple exceptions. Is there a way to make it do it only one time?
I would like to have the "Offline" ping in Excel (1,4).
Any help will be definitely appreciated! If you don't mind explaining how and why it works too, that would be perfect.
Thank you.
$Comps = Get-Content -Path "FilePath\ComputerList.txt"
$Date = Get-Date -Format MM-dd-yyyy
#Stop-Process -Name "Excel" -ErrorAction SilentlyContinue
#Suspends activity for a # of seconds.
Start-Sleep 3
$XL = New-Object -comobject Excel.Application
$xL.displayAlerts = $false
$WB = $XL.Workbooks.Add()
$WS = $WB.Worksheets.Item(1)
$WS.Cells.Item(1,1) = "Date"
$WS.Cells.Item(1,2) = "IP Address"
$WS.Cells.Item(1,3) = "Computer Name - Online"
$WS.Cells.Item(1,4) = "Computer Name - Offline"
$counter = 2
$CompStatus = #()
$Comps = Get-Content -Path "FilePath\ComputerList.txt"
$Processes = Test-Connection -ComputerName $Comps -Count 1| select #{n='TimeStamp';e={Get-Date}}, Address, ProtocolAddress
foreach($Proc in $Processes) {
If(Test-Connection $Comps){
Test-Connection $Comp
}
write-host "$Comp is online" -ForegroundColor Green
$WS.cells.item(2,1) = $Proc.TimeStamp
$WS.cells.item($counter,2) = $Proc.ProtocolAddress
$WS.cells.item($counter,3) = $Proc.Address
$WS.columns.autofit()
$counter++
}else{
write-host "$Comp is offline" -ForegroundColor Red
$WS.cells.item($counter,4) = $Proc.$CompStatus += $Comp + "Offline"
}
$XL.Visible = $True
$XL.ActiveWorkbook.SaveAs("FilePath\ComputerListPinged_$Date")
You really should have a look at Douglas Finke's ImportExcel Module, it has a Conditional Formatting parameter that works fine for what you need. You can also set RGB colors on it same as you would see them on Excel (like the classic light green background with green font, and light red background with red fount, etc). I think it will make your life easier.
Here are a few examples: https://dfinke.github.io/powershell/2020/05/02/PowerShell-Excel-and-Conditional-Formatting.html
The module itself is pretty easy to use and there are plenty of guides on Google.
I have 200 unsorted users in office 365. I want to find an easy way to manage who they are and what security group each user belongs to.
Is there an easy way to export username and what groups each user belongs to?
Iam quite new to poweshell...
But i want to export a CSV file with user and gruops.
Is this possible?
Or do you recommend any other way to quick get an overview of all users and what grups they belong to.
Some users need to be in multiple groups and i suspect some users are missing in groups they should be in..
Thanks for any tips i can get.
################################################################################################################################################################
# Script accepts 2 parameters from the command line
#
# Office365Username - Optional - Administrator login ID for the tenant we are querying
# Office365Password - Optional - Administrator login password for the tenant we are querying
#
#
# To run the script
#
# .\Get-DistributionGroupMembers.ps1 [-Office365Username admin#xxxxxx.onmicrosoft.com] [-Office365Password Password123]
#
#
# Author: Alan Byrne
# Version: 2.0
# Last Modified Date: 16/08/2014
# Last Modified By: Alan Byrne alan#cogmotive.com
################################################################################################################################################################
#Accept input parameters
Param(
[Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)]
[string] $Office365Username,
[Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)]
[string] $Office365Password
)
#Constant Variables
$OutputFile = "DistributionGroupMembers.csv" #The CSV Output file that is created, change for your purposes
$arrDLMembers = #{}
#Remove all existing Powershell sessions
Get-PSSession | Remove-PSSession
#Did they provide creds? If not, ask them for it.
if (([string]::IsNullOrEmpty($Office365Username) -eq $false) -and ([string]::IsNullOrEmpty($Office365Password) -eq $false))
{
$SecureOffice365Password = ConvertTo-SecureString -AsPlainText $Office365Password -Force
#Build credentials object
$Office365Credentials = New-Object System.Management.Automation.PSCredential $Office365Username, $SecureOffice365Password
}
else
{
#Build credentials object
$Office365Credentials = Get-Credential
}
#Create remote Powershell session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $Office365credentials -Authentication Basic –AllowRedirection
#Import the session
Import-PSSession $Session -AllowClobber | Out-Null
#Prepare Output file with headers
Out-File -FilePath $OutputFile -InputObject "Distribution Group DisplayName,Distribution Group Email,Member DisplayName, Member Email, Member Type" -Encoding UTF8
#Get all Distribution Groups from Office 365
$objDistributionGroups = Get-DistributionGroup -ResultSize Unlimited
#Iterate through all groups, one at a time
Foreach ($objDistributionGroup in $objDistributionGroups)
{
write-host "Processing $($objDistributionGroup.DisplayName)..."
#Get members of this group
$objDGMembers = Get-DistributionGroupMember -Identity $($objDistributionGroup.PrimarySmtpAddress)
write-host "Found $($objDGMembers.Count) members..."
#Iterate through each member
Foreach ($objMember in $objDGMembers)
{
Out-File -FilePath $OutputFile -InputObject "$($objDistributionGroup.DisplayName),$($objDistributionGroup.PrimarySMTPAddress),$($objMember.DisplayName),$($objMember.PrimarySMTPAddress),$($objMember.RecipientType)" -Encoding UTF8 -append
write-host "`t$($objDistributionGroup.DisplayName),$($objDistributionGroup.PrimarySMTPAddress),$($objMember.DisplayName),$($objMember.PrimarySMTPAddress),$($objMember.RecipientType)"
}
}
#Clean up session
Get-PSSession | Remove-PSSession