PowerShell

PowerShell Script: Quickly Convert SIDs to Usernames

Posted on Updated on

Have you ever looked at a security log or a orphaned folder permission and seen a string like S-1-5-21-3623811015-3361044348-30300820-1013? Those are SIDs (Security Identifiers). While they are great for the Windows OS, they are nearly impossible for humans to read.

If you have a list of these SIDs from an audit or a log file, you don’t have to look them up one by one. This PowerShell script will take a bulk list of SIDs and “translate” them into readable Usernames (UIDs).


The PowerShell Script

Save this script as SIDtoUID.ps1. It uses the .NET SecurityIdentifier class to perform the translation locally or against your Active Directory domain.

PowerShell
# Create or clear the output file
Out-File UID.txt
# Loop through each SID in the source text file
foreach ($SID in (Get-Content SID.txt))
{
# Create a SID object
$objSID = New-Object System.Security.Principal.SecurityIdentifier ($SID)
Try
{
# Attempt to translate the SID to an NT Account name
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
# Append the Username to the output file
$objUser.Value >> UID.txt
Write-Host "Translated: $SID -> $($objUser.Value)" -ForegroundColor Green
}
Catch
{
# If translation fails (e.g., deleted account), keep the original SID
$SID >> UID.txt
Write-Warning "Failed to translate: $SID"
}
}

How to Use It

  1. Create your input: Create a file named SID.txt in the same folder as the script. Paste your SIDs there, one per line.
  2. Run the script: Open PowerShell and execute .\SIDtoUID.ps1.
  3. Check your results: A new file named UID.txt will appear, containing the translated usernames in the same order as your original list.

Why do SIDs sometimes fail to translate?

In the Catch block of the script, we tell PowerShell to just output the original SID if it can’t find a match. This usually happens for two reasons:

  • Deleted Accounts: The user or group no longer exists in Active Directory, leaving behind an “orphaned” SID.
  • Connectivity: Your machine cannot reach the Domain Controller to perform the lookup.

#PowerShell #ActiveDirectory #SysAdmin #ITPro #CyberSecurity #WindowsServer #Automation #LazyAdmin #TechTips #ITAudit

PowerShell Script: Export User Group Memberships to CSV

Posted on Updated on

Auditing which users belong to which groups is one of the most frequent requests for a System Administrator. Whether it’s for a security audit, a helpdesk ticket, or a “copy permissions” request, digging through the Member Of tab in Active Directory is slow and prone to error.

This PowerShell script simplifies the process by generating a clean, object-based list of memberships that you can easily export to CSV, HTML, or plain text.


The PowerShell Script

Save the following code as Get-UserGroupMembership.ps1. It is designed to handle single users, lists from text files, or entire Organizational Units (OUs) via the pipeline.

PowerShell
Param (
[Parameter(Mandatory=$true,ValueFromPipeLine=$true)]
[Alias("ID","Users","Name")]
[string[]]$User
)
Begin {
Try { Import-Module ActiveDirectory -ErrorAction Stop }
Catch { Write-Host "Unable to load Active Directory module. Is RSAT installed?"; Break }
}
Process {
ForEach ($U in $User) {
Try {
$UN = Get-ADUser $U -Properties MemberOf
$Groups = ForEach ($Group in ($UN.MemberOf)) {
(Get-ADGroup $Group).Name
}
# Sort groups alphabetically for a cleaner report
$Groups = $Groups | Sort
ForEach ($Group in $Groups) {
New-Object PSObject -Property @[ordered]@{
User = $UN.Name
Group = $Group
}
}
}
Catch {
Write-Warning "Could not find user: $U"
}
}
}

How to Use the Script

1. Single User Lookup

To quickly see the groups for one specific user:

PowerShell

.\Get-UserGroupMembership.ps1 -User "John.Doe"

2. Bulk Export from a Text File

If you have a list of usernames in users.txt, use this command to generate a full CSV report:

