How To Create An Array Reading from Host? [duplicate] - powershell

This question already has answers here:
Parsing a file to create an array of lines
(2 answers)
Closed 3 years ago.
I am creating a script that will allow batch creation of new users but am running into an issue with the creation of the array.
$fname = #()
$lname = #()
$i = 0
$fname[$i] = Read-Host "`nWhat is the first name of the new user?"
$fname[$i] = $fname[$i].trim()
$lname[$i] = Read-Host "What is the last name of the new user?"
$lname[$i] = $lname[$i].trim()
If I run this I get the error:
Index was outside the bounds of the array.
At line:1 char:1
+ $fname[$i] = Read-Host "`nWhat is the first name of the new user?"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException
Method invocation failed because [System.Object[]] does not contain a method named 'trim'.
At line:2 char:13
+ $fname[$i] = $fname.trim()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

You are creating an array with an fixed size of zero. As $fname[0] doesn't exist in the array you can't change it's value. One solution would be to use += to add an element to your existing array:
$fname = #()
$lname = #()
$i = 0
$fname += Read-Host "`nWhat is the first name of the new user?"
$fname[$i] = $fname[$i].trim()
$lname += Read-Host "What is the last name of the new user?"
$lname[$i] = $lname[$i].trim()
As a side note, I personally wouldn't use different arrays for my user information but instead create PSCustomObject:
$UserTable = #()
$obj = New-Object psobject
$obj | Add-Member -MemberType NoteProperty -Name FirstName -Value (Read-Host "`nWhat is the first name of the new user?").Trim()
$obj | Add-Member -MemberType NoteProperty -Name LastName -Value (Read-Host "What is the last name of the new user?").Trim()
$UserTable += $obj
$i = 0
$UserTable[$i].FirstName
$UserTable[$i].LastName

Related

InvalidArgument when Invoking Expression containing get-date

Whenever i try to invoke the following String
$log = "Get-EventLog -LogName " + $name + " -EntryType Error -After " + $datum + " | Format-List -Property TimeWritten,Message"
i get an error
+ ... gName Application -EntryType Error -After 03/08/2021 11:51:37 | Forma ...
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-EventLog], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetEventLogCommand
The $datum variable is filled like this
$datum = $((get-date).AddDays(-10))
As the error indicates, $datum expands to a string with a space in between the date and time parts - you need to add quotes around it.
Instead of showing you how to quote it, I'm gonna show you a better way:
Use splatting instead of Invoke-Expression:
$logParams = #{
LogName = $name
EntryType = 'Error'
After = $datum
}
Get-EventLog #logParams |Format-List -Property TimeWritten,Message
Now we don't need to worry about quoting or qualifying parameter argument values, PowerShell binds them correctly for us.

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.

Increment a variable based on number of items in Powershell

I am relatively new to PS, but using PS within a wider IaC workflow. I have the following script, which checks for number of services installed, and increments the port number variable by 1.
$Service = Get-Service Test* | Select-Object Name
If( $Service.Name.count -eq 0){
$port = 12000 }
If( $Service.Name.count -eq 1){
$port = 12001 }
If ( $Service.Name.Count -eq 2){
$port = 12002 }
If ( $Service.Name.Count -eq 3){
$port = 12003 }
Unfortunately, this is not as dynamic as I would like, as the script will fail if there is more than 3 services.
How can I dynamically increment the port number based on number of services that exist? The port number starts at 12000, then if another service is installed, the port will be 12001, and if a third service is detected, the port number is 12002 and so on.
You can follow the advice in comment by AdminOfThings if you ensure that the $Service object is a collection:
$Service = #(Get-Service Test* | Select-Object Name)
$port = 12000 + $Service.Count
Otherwise, you encounter the following errors:
$Service = Get-Service Test* ; $Service; $Service.Count
The property 'Count' cannot be found on this object. Verify that the property exists.
At line:1 char:42
+ $Service = Get-Service Test* ; $Service; $Service.Count
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
$Service = Get-Service Te* ; $Service; $Service.Count
Status Name DisplayName
------ ---- -----------
Running TermService Remote Desktop Services
The property 'Count' cannot be found on this object. Verify that the property exists.
At line:1 char:40
+ $Service = Get-Service Te* ; $Service; $Service.Count
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict

Error: "New-ADUser : The object name has bad syntax"

I am creating a PowerShell script at work to copy user accounts. The script works perfectly on my test Server 2016 VM. It also works in our work environment on a coworkers Windows 10 PC, however I cannot run it on my local machine. It returns the following error:
New-ADUser : The object name has bad syntax
At line:155 char:1
+ New-ADUser -Name $New_DisplayName #params
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (CN=cnelson test...ctions,DC=local:String) [New-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8335,Microsoft.ActiveDirectory.Management.Commands.NewADUser
Add-ADGroupMember : Cannot find an object with identity: 'cnelsontest1' under:
'DC=,DC=local'.
At line:159 char:29
+ Add-ADGroupMember -Members $Username.Text
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (cnelsontest1:ADPrincipal) [Add-ADGroupMember], ADIdentityNotFoundException
+ FullyQualifiedErrorId : SetADGroupMember.ValidateMembersParameter,Microsoft.ActiveDirectory.Management.Commands.AddADGroupMember
$params = #{'SamAccountName' = $Username.Text;
'Instance' = $AD_Account_To_Copy;
'DisplayName' = $New_DisplayName;
'GivenName' = $FirstName.Text;
'Path' = $New_Path;
'SurName' = $LastName.Text;
'ChangePasswordAtLogon' = $true;
'Enabled' = $true;
'UserPrincipalName' = $Username.Text;
'AccountPassword' = $New_Pass;
'EmailAddress' = $Username.Text + '#azcorrections.gov';
'HomePage' = $HomePage.HomePage;
'Description' = $NewDescription.Description;
'Office' = $NewOffice.Office;
'StreetAddress' = $NewStreet.StreetAddress;
'City' = $NewCity.City;
'State' = $NewState.State;
'PostalCode' = $NewPostalCode.PostalCode;
'Title' = $NewTitle.Title;
'Department' = $NewDepartment.Department;
'Company' = $NewCompany.Company;
'ScriptPath' = $NewScript.ScriptPath;
'OfficePhone' = $PhoneNumber.text;
}
New-ADUser -Name $New_DisplayName #params
Full Script link
I'm running PSVersion 5.1.150
Any ideas as to what i'm missing and why i'm coming across this error? I have no idea what it is referring to, nor why it works on one coworkers computer but not my own.
Edit: Value of $params at the time of the error:
Name Value
---- -----
AccountPassword System.Security.SecureString
Description Chris Nelson Test Account
UserPrincipalName cnelsontest1
HomePage http://...
DisplayName cnelson test1
SamAccountName cnelsontest1
ScriptPath
EmailAddress cnelsontest1#example.com
Office test
GivenName cnelson
Title SYSTEMS/LAN ADMR
Company
OfficePhone 555-1234
StreetAddress Sesame Street
PostalCode 54321
SurName test1
State candid
Department IT
ChangePasswordAtLogon True
Path cnelson,OU=IT_TECHSRVS,OU=Information Technology,OU=ADMIN,OU=CENT_OFF,DC=example,DC=com
City
Enabled True
Instance CN=test\, cnelson,OU=IT_TECHSRVS,OU=Information Technology,OU=ADMIN,OU=CENT_OFF,DC=example,DC=com
I'm calculating $New_Path like this:
$New_Path = (Get-ADUser ($UsernameCopy.Text)).DistinguishedName -replace '^.*?,', ''
The way you remove the common name portion from the value of $AD_Account_To_Copy is flawed. -replace '^.*?,', '' will remove everything up to the first comma in the string. If the common name itself contains a comma (like in CN=test\, cnelson,OU=...) the replacement won't remove cnelson,. Amend your regular expression with a positive lookahead assertion, so that everything before the first OU= is removed:
$New_Path = $AD_Account_To_Copy -replace '^.*?,\s*(?=ou=)', ''

New-Object cannot contain a dash (-) but "needs to"

I am creating a new object for export values to CSV:
New-Object -TypeName PSObject -Property #{
host_name = ($server.name).ToLower()
address = $IPAddress
host_is_collector = "no"
host-preset = "windows-server"
} | Select-Object host_name,address,host-preset | Export-Csv -Path $nConf_import_host_file
The problem is that one of the lines contains a dash (host-preset). I would ofcourse simply change it to an underscore, but my CSV needs this value to be a dash. I could also do a -replace on the entire csv after it has been created but that seems dirty.
Is there a way I can use dash here?
My error msg is:
Missing '=' operator after key in hash literal.
At Z:\Scripts\Testscripts\ScanServers_and_check_nagiosV7.ps1:336 char:16
+ host-preset <<<< = "windows-server"
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral
You simply need to treat the host-preset property name as a string by enclosing it in quotes:
New-Object -TypeName PSObject -Property #{ "host-preset" = "windows-server" }