Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the way computer name is set #137

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kurtbahartr
Copy link

@kurtbahartr kurtbahartr commented Dec 14, 2024

ActiveComputerName and ComputerName keys require NetBIOS compliance. Violation of it will cause BSoD with CRITICAL_PROCESS_DIED. However, Tcpip parameters "Hostname" and "NV Hostname" are fine with names longer than what NetBIOS requires. These are the keys local Windows apps like Settings and the "hostname" command in CMD read from, too.

Also adds "ActiveComputerName" key along so that we do it the way Windows itself does it when the user sets the hostname themselves. This won't impact future (manual) hostname changes done through Settings.

A script I made to test this: https://github.com/kurtbahartr/windows-configs/blob/0dd55d66ce1bf1b1271d2fa11dc403ab31bac4af/autounattend.xml#L124-L127

Recommended environment to test on: VMware Workstation Virtual Machine with Windows 10/11.

ActiveComputerName and ComputerName keys require NetBIOS compliance.
Violation of it will cause BSoD with CRITICAL_PROCESS_DIED. However,
Tcpip parameters "Hostname" and "NV Hostname" are fine with names
longer than what NetBIOS requires. These are the keys local Windows
apps like Settings and the "hostname" command in CMD read from, too.

Also adds "ActiveComputerName" key along so that we do it the way
Windows itself does it when the user sets the hostname themselves.
This won't impact future (manual) hostname changes done through
Settings.
@ProgrammerBruce
Copy link

ProgrammerBruce commented Dec 26, 2024

Why not use Rename-Computer -NewName instead of Set-ItemProperty?

@kurtbahartr
Copy link
Author

kurtbahartr commented Dec 26, 2024

I have absolutely no idea. That was the quickest workaround I could think of at the time. However, I'm sure there's a reason why the original maintainer opted for Set-ItemProperty -probably for Windows versions older than 10 or Rename-Computer performing a reboot right as the operation is completed?- since not all PowerShell snippets are supported by all versions. The method in the generator runs these scripts using powershell.exe, the stock PS shipped with the Windows version installed.

@cschneegans
Copy link
Owner

Why not use Rename-Computer -NewName instead of Set-ItemProperty?

The computer name cannot be set by one synchronous call because Windows Setup would just override the name later. Instead, the name is set again and again in a separate process, possibly hundreds of times. Hence, timing and performance matter, and three Set-ItemProperty calls are still faster than one Rename-Computer call.

@kurtbahartr
Copy link
Author

kurtbahartr commented Dec 27, 2024

Why not use Rename-Computer -NewName instead of Set-ItemProperty?

The computer name cannot be set by one synchronous call because Windows Setup would just override the name later. Instead, the name is set again and again in a separate process, possibly hundreds of times. Hence, timing and performance matter, and three Set-ItemProperty calls are still faster than one Rename-Computer call.

@ProgrammerBruce, above is your reply in case you weren't notified. Turns out, it was more of a technical workaround than anything.

@cschneegans, thanks for the correction! Sorry for my hurry but, how do you think is this patch? Should I change anything in it?

@ProgrammerBruce
Copy link

ProgrammerBruce commented Jan 8, 2025

I am not convinced that the time saved with Set-ItemProperty instead of Rename-Computer is worth the trade-off. In my testing, 1000 repetitions saves a little over 10 seconds (73 seconds instead of 62 seconds). To make up for these 10 seconds, just change the delay to 40 milliseconds instead of 50.

$newName = "NEWCOMPNAME";
$reps = 1000;

(Measure-Command {
for ($i=0; $i -lt $reps; $i++) {
	Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "NV Hostname" -Value "$newName";
	Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name ComputerName -Value "$newName";

	Start-Sleep -Milliseconds 50;
}
}).TotalMilliseconds;

(Measure-Command {
for ($i=0; $i -lt $reps; $i++) {
	(Rename-Computer -NewName "$newName") *> $null;

	Start-Sleep -Milliseconds 50;
}
}).TotalMilliseconds;

That said...

Instead of just truncating to 15 1-byte characters, what about more fully enforcing the naming rules? By initially using Rename-Computer to validate? Or by validating in the same way that it does?
https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Management/commands/management/Computer.cs

Maybe a sequence such as this (assuming that repeated calls to Set-ItemProperty is preferred to repeated or timely calls to Rename-Computer):

