I'm using PowerShell to read some extension attributes from AD, then read a local file from the C: drive (if it exists), substitute the values in the extension attributes, and write the file back to the same place.
I'm also reading a generic file from the network in case the local file does not exist, and I'll update that file and write it to the local path if necessary.
I can get the AD user, the extensionattribute values, the generic file from the network, substitute the extensionattributes into some variables, and the path of the local file, but this is where I get the problem. The local file is stored in the user's profile (which, very unhelpfully, contains spaces), so I need to use an environment variable in the path.
Here's my code:
$names=get-adgroupmember sg-deptest-test | foreach-object {
# Get the relevant properties for each user in the group
$userdetails = Get-ADUser -Id $_.samaccountname -Properties extensionattribute11, extensionattribute12, extensionattribute13, extensionattribute14, extensionattribute15
# Assign the 3CX values in the extension attributes to some variables
$AccountName = $userdetails.extensionattribute11
$CallerID = $userdetails.extensionattribute12
$Extension = $userdetails.extensionattribute13
$ID = $userdetails.extensionattribute14
$Password = $userdetails.extensionattribute15
# Read the generic 3CX Configuration file on the network into the $3CXconfig
# array
$3CXconfig = Get-Content \\domain\itservices\appdeployment\3cx\3CXVoipPhone.ini
# Set the relevant lines in the $3CXconfig array according to the variables
# containing the extensionattribute values
$3CXconfig[2] = "Name=$AccountName"
$3CXconfig[4] = "CallerID=$CallerID"
$3CXconfig[5] = "AuthUser=$Extension"
$3CXconfig[6] = "AuthID=$ID"
$3CXconfig[7] = "AuthPass=$Password"
# Sets the path to the local config file
$LocalFilePathPart1 = $env:localappdata
$LocalFilePathPart2 = "\3CX Voip Phone\3CXVoipPhone.ini"
$LocalFilePath = $LocalFilePathPart1 + $LocalFilePathPart2
# Read the existing 3CX configuration file into the $ExistingConfig array
$ExistingConfig = Get-Content -Path $LocalFilePath
# If the 3CX local config file already exists, then write the user values
# into the correct lines in the array and output the file again. This results
# in an unchanged 3CX config file. If it doesn't exist, it'll write the
# $3CXconfig array to the correct location. Some other values will need set
# (e.g. Playback devices)
if (Test-Path $LocalFilePath){
$ExistingConfig[2] = $3CXConfig[2]
$ExistingConfig[4] = $3CXConfig[4]
$ExistingConfig[5] = $3CXConfig[5]
$ExistingConfig[6] = $3CXConfig[6]
$ExistingConfig[7] = $3CXConfig[7]
$ExistingConfig | Out-File -Filepath $LocalFilePath -Encoding Default
} else {
$3CXconfig | Out-File -Filepath $LocalFilePath -Encoding Default
}
}
The problem is with the lines between all the hashes. No matter what I try, the Get-Content
command will NOT read the INI file at the specified location. The path is like this: C:\Users\User Name\Appdata\Local\3CX Voip Phone\3CXVoipPhone.ini
.
So, there are spaces in both the environment variable part (%localappdata%
) and the application-specific part (3CX Voip Phone
).
I have used many combinations of curly brackets, quotes, the addition sign (+
), Join-Path
, and although many of these compile correctly, none of them ends up with a populated $ExistingConfig
.
The error message is:
Cannot index into a null array.
It seems obvious that the array is null because the Get-Content
command did not populate it.
Just to confirm, the Get-Content
command for the $3CXConfig
variable works perfectly and displays the entire file from the network. The lines setting the variables to the extensionattribute variables also work correctly.
The OP has confirmed that the problem was an empty (zero-byte)
$LocalFilePath
file.In other words:
$LocalFilePath
existed, but it happened to have no content (it was a zero-byte[-sized] file).If you read a zero-byte file's content using
Get-Content
- e.g.,$ExistingConfig = Get-Content $LocalFilePath
- the result is$null
(not a an empty array).Therefore, any attempt to index (use a subscript on) the resulting variable - e.g.,
$ExistingConfig[2]
- causes PowerShell to report errorCannot index into a null array.
.