DeepSite Review

DeepSite Review

Not much takes me by Suprise, but this little tool has really done just that. I want to do a Deepsite Review in today’s post. Deepsite is a unique AI tool that builds websites. Unlike chat gpt, you don’t have to feed it a complex prompt to make one page look decent. I am going to give you some examples of what I was able to make with it and the prompts used.

So what is deep site. Deep site is a hugging face tool made by enzostvs. https://enzostvs-deepsite.hf.space/. It uses deepseek’s AI to help create fairly simple sites to complex sits. I have made everything from flappy bird games to sites about possums. If it can be done inside a browser, deepsite can do it. When you first come to deepsite, this is what you get. A simple prompt, and a page. The HTML will be generated in the side. So lets look at some examples.

DeepSite Review Examples

Flappy Bird

Link: CyberFlap – Cyberpunk Flappy Bird

Prompt: create a cyberpunk flappy bird clone

It took about 5 minutes and wrote each line of code. You can play this clone at CyberFlap – Cyberpunk Flappy Bird. Is it perfect, no, but is it dang amazing, yes. This would have taken me a full day or two to code. It only took 5 minutes and it was a single file. So no copying and pasting multiple files and folder structing.

One and Two Liberty Square

Link: One&Two Liberty Square Greenville | Premier Property Management

Prompt: Create a website for a company called one and two liberty square. Here is the content (content from the previous site).

What amazed me here is it got most of the content together. It’s not the best layout, but it’s useable. The downside can be seen here. The longer the site, the harder it takes to make the site be creatively clean. It did poorly on the dots and sounds the same in a lot of places. That’s where the human charm comes into play.

What I would do to improve this site is change the menu to go to each building. I would also flip the images from one side to another. Then make a section for the corporate partners for it’s own.

One big thing to remember, this can only create the surface level. So, you see that contact us? Yeah, that doesn’t work. So, if your backend guy doesn’t know how to do the back end stuff, good luck.

Meme Generator

Link: Meme Maker Pro

Prompt: Create a dark themed meme generator where I can upload a picture and add text to the top and bottom and save it to my computer.

So, This was pretty cool. It made it within 5 minutes and only had 1 problem and it still does. It can’t save the three memes it shows in the left hand window because they are not in memory. However, you upload something and add your text, and click save, bam. Quick and easy. Some of the protriat shaped images will have odd text, but for the most part, it works.

Task Manager

Link: ZenFocus Pro – Advanced Todo App

Prompt: Make a Zen focus task manager with a dark mode.

Guess what, it will keep as long as you keep your cache. After that it forgets, and the dark mode sucks. So, if you clear your cache or move to a different browser, your stuff will not be there.

Deepsite Review

Pros

  • Create a basic website in seconds with little interaction
  • HTML code is split up the site using sections. Which allows for easy editing
  • The system users tailwindcss.com
  • Can create unique games with a simple command
  • Keeps standard praticies
  • Single html site file.
  • System will response

Cons

  • Creates a basic site, but nothing bigger
  • Keeps standard practices but not best practices
  • Odd formatting.
  • No backend

Final thoughts

This tool is great for simple sites and nothing more. If you want more than one page, this tool can’t do that. If you want a fully functioning back and front end product. This isn’t for you. However, front end development, is a yeppers. I personally like making cool 404 pages with this tool. I don’t do reviews often and the main reason why I wanted to bring this tool up is because it’s the beginning. If AI doesn’t eat itself and die, we will see the end of an industry. My last blog post was me asking questions to gpt and it giving me a response. I just told it to make it a blog post and bam, it did it. Which took the fun out of blogging. These tools are powerful and deepsite is just the beginning of replacing front end development. That’s my thinking on this Deepsite Review.

What we can learn as a person

When I was a child, I was told I will never have a calculator. I had to learn the division, exponets, square roots, and more by hand. (Yes, I know I just dated myself). I’m greatful for learning those things. Now when I am working with complex problems, I use the same structures and a lot of times the same formulas. Over the past 20 years, I have used my phone’s calculator. I am noticing a decline in my ability to preform simple maths. More I use chat gpt, I notice a skill drain.

Technology can replace our need to have a skill set over time. Is this a good thing? Sometimes, however, sometimes it’s not. I use AI in my daily life for a lot of things. But I don’t lean 100% into it like many of my peers do. The reason why is because I love to discover what I learn. I enjoy making the mistakes and correcting them. At the end of the day, i want the brain tingles. When I’m in my 70s, that love will keep my brain on track. I have seen a decline as I have gotten older. We all know that one day we will not be able to think like we did when we were 25 and that’s ok.

Two keeps to success

I have learned in this life there are two keys to success. Adaptability and Work. We have the adapt to the world around us. If it takes me 1 hour to code a deployment, but AI takes 5 seconds, might as well use the ai, but make sure I understand the ai’s code. So I can fix it later when it breaks. Adapting is imporatnt, but putting in the work is also as importatnt. Like this Deepsite Review, I could have had gpt do it, but I wanted to figure it out. So, I can see the full scope of what deepsite could do for me. If you don’t work at what you have in life, it doesn’t happen. Sometimes that means we have to work at being adaptable as well. That could mean a 15k paycut to escape a trauma inducing job. Other times it’s using a weed eater instead of a push mower. It means different things for different situations.

So, learn how to adapt. Work at what you do and enjoy. I find joy in work. It’s a simple concept. Seeing a clean room knowing I just did that, is a simple joy. It’s like putting back into myself. It’s worth it and so are you.

Intune devices vs app policies

Intune devices vs app policies

Ever feel like you’re just guessing which Intune policy to use?

You go into Microsoft Intune thinking, “I just want to block copy/paste from Teams to a student’s phone,” and suddenly you’re knee-deep in device configs, app restrictions, compliance policies, and something called MAM-WE (which sounds like a failed robot uprising).

If you’ve ever been stumped by the difference between Intune device vs app policies, you’re not alone. And you’re not doing it wrong — the naming is genuinely confusing.

So, let’s break it down the way it actually clicks — using real-world scenarios instead of theory and tech jargon. If you know what you want to do, you’ll know what to use. Lets dive into intune devices vs app policies.

The Three Intune Policy Buckets

Device Configuration Policies – You Own It, You Control It

Think of this like setting the house rules — but only for houses you own.

Device configuration policies give you OS-level control. You can push BitLocker, set PIN rules, enforce Delivery Optimization, apply VPN profiles, and more. But they only work if the device is enrolled in Intune — like, actually enrolled. Not “kinda managed.” Full enrollment.

Lets take a look at a real world senerio. Imagine you have 200 windows 11 laptops and want to enable delivery optimization for windows updates. This would be a Device Configuration Profile. Another example would be if you have 1000 windows 11 laptops that you want to encrypt their fixed drive with bit-locker. Once again, this is another device configuration profile.

If the deivce is apersonal and not enrolled, this policy type is off-limits. No Bitlocker, no VPN, nothing. You don’t own it, you don’t get a say.

App Protection Policies – Protecting the Data, Not the Device

This one is magic for BYOD situations. Think of it like zipping up your company’s data in a fireproff pouch, even if it’son someone else’s device. App protection polcies don’t care who owns the device. They care about your data. These policies apply to managed apps. Things like outlook, teams, onedrive, and lets you do things like bloc copy and paste. Require PINs to open apps, wipe work data and more.

Lets take a look at a few real world senerios. Students are copying teams messagers and pasting them into discord on their phones. You can block this using App Protection Policy. Lets say you have truck drivers with ipads with outlook on them. You can force the user to enter a pin each time they check their email. That’s a App Protection Policy.

App Configuration Policies – Pre-setting the Knobs

Here we are putting the settings into place for different apps. We are not locking down the device. So, if you need a pin for the device, you do this with a device configuration policy. If you need chrome to open on a set website, that’s the App Configuration Policy. App configuratin policies let you predefine how apps behave. It’s not about control, but it’s about consistency. You can push bookmarks, force outlook to use only work accounts, set default browsers for teams, and more.

