diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..3ae40f1
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,54 @@
+# Security Policy
+
+## Supported Versions
+
+This project is a collection of PowerShell scripts.
+We aim to support the latest PowerShell7.x and Windows PowerShell5.1 runtimes.
+Security fixes will be applied to the `main` branch and released as soon as practical.
+
+| Version | Supported |
+| ------- | ------------------ |
+| 1.0.x | :white_check_mark: |
+| 0.1.x | :x: |
+
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability, please report it privately so we can investigate and fix it before public disclosure.
+
+Preferred reporting methods:
+
+- Use GitHub's Security Advisories for this repository (recommended) so the maintainers can coordinate a fix and private disclosure. See: https://docs.github.com/en/code-security/security-advisories
+- If GitHub Security Advisories are not available for you, open a private communication to the repository maintainers (for example an email to the project maintainer) if such contact is published in the repository. Do not post security-sensitive information in public issues or PRs.
+
+If you must use a public channel initially, avoid including exploit code or detailed reproduction steps until a private channel is established.
+
+## What to Include in a Report
+
+Please include as much of the following as possible:
+
+- A clear description of the vulnerability and its impact (confidentiality, integrity, availability).
+- Step-by-step reproduction steps or a minimal proof-of-concept (in a private channel only).
+- Affected versions/files and the environment where the issue was observed (PowerShell version, OS).
+- Any relevant logs, stack traces or configuration snippets.
+- Contact information so the maintainers can follow up.
+
+## Response Process and Timeline
+
+- Acknowledgement: We will acknowledge receipt as soon as practicable.
+- Triage: We will triage and begin an investigation as soon as practicable.
+- Fix: We will work to provide a fix or mitigation as soon as practicable; timelines vary by severity and complexity.
+- Public disclosure: The project follows coordinated disclosure practices. We will coordinate any public disclosure with the reporter; if no agreement is reached, we may disclose after a reasonable period once a fix is available.
+
+## Disclosure Policy
+
+We prefer coordinated disclosure so that users can update safely.
+Please do not publicly disclose vulnerabilities until a maintainer has had a reasonable opportunity to respond and a fix is available.
+
+## Credits
+
+We appreciate security reports and will credit reporters in release notes or acknowledgements unless the reporter requests to remain anonymous.
+
+---
+
+If you have questions about this policy or need an alternate contact method, open an issue marked with the `security` label (avoid posting exploit details) or check the repository README for maintainer contact information.
\ No newline at end of file
diff --git a/src/Create-VSSolution.ps1 b/src/Create-VSSolution.ps1
index 706e733..0ee1936 100644
--- a/src/Create-VSSolution.ps1
+++ b/src/Create-VSSolution.ps1
@@ -126,29 +126,6 @@ function UnzipFileFromUrl {
Remove-Item -Path $tempZip
}
-function Run {
- param (
- [string]$cmd,
- [object]$second = $null
- )
-
- # If second argument provided, treat as executable path + args; otherwise treat first as a PowerShell command string
- if ($null -ne $second) {
- $argList = @()
- if ($second -is [System.Array]) { $argList = $second } else { $argList = @($second) }
- Write-Debug "Running: $cmd $($argList -join ' ')"
- $proc = Start-Process -FilePath $cmd -ArgumentList $argList -Wait -PassThru -WindowStyle Hidden
- }
- else {
- Write-Debug "Running: $cmd"
- $proc = Start-Process -FilePath "powershell" -ArgumentList @('-NoProfile', '-Command', $cmd) -Wait -PassThru -WindowStyle Hidden
- }
- if ($proc.ExitCode -ne 0) {
- Write-Err "Process $cmd $($argList -join ' ') failed with exit code $($proc.ExitCode)"
- }
- return $proc.ExitCode
-}
-
function CreateProjectPath {
param (
[string]$solutionPath,
@@ -168,14 +145,67 @@ function CreateCleanArchitectureProjects {
[string]$projectPath = "src",
[string]$targetFramework
)
+
+ function Remove-DefaultClassFile {
+ param (
+ [string] $projectPath
+ )
+ $classFile = Join-Path -Path $projectPath -ChildPath "Class1.cs"
+ if (Test-Path $classFile) {
+ $cmd = "Remove-Item -Path `"$classFile`""
+ $rc = Run $cmd
+ Write-Debug "Removed default class file: $classFile"
+ }
+ }
+
+ function AddReferencesToProject {
+ param (
+ [string] $projectPath,
+ [string[]] $references
+ )
+ # Find the project's .csproj file
+ $projCsproj = Get-ChildItem -Path $projectPath -Filter '*.csproj' -File -ErrorAction SilentlyContinue | Select-Object -First 1
+ if (-not $projCsproj) {
+ Write-Warn "No .csproj found in project folder: $projectPath. Skipping reference addition."
+ return
+ }
+ $projCsprojPath = $projCsproj.FullName
+
+ foreach ($ref in $references) {
+ # Determine the sibling project directory (projects live under the same parent 'src' folder)
+ $parentDir = Split-Path -Path $projectPath -Parent
+ $refProjPath = Join-Path -Path $parentDir -ChildPath $ref
+ $refProjFile = Join-Path -Path $refProjPath -ChildPath "$($ref).csproj"
+ Write-Debug "Reference project file: $refProjFile"
+ Write-Debug "Reference project path: $refProjPath"
+ Write-Debug "projCsprojPath: $projCsprojPath"
+ if (Test-Path $refProjFile) {
+ Write-Debug "Adding reference to project: $refProjFile in $projCsprojPath"
+ # Use dotnet CLI directly so we can check the exit code
+ $cmd = "dotnet reference add `"$refProjFile`" --project `"$projCsprojPath`""
+ $rc = Run $cmd
+ if ($rc -ne 0) {
+ Write-Warn "dotnet add returned exit code $rc when adding reference $refProjFile to $projCsprojPath"
+ }
+ else {
+ Write-RunDone $true
+ }
+ }
+ else {
+ Write-Warn "Reference project file not found: $refProjFile"
+ }
+ }
+ }
+
$projects = @(
- @{ Name = "Core"; Suffix = ".Core"; Type = "classlib" },
- @{ Name = "Infrastructure"; Suffix = ".Infrastructure"; Type = "classlib" },
- @{ Name = "Domain"; Suffix = ".Domain"; Type = "classlib" }
+ @{ Name = "Domain"; Suffix = ".Domain"; Type = "classlib"; References = @() },
+ @{ Name = "Core"; Suffix = ".Core"; Type = "classlib"; References = @("Domain") },
+ @{ Name = "Infrastructure"; Suffix = ".Infrastructure"; Type = "classlib"; References = @("Core") }
)
foreach ($proj in $projects) {
$projName = $proj.Name
$projType = $proj.Type
+ $projRefs = $proj.References
# Build path as: $solutionPath\$projectPath\$projName
$projPath = Join-Path -Path (Join-Path -Path $solutionPath -ChildPath $projectPath) -ChildPath $projName
Write-Debug "Creating project: $projName at $projPath"
@@ -193,6 +223,17 @@ function CreateCleanArchitectureProjects {
Write-Warning "Failed to add project $projName to solution."
exit 2
}
+
+ # Remove Class1.cs
+ Remove-DefaultClassFile $projPath
+
+ if (-not $projRefs.Count -eq 0) {
+ # Add references
+ Write-Debug "project path $projPath"
+ Write-Debug "project refs $projRefs"
+ AddReferencesToProject -projectPath $projPath -references $projRefs
+ }
+
CreateSubFolderForEachCleanArchitectureProjects -ProjectPath $projPath -projectName $projName
}
}
@@ -238,6 +279,7 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$ScriptNamespace = "TirsvadScript.CreateVSSolution"
# Path to the 'inc' directory for sourced libraries
$ScriptDirectoryInc = Join-Path -Path $ScriptDirectory -ChildPath (Join-Path -Path $ScriptNamespace -ChildPath "inc")
+$ScriptDirectoryTemplates = Join-Path -Path $ScriptDirectory -ChildPath (Join-Path -Path $ScriptNamespace -ChildPath "templates")
################################################################################
# Include logging library early so helper functions (Write-Warn etc.) are available
@@ -246,7 +288,10 @@ $ScriptDirectoryInc = Join-Path -Path $ScriptDirectory -ChildPath (Join-Path -Pa
# Dependencies
$dependenciesTupleList = New-Object 'System.Collections.Generic.List[System.Tuple[string,string,string]]'
-$dependenciesTupleList.Add([Tuple]::Create("TirsvadScript.Logging", "TirsvadScript.LoggingLoaded", "https://github.com/TirsvadScript/PS.Logging/releases/download/v0.1.0/TirsvadScript.Logging.zip"))
+# $dependenciesTupleList.Add([Tuple]::Create("TirsvadScript.Logging", "TirsvadScript.LoggingLoaded", "https://github.com/TirsvadScript/PS.Logging/releases/download/v0.1.0/TirsvadScript.Logging.zip"))
+
+# internal include of dependencies
+. "$ScriptDirectoryInc\command-handler.ps1"
CheckDependencies
# exit0
@@ -263,7 +308,7 @@ $startingLocation = Get-Location
$solutionPath = Join-Path -Path $startingLocation -ChildPath $SolutionName
if (-not (Test-Path $solutionPath)) {
New-Item -ItemType Directory -Path $solutionPath | Out-Null
- Write-Ok "Created solution directory: $solutionPath"
+ Write-Debug "Created solution directory: $solutionPath"
}
# Check if solutionDirectory is empty
@@ -316,13 +361,21 @@ switch ($ProjectTemplate) {
"wpf" {
$projectType = "wpf"
$ProjectPath = Join-Path -Path (Join-Path -Path $solutionPath -ChildPath "src") -ChildPath "WpfUI"
- Write-Info "Created WPF solution: $SolutionName"
$cmd = "dotnet new $projectType -n `"WpfUI`" -o `"${ProjectPath}`" -f `"$targetFramework`""
$rc = Run $cmd
if ($rc -ne 0) {
Write-Warn "'dotnet new' failed for project WpfUI (rc=$rc)."
exit 2
}
+ # Add project to solution
+ $slnFile = Join-Path -Path $solutionPath -ChildPath "$($SolutionName).sln"
+ $projFile = Join-Path -Path $ProjectPath -ChildPath "WpfUI.csproj"
+ $added = AddProjectToSolution -slnPath $slnFile -projPath $projFile
+ if (-not $added) {
+ Write-Warning "Failed to add project $projName to solution."
+ exit 2
+ }
+ Write-Info "Created WPF solution: $SolutionName"
}
default {
Write-Err "Unsupported project template: $ProjectTemplate"
diff --git a/src/TirsvadScript.CreateVSSolution/inc/TirsvadScript.Logging/TirsvadScript.Logging.ps1 b/src/TirsvadScript.CreateVSSolution/inc/TirsvadScript.Logging/TirsvadScript.Logging.ps1
deleted file mode 100644
index 10ea823..0000000
--- a/src/TirsvadScript.CreateVSSolution/inc/TirsvadScript.Logging/TirsvadScript.Logging.ps1
+++ /dev/null
@@ -1,130 +0,0 @@
-# Guard: this file is intended to be dot-sourced (included) by the main script.
-# If executed directly, warn but continue so tests and other runspaces that dot-source still get the definitions.
-if ($MyInvocation.InvocationName -ne '.') {
- Write-Host "This script is a library and is intended to be dot-sourced (e.g. `. .\Create-VSSolution.ps1`). Continuing anyway." -ForegroundColor Yellow
-}
-
-# Mark that logging was loaded in a global helper object. Be defensive: the global may not exist or may be a primitive.
-$existingVar = Get-Variable -Name TirsvadScript -Scope Global -ErrorAction SilentlyContinue
-if ($null -eq $existingVar) {
- # Create a PSCustomObject container to hold markers
- $global:TirsvadScript = [PSCustomObject]@{ LoggingLoaded = $true }
-}
-else {
- $container = $existingVar.Value
- if ($container -is [System.Collections.Hashtable]) {
- $container['LoggingLoaded'] = $true
- }
- elseif ($container -is [System.Management.Automation.PSCustomObject]) {
- # Add or update property
- if ($container.PSObject.Properties.Match('LoggingLoaded').Count -eq0) {
- $container | Add-Member -NotePropertyName LoggingLoaded -NotePropertyValue $true
- }
- else {
- $container.LoggingLoaded = $true
- }
- }
- else {
- # Primitive or other type: preserve original value under 'OriginalValue' and replace global with a hashtable
- $global:TirsvadScript = @{ OriginalValue = $container; LoggingLoaded = $true }
- }
-}
-
-# Ensure a reasonable default verbosity when the caller hasn't set one.
-# When this file is dot-sourced it runs in the caller's script scope, so
-# checking for a script-scoped variable lets callers pre-set it (test expects that).
-if (-not (Get-Variable -Name VerboseMode -Scope Script -ErrorAction SilentlyContinue)) {
- $script:VerboseMode =2
-}
-
-# Write helpers respect numeric verbosity:0 = silent,1 = errors/warnings only,2 = errors+warnings+ok+info,3+ = debug
-function Write-Info { if ($script:VerboseMode -ge2) { Write-Host "[INFO] " -ForegroundColor Cyan -NoNewline; Write-Host " $args" } }
-function Write-Ok { if ($script:VerboseMode -ge2) { Write-Host "[OK] " -ForegroundColor Green -NoNewline; Write-Host " $args" } }
-function Write-Err { if ($script:VerboseMode -ge1) { Write-Host "[ERR] " -ForegroundColor Red -NoNewline; Write-Host " $args" } }
-function Write-Warn { if ($script:VerboseMode -ge1) { Write-Host "[WARN] " -ForegroundColor Magenta -NoNewline; Write-Host " $args" } }
-function Write-Debug { if ($script:VerboseMode -ge3) { Write-Host "[DEBUG] " -ForegroundColor Yellow -NoNewline; Write-Host " $args" } }
-function Write-Run { if ($script:VerboseMode -ge2) { Write-Host "[RUN] " -ForegroundColor DarkGray -NoNewline; Write-Host " $args" } }
-
-function Write-RunDone {
- param (
- [bool]$Success = $true
- )
- if ($Success) {
- $msg = 'DONE'
- $msgColor = 'DarkGray'
- }
- else {
- $msg = 'FAIL'
- $msgColor = 'Red'
- }
- if ($script:VerboseMode -ge 2) {
-
- try {
- $raw = $Host.UI.RawUI
- $pos = $raw.CursorPosition
- if ($pos.Y -gt 0) {
- # Move cursor to the start of the previous line
- $up = New-Object System.Management.Automation.Host.Coordinates(0, ($pos.Y -1))
- $raw.CursorPosition = $up
- # Overwrite the [RUN] marker
- Write-Host "[$msg] " -ForegroundColor $msgColor -NoNewline
- # Restore cursor to the original line start so the rest of the message prints on the next line
- $raw.CursorPosition = New-Object System.Management.Automation.Host.Coordinates(0, $pos.Y)
- }
- else {
- Write-Host "[$msg] " -ForegroundColor $msgColor -NoNewline
- }
- }
- catch {
- # Host doesn't support RawUI; just print $msg marker
- #Write-Host "[$msg] " -ForegroundColor $msgColor -NoNewline
- }
-
- #Write-Host " $args"
- }
-}
-function Write-Header {
- param (
- [string]$Message,
- [array]$SubMessages = @()
- )
-
- if ($script:VerboseMode -lt 1) { return }
-
- # Determine maximum content width (consider submessages)
- $maxLength =0
- if ($Message) { $maxLength = $Message.Length }
- foreach ($subMsg in $SubMessages) {
- if ($subMsg.Length -gt $maxLength) { $maxLength = $subMsg.Length }
- }
-
- # Add extra whitespace padding around the message for visual separation
- $innerWidth = $maxLength +4 # two spaces on each side when centered
-
- # Build top/bottom rule length: '===' + ' ' + inner + ' ' + '===' -> innerWidth +8
- $ruleLength = $innerWidth +8
- $line = '=' * $ruleLength
- Write-Host $line -ForegroundColor DarkCyan
-
- # Center the main message within the inner width
- if ($Message) {
- $leftPadding = [int](([double]($innerWidth - $Message.Length) /2.0) + $Message.Length)
- if ($leftPadding -lt $Message.Length) { $leftPadding = $Message.Length }
- $centered = $Message.PadLeft($leftPadding).PadRight($innerWidth)
- Write-Host "=== " -NoNewline -ForegroundColor DarkCyan
- Write-Host "$centered" -NoNewline -ForegroundColor white
- Write-Host " ===" -ForegroundColor DarkCyan
- }
-
- # Optionally print sub-messages centered as well
- if ($SubMessages -and $SubMessages.Count -gt0) {
- foreach ($sub in $SubMessages) {
- $leftPadding = [int](([double]($innerWidth - $sub.Length) /2.0) + $sub.Length)
- if ($leftPadding -lt $sub.Length) { $leftPadding = $sub.Length }
- $centeredSub = $sub.PadLeft($leftPadding).PadRight($innerWidth)
- Write-Host "=== $centeredSub ===" -ForegroundColor DarkCyan
- }
- }
-
- Write-Host $line -ForegroundColor DarkCyan
-}
\ No newline at end of file
diff --git a/src/TirsvadScript.CreateVSSolution/inc/command-handler.ps1 b/src/TirsvadScript.CreateVSSolution/inc/command-handler.ps1
new file mode 100644
index 0000000..143fb28
--- /dev/null
+++ b/src/TirsvadScript.CreateVSSolution/inc/command-handler.ps1
@@ -0,0 +1,33 @@
+# Guard: this file is intended to be dot-sourced (included) by the main script.
+# If executed directly, warn and exit to avoid unintended behavior.
+if ($MyInvocation.InvocationName -ne '.') {
+ Write-Host "This script is a library and must be dot-sourced from the main script (e.g. `. .\Create-VSSolution.ps1`). Exiting." -ForegroundColor Yellow
+ exit 1
+}
+
+function Run {
+ param (
+ [string]$cmd,
+ [object]$second = $null
+ )
+
+ # If second argument provided, treat as executable path + args; otherwise treat first as a PowerShell command string
+ if ($null -ne $second) {
+ $argList = @()
+ if ($second -is [System.Array]) { $argList = $second } else { $argList = @($second) }
+ Write-Run "Running: $cmd $($argList -join ' ')"
+ $proc = Start-Process -FilePath $cmd -ArgumentList $argList -Wait -PassThru -WindowStyle Hidden
+ }
+ else {
+ Write-Run "Running: $cmd"
+ $proc = Start-Process -FilePath "powershell" -ArgumentList @('-NoProfile', '-Command', $cmd) -Wait -PassThru -WindowStyle Hidden
+ }
+ if ($proc.ExitCode -ne 0) {
+ Write-RunDone $false
+ Write-Err "Process $cmd $($argList -join ' ') failed with exit code $($proc.ExitCode)"
+ }
+ else {
+ Write-RunDone $true
+ }
+ return $proc.ExitCode
+}
\ No newline at end of file
diff --git a/src/TirsvadScript.CreateVSSolution/inc/create-solution.ps1 b/src/TirsvadScript.CreateVSSolution/inc/create-solution.ps1
index d241f8a..d2f4f41 100644
--- a/src/TirsvadScript.CreateVSSolution/inc/create-solution.ps1
+++ b/src/TirsvadScript.CreateVSSolution/inc/create-solution.ps1
@@ -7,24 +7,22 @@ if ($MyInvocation.InvocationName -ne '.') {
# Define paths for solution-level configuration files
$solutionDirectoryBuildPropsDestPath = Join-Path -Path $solutionPath -ChildPath "Directory.Build.props"
-$solutionDirectoryBuildPropsSourcePath = Join-Path -Path $ScriptDirectoryInc -ChildPath "templates\Directory.Build.props"
+$solutionDirectoryBuildPropsSourcePath = Join-Path -Path $ScriptDirectoryTemplates -ChildPath "solution/Directory.Build.props"
$solutionDirectoryBuildTargetsDestPath = Join-Path -Path $solutionPath -ChildPath "Directory.Build.targets"
-$solutionDirectoryBuildTargetsSourcePath = Join-Path -Path $ScriptDirectoryInc -ChildPath "templates\Directory.Build.targets"
+$solutionDirectoryBuildTargetsSourcePath = Join-Path -Path $ScriptDirectoryTemplates -ChildPath "solution/Directory.Build.targets"
function CreateSolution {
param (
[string]$solutionName,
[string]$solutionPath
)
+ Write-Info "Creating solution '$solutionName' at path: $solutionPath"
$cmd = "dotnet new sln -n `"$solutionName`" -o `"$solutionPath`""
- Write-Run "Command: $cmd"
$rc = Run $cmd
if ($rc -ne 0) {
- Write-RunDone $false
Write-Err "'dotnet new sln' failed (rc=$rc)."
exit 2
}
- Write-RunDone $true
}
# TODO : implement Directory.Build.props content as needed
@@ -33,28 +31,14 @@ function CreateSolutionDirectoryBuildProps {
param (
[string]$solutionPath
)
- $slnDir = Get-Item $solutionPath
- $slnPropFile = Join-Path $slnDir.FullName "Directory.Build.props"
- Write-Debug "Creating Directory.Build.props at: $slnPropFile"
+ $rc = Run "Copy-Item -Path `"$solutionDirectoryBuildPropsSourcePath`" -Destination `"$solutionDirectoryBuildPropsDestPath`" -Force"
}
function CreateSolutionDirectoryTargets {
param (
[string]$solutionPath
)
- $slnDir = Get-Item $solutionPath
- $slnTargetFile = Join-Path $slnDir.FullName "Directory.Build.targets"
- $content = @'
-
-
-
-
-
-
-
-'@
- Write-Debug "Creating Directory.Build.targets at: $slnTargetFile"
- $content | Out-File -FilePath $slnTargetFile -Encoding UTF8 -Force
+ $rc = Run "Copy-Item -Path `"$solutionDirectoryBuildTargetsSourcePath`" -Destination `"$solutionDirectoryBuildTargetsDestPath`" -Force"
}
# Helper to add a project to a specific solution and verify
@@ -65,20 +49,19 @@ function AddProjectToSolution {
)
if (-not (Test-Path $slnPath)) {
- Write-Warning "Solution file not found: $slnPath"
+ Write-Warn "Solution file not found: $slnPath"
return $false
}
if (-not (Test-Path $projPath)) {
- Write-Warning "Project file not found: $projPath"
+ Write-Warn "Project file not found: $projPath"
return $false
}
- Write-Host "Adding project to solution: $projPath -> $slnPath"
+ Write-Debug "Adding project to solution: $projPath -> $slnPath"
& dotnet sln $slnPath add $projPath | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Warning "dotnet sln add failed with exit code $LASTEXITCODE"
return $false
}
-
return $true
}
\ No newline at end of file
diff --git a/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.props b/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.props
index 7908c72..a49f1a9 100644
--- a/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.props
+++ b/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.props
@@ -1,15 +1,14 @@
-
-
- $([System.IO.Path]::GetPathRoot('$(SolutionDir)'))
- $([System.IO.Path]::GetPathRoot('$(MSBuildProjectDirectory)'))
+
+
+ $([System.IO.Path]::GetPathRoot('$(SolutionDir)'))
+ $([System.IO.Path]::GetPathRoot('$(MSBuildProjectDirectory)'))
-
- $([System.IO.Path]::Combine('$(SolutionDriveRoot)','g','$(MSBuildProjectName)'))
- $([System.IO.Path]::Combine('$(BaseOutputPath)','obj'))
+
+ $([System.IO.Path]::Combine('$(SolutionDriveRoot)','g','$(MSBuildProjectName)'))
+ $([System.IO.Path]::Combine('$(BaseOutputPath)','obj'))
-
- $(BaseIntermediateOutputPath)
-
-
+
+ $(BaseIntermediateOutputPath)
+
\ No newline at end of file
diff --git a/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.targets b/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.targets
new file mode 100644
index 0000000..9ed69a3
--- /dev/null
+++ b/src/TirsvadScript.CreateVSSolution/templates/solution/Directory.Build.targets
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/install.ps1 b/src/install.ps1
index 6b80df0..8320de5 100644
--- a/src/install.ps1
+++ b/src/install.ps1
@@ -104,7 +104,7 @@ $ScriptIncPath = Join-Path -Path (Join-Path -Path $ScriptDirectory -ChildPath $S
# Download, unzip and dot-source logging library
$loggingDir = Join-Path -Path $ScriptIncPath -ChildPath 'TirsvadScript.Logging'
$loggingScript = Join-Path -Path $loggingDir -ChildPath 'TirsvadScript.Logging.ps1'
-$loggingZipUrl = 'https://github.com/TirsvadScript/PS.Logging/releases/download/v0.1.0/TirsvadScript.Logging.zip'
+$loggingZipUrl = 'https://github.com/TirsvadScript/PS.Logging/releases/download/v0.1.1/TirsvadScript.Logging.zip'
if (-not (Test-Path -Path $loggingScript)) {
Write-Host "Logging library not found. Downloading from $loggingZipUrl..."