SQL Server License Retrieval

# Confirmed working for Windows versions of SQL Server 2016-2019
function GetSqlServerProductKey($InstanceName="MSSQL13.MSSQLSERVER") {
    $localmachine = [Microsoft.Win32.RegistryHive]::LocalMachine
    $defaultview = [Microsoft.Win32.RegistryView]::Default
    $reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey($localmachine, $defaultview)
    $key = "SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceName\Setup"
    $encodedData = $reg.OpenSubKey($key).GetValue("DigitalProductID")
    $reg.Close()
 
    try {
        $binArray = ($encodedData)[0..66]
        $productKey = $null
 
        $charsArray = "B", "C", "D", "F", "G", "H", "J", "K", "M", "P", "Q", "R", "T", "V", "W", "X", "Y", "2", "3", "4", "6", "7", "8", "9"
 
        $isNKey = ([math]::truncate($binArray[14] / 0x6) -band 0x1) -ne 0;
        if ($isNKey) {
        $binArray[14] = $binArray[14] -band 0xF7
        }
 
        $last = 0
 
        for ($i = 24; $i -ge 0; $i--) {
            $k = 0
            for ($j = 14; $j -ge 0; $j--) {
                $k = $k * 256 -bxor $binArray[$j]
                $binArray[$j] = [math]::truncate($k / 24)
                $k = $k % 24
            }
            $productKey = $charsArray[$k] + $productKey
            $last = $k
        }
 
        if ($isNKey) {
            $part1 = $productKey.Substring(1, $last)
            $part2 = $productKey.Substring(1, $productKey.Length-1)
            if ($last -eq 0) {
                $productKey = "N" + $part2
            }
            else {
                $productKey = $part2.Insert($part2.IndexOf($part1) + $part1.Length, "N")
            }
        }
 
        $productKey = $productKey.Insert(20, "-").Insert(15, "-").Insert(10, "-").Insert(5, "-")
    } 
    catch {
        $productkey = "Cannot decode product key."
    }
 
    $productKey
}

Change the instance name to what is displayed in the registry

Then run the below command in powershell, after execting the function creation script above ofcourse.

GetSqlServerProductKey($InstanceName="MSSQL13.MSSQLSERVER")

Adapt the instance name to what is required.

Exchange autodiscover URL

After certain updates, it seems autodiscover url can get removed from the existing config, the below will re-configure it. Commands are to be used in the Exchange Management Shell

Set-ClientAccessService -Identity "HOSTNAME" -AutoDiscoverServiceInternalUri https://mail.XX.com/Autodiscover/Autodiscover.xml

This will list the current autodiscover url

Get-clientAccessServer | fl Name,AutoDiscoverServiceInternalUri

This will list all exchange services url’s

$virtdirs = "ECP,OWA,OAB,WebServices,Activesync,autodiscover,mapi"
$array = $virtdirs.split(",")
foreach ($i in $array) {
$j = "Get-"+$i+"VirtualDirectory"+" | fl name,server,internalurl,externalurl"
iex $j
}

Reset password via Azure CloudShell

Connect-AzureAD

$Password = "em2Y2DA7KiZx2uo5QSAk*" | ConvertTo-SecureString -AsPlainText -Force

Set-AzureADUserPassword -ObjectID "7de0a4c8-8bfb-43bc-9d6e-e4b6131f3e66" -Password $password

This reset’s the account password to the specified one above, ignores already used passwords and extends expired account password lifecycle.

List user logon sessions on all servers in AD domain

# Define the OU path where your servers are located
$ouPath = "OU=servers,DC=domain,DC=local"  # Replace with your OU path

# Get a list of servers in the specified OU
$servers = Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} -SearchBase $ouPath | Select-Object -ExpandProperty Name

# Loop through each server and query logged-on users
foreach ($server in $servers) {
    try {
        # Use WMI to query logged-on user information
        $loggedOnUsers = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $server | Select-Object -ExpandProperty UserName

        if ($loggedOnUsers) {
            Write-Host "Logged-on users on $server"
            $loggedOnUsers | ForEach-Object {
                Write-Host "  $_"
            }
        } else {
            Write-Host "No users logged on to $server"
        }
    } catch {
        Write-Host "Failed to query $server"
    }
}

If you want to search by specific names, you can adjust the filter to this –