Lets look at a real world. You have 500 Android Zebra scanners, you need to make sure they all open chrome to a local site. This can be done through the App Configuration Policy. One thing we did for was setup auto updates with zebra on our scanners. We did this with a App configuration profile.

The problem with it is the BYOD. App Configuration policies only work with managed apps. This means, if a user installs outlook through the company portal via intune, then you can manage it. However, if you install outlook through the store app, it just doesn’t work.

Why it gets confussing

Let’s be real, the names don’t help. “App Protection” and “App Configuration” sound way to similar. So here’s a simple mental hack to seperating devices vs app policies.

  • Device Configuration = Control the device itself.
  • App Configuration = Setup how the app works.
  • App Protection = Lock down the data inside the app.

Lets test this thinking out with a few senerios.

  • Possible Answers
    • Device Configuration Policy
    • App Configuration Policy
    • App Protection Policy
  1. You want to prevent employees from copying data from teams to another non-company app.
  2. Your factory has 300 kiosk devices. You want to make sure that the devices can’t be logged into by non-it users.
  3. Doctors are using outlook on their personal phones. You need to prevent attachments from being saved locally.
  4. Your compamy users Android enterprise, and you want to push bookmarks to chrome.
  5. You want to rotate the local admin password on all of your windows 11 devices using windows LAPS
  6. Force outlook to only use work accounts
  7. Encrypt phones and force a pin lock on bring your own devices.

Here is a nice little chart to help with these.

Do I manage the entire device?
   ↳ Yes ➡ Device Configuration
   ↳ No ➡ Do I want to protect corporate data?
            ↳ Yes ➡ App Protection
            ↳ No ➡ Do I want to change how the app behaves?
                     ↳ Yes ➡ App Configuration

Here are the answers.

  1. App Protection
  2. Device Configuration
  3. App Protection
  4. App Configuration
  5. Device Configuration
  6. App Configuration
  7. None of the above, Yep, I tricked you, maybe. If it wasn’t a bring your own device, then you would be correct if you say device configruation profiles. Other than that, it’s nothing really.

Final Thoughts – “You Know More Than You Think”

This stuff is confusing, and Microsoft doesn’t always make it easy. But now, you’ve got the mental framework:

  • Device Config = You own the device
  • App Protection = You own the data
  • App Config = You shape the experience

Don’t worry about getting it perfect on the first try. Intune is meant to be layered. Pilot first, then scale.

If you ever get stuck again, just ask: “What exactly am I trying to control here?”
The answer will almost always tell you the policy you need.

You’ve got this, lets get those devices vs app policies.

What can we learn as a person

In IT, we have access to a lot. More than most people will ever know.

We can shut down Windows Hello, enforce biometric logins, or require ID badges scanned by a camera just to unlock a screen. As system administrators, we often hold keys to every digital door. I could, right now, grant myself full access to every mailbox in the company — all in the name of “making admin easier.” I could quietly assign myself as an owner on every user’s OneDrive and SharePoint site using policies that no one would even notice.

That level of control? It’s terrifying, if you’re honest about it.

Because with great power doesn’t just come great responsibility.
It comes with weight. A psychological and emotional load that most people never talk about.

Knowing that you can access someone’s private data — and choosing not to — becomes a moral and mental burden. It sits on your nervous system like a background process you can’t kill. Over time, that mental load becomes stress. That stress becomes anxiety. That anxiety becomes burnout, or worse — panic attacks that don’t go away.

Let’s go back to those access examples:

If you make yourself owner of every mailbox, and something illegal ends up in one — say, child pornography in OneDrive — you’re now not just an admin. You’re a co-owner of that content. You’re legally implicated. That’s not just a technical decision. That’s jail time.

When you hold that kind of access, your body knows, even if your conscious mind tries to ignore it. It keeps a tally. And that tally eventually tips the scale — panic attacks, heart strain, and real, physical damage.

The Illusion of Total Control

I’ve seen brilliant people collapse under the pressure of trying to control everything — juggling complex networks, hybrid systems, countless endpoints, compliance rules, and impossible expectations.

They thought the job was about mastery. But really, it’s about boundaries.

Technology is growing faster than any one human can keep up with. We’re now expected to specialize and generalize. To know cloud, on-prem, security, devices, data — and also keep every system running 24/7 with no mistakes.

That pressure? It breaks people.

So What Can We Learn?

Here’s what I’ve learned — sometimes the hard way:

  • Control less. Not because you’re lazy — but because your health matters more than a perfect config.
  • Set boundaries. Just because you can access something doesn’t mean you should.
  • Say no to full access. Delegate. Distribute. Limit yourself.
  • Audit yourself. Regularly review what you have access to, and ask: Do I really need this?
  • Let go. Systems don’t have to be perfect. People don’t have to be flawless. Neither do you.

You’re not here to own everything. You’re here to protect what matters — and that includes you.

So the next time you feel the urge to control every setting, script every failover, and be the hero of the whole system…
Pause.
Breathe.
And remember: the best admins don’t control everything. They know what not to control — and they sleep better because of it.

Additional Content

PowerShell regex use case

PowerShell regex use case

If you’ve ever needed to extract specific information from a log file or validate user input in a PowerShell script, you’ve probably wished for a magic tool that could do the heavy lifting. Well, that’s exactly where regular expressions (regex) come in.

Regex is one of those tools that feels intimidating at first, but once you get the hang of it, you’ll start seeing patterns everywhere. It’s like suddenly being able to read the Matrix, except instead of dodging bullets, you’re filtering out bad email addresses or pulling MAC addresses from a system log.

Why Use Regex in PowerShell?

PowerShell has built-in support for regex, making it an incredibly powerful tool for system administrators, developers, and anyone who works with structured or unstructured text. Whether you’re:

  • Validating user input (like email addresses in a script)
  • Extracting important data from logs (like MAC or IP addresses)
  • Searching for patterns in massive amounts of text

Regex allows you to do all of this with just a few carefully crafted expressions. It’s like having a Swiss Army knife for text processing.

What We’ll Cover in This Guide

In this post, we’ll walk through three practical PowerShell regex use cases:

  1. Email Addresses – How to validate email input and extract emails from a document
  2. MAC Addresses – How to validate MAC addresses and find them in logs
  3. IP Addresses – How to check if an IP is valid and pull all IPs from a file

Before we dive into these examples, we’ll go over some regex basics, including common syntax and flags that make regex so powerful. By the end, you’ll not only understand how regex works in PowerShell but also feel confident using it in your own projects.

Let’s get started!

Understanding Regex Flags and Syntax

Regular expressions might look like a confusing mess of symbols at first, kind of like trying to understand a cat’s behavior. One minute it’s purring in your lap, the next it’s knocking your coffee off the table. But once you start recognizing the patterns—like how a tail flick means back away, human—it all starts to make sense.

Regex is the same way. At first glance, it looks like a secret code of slashes, dots, and brackets. But once you learn the building blocks, you start seeing patterns everywhere, and suddenly, text manipulation in PowerShell becomes effortless. PowerShell has native support for regex, meaning you can use it to search, validate, and extract information with just a few well-placed symbols—kind of like bribing a cat with treats to do what you want.

Character Classes: Defining What to Match

Character classes allow you to specify what kind of characters should match. Instead of listing every possibility, regex provides shorthand notations.

Common Character Classes in PowerShell Regex

Character ClassDescriptionExample Match
\dMatches any digit (0-9)123 in abc123
\wMatches any word character (A-Z, a-z, 0-9, _)hello in hello_123
\sMatches any whitespace (space, tab, newline)The space in "Hello World"
.Matches any character (except newline)H or ! in "Hi!"

Example in Powershell:

"This is a test 123" -match "\d+"  # Matches "123"

Quantifiers: Controlling Repetitions

