Tag: #Automation

  • List Windows Version and Updates PowerShell Script

    This PowerShell script retrieves and displays the current Windows operating system name and version, including the major, minor, build, and revision numbers. It also lists all installed updates, sorted by installation date, with details such as the hotfix ID, description, and when each update was applied.

    Click to view script…
    # Get OS name
    $os = Get-CimInstance -ClassName Win32_OperatingSystem
    $osName = $os.Caption
    
    # Get OS version
    $osVersion = [System.Environment]::OSVersion.Version
    
    # Display OS name and version
    Write-Output "Operating System: $osName"
    Write-Output "Version: $($osVersion.Major).$($osVersion.Minor).$($osVersion.Build).$($osVersion.Revision)"
    
    # Get and display installed updates
    Write-Output "Installed Updates:"
    Get-HotFix | Sort-Object InstalledOn | Format-Table HotFixID, Description, InstalledOn
  • Interactive Sequential Folder Creator PowerShell Script

    This PowerShell script allows users to select a target directory either by entering a path directly or by navigating through subdirectories with a numbered menu. Once a directory is chosen, the script creates a series of sequentially numbered folders using a base name provided by the user.

    Click to view script…
    # Function: Recursively select a folder by listing subdirectories
    function Select-Folder($startingPath) {
        $currentPath = $startingPath
        while ($true) {
            Write-Host "`nCurrent Directory: $currentPath" -ForegroundColor Cyan
    
            # Get subdirectories (if any)
            $subDirs = Get-ChildItem -Path $currentPath -Directory -ErrorAction SilentlyContinue
    
            if (!$subDirs -or $subDirs.Count -eq 0) {
                Write-Host "No subdirectories found in $currentPath. Using this folder."
                break
            }
    
            # List options: 0 to select current folder, then list each subfolder with a number
            Write-Host "0: [Select this directory]"
            $index = 1
            foreach ($dir in $subDirs) {
                Write-Host ("{0}: {1}" -f $index, $dir.Name)
                $index++
            }
    
            $choice = Read-Host "Enter the number to navigate into a folder, or 0 to select the current directory"
    
            if (-not [int]::TryParse($choice, [ref]$null)) {
                Write-Host "Invalid input. Please enter a number."
                continue
            }
    
            $choice = [int]$choice
    
            if ($choice -eq 0) {
                break
            }
            elseif ($choice -ge 1 -and $choice -le $subDirs.Count) {
                $currentPath = $subDirs[$choice - 1].FullName
            }
            else {
                Write-Host "Invalid selection. Please try again."
            }
        }
        return $currentPath
    }
    
    # Prompt the user to choose the directory selection method
    Write-Host "Select target directory method:" -ForegroundColor Green
    Write-Host "1: Type the full directory path"
    Write-Host "2: Navigate directories using a numbered list"
    $method = Read-Host "Enter 1 or 2"
    
    if ($method -eq "1") {
        $targetDirectory = Read-Host "Enter the target directory path"
        if (-not (Test-Path $targetDirectory)) {
            Write-Host "Directory '$targetDirectory' does not exist. Exiting." -ForegroundColor Red
            exit
        }
    }
    elseif ($method -eq "2") {
        # Optionally allow the user to set a starting directory; default is C:\
        $startingPath = Read-Host "Enter starting directory path (press Enter for default C:\)"
        if ([string]::IsNullOrWhiteSpace($startingPath)) {
            $startingPath = "C:\"
        }
        if (-not (Test-Path $startingPath)) {
            Write-Host "The starting directory '$startingPath' does not exist. Exiting." -ForegroundColor Red
            exit
        }
        $targetDirectory = Select-Folder $startingPath
        Write-Host "Selected Directory: $targetDirectory" -ForegroundColor Green
    }
    else {
        Write-Host "Invalid selection. Exiting." -ForegroundColor Red
        exit
    }
    
    # Prompt user for the base folder name
    $baseName = Read-Host "Enter the base folder name for the folders to be created"
    
    # Prompt user for the number of folders to create
    $numFoldersInput = Read-Host "Enter the number of folders to create"
    if (-not [int]::TryParse($numFoldersInput, [ref]$null)) {
        Write-Host "The number of folders must be a valid integer. Exiting." -ForegroundColor Red
        exit
    }
    $numFolders = [int]$numFoldersInput
    
    # Create folders sequentially
    for ($i = 1; $i -le $numFolders; $i++) {
        # Construct folder name: "BaseName 1", "BaseName 2", etc.
        $folderName = "{0} {1}" -f $baseName, $i
        $folderPath = Join-Path $targetDirectory $folderName
    
        if (-not (Test-Path $folderPath)) {
            New-Item -Path $folderPath -ItemType Directory | Out-Null
            Write-Host "Created folder: $folderPath" -ForegroundColor Yellow
        }
        else {
            Write-Host "Folder already exists: $folderPath" -ForegroundColor DarkYellow
        }
    }
  • Installed Applications Info PowerShell Script

    This PowerShell script scans the Windows registry for installed applications, retrieving key details such as application name, version number, publisher, and installation date. It then displays the information in a neatly formatted table, making it easy to audit and manage software installations on your system.

    Click to view script…
    # Define registry paths for 64-bit and 32-bit applications
    $registryPaths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
        "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
    )
    
    # Retrieve applications from the registry
    $installedApps = foreach ($path in $registryPaths) {
        Get-ItemProperty -Path $path -ErrorAction SilentlyContinue |
            Where-Object { $_.DisplayName -and $_.DisplayVersion }
    }
    
    # Display the results in a formatted table
    $installedApps |
        Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
        Sort-Object DisplayName |
        Format-Table -AutoSize
  • Smart Finder Tabs Launcher for macOS AppleScript

    This AppleScript streamlines your Finder workspace by checking for an existing Finder window and reusing it to open specified folders as individual tabs, thereby avoiding duplicate windows or tabs. Customize the folders by editing the definitions at the top of the script.

    The folder paths are defined near the beginning of the script. For example, you can customize the following lines to change which folders open:

    set docsFolder to (path to documents folder)
    set desktopFolder to (path to desktop folder)
    set downloadsFolder to (path to downloads folder)


    Simply modify these variables to point to your desired folder paths.

    Click to view script…
    -- Title: Finder Tabs Organizer
    -- Description:
    -- This AppleScript opens designated folders as tabs in Finder
    -- Customize the folders to open by modifying the folder definitions below.
    
    -- Handler to open a new tab for a given folder
    on openNewTabWithFolder(theFolder)
        tell application "System Events"
            keystroke "t" using {command down} -- simulate Command+T to open a new tab
        end tell
        delay 0.5
        tell application "Finder"
            set target of front Finder window to theFolder
        end tell
    end openNewTabWithFolder
    
    -- Define the folders to open
    set docsFolder to (path to documents folder)
    set desktopFolder to (path to desktop folder)
    set downloadsFolder to (path to downloads folder)
    
    tell application "Finder"
        activate
        if (count of Finder windows) > 0 then
            -- Use the existing Finder window and set its target to Documents
            set target of front Finder window to docsFolder
        else
            -- No window exists, so open a new window for Documents
            open docsFolder
        end if
    end tell
    
    delay 0.5
    
    -- Open additional tabs for the other folders.
    openNewTabWithFolder(desktopFolder)
    openNewTabWithFolder(downloadsFolder)

  • macOS User Login and Uptime Report Bash Script

    This script provides system administrators with a clear overview of the system’s current uptime and detailed last login information for human user accounts (UID ≥ 500). It displays key details such as the terminal, login date, login time, and session status for each account.

    Click to view script…
    #!/bin/bash
    # Title: Detailed macOS User Last Login Checker with System Uptime
    # Description:
    # This script lists human user accounts (UID ≥ 500) on macOS and displays detailed information about their last login session.
    # It also shows the current system uptime at the top.
    #
    # The output includes:
    #   - System Uptime: How long the machine has been running since the last boot.
    #   - Username     : The account name.
    #   - Terminal     : The terminal device used during login.
    #   - Login Date   : The date of the login (Day Month Date).
    #   - Login Time   : The time when the login occurred.
    #   - Login Status : Indicates if the session is still active or has ended.
    #
    # Note: "Never logged in" is shown if no login record exists.
    #
    # Retrieve and display system uptime
    systemUptime=$(uptime)
    echo "System Uptime: $systemUptime"
    echo ""
    
    # Print header for the login details
    echo "Username | Terminal | Login Date       | Login Time | Login Status"
    echo "---------------------------------------------------------------------"
    
    # List users with their UniqueIDs and process each one.
    dscl . -list /Users UniqueID | while read username uid; do
        if [ "$uid" -ge 500 ]; then
            # Retrieve the most recent login record for the user
            loginInfo=$(last -1 "$username" | head -n 1)
            
            # Check if there is a valid login record
            if echo "$loginInfo" | grep -q "wtmp begins"; then
                echo "$username |    -     |       -        |     -    | Never logged in"
            else
                # Parse the login record:
                #   Field 1: Username (redundant here)
                #   Field 2: Terminal (e.g., ttys000)
                #   Fields 3-5: Login Date (e.g., "Mon Feb 17")
                #   Field 6: Login Time (e.g., "05:44")
                #   Fields 7+: Login Status (e.g., "still logged in" or the session end time)
                terminal=$(echo "$loginInfo" | awk '{print $2}')
                login_date=$(echo "$loginInfo" | awk '{print $3, $4, $5}')
                login_time=$(echo "$loginInfo" | awk '{print $6}')
                login_status=$(echo "$loginInfo" | cut -d' ' -f7-)
                
                # Output the parsed details in a table-like format
                printf "%-8s | %-8s | %-16s | %-10s | %s\n" "$username" "$terminal" "$login_date" "$login_time" "$login_status"
            fi
        fi
    done
    
    # Legend:
    #   System Uptime - How long the system has been running since the last boot.
    #   Username      - The account name.
    #   Terminal      - The terminal device used during login.
    #   Login Date    - The date of the login (Day Month Date).
    #   Login Time    - The time of the login.
    #   Login Status  - The current status of the login session.
  • Enhanced macOS User Account Details Bash Script

    This Bash script retrieves and displays detailed information for all human user accounts (UID ≥ 500) on macOS, including the username, UID, admin privileges, full name, home directory, and default shell. It provides a clear and organized summary that is useful for system administrators to review and manage user configurations.

    Click to view script…
    #!/bin/bash
    # This script lists user accounts (UID >= 500) and shows additional details:
    # Username, UID, Admin Privileges (true/false), Full Name, Home Directory, and Shell
    
    # Print header for clarity
    echo "Username : UID : Has Admin Privileges : Full Name : Home Directory : Shell"
    
    # List all users with their UniqueID and process each line
    dscl . -list /Users UniqueID | while read username uid; do
        # Only process accounts with UID >= 500 (typically non-system, human user accounts)
        if [ "$uid" -ge 500 ]; then
            # Check if the user belongs to the 'admin' group
            if id -Gn "$username" 2>/dev/null | grep -qw "admin"; then
                adminFlag="true"
            else
                adminFlag="false"
            fi
    
            # Get the user's full name (if set). The command outputs a line like "RealName: John Doe"
            fullName=$(dscl . -read /Users/"$username" RealName 2>/dev/null | sed 's/RealName: //')
            
            # Get the user's home directory
            homeDir=$(dscl . -read /Users/"$username" NFSHomeDirectory 2>/dev/null | sed 's/NFSHomeDirectory: //')
            
            # Get the user's default shell
            shell=$(dscl . -read /Users/"$username" UserShell 2>/dev/null | sed 's/UserShell: //')
            
            # Output the collected information in a clear, colon-separated format
            echo "$username : $uid : $adminFlag : $fullName : $homeDir : $shell"
        fi
    done
  • Scheduled URL Launcher AppleScript

    This AppleScript prompts the user to input multiple URLs and offers a choice to open them immediately or after a countdown timer. For immediate launches, it confirms the URLs before opening, while for countdown mode it notifies the user that the countdown has started and then provides a final confirmation after the URLs have been opened.

    Click to view script…
    -- Create a large default text field by including multiple line breaks
    set multiLineDefault to return & return & return & return
    
    -- Prompt the user for a list of URLs (one URL per line)
    set urlInput to text returned of (display dialog "Enter list of URLs (one per line):" default answer multiLineDefault)
    
    -- Split the input into a list of lines
    set urlList to paragraphs of urlInput
    
    -- Ask the user if they want to open the URLs now or after a countdown
    set schedulingOption to button returned of (display dialog "Choose when to open the URLs:" buttons {"Now", "Countdown"} default button "Now")
    
    if schedulingOption is "Now" then
    	-- Build a confirmation message listing the URLs to be opened immediately
    	set confirmDialogText to "The following URLs will be opened now:" & return & return
    	repeat with aURL in urlList
    		set trimmedURL to trimWhitespace(aURL)
    		if trimmedURL is not "" then
    			-- Prepend protocol if missing
    			if (trimmedURL does not start with "http://") and (trimmedURL does not start with "https://") then
    				set trimmedURL to "https://" & trimmedURL
    			end if
    			set confirmDialogText to confirmDialogText & trimmedURL & return
    		end if
    	end repeat
    	
    	-- Show confirmation dialog before launching
    	set confirmResponse to button returned of (display dialog confirmDialogText buttons {"Cancel", "Open Now"} default button "Open Now")
    	if confirmResponse is "Cancel" then return
    	
    	-- Open URLs immediately
    	repeat with aURL in urlList
    		set trimmedURL to trimWhitespace(aURL)
    		if trimmedURL is not "" then
    			if (trimmedURL does not start with "http://") and (trimmedURL does not start with "https://") then
    				set trimmedURL to "https://" & trimmedURL
    			end if
    			open location trimmedURL
    		end if
    	end repeat
    	
    else if schedulingOption is "Countdown" then
    	-- Prompt for countdown seconds
    	set countdownInput to text returned of (display dialog "Enter countdown time in seconds:" default answer "10")
    	try
    		set countdownSeconds to countdownInput as integer
    	on error
    		display dialog "Invalid number. Exiting." buttons {"OK"} default button "OK"
    		return
    	end try
    	
    	-- Notify the user that the countdown is starting
    	display dialog "Countdown started for " & countdownSeconds & " seconds. The URLs will open automatically afterwards." buttons {"OK"} default button "OK"
    	
    	-- Delay for the specified number of seconds
    	delay countdownSeconds
    	
    	-- Open URLs after the delay
    	repeat with aURL in urlList
    		set trimmedURL to trimWhitespace(aURL)
    		if trimmedURL is not "" then
    			if (trimmedURL does not start with "http://") and (trimmedURL does not start with "https://") then
    				set trimmedURL to "https://" & trimmedURL
    			end if
    			open location trimmedURL
    		end if
    	end repeat
    	
    	-- Build a final confirmation message listing the URLs that were opened
    	set finalConfirmDialogText to "The following URLs have been opened:" & return & return
    	repeat with aURL in urlList
    		set trimmedURL to trimWhitespace(aURL)
    		if trimmedURL is not "" then
    			if (trimmedURL does not start with "http://") and (trimmedURL does not start with "https://") then
    				set trimmedURL to "https://" & trimmedURL
    			end if
    			set finalConfirmDialogText to finalConfirmDialogText & trimmedURL & return
    		end if
    	end repeat
    	
    	-- Show the final confirmation dialog
    	display dialog finalConfirmDialogText buttons {"OK"} default button "OK"
    end if
    
    --------------------------------------------------------------------------------
    -- Helper Handler: trimWhitespace
    -- Removes leading and trailing whitespace from a string
    --------------------------------------------------------------------------------
    on trimWhitespace(theText)
    	set AppleScript's text item delimiters to {" ", tab, return, linefeed}
    	set textItems to text items of theText
    	set AppleScript's text item delimiters to space
    	set trimmed to textItems as text
    	set AppleScript's text item delimiters to ""
    	return trimmed
    end trimWhitespace
  • Advanced Password Strength Checker Python Script

    This script assesses the security of any given password by checking its length, character diversity, and commonality, then provides a strength score along with detailed improvement suggestions if needed. It also explains why a password is strong when it meets all the criteria.

    Click to view script…
    #!/usr/bin/env python3
    import re
    import getpass
    
    def evaluate_password_strength(password):
        """
        Evaluate the password strength based on five criteria:
        - At least 8 characters long
        - Contains an uppercase letter
        - Contains a lowercase letter
        - Contains a digit
        - Contains a special character
        Additionally, the function checks for commonly used (and easily guessable) passwords.
        Returns a tuple containing the strength rating, score, and suggestions for improvement.
        """
        score = 0
        suggestions = []
    
        # Check for common (easily guessable) passwords
        common_passwords = {
            "password", "12345", "123456", "qwerty", "abc123",
            "111111", "123123", "password1", "letmein", "admin"
        }
        if password.lower() in common_passwords:
            suggestions.append("Your password is among the most commonly used and easily guessable passwords. Please choose a more unique password.")
            # Override the score for common passwords
            score = 0
            # Early return the evaluation since it's a significant security risk.
            return "Weak", score, suggestions
    
        # Check for minimum length
        if len(password) >= 8:
            score += 1
        else:
            suggestions.append("Make sure your password is at least 8 characters long.")
    
        # Check for uppercase letters
        if re.search(r'[A-Z]', password):
            score += 1
        else:
            suggestions.append("Include at least one uppercase letter.")
    
        # Check for lowercase letters
        if re.search(r'[a-z]', password):
            score += 1
        else:
            suggestions.append("Include at least one lowercase letter.")
    
        # Check for digits
        if re.search(r'\d', password):
            score += 1
        else:
            suggestions.append("Include at least one digit.")
    
        # Check for special characters
        if re.search(r'[\W_]', password):
            score += 1
        else:
            suggestions.append("Include at least one special character.")
    
        # Determine strength rating based on the score
        if score <= 2:
            strength = "Weak"
        elif score in [3, 4]:
            strength = "Moderate"
        else:
            strength = "Strong"
    
        return strength, score, suggestions
    
    def main():
        print("Password Strength Checker")
        # Using getpass to hide input for privacy; replace with input() if needed.
        password = getpass.getpass("Enter a password to evaluate: ")
        
        strength, score, suggestions = evaluate_password_strength(password)
        
        print(f"\nPassword Strength: {strength}")
        print(f"Score: {score} out of 5")
        
        if score == 5:
            print("\nExplanation: This password is strong because it meets all the required criteria: it is at least 8 characters long, includes both uppercase and lowercase letters, contains at least one digit, and has at least one special character.")
        elif suggestions:
            print("\nSuggestions for improvement:")
            for suggestion in suggestions:
                print(f" - {suggestion}")
    
    if __name__ == '__main__':
        main()
  • Universal Age & Birth Date Calculator Python Script

    This script calculates an age in years, months, and days from a given date of birth or determines an approximate birth date based on an exact age input.

    The script utilizes the python-dateutil library, which extends Python’s standard datetime module by offering the relativedelta class for sophisticated date arithmetic; install it using pip3 install python-dateutil if it’s not already available.

    Click to view script…
    #!/usr/bin/env python3
    from datetime import datetime
    try:
        from dateutil.relativedelta import relativedelta
    except ImportError:
        print("This script requires the 'python-dateutil' module. Install it via 'pip3 install python-dateutil'")
        exit(1)
    
    def calculate_age(birth_date, current_date):
        """Calculate the difference between two dates as (years, months, days) using relativedelta."""
        delta = relativedelta(current_date, birth_date)
        return delta.years, delta.months, delta.days
    
    def main():
        print("Select an option:")
        print("1. Calculate an age from a date of birth")
        print("2. Calculate a birth date from an exact age")
        choice = input("Enter 1 or 2: ").strip()
        
        today = datetime.today()
        
        if choice == "1":
            dob_str = input("Enter a date of birth (YYYY-MM-DD): ").strip()
            try:
                birth_date = datetime.strptime(dob_str, "%Y-%m-%d")
            except ValueError:
                print("Invalid date format. Please use YYYY-MM-DD.")
                exit(1)
            
            years, months, days = calculate_age(birth_date, today)
            print(f"Calculated age: {years} years, {months} months, and {days} days.")
        
        elif choice == "2":
            print("Enter an exact age as three numbers separated by spaces.")
            print("For example, if the age is 25 years, 4 months, and 15 days, type: 25 4 15")
            age_input = input("Exact age (years months days): ").strip()
            parts = age_input.split()
            if len(parts) != 3:
                print("Invalid input. Please enter three integers separated by spaces.")
                exit(1)
            try:
                years = int(parts[0])
                months = int(parts[1])
                days = int(parts[2])
            except ValueError:
                print("Invalid input. Please ensure you enter numbers for years, months, and days.")
                exit(1)
            
            birth_date = today - relativedelta(years=years, months=months, days=days)
            print("Calculated birth date is approximately:", birth_date.strftime("%Y-%m-%d"))
        
        else:
            print("Invalid option selected.")
    
    if __name__ == '__main__':
        main()
  • Unique Entry Filter Python Script

    This script prompts the user to enter a comma-separated list of strings, then processes the input by trimming whitespace and converting entries to lowercase for case-insensitive duplicate checking. It finally outputs a comma-separated list of unique entries, preserving the order of their first appearance.

    Click to view script…
    #!/usr/bin/env python3
    
    def remove_duplicates(input_string):
        # Split the input string by commas and remove any extra spaces
        items = [item.strip() for item in input_string.split(',')]
        unique_items = []
        seen = set()
    
        for item in items:
            # Convert to lowercase for case-insensitive comparison
            if item.lower() not in seen:
                seen.add(item.lower())
                unique_items.append(item)
        return unique_items
    
    if __name__ == '__main__':
        user_input = input("Enter a comma-separated list of strings: ")
        unique = remove_duplicates(user_input)
        print("Unique entries:", ", ".join(unique))