Office 365 Helps Small Business Do Big Work

BlackOps Consulting takes a deeper look at how Microsoft Office 365 helps small business owner Scott Naucler and his three employees work together across two states to maintain wind turbines across America’s wind corridor. Office 365 helps Turbine Test Services get the job done because it is always-up-to-date, letting Turbine Test Services work easily and flexibly, whether they’re on the ground in the office, or inspecting a wind turbine from 300 feet in the air. Contact us today to find out how we can help you do the same.

Broadclyst School–Communicating with Skype

In this new clip, BlackOps Consulting shows how Microsoft Office 365 with Skype for Business facilitates real-time communication and collaboration among student teams across geographies.

Skype’s video-conferencing and group-calling features support the Broadclyst School’s curriculum and enhance pupil engagement, but that’s not all. Using Skype, parents can attend and participate virtually in school meetings when they can’t be there in person–connecting them with their children’s learning. Let us help you reap the benefits of stronger partnerships too.

Office 365 Empowers a School to Take a Different Approach

In this clip, BlackOps Consulting takes a look at how technology is transforming learning and preparing students for the future at Broadclyst School. Microsoft Office 365 and devices form the foundation for a rich curriculum that teaches children important skills they’ll need as they enter the workforce and move through life. Let us show you how Office 365 can help your business take the same forward-looking approach to empower your future.

Get path and name of process by port

This needs to run as an administrator to get paths for all processes

This one liner gets the path of the process that is using local port 61119

([System.Diagnostics.Process]::GetProcessById((Get-NetTCPConnection -localport 61119).owningprocess)).path

This will get you a list of process identifiers (PID) sorted by local port

Get-NetTCPConnection | select localport, owningprocess | sort localport

Finally get all the ports in use by a process

Get-NetTCPConnection -owningprocess 61980 | select localport

Know a port and wonder what other ports the process is using?

Get-NetTCPConnection -owningprocess([System.Diagnostics.Process]::GetProcessById((Get-NetTCPConnection -localport 61119).owningprocess).id) | select localport

Find something on your HD

I was trying to search for something on a large file system, but between circular references in symbolic links creating errors with long paths etc it was harder than I thought it should be.

Here is some quick powershell to do a recursive, case insensative search while skipping symbolic links, but it does pick up hidden files and folders and ones with strange characters in the names.

function Recurse($path) {
# $path.tolower()

$files = Get-ChildItem -literal $path -file -force
foreach ($file in $files) {
if ($file.fullname.ToLower().contains($searchstring)) {
# write-host $file.fullname -foregroundcolor "magenta"
$FoundArray.add( $file.fullname )
$folders = Get-ChildItem -literal $path -directory -force
foreach ($folder in $folders) {
# $folder.fullname
if ($folder.fullname.ToLower().contains($searchstring)) {
# write-host $folder.fullname -foregroundcolor "magenta"
$FoundArray.add( $folder.fullname )
if ( (get-item -literal $folder.fullname -force).Attributes.ToString().Contains("ReparsePoint") -eq $false) {
Recurse $folder.fullname
$FoundArray = New-Object System.Collections.ArrayList
recurse "C:\Users"

Get logon and logoff times for user

I know there are some issues with this and it should depend on some lag in replication times. To be really accurate you should be auditing these events and running this on your DC’s but for a quick and dirty option to get the times for a users on a specific server you can run the following script.

I got the base of this somewhere and had to alter it to do what i needed. I lost the initial location  in the process.  If you find it let me know so I can provide credit

function Get-LogonHistory {
$logons = Get-EventLog Security -AsBaseObject -InstanceId 4624,4647 |
Where-Object { ($_.InstanceId -eq 4647) `
-or (($_.InstanceId -eq 4624) -and ($_.Message -match "Logon Type:\s+2")) `
-or (($_.InstanceId -eq 4624) -and ($_.Message -match "Logon Type:\s+10")) }
$poweroffs = Get-EventLog System -AsBaseObject -InstanceId 41
$events = $logons + $poweroffs | Sort-Object TimeGenerated

if ($events) {
foreach($event in $events) {
# Parse logon data from the Event.
if ($event.InstanceId -eq 4624) {
# A user logged on.
$action = 'logon'

$event.Message -match "Logon Type:\s+(\d+)" | Out-Null
$logonTypeNum = $matches[1]

# Determine logon type.
if ($logonTypeNum -eq 2) {
$logonType = 'console'
} elseif ($logonTypeNum -eq 10) {
$logonType = 'remote'
} else {
$logonType = 'other'

# Determine user.
if ($event.message -match "New Logon:\s*Security ID:\s*.*\s*Account Name:\s*(\w+)") {
$user = $matches[1]
} else {
$index = $event.index
Write-Warning "Unable to parse Security log Event. Malformed entry? Index: $index"

} elseif ($event.InstanceId -eq 4647) {
# A user logged off.
$action = 'logoff'
$logonType = $null

# Determine user.
if ($event.message -match "Subject:\s*Security ID:\s*.*\s*Account Name:\s*(\w+)") {
$user = $matches[1]
} else {
$index = $event.index
Write-Warning "Unable to parse Security log Event. Malformed entry? Index: $index"
} elseif ($event.InstanceId -eq 41) {
# The computer crashed.
$action = 'logoff'
$logonType = $null
$user = '*'

# As long as we managed to parse the Event, print output.
if ($user=$username) {
$timeStamp = Get-Date $event.TimeGenerated
$output = New-Object -Type PSCustomObject
Add-Member -MemberType NoteProperty -Name 'UserName' -Value $user -InputObject $output
Add-Member -MemberType NoteProperty -Name 'ComputerName' -Value $env:computername -InputObject $output
Add-Member -MemberType NoteProperty -Name 'Action' -Value $action -InputObject $output
Add-Member -MemberType NoteProperty -Name 'LogonType' -Value $event.ReplacementStrings[8] -InputObject $output
Add-Member -MemberType NoteProperty -Name 'TimeStamp' -Value $timeStamp -InputObject $output
Add-Member -MemberType NoteProperty -Name 'IP' -Value $event.ReplacementStrings[18] -InputObject $output
Write-Output $output
$fulloutput += $output
} else {
Write-Host "No recent logon/logoff events."

$fulloutput | Export-Csv -Path .\logonlog.csv -Encoding ascii -NoTypeInformation
$fulloutput= @()


Ransomware – Better get used to it


The reality is that Ransomware is here to stay. There is simply too much money involved for it to go away in the near term. Antivirus and technology companies do their best to keep up safe but new variants arrive almost everyday.

This means that you need to be extra vigilant. Be careful and don’t open documents from people you don’t know. Be very careful when downloading files when you are not sure who the author is. Keep your operating system, browser, and antivirus up to date on your computer and phone (yes your smartphone too). Don’t turn off UAC or run as an administrator just because it’s a little inconvenient from time to time. Most importantly have a good backup that has version control or one that you keep offline. The first thing Ransomware typically wants to do is delete all your backups.

If you are looking for an online backup I suggest the following

One of the latest attacks just asks you to turn on macros.  For reference a document will never look like this just because your macros are off.


If you are not sure don’t open it. If you are worried it might be legitimate ask professional first. 

It’s much easier to tell you that it’s OK to open than to recover if it wasn’t.