Changing windows hostname automatically after nslookup.

Hi Experts.

I have an issue that I can not seem to resolve and I am a complete Powershell newbie.

I am using HPSA to do unattended installations of Windows 2008/2008R2/20012/2012R2

The installations work fine and get a dhcp address, I then use a powershell script to do an nslookup of the supplied dhcp address to get the hostname then set that as the hostname inplace fo the default one I supply in my unattend.xml file.

The script works fine on 2008R2, 2012 and 2012 R2 in the following languages:

English
German
Spanish
Portuguese

It runs and changes the hostname as expected which then gets set after a reboot.

However it does not work in:

French
Russian
Korean
Japanese
Chinese.

In theses languages I get an error that there is a missing terminator ".
However as it works in other languages I am confused as to what or where this error is coming from.

Here is my script:

powershell -command “$name=((gwmi Win32_NetworkAdapterConfiguration | ? {$.IPAddress -ne $null }).ipaddress | Select-Object -First 1 | nslookup $ | Select-String -Pattern "Name:").Line; $name = $name -Replace "Name:", ""; $name=$name.Trim(); $nameSplit = $name -split "."; $name = $nameSplit[0]; netdom renamecomputer $env:COMPUTERNAME /newname:$name /force”

I change the word Name in two places for the languages that work.

But for the languages it does not work on I get the following error:

