Category: Uncategorized

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
}

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

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;

NPS Smartcard/Certificate Authentication

HKLM\System\CurrentControlSet\Control\SecurityProviders\Schannel\

value: CertificateMappingMethods
Data Type: DWORD
Data: 0x1F

If you are facing issues on a newly deployed NPS or even an existing one, whilst using a certificate method to authenticate your users/devices, you might find that the above registry key will resolve the issue.

There has also been reports about the below updates causing issues with NPS on Server 2019 –

KB5013641

KB5013941

KB5014754

Azure Resource Inventory Export

If you do not have any CMDB actively scanning you Azure environment, things could get messy if you’ve had several rushed deployments into your Azure infrastructure. I recently got to know about a script by a colleague, that can export every single resource in your subscription and display it in a very organized excel sheet.

Example

I’ve uploaded the file here in TXT format, download it and rename to .ps1 ; You might need to have the below modules installed on your PC and one extension –

Azure AD
Azure CLI

Once those are installed, add the resource graph extension with this command -|

az extension add --name resource-graph

Now run the script, it will take you to the login page of Microsoft, use an admin account with permissions to read the tenant.

Some users reported having to run the script with the trigger -Online as the excel was not being generated. I have also verified this bug occurs and using the -Online resolves it. A second bug is that it will show 0 resources in the excel. This is something on your PC and you must re-install the powershell modules and extension.

Credits for this script go to https://github.com/microsoft/ARI

Check password expiry Office365

$cred = Get-Credential “[email protected]

Connect-MsolService -Credential $cred

$domain = Get-MsolDomain | where {$_.IsDefault -eq $true}

$PasswordPolicy = Get-MsolPasswordPolicy -DomainName $domain.Name

$Account = “[email protected]” # Change HERE !!

$UserPrincipal = Get-MsolUser -UserPrincipalName $Account

$UserPrincipal | fl PasswordNeverExpires

$PasswordExpirationDate = $UserPrincipal.LastPasswordChangeTimestamp.AddDays($PasswordPolicy.ValidityPeriod)

Write-host “Password will Expire on : $PasswordExpirationDate”

$StartDate = (GET-DATE)
$DaysLeft = NEW-TIMESPAN -Start $StartDate -End $PasswordExpirationDate
$DaysLeft = [math]::Floor($DaysLeft.TotalDays)

Write-host “Password will Expire in # Days : $DaysLeft”

$UserPrincipal | select DisplayName, LastPasswordChangeTimeStamp,@{Name=”PasswordAge”;Expression={((Get-Date).ToUniversalTime())-$_.LastPasswordChangeTimeStamp}} | sort-object PasswordAge -desc

Replace registry keys

I was recently tasked with migrating a software which had all of it’s configuration stored in the registry. The only way to update it “officially” was by uninstalling and reinstalling the whole suite, since this would take too long for 30 machines, I decided to script it to quicken things up.

The way this works is by using the PowerShell functionality to search the registry –

foreach ($a in Get-ChildItem -Path ‘HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer’ -Recurse) {
  $a.Property | Where-Object {
    $a.GetValue($_) -Like “*value123*”
  } | ForEach-Object {
    $CurrentValue = $a.GetValue($_)
    $ReplacedValue = $CurrentValue.Replace(“value123", “value1234”)
    Write-Output “Changing value of $a\$_ from ‘$CurrentValue’ to ‘$ReplacedValue’”
    Set-ItemProperty -Path Registry::$a -Name $_ -Value $ReplacedValue
  }
}

The script explained –

i) It is searching in the Installer path with -Recurse, this means all the folder underneath it also.

ii) GetValue – This is going to first build the search index with any registry key containing value123. It will find values such as https://value123.domain.com or just value123 alone.

iii) ReplacedValue – We are giving it the value123 to identify and then replace it with value1234. It will not replace the whole string https://value123.domain.com, it will just replace it to https://value1234.domain.com

I hope this comes in handy for anyone searching to do something similar!