Skip to main content

Create-WorkloadFolder-v1.2

 

##########################################
# AUTHOR   : Ryan Mutschler
# DATE     : 3-19-2025
# EDIT     : 3-19-2025
# PURPOSE  : This script creates folders for Changes, Incidents, or Projects following the specified naming convention
#
# VERSION   : 1.0     (Initial release)
# VERSION   : 1.1     (URL subfolder creation)
# VERSION   : 1.2     (Communications subfolder creation)
##########################################

# Function to validate input is not empty
function Test-Input {
    param (
        [string]$userInput
    )
    
    if ([string]::IsNullOrWhiteSpace($userInput)) {
        return $false
    }
    return $true
}

# Get the base workload folder path by reading from the Windows Registry
try {
    # Get the Documents folder path from Registry
    $documentsPath = (Get-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Personal").Personal
    
    # Expand environment variables if they exist in the path
    $documentsPath = [System.Environment]::ExpandEnvironmentVariables($documentsPath)
    
    # Build the workload path
    $workloadBasePath = Join-Path -Path $documentsPath -ChildPath "Workload"
}
catch {
    Write-Host "Error accessing Registry. Falling back to default Documents location." -ForegroundColor Yellow
    $workloadBasePath = Join-Path -Path $env:USERPROFILE -ChildPath "Documents\Workload"
}

# Check if the workload folder exists, create it if not
if (-not (Test-Path -Path $workloadBasePath)) {
    Write-Host "Creating base Workload folder structure..."
    New-Item -Path $workloadBasePath -ItemType Directory | Out-Null
    
    # Create main category folders
    $categories = @("Changes", "Incidents", "Projects")
    foreach ($category in $categories) {
        $categoryPath = Join-Path -Path $workloadBasePath -ChildPath $category
        New-Item -Path $categoryPath -ItemType Directory | Out-Null
        
        # Create subcategories based on the parent folder
        $subcategories = @()
        switch ($category) {
            "Changes" {
                $subcategories = @(
                    "1. Discovery", 
                    "2. Testing", 
                    "3. Implementation", 
                    "4. Completed", 
                    "99. Uncategorized"
                )
            }
            "Incidents" {
                $subcategories = @(
                    "1. Investigation", 
                    "2. On Hold", 
                    "3. Resolved", 
                    "99. Uncategorized"
                )
            }
            "Projects" {
                $subcategories = @(
                    "1. Discovery", 
                    "2. Implementation", 
                    "3. Maintenance", 
                    "4. Decommissioned", 
                    "99. Uncategorized"
                )
            }
        }
        
        # Create each subcategory folder
        foreach ($subcategory in $subcategories) {
            $subcategoryPath = Join-Path -Path $categoryPath -ChildPath $subcategory
            New-Item -Path $subcategoryPath -ItemType Directory | Out-Null
        }
    }
    Write-Host "Base folder structure created successfully."
}

# Main script execution starts here
Write-Host "=== Workload Folder Creation Tool ===" -ForegroundColor Cyan
Write-Host "This script will create a new folder for your workload item."

# Prompt for workload type
$validSelection = $false
$workloadType = ""
$prefix = ""

while (-not $validSelection) {
    Write-Host "`nSelect the type of workload:" -ForegroundColor Yellow
    Write-Host "1. Change"
    Write-Host "2. Incident"
    Write-Host "3. Project"
    $selection = Read-Host "Enter your selection (1-3)"
    
    switch ($selection) {
        "1" {
            $workloadType = "Changes"
            $prefix = "RMCHG"
            $validSelection = $true
        }
        "2" {
            $workloadType = "Incidents"
            $prefix = "RMINC"
            $validSelection = $true
        }
        "3" {
            $workloadType = "Projects"
            $prefix = "RMPRJ"
            $validSelection = $true
        }
        default {
            Write-Host "Invalid selection. Please enter a number between 1 and 3." -ForegroundColor Red
        }
    }
}

# Get the workload name
$workloadName = ""
$validName = $false
while (-not $validName) {
    $workloadName = Read-Host "Enter the name of the $($workloadType.TrimEnd('s'))"
    
    if ([string]::IsNullOrWhiteSpace($workloadName)) {
        Write-Host "Name cannot be empty. Please enter a valid name." -ForegroundColor Red
    } else {
        $validName = $true
    }
}

# Get current date in the required format (YYMMdd)
$currentDate = Get-Date -Format "yyMMdd"

# Determine the next available sequence number
function Get-NextSequenceNumber {
    param (
        [string]$TargetPath,
        [string]$Prefix,
        [string]$Date
    )
    
    # Get all folders that match the pattern for today in the target path only
    $pattern = "$Prefix$Date*"
    $existingFolders = Get-ChildItem -Path $TargetPath -Directory | 
                      Where-Object { $_.Name -like $pattern }
    
    if ($existingFolders.Count -eq 0) {
        # No folders exist for today, start with 001
        return "001"
    }
    
    # Extract sequence numbers from existing folders
    $sequenceNumbers = @()
    foreach ($folder in $existingFolders) {
        if ($folder.Name -match "$Prefix$Date(\d{3})") {
            $sequenceNumbers += [int]$matches[1]
        }
    }
    
    if ($sequenceNumbers.Count -eq 0) {
        # No sequence numbers found, start with 001
        return "001"
    }
    
    # Find the highest sequence number and increment by 1
    $nextNumber = ($sequenceNumbers | Measure-Object -Maximum).Maximum + 1
    return $nextNumber.ToString("000")
}

# Get the next sequence number for the specific subcategory folder
$sequenceNumber = Get-NextSequenceNumber -TargetPath $subcategoryPath -Prefix $prefix -Date $currentDate

# Build the folder name with sequence number
$folderName = "$prefix$currentDate$sequenceNumber - $workloadName"

# Prompt for subcategory
Write-Host "`nSelect the subcategory:" -ForegroundColor Yellow
$subcategories = @()
switch ($workloadType) {
    "Changes" {
        Write-Host "1. Discovery"
        Write-Host "2. Testing"
        Write-Host "3. Implementation"
        Write-Host "4. Completed"
        Write-Host "5. Uncategorized"
        $subcategories = @(
            "1. Discovery", 
            "2. Testing", 
            "3. Implementation", 
            "4. Completed", 
            "99. Uncategorized"
        )
    }
    "Incidents" {
        Write-Host "1. Investigation"
        Write-Host "2. On Hold"
        Write-Host "3. Resolved"
        Write-Host "4. Uncategorized"
        $subcategories = @(
            "1. Investigation", 
            "2. On Hold", 
            "3. Resolved", 
            "99. Uncategorized"
        )
    }
    "Projects" {
        Write-Host "1. Discovery"
        Write-Host "2. Implementation"
        Write-Host "3. Maintenance"
        Write-Host "4. Decommissioned"
        Write-Host "5. Uncategorized"
        $subcategories = @(
            "1. Discovery", 
            "2. Implementation", 
            "3. Maintenance", 
            "4. Decommissioned", 
            "99. Uncategorized"
        )
    }
}

$validSubcategory = $false
$subcategoryPath = ""

while (-not $validSubcategory) {
    $maxOption = if ($workloadType -eq "Incidents") { 4 } else { 5 }
    $subcategorySelection = Read-Host "Enter your selection (1-$maxOption)"
    
    $subcategoryIndex = [int]$subcategorySelection - 1
    
    # Handle "Uncategorized" as special case
    if ($subcategorySelection -eq $maxOption.ToString()) {
        $subcategoryIndex = $subcategories.Count - 1
    }
    
    if ($subcategoryIndex -ge 0 -and $subcategoryIndex -lt $subcategories.Count) {
        $subcategoryPath = Join-Path -Path $workloadBasePath -ChildPath "$workloadType\$($subcategories[$subcategoryIndex])"
        $validSubcategory = $true
    }
    else {
        Write-Host "Invalid selection. Please enter a number between 1 and $maxOption." -ForegroundColor Red
    }
}

# Create the full path for the new folder
$newFolderPath = Join-Path -Path $subcategoryPath -ChildPath $folderName

# Check if the folder already exists
if (Test-Path -Path $newFolderPath) {
    Write-Host "`nWarning: A folder with this name already exists at this location." -ForegroundColor Yellow
    $confirmation = Read-Host "Would you like to create it anyway? (Y/N)"
    
    if ($confirmation.ToUpper() -ne "Y") {
        Write-Host "Operation cancelled by user." -ForegroundColor Red
        exit
    }
}

# Create the folder
try {
    # Create the main workload folder
    New-Item -Path $newFolderPath -ItemType Directory | Out-Null
    
    # Create subfolders within the new workload folder
    $urlFolderPath = Join-Path -Path $newFolderPath -ChildPath "URL"
    $commsFolderPath = Join-Path -Path $newFolderPath -ChildPath "Communications"
    
    New-Item -Path $urlFolderPath -ItemType Directory | Out-Null
    New-Item -Path $commsFolderPath -ItemType Directory | Out-Null
    
    Write-Host "`nSuccess! Created folder:" -ForegroundColor Green
    Write-Host $newFolderPath
    Write-Host "Subfolders created:"
    Write-Host "- URL: $urlFolderPath"
    Write-Host "- Communications: $commsFolderPath"
    
    # Open the folder in Explorer
    $openFolder = Read-Host "Would you like to open the folder now? (Y/N)"
    if ($openFolder.ToUpper() -eq "Y") {
        Invoke-Item -Path $newFolderPath
    }
}
catch {
    Write-Host "`nError creating folder: $_" -ForegroundColor Red
}

Version 0.1

Features:

    Base Folder Structure Setup:
      Creates the Workload folder structure if it doesn't already exist Establishes the correct hierarchy for Changes, Incidents, and Projects with appropriate subcategories User Interaction:
        Prompts the user to select the workload type (Change, Incident, or Project) Asks for the name of the workload item Lets the user select which subcategory the item belongs in Naming Convention:
          Automatically applies the correct prefix (RMCHG, RMINC, or RMPRJ) Includes the current date in YYMMDD format Follows the specified format: [PREFIX][DATE] - [NAME] Error Handling:
            Validates user input Checks if folders already exist Provides appropriate error messages Convenience Features:
              Option to open the newly created folder directly after creation Clear user interface with color-coded prompts

              Usage:

                Simply run the script in PowerShell Follow the prompts to select workload type, name, and subcategory The script will create the folder with the proper naming convention in the correct location
                Version 0.2

                Updated the script to retrieve the user's Documents folder location from the Windows Registry instead of assuming the default location. This change makes the script more robust by:

                  Reading the actual Documents folder path from the Registry key: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal Expanding any environment variables that might be in the path Including error handling that falls back to the default location if the Registry read fails for any reason

                  This modification ensures that the script will correctly place the Workload folder in the user's actual Documents folder location, even if they've customized it to be somewhere other than the default %USERPROFILE%\Documents.

                  The rest of the script's functionality remains unchanged - it will still create the proper folder structure according to the requirements and follow the specified naming convention.

                  Version 0.3

                  I've updated the script to include logic for sequential numbering of folders created on the same day. Here's how the new functionality works:

                    Sequential Numbering System:
                      Added a 3-digit sequence number (starting with "001") between the date and the folder name The format is now: [PREFIX][DATE][SEQUENCE] - [NAME] (e.g., "RMPRJ250319001 - Project Name") Automatic Sequence Detection:
                        The script searches all subfolders in the Workload structure for folders with the same prefix and date It identifies the highest existing sequence number and increments it by 1 for the new folder Implementation Details:
                          Created a new function Get-NextSequenceNumber that:
                            Searches recursively through all subfolders in the Workload structure Uses regex pattern matching to extract existing sequence numbers Determines the next available sequence number Formats the number with leading zeros (e.g., "001", "002", etc.) Handling Edge Cases:
                              If no folders exist for the current date, it starts with "001" If folders exist but don't follow the sequence numbering pattern, it still starts with "001" Handles multiple folders across different subcategories (e.g., if there's already a "001" in Discovery and a "002" in Testing, the next folder will be "003")

                              This enhancement ensures that each folder has a unique identifier, even if multiple folders are created on the same day with the same type and name.

                              Version 1.0

                              I've updated the script to only scan for existing folders within the specific subcategory folder where the new folder will be created, rather than searching the entire Workload structure. Here are the key changes:

                                Limited Scope for Sequence Number Search:
                                  Modified the Get-NextSequenceNumber function to only check within the target subcategory folder Removed the -Recurse parameter from the Get-ChildItem command to prevent searching through subfolders Changed the parameter name from BasePath to TargetPath to better reflect its purpose Sequence Number Generation:
                                    Now the sequence numbers will only be unique within each subcategory folder For example, you could have "RMPRJ250319001 - Test Project" in the "1. Discovery" folder and another "RMPRJ250319001 - Different Project" in the "2. Implementation" folder Function Call Update:
                                      Updated the function call to pass the specific subcategory path rather than the workload base path

                                      This change makes the sequence numbering more compartmentalized, ensuring that folders in different subcategories don't affect each other's numbering. The sequence will now only increment based on existing folders within the same subcategory.

                                      Version 1.1

                                      I've updated the script to automatically create a URL subfolder within each new workload folder. Here's what the script does now:

                                        When a new workload folder is created (e.g., "RMPRJ250319001 - Test Project"), the script will:
                                          First create the main workload folder as before Then create a subfolder named "URL" inside that workload folder The success message has been enhanced to show:
                                            The path of the main workload folder that was created Confirmation that the URL subfolder was created, along with its path When you choose to open the folder after creation, it will still open the main workload folder (not the URL subfolder directly)

                                            All other functionality remains the same. This enhancement ensures that each workload folder automatically has a URL subfolder ready for use, eliminating the need to manually create it later.

                                            Version 1.2

                                            I've updated the script to create both "URL" and "Communications" subfolders within each new workload folder. Here's what the script now includes:

                                              When a new workload folder is created, the script will automatically:
                                                Create the main workload folder (e.g., "RMPRJ250319001 - Test Project") Create a "URL" subfolder inside the workload folder Create a "Communications" subfolder inside the workload folder The success message has been improved to:
                                                  Show the path of the main workload folder List all created subfolders with their paths in a clear, bulleted format All other functionality remains the same, including:
                                                    The option to open the main folder in Explorer after creation Error handling for any issues during folder creation

                                                    This update ensures that each workload folder is created with a consistent internal structure, with both URL and Communications subfolders ready for use from the start.