Quantifiers define how many times a pattern should repeat.

Common Quantifiers

QuantifierDescriptionExample Match
*Matches 0 or more timesaaa in "aaaaa"
+Matches 1 or more timesabc in "abc"
?Matches 0 or 1 time (optional)a in "a" or empty string
{n}Matches exactly n times333 in "333"
{n,}Matches at least n times111 in "11111"
{n,m}Matches between n and m times55 in "5555" (if {2,3})

Example in PowerShell:

"This is 55555" -match "\d{2,3}"  # Matches "555"

Anchors: Defining Position in Text

Anchors don’t match actual characters but instead define where a match should occur.

Common Anchors

AnchorDescriptionExample Match
^Matches the start of a stringHello in "Hello world"
$Matches the end of a stringworld in "Hello world"
\bMatches a word boundarycat in "cat dog" but not "scatter"

Example in PowerShell:

"This is a test" -match "^This"  # Matches "This"

Escaping Special Characters

Some characters in regex have special meanings (like . or *). If you want to match them literally, you need to escape them with a backslash \.

Common Special Characters That Need Escaping

  • . (dot) → Matches any character, so use \. to match a literal dot.
  • * (asterisk) → Use \* to match an actual asterisk.
  • ? (question mark) → Use \? to match a literal question mark.

Example in PowerShell:

"This is version 1.0.1" -match "1\.0\.1"  # Matches "1.0.1"

How to Use Regex in PowerShell

PowerShell provides multiple ways to work with regex:

  1. -match Operator – Checks if a string matches a pattern.
  2. -replace Operator – Replaces matched patterns in a string.
  3. [regex]::matches() – Extracts all matches from a string.

Example of Finding All Matches in a String:

$text = "Emails: test@example.com, admin@company.net"
$pattern = "[\w\.-]+@[\w\.-]+\.\w+"
$matches = [regex]::Matches($text, $pattern)

$matches.Value  # Outputs: test@example.com, admin@company.net

Extracting and Validating Email Addresses with PowerShell

When working with PowerShell scripts, validating user input is crucial—especially when dealing with email addresses. You don’t want users submitting "notanemail@oops" or "hello@.com" and breaking your workflow. Thankfully, regex makes it easy to verify if an email address is properly formatted and even extract all emails from a document.

Before we get into validating and extracting emails, let’s break down the regex pattern that makes it all work.

Breaking Down the Email Regex

Email validation might seem simple at first—just look for an “@” symbol, right? But things get complicated fast. A valid email address follows these rules:

  1. A username section, which can include letters, numbers, dots, dashes, and underscores.
  2. An “@” symbol separating the username from the domain.
  3. A domain name that includes letters and numbers.
  4. A top-level domain (TLD) like .com, .net, .org, etc.

A regex pattern that matches most valid email addresses looks like this:

[\w\.-]+@[\w\.-]+\.\w+

Let’s break it down piece by piece:

Username Section: [\w\.-]+

  • \w → Matches letters, numbers, and underscores (a-z, A-Z, 0-9, _).
  • . and - → Allows dots and dashes in the username.
  • + → Ensures one or more of these characters exist.

“@” Symbol: @

  • The @ is a literal character—every valid email must have it.

Domain Name: [\w\.-]+

  • Just like the username, the domain allows letters, numbers, dots, and dashes.

Top-Level Domain (TLD): \.\w+

  • \. → Matches a literal dot before the TLD.
  • \w+ → Ensures at least one letter (like .com or .net).

Example Matches:

  • user@example.com
  • john.doe123@company.co.uk
  • admin-test@my-site.net

Invalid Matches:

  • @example.com (No username)
  • user@.com (Invalid domain name)
  • user@domain (No TLD)

This regex is great for general email validation, but in PowerShell, we need to apply it properly. Next, we’ll use this pattern in a ValidateSet to enforce correct email input in scripts.

Using Regex for PowerShell ValidateSet

PowerShell has built-in ways to enforce valid input in scripts, and one way to do this is by using regex inside a function. The function below checks if an email matches our regex pattern. If it’s valid, it returns $true; if not, it gives a reason why.

PowerShell Email Validation Function

function Test-EmailAddress {
    param (
        [string]$Email
    )

    $pattern = "^[\w\.-]+@[\w\.-]+\.\w+$"

    if (-not $Email) {
        return "False - No email provided."
    }

    if ($Email -match $pattern) {
        return "True"
    }
    
    # Now let's figure out why it failed  
    if ($Email -notmatch "@") {
        return "False - Missing '@' symbol."
    }
    
    if ($Email -match "@\." -or $Email -match "@$") {
        return "False - Invalid placement of '@' or '.'"
    }

    if ($Email -notmatch "\.\w+$") {
        return "False - Missing top-level domain (e.g., .com, .net)."
    }

    return "False - Invalid email format."
}

How It Works

  1. Checks if an email is provided – If the input is empty, it immediately returns a failure message.
  2. Validates using regex – If the input matches the regex pattern, it returns True.
  3. Identifies why the email is invalid – It checks for common issues like missing @, misplaced dots, or a missing TLD.

This function is useful for scripts that require valid emails before proceeding. Next, we’ll explore how to extract all emails from a document using regex!

Finding All Email Addresses in a Document

If you’re working with logs, reports, or any large text files, regex is your best friend for extracting structured data like email addresses. Instead of manually scanning through lines of text, PowerShell can do the heavy lifting in seconds.

Here’s a script that:

  1. Reads a file line by line.
  2. Uses regex to find all email addresses.
  3. Outputs the results to the console (or optionally saves them to another file).

PowerShell Script to Extract Emails from a File

function Get-EmailAddressesFromFile {
    param (
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        Write-Host "Error: File not found at path: $FilePath"
        return
    }

    $pattern = "[\w\.-]+@[\w\.-]+\.\w+"
    $emails = @()

    Get-Content $FilePath | ForEach-Object {
        $matches = [regex]::Matches($_, $pattern)
        if ($matches.Count -gt 0) {
            $emails += $matches.Value
        }
    }

    if ($emails.Count -eq 0) {
        Write-Host "No email addresses found in the file."
    } else {
        Write-Host "Found $($emails.Count) email addresses:"
        $emails | Sort-Object -Unique
    }
}

# **Example Usage**
Get-EmailAddressesFromFile -FilePath "C:\path\to\your\file.txt"

How It Works

  1. Checks if the file exists – Avoids errors if the file path is incorrect.
  2. Reads the file line by line – Prevents loading large files into memory at once.
  3. Uses regex to find emails – Looks for matches in each line.
  4. Stores and displays unique results – Avoids duplicates and outputs all found emails.

Example File (C:\path\to\your\file.txt)

Hello John, please contact us at support@example.com.
You can also reach admin@company.net for further assistance.
But we dont want to see a snail@the white house. 
However, we might @ your friend .com
How about a cheesecake@cheesecakefactory.com?

Script Output

Found 3 email addresses:
admin@company.net
cheesecake@cheesecakefactory.com
support@example.com

This script is super useful for extracting emails from logs, reports, or even messy text files. Next up, we’ll apply these same techniques to MAC addresses!

Extracting and Validating MAC Addresses with PowerShell

MAC addresses (Media Access Control addresses) are unique hardware identifiers assigned to network interfaces. If you’re dealing with network logs, device configurations, or security audits, you may need to validate or extract MAC addresses.

A valid MAC address follows one of these formats:

  • Colon-separated: 00:1A:2B:3C:4D:5E
  • Hyphen-separated: 00-1A-2B-3C-4D-5E
  • No separator: 001A2B3C4D5E

But Cisco devices often use a dot-separated format:

  • Cisco-style: 001A.2B3C.4D5E

Now, let’s break down the regex pattern that will help us match MAC addresses.

Breaking Down the MAC Address Regex

MAC addresses consist of six groups of two hexadecimal digits (0-9 and A-F), separated by colons, hyphens, or nothing at all. Here’s a regex pattern that matches all common formats:

