Powershell issue reading groups from txt file - windows

So, with the same code from my last question I've got a new problem. It returns a count, but there's two AD groups causing problems. We'll call them 'East Group' and 'West Group'. Both written exactly that way with spaces and thus requiring quotes. When I run:
(Get-ADGroup "East Group" -Properties *).member.count
It returns the count of users no problem. However, when I run the code for my grand total ignoring duplicates:
$script:cnt = 0
$Groups = Get-Content -Path $someFile
$Groups | Get-ADGroupMember | Select-Object -expand DistinguishedName -Unique | ForEach-Object { $script:cnt++ }
$script:cnt
It returns a total, but also an error saying that it cannot find West Group or East Group under my domain. My best guess is it's somehow ignoring the quotation marks in the text file. Is there a way to make it read it as "East Group" or some other workaround?

it's somehow ignoring the quotation marks in the text file.
Don't put quotation marks in your plain-text file with group names, if you're reading it with Get-Content - such quotes will become part of the values, which is not your intent - simply rely on Get-Content to read the file line by line, which will work correctly even with values with spaces.
# Create the group-list file - do NOT use quotation marks around the entries.
#'
NoSpacesGroup
East Group
'# > Groups.txt
# Demonstrate that each group name is read correctly, even if it
# contains spaces.
Get-Content Groups.txt | ForEach-Object { "this group: >>$_<<" }
The above yields:
this group: >>NoSpacesGroup<<
this group: >>East Group<<
demonstrating that even the value with spaces was correctly read as a single value (line).
Therefore, simply remove the quotes from your group file and try your command again.

Related

Is there a PowerShell Get-Content Function to extract line based on the first character?