PowerShell

Get-Content C:\Temp\users.txt | .\Get-UserGroupMembership.ps1 | Export-CSV C:\Temp\UserMemberships.csv -NoTypeInformation

3. Audit an Entire OU

To see the memberships for every user within a specific department or location:

PowerShell

Get-ADUser -Filter * -SearchBase "OU=Users,DC=yourdomain,DC=local" | .\Get-UserGroupMembership.ps1 | Export-CSV C:\audit_output.csv -NoTypeInformation

Why This Method Beats the GUI

  • Alphabetical Sorting: Groups are presented A-Z, making it much easier to read than the random order in ADUC.
  • Pipeline Support: Because it outputs a PSObject, you can pipe it directly into ConvertTo-HTML for a report or Out-GridView for an interactive window.
  • Automation Ready: You can schedule this script to run weekly to maintain a “snapshot” of your environment’s security posture.

#PowerShell #ActiveDirectory #SysAdmin #WindowsServer #ITAdmin #CyberSecurity #Automation #LazyAdmin #TechTips #ITAudit

Automating Active Directory: Export All AD Groups and Members to CSV

Posted on Updated on

Auditing Active Directory groups is a fundamental part of identity management. Whether you are performing a quarterly security review or preparing for a domain migration, knowing exactly who is in which group—and what the scope of those groups is—is essential.

This PowerShell script does more than just list group names; it iterates through every group in your domain, identifies the members (skipping disabled users to keep your data clean), and exports everything into a dated CSV file.


The PowerShell Script

Save this script as ADGroupsExport.ps1 in C:\Temp\ExportADgroups. Ensure you are running this from a machine with the RSAT (Remote Server Administration Tools) installed and logged in with a domain account that has read permissions.

PowerShell
# Get year and month for the filename
$DateTime = Get-Date -f "yyyy-MM"
# Set CSV file destination
$CSVFile = "C:\Temp\ExportADgroups\AD_Groups_"+$DateTime+".csv"
if (!(Test-Path "C:\Temp\ExportADgroups")) { New-Item -ItemType Directory -Path "C:\Temp\ExportADgroups" }
$CSVOutput = @()
# Fetch all AD groups
$ADGroups = Get-ADGroup -Filter *
$i = 0
$tot = $ADGroups.count
foreach ($ADGroup in $ADGroups) {
$i++
$status = "{0:N0}" -f ($i / $tot * 100)
Write-Progress -Activity "Exporting AD Groups" -status "Processing Group $i of $tot : $status% Completed" -PercentComplete ($i / $tot * 100)
$Members = ""
# Fetch members and filter for enabled objects
$MembersArr = Get-ADGroup $ADGroup.DistinguishedName -Properties Member | Select-Object -ExpandProperty Member
if ($MembersArr) {
foreach ($Member in $MembersArr) {
$ADObj = Get-ADObject -Filter "DistinguishedName -eq '$Member'" -Properties Enabled
# Skip disabled users to keep the report relevant
if ($ADObj.ObjectClass -eq "user" -and $ADObj.Enabled -eq $false) {
continue
}
$Members = $Members + "," + $ADObj.Name
}
if ($Members) {
$Members = $Members.Substring(1)
}
}
# Create ordered hash table for clean CSV columns
$HashTab = [ordered]@{
"Name" = $ADGroup.Name
"Category" = $ADGroup.GroupCategory
"Scope" = $ADGroup.GroupScope
"Members" = $Members
}
$CSVOutput += New-Object PSObject -Property $HashTab
}
# Sort by name and export
$CSVOutput | Sort-Object Name | Export-Csv $CSVFile -NoTypeInformation
Write-Host "Export Complete: $CSVFile" -ForegroundColor Green

