Can't access object property from inside nested loop - powershell

Below is my code, I have tried making the object a global variable as well but that doesn't seem to help. Doing += syntax gives the same error as .add() syntax.
foreach ($x in $groups_data) {
$group_name = $x.targetName
$group_shifts_path = "$base/api/xm/1/groups/$group_name/shifts"
$group_shifts_req = Invoke-WebRequest -Credential $cred -Uri $group_shifts_path
$group_shifts_res = ConvertFrom-Json $group_shifts_req.Content
$group_shifts_data = $group_shifts_res.data
foreach ($y in $group_shifts_data) {
$shift_name = $y.name
$shift_id = $y.id
$group_info = #{
'group_name' = $group_name
'offending_shifts' = #{}
}
$group_info = $group_info | ConvertTo-Json
$group_shift_members_path = "$group_shifts_path/$shift_id/members"
$group_shift_members_req = Invoke-WebRequest -Credential $cred -Uri $group_shift_members_path
$group_shift_members_res = ConvertFrom-Json $group_shift_members_req.Content
$group_shift_members_data = $group_shift_members_res.data
foreach ($z in $group_shift_members_data) {
if ($z.recipient.recipientType -ne 'PERSON') {
$group_info.offending_shifts += $shift_name # HERE'S MY ISSUE
break
}
}
}
}
There error I am getting is the following:
The property 'offending_shifts' cannot be found on this object. Verify that the
property exists and can be set.
At \\etoprod\xMatters\PowerShell Scripts\Group Shift Cleanup & Notify.ps1:42 char:17
+ $group_info.offending_shifts += $shift_name
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Why can't I access this property?

Related

PowersShell script doesn't work remotely with Invoke-Command but works perfectly locally

