I have a script which is to reset local administrator password of remote machines and I have mentioned the host list in the script.But just would like is there any way, so that we can add line in my script, so that this will reset the administrator password of all machine which is there in a specific set of subnet(example :10.241.1.0 and 10.241.2.0)?
Can anyone help me with that ?
$computers = Get-Content -path C:\hosts.txt
$user = "Administrator"
$pass = "password1"
Foreach($computer in $computers)
{
$user = [adsi]"WinNT://$computer/$user,user"
$user.SetPassword($pass)
$user.SetInfo()
}
You can easily generate a subnet of IP's using the range operator (a..b). I would define a function and then call it with the particular subnet:
Function Get-SubnetIps($subnet){ 1..254 | %{ $subnet + $_ } }
Example usage would be:
$computers = Get-SubnetIps "192.168.1."
$user = "Administrator"
$pass = "password1"
Foreach($computer in $computers)
{
$user = [adsi]"WinNT://$computer/$user,user"
$user.SetPassword($pass)
$user.SetInfo()
}
You may run into problems if every IP is not reachable. try/catch will save you if that should come to pass. When writing these sorts of scripts, it can be helpful to report progress.
Related
I'm looking at creating a local administrator on a handful of machines (>30). I don't really want to use GPO if I can get away with it. LAPS is a little overkill for what I need.
I found a nice script online but it only creates the user and doesn't add them to the administrators group. Can anyone see the error?
#Define variables
$computers = Get-Content C:\Computers.txt
#$computers = Import-CSV C:\Computers.txt | select Computer
$username = "Admin"
$password = "Password99"
$fullname = "Admin"
$local_security_group = "Administrators"
$description = "Description"
Foreach ($computer in $computers) {
$users = $null
$comp = [ADSI]"WinNT://$computer"
#Check if username exists
Try {
$users = $comp.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username already exists on $computer"
} else {
#Create the account
$user = $comp.Create("User", "$username")
$user.SetPassword("$password")
$user.Put("Description", "$description")
$user.Put("Fullname", "$fullname")
$user.SetInfo()
#Set password to never expire
#And set user cannot change password
$ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
$ADS_UF_PASSWD_CANT_CHANGE = 0x40
$user.userflags = $ADS_UF_DONT_EXPIRE_PASSWD + $ADS_UF_PASSWD_CANT_CHANGE
$user.SetInfo()
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$username = [ADSI]"WinNT://$Computer/$username,user"
#Validate whether user account has been created or not
$users = $comp.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username has been created on $computer"
} else {
Write-Host "$username has not been created on $computer"
}
}
}
Catch {
Write-Host "Error creating $username on $($computer.path): $($Error[0].Exception.Message)"
}
}
In your code you are not actually adding the user to the group.
Here you are actually retrieving a group object, but you are not doing anything with it.
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$username = [ADSI]"WinNT://$Computer/$username,user"
First you must remove the assignment to $username. Then you must invoke a method on the $group object to add the user:
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$computerHostName = (Get-WmiObject -ComputerName $computer Win32_ComputerSystem).Name
$group.Add([ADSI]"WinNT://$computerHostName/$username,user")
There is a catch here. Notice I use Get-WmiObject to get the hostname from the computer. When using the Add() method, the computer name must be the unqualified hostname. For example server-01, and NOT server-01.domain.lan
If you want to retrieve the ADSI object for the user later, I recommend assigning it to a different variable name, like this:
$adsiUser = [ADSI]"WinNT://$Computer/$username,user"
I am trying to write a powershell script that runs a specific code block as a domain admin and moves a computer to a specific OU.
If I run it as a domain admin, it works fine, but the problem is it usually runs it as a local admin; which obviously won't add the computer to the domain.
So I added the credentials as part of the script, but it doesn't seem to be working.
Here is my code:
CLS
$command = {
# Specify, or prompt for, NetBIOS name of computer.
$Name = $env:COMPUTERNAME
# Retrieve Distinguished Name of current domain.
$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Root = $Domain.GetDirectoryEntry()
$Base = ($Root.distinguishedName)
# Use the NameTranslate object.
$objTrans = New-Object -comObject "NameTranslate"
$objNT = $objTrans.GetType()
# Initialize NameTranslate by locating the Global Catalog.
$objNT.InvokeMember("Init", "InvokeMethod", $Null, $objTrans, (3, $Null))
# Retrieve NetBIOS name of the current domain.
$objNT.InvokeMember("Set", "InvokeMethod", $Null, $objTrans, (1, "$Base"))
$NetBIOSDomain = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $objTrans, 3)
# Retrieve Distinguished Name of specified object.
# sAMAccountName of computer is NetBIOS name with trailing "$" appended.
$objNT.InvokeMember("Set", "InvokeMethod", $Null, $objTrans, (3, "$NetBIOSDomain$Name$"))
$ComputerDN = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $objTrans, 1)
#Bind to computer object in AD.
$Computer = [ADSI]"LDAP://$ComputerDN"
#Specify target OU.
$TargetOU = "OU=Block-Policies,OU=Windows 10,OU=LAPTOPS,OU=COMPUTERS,OU=COMPUTER-SYSTEMS,DC=domain,DC=com"
#Bind to target OU.
$OU = [ADSI]"LDAP://$TargetOU"
# Move computer to target OU.
$Computer.psbase.MoveTo($OU)
}
#Credentials
$domain = "domain.com"
$password = "2093dhqwoe3212" | ConvertTo-SecureString -asPlainText -Force
$username = "$domain\DomainAdmin"
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
#Run the command with escalation
Invoke-Command -Credential credential -ComputerName localhost -ScriptBlock {$command}
I know the credentials work because if I manually type them in and run the script, it works. I have tried using invoke-command as well as
start-job -ScriptBlock {$command} -Credential $credential
Neither seem to be working for me.
The start-job seems to go through, but doesn't actually move the computer. The invoke-command gives me an error.
"[localhost] Connecting to remote server localhost failed with the following error message: The client cannot connect to the destination specified in the request ..."
Setup:
We are all in domain environment. Active Directory is Windows Server 2012 R2
Client Workstations are mix of Windows 10 versions (1703 and 1709)
Need to create user "Servis" on all workstation and place it to local Administrator group. I will input a text file with the host names.
This is the script im trying to make it work, but no success.
The user is created, but user is not added to local admin group.
This is the error i get :
Error creating Service23 on WinNT://WS-TEST: The following exception occurred while retrieving member "add": "The network path was not found.
$computers = Get-Content -path C:\Scripts\CreateLocalUser\New\Computers.txt
$username = "Servis"
$password = "P4$$w0rd!##"
Foreach ($computer in $computers) {
$users = $null
$computer = [ADSI]"WinNT://$computername"
Try {
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username already exists" -ForegroundColor Green
}
Else {
$user_obj = $computer.Create("user", "$username")
$user_obj.SetPassword($password)
$user_obj.SetInfo()
$user_obj.Put("description", "$username")
$user_obj.SetInfo()
$user_obj.psbase.invokeset("AccountDisabled", "False")
$user_obj.SetInfo()
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username has been created on $($computer.name)"
$group = [ADSI]("WinNT://" + $computername + "/administrators,group")
$group.add("WinNT://" + $computername + "/" + $username + ",user")
}
Else {
Write-Host "$username has not been created on $($computer.name)"
}
}
}
Catch {
Write-Host "Error creating $username on $($computer.path): $($Error[0].Exception.Message)"
}
}
Once you've defined your credential correctly with a password in a SecureString format creating a local admin is a 2 step process:
Create a user
Add that user to the Local Administrators group
These few lines are the powershell code needed:
$username = "Servis"
$password = ConvertTo-SecureString -AsPlainText "P4$$w0rd!##" -Force
New-LocalUser "$username" -Password $password -FullName "$username" -Description "Local admin $username"
Add-LocalGroupMember -Group "Administrators" -Member "$username"
If you want make you script more robust you should consider to create some Pester tests and add these checks to your script:
Validate if your file exists
Validate the content of the file (if is an IP or a FQDN with a regex)
Test if the host is reachable (e.g. Test-Connection -computername $computer -count 1 -quiet) before connecting
Using invoke-command with computername and argumentlist (username, password)
Check if the user was created successfully and is a member of the administrator group if not throwing an error
Write a log file to keep trace of all the tasks completed (by who, when on what host and so on).
I wrote a blog post on www.scriptinglibrary.com on few better ways of completing this task if you're interested.
I am trying to create user on remote machine using Powershell. Once account created I want to add that in local admin group.
Account is getting created but it is not getting added in admin group. Below is the code that I am using.
cls
$username = "test_user"
$password = "password"
$computer1 = hostname
$users = $null
$computer = [ADSI]“WinNT://$computer1”
Try {
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username already exists"
} Else {
$user_obj = $computer.Create(“user”, “$username”)
$user_obj.SetPassword($password)
$user_obj.SetInfo()
$user_obj.Put(“description”, “$username”)
$user_obj.SetInfo()
$user_obj.psbase.invokeset(“AccountDisabled”, “False”)
$user_obj.SetInfo()
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username has been created on $($computer.name)"
$group = [ADSI]("WinNT://"+$env:COMPUTERNAME+"/administrators,group")
$group.add("WinNT://$env:localhost/$username,user")
} Else {
Write-Host "$username has not been created on $($computer.name)"
}
}
} Catch {
Write-Host "Error creating $username on $($computer.path): $($Error[0].Exception.Message)"
}
What am I doing wrong?
$env:computername is your local computer. $env:localhost doesn't exist. $computer1 is the variable you defined of the computer to you are adding the user to earlier.
$group = [ADSI]("WinNT://$computer1/administrators,group")
$group.add("WinNT://$computer1/$username,user")
I use this
$computername = "computername" # place computername here for remote access
$username = 'user'
$password = 'P#ssw0rd1' #password
$desc = 'Local admin account'
$computer = [ADSI]"WinNT://$computername,computer"
$user = $computer.Create("user", $username)
$user.SetPassword($password)
$user.Setinfo()
$user.description = $desc
$user.setinfo()
$user.UserFlags = 65536
$user.SetInfo()
$group = [ADSI]("WinNT://$computername/administrators,group")
$group.add("WinNT://$username,user")
That is a whole lot of code, just to do this.
Invoke-Command -ComputerName SomeRemoteComputerName -ScriptBlock {
net user SomeNewUserName SomePassword
net localgroup administrators SomeNewUserName /add
}
Yeppers, I know, it's not all pure PoSH. Sure, you can do this with via more code in PoSH (way more in ), but sometimes you just need to get stuff done.
But vs doing this from scratch (well, unless you are just trying to learn stuff). There is a whole set of pre-built scripts and module for you to leverage. See:
'gallery.technet.microsoft.com/scriptcenter/site/search?f%5B0%5D.Type=RootCategory&f%5B0%5D.Value=localaccount'
Of course if all machines were on PoSH v5+, then you just use the built-in cmdlets for local user / group management.
'learn.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/?view=powershell-5.1'
As for the other question:
'check service account exist or not'
Assuming you are asking if this is for a remote computer, then it's the same approach.
Invoke-Command -ComputerName SomeRemoteComputerName -ScriptBlock {
Get-Service -Name SomeServiceName
Get-Service -DisplayName SomeServiceDisplayName
}
I want to create a PowerShell script which will disable the windows account, the target host name will be provided as an argument. Only admin should be able to execute this task.
This is what I have tried. Could someone please tell me if this approach is right or is there any better way to do this.
param( [Parameter(Mandatory=$true)] [String] $TargetHost ,
[Parameter(Mandatory=$true)] [String] $TargetUserName ,
[String] $User ,
[String] $Password)
# Set up a trap to properly exit on terminating exceptions
trap [Exception] {
write-error $("TRAPPED: " + $_)
exit 1
}
function DeactivateAccount($TargetHost , $TargetUserName ,$User , $Password){
$TargetHost = $TargetHost #Target Host on which windows account deactivation will be done.
$TargetUserName = $TargetUserName #User Name of Target.
$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() #Domain name of the localhost.
$localHost = [System.Net.Dns]::GetHostName()
$localIP = [System.Net.Dns]::GetHostAddresses("$localHost")
#if TargetHost and LocalHost are same.
if($localHost -like $TargetHost -OR $localIP -like $TargetHost) {
if($Domain -eq [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()){
$process = net user $TargetUsername /domain /active:no #Performs the operation on the domain controller in the computer's primary domain.
} else {
$process = net user $TargetUsername /active:no
}
Write-host " $TargetUsername account deactivated "
}
#If TargetHost is remote Host.
else {
$User = $User #Creds to perform admin function.
$Password = $Password
$SecurePassword = new-Object System.Security.SecureString #Convert password into secure string.
$Password.ToCharArray() | % { $SecurePassword.AppendChar($_) }
$Cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist "$User",$securePassword
$newSession = New-PSSession -ComputerName "$TargetHost" -credential $Cred #Used PSSession for persistent connection and credentials to Specify a user account that has permission to perform this action.
$export_username = Invoke-Command -Session $newSession -ScriptBlock {$username=args[1]} # Invoke-Command command uses the Session parameter(here newSession) to run the commands in same session.
if($Domain -eq [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()){
$process = Invoke-Command -Session $newSession -ScriptBlock {net user $username /domain /active:no}
} else {
$process = Invoke-Command -Session $newSession -ScriptBlock {net user $username /active:no}
}
Write-host " $TargetUsername account deactivated "
Remove-PSSession $newSession # Closes Windows PowerShell sessions.
}
if(-not $?) { # Returns true if last command was successful.
Write-Error "Windows Deactivation Failed!!"
exit 1
}
}
DeactivateAccount($TargetHost , $TargetUserName ,$User , $Password)
Couple of things:
Your meant to show some code to show you tried but since you're new to Powershell I'll let that slide :)
Is it a local windows account you are trying to disable or an AD one? For the purpose of this I'll assume local.
Grab this module: https://gallery.technet.microsoft.com/PowerShell-Module-to-255637a3
The dude basically made a module for exactly what you want to do :)
Note: If you have Powershell 5.1+ you won't need the module they added new cmdlets to do this natively.
Credential-wise I wouldn't worry, Powershell can't bypass windows security, it will execute with the permissions of the user that ran the script unless your script specifically gives credentials for another user in the commands.
Let me know how you get on.