Key Features of this Script

  • Progress Bar: Since large domains can take a long time to process, the Write-Progress bar gives you a real-time percentage of the completion.
  • Clean Membership Lists: The script concatenates all members into a single “Members” column, separated by commas, making it easy to read in Excel.
  • Disabled User Filtering: It intelligently checks the Enabled status of user objects. If a user is disabled, they are omitted from the report to focus on active security risks.
  • Scope & Category: Clearly identifies if a group is Security vs. Distribution and Global vs. Universal.

#ActiveDirectory #PowerShell #SysAdmin #ITAutomation #WindowsServer #IdentityManagement #LazyAdmin #TechTips #Reporting #CyberSecurity

How to Export Folder and Share Permissions to CSV via PowerShell

Posted on Updated on

Auditing file share permissions is a critical task for security and compliance. While the Windows GUI allows you to view permissions one folder at a time, it is impossible to get a “big picture” view without automation.

By using the Get-Acl (Access Control List) cmdlet in PowerShell, you can recursively scan a directory and export every user and group permission to a clean CSV file for review in Excel.


The PowerShell Script

Save the following code as ExportFolderPermissions.ps1. Before running it, ensure you update the $FolderPath and the output path for the CSV file.

PowerShell
# Define the source path (Local folder or UNC Share)
$FolderPath = dir -Directory -Path "\\ServerName\SharePath" -Recurse -Force
$Report = @()
Foreach ($Folder in $FolderPath) {
# Fetch the Access Control List for the current folder
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access) {
# Create an ordered object for each permission entry
$Properties = [ordered]@{
'FolderName' = $Folder.FullName
'AD Group or User' = $Access.IdentityReference
'Permissions' = $Access.FileSystemRights
'Inherited' = $Access.IsInherited
}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
# Export the final report to CSV
$Report | Export-Csv -Path "C:\Temp\FolderPermissions.csv" -NoTypeInformation

How the Script Works

  1. dir -Recurse: This command crawls through every subfolder within your target directory. The -Directory switch ensures we only look at folders, not individual files (which would make the report massive).
  2. Get-Acl: This retrieves the security descriptor for the folder, including who has access and what specific rights they have (Read, Write, Full Control, etc.).
  3. PSObject: We bundle the folder name, user identity, and rights into a custom object so that Export-Csv can easily format them into columns.
  4. IdentityReference: This shows you the exact AD Group or User name assigned to that folder.

💡 Lazy Admin Tips

  • Run as Admin: You must run PowerShell as an Administrator and have “Read Permissions” rights on the target folders, or the script will return “Access Denied” errors.
  • Performance: Scanning thousands of subfolders over a slow network link can take time. If you have a massive file server, run the script locally on the server itself rather than over a mapped drive.
  • Filter Results: Once you open the CSV in Excel, use Filters to quickly find “Everyone” or “Anonymous” permissions, or to see which folders have inheritance disabled.

#PowerShell #SysAdmin #ActiveDirectory #SecurityAudit #WindowsServer #ITPro #Coding #LazyAdmin #CyberSecurity #TechTips

Stop Hunting for Web Servers: How to Auto-Discover Every IIS Instance in Your Domain | Lazy Admin Blog

Posted on Updated on

IIS Discovery

Have you ever been asked for a list of every active web server in your environment, only to realize your documentation is six months out of date? You could check your DNS records manually, or you could let PowerShell do the detective work for you.

This script scans your Active Directory for Windows Servers, checks if the World Wide Web Publishing Service (W3SVC) is actually running, and then pulls a deep-profile of the hardware, OS, and network configuration for every active hit.

The Setup

  1. Create the workspace: Create a folder at C:\Temp\ServersRunningIIS.
  2. Prepare the list: The script will automatically generate a list of all Windows Servers from AD, but ensure you have the Active Directory PowerShell module installed.
  3. Run with Privileges: Since the script uses WMI to query remote system info (RAM, OS Version, etc.), run your PowerShell ISE or Console as a Domain Admin.

The PowerShell Script

PowerShell
# Script: IIS Server Discovery & Profiler
# Location: lazyadminblog.com
# Purpose: Identify active IIS nodes and collect hardware/OS specs
Import-Module ActiveDirectory
# 1. Harvest all Windows Servers from AD
Write-Host "Gathering server list from Active Directory..." -ForegroundColor Cyan
$servers = Get-ADComputer -Filter {operatingsystem -Like "Windows server*"} | Select-Object -ExpandProperty Name
$servers | Out-File "C:\Temp\ServersRunningIIS\serverlist.txt"
# 2. Load the list for processing
$serversall = Get-Content "C:\Temp\ServersRunningIIS\serverlist.txt"
Start-Transcript -Path "C:\Temp\ServersRunningIIS\log_output.txt" -Append
foreach($vm in $serversall) {
try {
# Check if IIS Service (W3SVC) exists and is running
$iis = Get-WmiObject Win32_Service -ComputerName $vm -Filter "name='W3SVC'" -ErrorAction SilentlyContinue
if($iis.State -eq "Running") {
Write-Host "FOUND: IIS is active on $vm" -BackgroundColor DarkBlue -ForegroundColor DarkYellow
# Collect Network Info
$ipinfo = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $vm |
Where-Object {$_.IPEnabled -eq $true -and $_.IPAddress -like "1*"} | Select-Object -First 1
# Collect Hardware Info
$hwinfo = Get-WmiObject Win32_Computersystem -ComputerName $vm
# Collect OS Info
$osinfo = Get-WmiObject Win32_OperatingSystem -ComputerName $vm
# Flattening data for CSV-style output
$allinfo = "$($hwinfo.Name);$($hwinfo.Domain);$($ipinfo.IPAddress);$($ipinfo.IPSubnet);$($ipinfo.DefaultIPGateway);$($hwinfo.TotalPhysicalMemory);$($hwinfo.Manufacturer);$($hwinfo.Model);$($osinfo.Caption);$($osinfo.OSArchitecture);$($osinfo.ServicePackMajorVersion);$($osinfo.SystemDrive);$($osinfo.Version)"
# Save results to our 'Running' list
$allinfo | Out-File "C:\Temp\ServersRunningIIS\RunningWebServers.txt" -Append
}
}
catch {
Write-Host "Could not connect to $vm" -ForegroundColor Red
}
}
Stop-Transcript
Write-Host "Audit Complete! Check C:\Temp\ServersRunningIIS\RunningWebServers.txt" -ForegroundColor Green

What’s inside the report?

The output file (RunningWebServers.txt) uses a semicolon (;) delimiter, making it easy to import into Excel. It captures:

  • Network: IP Address, Subnet, and Gateway.
  • Hardware: Manufacturer, Model, RAM, and Domain membership.
  • Software: OS Version, Architecture (x64/x86), and System Drive.

Lazy Admin Tip

If you want to open the results immediately in Excel, just rename the output file from .txt to .csv and use the “Text to Columns” feature in Excel with the semicolon as the separator!

Automation: Bulk Create and Delete VM Snapshots Across Linked vCenters | Lazy Admin Blog

Posted on Updated on

In a large environment, taking snapshots before a major patch or application update is a standard safety net. But if you have servers spread across multiple vCenters in Linked Mode (e.g., Datacenter1 and Datacenter2), clicking through the vSphere Client is a waste of time.

Today, I’m sharing a “Lazy Admin” script that allows you to bulk create, check, and remove snapshots using a simple CSV list.

Prerequisites

  • VMware PowerCLI: Ensure the PowerCLI module is installed on the machine running the script.
  • CSV Setup: Create a file named snapshot_servers.csv in C:\Temp\VMSnapshots\.

The CSV should look like this: | Host | Location | | :— | :— | | Server01 | Datacenter1 | | Server02 | Datacenter2 |


Part 1: Creating Snapshots

  1. Open PowerShell ISE with vCenter Administrator credentials.
  2. Load the functions by running the full script (provided below).
  3. Run the following command:
PowerShell
Create-VMSnapshots -SS_CSV "C:\Temp\VMSnapshots\snapshot_servers.csv" -SS_Name "Pre-Patching" -SS_Description "Requested by App Team"

The script will iterate through your CSV and create snapshots sequentially. You can monitor the progress in the vSphere Tasks console.


Part 2: Deleting Snapshots

Once your changes are verified, don’t let those snapshots linger and bloat your datastores! To remove them:

  1. Use the same snapshot_servers.csv list.
  2. Run the following command:
PowerShell
Remove-VMSnapshots -SS_CSV "C:\Temp\VMSnapshots\snapshot_servers.csv"

Note: This is a sequential script; it will wait for one snapshot removal to finish before moving to the next to avoid pinning your storage I/O.


The Script: VMSnapshots.ps1

Save this code to C:\Temp\VMSnapshots\VMSnapshots.ps1.

PowerShell
function Create-VMSnapshots {
param (
[string]$SS_CSV = $(Read-Host "Enter path to CSV"),
[string]$SS_Name = $(Read-Host "Enter name for snapshots"),
[string]$SS_Description = $(Read-Host "Enter description for snapshots")
)
# Import VMware PowerCLI Module
If ( !(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) ) {
import-module VMware.VimAutomation.Core
}
$Servers = Import-CSV $SS_CSV
$WLM_vCenter = Connect-VIServer vCenter1 -WarningAction SilentlyContinue
$EDN_vCenter = Connect-VIServer vCenter2 -WarningAction SilentlyContinue
ForEach($Server in $Servers){
If($Server.Location -eq 'Datacenter1'){
New-Snapshot -VM $Server.Host -Name $SS_Name -Description $SS_Description -Quiesce -Server $WLM_vCenter -WarningAction SilentlyContinue
}
ElseIf($Server.Location -eq 'Datacenter2'){
New-Snapshot -VM $Server.Host -Name $SS_Name -Description $SS_Description -Quiesce -Server $EDN_vCenter -WarningAction SilentlyContinue
}
}
}
function Check-VMSnapshots {
param (
[string]$SS_CSV = $(Read-Host "Enter path to CSV"),
[string]$SS_Name = $(Read-Host "Enter snapshot name")
)
# Import VMware PowerCLI Module
If ( !(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) ) {
import-module VMware.VimAutomation.Core
}
$Servers = Import-CSV $SS_CSV
$WLM_vCenter = Connect-VIServer vCenter1 -WarningAction SilentlyContinue
$EDN_vCenter = Connect-VIServer vCenter2 -WarningAction SilentlyContinue
ForEach($Server in $Servers){
If($Server.Location -eq 'Datacenter1'){
Get-Snapshot -VM $Server.Host -Name $SS_Name -Server $WLM_vCenter | Select VM, Name, @{ n="SpaceUsedGB"; e={[math]::round( $_.SizeGB )}} -WarningAction SilentlyContinue
}
ElseIf($Server.Location -eq 'Datacenter2'){
Get-Snapshot -VM $Server.Host -Name $SS_Name -Server $EDN_vCenter | Select VM, Name, @{ n="SpaceUsedGB"; e={[math]::round( $_.SizeGB )}} -WarningAction SilentlyContinue
}
}
}
function Remove-VMSnapshots {
param (
[string]$SS_CSV = $(Read-Host "Enter path to CSV")
)
# Import VMware PowerCLI Module
If ( !(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) ) {
import-module VMware.VimAutomation.Core
}
$Servers = Import-CSV $SS_CSV
$WLM_vCenter = Connect-VIServer vCenter1 -WarningAction SilentlyContinue
$EDN_vCenter = Connect-VIServer vCenter2 -WarningAction SilentlyContinue
ForEach($Server in $Servers){
If($Server.Location -eq 'Datacenter1'){
Get-Snapshot $Server.Host -Server $WLM_vCenter | Remove-Snapshot -Confirm:$false -WarningAction SilentlyContinue
}
ElseIf($Server.Location -eq 'Datacenter2'){
Get-Snapshot $Server.Host -Server $EDN_vCenter | Remove-Snapshot -Confirm:$false -WarningAction SilentlyContinue
}
}
}

Setting Up Microsoft Entra Connect (Step-by-Step) | Lazy Admin Blog

Posted on Updated on

Why do manual user management when you can let a sync engine do the heavy lifting?

If you’re still manually creating users in both on-premises Active Directory and the Microsoft 365 portal, stop. You’re working too hard. Microsoft Entra Connect (formerly Azure AD Connect) is the “bridge” that syncs your local identities to the cloud. Set it up once, and your users get one identity for everything.

1. The “Pre-Flight” Checklist (Don’t skip this!)

The biggest mistake admins make is running the installer before the environment is ready. To be truly “lazy,” do the prep work so the installation doesn’t fail midway.

  • Server: A domain-joined Windows Server 2016 or later (2022 is recommended).
  • Hardware: Minimum 4GB RAM and a 70GB hard drive.
  • Permissions: * Local: You need to be a Local Admin on the sync server.
    • On-Prem: An Enterprise Admin account for the initial setup.
    • Cloud: A Global Administrator or Hybrid Identity Administrator account in Entra ID.
  • Software: .NET Framework 4.7.2 or higher and TLS 1.2 enabled.

Pro Tip: Run the Microsoft IdFix tool first. It finds duplicate emails and weird characters in your AD that would otherwise break the sync.


2. Step-by-Step Installation

Download the latest version of the Entra Connect MSI here.

Step A: The Express Route

  1. Launch AzureADConnect.msi.
  2. Agree to the terms and click Use Express Settings. (Note: Use “Custom” only if you have multiple forests or need specific attribute filtering).
  3. Connect to Entra ID: Enter your Cloud Admin credentials.
  4. Connect to AD DS: Enter your Enterprise Admin credentials.
  5. Entra ID Sign-in: Ensure your UPN suffixes match. If your local domain is corp.local but your email is lazyadminblog.com, you need to add lazyadminblog.com as a UPN suffix in AD.

Step B: The “Staging Mode” Safety Net

Before you hit install, you’ll see a checkbox for “Start the synchronization process when configuration completes.” If you are replacing an old server or are nervous about what will happen to your 5,000 users, check the “Enable staging mode” box. This allows the server to calculate the sync results without actually exporting anything to the cloud. You can “peek” at the results before going live.


3. Post-Setup: The “Lazy” Health Check

Once installed, the sync runs every 30 minutes by default. You don’t need to babysit it, but you should know how to check it:

  • The Desktop Tool: Open the Synchronization Service Manager to see a green “Success” status for every run.
  • The PowerShell Way: To force a sync right now (because you’re too impatient for the 30-minute window), run:PowerShellStart-ADSyncSyncCycle -PolicyType Delta

4. Troubleshooting Common “Gotchas”

  • “Top-level domain not verified”: You forgot to add your domain (e.g., https://www.google.com/search?q=myblog.com) to the Entra ID portal.
  • “Object Synchronization Triggered Deletion”: By default, Entra Connect won’t delete more than 500 objects at once. This is a safety feature to stop you from accidentally wiping your cloud directory. If you intended to delete them, you’ll need to disable the export deletion threshold.

The “Lazy Admin” Sync Monitor Script

Copy and save this as Monitor-EntraSync.ps1 on your sync server.

# --- CONFIGURATION ---
$SMTPServer = "smtp.yourrelay.com"
$From = "EntraAlert@lazyadminblog.com"
$To = "you@yourcompany.com"
$Subject = "⚠️ ALERT: Entra ID Sync Failure on $(hostname)"
# --- THE LOGIC ---
# Import the AdSync module (usually already loaded on the server)
Import-Module ADSync
# Get the statistics of the very last sync run
$LastRun = Get-ADSyncRunProfileResult | Sort-Object StartDateTime -Descending | Select-Object -First 1
# Check if the result was NOT 'success'
if ($LastRun.Result -ne "success") {
    $Body = @"
    The last Entra ID Sync cycle failed!
    
    Server: $(hostname)
    Run Profile: $($LastRun.RunProfileName)
    End Time: $($LastRun.EndDateTime)
    Result: $($LastRun.Result)
    
    Please log in to the Synchronization Service Manager to investigate.
"@
    # Send the alert
    Send-MailMessage -SmtpServer $SMTPServer -From $From -To $To -Subject $Subject -Body $Body -Priority High
}

🛠️ How to set it up (The Lazy Way)

To make this fully automated, follow these steps:

  1. Create a Scheduled Task: Open Task Scheduler on your Entra Connect server.
  2. Trigger: Set it to run every hour (or every 30 minutes to match your sync cycle).
  3. Action: * Program/script:powershell.exe
    • Add arguments: -ExecutionPolicy Bypass -File "C:\Scripts\Monitor-EntraSync.ps1"
  4. Security Options: Run it as SYSTEM or a Service Account that has local admin rights so it can access the ADSync module.

Why this is better than “Default” monitoring:

  • No Noise: You only get an email if there is an actual problem.
  • Proactive: You’ll likely know the sync is broken before your users start complaining that their new passwords aren’t working.
  • Zero Cost: No need for expensive third-party monitoring tools for a single-server task.

References & Further Reading

The Ultimate Robocopy Command for Large-Scale Migrations | Lazy Admin Blog

Posted on Updated on

If you need to move huge files while keeping a close eye on progress, this is the syntax you want. It includes logging, multi-threading for speed, and the ability to resume if the network drops.

The “Power User” Command

DOS

robocopy "D:\Source_Data" "E:\Destination_Data" /s /e /z /mt:32 /tee /log+:"C:\Logs\MigrationLog.txt"

Switch Breakdown: Why We Use Them

SwitchWhat it does
/s /eCopies all subdirectories, including empty ones.
/zRestart Mode: If the connection drops mid-file, Robocopy can resume from where it left off instead of starting the file over. Essential for 100GB+ files!
/mt:32Multi-Threading: Uses 32 threads to copy multiple files simultaneously. (Default is 8). Adjust based on your CPU/Disk speed.
/teeWrites the status to the console window and the log file at the same time.
/log+:Creates a log file. Using the + appends to an existing log rather than overwriting it—perfect for multi-day migrations.

How to Monitor Progress in Real-Time

Because we used the /tee and /log+ switches, you have two ways to monitor the status:

  1. The Console: You’ll see a rolling percentage for each file directly in your Command Prompt.
  2. Tail the Log: Since the log is being updated live, you can “tail” it from another window (or even remotely) to see the progress without touching the active copy session.

Lazy Admin Tip (PowerShell):

Open a PowerShell window and run this command to watch your Robocopy log update in real-time as files move:

PowerShell
Get-Content "C:\Logs\MigrationLog.txt" -Wait

Important Notes for Huge Files

  • Disk Quotas: Robocopy doesn’t check destination space before starting. Use dir or df (if using Linux targets) to ensure you have enough room.
  • Permissions: If you need to copy NTFS permissions (ACLs), add the /copyall switch.
  • Bandwidth: Running /mt:128 (the max) can saturate a 1Gbps link. If you’re copying over a live production network, stick to /mt:8 or /mt:16.

#WindowsServer #Robocopy #DataMigration #SysAdmin #ITInfrastructure #StorageAdmin #TechTips #LazyAdmin #CloudMigration

How to Get Hardware Serial Numbers Remotely (WMIC & PowerShell)

Posted on Updated on

As a SysAdmin, you often need a serial number or UUID for a warranty check or asset tracking. Instead of walking to the user’s desk or remoting into their session, you can pull this data directly from your workstation using these simple commands.

1. Using WMIC (Legacy Command Line)

WMIC is incredibly efficient for quick, one-off queries against remote systems.

To get a remote serial number:

DOS

wmic /node:"RemoteComputerName" bios get serialnumber

To export results to a central text file: If you are auditing multiple machines, use the /append switch to create a running list:

DOS

set myfile=\\Server\Share\Inventory.txt
wmic /append:%myfile% /node:"RemoteComputerName" bios get serialnumber

2. Using PowerShell (Modern Method)

PowerShell is the preferred method for modern Windows environments (Windows 10/11 and Server 2016+). It returns objects that are much easier to manipulate.

Standard Command:

PowerShell

Get-WmiObject -ComputerName "RemoteComputerName" -Class Win32_BIOS

The “Lazy” Short Version:

PowerShell

gwmi -comp "RemoteComputerName" -cl win32_bios

3. Bonus Hardware Commands

Sometimes the serial number isn’t enough. Use these WMIC commands to get a deeper look at the hardware specs:

  • CPU Details: Get the exact model and clock speeds. wmic cpu get name, CurrentClockSpeed, MaxClockSpeed
  • System Product Info: Pull the motherboard name and the system’s unique UUID. wmic csproduct get name, identifyingnumber, uuid
  • Full BIOS Audit: Get the BIOS name, version, and serial number in one go. wmic bios get name, serialnumber, version

Troubleshooting Connectivity

If these commands fail with “Access Denied” or “RPC Server Unavailable,” check the following:

  1. Admin Rights: Your shell must be running with Domain Admin or local administrator permissions on the target.
  2. Firewall: Ensure “Windows Management Instrumentation (WMI)” is allowed through the Windows Firewall on the remote machine.
  3. WMI Service: Ensure the WinMgmt service is running on the target.

#SysAdmin #PowerShell #WMIC #WindowsServer #ITPro #TechTips #InventoryManagement #LazyAdmin #RemoteAdmin #HardwareHack

How to Enable Remote Logins in a Windows server

Posted on Updated on

🛠️ The Registry Method (Headless Activation)

By default, Windows Server hardens itself by denying Terminal Server (TS) connections. You can flip this switch manually in the Registry Editor.

  1. Open Registry Editor: Press Win + R, type regedit, and hit Enter.
  2. Navigate to the Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\
  3. Modify the Value: Locate the fDenyTSConnections DWORD.
    • Value = 1: Remote Desktop is Disabled (Default).
    • Value = 0: Remote Desktop is Enabled.

💻 The PowerShell Method (The Modern Way)

If you have PowerShell Remoting enabled, you don’t even need to open a GUI. You can push this change with a single line of code:

PowerShell
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0

To verify the change:

PowerShell
Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections"

🛡️ Important: Don’t Forget the Firewall!

Enabling the registry setting is only half the battle. If the Windows Firewall is active, it will still block port 3389. You must allow the RDP traffic:

Via PowerShell:

PowerShell

Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

⚠️ Security Checklist

  • NLA (Network Level Authentication): For modern security, ensure the value UserAuthentication in the same registry path is set to 1. This requires users to authenticate before a session is even created.
  • Permissions: Simply enabling the service isn’t enough; the user account must be part of the Remote Desktop Users group or have Administrative privileges.
  • BlueKeep & Vulnerabilities: Ensure your server is fully patched if you are exposing RDP, as unpatched legacy servers are prime targets for ransomware.

#WindowsServer #RDP #RemoteDesktop #SysAdmin #ITPro #PowerShell #RegistryHacks #LazyAdmin #TechTips #ServerSecurity