Functions/GenXdev.AI.ComfyUI/Set-ComfyUIModelPath.ps1
<##############################################################################
Part of PowerShell module : GenXdev.AI.ComfyUI Original cmdlet filename : Set-ComfyUIModelPath.ps1 Original author : René Vaessen / GenXdev Version : 1.300.2025 ################################################################################ Copyright (c) René Vaessen / GenXdev Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ################################################################################> ############################################################################### <# .SYNOPSIS Adds a custom model path to ComfyUI's extra_model_paths.yaml configuration .DESCRIPTION Configures ComfyUI to use an additional custom path for model storage alongside the default ComfyUI models directory. This function creates or updates the 'custom' section in the extra_model_paths.yaml file, allowing ComfyUI to find models in additional locations without affecting the default model discovery. The function handles both creating new configuration files and updating existing ones, ensuring that the custom model path is properly configured as a supplementary model source. Can also clear the custom configuration when using the -Clear parameter. This does NOT replace ComfyUI's default model paths - it adds an additional location where ComfyUI will search for models, VAEs, LoRAs, etc. .PARAMETER ModelPath The base path to add as an additional model directory. This should be the root directory that contains subdirectories like checkpoints/, vae/, loras/, etc. ComfyUI will search this location IN ADDITION to its default model directories. For example, if you have models organized as: E:\MyModels\checkpoints\ E:\MyModels\vae\ E:\MyModels\loras\ Then pass "E:\MyModels" as the ModelPath. .PARAMETER Clear Removes the custom section from the extra_model_paths.yaml configuration file. .PARAMETER Monitor The monitor to use, 0 = default, -1 is discard .PARAMETER NoBorders Removes the borders of the window .PARAMETER Width The initial width of the window .PARAMETER Height The initial height of the window .PARAMETER X The initial X position of the window .PARAMETER Y The initial Y position of the window .PARAMETER KeysToSend Array of keys to send to the ComfyUI window after ready .PARAMETER SendKeyDelayMilliSeconds Delay in milliseconds between key send operations .PARAMETER Timeout Timeout in seconds to wait for ComfyUI server readiness .PARAMETER Left Place window on the left side of the screen .PARAMETER Right Place window on the right side of the screen .PARAMETER Top Place window on the top side of the screen .PARAMETER Bottom Place window on the bottom side of the screen .PARAMETER Centered Place window in the center of the screen .PARAMETER FullScreen Sends F11 to the window .PARAMETER RestoreFocus Restore PowerShell window focus .PARAMETER SideBySide Position windows side by side .PARAMETER FocusWindow Focus the window after opening .PARAMETER SetForeground Set the window to foreground after opening .PARAMETER Maximize Maximize the window after positioning .PARAMETER SetRestored Restore the window to normal state after positioning .PARAMETER SendKeyEscape Escape control characters and modifiers when sending keys .PARAMETER SendKeyHoldKeyboardFocus Hold keyboard focus on target window when sending keys .PARAMETER SendKeyUseShiftEnter Use Shift+Enter instead of Enter when sending keys .PARAMETER ShowWindow Show the ComfyUI window during initialization process .PARAMETER Force Force stop any existing ComfyUI process before starting a new one .PARAMETER MoveModels Move models from old path to new path when changing model path .EXAMPLE Set-ComfyUIModelPath -ModelPath "E:\MyModels" Adds E:\MyModels as an additional model search path. ComfyUI will search for: - Checkpoints in E:\MyModels\checkpoints\ - VAEs in E:\MyModels\vae\ - LoRAs in E:\MyModels\loras\ - Plus all the default ComfyUI model directories .EXAMPLE Set-ComfyUIModelPath "D:\StableDiffusionModels" Adds D:\StableDiffusionModels as a supplementary model path alongside ComfyUI's default model locations. Models should be organized in subdirectories: D:\StableDiffusionModels\checkpoints\ D:\StableDiffusionModels\vae\ etc. .EXAMPLE Set-ComfyUIModelPath -Clear Removes the custom model path configuration from ComfyUI. #> function Set-ComfyUIModelPath { [CmdletBinding(DefaultParameterSetName = 'SetPath')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] param( ############################################################################### [Parameter( Mandatory = $true, Position = 0, ParameterSetName = 'SetPath', HelpMessage = "The base path to set as the model directory" )] [ValidateNotNullOrEmpty()] [string] $ModelPath, ############################################################################### [Parameter( Mandatory = $true, ParameterSetName = 'Clear', HelpMessage = "Remove the custom model path configuration" )] [switch] $Clear, ############################################################################### [Parameter( Position = 1, Mandatory = $false, HelpMessage = 'The monitor to use, 0 = default, -1 is discard' )] [Alias('m', 'mon')] [int] $Monitor = -2, ############################################################################### [Parameter( Position = 2, Mandatory = $false, HelpMessage = 'The initial width of the window' )] [int] $Width, ############################################################################### [Parameter( Position = 3, Mandatory = $false, HelpMessage = 'The initial height of the window' )] [int] $Height, ############################################################################### [Parameter( Position = 4, Mandatory = $false, HelpMessage = 'The initial X position of the window' )] [int] $X, ############################################################################### [Parameter( Position = 5, Mandatory = $false, HelpMessage = 'The initial Y position of the window' )] [int] $Y, ############################################################################### [Parameter( Position = 6, Mandatory = $false, HelpMessage = 'Array of keys to send to the ComfyUI window after ready' )] [string[]] $KeysToSend, ############################################################################### [Parameter( Position = 7, Mandatory = $false, HelpMessage = 'Delay in milliseconds between key send operations' )] [Alias('DelayMilliSeconds')] [int] $SendKeyDelayMilliSeconds, ############################################################################### [Parameter( Position = 8, Mandatory = $false, HelpMessage = 'Timeout in seconds to wait for ComfyUI server readiness' )] [int] $Timeout = 600, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Removes the borders of the window' )] [Alias('nb')] [switch] $NoBorders, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place window on the left side of the screen' )] [switch] $Left, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place window on the right side of the screen' )] [switch] $Right, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place window on the top side of the screen' )] [switch] $Top, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place window on the bottom side of the screen' )] [switch] $Bottom, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place window in the center of the screen' )] [switch] $Centered, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Sends F11 to the window' )] [switch] $FullScreen, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Restore PowerShell window focus' )] [switch] $RestoreFocus, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Position windows side by side' )] [switch] $SideBySide, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Focus the window after opening' )] [switch] $FocusWindow, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Set the window to foreground after opening' )] [switch] $SetForeground, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Maximize the window after positioning' )] [switch] $Maximize, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = 'Restore the window to normal state after positioning' )] [switch] $SetRestored, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Escape control characters and modifiers when sending keys' )] [switch] $SendKeyEscape, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Hold keyboard focus on target window when sending keys' )] [switch] $SendKeyHoldKeyboardFocus, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Use Shift+Enter instead of Enter when sending keys' )] [switch] $SendKeyUseShiftEnter, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Show the ComfyUI window during initialization process' )] [switch] $ShowWindow, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Force stop any existing ComfyUI process before starting a new one' )] [switch] $Force, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Move models from old path to new path when changing model path' )] [switch] $MoveModels ############################################################################### ) begin { # get the current configured model path $current = GenXdev.AI\Get-ComfyUIModelPath # only process model path expansion when not clearing if (-not $Clear) { # expand the model path to full path $modelPathExpanded = GenXdev.FileSystem\Expand-Path $ModelPath # check if the path is already configured if ($current -eq $modelPathExpanded) { Microsoft.PowerShell.Utility\Write-Verbose ( "The specified model path is already configured: " + "${modelPathExpanded}" ) return } # move existing models if requested and source path exists if ($MoveModels -and (Microsoft.PowerShell.Management\Test-Path -LiteralPath $current)) { # copy models from old to new location using robocopy GenXdev.FileSystem\Start-RoboCopy "${current}\*" ( GenXdev.FileSystem\Expand-Path "${modelPathExpanded}\" ` -CreateDirectory ) -Move } } # define the yaml configuration file path $yamlPath = Microsoft.PowerShell.Management\Join-Path ` $env:LOCALAPPDATA ( "Programs\@comfyorgcomfyui-electron\resources\ComfyUI\" + "extra_model_paths.yaml" ) # ensure the yaml directory structure exists $yamlDir = [System.IO.Path]::GetDirectoryName($yamlPath) if (-not [System.IO.Directory]::Exists($yamlDir)) { $null = [System.IO.Directory]::CreateDirectory($yamlDir) } # check if comfyui is currently running $wasRunning = $false if (-not $Clear) { $currentExpanded = GenXdev.FileSystem\Expand-Path $current if ($modelPathExpanded -ne $currentExpanded) { $wasRunning = Microsoft.PowerShell.Management\Get-Process ` -Name "ComfyUI" ` -ErrorAction SilentlyContinue # stop comfyui if it's running to apply changes if ($wasRunning) { GenXdev.AI\Stop-ComfyUI } } } } process { # read existing yaml content or initialize empty string $yamlContent = if ([System.IO.File]::Exists($yamlPath)) { [System.IO.File]::ReadAllText($yamlPath) } else { "" } if ($Clear) { # remove custom section if it exists in the yaml if ($yamlContent -match "custom:") { # remove the entire custom section including sub-properties $yamlContent = $yamlContent -replace ( "(?ms)^custom:.*?(?=^[a-zA-Z_]|\z)" ), "" # clean up any excessive newlines $yamlContent = $yamlContent -replace "\r?\n\r?\n+", "`r`n`r`n" $yamlContent = $yamlContent.Trim() # delete file if content is now empty if ([string]::IsNullOrWhiteSpace($yamlContent)) { if ([System.IO.File]::Exists($yamlPath)) { [System.IO.File]::Delete($yamlPath) } Microsoft.PowerShell.Utility\Write-Verbose ( "Removed custom section and deleted empty " + "extra_model_paths.yaml" ) } else { [System.IO.File]::WriteAllText($yamlPath, $yamlContent) Microsoft.PowerShell.Utility\Write-Verbose ( "Removed custom section from extra_model_paths.yaml" ) } } else { Microsoft.PowerShell.Utility\Write-Verbose ( "No custom section found in extra_model_paths.yaml" ) } } else { # create the custom section yaml configuration $customSection = ( "custom:`n" + " base_path: ${modelPathExpanded}`n" + " checkpoints: checkpoints/`n" + " vae: vae/`n" + " loras: loras/`n" + " upscale_models: upscale_models/`n" + " embeddings: embeddings/`n" + " controlnet: controlnet/" ) if ($yamlContent -notmatch "custom:") { # append custom section to existing content $yamlContent += "`n${customSection}" [System.IO.File]::WriteAllText($yamlPath, $yamlContent) Microsoft.PowerShell.Utility\Write-Verbose ( "Added custom model path to extra_model_paths.yaml: " + "${modelPathExpanded}" ) } else { # update base_path in existing custom section $yamlContent = $yamlContent -replace ( "(?<=custom:\n\s*)base_path:\s*.+" ), "base_path: ${modelPathExpanded}" [System.IO.File]::WriteAllText($yamlPath, $yamlContent) Microsoft.PowerShell.Utility\Write-Verbose ( "Updated existing custom model path in " + "extra_model_paths.yaml: ${modelPathExpanded}" ) | Microsoft.PowerShell.Core\ForEach-Object fulln} } } end { # restart comfyui if it was running before the change if ($wasRunning) { $params = GenXdev.FileSystem\Copy-IdenticalParamValues ` -BoundParameters $PSBoundParameters ` -FunctionName "GenXdev.AI\EnsureComfyUI" GenXdev.AI\EnsureComfyUI @params } } } ############################################################################### |