Remove Read Only Item Flag

I recently had an issue where I needed to update the Read Only Item Property on a large set of files.

Below is a script that will process all files under ‘C:\BACKUPFILES’ and set the Item Property ‘Read Only’ to false on all files.

$FolderPath = 'C:\BACKUPFILES'
$setRoAttributeTo = $false
$Items = Get-ChildItem -Path $folderPath -Recurse
Foreach ($File in $Items) {

 IF ($file.Attributes -like '*ReadOnly*'){
Write-Host $file.FullName
Write-Host "File Read Only" -BackgroundColor DarkRed
  Set-ItemProperty $File.FullName -Name IsReadOnly -Value $setRoAttributeTo
 }
}

Skype /WebTicket Validation

Issues with /WebTicket/WebTicketService.svc/mex

I recently helped a customer expand their existing Skype 2015 environment to add additional front end pools and additional servers to their existing pools. This expansion was to support business growth over the next two years as they setup the foundations for O365 and plan a move to MS Teams.

To successfully expand the existing pools without impacting current users we first migrated all users off a pool, expanded the topology, deployed Skype and other 3rd party software needed, and moved users back after the pools were healthy. During this process we had a handful of tickets created that came up for some (but not all) users.

Issue 1: Users were unable to log into mobile clients (external)

Issue 2: Some users were getting errors when attempting to join meeting via the Skype for Business Web App:

Digging into this we quickly identified that a handful of the new servers deployed were not correctly responding to Web Ticket requests. Instead of receiving the typical XML page with a status 200 message we were seeing Page could not be displayed errors with a status 500 message.

To temporarily resolve this issue I identified what servers were not responding correctly to /WebTicket/ calls and disabled them in the Load Balancer web conferencing VIPs.

Once this was done we reinstalled the conferencing components and confirmed /WebTicket requests were correctly responding.

To avoid this issue in the future I wrote a script that would query Skype for the front end pools, select all servers in each pool and test the /WebTicket URL and output the status result (200 for success, 500 for failure)

Validate-WebTickets.ps1

$Pools = Get-CsPool | WHERE {$_.Services -like "Registrar:*"}|Sort-Object Identity | SELECT Identity

ForEach ($Pool in $Pools) {
    $Servers = Get-CSPool -Identity $Pool.Identity |SELECT -ExpandProperty Computers
    Write-Host $Pool.Identity -ForegroundColor Yellow -BackgroundColor Black
    ForEach ($Server in $Servers){
    $WebCall = 'https://'+ $Server + '/WebTicket/WebTicketService.svc/mex'
    #Write-Host $Webcall
    $StatusDetails = Invoke-WebRequest -Uri $WebCall |SELECT StatusCode,StatusDescription,Headers
    $StatusDetails
    }
}

Bulk Enable CAPI2 Logging

Enable & Disable CAPI2/Operational Logging

One of the biggest headaches to troubleshoot when working with customer deployments is certificates.

What is the CAPI2/Operational Log? CAPI2 stands for Cryptographic API. The CAPI2 log is located in event viewer under Application and Services Logs/Microsoft/CAPI2/Operational.

By default, Microsoft has this log disabled. This log will grow/overwrite itself extremely fast on a production server that relies on certificates.

During a recent Skype to Exchange troubleshooting effort Microsoft requested that we enable CAPI2 logging to identify why Exchange was throwing an error accepting Unified Messaging (UM) calls from a Skype Pool.

Due to the nature of this issue we had to enable CAPI2 logging on All production Exchange servers as we had no way to force Skype to connect to a specific server.

Below is an example of what you would see in a CAPI2 log once enabled

Note: I only turned this logging on my laptop for 15 seconds and already have over 300 events captured)

I had to enable CAPI2 logging on almost 50 servers, reproduce our failed connection attempt, then disable the logs before they overwrote themselves.

Below is the script I used to set the log size to 20MB as well as enable or disable the logs in bulk

Enable-CAPI2Loging.ps1

$Servers = @(Import-CSV -Path '.\servers.txt')

If ($Servers.count -like 0){
Write-Host 'No Servers Listed' 
Exit
}
Else{
Write-Host "Total Server Count: " -NoNewline
Write-Host $Servers.count
}

ForEach ($i in $Servers) {

    $Server = $i
    Write-Host 'Working on Server' $Server -BackgroundColor Yellow -ForegroundColor Black
    Invoke-Command -ComputerName $Server -ScriptBlock { 
	wevtutil sl Microsoft-Windows-CAPI2/Operational /ms:20000000
	wevtutil.exe sl Microsoft-Windows-CAPI2/Operational /e:true
    }
 }


Disable-CAPI2Logging.ps1

$Servers = @(Import-CSV -Path '.\servers.txt')

If ($Servers.count -like 0){
Write-Host 'No Servers Listed' 
Exit
}
Else{
Write-Host "Total Server Count: " -NoNewline
Write-Host $Servers.count
}

ForEach ($i in $Servers) {

    $Server = $i
    Write-Host 'Working on Server' $Server -BackgroundColor Yellow -ForegroundColor Black
    Invoke-Command -ComputerName $Server -ScriptBlock { 
	wevtutil.exe sl Microsoft-Windows-CAPI2/Operational /e:false
    }
 }

PowerShell Scripts

Public GitHub Repo

Over the years I’ve written hundreds of PowerShell scripts to help make my job more efficient. Often the genesis of a script comes from something I’ve found online or a code tidbit posted on a forum.

I went through my old script repositories and uploaded a handful of my favorite scripts. I have many more I plan to share but I will need to clean them up prior to posting.

I’ve created a public GitHub Repo to store these scripts located here:
https://github.com/kevincallanan/PowerShellScripts