Category Archives: Windows

Automating DHCP Scope Option Removal with PowerShell

If you’re managing a large network with multiple DHCP servers, you know how tedious it can be to manually remove DHCP scope options. Fortunately, PowerShell can help automate the process and make network management much more efficient. In this post, we’ll walk you through a PowerShell function that can remove DHCP scope options with just a few lines of code.

The “Remove-DhcpScopeOptions” Function

The “Remove-DhcpScopeOptions” function takes two parameters: the name of the DHCP server and a switch for the “-WhatIf” parameter. The “-WhatIf” parameter allows you to see what the function would do without actually making any changes.

function Remove-DhcpScopeOptions {
  param (

  # Get all DHCP scopes on the server
  $scopes = Get-DhcpServerv4Scope -ComputerName $ComputerName

  # Get all options for the DHCP server
  $serverOptions = Get-DhcpServerv4OptionValue -ComputerName $ComputerName

  # For each scope, get the options and compare them to the server-level options
  foreach ($scope in $scopes) {
    $scopeOptions = Get-DhcpServerv4OptionValue -ScopeId $scope.ScopeId -ComputerName $ComputerName

    # For each option in the scope, check if it exists at the server level with the same value
    foreach ($option in $scopeOptions) {
      $serverOption = $serverOptions | Where-Object { $_.OptionId -eq $option.OptionId }
      if ($serverOption -ne $null -and $serverOption.Value -eq $option.Value) {
        # If the option exists at the server level with the same value, remove it from the scope
        if ($WhatIf) {
          Write-Host "What if: Removing option $($option.OptionId) from scope $($scope.ScopeId) on DHCP server $ComputerName."
        } else {
          Remove-DhcpServerv4OptionValue -ScopeId $scope.ScopeId -OptionId $option.OptionId -ComputerName $ComputerName -Confirm:$false

  # Replicate the scopes to all DHCP servers in the enterprise
  if (!$WhatIf) {
    Invoke-DhcpServerv4ReplicateScopes -ComputerName $ComputerName

How it Works

The “Remove-DhcpScopeOptions” function works by first getting all DHCP scopes on the server using the “Get-DhcpServerv4Scope” cmdlet. It stores the results in the $scopes variable. It then gets all options for the DHCP server using the “Get-DhcpServerv4OptionValue” cmdlet and stores the results in the $serverOptions variable.

For each DHCP scope, the function gets the options using the “Get-DhcpServerv4OptionValue” cmdlet and stores the results in the $scopeOptions variable. It then compares the options in each scope to the server-level options and removes any options that exist at the server level with the same value. Finally, the function replicates the scopes to all DHCP servers in the enterprise.


Remove-DhcpScopeOptions -ComputerName "dhcpserver01" -WhatIf

How to Convert DHCP Leases to Reservations Using PowerShell

As a system administrator, you might have to manage a Windows DHCP server and convert DHCP leases to reservations at some point. However, this can be a tedious task if you have many leases to convert. Fortunately, PowerShell can automate this process, making it much easier and faster. This post provides a step-by-step guide on how to convert DHCP leases to reservations using PowerShell.

Step 1: Open PowerShell

The first step is to open PowerShell with administrative privileges on the Windows DHCP server. You can do this by right-clicking on the PowerShell icon and selecting “Run as administrator.”

Step 2: Define the Functions

Copy and paste the following functions into PowerShell:

function Convert-DhcpLeasesToReservations
    param (


    $leases = Get-DhcpServerv4Lease -ComputerName localhost -ScopeId $ScopeId

    foreach ($lease in $leases)
        $reservation = New-DhcpServerv4Reservation -IPAddress $lease.IPAddress -ClientId $lease.ClientId -ScopeId $lease.ScopeId -Description "Converted from DHCP lease"
        if (!$WhatIf) {
            Add-DhcpServerv4Reservation -ComputerName localhost -Reservation $reservation

    Write-Host "All DHCP leases within scope $ScopeId have been converted to reservations"

function Convert-DhcpLeasesToReservationsByFilter
    param (


    $scopes = Get-DhcpServerv4Scope -ComputerName localhost | Where-Object { $_.Name -like $Filter }

    foreach ($scope in $scopes)
        Convert-DhcpLeasesToReservations -ScopeId $scope.ScopeId -WhatIf:$WhatIf

Step 3: Run the Functions

To use these functions, you need to run Convert-DhcpLeasesToReservationsByFilter and specify the filter to select the DHCP scopes you want to convert DHCP leases to reservations. For instance, you can run:

Convert-DhcpLeasesToReservationsByFilter -Filter "192.168.*"

This command will convert all DHCP leases within the scopes that match the filter “192.168.*” to reservations.

You can also use the -WhatIf parameter to simulate the execution of the function without making any changes. This helps you to see what the function will do before actually running it. For instance, you can run:

Convert-DhcpLeasesToReservationsByFilter -Filter "192.168.*" -WhatIf

This command will display the details of the actions the function will perform, but it will not execute them.


Using PowerShell to convert DHCP leases to reservations can save you time and effort. The functions provided in this blog post simplify the process, allowing you to automate the conversion of DHCP leases to reservations in a few simple steps. By following the steps outlined above, you can easily and quickly convert DHCP leases to reservations on your Windows DHCP server.

PowerShell Script to Audit User Permissions and Identify Users with High Permission

Managing permissions and ensuring proper access control is critical to maintain the security of your organization’s resources. In this blog post, we introduce a PowerShell script that can audit user permissions on file shares and directories, calculate a permission score for each user, and help you identify users with the most permissive rights.


The PowerShell script consists of the following main parts:

  1. A hashtable that defines important rights and their corresponding scores.
  2. A list of excluded users and shares that should not be considered in the audit process.
  3. A function called Get-ImportantDirectoryACLs that retrieves the Access Control List (ACL) for a given directory, filters out excluded users, and calculates a permission score for each user.
  4. A main script block that connects to a target server, retrieves the file shares and directories, and invokes the Get-ImportantDirectoryACLs function.

The script calculates the permission scores for each user based on the importance of their rights. In this example, we assign a score of 100 to the ‘TakeOwnership’ right, 90 to the ‘FullControl’ right, and lower scores to other important rights. The resulting CSV file will display the users with the highest scores at the top, making it easy to identify users with the most permissive rights.

$ImportantRights = @{
    'FullControl' = 100
    'Modify' = 80
    'ReadAndExecute' = 60
    'Write' = 40
    'CreateFiles' = 20
    'CreateDirectories' = 20
    'Delete' = 10
    'TakeOwnership' = 100
$ExcludedShares = @("IPC$", "ADMIN$")

function Get-ImportantDirectoryACLs {
        [Parameter(Mandatory, ValueFromPipeline)]

    process {
        $ACL = Get-Acl $DirectoryPath
        Foreach ($AccessRule in $ACL.Access) {
            If (!$AccessRule.IsInherited) {
                $User = $($AccessRule.IdentityReference)
                if ($User -notin $ExcludedUsers) {
                    $TotalScore = 0
                    $Rights = @($AccessRule.FileSystemRights -split ",") | Where-Object { $ImportantRights.ContainsKey($_) }
                    Foreach ($Right in $Rights) {
                        $TotalScore += $ImportantRights[$Right]
                    if ($TotalScore -gt 0) {
                            DirectoryPath = $DirectoryPath
                            IdentityReference = $AccessRule.IdentityReference
                            AccessControlType = $AccessRule.AccessControlType
                            FileSystemRights = $AccessRule.FileSystemRights
                            Score = $TotalScore

$Server = "ServerName"

$Cim = New-CimSession -ComputerName $Server
if ($Cim) {
    $Shares = Get-SmbShare -CimSession $Cim | Where-Object { $ExcludedShares -notcontains $_.Name } | ForEach-Object {
    $Directories = $Shares | ForEach-Object { Get-ChildItem $_ -Directory } | Select-Object -ExpandProperty FullName

    $ShareRights = $Shares | Get-ImportantDirectoryACLs -ExcludedUsers $ExcludedUsers
    $DirectoryRights = $Directories | Get-ImportantDirectoryACLs -ExcludedUsers $ExcludedUsers

    $Results = @($ShareRights) + @($DirectoryRights)

    # Sort results by Score in descending order
    $SortedResults = $Results | Sort-Object -Property Score -Descending

    # Export the sorted results to a CSV file
    $SortedResults | Export-Csv -Path "$Server.csv" -NoTypeInformation

How to Use It

  1. Copy the script to your PowerShell environment and save it as a .ps1 file.
  2. Replace “ServerName” in the $Server variable with the name of the server you want to audit.
  3. Run the script. It will generate a CSV file named ServerName.csv that contains the audit results.
  4. Review the CSV file to identify users with the highest permission scores.


Using PowerShell to audit user permissions and identify users with the most permissive rights is an efficient and effective way to manage access control in your organization. By assigning permission scores to important rights, you can quickly identify the users that may require further investigation. Remember to adapt the script to your environment and adjust the scores as needed to suit your organization’s security requirements.

Use PowerShell to export AD User accounts to a CSV with their properties flattened

This queries for specific users (modify this to match your need)

Taking a list of users Flatten-Object will go through their properties and join multivalued attributes with a semi-colon so that you can export it in a useful way to CSV.

# Change this to and LDAP filter that fits your needs
$admins = Get-ADUser -filter "employeeType -eq 'Administrator Acct'" -Properties *

# take multivalued properties and join them with ;
function Flatten-Object {
    process {
        $flattened_object = [pscustomobject]@{}

        foreach ($field in $object | get-member) {
            if ($field.MemberType -eq “Property” -and $field.Name -notlike “__*”) {
                $flattened_object | Add-Member -NotePropertyName $field.Name -NotePropertyValue $($object.$($field.Name) -join ";")

$admins | Flatten-Object | Export-Csv -Path "user.csv" -NoTypeInformation

Finding who is using a Windows Share in PowerShell

You can find the users and computers connected to a share pretty easily in powershell.

$share_name = "*"
$shares = Get-WmiObject Win32_ServerConnection 
$shares = $shares | Where-Object {$_.ShareName -like $share_name} | `
                    Select-Object ShareName, UserName, `
$shares | Group-Object -Property ShareName | ` 
          Select Name, `
                 @{n="Computers";e={$_.Group | Select -ExpandProperty Computer | Get-Unique}},`
                 @{n="Users";e={$_.Group | Select -ExpandProperty UserName | Get-Unique}},`

$share_name is a filter to narrow down the shares you are checking. Other than that it gets all the share connections then groups them by share. It shows unique users and computers connected to each share.

Find GPOs with LoopBack Enabled

You can get a list of all Group Policy Objects (GPOs) with loopback very easily:

Get-GPO -All | Where { $($_ | Get-GPRegistryValue -Key "HKLM\Software\Policies\Microsoft\Windows\System" -Value UserPolicyMode -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select -ExpandProperty Value) -eq 1}

This will query all GPOs and then conditionally return them if they have the value for UserPolicyMode set.

You could replace the “Get-GPO -all” with a filtered version if you were only interested in certain GPOs

A little longer version if you want to abstract it or modify it earlier:

Function GetLoopBack {
    $gpo | Get-GPRegistryValue -Key "HKLM\Software\Policies\Microsoft\Windows\System" -Value UserPolicyMode `
                               -WarningAction SilentlyContinue | Select -ExpandProperty Value

$GPOs = $GPOs | SELECT -Property *, @{Name='LoopBack';Expression={GetLoopBack2 $_}}


Finding Orphaned GPO Folders with PowerShell

During years and years of working in AD occasionally the sysvol folders gets out of sync with the actual GPOs. The following script will return all folders in sysvol\policies that no long have a corresponding GPO. **Please be sure to backup folders before taking any action based on this**

#Initial Source:

function Get-OrphanedGPOs {

    param (
    begin {
        $orphaned = @()
    process {
        Write-Verbose "Domain: $Domain"
        # Get GPOs and convert guid into same format as folders
        $gpos = Get-GPO -All -Domain $domain | Select @{ n='GUID'; e = {'{' + $_.Id.ToString().ToUpper() + '}'}}| Select -ExpandProperty GUID
        Write-Verbose "GPOs: $($gpos | Measure-Object | Select -ExpandProperty Count)"
        # Get GPOs policy folder
        $polPath = "\\$domain\SYSVOL\$domain\Policies\"
        Write-Verbose "Policy Path: $polPath"

        # Get all folders in the policy path
        $folders = Get-ChildItem $polPath -Exclude 'PolicyDefinitions'
        Write-Verbose "Folders: $($folders | Measure-Object | SElect -ExpandProperty Count)"

        #compare and return only the Folders that exist without a GPO
        $gpoArray = $gpos.GUID
        ForEach ($folder in $folders) {
            if (-not $gpos.contains($folder.Name)) {
                $orphaned += $folder
        Write-Verbose "Orphaned: $($orphaned | Measure-Object | SElect -ExpandProperty Count)"
        return $orphaned
    end {


Running anything as a Service

You can use NSSM to run anything you want as a service very quickly.  In my case, I was looking to run AcuRite even when not logged in or while locked so that my weather station is always updating the cloud.

  1. Download NSSM and extract somewhere on your C Drive (i just put it in c:\nssm\
  2. Open a command prompt and change directories to where NSSM was extracted and run the following command (replace AcuRite with the name of the service you want to create)
  3. nssm.exe install AcuRite
  4. In the path field select the exe you would normally be running
  5. On the details tab set a description so you remember in the future why you created this.
  6. Click “Install Service”
  7. Start the service from the Services control panel

Easy and quick you now have AcuRite (or whatever you want) running as a service.