Adding Lines to the Beginning and Ending of Files Using PowerShell

Stack Overflow PowerShell question

In dealing with an application with which I had little familiarity, I discovered that troubleshooting an app (in this case developed using ColdFusion) where many of the source code files are “included” dynamically can be difficult – especially when JavaScript scripts are combined that have functions with identical names.

Because so many of the functions were not only identically named, but also similarly constructed, I decided to add commented identifiers to the beginning and ending of each JS file.

This could be done in a number of ways, but given my recent forays into using PowerShell scripts, I chose that route again.

Stack Overflow PowerShell question
Stack Overflow and Google – developers’ best friends.

After some Googling and a brief visit to Stack Overflow, I learned about the two PowerShell “cmdlets” that would be most useful here: Set-Content and Add-Content.

The text of the script is below. What this script does is recursively search through the file path in line 1, choosing only files that have the extension after the filter switch (.js in this case). Looping through these file names, each file is read into memory (using Get-Content). The root of the file is then removed with the first replace command, and for aesthetics, I chose to change backslashes into forward slashes with the second one (lines 4 and 5). Notice that backslashes must be escaped by using an extra backslash, whereas forward slashes are not escaped. Also, in case you’re wondering, the backtick-n (`n) is the newline character in PowerShell. The Set-Content cmdlet is used to add the “$newline” string and then the original file content. The Add-Content cmdlet is then used to add the line marking the end of the file.

Get-ChildItem "C:\Folder\Subfolder" -recurse -Filter *.js | `
Foreach-Object{    
    $content = Get-Content $_.FullName
    $fullname = $_.FullName -replace "C:\\Folder\\Subfolder", ""
    $fullname = $fullname -replace "\\", "/"

    $newline = "// file: " + $fullname + " `n"       
    Set-Content $_.FullName -value $newline, $content
    $endline = "// end of file: " + $fullname + " `n"
    Add-Content $_.FullName $endline
}

Adding a User to Multiple Exchange Distribution Lists Using Windows PowerShell

PowerShell command line window

Adding a user to multiple distribution lists via Outlook can be a tedious process if many lists are involved. For today’s problem, I had to add a user to many lists that have a similar prefix. Instead of spending a an hour or more of adding the user to the DLs through the Global Address Book, I decided to use PowerShell.

This script, which I call “addtodl.ps1”, receives three parameters: the user’s email address, the name of the distribution list – which can include a wildcard character (*) to get multiple names, and the Exchange Server FQDN.

Param(
	[string] $UserName,
	[string] $DLName,
	[string] $Exchange
)

$exch = "http://" + $Exchange + "/PowerShell/?SerializationLevel=Full"

$Credentials = Get-Credential
$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exch -Credential $Credentials -Authentication Kerberos
Import-PSSession $ExSession

$distlists =  Get-DistributionGroup $DLName

foreach ($distlist in $distlists) {		
	Add-DistributionGroupMember -Identity $distlist.PrimarySmtpAddress -Member $UserName
	#$ManagedBy = $distlist.ManagedBy
	#foreach ($owner in $ManagedBy) {
	#	echo $owner
	#}
}

Exit-PSSession
Remove-PSSession -ID $ExSession.ID
[GC]::Collect()

By running this at the PowerShell command line with the parameters, you will be able to add the user to all distribution lists in the query that you manage. Those that you do not have access to will cause an error that will not halt the script. A dialog box asking for your username and password will appear first.

PowerShell command line window

When I have time, I intend to revisit this issue to get more useful information such as owner email addresses. Currently, if you uncomment the lines inside the foreach statement, the owners of each DL will be printed on the screen as well. It’s not too useful yet – which is why I still have it commented here.

Renaming Files Containing a Particular Pattern Using PowerShell

I had mistakenly allowed a string to be appended multiple times on the names of files in a folder on my Windows server by a Python script on which I was working. It was a date string that was applied several times: “_2015-11-04_2015-11-04_2015-11-04_2015-11-04_2015-11-04”

I wanted to remove this string from multiple files that were named MailXXXXXXXXX_2015-11-04_2015-11-04_2015-11-04_2015-11-04_2015-11-04.cfmail (the Xs represent numbers).

I tried using the old RENAME command like this: rename “_2015-11-04_2015-11-04_2015-11-04_2015-11-04_2015-11-04.cfmail” “/…(53 slashes here)…/.cfmail”, but I kept getting errors saying the file was in use.

I turned to PowerShell and found a good script for this purpose on TechNet.

After making the necessary changes, I logged onto the server, opened a Command Prompt with admin privileges, and started PS. I navigated to the folder that contained the files to be renamed and created a script I called rename.ps1 here.

Get-ChildItem -Filter "*_2015-11-04_2015-11-04_2015-11-04_2015-11-04_2015-11-04*" -Recurse | Rename-Item -NewName {$_.name -replace '_2015-11-04_2015-11-04_2015-11-04_2015-11-04_2015-11-04','' }

At the PS prompt, I had to run the command “Set-ExecutionPolicy RemoteSigned” to run the script, and then ran the script: “./rename.ps1”. All the files were renamed as I had hoped.

Using PowerShell to Check if a Particular User is in the Local Administrators Group

PowerShell is a very powerful tool for Windows administrators and developers alike.

I wanted to find out if a particular user ID was in the local admin group on all servers in my domain. Fortunately, someone had written a script (source link no longer exists) to check that very thing on the server you’re logged onto.

However, I wanted to check not just the server I’m on, but on all servers in the domain.

The script below, called findadmins.ps1, should do just that:

$userToFind = $args[0] 

$servers = Get-ADComputer -Filter {OperatingSystem -Like "Windows *Server*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

foreach ($server in $servers) {

	$administratorsAccount = Get-WmiObject Win32_Group -ComputerName $server -filter "LocalAccount=True AND SID='S-1-5-32-544'" 
	$administratorQuery = "GroupComponent = `"Win32_Group.Domain='" + $administratorsAccount.Domain + "',NAME='" + $administratorsAccount.Name + "'`"" 
	$user = Get-WmiObject Win32_GroupUser -filter $administratorQuery | select PartComponent |where {$_ -match $userToFind} 
	$user.PartComponent.Replace("\\","").Split("\", 2, [System.StringSplitOptions]::None)[0]

}

You should be able to run this at the PS command prompt like this, once you’ve changed to the directory where the script is: “.\findadmins.ps1 userid”.

I have not completely finished testing this, as I got a series of errors, though these errors do not appear to be due to errors in the script itself.