Get-ADComputer -Filter {Name -like "AZ-EUW-*"} -SearchBase $ouPath

Remotely change all DNS IP’s on Windows Servers in AD

# Define the new DNS server IP addresses
$dnsServers = "8.8.8.8", "1.1.1.1", "8.8.4.4"

# Define the OU where you want to change DNS servers
$OU = "OU=server,DC=domain,DC=local"  # Replace with your actual OU path

# Create an array to store results
$results = @()

# Get all computer objects in the specified OU
$computers = Get-ADComputer -Filter {Name -like "AZ-EIW-DC01*"} -SearchBase $OU

# Loop through each computer object
foreach ($computer in $computers) {
    $computerName = $computer.Name
    $computerDN = $computer.DistinguishedName

    try {
        # Set the DNS server IP addresses on the remote computer
        Invoke-Command -ComputerName $computerName -ScriptBlock {
            $networkAdapter = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
            Set-DnsClientServerAddress -InterfaceAlias $networkAdapter.Name -ServerAddresses $using:dnsServers -ErrorAction Stop
        }

        # Record the success in the results array
        $results += [PSCustomObject]@{
            ComputerName = $computerName
            Status = "Success"
        }
    }
    catch {
        # If an error occurs, record the failure in the results array
        $results += [PSCustomObject]@{
            ComputerName = $computerName
            Status = "Error: $_"
        }
    }
}

# Export the results to a CSV file
$results | Export-Csv -Path "C:\Temp\DNSChangeResults.csv" -NoTypeInformation

# Display the results on the console
$results

Report of DNS settings on all Windows Servers via powershell

$AllServers=Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*" -and Enabled -eq 'True'}
$Servers = ForEach ($Server in $AllServers){

$Result=Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'" -Property DNSServerSearchOrder -ComputerName $Server.Name

New-Object -TypeName PSObject -Property @{
ComputerName = $Server.Name -join ','
DNSServerSearchOrder = $Result.DNSServerSearchOrder -join ','

} | Select-Object ComputerName,DNSServerSearchOrder | Export-Csv -Path C:\Temp\ServerDNSSettings.csv -NoTypeInformation -Append
}

Run this from a domain controller and it will report the DNS servers set on the NIC card.

Find memory in use by sql databases

Run this query in SSMS to show how much memory the DB’s are currently using.

DECLARE @total_buffer INT;

SELECT @total_buffer = cntr_value
FROM sys.dm_os_performance_counters 
WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
AND counter_name = 'Database Pages';

;WITH src AS
(
SELECT 
database_id, db_buffer_pages = COUNT_BIG(*)
FROM sys.dm_os_buffer_descriptors
--WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
)
SELECT
[db_name] = CASE [database_id] WHEN 32767 
THEN 'Resource DB' 
ELSE DB_NAME([database_id]) END,
db_buffer_pages,
db_buffer_MB = db_buffer_pages / 128,
db_buffer_percent = CONVERT(DECIMAL(6,3), 
db_buffer_pages * 100.0 / @total_buffer)
FROM src
ORDER BY db_buffer_MB DESC;

Search group policies for specific setting

Sometimes you need to search in a domain environment for a specific setting in GPO’s. This script will search through all the GPO’s in the domain and list the results at the end!

# Get the string you want to search for
$string = Read-Host -Prompt "What string do you want to search for?"

# Set the domain to search for GPOs
$DomainName = $env:USERDNSDOMAIN

# Find all GPO's in the current domain of logged on user
write-host "Finding all the GPO's in $DomainName"
Import-Module grouppolicy
$allGposInDomain = Get-GPO -All -Domain $DomainName
[string[]] $MatchedGPOList = @()

# Look through each GPO's XML for the string
Write-Host "Starting search...."
foreach ($gpo in $allGposInDomain) {
    $report = Get-GPOReport -Guid $gpo.Id -ReportType Xml
    if ($report -match $string) {
        write-host "********** Match found in: $($gpo.DisplayName) **********" -foregroundcolor "Green"
        $MatchedGPOList += "$($gpo.DisplayName)";
    } # end if
    else {
        Write-Host "No match in: $($gpo.DisplayName)"
    } # end else
} # end foreach
write-host "`r`n"
write-host "Results: **************" -foregroundcolor "Yellow"
foreach ($match in $MatchedGPOList) {
    write-host "Match found in: $($match)" -foregroundcolor "Green"
}