Author Posts

March 14, 2018 at 5:04 pm

Hello
I have 2 text files: 1 for online computers, 1 for offline computers. These files were generated using powershell by pinging computers in a specific OU and writing the pingable computers to Onlinecomps.txt and writing the un-pingable computers to Offlinecomps.txt.

I am creating a new Local Admin account on all the computers in the domain. Some computers are not online at all times (laptops, tablets etc).

The part of the script to create the account on an online computer already works. But from this point on, I only want to iterate through the offlinecomps.txt, ping them and if any of them is online; create the local admin account, take the computername out of the file and append it to the onlinecomps.txt file.

I would run this script manually, several times a day until all computers have the new Local Admin account. (Then I will look at disabling "The" Administrator account).

I know I can get the computer names from the get-content and using a foreach, but I can't seem to find a way to remove it from one file and append it to another.

Ex:
$x = Get-Content c:\temp\offlinecomps.txt
Foreach($comp in $x) {
$ping=Test-Connection $comp.name -count 1 -quiet
If ($Ping) {
Create the account script — this part of my script already works as it should.
Remove that line from offlinecomps.txt file
Add that computername to the onlinecomps.txt so that it does not get tested the next time the script is run...
}
}

Any help would be appreciated.

Thank You
Terry

March 14, 2018 at 6:31 pm

You can't remove a line from a file. You need to read in the entire file, and write out, to a new file, the lines you want to keep. PowerShell's text file manipulation just isn't complex enough to support search-and-replace type activities.

So, read in file A, write out file B, delete file A, rename B to A.

Appending is easy. Use Add-Content or Out-File with the -Append parameter.

March 15, 2018 at 3:31 pm

That's Awesome
Thank you for the concept of how it needs to be done.

Terry

March 15, 2018 at 10:30 pm

Hello
1. I need to preserve values in the onlinecomps.txt and add new compnames that are currently pingable.
2. I need to remove those currently pingable compnames from offlinecomps.txt and save the file with the same name.
3. The two text files are created by another script that simply tries to ping the computer from AD. And based on the ping results
the computer names are put into the appropriate file.

Onlinecomps.txt
Two
Three
Four
Five

Offlinecomps.txt
Six
Seven
Eight
Nine
Ten
Eleven

Currently pingable computers – Six, Nine, Ten

Here's what Im doing:

$A=@()
$txt1=get-content D:\Tmp\onlinecomps.txt
$txt2=get-content D:\tmp\offlinecomps.txt

$Lookup = @{
    "=>" = "Present in File2"
    "< =" = "Present in File1"
    "==" = "Present in both files"
}

$Vals=Compare-Object -ReferenceObject $txt1 -DifferenceObject $txt2 -IncludeEqual | Select @{Name="String";Expression={$_.InputObject}},@{Name="Presence";Expression={$Lookup[$_.SideIndicator]}}
foreach($L in $Vals) {If($L.Presence -eq "Present in both Files") { Add-Content -Path D:\Tmp\onlinecomps.txt -Value $L.String
$A += $L.String
For ($b -eq 0;$b -le $A.count;$b ++) {
$offline =$txt2 | Where {$A -notmatch $A[$b] } | Set-Content D:\Tmp\offlinecomps.txt}  # I'm out to lunch on this line....
}
}

So, $A collects the currently pingable computers (it collects the right values)
$offline contains all comps listed in offlinecomps.txt except those that don't match any of the values in $A — so that I will now have all currently offline computers for the next time I run my script.
It all seems to work except the rebuilding of the offlinecomps.txt

Any suggestions?

Thank You
Terry

March 15, 2018 at 10:35 pm

The logic seems overly complex for me.

ForEach ($line in (Get-Content offline.txt)) {
  if ( (Test-Computer -Comp $line -Quiet) ) {
    $line | Out-File online.txt -Append
  } else {
    $line | Out-File newoffline.txt -Append
  }
}
Remove-Item offline.txt
Rename-Item newoffline.txt offline.txt

No? Or am I massively missing something? I guess I don't understand the need to compare files, nor all the array management.

March 15, 2018 at 10:39 pm

It may seem over complex to you because I am a noob 🙂
Thanks Don
I'll try the new "simpler" logic 🙂

Terry

March 15, 2018 at 10:39 pm

Sorry, I did miss the bit about the other script doing the pinging. That seems unnecessary. But whatever, if that's what you've got. I'm having trouble following the need, then.

1. I need to preserve values in the onlinecomps.txt and add new compnames that are currently pingable.
How do you know which computer names are "currently pingable?" If all computers in onlinecomps.txt respond to a ping, then by definition everything in onlinecomps.txt are pingable, right?

2. I need to remove those currently pingable compnames from offlinecomps.txt and save the file with the same name.
How do you know which computers in offlinecomps.txt are pingable?

Like, are you saying it's possible for both files to contain a given computer name, and if so, then the computer is pingable and should be removed from offlinecomps.txt? If this other script is populating these files, why isn't it just updating both files correctly?

March 16, 2018 at 10:11 am

Why not just use group policy to create the local admin account ??

March 16, 2018 at 2:48 pm

Hi Don
I Apologize for being unclear:
My other script searches an OU and pulls out computer names.
It then pings the computer (by name); if the computer pings successfully, it gets put into an array with it's model. If the computer does not ping successfully, it is written to the offlinecomps.txt file (so that I can monitor which computers have and which have not received a new LocalAdmin Account. Not all computers are on the network all the time – some are in the field etc.

Now these files have been created, so I now only need to test ping the "offline" computers to see if any of them are now online.
If they are online, the script will create a new LocalAdmin account on it/them. The computername will be taken out of the "offline" computers text file and placed in the "online" computers text file (so that it does not get tested the next time).

$userName = 'newAdmin'
$password = ConvertTo-SecureString -String '123456789' -AsPlainText -Force
$group = 'Administrators'
$computers=Get-ADComputer -filter * -SearchBase "OU=Test OU,OU=Computers,OU=AnotherOU,DC=Domain,DC=local"
foreach ($comp in $Computers) 
{
Invoke-Command -ComputerName $comp.Name -ArgumentList $userName, $password, $group -ScriptBlock {
    New-LocalUser -Name $args[0] -FullName 'Local Admin' -Description 'Local Admin Account' -Password $args[1] -PasswordNeverExpires -AccountNeverExpires -UserMayNotChangePassword
    Add-LocalGroupMember -Group $args[2] -Member $args[0]
}
}

Once all computers have been successfully processed (they have all received the new LocalAdmin Account), I can then inventory all computers for each model, simply by querying the "onlinecomps.txt" file.

So my scripting is dual purposed. It gathers the computer names and models and it ensures that all computers in the domain get the new Admin Account.

The reason I am not creating a GPO to create the new admin account is because I do not want to have a file on the network with a clear password. So, I will run this script from my own desktop and when its all done, I will place it in a protected place on the network. Seems MS has recently disallowed a computername to be considered a user for authentication, So any authenticated user would have access to view the script (not that most would know how to find it or what to do with it).

I hope I have explained my scenario clearly

Thank you
Terry

March 16, 2018 at 2:51 pm

OK. So, my previous short example should at least give you the logic you need. Read in the offline names, ping and do whatever with them. If they ping, append them to online. If they don't, write them to a new offline file. At the end, delete the original offline file and rename the new one.

I'll second the GPO comment, though. Much more reliable way to manage privileged accounts.