0
votes

I have a largish set of Windows 10 workstations that need to be renamed. I've tried running the script below, but get errors that are beyond my current PS level.

$computers = Import-Csv "c:\rename-computers\computers.csv" 
foreach ($oldname in $computers){
    #Write-Host "EmpID=" + $computers.NewName
    Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName -DomainCredential hole\inwall -Force -Restart
}

Produces:

Rename-Computer : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'ComputerName'. Specified method is not supported. At \siat-ds0\appdeploy\LabPacks\rename-computers\rename-siat.ps1:4 char:35 + Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName ... + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Rename-Computer], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.RenameComputerCommand

I've seen similar closed threads on this topic elsewhere without mention of the error I'm receiving.

2

2 Answers

3
votes

You mistakenly used the collection variable $computers instead of the loop-iteration variable $oldname inside your loop, and since $computers.NewName expanded to an array of names rather than a single one, you got the error you saw.

That said, you don't need a loop at all - a single pipeline will do:

Import-Csv "c:\rename-computers\computers.csv" |
 Rename-Computer -ComputerName { $_.OldName } -DomainCredential hole\inwall -Force -Restart

Rename-Computer will implicitly bind the NewName property of each input object to the -NewName parameter.

The -ComputerName parameter, by contrast, must be told what property on the input objects to access, given that the input objects have no ComputerName property.
This is what script block { $_.OldName } does, inside which automatic variable $_ represents the input object at hand.

To see which parameters accept pipeline input, examine the output from
Get-Help -full Rename-Computer; for details and a programmatic alternative, see this answer of mine.

1
votes

YOu are iterating but not using the singular:

Instead of this:

foreach ($oldname in $computers){
    #Write-Host "EmpID=" + $computers.NewName
    Rename-Computer -ComputerName $computers.OldName -NewName $computers.NewName -DomainCredential hole\inwall -Force -Restart
}

Try this:

foreach ($oldname in $computers){

Rename-Computer -ComputerName $oldname.OldName -NewName $oldname.NewName -DomainCredential hole\inwall -Force -Restart

}

Note: $oldname is holding one value at a point. So the number of computers present in $computers will come one by one to $oldname and will perform the activity inside the loop. YOu should use the singular $oldname inside the loop to iterate one by one.