Writing DWORD value in HEX to Remote Registry in Powershell - powershell

I am trying to write a HEX value DWORD Key to the remote registry on a machine I target. The key lies under the HKEY_Users hive and targets the SID of the user, then the path I need. My issue lies with constantly receiving the following error:
Exception calling "SetValue" with "3" argument(s): "The type of the value object did not match the specified RegistryValueKind or the object could not be properly converted."
Here is my script; the connection to the remote registry works, as does determining the SID of the user. Can anyone see where I am going wrong?
$Value1 = "1f24db0a"
$Value2 = "062efc0a"
$remoteuser = Read-Host 'Enter Username of User'
$Comptername = Read-Host 'Enter Asset Number of User'
$userLogin = New-Object System.Security.Principal.NTAccount(“TestDomain“,$remoteuser)
$userSID = $userLogin.Translate([System.Security.Principal.SecurityIdentifier])
If (Test-Connection $Comptername -count 1) {
$subkey = $userSID.value+"\Software\SoftwareVendor\Application"
$type = [Microsoft.Win32.RegistryHive]::Users
$regkey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type,$Computername)
$regkey.OpenSubKey($subkey, $true)
$regkey.SetValue('CommsServer1', $Value1, 'DWORD')
$regkey.SetValue('CommsServer2', $Value2, 'DWORD')
}
else
{
Write-Host "User's computer unreachable! Please try again!"
PAUSE
}

Hex-values uses 0x-prefix. Try:
$Value1 = 0x1f24db0a
$Value2 = 0x062efc0a

Related

Variable showing null but not empty

