diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 4cd927b3..4ca5dfd2 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -1,7 +1,6 @@
{
- "model": "opus",
+ "model": "sonnet",
"cleanupPeriodDays": 30,
- "dangerously-skip-permissions": true,
"permissions": {
"defaultMode": "bypassPermissions",
"allow": ["*"],
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index e6da3300..5b528f28 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -52,7 +52,9 @@
}
},
"terminal.integrated.shell.linux": "pwsh",
- "terminal.integrated.defaultProfile.linux": "pwsh"
+ "terminal.integrated.defaultProfile.linux": "pwsh",
+ "powershell.developer.editorServicesLogLevel": "Error",
+ "powershell.integratedConsole.suppressStartupBanner": true
},
"extensions": [
"ms-vscode.powershell",
diff --git a/.devcontainer/scripts/profile.ps1 b/.devcontainer/scripts/profile.ps1
index e69de29b..bbf4ee49 100644
--- a/.devcontainer/scripts/profile.ps1
+++ b/.devcontainer/scripts/profile.ps1
@@ -0,0 +1 @@
+$env:POWERSHELL_UPDATECHECK = 'Off'
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index e422526b..482c94c2 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -21,8 +21,32 @@ on:
required: false
jobs:
+ linux-build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 6.0.x
+
+ - name: Build core/lib
+ shell: pwsh
+ run: |
+ ./build/build.ps1 -CoreOnly
+
+ - name: Upload Linux artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: core-lib-linux
+ path: artifacts/dbatools.library/core/lib/
+
build-windows:
runs-on: windows-latest
+ needs: linux-build
steps:
- name: Checkout code
@@ -45,7 +69,23 @@ jobs:
shell: pwsh
run: |
# Run the build script
- .\build\build.ps1
+ .\build\build.ps1 -BuildZip
+
+ - name: Download Linux artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: core-lib-linux
+ path: artifacts/core-lib-linux/
+
+ - name: Extract core-lib-linux artifact and copy to core/lib
+ shell: pwsh
+ run: Copy-Item -Path "artifacts/core-lib-linux/*" -Destination "artifacts/dbatools.library/core/lib" -Recurse -Force
+
+ - name: Ensure sqlpackage is executable
+ shell: pwsh
+ run: |
+ chmod +x ./artifacts/dbatools.library/core/lib/dac/linux/sqlpackage
+ chmod +x ./artifacts/dbatools.library/core/lib/dac/mac/sqlpackage
- name: Verify critical files and directories
shell: pwsh
@@ -56,14 +96,13 @@ jobs:
$criticalPaths = @(
"desktop\lib",
"desktop\lib\runtimes\win-x64\native",
+ "core\lib\dac\windows",
"desktop\third-party",
"core\lib",
"core\lib\runtimes\win-x64\native",
- "core\lib\dac\windows",
"core\lib\dac\linux",
"core\lib\dac\mac",
- "core\third-party",
- "private"
+ "core\third-party"
)
$missingPaths = @()
@@ -110,7 +149,7 @@ jobs:
path: artifacts/dbatools.library.zip
test-sqlpackage:
- name: Test SqlPackage on ${{ matrix.os }}
+ name: Test sqlpackage on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
needs: build-windows
strategy:
@@ -144,7 +183,7 @@ jobs:
exit 1
}
- - name: Test SqlPackage
+ - name: Test sqlpackage
shell: pwsh
run: |
# Import the built module
@@ -158,71 +197,68 @@ jobs:
Write-Host "Module loaded successfully with version: $($module.Version)"
Write-Host "Module path: $($module.ModuleBase)"
- # Determine SqlPackage path based on OS
+ # Determine sqlpackage path based on OS
$modulePath = $module.ModuleBase
- if ($IsWindows -or $PSVersionTable.PSVersion.Major -eq 5) {
- Write-Host "Testing Windows SqlPackage..."
- $dacPath = Join-Path $modulePath "core/lib/dac/windows"
- $sqlPackageName = "SqlPackage.exe"
- } elseif ($IsLinux) {
- Write-Host "Testing Linux SqlPackage..."
- $dacPath = Join-Path $modulePath "core/lib/dac/linux"
- $sqlPackageName = "SqlPackage"
- } elseif ($IsMacOS) {
- Write-Host "Testing macOS SqlPackage..."
- $dacPath = Join-Path $modulePath "core/lib/dac/mac"
- $sqlPackageName = "SqlPackage"
- } else {
- Write-Error "Unknown operating system"
- exit 1
- }
+ $sqlPackageName = @(
+ (Join-Path $modulePath "desktop/lib/dac/SqlPackage.exe"),
+ (Join-Path $modulePath "core/lib/dac/windows/sqlpackage.exe"),
+ (Join-Path $modulePath "core/lib/dac/linux/sqlpackage"),
+ (Join-Path $modulePath "core/lib/dac/mac/sqlpackage")
+ )
- # Check if SqlPackage directory exists
- if (-not (Test-Path $dacPath)) {
- Write-Error "SqlPackage directory not found: $dacPath"
- Write-Host "Available directories in core/lib:"
- Get-ChildItem (Join-Path $modulePath "core/lib") -Directory | ForEach-Object { Write-Host " - $($_.Name)" }
- exit 1
+ foreach ($sqlPackage in $sqlPackageName) {
+ if (Test-Path $sqlPackage) {
+ Write-Host "Found sqlpackage at: $sqlPackage"
+ } else {
+ Write-Warning "sqlpackage not found: $sqlPackage"
+ Write-Host "Available directories in module"
+ Get-ChildItem $modulePath -Recurse | Where-Object Name -match sqlpack | Select-Object Fullname
+ }
}
- # Check if SqlPackage executable exists
- $sqlPackagePath = Join-Path $dacPath $sqlPackageName
- if (-not (Test-Path $sqlPackagePath)) {
- Write-Error "SqlPackage executable not found: $sqlPackagePath"
- Write-Host "Files in $dacPath :"
- Get-ChildItem $dacPath | ForEach-Object { Write-Host " - $($_.Name)" }
- exit 1
+ $sqlPackagePath = if ($IsMacOS) {
+ Join-Path $modulePath "core/lib/dac/mac/sqlpackage"
+ } elseif ($IsLinux) {
+ Join-Path $modulePath "core/lib/dac/linux/sqlpackage"
+ } else {
+ # if core then core
+ if ($PSVersionTable.PSEdition -eq 'Core') {
+ Join-Path $modulePath "core/lib/dac/windows/sqlpackage.exe"
+ } else {
+ # if desktop then desktop
+ Join-Path $modulePath "desktop/lib/dac/SqlPackage.exe"
+ }
}
- Write-Host "SqlPackage found at: $sqlPackagePath"
+ Write-Host "Using sqlpackage at: $sqlPackagePath"
- # Make SqlPackage executable on non-Windows platforms
+ # Make sqlpackage executable on non-Windows platforms
if ($IsLinux -or $IsMacOS) {
chmod +x $sqlPackagePath
}
- # Test SqlPackage execution
+ # Test sqlpackage execution
try {
- Write-Host "Testing SqlPackage execution..."
+ Write-Host "Testing sqlpackage execution..."
$versionOutput = & $sqlPackagePath /Version 2>&1
- Write-Host "SqlPackage version: $versionOutput"
+ Write-Host "sqlpackage version: $versionOutput"
# Basic functionality test - show help
- Write-Host "`nTesting SqlPackage help command..."
+ Write-Host "`nTesting sqlpackage help command..."
$helpOutput = & $sqlPackagePath /? 2>&1 | Select-Object -First 10
$helpOutput | ForEach-Object { Write-Host $_ }
Write-Host "... (output truncated)"
# Verify expected output from help
$helpString = $helpOutput -join "`n"
- if ($helpString -match "Specifies a name value pair" -or $helpString -match "SqlPackage" -or $helpString -match "Command") {
- Write-Host "`nSqlPackage test completed successfully!"
+ if ($helpString -match "Specifies a name value pair" -or $helpString -match "sqlpackage" -or $helpString -match "Command") {
+ Write-Host "`nsqlpackage test completed successfully!"
} else {
- Write-Error "SqlPackage help output does not contain expected content"
+ Write-Error "sqlpackage help output does not contain expected content"
exit 1
}
} catch {
- Write-Error "Failed to execute SqlPackage: $_"
+ Write-Error "Failed to execute sqlpackage: $_"
exit 1
}
@@ -252,7 +288,7 @@ jobs:
}
# Download dbatools from GitHub
- $branch = "${{ github.event.inputs.dbatools_branch || 'newver' }}"
+ $branch = "${{ github.event.inputs.dbatools_branch || 'newestver' }}"
Write-Host "Downloading dbatools from GitHub (branch: $branch)..."
$zipUrl = "https://github.com/dataplat/dbatools/archive/refs/heads/$branch.zip"
@@ -309,17 +345,20 @@ jobs:
Write-Host "Importing dbatools..."
Import-Module dbatools -Force
- Write-Host "Testing Get-DbaManagementObject..."
+ Write-Host "Testing Connect-DbaInstance..."
try {
- $result = Get-DbaManagementObject
- Write-Host "Test passed: Get-DbaManagementObject ran without fail"
+ $result = Connect-DbaInstance -SqlInstance localhost
} catch {
- Write-Error "Test failed with exception: $_"
- exit 1
+ if ($PSItem.Exception.Message -notmatch "not accessible") {
+ Write-Error "Test failed with exception: $_"
+ exit 1
+ } else {
+ Write-Host "Test failed successfully (lol) with inaccessible instance message: $($PSItem.Exception.Message)" -ForegroundColor Green
+ }
}
create-preview-release:
- needs: [build-windows, test-sqlpackage]
+ needs: [linux-build, build-windows, test-sqlpackage]
runs-on: windows-latest
# Create release if manually triggered OR if version contains "preview"
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 93593d50..6f728773 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,14 +5,42 @@ defaults:
run:
shell: pwsh
jobs:
- # Linux tests are disabled - build-core.ps1 script not found
- # Keeping Windows build test only for now
+ linux-build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 6.0.x
+
+ - name: Build core/lib
+ shell: pwsh
+ run: |
+ ./build/build.ps1 -CoreOnly
+
+ - name: Upload Linux artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: core-lib-linux
+ path: artifacts/dbatools.library/core/lib/
+
windows-tests:
runs-on: windows-latest
+ needs: linux-build
steps:
- uses: actions/checkout@v4
+ - name: Download Linux artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: core-lib-linux
+ path: artifacts/dbatools.library/core/lib/
+
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
@@ -31,6 +59,13 @@ jobs:
run: |
./build/build.ps1
+ - name: Copy Linux core/lib files
+ shell: pwsh
+ run: |
+ Copy-Item -Path artifacts/core-lib-linux/* -Destination artifacts/dbatools.library/core/lib/ -Recurse -Force
+ # delete windows sqlpackage on core cuz its the same as desktop
+ Remove-Item -Path artifacts/dbatools.library/core/lib/dac/windows -Recurse -Force -ErrorAction Ignore
+
- name: Verify critical files and directories
shell: pwsh
run: |
@@ -39,15 +74,14 @@ jobs:
$artifactsDir = "./artifacts/dbatools.library"
$criticalPaths = @(
"desktop\lib",
+ "desktop\lib\dac",
"desktop\lib\runtimes\win-x64\native",
"desktop\third-party",
"core\lib",
"core\lib\runtimes\win-x64\native",
- "core\lib\dac\windows",
"core\lib\dac\linux",
"core\lib\dac\mac",
- "core\third-party",
- "private"
+ "core\third-party"
)
$missingPaths = @()
diff --git a/.gitignore b/.gitignore
index 331a2b42..deedfe37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,4 @@ lib/
.devcontainer/.env
dbatools.library.zip
/artifacts
+.roo/mcp.json
diff --git a/.roo/mcp.json b/.roo/mcp.json
deleted file mode 100644
index 1f1b22aa..00000000
--- a/.roo/mcp.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "mcpServers": {
- "brave-search": {
- "command": "npx",
- "args": [
- "-y",
- "@modelcontextprotocol/server-brave-search"
- ]
- }
- }
-}
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
index e8e119d3..ca602285 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -91,7 +91,7 @@ Get-DbatoolsLoadedAssembly
1. **Clean**: Removes previous build artifacts
2. **Compile**: Builds C# projects for both target frameworks
3. **Package Dependencies**: Downloads and extracts:
- - SQL Server DacFramework (SqlPackage)
+ - SQL Server DacFramework (sqlpackage)
- Third-party NuGet packages (Bogus, LumenWorks CSV)
- XESmartTarget for Extended Events
4. **Platform Distribution**: Copies assemblies to appropriate platform directories
@@ -159,17 +159,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Development Commands
### Testing
+
+> **Note:** The following test commands reference Appveyor and Windows PowerShell scripts. For modern Linux/macOS/PowerShell Core setups or non-Appveyor CI, substitute with appropriate Pester/Invoke-Pester commands, and paths using forward slashes as needed.
+
```powershell
-# Run all tests
+# Run all tests (legacy, Windows/Appveyor)
.\tests\appveyor.pester.ps1
-# Run tests with code coverage
+# Run tests with code coverage (Windows/Appveyor)
.\tests\appveyor.pester.ps1 -IncludeCoverage
-# Run specific test file
+# Run specific test file (cross-platform)
Invoke-Pester ./tests/Get-DbaDatabase.Tests.ps1
-# Finalize test results
+# Finalize test results (Windows/Appveyor)
.\tests\appveyor.pester.ps1 -Finalize
```
diff --git a/build/build.ps1 b/build/build.ps1
index 92b6a435..7f424286 100644
--- a/build/build.ps1
+++ b/build/build.ps1
@@ -1,9 +1,10 @@
param(
- [switch]$NoZip
+ [switch]$BuildZip,
+ [switch]$CoreOnly
)
$PSDefaultParameterValues["*:Force"] = $true
$PSDefaultParameterValues["*:Confirm"] = $false
-
+$ProgressPreference = "SilentlyContinue"
# Import MSI waiting functions
. "$PSScriptRoot\Wait-MsiInstall.ps1"
@@ -15,8 +16,6 @@ if (-not $scriptroot) {
$root = Split-Path -Path $scriptroot
Push-Location $root
-Write-Warning $root
-
# Update module version to today's date
$today = Get-Date -Format "yyyy.M.d"
$psd1Path = Join-Path $root "dbatools.library.psd1"
@@ -80,61 +79,79 @@ Write-Host "Copying .NET 8 output with preserved structure..."
$null = New-Item -ItemType Directory -Path (Join-Path $libPath "core/lib") -Force
Copy-Item -Path "$tempCorePublish\*" -Destination (Join-Path $libPath "core/lib") -Recurse -Force
-# Handle legacy lib/release output directory if it exists (for backward compatibility)
-$legacyReleaseDir = Join-Path $root "lib\release"
-if (Test-Path $legacyReleaseDir) {
- Write-Host "Found legacy lib/release directory, copying to artifacts/release" -ForegroundColor Yellow
- $artifactsReleaseDir = Join-Path $artifactsDir "release"
- $null = New-Item -ItemType Directory -Path $artifactsReleaseDir -Force
- Copy-Item -Path "$legacyReleaseDir\*" -Destination $artifactsReleaseDir -Recurse -Force
+# Verify and organize runtime dependencies
+Write-Host "Verifying .NET 8 runtime dependencies..."
+$coreRuntimesPath = Join-Path $libPath "core\lib\runtimes"
+$desktopRuntimesPath = Join-Path $libPath "desktop\lib\runtimes"
- # Inform about the change
- Write-Host "NOTE: The lib directory in the root is deprecated. Please use artifacts/release instead." -ForegroundColor Yellow
-}
+# Ensure desktop runtimes directory exists
+New-Item -ItemType Directory -Path $desktopRuntimesPath -Force | Out-Null
-# Verify core runtime dependencies
-Write-Host "Verifying .NET 8 runtime dependencies..."
-$sniPath = Join-Path $libPath "core\lib\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll"
-if (Test-Path $sniPath) {
- $sniBase = Join-Path $libPath "core\lib\runtimes"
- $targetBase = Join-Path $libPath "desktop\lib\runtimes"
+if (Test-Path $coreRuntimesPath) {
+ Write-Host "Core runtimes folder found. Processing native dependencies..." -ForegroundColor Green
$architectures = @("win-x86", "win-x64", "win-arm", "win-arm64")
foreach ($arch in $architectures) {
- $sniPath = Join-Path $sniBase "$arch\native\Microsoft.Data.SqlClient.SNI.dll"
- if (Test-Path $sniPath) {
- Write-Host "Found SNI DLL at: $sniPath" -ForegroundColor Green
- $dllInfo = Get-Item $sniPath
- Write-Host "DLL Size: $($dllInfo.Length) bytes"
-
- $destFolder = Join-Path $targetBase "$arch\native"
- New-Item -ItemType Directory -Path $destFolder -Force | Out-Null
- Copy-Item $sniPath -Destination $destFolder -Force
-
- Write-Host "Copied to: $destFolder" -ForegroundColor Cyan
+ $coreArchPath = Join-Path $coreRuntimesPath "$arch\native"
+ $desktopArchPath = Join-Path $desktopRuntimesPath "$arch\native"
+
+ if (Test-Path $coreArchPath) {
+ Write-Host "Processing architecture: $arch" -ForegroundColor Cyan
+
+ # Ensure desktop architecture directory exists
+ New-Item -ItemType Directory -Path $desktopArchPath -Force | Out-Null
+
+ # Copy all native files from core to desktop for Windows PowerShell compatibility
+ Get-ChildItem -Path $coreArchPath -File | ForEach-Object {
+ $sourcePath = $_.FullName
+ $destPath = Join-Path $desktopArchPath $_.Name
+
+ Copy-Item $sourcePath -Destination $destPath -Force
+ Write-Host " Copied: $($_.Name)" -ForegroundColor Green
+ }
+
+ # Verify SNI DLL specifically
+ $sniPath = Join-Path $coreArchPath "Microsoft.Data.SqlClient.SNI.dll"
+ if (Test-Path $sniPath) {
+ $dllInfo = Get-Item $sniPath
+ Write-Host " SNI DLL verified - Size: $($dllInfo.Length) bytes" -ForegroundColor Green
+ } else {
+ Write-Warning " SNI DLL not found for $arch"
+ }
} else {
- Write-Warning "Missing: $sniPath"
+ Write-Warning "Architecture path not found: $coreArchPath"
}
}
-
} else {
- Write-Host "ERROR: SNI DLL not found at expected location: $sniPath" -ForegroundColor Red
- # Check if runtimes folder exists at all
- if (Test-Path (Join-Path $libPath "core\lib\runtimes")) {
- Write-Host "Runtimes folder exists. Contents:"
- Get-ChildItem -Path (Join-Path $libPath "core\lib\runtimes") -Recurse | Select-Object FullName
- } else {
- Write-Host "ERROR: Runtimes folder not found in output!" -ForegroundColor Red
+ Write-Host "ERROR: Core runtimes folder not found at: $coreRuntimesPath" -ForegroundColor Red
+
+ # Check what's actually in the core lib directory
+ $coreLibPath = Join-Path $libPath "core\lib"
+ if (Test-Path $coreLibPath) {
+ Write-Host "Core lib directory contents:" -ForegroundColor Yellow
+ Get-ChildItem -Path $coreLibPath -Recurse | Where-Object { $_.Name -like "*SNI*" } | Select-Object FullName
}
}
+Copy-Item (Join-Path $libPath "core\lib\runtimes\unix\lib\net8.0\Microsoft.Data.SqlClient.dll") -Destination (Join-Path $libPath "core/lib/") -Force
+
+if ($CoreOnly) {
+ Write-Host "CoreOnly specified - returning after core build"
+ return
+}
# Run tests specifically for dbatools.Tests
# dotnet test dbatools.Tests/dbatools.Tests.csproj --framework net472 --verbosity normal --no-restore --nologo | Out-String -OutVariable test
Pop-Location
-Remove-Item -Path (Join-Path $libPath "desktop/net472") -Recurse -ErrorAction SilentlyContinue
-Remove-Item -Path (Join-Path $libPath "core/net8.0") -Recurse -ErrorAction SilentlyContinue
+$targetDesktop = (Join-Path $libPath "desktop/net472")
+if (Test-Path $targetDesktop) {
+ Remove-Item -Path $targetDesktop -Recurse -ErrorAction SilentlyContinue
+}
+$targetCore = (Join-Path $libPath "core/net8.0")
+if (Test-Path $targetCore) {
+ Remove-Item -Path $targetCore -Recurse -ErrorAction SilentlyContinue
+}
$tempdir = Join-Path ([System.IO.Path]::GetTempPath()) "dbatools-build"
@@ -147,10 +164,11 @@ $null = New-Item -ItemType Directory (Join-Path $tempPath "mac") -Force -ErrorAc
$null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/XESmartTarget") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/bogus") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "desktop/third-party/LumenWorks") -Force
+$null = New-Item -ItemType Directory (Join-Path $libPath "desktop/lib/dac") -Force
+$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/windows") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/XESmartTarget") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/bogus") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/third-party/LumenWorks") -Force
-$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/windows") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/mac") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/dac/linux") -Force
$null = New-Item -ItemType Directory (Join-Path $libPath "core/lib/runtimes") -Force
@@ -159,36 +177,9 @@ $null = New-Item -ItemType Directory (Join-Path $tempdir "nuget") -Force
Register-PackageSource -provider NuGet -name nugetRepository -Location https://www.nuget.org/api/v2 -Trusted -ErrorAction Ignore
-$ProgressPreference = "SilentlyContinue"
-
-# Install Microsoft.Identity.Client NuGet package
-$parms = @{
- Provider = "Nuget"
- Destination = "$tempdir\nuget"
- Source = "nugetRepository"
- Scope = "CurrentUser"
- Force = $true
- SkipDependencies = $true
-}
-
-$parms.Name = "Microsoft.Identity.Client"
-$parms.RequiredVersion = "4.61.3.0"
-$null = Install-Package @parms
-
-$parms.Name = "Microsoft.Data.SqlClient"
-$parms.RequiredVersion = "5.1.6"
-Install-Package @parms
-
-
-# Copy DLLs to appropriate lib directories
-Copy-Item "$tempdir\nuget\Microsoft.Identity.Client.4.61.3\lib\net462\Microsoft.Identity.Client.dll" -Destination (Join-Path $libPath "desktop/lib/") -Force
-
-Copy-Item "$tempdir\nuget\Microsoft.Data.SqlClient.5.1.6\runtimes\unix\lib\net6.0\Microsoft.Data.SqlClient.dll" -Destination (Join-Path $libPath "core/lib/") -Force
-
-#Copy-Item "$tempdir\nuget\Microsoft.Identity.Client.4.61.3.0\lib\net461\Microsoft.Identity.Client.dll" -Destination (Join-Path $libPath "core/lib/") -Force
-
# Download all required packages
Invoke-WebRequest -Uri https://aka.ms/dacfx-msi -OutFile (Join-Path $tempPath "DacFramework.msi")
+Invoke-WebRequest -Uri https://aka.ms/sqlpackage-windows -OutFile (Join-Path $tempPath "sqlpackage-windows.zip")
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Bogus -OutFile (Join-Path $tempPath "bogus.zip")
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/LumenWorksCsvReader -OutFile (Join-Path $tempPath "LumenWorksCsvReader.zip")
Invoke-WebRequest -Uri https://github.com/spaghettidba/XESmartTarget/releases/download/v1.5.7/XESmartTarget_x64.msi -OutFile (Join-Path $tempPath "XESmartTarget_x64.msi")
@@ -202,6 +193,7 @@ $ProgressPreference = "Continue"
7z x (Join-Path $tempPath "LumenWorksCsvReader.zip") "-o$(Join-Path $tempPath "LumenWorksCsvReader")" -y
7z x (Join-Path $tempPath "bogus.zip") "-o$(Join-Path $tempPath "bogus")" -y
7z x (Join-Path $tempPath "XESmartTarget-linux.zip") "-o$(Join-Path $tempPath "xe-linux")" -y
+7z x (Join-Path $tempPath "sqlpackage-windows.zip") "-o$(Join-Path $tempPath "windows")" -y
7z x (Join-Path $tempPath "sqlpackage-linux.zip") "-o$(Join-Path $tempPath "linux")" -y
7z x (Join-Path $tempPath "sqlpackage-macos.zip") "-o$(Join-Path $tempPath "mac")" -y
@@ -287,40 +279,58 @@ if (-not $bogusCoreCopied) {
Copy-Item (Join-Path $tempPath "LumenWorksCsvReader/lib/net461/LumenWorks.Framework.IO.dll") -Destination (Join-Path $libPath "desktop/third-party/LumenWorks/LumenWorks.Framework.IO.dll") -Force
Copy-Item (Join-Path $tempPath "LumenWorksCsvReader/lib/netstandard2.0/LumenWorks.Framework.IO.dll") -Destination (Join-Path $libPath "core/third-party/LumenWorks/LumenWorks.Framework.IO.dll") -Force
-# Copy ALL SqlPackage files for each platform
-Write-Host "Copying SqlPackage files for all platforms..." -ForegroundColor Green
+# Copy ALL sqlpackage files for each platform
+Write-Host "Copying sqlpackage files for all platforms..." -ForegroundColor Green
-# Windows - Copy ALL files from DAC bin directory
+# Windows - Copy ALL files from DAC bin directory to desktop/lib/dac (dacfx-msi)
$dacPath = Join-Path (Join-Path $tempPath "dacfull") "Microsoft SQL Server\170\DAC\bin"
if (Test-Path $dacPath) {
- Write-Host "Copying ALL SqlPackage files for Windows..." -ForegroundColor Green
- Copy-Item (Join-Path $dacPath "*") -Destination (Join-Path $libPath "core/lib/dac/windows/") -Recurse -Force
+ Write-Host "Copying dacfx-msi files to desktop/lib/dac..." -ForegroundColor Green
+ Copy-Item (Join-Path $dacPath "*") -Destination (Join-Path $libPath "desktop/lib/dac/") -Recurse -Force
} else {
Write-Warning "Windows DAC path not found: $dacPath"
}
+# Windows Core - Copy ALL files from sqlpackage Windows download to core/lib/dac/windows
+if (Test-Path (Join-Path $tempPath "windows")) {
+ Write-Host "Copying sqlpackage Windows files to core/lib/dac/windows..." -ForegroundColor Green
+ Copy-Item (Join-Path $tempPath "windows/*") -Destination (Join-Path $libPath "core/lib/dac/windows/") -Recurse -Force
+} else {
+ Write-Warning "Windows sqlpackage path not found: $(Join-Path $tempPath "windows")"
+}
+
# Linux - Copy ALL files from temp/linux
if (Test-Path (Join-Path $tempPath "linux")) {
- Write-Host "Copying ALL SqlPackage files for Linux..." -ForegroundColor Green
+ Write-Host "Copying ALL sqlpackage files for Linux..." -ForegroundColor Green
Copy-Item (Join-Path $tempPath "linux/*") -Destination (Join-Path $libPath "core/lib/dac/linux/") -Recurse -Force
-
- # Fix SqlPackage naming for Linux - rename lowercase to uppercase if it exists
- $linuxSqlPackageLowerCase = Join-Path $libPath "core/lib/dac/linux/sqlpackage"
- $linuxSqlPackageUpperCase = Join-Path $libPath "core/lib/dac/linux/SqlPackage"
- if (Test-Path $linuxSqlPackageLowerCase) {
- Write-Host "Renaming lowercase 'sqlpackage' to 'SqlPackage' for Linux compatibility"
- Move-Item $linuxSqlPackageLowerCase $linuxSqlPackageUpperCase -Force
+ # Ensure SqlPackage is renamed to sqlpackage (Linux is case-sensitive)
+ $linSqlPackage = Join-Path $libPath "core/lib/dac/linux/SqlPackage"
+ $finalname = Join-Path $libPath "core/lib/dac/linux/sqlpackage"
+ $tempname = Join-Path $libPath "core/lib/dac/linux/sqlpackage-temp"
+
+ if (Test-Path $linSqlPackage) {
+ Rename-Item $linSqlPackage $tempname
+ Rename-Item $tempname $finalname
}
} else {
- Write-Warning "Linux SqlPackage path not found: $(Join-Path $tempPath "linux")"
+ Write-Warning "Linux sqlpackage path not found: $(Join-Path $tempPath "linux")"
}
# macOS - Copy ALL files from temp/mac
if (Test-Path (Join-Path $tempPath "mac")) {
- Write-Host "Copying ALL SqlPackage files for macOS..." -ForegroundColor Green
+ Write-Host "Copying ALL sqlpackage files for macOS..." -ForegroundColor Green
Copy-Item (Join-Path $tempPath "mac/*") -Destination (Join-Path $libPath "core/lib/dac/mac/") -Recurse -Force
+ # Ensure SqlPackage is renamed to sqlpackage (macOS case-sensitive too)
+ $linSqlPackage = Join-Path $libPath "core/lib/dac/mac/SqlPackage"
+ $finalname = Join-Path $libPath "core/lib/dac/mac/sqlpackage"
+ $tempname = Join-Path $libPath "core/lib/dac/mac/sqlpackage-temp"
+
+ if (Test-Path $linSqlPackage) {
+ Rename-Item $linSqlPackage $tempname
+ Rename-Item $tempname $finalname
+ }
} else {
- Write-Warning "macOS SqlPackage path not found: $(Join-Path $tempPath "mac")"
+ Write-Warning "macOS sqlpackage path not found: $(Join-Path $tempPath "mac")"
}
# Core files are already in place from dotnet publish
@@ -341,15 +351,6 @@ Write-Host "Cleaning up temporary files..."
# We don't remove the artifacts directory since it's our centralized build output
Get-ChildItem -Path (Join-Path $libPath "*") -Recurse -Include "*.pdf","*.xml" | Remove-Item -Force
-# Create private directory for assembly loading scripts
-$null = New-Item -ItemType Directory -Path "./private" -Force -ErrorAction SilentlyContinue
-
-# Copy assembly loading scripts to private directory
-if (Test-Path (Join-Path $root "private")) {
- Copy-Item -Path (Join-Path $root "private\*") -Destination "./private/" -Force -ErrorAction SilentlyContinue
- Write-Host "Copied assembly loading scripts to private directory"
-}
-
# Create directory structure for different versions of System.Runtime.CompilerServices.Unsafe.dll
$null = New-Item -ItemType Directory -Path (Join-Path $libPath "desktop/v4") -Force
$null = New-Item -ItemType Directory -Path (Join-Path $libPath "desktop/lib/v6") -Force
@@ -375,12 +376,6 @@ Copy-Item -Path (Join-Path $root "dbatools.library.psm1") -Destination $dbatools
Copy-Item -Path (Join-Path $root "LICENSE") -Destination $dbatoolsLibraryDir -Force -ErrorAction SilentlyContinue
Write-Host "Copied module files to artifacts/dbatools.library" -ForegroundColor Green
-# Copy private folder with assembly loading scripts
-if (Test-Path (Join-Path $root "private")) {
- Copy-Item -Path (Join-Path $root "private") -Destination $dbatoolsLibraryDir -Recurse -Force
- Write-Host "Included private folder in artifacts/dbatools.library" -ForegroundColor Green
-}
-
# Copy third-party-licenses
$licensePath = Join-Path $dbatoolsLibraryDir "third-party-licenses"
$null = New-Item -ItemType Directory -Path $licensePath -Force
@@ -396,7 +391,9 @@ if (Test-Path (Join-Path $root "var/third-party-licenses")) {
# Create zip file for testing (release format)
Write-Host "Creating dbatools.library.zip for testing..."
$zipPath = Join-Path $artifactsDir "dbatools.library.zip"
-Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue
+if (Test-Path $zipPath) {
+ Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue
+}
# Copy third-party-licenses
if (Test-Path (Join-Path $root "var\third-party-licenses")) {
@@ -409,7 +406,7 @@ Write-Host "All build artifacts are centralized in: $artifactsDir" -ForegroundCo
# Create the zip file directly from the artifacts/dbatools.library directory
Push-Location $artifactsDir
-if (-not $NoZip) {
+if ($BuildZip) {
Compress-Archive -Path "dbatools.library" -DestinationPath $zipPath -CompressionLevel Optimal -Force
}
Pop-Location
diff --git a/dbatools.library.psd1 b/dbatools.library.psd1
index 21c37844..36c2a16c 100644
--- a/dbatools.library.psd1
+++ b/dbatools.library.psd1
@@ -7,7 +7,7 @@
#
@{
# Version number of this module.
- ModuleVersion = '2025.7.13'
+ ModuleVersion = '2025.7.19'
# ID used to uniquely identify this module
GUID = '00b61a37-6c36-40d8-8865-ac0180288c84'
diff --git a/dbatools.library.psm1 b/dbatools.library.psm1
index 343dd585..90fdfbd8 100644
--- a/dbatools.library.psm1
+++ b/dbatools.library.psm1
@@ -1,76 +1,192 @@
function Get-DbatoolsLibraryPath {
[CmdletBinding()]
param()
- Write-Debug "PSScriptRoot: $PSScriptRoot"
- Write-Debug "Module Base: $($MyInvocation.MyCommand.Module.ModuleBase)"
-
- # Use ModuleBase as it's more reliable when importing via absolute path
- $MyInvocation.MyCommand.Module.ModuleBase
+ if ($PSVersionTable.PSEdition -eq "Core") {
+ Join-Path -Path $PSScriptRoot -ChildPath core
+ } else {
+ Join-Path -Path $PSScriptRoot -ChildPath desktop
+ }
}
$script:libraryroot = Get-DbatoolsLibraryPath
-# Ensure private directory exists
-$privateDir = Join-Path $PSScriptRoot "private"
-if (-not (Test-Path $privateDir)) {
- $null = New-Item -ItemType Directory -Path $privateDir -Force
-}
+if ($PSVersionTable.PSEdition -ne "Core") {
+ $dir = [System.IO.Path]::Combine($script:libraryroot, "lib")
+ $dir = ("$dir\").Replace('\', '\\')
-# Define component load order (important for dependencies)
-$components = @(
- 'assembly-lists.ps1', # Must be first as others depend on its variables
- 'assembly-redirector.ps1', # Assembly redirection for version conflicts
- 'assembly-compilerservices-resolver.ps1', # Specific resolver for System.Runtime.CompilerServices.Unsafe
- 'assembly-resolution.ps1', # Depends on assembly lists
- 'assembly-loader.ps1', # Depends on both above
- 'assembly-troubleshoot.ps1' # Troubleshooting tools
-)
-
-# Load component scripts
-foreach ($component in $components) {
- $componentPath = Join-Path $PSScriptRoot "private\$component"
- if (Test-Path $componentPath) {
- . $componentPath
- } else {
- throw "Required component not found: $componentPath"
+ if (-not ("Redirector" -as [type])) {
+ $source = @"
+ using System;
+ using System.Linq;
+ using System.Reflection;
+ using System.Text.RegularExpressions;
+
+ public class Redirector
+ {
+ public Redirector()
+ {
+ this.EventHandler = new ResolveEventHandler(AssemblyResolve);
+ }
+
+ public readonly ResolveEventHandler EventHandler;
+
+ protected Assembly AssemblyResolve(object sender, ResolveEventArgs e)
+ {
+ string[] dlls = {
+ "System.Memory",
+ "System.Runtime.CompilerServices.Unsafe",
+ "Microsoft.Bcl.AsyncInterfaces",
+ "System.Text.Json",
+ "System.Resources.Extensions",
+ "Microsoft.SqlServer.ConnectionInfo",
+ "Microsoft.SqlServer.Smo",
+ "Microsoft.Identity.Client",
+ "System.Diagnostics.DiagnosticSource",
+ "Microsoft.IdentityModel.Abstractions",
+ "Microsoft.Data.SqlClient",
+ "Microsoft.SqlServer.Types",
+ "System.Configuration.ConfigurationManager",
+ "Microsoft.SqlServer.Management.Sdk.Sfc",
+ "Microsoft.SqlServer.Management.IntegrationServices",
+ "Microsoft.SqlServer.Replication",
+ "Microsoft.SqlServer.Rmo",
+ "System.Private.CoreLib",
+ "Azure.Core",
+ "Azure.Identity"
+ };
+
+ var name = new AssemblyName(e.Name);
+ var assemblyName = name.Name.ToString();
+ foreach (string dll in dlls)
+ {
+ if (assemblyName == dll)
+ {
+ string filelocation = "$dir" + dll + ".dll";
+ //Console.WriteLine(filelocation);
+ return Assembly.LoadFrom(filelocation);
+ }
+ }
+
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ // maybe this needs to change?
+ var info = assembly.GetName();
+ if (info.FullName == e.Name) {
+ return assembly;
+ }
+ }
+ return null;
+ }
+ }
+"@
+
+ $null = Add-Type -TypeDefinition $source
+ }
+
+ try {
+ $redirector = New-Object Redirector
+ [System.AppDomain]::CurrentDomain.add_AssemblyResolve($redirector.EventHandler)
+ } catch {
+ # unsure
}
}
-# Initialize assembly handling
+# REMOVED win-sqlclient logic - SqlClient is now directly in lib
+$sqlclient = [System.IO.Path]::Combine($script:libraryroot, "lib", "Microsoft.Data.SqlClient.dll")
+
try {
- Initialize-DbatoolsAssemblyLoader
- Write-Debug "Assembly loader initialized successfully"
+ Import-Module $sqlclient
} catch {
- throw "Failed to initialize assembly loader: $_"
+ throw "Couldn't import $sqlclient | $PSItem"
}
-# Register cleanup for module removal
-$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
- if ($PSVersionTable.PSEdition -ne "Core") {
- try {
- # Remove both event handlers
- [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($script:onAssemblyResolveEventHandler)
+if ($PSVersionTable.PSEdition -ne "Core") {
+ [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($onAssemblyResolveEventHandler)
+}
- # Get the redirector instance and remove its handler
- $redirector = New-Object Redirector
- [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($redirector.EventHandler)
+if ($PSVersionTable.PSEdition -eq "Core") {
+ $names = @(
+ 'Microsoft.SqlServer.Server',
+ 'Azure.Core',
+ 'Azure.Identity',
+ 'Microsoft.IdentityModel.Abstractions',
+ 'Microsoft.SqlServer.Dac',
+ 'Microsoft.SqlServer.Smo',
+ 'Microsoft.SqlServer.SmoExtended',
+ 'Microsoft.SqlServer.SqlWmiManagement',
+ 'Microsoft.SqlServer.WmiEnum',
+ 'Microsoft.SqlServer.Management.RegisteredServers',
+ 'Microsoft.SqlServer.Management.Collector',
+ 'Microsoft.SqlServer.Management.XEvent',
+ 'Microsoft.SqlServer.Management.XEventDbScoped',
+ 'Microsoft.SqlServer.XEvent.XELite'
+ )
+} else {
+ $names = @(
+ 'Azure.Core',
+ 'Azure.Identity',
+ 'Microsoft.IdentityModel.Abstractions',
+ 'Microsoft.Data.SqlClient',
+ 'Microsoft.SqlServer.Dac',
+ 'Microsoft.SqlServer.Smo',
+ 'Microsoft.SqlServer.SmoExtended',
+ 'Microsoft.SqlServer.SqlWmiManagement',
+ 'Microsoft.SqlServer.WmiEnum',
+ 'Microsoft.SqlServer.Management.RegisteredServers',
+ 'Microsoft.SqlServer.Management.IntegrationServices',
+ 'Microsoft.SqlServer.Management.Collector',
+ 'Microsoft.SqlServer.Management.XEvent',
+ 'Microsoft.SqlServer.Management.XEventDbScoped',
+ 'Microsoft.SqlServer.XEvent.XELite'
+ )
+}
- Write-Debug "Successfully removed assembly resolve handlers"
- }
- catch {
- Write-Warning "Error removing assembly resolve handlers: $_"
- }
- }
+if ($Env:SMODefaultModuleName) {
+ # then it's DSC, load other required assemblies
+ $names += "Microsoft.AnalysisServices.Core"
+ $names += "Microsoft.AnalysisServices"
+ $names += "Microsoft.AnalysisServices.Tabular"
+ $names += "Microsoft.AnalysisServices.Tabular.Json"
+}
+
+# XEvent stuff kills CI/CD
+if ($PSVersionTable.OS -match "ARM64") {
+ $names = $names | Where-Object { $PSItem -notmatch "XE" }
+}
+#endregion Names
+
+# this takes 10ms
+$assemblies = [System.AppDomain]::CurrentDomain.GetAssemblies()
+
+try {
+ $null = Import-Module ([IO.Path]::Combine($script:libraryroot, "third-party", "bogus", "Bogus.dll"))
+} catch {
+ Write-Error "Could not import $assemblyPath : $($_ | Out-String)"
+}
+
+try {
+ $null = Import-Module ([IO.Path]::Combine($script:libraryroot, "third-party", "LumenWorks", "LumenWorks.Framework.IO.dll"))
+} catch {
+ Write-Error "Could not import LumenWorks.Framework.IO.dll : $($_ | Out-String)"
}
-# Export module functions
-Export-ModuleMember -Function @(
- 'Get-DbatoolsLibraryPath',
- 'Get-DbatoolsPlatformInfo',
- 'Get-DbatoolsLoadedAssembly',
- 'Test-DbatoolsAssemblyLoading',
- 'Reset-DbatoolsAssemblyLoader',
- 'Test-DbatoolsAssemblyEnvironment',
- 'Reset-DbatoolsAssemblyCache',
- 'Get-PlatformDetails'
-)
\ No newline at end of file
+foreach ($name in $names) {
+ # REMOVED win-sqlclient handling and mac-specific logic since files are in standard lib folder
+
+ $x64only = 'Microsoft.SqlServer.Replication', 'Microsoft.SqlServer.XEvent.Linq', 'Microsoft.SqlServer.BatchParser', 'Microsoft.SqlServer.Rmo', 'Microsoft.SqlServer.BatchParserClient'
+
+ if ($name -in $x64only -and $env:PROCESSOR_ARCHITECTURE -eq "x86") {
+ Write-Verbose -Message "Skipping $name. x86 not supported for this library."
+ continue
+ }
+
+ $assemblyPath = [IO.Path]::Combine($script:libraryroot, "lib", "$name.dll")
+ $assemblyfullname = $assemblies.FullName | Out-String
+ if (-not ($assemblyfullname.Contains("$name,"))) {
+ $null = try {
+ $null = Import-Module $assemblyPath
+ } catch {
+ Write-Error "Could not import $assemblyPath : $($_ | Out-String)"
+ }
+ }
+}
\ No newline at end of file
diff --git a/project/dbatools/dbatools.csproj b/project/dbatools/dbatools.csproj
index 02e7f1cd..5e4b6dae 100644
--- a/project/dbatools/dbatools.csproj
+++ b/project/dbatools/dbatools.csproj
@@ -14,38 +14,71 @@
true
true
-
- latest
- ..\..\artifacts\lib\$(Configuration)\
- ..\..\artifacts\lib\$(Configuration)\dbatools.xml
-
full
DEBUG;TRACE
+ ..\..\artifacts\lib\$(Configuration)\
+ 7.3
pdbonly
true
TRACE
+ ..\..\artifacts\lib\$(Configuration)\
+ ..\..\artifacts\lib\$(Configuration)\dbatools.xml
+ 7.3
+
+
+
+ ..\..\artifacts\lib\
+ TRACE;NORUNSPACENAME
+ ..\..\artifacts\lib\dbatools.xml
+ true
+ pdbonly
+ MinimumRecommendedRules.ruleset
+ 5
+
+
+
+ ..\..\artifacts\lib\
+ TRACE;NORUNSPACENAME
+ ..\..\artifacts\lib\dbatools.xml
+ true
+ pdbonly
+ MinimumRecommendedRules.ruleset
+ 7.3
+
+
+
-
-
+
+
+
+
+
+
+
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
False
False
+
+
+
+
+
\ No newline at end of file
diff --git a/var/misc/both/Microsoft.SqlServer.ReplEnum.dll b/var/misc/both/Microsoft.SqlServer.ReplEnum.dll
new file mode 100644
index 00000000..ff1205ed
Binary files /dev/null and b/var/misc/both/Microsoft.SqlServer.ReplEnum.dll differ
diff --git a/var/misc/both/Microsoft.SqlServer.Replication.dll b/var/misc/both/Microsoft.SqlServer.Replication.dll
index c9003132..95f12f04 100644
Binary files a/var/misc/both/Microsoft.SqlServer.Replication.dll and b/var/misc/both/Microsoft.SqlServer.Replication.dll differ
diff --git a/var/misc/both/Microsoft.SqlServer.Rmo.dll b/var/misc/both/Microsoft.SqlServer.Rmo.dll
index c90ced12..77355aa1 100644
Binary files a/var/misc/both/Microsoft.SqlServer.Rmo.dll and b/var/misc/both/Microsoft.SqlServer.Rmo.dll differ
diff --git a/var/misc/both/instapi170.dll b/var/misc/both/instapi170.dll
new file mode 100644
index 00000000..6316a905
Binary files /dev/null and b/var/misc/both/instapi170.dll differ