([A-Fa-f0-9]{2}[:-]?){5}[A-Fa-f0-9]{2}|([A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}

Breaking It Down

  1. First Half: Standard MAC Formats
    • ([A-Fa-f0-9]{2}[:-]?){5}[A-Fa-f0-9]{2} → Matches colon, hyphen, or no separator formats.
  2. Second Half: Cisco’s Dot-Format
    • ([A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4} → Matches two groups of four hex digits separated by dots.

Example Matches:

  • 00:1A:2B:3C:4D:5E
  • 00-1A-2B-3C-4D-5E
  • 001A2B3C4D5E
  • 001A.2B3C.4D5E (Cisco format!)

Invalid Matches:

  • 00:1A:2B:3C:4D (Only five pairs)
  • 00:1G:2B:3C:4D:5E (Invalid hex digit G)
  • 00::1A:2B:3C:4D:5E (Double colon is not valid)

Using Regex for PowerShell ValidateSet (Including Cisco Format)

We’ll now create a PowerShell function that checks if a given MAC address is valid. If it’s valid, it returns True; if not, it returns False with a reason why.

Updated PowerShell MAC Address Validation Function

function Test-MacAddress {
    param (
        [string]$MacAddress
    )

    $pattern = "^([A-Fa-f0-9]{2}[:-]?){5}[A-Fa-f0-9]{2}$|^([A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}$"

    if (-not $MacAddress) {
        return "False - No MAC address provided."
    }

    if ($MacAddress -match $pattern) {
        return "True"
    }

    # Identify why it failed
    if ($MacAddress -notmatch "^[A-Fa-f0-9]+$" -and $MacAddress -notmatch "[:-\.]") {
        return "False - Contains invalid characters."
    }

    if ($MacAddress -notmatch "([A-Fa-f0-9]{2}[:-]?){5}[A-Fa-f0-9]{2}" -and $MacAddress -notmatch "([A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}") {
        return "False - Incorrect format. Should be XX:XX:XX:XX:XX:XX, XX-XX-XX-XX-XX-XX, XXXXXXXX, or XXXX.XXXX.XXXX (Cisco)."
    }

    return "False - Invalid MAC address format."
}

How It Works

  1. Checks if a MAC address is provided – Ensures input isn’t empty.
  2. Uses regex for validation – If the input matches the pattern, it’s valid.
  3. Identifies specific errors – Helps users understand why an input is invalid.

Now that we can validate a single MAC address, let’s move on to extracting all MAC addresses from a file!

Finding All MAC Addresses in a Document

This next script scans a file and extracts all MAC addresses using regex. It works just like our email extraction script, but with a MAC address pattern.

PowerShell Script to Extract MAC Addresses from a File

function Get-MacAddressesFromFile {
    param (
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        Write-Host "Error: File not found at path: $FilePath"
        return
    }

    $pattern = "([A-Fa-f0-9]{2}[:-]?){5}[A-Fa-f0-9]{2}|([A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}"
    $macAddresses = @()

    Get-Content $FilePath | ForEach-Object {
        $matches = [regex]::Matches($_, $pattern)
        if ($matches.Count -gt 0) {
            $macAddresses += $matches.Value
        }
    }

    if ($macAddresses.Count -eq 0) {
        Write-Host "No MAC addresses found in the file."
    } else {
        Write-Host "Found $($macAddresses.Count) MAC addresses:"
        $macAddresses | Sort-Object -Unique
    }
}

# **Example Usage**
Get-MacAddressesFromFile -FilePath "C:\path\to\your\file.txt"

How It Works

  1. Checks if the file exists – Prevents errors if the file path is wrong.
  2. Reads the file line by line – Efficient for large files.
  3. Uses regex to extract MAC addresses – Searches each line for matches.
  4. Stores and displays unique results – Removes duplicate addresses for cleaner output.

Example File (C:\path\to\your\file.txt)

Device 1: 00:1A:2B:3C:4D:5E  
Device 2: 00-1A-2B-3C-4D-5E  
Cisco Router: 001A.2B3C.4D5E  
Error Log: Invalid MAC -> 00:1A:2B:3G:4D:5E  

Script Output

Found 3 MAC addresses:
00:1A:2B:3C:4D:5E
00-1A-2B-3C-4D-5E
001A.2B3C.4D5E

This script is super useful for network admins who need to extract MAC addresses from logs or reports. Next up, we’ll do the same for IP addresses!

Extracting and Validating IP Addresses with PowerShell

IP addresses are everywhere—logs, configs, audit reports—you name it. If you’re working with networking or security, you’ll often need to validate or extract IPs from text files.

We’re going to cover IPv4 and IPv6, because while IPv4 is still dominant, IPv6 is becoming more common.

What Makes an IP Address Valid?

IPv4 Format

  • Consists of four octets (groups of numbers) separated by dots: 192.168.1.1
  • Each octet must be between 0 and 255

IPv6 Format

  • Consists of eight groups of hexadecimal numbers (0-9, A-F), separated by colons: 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  • Can contain compressed notation (e.g., :: represents consecutive zero blocks)

Breaking Down the IP Address Regex

To match both IPv4 and IPv6, we’ll use two separate regex patterns.

IPv4 Regex Pattern

\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b

Breaking It Down

  • 25[0-5] → Matches 250-255
  • 2[0-4][0-9] → Matches 200-249
  • 1[0-9]{2} → Matches 100-199
  • [1-9]?[0-9] → Matches 0-99
  • \. → Ensures each octet is separated by a dot
  • {3} → Ensures exactly three dots appear

IPv6 Regex Pattern

\b([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}\b

Breaking It Down

  • [A-Fa-f0-9]{1,4} → Matches hexadecimal numbers (1-4 digits)
  • : → Ensures each section is separated by a colon
  • {7} → Ensures exactly seven colons appear

⚠️ This regex does not handle compressed IPv6 addresses (::), but we’ll take care of that in PowerShell logic!

Using Regex for PowerShell ValidateSet

Now, let’s create a PowerShell function to validate both IPv4 and IPv6 addresses.

PowerShell IP Address Validation Function

function Test-IPAddress {
    param (
        [string]$IPAddress
    )

    $ipv4Pattern = "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$"
    $ipv6Pattern = "^([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}$"

    if (-not $IPAddress) {
        return "False - No IP address provided."
    }

    if ($IPAddress -match $ipv4Pattern) {
        return "True (IPv4)"
    }

    if ($IPAddress -match $ipv6Pattern -or $IPAddress -match "^(::|([A-Fa-f0-9]{1,4}:){1,6}:?([A-Fa-f0-9]{1,4})?)$") {
        return "True (IPv6)"
    }

    return "False - Invalid IP address format."
}

How It Works

  1. Checks for input – Ensures an IP address was provided.
  2. Matches against IPv4 regex – If valid, returns True (IPv4).
  3. Matches against IPv6 regex – If valid, returns True (IPv6).
  4. Handles compressed IPv6 (::) – Using additional PowerShell logic.
  5. Returns an error if invalid – Helps troubleshoot incorrect formats.

Now, let’s move on to extracting all IPs from a document!

Finding All IP Addresses in a Document

This script scans a file and extracts all IPv4 and IPv6 addresses.

PowerShell Script to Extract IP Addresses from a File

function Get-IPAddressesFromFile {
    param (
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        Write-Host "Error: File not found at path: $FilePath"
        return
    }

    $ipv4Pattern = "\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b"
    $ipv6Pattern = "\b([A-Fa-f0-9]{1,4}:){1,7}[A-Fa-f0-9]{1,4}\b"
    $ipAddresses = @()

    Get-Content $FilePath | ForEach-Object {
        $matchesIPv4 = [regex]::Matches($_, $ipv4Pattern)
        $matchesIPv6 = [regex]::Matches($_, $ipv6Pattern)

        if ($matchesIPv4.Count -gt 0) {
            $ipAddresses += $matchesIPv4.Value
        }
        if ($matchesIPv6.Count -gt 0) {
            $ipAddresses += $matchesIPv6.Value
        }
    }

    if ($ipAddresses.Count -eq 0) {
        Write-Host "No IP addresses found in the file."
    } else {
        Write-Host "Found $($ipAddresses.Count) IP addresses:"
        $ipAddresses | Sort-Object -Unique
    }
}

Example File (C:\path\to\your\file.txt)

Server 1: 192.168.1.1  
Server 2: 255.255.255.255  
Router: 2001:db8:85a3::8a2e:370:7334  
Log Entry: Invalid IP -> 999.999.999.999  

Script Output

Found 3 IP addresses:
192.168.1.1
255.255.255.255
2001:db8:85a3::8a2e:370:7334

Regex Exploration in PowerShell

At this point, you’ve seen how regex can validate, extract, and manipulate data in PowerShell. Whether it’s emails, MAC addresses (including Cisco formats), or IPs (both IPv4 and IPv6), you now have practical tools to handle real-world scenarios.

Why Keep Learning Regex?

Regex is one of those skills that pays off the more you use it. The same way a system admin gets better at troubleshooting networks over time, you’ll get faster at spotting patterns and writing efficient expressions.

Here are some great ways to keep sharpening your regex skills:

  • Practice on Real Logs – Take a firewall log, an Apache log, or an email report and extract useful data.
  • Use Online Regex Tools – Websites like regex101.com let you test regex patterns with real-time explanations.
  • Experiment with PowerShell – Try using -match, -replace, and [regex]::Matches() in your daily scripts.
  • Challenge Yourself – Create a script that finds phone numbers, dates, or even URLs in a document.
  • Accept Growth – A few years ago, I wrote SHD – Set Mac Structure – The Random Admin, and I am glad to say I have grown a lot since then. It feels good.

Final Thought

Regex is a skill, not magic. It may look complex at first, but like learning any new language, it becomes second nature with practice. The best way to improve? Find a problem and solve it with regex.

So, what’s your next PowerShell regex use case going to be?

What can we learn as a person today?

When a script fails, we don’t just throw our hands up and quit—we debug it. We check the logs, isolate the issue, and find a fix. But when our own minds start feeling overwhelmed, anxious, or burned out, we often just push through, hoping the problem resolves itself. What if we approached our mental health like we approach troubleshooting code? Debugging isn’t just for PowerShell scripts—it can work for stress, too.

Find the errors

The first step in debugging stress is identifying the error messages. In IT, a recurring issue in the logs might mean something deeper is wrong, and the same goes for mental health. Are you feeling exhausted every morning? Snapping at coworkers over small things? Losing focus even on tasks you usually enjoy? These could be your mind’s version of Event ID 1000: Application Crash. Instead of ignoring the warning signs, acknowledge them—just like you would in a system check.

Analyze the variables

Next, we analyze the variables. Just like a misconfigured setting can break a script, small changes in your routine can make or break your mental well-being. Are you sleeping enough? Eating well? Taking breaks? IT professionals are notorious for skipping meals, working through exhaustion, and staying up late chasing down problems. But just like an unstable system needs a reboot, your brain needs rest. Run a self-check—what’s missing from your routine that could improve stability?

Implement something

Finally, implement a fix and test the results. Maybe you start with a simple -replace—swapping out caffeine overload for proper hydration or scheduling actual breaks instead of “just five more minutes.” Maybe you automate self-care reminders, like setting a PowerShell script to remind you every hour to step away from the screen. And if the issue persists? Just like with a stubborn bug, escalate it—talk to a friend, mentor, or even a therapist. There’s no shame in calling in extra support when needed.

In IT, we don’t assume things will “just work”—we test, refine, and optimize. Treat your mental health the same way. Debug your stress, adjust your variables, and don’t be afraid to run an upgrade on your self-care routine. The best systems run smoothly when properly maintained—and that includes you.

CG-NATed Home lab

CG-NATed Home lab

Recently I switched ISP providers. The one I was using started the price increase game. We picked up the ISP while it was $70 per month for 1 GB. They are the only physical line provider in my town. The town has a law that “beautifies” the power lines. This means only one ISP with cables is allowed to use them. They also have a digging bill. It was designed by a corrupt city council to keep this one ISP as the primary provider. Well, this ISP has started their price walking. They start off with $10 fines here and there. Finally, it reaches $200 after a year for 1 GB. For years, the only other option has been HughesNet. Thankfully, T-Mobile has stepped in. However, they are CG-Nated and a home lab is hard to work with.

CG-NAT

Most people don’t know what CG-NAT is and how ugly it can get. Carrier-grade NAT is where the carrier places you inside a natted bubble. This saves IP addresses. You are essentially part of a nested network. It’s all nated inside each other. It tends to be standard to have your own network, then the carriers, then the public. So while you can reach therandomadmin.com with a public IP address, you can’t reach my home network with one. CGNs do not allow for port forwarding. These networks are ideal for simple plug-and-play networks. However, they are sad for us IT home lab people.

There is a ray of hope with these types of networks. VPN over SSL. This can be done via WireGuard and other VPN software. The thing to remember is you need an external, public-facing device. That’s where Oracle comes into play. Remember in my blog about free WordPress, we built an Oracle Cloud server. We are going to use this beast to get around our CG-NAT issue and open some of our services to the world. This makes a CG-NATed home lab really hard to work with, but we have magic on our side.

The Magical Connections

Ok, so we are going to use our Oracle Cloud server and combine it with our Tailscale network. Our Oracle Cloud server already has an Apache server on it. All we have to do is enable the reverse proxy settings on it.

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo systemctl reload apache2

Now we need to take our Tailscale network and make some reverse proxies. We are going to be doing the Docker world this time around. You can read about setting up your Docker in WordPress here. Once you have your Docker setup on your home lab server, take note of the IP address and the port number of that Docker. Please ensure you can access it locally before proceeding with any other tasks. With this first step, our CG-NATed home lab is going public.

DNS

The next part is important. I use Namecheap DNS. What you need to do is set the DNS to the Oracle host. For my example, I am pointing to therandomadmin.com host IP address for it.dpb.one. DNS can take some time to populate as well. A good rule of thumb I follow is, if you can’t ping it and get the IP address you want, wait.

Reverse Proxy

Now we will make our reverse proxy on the Apache side. First you will need to make the conf file inside your site’s available location.

sudo nano /etc/apache2/sites-available/it.dpb.one.conf

The above command will create the file and drop you into the nano prompt. This is a configuration file for one of my home lab devices. I want you to read over this file.

<VirtualHost *:80>
    ServerName it.dpb.one

    ProxyPreserveHost On

    # Point directly to lab app's port (9000 in this example)
    ProxyPass / http://100.104.5.106:9000/
    ProxyPassReverse / http://100.104.5.106:9000/

    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"

    ErrorLog ${APACHE_LOG_DIR}/it.dpb.one-error.log
    CustomLog ${APACHE_LOG_DIR}/it.dpb.one-access.log combined
</VirtualHost>

breaking it down

Just like any other virtual host, we are starting off with our tags. Then we have the name of the server. So, when DNS points the it.dpb.one to the IP address. Apache will be like, I know this. It knows it’s a reverse proxy because it sees that Proxy Preserve Host on. Then it grabs the proxypass and the proxy return pass. This is where we want to put the IP addresses.

    ProxyPass / http://100.104.5.106:9000/
    ProxyPassReverse / http://100.104.5.106:9000/

Notice this line: ProxyPass / This / is important. If you want to make a subdirectory, this is where you would place it. So, let’s say I wanted it.dpb.one/nextcloud to point to another server that hosts my Nextcloud; that is where I would place it. The next part will be the inside of your network. Notice the IP address is the Tailscale IP address.

    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"

The next two lines are for custom items. The first tells us we are using HTTP. So the requests internally are HTTP. You can set this to HTTPS if you like. However, you will get cert errors. The second line is to pass the remote user’s IP address and not the host’s to the machine in question. If you don’t want the user’s IP address to hit your machine, then leave this line out. While the final two lines are for logging.

Now run the next two commands; the first is to enable the conf file, and the final is to load it into the Apache system.

sudo a2ensite it.dpb.one.conf
sudo systemctl reload apache2

Certbot

Finally, we like having SSL on things. I feel like if you are not using an SSL on a site, something is wrong with you. SSLs are free thanks to Certbot and the Electronic Frontier Foundation. Please donate to these people as they are doing great work. So on the Oracle Cloud server, you can run the certbot command for the domain. If you don’t have Certbot installed, here are some nice instructions.

sudo certbot --apache -d it.dpb.one

Once you have the cert setup, you will notice another file is created inside your sites-available location. Everything else is done for you at this point. Now you can access the website from the remote world. You can’t, however, access SSH remotely. This is a good protection. But, but, Random, I want to access my home lab via SSH.

Setting up SSH Jump Box

So, you want to be able to type ssh and your site’s name and go straight to your home lab. Here is what I have to say: don’t. Years of experience tell me this is a bad idea.

However, what you can do is SSH into the Oracle Cloud, then SSH into the Tailscale box. Your Oracle Cloud is your jump box now. It’s best to keep it that way for security. What’s amazing about Tailscale is if you have it on your PC, you can access your machines via the Tailscale IP address with SSH. If you don’t, just use the Oracle Cloud’s SSH.

Warnings

A CG-NATed home lab is much slower than a regular home lab. The reason why is you are going in and out of that Tailscale network over and over again. It slows things down. It gets much slower when you add the SSL. The first time you connect to it, it takes a good 10 seconds to load because it’s grabbing all of that information. So don’t use it for the following:

  • Gaming
  • Plex/Jellyfin
  • audiobooks

All of those take up large amounts of data. It’s not worth the effort. Your Plex will work locally inside your home network. You may need a DHCP box of some sort; other than that, you are good to go.

What can we learn as a person

While cutting my grass, I noticed that the grass was growing through the asphalt. A little dandelion. I like these flowers, as they make great tea. It was growing through that hard rock. While the others were growing in the grass. This little weed grew and became a beautiful yellow flower. In the plant world, if it didn’t make it through the rock, it would have died. Often times we see these “weeds” growing through these rocks, like concrete. I love seeing a dandelion growing through a concrete slab. It takes advantage of the cracks in the stone and shines.

Often times people face hardships and stop growing. These people don’t make it a habit to find a way around those hardships. Those systems that are in place to keep us locked down. For years women in the science community have been like this. They are beautiful dandelions who have brought so much to this world, but because of their physical gender, many of their discoveries were taken credit for by men. However, when you see one who gets the credit, they shine. The asphalt is the systems we are born into. The hardships we have to face. No one sees those hardships unless they look for them. It’s not part of human nature yet to look for them.

So, if you ever see someone and think, They should be farther along than they are, what hardships did they face, and how much of a dandelion are they? The same is true for those who are shining. There is a story behind everyone, and to explore that story is to find connection and community. With community we can find real joy. We are social creatures, and we all have our own unique stories. Maybe it’s time for us to share more of it with each other.

Additional Resources

Automate Windows 11 Upgrade

Automate Windows 11 Upgrade

Upgrading Windows 11 across multiple machines is one of those tasks that sounds simple—until you realize you need to manually download the ISO, mount it, and run the upgrade for every single computer. If you’re managing a fleet of devices, that’s a lot of clicking and waiting. Thankfully, PowerShell can help automate this process, saving IT admins from hours of repetitive work. So today, we will Automate Windows 11 Upgrade with PowerShell.

But before we jump in, there’s one crucial step: Microsoft requires you to manually generate the download link for the Windows 11 ISO. That’s right—no direct API calls or magic URLs here. You’ll need to visit the Microsoft website and grab the link yourself. Don’t worry, we’ll walk you through that part.

And hey, if you’re wondering why Microsoft makes you do this manually… well, let’s just say it’s like trying to convince a cat to use the expensive bed you bought instead of the random cardboard box it found in the corner. Some things just don’t make sense, but we roll with it anyway.

Alright, let’s dive in! First up: generating that all-important download link.

The Script

Write-Host "Go to: https://www.microsoft.com/en-us/software-download/windows11"
Write-Host "Select Windows 11 (multi-edition ISO for x64 devices)"
Write-Host "Click Download"
Write-Host "Select English (United States)"
Write-Host "Click Confirm"
Write-Host "Right Click '64-bit Download' and click 'Copy link'"

$DownloadURL = Read-Host "Enter the Windows 11 ISO download link (in quotes)"
$ComputerName = Read-Host "Enter the target Computer Name"

# Check if the computer is online
if ($null -ne (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)) {  
    
    # Start a remote PowerShell session
    Enter-PSSession -ComputerName $ComputerName  
    
    # Ensure C:\temp exists
    if (!(Test-Path C:\temp)) {New-Item -Path C:\ -Name temp -ItemType Directory -Force}  

    # Set download path
    $DownloadPath = "C:\temp\win11.iso"

    # Download Windows 11 ISO
    Invoke-WebRequest -Uri $DownloadURL -OutFile $DownloadPath  

    # Mount the ISO
    $DiskImage = Mount-DiskImage -ImagePath $DownloadPath -StorageType ISO -NoDriveLetter -PassThru  
    $ISOPath = (Get-Volume -DiskImage $DiskImage).UniqueId

    # Create a PSDrive for the mounted ISO
    New-PSDrive -Name ISOFile -PSProvider FileSystem -Root $ISOPath  
    Push-Location ISOFile:

    # Find and run Setup.exe with upgrade parameters
    $SetupExe = (Get-ChildItem | Where-Object {$_.Name -like "*Setup.exe*"}).FullName  
    $Arguments = "/auto upgrade /DynamicUpdate Disable /quiet /eula accept /noreboot"  
    Start-Process -Wait -FilePath $SetupExe -ArgumentList "$Arguments" -PassThru  

    # Clean up: Unmount ISO and remove PSDrive  
    Pop-Location  
    Remove-PSDrive ISOFile  
    Dismount-DiskImage -DevicePath $DiskImage.DevicePath  

    # Ask for a restart decision  
    $YN = Read-Host "Do you want to restart? (Y/N)"  
    if ($YN -like "*Y*") {Restart-Computer -Force}  
    elseif ($YN -like "*N*") {Write-Host "Ask the user to restart."}  
    else {Write-Host "Ok, whatever, ask the user to restart."}  

} else {  
    Write-Host "The target computer is not reachable. Check the network or hostname and try again."  
}

Step 1: Generate the Windows 11 ISO Download Link

Before we can automate the upgrade, we need the direct download link for the Windows 11 ISO. Microsoft doesn’t make this easy—there’s no simple API to fetch it. Instead, you have to manually grab the link from their website.

This step is non-negotiable because Microsoft generates a unique download link each time, which expires after 24 hours. So if you’re thinking, “Can’t I just reuse an old link?”—nope, Microsoft shut that door. But don’t worry, it’s a quick process:

How to Get the Windows 11 Download Link

  1. Go to the official Microsoft download page:
  2. Scroll down to ‘Download Windows 11 Disk Image (ISO)’
    • Select Windows 11 (multi-edition ISO for x64 devices) from the dropdown.
  3. Click ‘Download’ and select English (United States) as the language.
  4. Click ‘Confirm’—Microsoft will generate a download button.
  5. Right-click ‘64-bit Download’ and select ‘Copy link’ (This is the direct ISO link).

You’ll need this URL when running the PowerShell script, so paste it somewhere handy.

Now that we have the link, let’s move on to running the script!

Step 2: Running the PowerShell Script

Alright, you’ve got your Windows 11 ISO download link. Now it’s time to run the PowerShell script and start the upgrade. But before we do that, let’s talk about remote execution. This is part of the process to Automate Windows 11 Upgrade with PowerShell.

PowerShell remoting (aka WinRM) needs to be enabled on the target machine. If you’ve never set it up before, it’s kind of like getting a cat to sit still for a vet visit—it might resist at first, but once it’s done, life is easier.

Prerequisites for Running the Script

Make sure the following are true before running the script:

  • Your user account has admin privileges on both the local and remote machine.
  • WinRM (Windows Remote Management) is enabled on the target machine. Run this command on the remote PC to check:
winrm quickconfig

If WinRM isn’t enabled, you’ll need to set it up first.

  • PowerShell Execution Policy allows scripts to run. If needed, you can temporarily bypass restrictions with:
Set-ExecutionPolicy Bypass -Scope Process -Force

Running the Script

Once the prerequisites are in place, open PowerShell as Administrator on your local machine and run the script. When prompted:

  1. Paste the Windows 11 ISO download link (from Step 1).
  2. Enter the target computer’s name (the one you want to upgrade).

If all goes well, PowerShell will initiate a remote session, create a C:\temp folder, and start downloading the ISO to the remote machine.

Just like how a cat will eventually use the new bed if you keep putting treats in it, the script will do its job—as long as everything is set up correctly.

Next up: Downloading and Mounting the ISO!

Step 3: Downloading and Mounting the ISO

At this point, the PowerShell script is running, and the target computer is ready. Now comes the fun part—actually downloading and mounting the Windows 11 ISO.

If you’ve ever tried downloading a large file over a shaky network, you know it can be as frustrating as a cat deciding to sprint across the house at 3 AM for no reason. But don’t worry, the script handles it all automatically.

How the Script Handles the Download

Once you enter the download link and the computer name, the script:

  1. Creates a C:\temp folder (if it doesn’t already exist).
  2. Uses Invoke-WebRequest to download the ISO to C:\temp\win11.iso.

Here’s the key part of the script doing the work:

if (!(Test-Path C:\temp)) {New-Item -Path c:\ -Name temp -ItemType Directory -Force}  
$DownloadPath = "C:\temp\win11.iso"  
Invoke-WebRequest -Uri $DownloadURL -OutFile $DownloadPath

Mounting the ISO

Once the ISO is downloaded, PowerShell mounts it like a virtual disk, allowing access to the installation files.

$DiskImage = Mount-DiskImage -ImagePath $DownloadPath -StorageType ISO -NoDriveLetter -PassThru  
New-PSDrive -Name ISOFile -PSProvider FileSystem -Root (Get-Volume -DiskImage $DiskImage).UniqueId  
Push-Location ISOFile:

At this point, the Windows 11 setup files are accessible.

If you check File Explorer on the target computer, you should see a new virtual drive containing the ISO contents—like when a cat suddenly appears on your keyboard, except this time, it’s actually doing something useful.

Now that we have the ISO mounted, it’s time for the real action: starting the upgrade!

Step 4: Starting the Upgrade Process

Alright, the ISO is mounted, and we’re at the final stretch—actually running the Windows 11 upgrade. If everything has gone smoothly so far, congratulations! You’re officially ahead of the game.

Now, instead of manually clicking through the Windows setup (which is about as exciting as watching a cat stare at a wall for hours), PowerShell will automate the upgrade process using Setup.exe and a few command-line arguments.

Finding and Running Setup.exe

Since we mounted the ISO in the previous step, we now need to:

  1. Find Setup.exe inside the mounted ISO
  2. Run it with automation flags to start the upgrade silently

The script takes care of that with:

$FileList = Get-ChildItem  
$SetupExe = ($FileList | Where-Object {$_.name -like "*Setup.exe*"}).FullName  
$Arguments = "/auto upgrade /DynamicUpdate Disable /quiet /eula accept /noreboot"  
Start-Process -Wait -FilePath $SetupExe -ArgumentList "$Arguments" -PassThru 

Breaking Down the Command-Line Arguments

Here’s what each flag does when running Setup.exe:

  • /auto upgrade → Tells Windows to start an upgrade instead of a fresh install.
  • /DynamicUpdate Disable → Skips downloading the latest updates during the install (useful for speeding things up).
  • /quiet → Runs the installer in the background, so no annoying pop-ups.
  • /eula accept → Automatically accepts Microsoft’s End User License Agreement (because let’s be real, no one reads it).
  • /noreboot → Prevents an automatic restart so we can control when it happens.

What Happens Next?

Once this runs, the Windows 11 upgrade process kicks off in the background. There won’t be any flashy UI—just PowerShell doing its thing. You can check progress by looking at Task Manager on the target machine.

At this point, it’s like when a cat finally decides to nap on that expensive bed instead of the cardboard box—you’ve done all the hard work, and now it just has to finish on its own.

But there’s one last decision to make: When do we restart?

How are we feeling about Automate Windows 11 Upgrade with PowerShell so far?

Step 5: Restarting the Machine

At this point, the Windows 11 upgrade is in motion, but the installation won’t complete until the target machine restarts. Now, we could just force a reboot, but let’s be real—no one likes unexpected restarts (especially end users in the middle of something important).

So, instead of pulling the plug immediately, the script politely asks whether to restart now or later. Here’s how that works:

$YN = Read-Host "Do you want to restart"  

if ($YN -like "*Y*") {  
    Restart-Computer -Force  
} elseif ($YN -like "*N*") {  
    Write-Host "Ask the user to restart"  
} else {  
    Write-Host "Ok, whatever, ask the user to restart."  
}  

Breaking It Down

  • If the admin enters Y → The system restarts immediately.
  • If the admin enters N → A message reminds them to tell the user to restart manually.
  • If they enter anything else → The script shrugs and tells them to figure it out.

This gives IT teams a bit of flexibility, which is crucial in environments where timing matters—like avoiding a forced reboot during an important meeting (unless it’s for that one guy who never restarts his PC… then maybe it’s justified).

What Happens After Restart?

Once the machine reboots, Windows 11 will finish the upgrade process. The whole thing usually takes 30-90 minutes depending on the hardware. During this time, users will see the “Working on updates” screen—so if they call asking why their PC is taking forever, just tell them “It’s optimizing performance” (it sounds fancier than “it’s just installing”).

Final Thoughts

And that’s it! With this script, you can automate Windows 11 upgrades remotely with minimal effort. No more manual downloads, no more sitting through setup screens—just a smooth, scripted process. To Automate Windows 11 Upgrade with PowerShell makes life much easier.

Recap of the key steps:

  • Generate the ISO link manually from Microsoft’s website (because they make us).
  • Run the PowerShell script and provide the ISO link + target computer name.
  • Download and mount the ISO automatically.
  • Start the Windows 11 upgrade silently using Setup.exe.
  • Decide when to restart—now or later.

Now, go forth and upgrade with confidence! And if anything goes wrong, well… let’s just say this script is less stubborn than a cat, so it’s probably not the script’s fault.

What can we learn as a person?

Upgrading an operating system is a big change, but it’s the small steps that make it happen. You don’t just magically jump to Windows 11—first, you grab the ISO, then you run the script, then you mount the image, and finally, the upgrade takes place. One step at a time.

Turns out, our mental health works the same way.

A lot of us get caught up in the idea that improving our mood or reducing stress requires some huge effort—taking a long vacation, completely overhauling our routines, or mastering meditation overnight. But that’s just not how it works. Big upgrades don’t happen all at once.

Instead, try small upgrades for yourself, just like how we upgrade Windows in steps:

  • Clear out junk files → Declutter one small space
    • Just like a clean drive helps performance, tidying up one small area can help clear your mind.
  • Run a quick system check → Check in with yourself
    • Pause for a moment and ask: How am I feeling today? Just acknowledging your emotions can help.
  • Disable unnecessary background processes → Say “no” to one unnecessary thing
    • Reduce mental load by cutting out one thing that’s draining you—whether it’s skipping an unimportant meeting or ignoring a toxic group chat.
  • Reboot when needed → Take a short break
    • A quick restart helps a computer, and sometimes, five minutes away from your screen can work wonders for you too.

No Need for a Full Reinstall

You don’t need a full personality reboot or a total life upgrade to feel better. Small tweaks, small wins—they add up.

So while you’re waiting for that Windows 11 install to finish, maybe take just one small action for yourself. It doesn’t have to be big. Just enough to upgrade your mood one step at a time.

Zebra Kiosk Mode

Zebra Kiosk Mode

Last time we talked about how to get our Zebra scanners into Intune. Today we are going to talk about how to set this unit as a kiosk scanner with a web link and a store app. This setup will be in such a way that we control the wireless networks and access to the device all from one configuration policy. The configuration policy is where we will be making our Zebra Kiosk Mode.

Creating a web app

A web app is super easy to build out. Remember, the scanner should be able to access said app.

  1. Navigate to intune.microsoft.com
  2. On the left-hand side, click Apps
  3. Click Android
  4. Click the Add button.
  5. Under Select app type, we will click Web link, which is under Other.
  6. Then Click Select
  7. This is where you can edit properties.
    • Name: The web link name
    • Description: I like to put the address of the web link here and what it’s for. Some people don’t. It’s up to you.
    • Publisher: I put my company’s name, unless I know for sure who it is.
    • App URL: This is where you will put your link. For example. https://therandomadmin.com
    • Require a managed browser to open this link:
      • This is special as it will require you to have edge or another managed browser like zebra’s managed browser. In our case, this isn’t a needed feature and can cause more issues down the road.
      • Doing a managed browser would force the user into a single tab. This is great for some apps, but others not so much. So, if you want a lockdown on the tabs, this is the way to go, and you will have to make sure you set the system defaults to that browser instead of Chrome.
    • Category: That’s for you to choose
    • Show this as a featured app in the company portal: Once again, not really needed since these will be kiosk machines.
    • Information URL: If the site has an information URL, this is where it would go.
    • Privacy URL: Most websites have a privacy link; this is where you would put that.
    • Developer: Who built it? Maybe a link if you feel like it.
    • Owner: Who is the owner, once again, Maybe a link?
    • Notes: I don’t use this personally, but I have seen where people will put who all should have it.
    • Logo: A good logo for the site; now I have seen a 512×512 PNG file work best for this.
  8. Click Next
  9. Assign your groups
  10. Review and create.

That’s all it takes to make a web link. It’s nothing special.

Other Apps

Create Device Restriction Configuration

This is where we will be doing our Zebra Kiosk Mode. Based on our Microsoft Managed Home Screen, we will create a device restriction, and this app will give us unique controls over the device.

  1. Navigate to Intune.microsoft.com
  2. Navigate to Devices > Android > Configuration
  3. Create a new policy
    • Platform: Android Enterprise
    • Profile Type: Device Restrictions
    • Click Next
  4. Name the policy and give it a good description. Then hit next
  5. These are the settings I am using:
    • General
      • Default Permissions Policy (Work Profile Level) Auto Grant
      • System Update: Automatic
      • Skip first Use Hint: Enabled
      • Locate Device: Allow
      • System Error Warning: Allow
      • Enabled System Navigation Features: Home and overview buttons
      • System Notifications and Information: Show system notifications and information in device status bar

Device Experience

  1. Device Experience Type: Kiosk Mode
  2. Kiosk Mode: Multi App
  3. Custom app layout: Enabled
    • This is where we will place items on the screen. I like having the main web link and the intune app. It looks real nice with a 3×4
  4. Grid Size: 3 Columns x 4 rows
  5. Home Screen.
    • Here you can click each plus button and add the app you want, and it will show up on the machine.
  6. Lock Home Screen: Enabled
  7. App Notification Badges: Enabled
    • I enable these because it lets the end user know what’s happening with the device itself. This is important for updates and the like.
  8. Leave Kiosk Mode: Enabled
  9. Leave Kiosk Mode Code: Make a 4-6 digit pin.
  10. Set a custom URL background:
    • This background for the MC9300 is 480×800.
    • The image must be accessible from the network on its own. If it is not, then we will have issues.
  11. Shortcut to settings menu: Disabled
  12. Quick access to the debug menu: Enable
  13. Wi-fi Allow List
    • This is where you can put the SSID of the networks you want the scanner to connect to. If it’s not in this list, they will not be able to connect to it while in kiosk mode.
  14. Media Volume Controls: Enabled
    • I do this to allow them to control how loud the beeps are. Note that your DataWedge profile needs to be set to media to make this happen.
  15. Quick Access to device information: enabled
    • This bad boy has saved me so many times. It has the device’s serial number. The MC9300 serial numbers are printed on the back, but old eyes just can’t read it. So, having this information at the user’s fingertips really adds to troubleshooting.
  16. Everything else in device restrictions is default.

Users and Accounts

This area is set to block. What that does is it forces the users to only be the kiosk user.

  • Add users: Block
  • User can configure credentials: block
  • User removal: block
  • personal google account: block
  • Account changes: block.

We don’t want you to edit anything with this profile. Hand slap, please.

Customer Support Information

This is where you would place all the customer support information. Like your helpdesk number or emails. I like to have the contact for your IT admins at XYZ. The lock screen message is important because even though we didn’t set it here, if you tell the system to lock via Intune, this message will appear.

Groups and why it’s important

The next area is the groups. So, this is very important. You cannot have two device restriction policies that do kiosk items applied to the same machine! This is very important and can look very weird. So I’m going to give you a simple scenario for you to fully understand.

  • There are three policies.
    • Zebra_Default
      • Assigned Group: Zebra-MC9300-Default
        • Dynamic assignment of android zebra mc9300
    • Zebra_Redzone
      • Assigned Group: Zebra-RedZone
        • Static Assignment
    • Zebra_Bluezone
      • Assigned Group: Zebra-BlueZone
        • Static Assignment

If I have a scanner, and I assign it to group zebra-RedZone. It will get the red zone and the default. The default links the bluezone if it’s assigned to a policy. Thus, now it gets two policies and starts conflicts. So what you have to do for each policy is place all other groups, excluding your default group into the exclude assignment. So, if you want the redzone, place the zebra-redzone inside the zebra_redzone policy assignment and place zebra-bluezone in zebras_redzone exclusion assignment. The Zebra_default will need to have the two zone groups added to it’s exclusion list as well. This makes everyone happy.

Once you have everything assigned, click create. Add the scanner to your group that you want, and it will be applied. We have a few departments like this; by doing it this way, I can give out a passcode to an end user for troubleshooting and not effect any other departments. Plus, I can push out a password change for the kiosk without effecting other departments. I personally set each background to that department name. So they know when scanners float between departments. This has stopped so many fights.

What can we learn as a person?

There is a flow to things in this life. Whether it makes sense or not is a different story. The first time I set up these profiles, I was confused about why I kept getting just one icon. Instead of the four I selected. Then it locked down to the point where it was super Zebra Kiosk Mode and not a usable version. After tracking where things went, I finally figured it out. It was like watching a flow. Sometimes we have that in our lives. Things come up, and they leave you left in the what-happened mode.

I’ll give a great example from my life: car keys. I come home late the night before and place my keys in front of my bed instead of on my nightstand. The next morning, I wake up late, and I’m rushing around. I pull everything out of the nightstand, but the keys are missing. This makes me freak out. Rather than searching frantically, I’ve learned to focus on the events of the previous day. What did I do when I got home? I follow each step until I find where I put my keys. Most of the time, the cat knocked it off. He likes my chest in front of the bed. It’s always a good thing to stop and look at the flow. What’s happening, and where did things go wrong? I hope you go with your flow. You deserve it.

Additional Resources: