66 [String ]$PythonVersion = ' 3.13' ,
77 [String ]$OverwriteInstallOptionsTo = ' ' ,
88 [Switch ]$InstallPwsh7SDK ,
9- [Switch ]$InstallGit ,
109 [Switch ]$InstallDotnetInteractive ,
11- [Switch ]$InstallNBExtensions ,
12- [Switch ]$UsePipKernel ,
13- [Switch ]$InstallPwsh7ForPipKernel ,
1410 [Switch ]$CleanupDownloadFiles ,
1511 [String ]$WorkingFolder = $PSScriptRoot
1612)
1713$ErrorActionPreference = ' Stop'
1814Push-Location $WorkingFolder
1915chcp 65001
20- $OutputEncoding = [System.Console ]::OutputEncoding = [ System.Console ]::InputEncoding = [ System. Text.Encoding ]::GetEncoding(' utf-8' )
16+ $OutputEncoding = [System.Text.Encoding ]::GetEncoding(' utf-8' )
2117
2218$psBoundParameters.Keys | ForEach-Object {
2319 if ($ ($PSBoundParameters .$_.GetType ().Name) -eq ' SwitchParameter' ) {
@@ -27,11 +23,11 @@ $psBoundParameters.Keys | ForEach-Object {
2723 $paramStrings += " -$_ $ ( $PSBoundParameters .$_ ) "
2824 }
2925}
30- Write-Verbose " Commandline: `" $PSCommandPath `" $paramStrings "
26+ Write-Host " Commandline: `" $PSCommandPath `" $paramStrings "
3127switch ($InstallationType ) {
3228 {@ (' system' , ' computer' , ' allusers' ) -contains $_ } {
3329 if (-not ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole ] " Administrator" )) {
34- Write-Verbose ' Relaunch script with admin privileges...'
30+ Write-Host ' Relaunch script with admin privileges...'
3531 Start-Process powershell.exe " -NoExit -ExecutionPolicy Bypass -Command `" $PSCommandPath `" $paramStrings " - Verb RunAs
3632 exit
3733 }
@@ -41,7 +37,6 @@ switch ($InstallationType) {
4137 else {
4238 $installOpt = $OverwriteInstallOptionsTo
4339 }
44- $pyTypeOpt = ' --sys-prefix'
4540 }
4641 {@ (' user' , ' justme' ) -contains $_ } {
4742 if ( ' ' -eq $OverwriteInstallOptionsTo ) {
@@ -50,7 +45,6 @@ switch ($InstallationType) {
5045 else {
5146 $installOpt = $OverwriteInstallOptionsTo
5247 }
53- $pyTypeOpt = ' --sys-prefix' # install to $env:LOCALAPPDATA (not to $env:APPDATA with --user option)
5448 }
5549 default {
5650 Write-Error ' Unexpected option.'
@@ -63,67 +57,56 @@ if ($ProgressPreference -ne 'SilentlyContinue') {
6357 $ProgressPreference = ' SilentlyContinue'
6458}
6559
66- Write-Verbose " Downloading latest Python $PythonVersion for Windows..."
60+ Write-Host " Downloading latest Python $PythonVersion for Windows..."
6761$links = (Invoke-WebRequest - uri ' https://www.python.org/downloads/windows/' - UseBasicParsing).Links.href
6862$targetLinks = $links | Select-String - Pattern " .*python-($PythonVersion \.\d*)-amd64.exe"
6963$latestVer = $PythonVersion + ' .' + ($targetLinks -replace " .*python-$PythonVersion \.(\d*)-amd64.exe" , ' $1' | Measure-Object - Maximum).Maximum
7064$fileUri = ($targetLinks | Select-String - Pattern " .*python-$latestVer -amd64.exe" | Get-Unique ).Tostring().Trim()
7165Invoke-WebRequest - uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' pythoninstaller.exe' ) - Verbose
7266
73- Write-Verbose ' Downloading Node.js...'
67+ Write-Host ' Downloading Node.js...'
7468$releaseURI = ' https://nodejs.org/download/release/latest-v22.x'
7569$links = (Invoke-WebRequest - uri $releaseURI - UseBasicParsing).Links.href
7670$fileUri = ' https://nodejs.org' + ($links | Select-String - Pattern " x64.*\.msi" | Get-Unique ).Tostring().Trim()
7771Invoke-WebRequest - Uri $fileUri - OutFile (Join-Path $WorkingFolder ' \nodeinstaller.msi' )
7872
7973if ($InstallGit ) {
80- Write-Verbose ' Downloading latest Git for Windows...'
74+ Write-Host ' Downloading latest Git for Windows...'
8175 $releaseURI = ' https://github.com/git-for-windows/git/releases'
8276 $latestRelease = (Invoke-WebRequest - Uri " $releaseURI /latest" - UseBasicParsing - Headers @ {' Accept' = ' application/json' }| ConvertFrom-Json ).update_url
8377 $versionString = $latestRelease -replace ' .*tag/(.*)' , ' $1'
8478 $links = (Invoke-WebRequest - Uri " $releaseURI /expanded_assets/$ ( $versionString ) " - UseBasicParsing).Links.href
8579 $fileUri = ' https://github.com' + ($links | Select-String - Pattern ' .*64-bit.exe' | Get-Unique ).Tostring().Trim()
86- Write-Verbose " Download from $fileUri "
80+ Write-Host " Download from $fileUri "
8781 Invoke-WebRequest - Uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' gitinstaller.exe' ) - Verbose
8882}
8983
90- if ($InstallPwsh7ForPipKernel ) {
91- Write-Verbose ' Downloading latest PowerShell 7...'
92- $releaseURI = ' https://github.com/PowerShell/PowerShell/releases'
93- $latestRelease = (Invoke-WebRequest - Uri " $releaseURI /latest" - UseBasicParsing - Headers @ {' Accept' = ' application/json' }| ConvertFrom-Json ).update_url
94- $versionString = $latestRelease -replace ' .*tag/(.*)' , ' $1'
95- $links = (Invoke-WebRequest - Uri " $releaseURI /expanded_assets/$ ( $versionString ) " - UseBasicParsing).Links.href
96- $fileUri = ' https://github.com' + ($links | Select-String - Pattern ' .*x64.msi' | Get-Unique ).Tostring().Trim()
97- Write-Verbose " Download from $fileUri "
98- Invoke-WebRequest - Uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' pwsh.msi' ) - Verbose
99- }
100-
10184if ($InstallDotnetInteractive ) {
102- Write-Verbose ' Downloading latest .NET SDK...'
85+ Write-Host ' Downloading latest .NET SDK...'
10386 $links = (Invoke-WebRequest - Uri ' https://dotnet.microsoft.com/download' - UseBasicParsing).Links.href
10487 $latestVer = (($links | Select-String - Pattern ' .*sdk.*windows-x64-installer' ) -replace ' .*sdk-(([0-9]+\.){1}[0-9]+(\.[0-9]+)?)-.*' , ' $1' | Measure-Object - Maximum).Maximum
10588 $latestUri = ' https://dotnet.microsoft.com' + ($links | Select-String - Pattern " .*sdk-$latestVer -windows-x64-installer" | Get-Unique ).Tostring().Trim()
10689 $fileUri = ((Invoke-WebRequest - Uri $latestUri - UseBasicParsing).Links.href | Select-String - Pattern ' .*\.exe' | Get-Unique ).Tostring().Trim()
10790 Invoke-WebRequest - Uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' dotnet.exe' ) - Verbose
10891}
10992else {
110- Write-Verbose ' Downloading latest .NET Runtime...'
93+ Write-Host ' Downloading latest .NET Runtime...'
11194 $links = (Invoke-WebRequest - Uri ' https://dotnet.microsoft.com/en-us/download/dotnet/8.0/runtime' - UseBasicParsing).Links.href
11295 $latestVer = (($links | Select-String - Pattern ' .*runtime.*windows-x64-installer' ) -replace ' .*runtime-(([0-9]+\.){1}[0-9]+(\.[0-9]+)?)-.*' , ' $1' | Measure-Object - Maximum).Maximum
11396 $latestUri = ' https://dotnet.microsoft.com' + ($links | Select-String - Pattern " .*runtime-$latestVer -windows-x64-installer" | Get-Unique ).Tostring().Trim()
11497 $fileUri = ((Invoke-WebRequest - Uri $latestUri - UseBasicParsing).Links.href | Select-String - Pattern ' .*\.exe' | Get-Unique ).Tostring().Trim()
11598 Invoke-WebRequest - Uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' dotnet.exe' ) - Verbose
11699}
117100
118- if ( -not ( $UsePipKernel )) {
119- $releaseURI = ' https://github.com/sakaztk/Jupyter-PowerShellSDK/releases '
120- $latestRelease = ( Invoke-WebRequest - Uri " $releaseURI /latest " - UseBasicParsing - Headers @ { ' Accept ' = ' application/json ' } | ConvertFrom-Json ).update_url
121- $versionString = $latestRelease -replace ' .*tag/(.*) ' , ' $1 '
122- $links = ( Invoke-WebRequest - Uri " $releaseURI /expanded_assets/ $ ( $versionString ) " - UseBasicParsing).Links.href
123- Write-Verbose ' Downloading latest DeepAQ pwsh5 Kernel... '
124- $fileUri = ' https://github.com ' + ( $links | Select-String - Pattern ' .* PowerShell5.zip' | Get-Unique ).Tostring().Trim()
125- Invoke-WebRequest - uri $fileUri - UseBasicParsing - OutFile ( Join-Path $WorkingFolder ' PowerShell5.zip ' ) - Verbose
126- Write-Verbose ' Downloading latest DeepAQ pwshSDK Kernel...'
101+ $releaseURI = ' https://github.com/sakaztk/Jupyter-PowerShellSDK/releases '
102+ $latestRelease = ( Invoke-WebRequest - Uri " $releaseURI /latest " - UseBasicParsing - Headers @ { ' Accept ' = ' application/json ' } | ConvertFrom-Json ).update_url
103+ $versionString = $latestRelease -replace ' .*tag/(.*) ' , ' $1 '
104+ $links = ( Invoke-WebRequest - Uri " $releaseURI /expanded_assets/ $ ( $versionString ) " - UseBasicParsing).Links.href
105+ Write-Host ' Downloading latest DeepAQ pwsh5 Kernel... '
106+ $fileUri = ' https://github.com ' + ( $links | Select-String - Pattern ' .*PowerShell5.zip ' | Get-Unique ).Tostring().Trim()
107+ Invoke-WebRequest - uri $fileUri - UseBasicParsing - OutFile ( Join-Path $WorkingFolder ' PowerShell5.zip' ) - Verbose
108+ if ( $InstallPwsh7SDK ) {
109+ Write-Host ' Downloading latest DeepAQ pwshSDK Kernel...'
127110 $fileUri = ' https://github.com' + ( $links | Select-String - Pattern ' Jupyter-PowerShellSDK-7.*\.zip' | Get-Unique ).Tostring().Trim()
128111 Invoke-WebRequest - uri $fileUri - UseBasicParsing - OutFile (Join-Path $WorkingFolder ' PowerShellSDK.zip' ) - Verbose
129112}
@@ -133,7 +116,7 @@ if ($null -ne $exProgressPreference) {
133116 $ProgressPreference = $exProgressPreference
134117}
135118
136- Write-Verbose ' Installing Python...'
119+ Write-Host ' Installing Python...'
137120Start-Process - FilePath (Join-Path $WorkingFolder ' pythoninstaller.exe' ) - ArgumentList $installOpt - Wait
138121if ($CleanupDownloadFiles ) {
139122 Start-Sleep - Seconds 5
@@ -144,84 +127,47 @@ $pythonRoot = Split-Path (python -c "import sys; print(sys.executable)") -Parent
144127$kernelPath = Join-Path $pythonRoot ' \share\jupyter\kernels'
145128$packagePath = Join-Path $pythonRoot ' \Lib\site-packages'
146129
147- Write-Verbose ' Installing Node.js...'
130+ Write-Host ' Installing Node.js...'
148131Start-Process - FilePath (Join-Path $WorkingFolder ' nodeinstaller.msi' ) - ArgumentList (' /passive' ) - wait
149132if ($CleanupDownloadFiles ) {
150133 Start-Sleep - Seconds 5
151134 Remove-Item (Join-Path $WorkingFolder ' nodeinstaller.msi' ) - Force
152135}
153136
154- if ($InstallGit ) {
155- Write-Verbose ' Installing latest Git for Windows...'
156- $installOpt = ' /SILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh"'
157- Start-Process - FilePath (Join-Path $WorkingFolder ' gitinstaller.exe' ) - ArgumentList ($installOpt ) - wait
158- $env: Path = [System.Environment ]::GetEnvironmentVariable(" Path" , " Machine" ) + " ;" + [System.Environment ]::GetEnvironmentVariable(" Path" , " User" )
159- if ( $CleanupDownloadFiles ) {
160- Start-Sleep - Seconds 5
161- Remove-Item (Join-Path $WorkingFolder ' gitinstaller.exe' ) - Force
162- }
163- }
164-
165- Write-Verbose ' ##### Jupyter Installation #####'
137+ Write-Host ' ##### Jupyter Installation #####'
166138python - m pip install -- upgrade pip
167139python - m pip install -- upgrade wheel
168140python - m pip install jupyter
169141python - m pip install notebook
170142python - m pip install jupyterlab
171- if ($InstallNBExtensions ) {
172- python - m pip install jupyter_nbextensions_configurator
173- python - m jupyter nbextensions_configurator enable
174- python - m pip install https:// github.com / ipython- contrib/ jupyter_contrib_nbextensions/ tarball/ master
175- python - m jupyter contrib nbextension install $pyTypeOpt
176- }
177- if ($UsePipKernel ) {
178- python - m pip install powershell_kernel
179- python - m powershell_kernel.install $pyTypeOpt
180- $fileContent = Get-Content " $packagePath \powershell_kernel\powershell_proxy.py" - Raw
181- $fileContent = $filecontent -replace ' \^' , ' \a'
182- $filecontent | Set-Content " $packagePath \powershell_kernel\powershell_proxy.py" - Force
183- if ($InstallPwsh7ForPipKernel ) {
184- Write-Verbose ' Installing PowerShell 7...'
185- Start-Process - FilePath (Join-Path $WorkingFolder ' pwsh.msi' ) - ArgumentList ' /passive' - Wait
186- Copy-Item - Path " $kernelPath \powershell" - Destination " $kernelPath \powershell7" - Recurse - Force
187- $fileContent = Get-Content " $kernelPath \powershell7\kernel.json" - Raw
188- $fileContent = $filecontent -replace ' "display_name": "[^"]*"' , ' "display_name": "PowerShell 7"'
189- $fileContent = $filecontent -replace ' "powershell_command": "[^"]*"' , " `" powershell_command`" : `" pwsh.exe`" "
190- $filecontent | Set-Content " $kernelPath \powershell7\kernel.json"
191- if ($CleanupDownloadFiles ) {
192- Start-Sleep - Seconds 5
193- Remove-Item (Join-Path $WorkingFolder ' pwsh.msi' ) - Force
194- }
195- }
196- }
197- else {
198- Write-Verbose ' Installing DeepAQ pwsh5 Kernel...'
199- $installPath = Join-Path $packagePath ' powershell5_kernel'
200- Expand-Archive - Path (Join-Path $WorkingFolder ' PowerShell5.zip' ) - DestinationPath $installPath - Force
201- New-Item - ItemType Directory - Path (Join-Path $kernelPath ' \powershell5\' ) - Force
202- Invoke-WebRequest - UseBasicParsing - Verbose - Uri ' https://raw.githubusercontent.com/PowerShell/PowerShell/master/assets/Powershell_64.png' - OutFile (Join-Path $kernelPath ' \powershell5\logo-64x64.png' )
203- Add-Type - AssemblyName System.Drawing
204- $image = [System.Drawing.Image ]::FromFile((Join-Path $kernelPath ' \powershell5\logo-64x64.png' ))
205- $bitmap32 = New-Object System.Drawing.Bitmap(32 , 32 )
206- [System.Drawing.Graphics ]::FromImage($bitmap32 ).DrawImage($image , 0 , 0 , 32 , 32 )
207- $bitmap32.Save ((Join-Path $kernelPath ' \powershell5\logo-32x32.png' ), [System.Drawing.Imaging.ImageFormat ]::Png)
143+
144+ Write-Host ' Installing DeepAQ pwsh5 Kernel...'
145+ $installPath = Join-Path $packagePath ' powershell5_kernel'
146+ Expand-Archive - Path (Join-Path $WorkingFolder ' PowerShell5.zip' ) - DestinationPath $installPath - Force
147+ New-Item - ItemType Directory - Path (Join-Path $kernelPath ' \powershell5\' ) - Force
148+ Invoke-WebRequest - UseBasicParsing - Verbose - Uri ' https://raw.githubusercontent.com/PowerShell/PowerShell/master/assets/Powershell_64.png' - OutFile (Join-Path $kernelPath ' \powershell5\logo-64x64.png' )
149+ Add-Type - AssemblyName System.Drawing
150+ $image = [System.Drawing.Image ]::FromFile((Join-Path $kernelPath ' \powershell5\logo-64x64.png' ))
151+ $bitmap32 = New-Object System.Drawing.Bitmap(32 , 32 )
152+ [System.Drawing.Graphics ]::FromImage($bitmap32 ).DrawImage($image , 0 , 0 , 32 , 32 )
153+ $bitmap32.Save ((Join-Path $kernelPath ' \powershell5\logo-32x32.png' ), [System.Drawing.Imaging.ImageFormat ]::Png)
208154@"
209155{
210- "argv": [
211- "$ ( $installPath.replace (' \' , ' /' )) /Jupyter_PowerShell5.exe",
212- "{connection_file}"
213- ],
214- "display_name": "PowerShell 5",
215- "language": "Powershell"
156+ "argv": [
157+ "$ ( $installPath.replace (' \' , ' /' )) /Jupyter_PowerShell5.exe",
158+ "{connection_file}"
159+ ],
160+ "display_name": "PowerShell 5",
161+ "language": "Powershell"
216162}
217163"@ | Set-Content - Path (Join-Path $kernelPath ' \powershell5\kernel.json' )
218- Move-Item - Path (Join-Path $installPath ' *.png' ) - Destination (Join-Path $kernelPath ' \powershell5\' ) - Force
219- if ( $CleanupDownloadFiles ) {
220- Remove-Item (Join-Path $WorkingFolder ' PowerShell5.zip' ) - Force
221- }
164+ Move-Item - Path (Join-Path $installPath ' *.png' ) - Destination (Join-Path $kernelPath ' \powershell5\' ) - Force
165+ if ( $CleanupDownloadFiles ) {
166+ Remove-Item (Join-Path $WorkingFolder ' PowerShell5.zip' ) - Force
222167}
168+
223169if ($InstallPwsh7SDK ) {
224- Write-Verbose ' Installing DeepAQ pwshSDK Kernel...'
170+ Write-Host ' Installing DeepAQ pwshSDK Kernel...'
225171 $installPath = Join-Path $packagePath ' powershellSDK_kernel'
226172 Expand-Archive - Path (Join-Path $WorkingFolder ' PowerShellSDK.zip' ) - DestinationPath $installPath - Force
227173 New-Item - ItemType Directory - Path (Join-Path $kernelPath ' \powershellSDK\' ) - Force
@@ -233,12 +179,12 @@ if ($InstallPwsh7SDK) {
233179 $bitmap32.Save ((Join-Path $kernelPath ' \powershellSDK\logo-32x32.png' ), [System.Drawing.Imaging.ImageFormat ]::Png)
234180@"
235181{
236- "argv": [
237- "$ ( $installPath.replace (' \' , ' /' )) /Jupyter_PowerShellSDK.exe",
238- "{connection_file}"
239- ],
240- "display_name": "PowerShell 7 (SDK)",
241- "language": "Powershell"
182+ "argv": [
183+ "$ ( $installPath.replace (' \' , ' /' )) /Jupyter_PowerShellSDK.exe",
184+ "{connection_file}"
185+ ],
186+ "display_name": "PowerShell 7 (SDK)",
187+ "language": "Powershell"
242188}
243189"@ | Set-Content - Path (Join-Path $kernelPath ' \powershellSDK\kernel.json' )
244190 Move-Item - Path (Join-Path $installPath ' *.png' ) - Destination (Join-Path $kernelPath ' \powershellSDK\' ) - Force
@@ -248,9 +194,9 @@ if ($InstallPwsh7SDK) {
248194}
249195
250196if ($InstallDotnetInteractive ) {
251- Write-Verbose ' Installing .NET Core SDK...'
197+ Write-Host ' Installing .NET Core SDK...'
252198 Start-Process - FilePath (Join-Path $WorkingFolder ' dotnet.exe' ) - ArgumentList ' /install /passive /norestart' - Wait
253- Write-Verbose ' Installing .NET Interactive...'
199+ Write-Host ' Installing .NET Interactive...'
254200 $env: Path = [System.Environment ]::GetEnvironmentVariable(" Path" , " Machine" ) + " ;" + [System.Environment ]::GetEnvironmentVariable(" Path" , " User" )
255201 dotnet tool install - g -- add-source " https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" Microsoft.dotnet- interactive
256202 dotnet interactive jupyter install -- path " $kernelPath "
@@ -260,7 +206,7 @@ if ($InstallDotnetInteractive) {
260206 }
261207}
262208elseif ($InstallPwsh7SDK ) {
263- Write-Verbose ' Installing .NET Runtime...'
209+ Write-Host ' Installing .NET Runtime...'
264210 Start-Process - FilePath (Join-Path $WorkingFolder ' dotnet.exe' ) - ArgumentList ' /install /passive /norestart' - Wait
265211 if ($CleanupDownloadFiles ) {
266212 Start-Sleep - Seconds 5
0 commit comments