powershell : The string is missing the terminator: ".
At line:1 char:1

  • powershell -command "$name=((gwmi Win32_NetworkAdapterConfiguration | ? {$_.IPAd …

  • CategoryInfo : NotSpecified: (The string is missing the terminator: ".:String) , RemoteException

  • FullyQualifiedErrorId : NativeCommandError

  • CategoryInfo : ParserError: ( , ParentContainsErrorRecordEx
    ception

  • FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

So can someon please tell me what is wrong, where I should put this missing dot or even rewrite the script better?

Thanks
Steve

Hi Steve,

I would rewrite it and use a script file (.ps1) instead.

PowerShell.exe -File RenameComputerFromDHCP.ps1

I assume you have at least PowerShell 3.0 installed in your build. So instead of doing prayer based parsing of the NSLookup output I would use the .NET Framework functionality to resolve the IP to the hostname. The parsing of the NSLookup output most likely fails because the output is in the local language.

$IPv4Addresses = @(
    Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "DHCPEnabled=True AND IPEnabled=True" |
        Select-Object -ExpandProperty IPAddress | Where-Object { ([IPAddress]$_).AddressFamily -eq 'InterNetwork' }
)

if ($IPv4Addresses.Count -gt 0) {

    $HostEntry = [System.Net.Dns]::GetHostEntry($IPv4Addresses[0])
    if ($HostEntry) {

        $NewName = $HostEntry.HostName.Split('.')[0].ToUpper()
        Rename-Computer -NewName $NewName -Force -Restart
    }
}

I hope above helps.

Best,
Daniel

If you can’t put this into a ps1 file for some reason, you’ll probably have a much better experience by using the -EncodedCommand parameter of powershell.exe instead of -Command. That gets around all of the silly escaping / quoting rules that you’d need to try to get right. -EncodedCommand takes a base64-encoded string of the UTF-16 representation of the PowerShell code that needs to be executed.

I also agree with Daniel’s use of the [System.Net.Dns] class instead of trying to parse the console output from nslookup; multiple language / culture tends to be what makes pre-PowerShell scripting such a fragile affair. However, just for demonstration purposes, here’s how you’d convert your original code to use -EncodedCommand. The only thing I’ve done is broken the code up into multiple lines (and removed semicolons) for readability, and removed the now-unnecessary backslashes that were escaping some of your double quotation marks:

$command = @'
    $name=((gwmi Win32_NetworkAdapterConfiguration |
    ? {$_.IPAddress -ne $null }).ipaddress |
    Select-Object -First 1 |
    nslookup $_ |
    Select-String -Pattern "Name:").Line
    
    $name = $name -Replace "Name:", ""
    $name = $name.Trim()
    $nameSplit = $name -split "\."
    $name = $nameSplit[0]
    
    netdom renamecomputer $env:COMPUTERNAME /newname:$name /force
'@

$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$base64 = [System.Convert]::ToBase64String($bytes)
$base64 | clip.exe

This puts the encoded command onto your clipboard, where you could then paste it into your call to PowerShell.exe. That would look like this:

powershell.exe -EncodedCommand IAAgACAAIAAkAG4AYQBtAGUAPQAoACgAZwB3AG0AaQAgAFcAaQBuADMAMgBfAE4AZQB0AHcAbwByAGsAQQBkAGEAcAB0AGUAcgBDAG8AbgBmAGkAZwB1AHIAYQB0AGkAbwBuACAAfAANAAoAIAAgACAAIAA/ACAAewAkAF8ALgBJAFAAQQBkAGQAcgBlAHMAcwAgAC0AbgBlACAAJABuAHUAbABsACAAfQApAC4AaQBwAGEAZABkAHIAZQBzAHMAIAB8AA0ACgAgACAAIAAgAFMAZQBsAGUAYwB0AC0ATwBiAGoAZQBjAHQAIAAtAEYAaQByAHMAdAAgADEAIAB8AA0ACgAgACAAIAAgAG4AcwBsAG8AbwBrAHUAcAAgACQAXwAgAHwADQAKACAAIAAgACAAUwBlAGwAZQBjAHQALQBTAHQAcgBpAG4AZwAgAC0AUABhAHQAdABlAHIAbgAgACIATgBhAG0AZQA6ACIAKQAuAEwAaQBuAGUADQAKACAAIAAgACAADQAKACAAIAAgACAAJABuAGEAbQBlACAAPQAgACQAbgBhAG0AZQAgAC0AUgBlAHAAbABhAGMAZQAgACIATgBhAG0AZQA6ACIALAAgACIAIgANAAoAIAAgACAAIAAkAG4AYQBtAGUAIAA9ACAAJABuAGEAbQBlAC4AVAByAGkAbQAoACkADQAKACAAIAAgACAAJABuAGEAbQBlAFMAcABsAGkAdAAgAD0AIAAkAG4AYQBtAGUAIAAtAHMAcABsAGkAdAAgACIAXAAuACIADQAKACAAIAAgACAAJABuAGEAbQBlACAAPQAgACQAbgBhAG0AZQBTAHAAbABpAHQAWwAwAF0ADQAKACAAIAAgACAADQAKACAAIAAgACAAbgBlAHQAZABvAG0AIAByAGUAbgBhAG0AZQBjAG8AbQBwAHUAdABlAHIAIAAkAGUAbgB2ADoAQwBPAE0AUABVAFQARQBSAE4AQQBNAEUAIAAvAG4AZQB3AG4AYQBtAGUAOgAkAG4AYQBtAGUAIAAvAGYAbwByAGMAZQA=

Hi.

I have tried Daniels way and it fails with the following error.

Rename-Computer : Skip computer ‘ChangeMe’ with new name ‘CHANGEME’ because
the new name is the same as the current name.
At C:\windows\temp\rename.ps1:12 char:9

  •     Rename-Computer -NewName $NewName -Force -Restart
    
  •     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidArgument: (CHANGEME:String) [Rename-Compu
      ter], InvalidOperationException
    • FullyQualifiedErrorId : NewNameIsOldName,Microsoft.PowerShell.Commands.R
      enameComputerCommand

It seems to be trying to apply the same name it already has rathe rthan doing an nslookup of its dhcp address.

Dave I don’t get what you mean about pasting the clipboard output.

This is a totally unattended install using HP Server Automation where a user requests a system in whatever language and it installs it with no administrator interaction.

I have put Daniels script into a ps1 file copied it over with the installation and then executed it automatically.

Can I put your code up to thr @ sign in a ps1 file and execute it or do I need the last 3 lines aswell?

Sorry for being dim but this is all new to me.

Cheers
Steve

The code with the @ sign is showing you how to generate the value that you would pass to the -EncodedCommand parameter of powershell.exe. You would paste that encoded command (not the code with the @ itself, but the base64 string it produces) into your unattend.xml file.

In the second Code block, I showed what this would look like in your unattend.xml file. You could even just copy and paste that as-is, if you like; it’s the actual encoded version of this code:

    $name=((gwmi Win32_NetworkAdapterConfiguration |
    ? {$_.IPAddress -ne $null }).ipaddress |
    Select-Object -First 1 |
    nslookup $_ |
    Select-String -Pattern "Name:").Line
 
    $name = $name -Replace "Name:", ""
    $name = $name.Trim()
    $nameSplit = $name -split "\."
    $name = $nameSplit[0]
 
    netdom renamecomputer $env:COMPUTERNAME /newname:$name /force

However, I don’t know if this code will work as-is on your various languages. Could be that there’s still going to be a bug in there somewhere.

No this code only works on English, German, Spanish and Portuguese.

Hi Guys,

so are we stuck on this then?