STOP THAT Print Spooler!

Scenario: With some of the latest exploits, stop that print spooler on your servers if its unneeded

Solution: PowerShell Scriptlets

If you are on the server, run the following:

Set-service Spooler -startuptype disabled
stop-service Spooler
get-service spooler


If you want to remotely run the commands, like the big bad admin that you are, run the following:

$s = "ExServer1","ExServer2"
$s | %{
    $n = $_
    "Disabling Spooler on $_"

    Invoke-Command -ComputerName $n -ScriptBlock { Set-service Spooler -startuptype disabled }
    Invoke-Command -ComputerName $n -ScriptBlock { stop-service Spooler}


PowerShell Scriptlets to check if NLA is enabled for Remote Desktop

Scenario: You want to see if  NLA (Network Level Authentication) is enabled on all of your servers for Remote Desktop.

The PowerShell code below is not a .ps1, although you can make a .ps1 out of it if you would like.  I like to teach working  “within” PowerShell, not just being a script monkey.

In order to run the code, you will need to open Powershell OR Powershell ISE with an account with elevated permissions to access your servers (Run-AS).  The purpose of working within PowerShell is so that you can  reuse/recycle the code below to do other things too.
Once PowerShell is opened, follow the steps:
  1. Build your $Servers Variable — Select a method to populate $Servers
  2. Run the Query to build the $Results table
  3. Display the $Results — Select a method



#1. Build your $Servers Variable — Select one of the methods below to populate $Servers

  $Servers = “ExSrv1″,”ExSrv2”   #Feel free to list the servers by name

        $Servers = Import-csv C:tempservers.csv | Select -expandproperty Name   #Create a CSV with a NAME column header

        $Servers =  get-adcomputer -searchbase “OU=Servers,DC=steve,DC=com” -properties Name -Filter *|  Select -ExpandProperty Name  #Pull a list of AD Computers via AD PowerShell

#2. Run the query to build the $Results variable 

$Results = @()
$Servers | %{
    #Collect NLA Data
    $name = $_
    $NLA = Get-WmiObject -class “Win32_TSGeneralSetting” -Namespace rootcimv2terminalservices -ComputerName $name -Filter “TerminalName=’RDP-tcp'” | Select -ExpandProperty UserAuthenticationRequired
    #Display in PowerShell Screen
    “$name : NLA_Enabled:$(If($NLA -eq 1){“Yes”}else{“No”})”

    #Add the data to the $results variable
    $ServerObj = New-Object PSObject
    $ServerObj | Add-Member NoteProperty -Name “Server” -value $name
    $ServerObj | Add-Member NoteProperty -Name “NLA_Enabled” -value $(If($NLA -eq 1){“Yes”}else{“No”})
    $Results += $ServerObj
    #Reset Variable
    $Name = $null
    $NLA = 0

#3. Display the $Results –  Select a method


    #-or Export the Results –
        $Results | Export-CSV C:tempresults.csv

    #-or Email the Results –
        $Header = @”
        TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
        TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
        TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black; text-align: center;}
        tr:nth-child(odd) { background-color:#F2F2F2;}
        tr:nth-child(even) { background-color:white;}
        $body =”$($results | ConvertTo-Html -Head $header)”
        $smtp = “”
        $to = “”
        $from = “”
        $subject = “Results of NLA”
        send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high

PowerShell: Find and copy text from multiple files

Scenario: You have to find a specific string of text in multiple files.  We are going to search for the term “steve” against all RPC Client Access logs for today.



$files = get-childitem -path “\ExSrv1c$Program FilesMicrosoftExchange ServerV15LoggingRPC Client Access”
$result = @()
$term = “steve”

#Perform the Search

$files | Where CreationTime -gt 9/6/2018| Sort CreationTime -Descending | %{
       $F = $_.fullname
       $result += select-string $f -pattern $term | %{$_.Line}

#Export Results

$result | out-file C:tempresults.txt

Disconnect Terminal Sessions via PowerShell on Remote ServersComputers

Scenario:  You want to disconnect all remote sessions on ServerComputers via PowerShell remotely.


#Disconnect Terminal Sessions via PowerShell################

#Gather the Servers in the $Servers Variable

$Servers = get-exchangeserver Exch* | Select -expandproperty Name

#Gather the Sessions
$TS = $Servers | %{
$computer = $_
quser /server:$computer 2>&1 | Select-Object -Skip 1 | ForEach-Object {
                $CurrentLine = $_.Trim() -Replace ‘s+’,’ ‘ -Split ‘s’
                $HashProps = @{
                    UserName = $CurrentLine[0]
                    ComputerName = $Computer

                # If session is disconnected different fields will be selected
                if ($CurrentLine[2] -eq ‘Disc’) {
                        $HashProps.SessionName = $null
                        $HashProps.Id = $CurrentLine[1]
                        $HashProps.State = $CurrentLine[2]
                        $HashProps.IdleTime = $CurrentLine[3]
                        $HashProps.LogonTime = $CurrentLine[4..6] -join ‘ ‘
                        $HashProps.LogonTime = $CurrentLine[4..($CurrentLine.GetUpperBound(0))] -join ‘ ‘
                } else {
                        $HashProps.SessionName = $CurrentLine[1]
                        $HashProps.Id = $CurrentLine[2]
                        $HashProps.State = $CurrentLine[3]
                        $HashProps.IdleTime = $CurrentLine[4]
                        $HashProps.LogonTime = $CurrentLine[5..($CurrentLine.GetUpperBound(0))] -join ‘ ‘

                New-Object -TypeName PSCustomObject -Property $HashProps | Select-Object -Property UserName,ComputerName,SessionName,Id,State,IdleTime,LogonTime,Error


#Disconnect the Sessions
$TS | %{
    $id = $
    $Name = $_.computerName
    $User = $_.Username
    rwinsta $ID /server:$name
    Write-Host “Session $Id for $User on $Name successfully disconnected”


Scheduled Task doesn’t allow powershell script to convert/save XLSX file to a CSV file

Scenario:  You have a PowerShell script running that will convert an .XLSX document into a .CSV Document.  When you run it natively in PowerShell, the script works fine and the document converts.  When you attempt to run it in Task Scheduler, it doesn’t convert and  create the new document.

Solution:  Create a Desktop folder in the following two directories and run the scheduled task again.:

  1. C:WindowsSysWOW64configsystemprofile

Remove a user/group permission on an AD Object via PowerShell

Scenario: You want to remove a users permission to an AD Object via PowerShell. This is the equivalent of opening Active Directory Users and Computers, finding your AD object (user, computer, ect), and removing the users permission from the Security Tab.

Scriptlets:  We are going to remove the user   domainjdoe from the AD Computer  test_computer.


#Set these variables
$DistinguishedName = "CN=test_computer,OU=Test,OU=Domain,DC=com"
$user = "domainjdoe"

#Collect the current ACL
$Acl = Get-Acl $DistinguishedName 

#Loop each access permission in the ACL
foreach ($access in $acl.Access) {
        if ($access.IdentityReference.Value -eq $user) {

#Set the ACL Back to the AD Object
set-acl $DistinguishedName  -AclObject $acl


Lets say you wanted to do this for every ADObject in a specific OU, run the following

#Set these Variables
$strOU = "CN=test,DC=Domain,DC=Com"
$Obj = get-adobject -searchbase $strOU -properties DistinguishedName,DisplayName -Filter * | Select DisplayName,DistinguishedName
$Obj = $obj | Sort DisplayName
$user = "domainjdoe"
$counter = 0

#Set AD as the location to find the user objects.
Set-Location ad:

#Loop it
$Obj | Select -first 5 | %{
#Increase counter
#Display Output
$counter / $($obj.count): Removing $User from $_.DisplayName - $_.DistinguishedName
#Get the current ACL for the AD Object
$DN = $_.DistinguishedName
$Acl = Get-Acl $DN 

#Loop each Access Level in the ACL And Remove for the User
foreach ($access in $acl.Access) {
       if ($access.IdentityReference.Value -eq $user) {$acl.RemoveAccessRule($access)} }

#Setting the Modified ACL back to the AD Object
set-acl $DN  -AclObject $acl

#reset variables
$ACL = $Null
$DN = $null



Script: Set NTFS Permissions on a Folder via PowerShell

Scenario: You want to set NTFS permissions on a folder via Powershell. You want the permissions to inherit down to SubFolders and files as well.


$folder = "\FileSvr1filestest12345"
$user = "DomainJdoe"

# Get the ACL for an existing folder
$existingAcl = Get-Acl -Path $folder

# Set the permissions that you want to apply to the folder
$permissions = $user, 'Read,Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow'

# Create a new FileSystemAccessRule object
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions

# Modify the existing ACL to include the new rule

# Apply the modified access rule to the folder
$existingAcl | Set-Acl -Path $folder


PowerShell: Search Multiple servers to see if a specific program is installed

Scenario:  You want to quickly search multiple remote servers to see if a specific program is installed.

Script: The following script checks to see if Wireshark is installed on any of our Exchange servers.

#Declare Server Variable
$Ex2013 = Get-exchangeserver ex* | Select -expandproperty Name

#Perform the Query against each server
$Ex2013 | %{"Checking WireShark on $_";Invoke-Command -Computer $_ -ScriptBlock {

#Declare App
$appToMatch = '*Wireshark*'

#Determine Uninstall Directory
if ([IntPtr]::Size -eq 4) {
        $regpath = 'HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall*'
    } else {
        $regpath = @(

#Get all Programs Installed
$1 = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }} | Select DisplayName, Publisher, InstallDate, DisplayVersion, UninstallString |Sort DisplayName

#Filter based on program
$result = $1 | where {$_.DisplayName -like $appToMatch}

#Display the result if found
If($result -ne $null){
    Write-Host "
    The following matching $appToMatch are Installed on $($env:computername) " -ForegroundColor Yellow
    Write-Host "$($result.displayName)
    " -ForegroundColor Yellow

Find the network driver version for multiple servers

Scenario:  You want to find the network driver information on multiple servers.  Run the following scriptlet below:

#Grab your collection variable

$servers = "ExServer1","ExServer2","ExServer3"

#For Cisco
$cisconetwork = $servers | %{get-WmiObject Win32_PnPSignedDriver -ComputerName $_ | ? Devicename -like "*Cisco VIC Ethernet*" | select devicename, driverversion, Driverdate, DriverProviderName, Manufacturer, PSCOMPUTERNAME}

#For HP
$HPnetwork = $HPservers | %{get-WmiObject Win32_PnPSignedDriver -ComputerName $_ | ? Devicename -like "*Ethernet*" | select devicename, driverversion, Driverdate, DriverProviderName, Manufacturer, PSCOMPUTERNAME}




Event ID 7000: The Cluster Virtual Miniport Driver service failed to start

Scenario:  When troubleshooting cluster related issues,  we found we could not start the cluster service. When we tried to start the service, we found the following entry in the System log:

Event ID: 7000 –  Source:  Service Control Manager

The Cluster Virtual Miniport Driver service failed to start due to the following error: The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.

Solution:  In our case, the Microsoft Failover Cluster Virtual Adapter was no longer present under Network Adapters (View –> Show Hidden Devices) in the Device Manager.  To reinstall it, perform the following:

  • Click on the server at the top of the device manager
  • Add legacy hardware
  • Install Hardware Manually
  • Select Network Adapters
  • Select Microsoft
  • Select Microsoft failover cluster virtual adapter