$newName = ...
if ((Rename-Computer -PassThru -Force -NewName "$newName").HasSucceeded) {
    $newShortName = (Get-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName").ComputerName;
    $newLongName = (Get-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters")."NV Hostname";
} else {
    # catch the error thrown by Rename-Computer
    # $newName is bad, so use a default value?
    $newShortName = "TEMPNAME";
    $newLongName = $newShortName;
}

while (true) {
    Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name "ComputerName" -Value "$newShortName";
    Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "NV Hostname" -Value "$newLongName";
    Start-Sleep -Milliseconds 50;
}
restart

Maybe use DnsValidateName:
https://learn.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsvalidatename

Additional Reference:
https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/naming-conventions-for-computer-domain-site-ou

====

As best I can tell, there are only 2 entries in the Registry that need to be set directly with Set-ItemProperty, in order to replicate Rename-Computer (with Windows 11 24H2). The restart process sets the remaining 20-ish Registry entries.

  1. Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name "ComputerName" -Value "COMPNAME0"

This immediately also sets this entry to the same value:

Get-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\ControlSet001\Control\ComputerName\ComputerName" -Name "ComputerName"

After restarting, all of these entries then have the same value:

[HKEY_USERS\S-1-5-21-3174056944-3246519551-245092962-1000\Volatile Environment]
"USERDOMAIN_ROAMINGPROFILE"="COMPNAME0"
"USERDOMAIN"="COMPNAME0"
"LOGONSERVER"="\\COMPNAME0"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName]
"ComputerName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName]
"ComputerName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName]
"ComputerName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ActiveComputerName]
"ComputerName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\S-1-5-21-3174056944-3246519551-245092962-1000\0]
"szName"="COMPNAME0\admin1"

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine\0]
"szTargetName"="COMPNAME0"
"szName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\S-1-5-21-3174056944-3246519551-245092962-1000\0]
"szName"="COMPNAME0\admin1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine\0]
"szTargetName"="COMPNAME0"
"szName"="COMPNAME0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData\1]
"LoggedOnUser"="COMPNAME0\admin1"
"LoggedOnSAMUser"="COMPNAME0\admin1"

[HKEY_CURRENT_USER\Volatile Environment]
"USERDOMAIN_ROAMINGPROFILE"="COMPNAME0"
"USERDOMAIN"="COMPNAME0"
"LOGONSERVER"="\\COMPNAME0"

  1. Set-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "NV Hostname" -Value "COMPNAME9"

This immediately also sets this entry to the same value:

Get-ItemProperty -LiteralPath "Registry::HKLM\SYSTEM\ControlSet001\Services\Tcpip\Parameters" -Name "NV Hostname"

After restarting, all of these entries then have the same value:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"Hostname"="COMPNAME9"
"NV Hostname"="COMPNAME9"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters]
"Hostname"="COMPNAME9"
"NV Hostname"="COMPNAME9"

@kurtbahartr
Copy link
Author

Instead of just truncating to 15 1-byte characters, what about more fully enforcing the naming rules?

This enforcement is already present on the webpage itself when a custom script is not in use. When a custom script is used, the webpage has no way of testing it against overflows, so it blows.

Also, the truncation happens in my proposed PR only for network name just as Windows itself intends to do, just as I stated in my original explanation. You don't see the network name yourself within your system but only during networking as your system's network name. This is a known standard especially since Windows 10 times.

$newName is bad, so use a default value?

NO! NEVER EVER GO FOR A DEFAULT! It will only cause more headaches than necessary to try and troubleshoot what went wrong with the hostname script on the end-user's end. The webpage offers no way to set a custom default as of yet, which I don't think is worth the effort either.


I still have no idea why you're insisting so much about breaking something that already existed there for probably years at this point. Does this cmdlet such as Rename-Computer exist on Windows versions older than 10? Don't go for assumptions such as people using such Windows versions are nonexistent. They do exist, and I'm one of them. One of my three workstations runs Windows 7 and I have another one among that three that runs 8.1. Not to mention I experiment with older versions of Windows in virtual machines sometimes purely out of fun and sometimes for software-specific troubleshooting purposes.

@ProgrammerBruce
Copy link

@kurtbahartr Perspectives are being talked pass. (Your responses take information I presented out of context.)

Where is there documentation about revision compatibility, and explanations for solutions? In locations such as commit history and elsewhere, I am failing to find a lot of the historical knowledge for implementation decisions.

@kurtbahartr
Copy link
Author

kurtbahartr commented Jan 9, 2025

@ProgrammerBruce, Such an ability was introduced in this specific repo back in October 2024. Maybe instead of doing such a discussion here in a PR I opened myself, you could move it all into an issue you would open yourself and you could discuss this with people who are willing to do such a change instead of with me, who is willing to keep the current implementation. Even better, instead of jumping into ideas in a PR, turn your idea into an actual code and propose it as a PR yourself and say "Hey, this person did this PR but I've come up with something possibly better." Make me close this PR with mature code and well done research instead of by mobbing.

Any further discussion without proper mature code and I'm going to block you. I have other things to care about and your replies and the ideas you throw into the field without proper examples are none of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants