PF Permissions

To be honest, I’ve never been a big fan of Public Folders (PFs). Actually, now that I think of it, I’ve never met an Exchange Administrator who doesn’t have a distaste for PFs. However, they are one of those things that many older and larger organizations started to used a long time ago, when it was one of the only choices for collaboration.

One of the nuances of PFs is permissions. When a Root (\) folder is created, typically us admins will setup the permissions for clients. At that point any new child item of folder inherits the permission of it’s parent folder. This works great, until you get into organizations where there can be hundreds of thousands of folders that make a giant mess.

Additionally, when you add PF permissions, the permissions do not get propagated to child folders. Of course you can use the EWS interface, however for very large trees, you will see the command timeout.

So to address this issue I made the below script. The intention of it is to set the permission on a public folder and all child directories. It is built to allow for multiple users and PF branches. This will look at the trees provided and get a list of all of the child public folders. Then it will check if the user already has permissions on the folder, and if so remove the current permissions. Why is this? Well a user can’t have more than on permission on a folder. So any attempt to add the desired permission will produce an error. So instead I strip out the current permission and then replace it with the desired permission.

Enjoy! Download

<#
.SYNOPSIS
Set the PF permissions on all children Public Folders
.DESCRIPTION

.PARAMETER PFrOOT
The path to the ROOT file that you want to set permission. This attrubte accepts multiple paths.
.PARAMETER Users
Provide the list of user
.EXAMPLE
C:\PS> .\Set-PFClientPermissions.ps1 -PFRoot ".\Folder" -Users "User1", "user2" -Perm PublishingEditor

.NOTES
Author: Joshua Wortz
Date: octover 12th, 2016
#>
paramaters(
[array]$PFRoot,
[array]$users,
[string]$Perm
)


$pfs = $pfroot | %{Get-PublicFolder $_ -Recurse}

foreach ($pf in $pfs)
{
foreach ($user in $users)
{

if (Get-PublicFolderClientPermission -User $user -Identity $pf.Identity -ErrorAction:SilentlyContinue)
{
Get-PublicFolderClientPermission -User $user -Identity $pf.Identity | Remove-PublicFolderClientPermission -Confirm:$false

}

Add-PublicFolderClientPermission -Identity $pf.Identity -AccessRights $Perm -User $user -ErrorAction:Stop

}
}

Clean-Logs

For those of us who have been administering Windows web based servers know that one feature that IIS is known for is not rolling over its logs. Many admins have left logging off when not needing to debug or troubleshoot to work around this. In many enterprise environments, it’s import to maintain these logs to review for security issues.

So I initially created this script to trim the IIS logs on exchange servers. it will search for the exchange servers on your environment and remotely query IIS to locate the log directories. After which it will delete any logs older than the configured amount of days.

When Exchange 2013 came out, I updated the script to also truncate the Exchange logs, since Exchange 2013 was created with a large amount of logging, that again doesn’t truncate. The script will also locate the Exchange log files and truncate those logs as well.

Finally at the end, the script will send an email report of all files deleted from each server for record keeping. Follow the link below to download.

Download


&lt;#
.SYNOPSIS
Used to trim IIS logs on Exchange 2013 servers
.DESCRIPTION
Because of the increased level of logging in Exchange 2013 I developed this script
to locate and truncate log files over a certain day length.
This script will find log files in the Default IIS logging location
and in the Exchange installation location
.NOTES
File Name : Clean-Logs.ps1
Author : Joshua Wortz (v1.0)
Prerequisite : PowerShell V2 over Vista and upper.
Versoion History : v1.0 23rd May 2015 : First Edition

#&gt;
param([switch]$Exchange)

$From = "From@domain.com"
$To = "To@domain.com"
$SMTPServer = "SMTPServer"

$days=30 #You can change the number of days here
#$IISLogPath ="C:\inetpub\logs"

Write-Host "Removing IIS and Exchange logs; keeping last" $days "days"

function Out-FileForce {
PARAM($path)
PROCESS
{
if(Test-Path $path)
{
Out-File -inputObject $_ -append -filepath $path
}
else
{
new-item -force -path $path -value $_ -type file
}
}
}

#Locating and Removing old Logs
Function CleanLogfiles($TargetFolder, $Server)
{
$targetfolder = $targetfolder -replace "%SystemDrive%", "c:"
$TargetServerFolder = "\\$($Server)\" + $TargetFolder.split(':')[0] + "$" + $TargetFolder.split(':')[1]
Write-Host $TargetServerFolder
if (Test-Path $TargetServerFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetServerFolder -Include *.log,*.blg -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

$files | Remove-Item -ErrorAction SilentlyContinue | out-null

$colItems = $files | Measure-Object -property length -sum

[string]$sum = "{0:N2}" -f ($colItems.sum / 1MB) + " MB"

$sum

}
Else {
Write-Host "The folder $TargetServerFolder doesn't exist! Check the folder path!" -ForegroundColor "red"
}

}
#gets the name of the Ex2015 servers
Function Get-ExchangeServerInDomain {

$configNC=([ADSI]"LDAP://RootDse").configurationNamingContext
$search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
$objectClass = "objectClass=msExchExchangeServer"
$serialNumber = "serialNumber=Version 15.*"
$name = "name=DC*"#modify if naming schema is different
$search.Filter = "(&amp;($objectClass)($serialNumber)($name))"
$search.PageSize=1000
[void] $search.PropertiesToLoad.Add("name")
[void] $search.PropertiesToLoad.Add("serialNumber")
$search.FindAll() | %{$_.Properties.name[0]}

}
[string]$Body = $null

#Gets list of Servers
[array]$Servers = Get-ExchangeServerInDomain

foreach ($Server In $Servers) {
[array]$logs = $null

#Queries IIS for log paths for Each IIS Site on Server
$IISLogPaths = Invoke-Command -ComputerName ($Server) -ScriptBlock {get-website | %{$_.logfile.Directory}}
$Body += "&lt;H1&gt;$Server&lt;/H1&gt;"
#Delete log files from each IIS path
foreach ($Path in $IISLogPaths)
{

$logs += $path | select @{N="Path";e={$_}}, @{N="Size Deleted";e={$( CleanLogfiles -TargetFolder $Path -server $Server)}}

}

if($Exchange -eq $true)
{
#Get Path of Exchange Installation on remote server
$objReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Server)
$objRegKey= $objReg.OpenSubKey("SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Setup\\")
[array]$ExchangeLoggingPath = $objRegkey.GetValue("MSiInstallPath") + "Logging\"
$exchangeloggingpath += "D:\Exchange\Logs"

$logs += $exchangeloggingpath | select @{N="Path";e={$_}}, @{N="Size Deleted";e={$(CleanLogfiles -TargetFolder $_ -server $Server)}}

$body += $logs | convertto-html -fragment
}

}

$head = @'
&lt;style&gt;
body { background-color:#dddddd;
font-family:Tahoma;
font-size:12pt; }
td, th { border:1px solid black;
border-collapse:collapse; }
th { color:white;
background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px }
table { margin-left:50px; }
&lt;/style&gt;
'@

[string]$html = convertto-html -Head $head -Body $body #| Out-File $reportFile -Force

Send-MailMessage -SmtpServer $SMTPServer -To $to -From $From -Body $html -Subject "IIS Logs Deleted" -BodyAsHtml

Exchange PowerShell Scripts

Earlier this week Exchange team had a new blog post about some of their favorite PowerShell Scripts for Exchange and Office 365 Admins. While they have a few good suggestions, there are a few more that I’ve found most helpful when working with Exchange.

Generate Health Report for an Exchange Server 2016/2013/2010 Environment

By Paul Cunningham
Download Link

This script is one of my personal favorites and I’ve used it for years in several environments. It does an amazing job of scanning your Exchange organization and reporting back with an easy for follow color coded HTML page that you can have emailed to you. I’ve used this as a daily health check of the environment before the workday begins, and also as a snapshot of the current system health by running it in a scheduled task and having the report outputted to a static HTML page, which can be displayed in a public monitoring space.

Exchange Server Performance Health Checker Script

By Marc Nivens
Download Link

The Health Checker script was created by a Microsoft employee as what I can only assume was a large amount of support calls about server performance that was tied to improper system configuration. So this script is ran against your Exchange servers and verifies that your system is configured to match the Exchange 2013 Sizing and Configuration Recommendations along with several patches and recommendations that have come later.   Below is a list of a few of the items it verifies.

  • OS Version
  • Page File Size
  • Server Role
  • Power Settings
  • Checking if Hyper Threading is enabled
  • .Net version

 I’ve found this script to be particularly helpful before bringing new or rebuilt servers into production as well as to verify that no .Net updates have not sneaked onto the server or that a new critical update isn’t missed. This script is growing and always being updated so be sure to check for updates before running.

If you know of any additional scripts that have been helpful to you as an Exchange administrator, please post them in a comment.

Ignite 2016 Sessions + Downloader

Michel de Rooij did a great job putting together this script to download the PowerPoint and video files. You will need youtube-dl.exe to download the videos. Also you can search based on keyword or tittle so you only need to download the sessions you are interested in.

EighTwOne (821)

imageNote: Due to Microsoft putting Ignite 2016 contents on YouTube and a new portal, I had to rewrite the download script. Mattias Fors was also working on this, and after integrating his contents pointers, I present you Ignite2016Download.ps1. Check the description on Technet Gallery page for usage options.

Today, the Ignite 2016 event will kick off in Atlanta, US. The agenda contains the whopping number of 1412 sessions, of which 395 touch Office 365 and 133 Exchange in some way or another.

With those numbers it is impossible to attend every session for folks interested in these topics, but luckily Microsoft will also publish Ignite 2016 sessions on Channel 9 this year.

Some of the interesting sessions to watch out for are (links should resolve to on-demand sessions, as they become available):

Session Description Speaker(s)
BRK1021 Unplug with the Microsoft Outlook experts Julia Foran, Gabe Bratton, Allen Filush…

View original post 830 more words