4: ServerConfig_InstallSN - DavidRueter/SQLVer GitHub Wiki

This one is a little frustrating. We need one tiny little sn.exe (Strong Name) utility from Microsoft, but they only make this available as part of either Visual Studio or the .NET SDK

If you have the sn.exe utility installed (on this server, or elsewhere), just go ahead and copy it (and the corresponding sn.exe.config file) to a folder C:\SQLVer\Tools\netfx

If you do not have the sn.exe available to copy, proceed with the following steps to install the .NET SDC and link to it.

Note: Since some people still run Windows Server 2016, these instructions assume you are installing .NET 8 (current version as of 3/13/2025). But you can find the address of the current version here: https://dotnet.microsoft.com/en-us/download/dotnet/8.0 ...or https://dotnet.microsoft.com/en-us/download/dotnet/9.0 if you are on a later version of Windows.

If you do opt to manually download the .NET SDK you can either install it, or open it (with 7-Zip or similar) to extract just sn.exe and sn.exe.config.

Remember...the ONLY thing we really need is the sn.exe and sn.exe.config files, and they are not too particular about .NET versions. It is super annoying that we have to go to all this trouble. (Copying these two files from a different machine to a folder C:\SQLVer\Tools\ netfx is perfectly fine, and is a lot simpler.)

In the PowerShell window, paste the following and press Enter:

# $dotnetURL = "https://download.visualstudio.microsoft.com/download/pr/6f043b39-b3d2-4f0a-92bd-99408739c98d/fa16213ea5d6464fa9138142ea1a3446/dotnet-sdk-8.0.407-win-x64.exe"

# $installerPath = "$env:TEMP\dotnet-sdk-8.0.407-win-x64.exe"

$dotnetURL = "https://download.visualstudio.microsoft.com/download/pr/b0032fde-aac9-4c3e-b78c-4bd605910241/8d2aa21baac4aef9b996671cd8a48fb2/dotnet-sdk-9.0.202-win-x64.exe"
$installerPath = "$env:TEMP\dotnet-sdk-9.0.202-win-x64.exe"

Invoke-WebRequest -Uri $dotnetURL -OutFile $installerPath
Start-Process -FilePath $installerPath -ArgumentList "/quiet /norestart" -Wait

# Prevent the PowerShell window from closing immediately
function Pause {
    Read-Host -Prompt "Press Enter to exit..."
}

# Define the target base directory
$dotnetSDKBase = "C:\Program Files (x86)\Microsoft SDKs\Windows"

# Define the symbolic link name
$symlinkPath = "C:\SQLVer\Tools\netfx"

# Ensure the script is running as Administrator
$CurrentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal $CurrentUser
if (-Not $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Host "Error: Please run PowerShell as Administrator." -ForegroundColor Red
    Write-Host "Attempting to restart as Administrator..."
    Start-Process PowerShell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
    exit 1
}

# Check if the .NET SDK directory exists
if (-Not (Test-Path $dotnetSDKBase)) {
    Write-Host "Error: .NET SDK directory not found at $dotnetSDKBase" -ForegroundColor Red
    Pause
    exit 1
}

# Get the most recent SDK version directory
$latestSDK = Get-ChildItem -Path $dotnetSDKBase | Sort-Object Name -Descending | Select-Object -First 1

if (-Not $latestSDK) {
    Write-Host "Error: No .NET SDK installations found in $dotnetSDKBase" -ForegroundColor Red
    Pause
    exit 1
}

# Define the NETFX 4.5.1 Tools folder inside the latest SDK directory
$dotnetSDKBase = $latestSDK.FullName + "\bin\"
$latestSDK = Get-ChildItem -Path $dotnetSDKBase | Sort-Object Name -Descending | Select-Object -First 1

# Define the actual NETFX 4.5.1 Tools path
$netfxToolsPath = $latestSDK.FullName

# Verify if the NETFX Tools folder exists
if (-Not (Test-Path $netfxToolsPath)) {
    Write-Host "Error: NETFX 4.5.1 Tools folder not found at $netfxToolsPath" -ForegroundColor Red
    Pause
    exit 1
}

# Remove existing symlink if it exists
if ((Get-Item $symlinkPath) -is [System.IO.DirectoryInfo] -and ((Get-Item $symlinkPath).Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
    Write-Host "Removing existing symbolic link: $symlinkPath"
    cmd /c rmdir $symlinkPath
}

# Create the symbolic link
Write-Host "Creating symbolic link: $symlinkPath -> $netfxToolsPath"
cmd.exe /c mklink /D "$symlinkPath" "$netfxToolsPath"

# Verify success
if (Test-Path $symlinkPath) {
    Write-Host "Symbolic link created successfully!" -ForegroundColor Green
} else {
    Write-Host "Error: Failed to create symbolic link." -ForegroundColor Red
    Pause
    exit 1
}

Write-Host "About to delete temp files." -ForegroundColor Red
Pause

# Delete the installer after installation
if (Test-Path $installerPath) {
    Remove-Item -Path $installerPath -Force
    Write-Host "Deleted temporary installer file: $installerPath"
}

# Pause before exiting to keep the window open
Pause