I have a script to check for and download windows updates. It isn't working remotely and I would like to know why. Here is the script:
$UpdateSession = New-Object -Com Microsoft.Update.Session
$updatesToDownload = New-Object -Com Microsoft.Update.UpdateColl
$updatesToInstall = New-Object -Com Microsoft.Update.UpdateColl
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
$Downloader = $UpdateSession.CreateUpdateDownloader()
$Installer = $UpdateSession.CreateUpdateInstaller()
# Check for updates ---------------------------------------------------------------------
if ($SearchResult.Updates.Count -gt 0) {
Write-Host("All updates found: " + $SearchResult.Updates.Count)
For ($X = 0; $X -lt $SearchResult.Updates.Count; $X++) {
$Update = $SearchResult.Updates.Item($X)
if ($Update.KBArticleIDs -eq '2267602') {
Write-Host("Updates with Ids 2267602 found: " + $Update.Title)
$updatesToDownload.Add($Update)
Write-Host("Update " + $Update.Title + " added to download list")
}
}
}
else {
# Write-Host(0) # No Security Intelligence Updates
Write-Host("No update found")
Exit
}
# Download updates ----------------------------------------------------------------------
if ($updatesToDownload.Count -gt 0) {
Write-Host("Start download process")
$Downloader.Updates = $updatesToDownload
$DownloadResult = $Downloader.Download()
Write-Host("Download ResultCode: " + $DownloadResult.ResultCode)
if ($DownloadResult.ResultCode -eq 2) {
For ($X = 0; $X -lt $updatesToDownload.Count; $X++) {
Write-Host("Adding updates to install list")
$Update = $updatesToDownload.Item($X)
if ($update.IsDownloaded -eq 'True') {
$updatesToInstall.Add($Update)
Write-Host("Update " + $Update.Title + " added to install list")
}
}
}
}
else {
# Write-Host(0) # No Security Intelligence Updates
Write-Host("No update to download found")
Exit
}
The script works perfectly when I run it on a computer using administrator account.
But when I try to run it remotely using below short script and the same administrator credentials it starts and do "Check for updates" bloc and stops with error.
$password = ConvertTo-SecureString "some_password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("computer_name\administrator", $password)
$sess = New-PSSession -ComputerName "computer_name" -Credential $cred
Invoke-Command -Session $sess -FilePath "D:\Test.ps1"
Where "D:\Test.ps1" is path to a file with script mentioned above.
Error message:
The property 'Updates' cannot be found on this object. Verify that the property exists and can be set.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
+ PSComputerName : computer_name
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : computer_name
I have checked remote credentials using other script (below) and the result is True yet updates script doesn't work.
[bool] (net session 2>$null)
[Security.Principal.WindowsPrincipal]::new(
[Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
What did I do wrong? Why doesn't the script work remotely?

Issue with System.Windows.Forms.ListViewItem / NullReferenceException

I am getting the following error when I try to get a Listview of Applications in Powershell
Exception calling "Add" with "1" argument(s): "Object reference not set to an instance of an object."
At D:\scripts\AWSA.ps1:527 char:79
+ ... ?{$_.Index -ne 0})){$Field = $Col.Text;$Item.SubItems.Add($_.$Field)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NullReferenceException
The code that is rendering the result is
...
$btnApplications = New-Object System.Windows.Forms.Button
$lvMain = New-Object System.Windows.Forms.ListView
...
$btnApplications_Click={
Get-ComputerName
Initialize-Listview
$SBPStatus.Text = "Retrieving Applications..."
Update-ContextMenu (Get-Variable cmsApp*)
$XML.Options.Applications.Property | %{Add-Column $_}
Resize-Columns
$Col0 = $lvMain.Columns[0].Text
$Info = Get-WmiObject win32_Product -ComputerName $ComputerName -ErrorVariable SysError | Sort Name,Vendor
Start-Sleep -m 250
if($SysError){$SBPStatus.Text = "[$ComputerName] $SysError"}
else{
$Info | %{
$Item = New-Object System.Windows.Forms.ListViewItem($_.$Col0)
ForEach ($Col in ($lvMain.Columns | ?{$_.Index -ne 0})){$Field = $Col.Text;$Item.SubItems.Add($_.$Field)}
$lvMain.Items.Add($Item)
}
$SBPStatus.Text = "Ready"
}
}
Do I need to add a null variable such as if($SubItem -ne $null){$Item.SubItems.Add($SubItem)} ?

PAssing an array to a hash table, single item array failing

I have the file below, which accepts an array of servers. Works well when there are multiple items in the array, and I note the answer that a user suggested in a previous post, which was to put a , in front of the values if its a single item array, trying that with a hash table just doesnt worked. I have tried various options without much luck.
param ([array[]]$servers = $(throw "Input array of servers.") , $folder )
$x = $servers
$k = 'serverid','servername','locationid','appid' # key names correspond to data positions in each array in $x
$h = #{}
For($i=0;$i -lt $x[0].length; $i++){
$x |
ForEach-Object{
[array]$h.($k[$i]) += [string]$_[$i]
}
}
$all_server_ids = $h['Serverid']
foreach ($server_id in $all_server_ids)
{
$severid = $h["serverid"][$all_server_ids.indexof($server_id)]
$servername = $h["servername"][$all_server_ids.indexof($server_id)]
$locationid = $h["locationid"][$all_server_ids.indexof($server_id)]
Write-Output "This $severid and this $servername and this $locationid"
}
Running the below.
.\test.ps1 -servers ,('72','Server1\DEV2','1.0') -folder "F:\files"
Getting the error
Cannot index into a null array.
+ $servername = $h["servername"][$all_server_ids.indexof($server_i ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Cannot index into a null array.
+ $locationid = $h["locationid"][$all_server_ids.indexof($server_i ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
The issue here is that, I need the script to work with multiple items in the array or a single item.

powershell The underlying connection was closed: An unexpected error occurred on a send

I'm new to Powershell and created some breakpoints to figure out why the script times out. But I'm getting below error. Any help would be appreciated.
Exception calling "GetRequestStream" with "0" argument(s): "The
underlying connection was closed: An unexpected error occurred on a
send." At C:\Users\ksingh\Documents\SQL
scripts\pdfimportPowerShell.ps1:155 char:5
+ $requestStream = [System.IO.Stream]$request.GetRequestStream()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Here is part of the script and the error occurs at ---
bytes = [System.Text.Encoding]::ASCII.GetBytes($data)
function to call token service
function GetNewToken()
{
$request = [Net.WebRequest]::Create($temptokenserviceurl)
$request.ServicePoint.Expect100Continue = $false
$request.ContentType = "application/json"
$request.Method = "POST"
$data = (New-Object PSObject |
Add-Member -PassThru NoteProperty username $temptokenserviceuser |
Add-Member -PassThru NoteProperty password $temptokenservicepassword
) | ConvertTo-JSON
$bytes = [System.Text.Encoding]::ASCII.GetBytes($data)
$request.ContentLength = $bytes.Length
$requestStream = [System.IO.Stream]$request.GetRequestStream()
$requestStream.write($bytes, 0, $bytes.Length)
$response = $request.GetResponse()
$StreamReader = New-Object IO.StreamReader($response.getResponseStream())
$Json = $StreamReader.ReadToEnd()
$responseString = $Json | ConvertFrom-Json
$response.Close()
return $responseString.tokenId
}

Error when trying to do a search with Powershell towards LDAP

The above gives:
PS C:\EndurAutomation\powershell\bin> C:\EndurAutomation\powershell\bin\ets_update_constring.ps1
Exception calling "FindAll" with "0" argument(s): "An operations error occurred.
"
At C:\EndurAutomation\powershell\bin\ets_update_constring.ps1:20 char:30
+ $result = $ldapSearch.FindAll <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
$ldapDN = "dc=<masked>,dc=<masked>"
$ldapURI = "ldap://<masked>/$ldapDN"
$env = "sqlplus -S <masked> ``#env.sql > env.list"
Invoke-Expression $env
$envData = (Get-Content "env.list")
$envFilter = "(|"
foreach ($env in $envData) {
$envFilter += "(cn=$env)"
}
$envFilter += ")"
$ldapEntry = New-Object System.DirectoryServices.DirectoryEntry($ldapUR, $null, $null, [System.DirectoryServices.AuthenticationTypes]::Anonymous)
$ldapSearch = New-Object System.DirectoryServices.DirectorySearcher($ldapEntry)
$ldapSearch.PageSize = 1000
$ldapSearch.Filter = $envFilter
$result = $ldapSearch.FindAll($envFilter)
You already set $ldapSearch.Filter = $envFilter so you don't need to call FindAll by passing in the filter again. Try doing this instead as your very last line of code, as it will still have your filter built into it:
$result = $ldapSearch.FindAll()
I think it's a typo:
$ldapEntry = New-Object System.DirectoryServices.DirectoryEntry(
**$ldapUR**, $null, $null,
[System.DirectoryServices.AuthenticationTypes]::Anonymous
)
Try
$ldapURI
instead of
$ldapUR