Im trying to get remote registry key vaules using this script, it works fine but throws a few null errors on certain units, I'd like it to just output the error text if it can't find powershell 5.1 key.
*clients are win 7 HP, Workgroup
*I know my logic is off (red if it's there, green if not) just trying to see what I can come up with myself before asking you guys for assistance
$ComputerName = get-content "C:\Users\David\Desktop\IPS.txt"
$Hive = 'LocalMachine'
$KeyPath = 'SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine'
$Value = 'PowerShellVersion'
$KeyPath1 = 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine'
$Value1 = 'PowerShellVersion'
Foreach ($Computer in $ComputerName) {
if (Test-Connection $computer -Count 2 -Quiet) {
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive, $Computer)
$key = $reg.OpenSubKey("$KeyPath")
$Data = $key.GetValue($Value)
$reg1 = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive, $Computer)
$key1 = $reg1.OpenSubKey("$KeyPath1")
$Data1 = $key1.GetValue($Value1)
If (($data = "2.0") -and ($Data1 = "5.1.14409.1005")){
Write-Host "$Computer needs updated " -ForegroundColor Red
##Added to try and do some error checking [string]::IsNullOrEmpty($Data1)
##Added to try and do some error checking Write-Host $Data1
}else {
Write-Host ""
Write-Host "$Computer $Data" -ForegroundColor Green
Write-Host "$Computer $Data1" -ForegroundColor Green
Write-Host ""
}
}
}
Error I'm getting:
it's weird cause I can output the variable and it looks fine.
The error is occurring on line 18, which is:
$Data1 = $key1.GetValue($Value1)
Since the error indicates you are calling a method on a null-valued expression, that shows that the error has occurred because $key1 is null.
$key1, in turn, is expected to have a value after the previous line (17) is executed:
$key1 = $reg1.OpenSubKey("$KeyPath1")
OpenSubKey returns null when the operation failed. This would happen if the subkey did not exist. So your program needs to check whether $key1 is null after line 17. Then, instead of attempting to call a method on a null object, your program can put out an error message saying that the subkey could not be opened.
If (($data = "2.0") -and ($Data1 = "5.1.14409.1005")){
The above is always true as you are doing assignments (=) vs testing (-eq).
Code should read:
If (($data -eq "2.0") -and ($Data1 -eq "5.1.14409.1005")){

Not entering Function

I'm trying to write a script to remotely rename multiple computers. Here's what I have (I know the Verify function works so that can be skipped over. The issue is occurring with the GetComputers function)
function main{
$DomainCredential = Verify
$computers = GetComputers
#Rename -computers $computers -DomainCredential $DomainCredential
}
function Verify{
# Prompt for Credentials and verify them using the DirectoryServices.AccountManagement assembly.
Write-Host "Please provide your credentials so the script can continue."
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
# Extract the current user's domain and also pre-format the user name to be used in the credential prompt.
$UserDomain = $env:USERDOMAIN
$UserName = "$UserDomain\$env:USERNAME"
# Define the starting number (always #1) and the desired maximum number of attempts, and the initial credential prompt message to use.
$Attempt = 1
$MaxAttempts = 5
$CredentialPrompt = "Enter your Domain account password (attempt #$Attempt out of $MaxAttempts):"
# Set ValidAccount to false so it can be used to exit the loop when a valid account is found (and the value is changed to $True).
$ValidAccount = $False
# Loop through prompting for and validating credentials, until the credentials are confirmed, or the maximum number of attempts is reached.
Do {
# Blank any previous failure messages and then prompt for credentials with the custom message and the pre-populated domain\user name.
$FailureMessage = $Null
$Credentials = Get-Credential -UserName $UserName -Message $CredentialPrompt
# Verify the credentials prompt wasn't bypassed.
If ($Credentials) {
# If the user name was changed, then switch to using it for this and future credential prompt validations.
If ($Credentials.UserName -ne $UserName) {
$UserName = $Credentials.UserName
}
# Test the user name (even if it was changed in the credential prompt) and password.
$ContextType = [System.DirectoryServices.AccountManagement.ContextType]::Domain
Try {
$PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext $ContextType,$UserDomain
} Catch {
If ($_.Exception.InnerException -like "*The server could not be contacted*") {
$FailureMessage = "Could not contact a server for the specified domain on attempt #$Attempt out of $MaxAttempts."
} Else {
$FailureMessage = "Unpredicted failure: `"$($_.Exception.Message)`" on attempt #$Attempt out of $MaxAttempts."
}
}
# If there wasn't a failure talking to the domain test the validation of the credentials, and if it fails record a failure message.
If (-not($FailureMessage)) {
$ValidAccount = $PrincipalContext.ValidateCredentials($UserName,$Credentials.GetNetworkCredential().Password)
If (-not($ValidAccount)) {
$FailureMessage = "Bad user name or password used on credential prompt attempt #$Attempt out of $MaxAttempts."
}
}
# Otherwise the credential prompt was (most likely accidentally) bypassed so record a failure message.
} Else {
$FailureMessage = "Credential prompt closed/skipped on attempt #$Attempt out of $MaxAttempts."
}
# If there was a failure message recorded above, display it, and update credential prompt message.
If ($FailureMessage) {
Write-Warning "$FailureMessage"
$Attempt++
If ($Attempt -lt $MaxAttempts) {
$CredentialPrompt = "Authentication error. Please try again (attempt #$Attempt out of $MaxAttempts):"
} ElseIf ($Attempt -eq $MaxAttempts) {
$CredentialPrompt = "Authentication error. THIS IS YOUR LAST CHANCE (attempt #$Attempt out of $MaxAttempts):"
}
}
} Until (($ValidAccount) -or ($Attempt -gt $MaxAttempts))
# If the credentials weren't successfully verified, then exit the script.
If (-not($ValidAccount)) {
Write-Host -ForegroundColor Red "You failed $MaxAttempts attempts at providing a valid user credentials. Exiting the script now... "
EXIT
} Else {
Write-Host "Credntials authenticated"
return $Credentials
}
}
function GetComputers{
$oldnames = New-Object System.Collections.ArrayList
Write-Output "Enter the PC numbers to be named. Do not include 'PC' only type the following numbers. Type 'end' when finished"
$userinput = Read-Host
while($userinput -ne "end"){
$userinput = "$('PC')$($userinput)"
[void]$oldnames.Add($userinput)
$userinput = Read-Host
}
return $oldnames
}
workflow Rename($computers, $DomainCredential){
foreach -parallel ($computer in $computers){
$newname = "$($computer)$('MK')"
Rename-Computer -PSComputerName $computer -NewName $newname -DomainCredential $DomainCredential
}
}
main
The Verify function works perfectly, but then it just hangs and nothing else happens. I added a debug line between the call of the Verify and the call of the GetComputer functions, and that also printed out. Im new to powershell and am out of ideas
Are you certain that it is hanging, or is Read-Host just showing a blank input location? Calling that function without any arguments will just give you a blinking cursor in command line. Try adding some form of prompt to read-host, like below:
PS C:\Users\mbolton> $var=read-host
"string"
PS C:\Users\mbolton> $var
"string"
PS C:\Users\mbolton> $var=read-host "type something in"
type something in: "different string"
PS C:\Users\mbolton> $var
"different string"
PS C:\Users\mbolton>

WSUS Command to decline updates

I am currently trying to force my WSUS to decline updates through a command line because it is overloaded i cannot access the mangement snap in. This is a code that i found online but the only problem i am having is that my server has dashes in the name and is messing up the code. I tried placing qoutations around the name and it still spits back an invalid character after ":" from 3rd line
EDIT: New Error
Invalid URI: The hostname could not be parsed. at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args) at Microsoft.UpdateServices.Administration.AdminProxy.GetupdateServer(String serverName, Boolean useSecureConnection, Int32 portnumber) at Callsite.Target(Closure , Callsite , Type , Object , Object , Object )
#Change server name and port number and $True if it is on SSL
$Computer = $env:common-n-sccm2012
$Domain = $env:airplane.black.low.com
$FQDN = "$Computer" + "." + "$Domain"
[String]$updateServer1 = $FQDN
[Boolean]$useSecureConnection = $False
[Int32]$portNumber = 8530
# Load .NET assembly
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$count = 0
# Connect to WSUS Server
$updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer1,$useSecureConnection,$portNumber)
write-host "<<<Connected sucessfully >>>" -foregroundcolor "yellow"
$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$u=$updateServer.GetUpdates($updatescope )
foreach ($u1 in $u )
{
if ($u1.IsSuperseded -eq 'True')
{
write-host Decline Update : $u1.Title
$u1.Decline()
$count=$count + 1
}
}
write-host Total Declined Updates: $count
trap
{
write-host "Error Occurred"
write-host "Exception Message: "
write-host $_.Exception.Message
write-host $_.Exception.StackTrace
exit
}
# EOF
I think you mean the error pops up at this line:
$Computer = $env:common-n-sccm2012
because you are trying to get an environment variable with dashes in its name. You may try to format it as:
$Computer = ${env:common-n-sccm2012}
HOWEVER
I think you are 'Environmentifying' hardcoded values and that is the actual problem.
It is hard to believe that you do in fact have Environment variables with names like common-n-sccm2012 and airplane.black.low.com.
To get the actual Fully Qualified Domain Name from the computer you are on, you could do this:
$Computer = $env:COMPUTERNAME # --> "common-n-sccm2012"
$Domain = $env:USERDNSDOMAIN # --> "airplane.black.low.com"
$FQDN = "$Computer" + "." + "$Domain" # --> "common-n-sccm2012.airplane.black.low.com"
( or in one line: $FQDN = "$env:COMPUTERNAME.$env:USERDNSDOMAIN" )
You can also obtain this FQDN using WMI:
$FQDN = (Get-WmiObject win32_computersystem).DNSHostName + "." + (Get-WmiObject win32_computersystem).Domain
You can read about Environment Variables here

Moving computer to another OU in OSD with PowerShell

I am having a lot of trouble getting this code to work in a TS environment.
From a Windows environment, it works great. Just about any variation you will find with a google search of this code works fine in Windows. However in a Task Sequence these variations just produce different error messages for why the computer can't be moved.
Unspecified Error
The specified domain either doesn't exist or couldn't be contacted
Instance of an object not set to an object
I feel that something is happening when we get to the psbase.MoveTo() method call. Up to that point, it can print something out that looks like a reasonable object. In other words, they aren't null or something.
Then psbase.MoveTo() says no.
Example code.
$logFile = "MoveComputerLog.txt"
# Domain Credentials
$account = "domain\osdaccount"
$password = "thepassword"
function logMessage {
param ([string]$logstring)
Write-Host $logstring
Add-content $logFile -value $logstring
}
$computerName = "COMPUTERNAME"
logMessage "computerName: $computerName"
$root = "LDAP://sweet.domain.com"
$domain = New-Object System.DirectoryServices.DirectoryEntry($root, $account, $password)
$search = New-Object System.DirectoryServices.DirectorySearcher($domain)
$search.filter = "(&(objectClass=computer)(name=$computerName))"
$result = $search.findall()
$computerDN = $result.Properties.Item("DistinguishedName")
logMessage "DN: $computerDn"
$computer = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$computerDN", $account, $password)
logMessage "Computer: $computer"
$destination = "LDAP://ou=here,ou=goes,ou=it,dc=sweet,dc=domain,dc=com"
$ou = New-Object System.DirectoryServices.DirectoryEntry($destination, $account, $password)
try {
# "The specified domain couldn't be connected or doesn't exist."
$computer.psbase.MoveTo($ou.Path)
} catch {
Write-Host "Encountered error while moving $computerName"
logMessage $error[0]
}
Here is the definition, ADSI is important:
PS C:\> $computer.psbase.MoveTo
OverloadDefinitions
-------------------
void MoveTo(adsi newParent)
void MoveTo(adsi newParent, string newName)
You can try this, rigth after $result = $search.findall() :
$computer = [ADSI]$result.path
$computer.psbase.Moveto( [ADSI]LDAP://ou=here,ou=goes,ou=it,dc=sweet,dc=domain,dc=com )

"variableB = $+variableA""

Script:
$ZZSG1 = "SGvcenter.domain.com"
$ZZBLR2 = "BlgvCenter.domain.com"
$ZZUS2 = "USvCenter.domain.com"
$siteid = Read-Host "enter physical site id eg:ZZUS2"
$siteids = "ZZSG1","ZZBLR2","ZZUS2"
if ($siteids -notcontains $siteid) {
Write-Host "siteid not found"}
else{
$SID = "$"+"$siteid"
Write-Host "$siteid contains this vCenter $SID"}
$SID
Output:
ZZSG1 contains this vCenter $ZZSG1
$ZZSG1
Expected Output:
ZZSG1 contains this vCenter SGvcenter.domain.com
SGvcenter.domain.com
Your definition of $SID is going to be set a string of the name variable not the value of the variable. Try something like this to get the variable value.
Replace:
$SID = "$"+"$siteid"
with:
$SID = (Get-Variable $siteid).value