1
votes

If I run the command from with in the script

reg add "HKU\$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoConfigURL /t REG_SZ /d "http://mydomaon.com/proxies/proxy.pac" /f

it works perfectly, because it is local.

When I try to change the same registry key on a remote machine and changing the line to this

reg add "\\$machinename\HKU\$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoConfigURL /t REG_SZ /d "http://mydomaon.com/proxies/proxy.pac" /f

It fails with ERROR: reg : ERROR: Invalid key name. + CategoryInfo : NotSpecified: (ERROR: Invalid key name.:String) [], RemoteException ERROR: + FullyQualifiedErrorId : NativeCommandError

ForEach ($machine in $machines)
{

    $User = New-Object System.Security.Principal.NTAccount($env:UserName)
    $sid = $User.Translate([System.Security.Principal.SecurityIdentifier]).value
    New-PSDrive HKU Registry HKEY_USERS
#       Get-Item "HKU:\${sid}"
    Set-Location HKU:\
    cd HKU:\
    reg add '$SID\Software\Microsoft\Windows\CurrentVersion\Internet Settings' /v AutoConfigURL /t REG_SZ /d 'http://proxy.domain.com/proxies/proxy.pac' /f

}
2
variables in '' will not be interpreted, what happens if you put the $sid part in "" or assemble it beforehand?Paul
@Paul is right. This question covers the quote issue easilyMatt
have you tested the command by typing it manually with fixed values?Paul
It works perfectly when I put the computer in and put the known sid I am looking for. See belowNobleMan
PS C:\> reg add "\\remote_computer\HKU\S-1-5-21-557486866-382535363-1543835964-500\Software\Microsoft\Windows\CurrentVersion \Internet Settings" /v AutoConfigURL /t REG_SZ /d "blabla.com/proxies/domain.pac" /f The operation completed successfully.NobleMan

2 Answers

1
votes

Here is an approach that should work (also better then using reg.exe):

Local Computer:

New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS
New-ItemProperty -Path "HKU:\$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name      AutoConfigURL -PropertyType String -value "http://proy.domain.com/proxies/proxy.pac" -Force

Remote Computer:

$credential = Get-Credential
Foreach($machine in $computers){

    Invoke-Command -ComputerName $machine -Credential $credential -ScriptBlock {$temp = $args[0];
    New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS; New-ItemProperty -Path "HKU:\$temp\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -PropertyType String -Name AutoConfigURL -Value "http://proy.domain.com/proxies/proxy.pac" -Force} -argumentlist $sid
}

Also here are the Type mappings for New-Itemproperty´s -PropertyType:

REG_SZ = String

REG_DWORD = DWord

REG_QWORD = QWord

REG_MULTI_SZ = MultiString

REG_BINARY = Binary

So after a few problems here is an updated version which should do everything including determining the local users sid by username (added linebreaks for readability, remove them when you copy)

$username = "yourUsername"
$credential = Get-Credential
Foreach($machine in $computers){

    Invoke-Command -ComputerName $machine -Credential $credential -ScriptBlock {$temp = $args[0];
    New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS; 
    $sid = (Get-CimInstance -Class Win32_UserAccount | where {$_.Name -eq $temp} | select SID).SID;
    New-ItemProperty -Path "HKU:\$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -PropertyType String -Name AutoConfigURL -Value "http://proy.domain.com/proxies/proxy.pac" -Force
    } -argumentlist $username

}

After furhter discussion with Kent and clearly specifying the environment (Windows XP domain-joined machines, user logged on) the script has to run in this was what we came up with:

(this works only if the user is logged in on XP)

$sid = ((get-aduser $username).SID).Value 
$credential = Get-Credential
Foreach($machine in $computers){

Invoke-Command -ComputerName $machine -Credential $credential -ScriptBlock {New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS; New-ItemProperty -Path "HKU:\$($args[0])\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -PropertyType String -Name AutoConfigURL -Value "http://proxy.domain.com/proxies/proxy.pac" -Force} -argumentlist $sid

}

This is how it would work if the user was not currently log in on XP:

$defaultprofilepath = "C:\documents and settings"
$username = "username"
$profilepath = "$defaultprofilepath\$username"
$credential = Get-Credential
Foreach($machine in $computers){

Invoke-Command -ComputerName $machine -Credential $credential -ScriptBlock {reg load "HKU\TempDir" "$($args[0])\NTUSER.DAT"; reg add "HKU\TempDir\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoConfigURL /t REG_SZ /d 'http://proxy.domain.com/proxies/proxy.pac' /f; reg unload "HKU\TempDir"} -argumentlist $profilepath

}

P.S. If someone has a clue if there is a powershell cmdlet to load registry hives please comment, i could not find one on the fly

0
votes

Using WMI you could do it like this:

$computers = ...

$user   = New-Object Security.Principal.NTAccount($env:USERNAME)
$sid    = $user.Translate([Security.Principal.SecurityIdentifier]).Value
$subkey = "$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
$url    = 'http://proy.domain.com/proxies/proxy.pac'
$HKU    = [convert]::ToUInt32('0x80000003', 16)

$credential = Get-Credential
foreach ($machine in $computers) {
  $reg = Get-WmiObject -List -Namespace 'root/default' -Computer $machine `
           -Credential $credential | ? { $_.Name -eq 'StdRegProv' }
  $reg.SetStringValue($HKU, $subkey, 'AutoConfigURL', $url) | Out-Null
}

Note, however, that for remote WMI access you need administrative privileges on the remote host. Without admin privileges you could use Invoke-Command for local WMI access on the remote host:

foreach ($machine in $computers) {
  Invoke-Command -Computer $machine -Credential $credential -ScriptBlock {
    $reg = Get-WmiObject -List -Namespace 'root/default' |
             ? { $_.Name -eq 'StdRegProv' }
    $reg.SetStringValue($args[0], $args[1], 'AutoConfigURL', $args[2]) | Out-Null
  } -ArgumentList $HKU, $subkey, $url
}

Note also that only domain accounts have the same SID accross hosts. For local accounts you need to determine the SID of the account on the remote host:

foreach ($machine in $computers) {
  Invoke-Command -Computer $machine -Credential $credential -ScriptBlock {
    $user   = New-Object Security.Principal.NTAccount($args[0])
    $sid    = $user.Translate([Security.Principal.SecurityIdentifier]).Value
    $subkey = "$sid\Software\Microsoft\Windows\CurrentVersion\Internet Settings"

    $reg = Get-WmiObject -List -Namespace 'root/default' |
             ? { $_.Name -eq 'StdRegProv' }
    $reg.SetStringValue($args[1], $subkey, 'AutoConfigURL', $args[2]) | Out-Null
  } -ArgumentList $env:USERNAME, $HKU, $url
}

If the account in question is a domain account, you may want to provide the domain name when creating the NTAccount object, because otherwise you'd be getting the wrong account/SID when there's a local account with the same name as the domain account.

$user = New-Object Security.Principal.NTAccount($env:USERDOMAIN, $env:USERNAME)
$sid  = $user.Translate([Security.Principal.SecurityIdentifier]).Value