I am trying to extract each line from a CSV that has over 1million (1,000,000) lines, where the first character is a 1.
The 1 in this case, refers to the 1st line of a log. There are several different logs in this file, and I need the first line from all of them. Problem is (as you could understand) 1 is not unique, and can appear in any of the 12 'columns' of data I have in this CSV
Essentially, I would like to extract them all to a new CSV file as well, for further break down.
I know it sounds simple enough, but I cannot seem to get the information I need.
I have searched StackOverflow, Microsoft, Google and my own Tech Team.
PS: Get-Content 'C:\Users\myfiles\Desktop\massivelogs.csv' | Select-String "1" | Out-File "extractedlogs.csv"
The immediate answer is that you must use Select-String '^1 in order to restrict matching to the start (^) of each input line.
However, a much faster solution is to use the switch statement with the -File` option:
$inFile = 'C:\Users\myfiles\Desktop\massivelogs.csv'
$outFile = 'extractedlogs.csv'
& { switch -File $inFile -Wildcard { '1*' { $_ } } } | Set-Content $outFile
Note, however, that the output file won't be a true CSV file, because it will lack a header row.
Also, note that Set-Content applies an edition-specific default character encoding (the active ANSI code page in Windows PowerShell, BOM-less UTF-8 in PowerShell Core); use -Encoding as needed.
Using -Wildcard with a wildcard pattern (1*) speeds things up slightly, compared to -Regex with ^1.

Adding/Removing hosts file entry using powershell corrupts the file

I'm trying to add or remove a specific entry in Windows hosts file using powershell, but when I do this, it works for some time, and after a while it gets edited again (when Windows reads it, I guess), and it becomes corrupted (displays chinese characters).
I've tried using parts of a code i found here.
It allows me to edit the file properly and the entry is effective, until it gets corrupted.
I'm doing this to add the entry:
If ((Get-Content "$($env:windir)\system32\Drivers\etc\hosts" ) -notcontains "111.111.111.111 example.com")
{ac -Encoding UTF8 "$($env:windir)\system32\Drivers\etc\hosts" "111.111.111.111 example.com" }
Here is what the file looks like after it gets corrupted:
Thanks for your help.
Solved:
Remove -Encoding UTF8
Because as it states in the comment of the hosts file, "The IP address and the host name should be separated by at least one space.", trying to find a string with exactly one space character in between could return false.
I think it would be better to use Regex for this as it allows matching on more than one space character to separate the IP from the host name.
However, this does require the usage of [Regex]::Escape() on both parts of the entry as they contain regex special characters (the dot).
Something like this:
$hostsFile = "$($env:windir)\system32\Drivers\etc\hosts"
$hostsEntry = '111.111.111.111 example.com'
# split the entry into separate variables
$ipAddress, $hostName = $hostsEntry -split '\s+',2
# prepare the regex
$re = '(?m)^{0}[ ]+{1}' -f [Regex]::Escape($ipAddress), [Regex]::Escape($hostName)
If ((Get-Content $hostsFile -Raw) -notmatch $re) {
Add-Content -Path $hostsFile -Value $hostsEntry
}

Deleting Lines in a Text File Given Strings From Another File Using Set-String (Powershell)

Basically what's happening is that I have two files, one with a list of allowed users and another list of users that are actually on the desktop. What I'm trying to do is use a for loop to grab each name in the AllowedUsers.txt file, and use Select-String to find any names that match and delete them from the original Users.txt (the list of users actually on the desktop). The end goal is to have a list of users that aren't allowed on the desktop left in the Users.txt file, where I can then for loop through once again and simply delete those users through command line.
Unfortunately, I have been unable to get this to work as I don't fully grasp how Select-String or for loops work, but any help writing the script would be greatly appreciated.
Example for AllowedUsers.txt (Input):
abbby
Sebastian
Evan
Example for Users.txt (Input):
abbby
Evan
Sebastian
Ethan
zachary
Example for edited Users.txt (Desired Output):
Ethan
zachary
here's another way to do it. unlike the solution by LotPings, it uses the array membership operator -notin to see if the items in the general user list are in the allowed list. i did not overwrite the the source user list since that bothers me. [grin] you can easily change that, tho.
note that PoSh versions below 3 will need to use -notcontains and swap the items to put the collection on the left of the test instead of the right. thanks to Theo for the reminder about that!
# fake reading in a text file
# in real life, use Get-Content
$AllowedUsers = #'
abbby
Sebastian
Evan
'# -split [environment]::NewLine
# another fake file read
$AllUsers = #'
abbby
Evan
Sebastian
Ethan
zachary
'# -split [environment]::NewLine
# this presumes the source files are both text and have the same name format
# the "-notin" operator is NOT case sensitive
$ExcludedUsers = $AllUsers |
Where-Object {$_ -notin $AllowedUsers}
# send to screen
$ExcludedUsers
# send to text file
$ExcludedUsers |
Set-Content -LiteralPath "$env:TEMP\BassoftheC_ExcludedUserList.txt"
on screen ...
Ethan
zachary
text file content ...
Ethan
zachary

Looking to extract information using powershell

I need to extract information using a powershell cmdlet and a txt file.
The TXT file contains a list of groups
I want to first feed powershell the script... pretty simple:
get-content c:\scripts\mygroups.txt
I then want to run a Foreach-object cmdlet against it and pull only the distinguished name
The problem is that I keep running into the -Filter command and I shouldn't need the filter command because the names are exactly pulled from AD.
Foreach-Object {Get-ADGroup -Filter "*" | select DistinguishedName} works but I dont want all the groups I want the variable that I used for the get-content command. I feel I am missing some type of link between the -Filter and selecting the field I want to display. Please help me link the two together. Thanks!
Here is the error I am getting...
Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADGroup
Assuming that each group name is on a line in the file and there are no blank lines, try this:
Get-Content c:\scripts\mygroups.txt | Foreach {Get-ADGroup $_} |
Select DistinguishedName
You could actually take out the "Foreach" part of Keith's code and just let the pipeline do the loop for you:
Get-Content c:\scripts\mygroups.txt | Get-ADGroup | Select DistinguishedName
This is still assuming that the text file contains the group names, ("Name" attribute), with only one group name per line.
Pipe the content of the file to the Get-ADGroup cmdlet and expand the DistinguishedName of each output object:
Get-Content c:\scripts\mygroups.txt |
Get-ADGroup |
Select-Object -ExpandProperty DistinguishedName

Read in two text file lists and write out 1 line from to a text file

I need to create a powershell script that reads in two text files with lists.
The first list is used to identify the remote computers that will have a file appended to it.
The second list is the key phrase that needs to be appended to the file.
List 1:
Computer1
Computer2
Computer3
List 2:
ABC
DEF
GHI
Script would loop through each pointing to a file say C:\temp\help.txt on each of the remote computers and write 1 line from List 2.
So Example: When the script runs it goes out to List 1, finds that computer 1 is first and opens the file \computer1\C$\temp\help.txt, it would then grab the first line from List 2 and write to the file ABC. Close the file and go on to Computer 2. Computer 2 would be \computer2\C$\temp\help.txt and would grab the 2nd item from List 2 and write to it DEF save and move on.
It's been hard to find any help reading in and looping through 2 lists. Or perhaps I am thinking of it wrong. I have gotten to Get-Content to read in the file and foreach($x for text1) can go through 1 of the text files loops but can not figure out how to loop through the 2nd text file.
Processing side-by-side arrays is always a pain, and tends to be error prone. Ideally, as suggested, the computer names and strings would be together in a CSV or something.
But as is, something like this should get you on the right track. You might have to fiddle with newlines at the beginning/end of the strings a bit.
$machines = Get-Content .\MachineList.txt
$strings = Get-Content .\StringsList.txt
if($machines.Count -ne $strings.Count){ throw 'Counts do not match' }
for($i = 0; $i -lt $strings.Count; $i++)
{
$path = "\\$($machines[$i])\C`$\temp\help.txt" # unc path
$strings[$i] | Add-Content $path
}
If you have it in a CSV like
Config.csv
---------
ComputerName,String
machine1,string1
machine2,string2
machine3,string3
Then you could simplify to this:
Import-Csv .\Config.csv |%{
$_.String | Add-Content "\\$($_.ComputerName)\C`$\temp\help.txt"
}

Resources