Last active
June 16, 2021 17:56
-
-
Save dotps1/492023ebd737f9cc46aa to your computer and use it in GitHub Desktop.
Creates a new Sccm Java Application and Deployment Type. All three functions are required. (See comments for details.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Param ( | |
| [Parameter( | |
| Mandatory = $true | |
| )] | |
| [String] | |
| $SourcePackageCreationPath, | |
| [Parameter( | |
| Mandatory = $true | |
| )] | |
| [String] | |
| $ComputerName, | |
| [Parameter()] | |
| [PSCredential] | |
| $Credential, | |
| [Parameter( | |
| Mandatory = $true | |
| )] | |
| [String] | |
| $SiteCode, | |
| [Parameter()] | |
| [String] | |
| $ApplicationFolder, | |
| [Parameter()] | |
| [System.Security.Cryptography.X509Certificates.X509Certificate2] | |
| $CodeSigningCertificate | |
| ) | |
| #region Main | |
| $ErrorActionPreference = 'Stop' | |
| if (($installers = Invoke-JavaDownloadAndMsiExtraction -Verbose:$VerbosePreference) -eq $null) { | |
| throw $_ | |
| } | |
| # Installer script to be generated in package directory. | |
| $installScript = @" | |
| `$location = Split-Path -Path `$(`$global:MyInvocation.MyCommand.Path) | |
| `$architecture = (Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name 'PROCESSOR_ARCHITECTURE').PROCESSOR_ARCHITECTURE | |
| # Uninstall existing versions of Java $($installers.VersionInfo.ProductMajorPart). | |
| foreach (`$install in (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { `$_.DisplayName -match 'Java $($installers.VersionInfo.ProductMajorPart) Update \d+' })) { | |
| Start-Process -FilePath "msiexec.exe" -ArgumentList "/x `$(`$install.PSChildName) /quiet" -Wait | |
| } | |
| if (-not (Test-Path -Path "`$env:ProgramData\Oracle\Java")) { | |
| New-Item -Path "`$env:ProgramData\Oracle\Java" -ItemType Directory -Force | Out-Null | |
| } | |
| # Ensure Java Settings Config file exists in the ProgramData Directory. | |
| Copy-Item -Path `${location}\java.settings.cfg -Destination "`$env:ProgramData\Oracle\Java" -Force | |
| if (`$architecture -eq 'AMD64') { | |
| foreach (`$install in (Get-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { `$_.DisplayName -match 'Java $($installers.VersionInfo.ProductMajorPart) Update \d+' })) { | |
| Start-Process -FilePath "msiexec.exe" -ArgumentList "/x `$(`$install.PSChildName) /quiet" -Wait | |
| } | |
| } | |
| try { | |
| # Install x86. | |
| Start-Process -FilePath 'msiexec.exe' -ArgumentList "/i `${location}\x86.msi INSTALLCFG=`${location}\java.settings.cfg /quiet" -Wait -ErrorAction Stop | |
| # Install x64 on compatiable systems. | |
| if (`$architecture -eq 'AMD64') { | |
| Start-Process -FilePath 'msiexec.exe' -ArgumentList "/i `${location}\x64.msi INSTALLCFG=`${location}\java.settings.cfg /quiet" -Wait -ErrorAction Stop | |
| } | |
| exit 0 | |
| } catch { | |
| exit 1 | |
| } | |
| "@ | |
| # Java installer config file to be generated in package directory. | |
| $installSettings = @' | |
| AUTO_UPDATE=0 | |
| REBOOT=0 | |
| NOSTARTMENU=1 | |
| '@ | |
| # Create output folder for package. | |
| try { | |
| Write-Verbose -Message "Creating output directory: $SourcePackageCreationPath\$($installers.VersionDisplayName)." | |
| $package = New-Item -Path $SourcePackageCreationPath -Name $installers.VersionDisplayName -ItemType Directory -Force -ErrorAction Stop | |
| } catch { | |
| throw $_ | |
| } | |
| # Copy installers to folder. | |
| try { | |
| Write-Verbose -Message "Copying $($installers.x86Msi.FullName) to $($package.FullName)\x86.msi." | |
| Copy-Item -Path $installers.x86Msi.FullName -Destination "$($package.FullName)\x86.msi" -Force -ErrorAction Stop | |
| Write-Verbose -Message "Copying $($installers.x64Msi.FullName) to $($package.FullName)\x64.msi." | |
| Copy-Item -Path $installers.x64Msi.FullName -Destination "$($package.FullName)\x64.msi" -Force -ErrorAction Stop | |
| } catch { | |
| throw $_ | |
| } | |
| # Extract install script and settings file to package folder. | |
| try { | |
| Write-Verbose -Message "Extracting Install-Java.ps1 to $($package.FullName)." | |
| Out-File -FilePath "$($package.FullName)\Install-Java.ps1" -InputObject $installScript -Encoding ascii -NoNewline -Force -ErrorAction Stop | |
| # Sign the extracted script. | |
| if ($PSBoundParameters.ContainsKey('CodeSigningCertificate')) { | |
| try { | |
| Write-Verbose -Message "Signing $($package.FullName)\Install-Java.ps1 with $($CodeSigningCertificate.Subject)." | |
| Set-AuthenticodeSignature -Certificate $CodeSigningCertificate -FilePath "$($package.FullName)\Install-Java.ps1" -ErrorAction Stop | Out-Null | |
| } catch { | |
| throw $_ | |
| } | |
| } | |
| Write-Verbose -Message "Extracting java.settings.cfg to $($package.FullName)." | |
| Out-File -FilePath "$($package.FullName)\java.settings.cfg" -InputObject $installSettings -Encoding ascii -NoNewline -Force -ErrorAction Stop | |
| } catch { | |
| throw $_ | |
| } | |
| #region CreateSccmApplicaion. | |
| try { | |
| $currentVerbosePreference = $VerbosePreference | |
| $VerbosePreference = 'SilentlyContinue' | |
| $sessionParams = @{ | |
| ComputerName = $ComputerName | |
| } | |
| if ($PSBoundParameters.ContainsKey('Credential')) { | |
| $sessionParams.Add('Credential', $Credential) | |
| } | |
| $session = New-PSSession @sessionParams | |
| Invoke-Command -Session $session -ScriptBlock { | |
| Import-Module -Name "$(Split-Path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1" -Verbose:$false | |
| Set-Location -Path "$(Get-PSDrive -PSProvider CMSite):\" | |
| } | |
| Import-PSSession -Session $session -Module ConfigurationManager -AllowClobber | Out-Null | |
| $VerbosePreference = $currentVerbosePreference | |
| } catch { | |
| throw $_ | |
| } | |
| if (Get-CMApplication -Name $installers.VersionInfo.ProductName) { | |
| throw "The application $($installers.VersionInfo.ProductName) already exists." | |
| } | |
| $applicationParams = @{ | |
| Name = $installers.VersionInfo.ProductName | |
| Description = "$($installers.VersionInfo.ProductName)" | |
| SoftwareVersion = $installers.VersionInfo.ProductVersion | |
| LocalizedName = "$($installers.VersionInfo.ProductName)" | |
| LocalizedDescription = "Installs and configures $($installers.VersionInfo.ProductName) for both x86 and x64 Systems. Please restart any open browsers after running this install." | |
| } | |
| try { | |
| Write-Verbose -Message 'Creating application.' | |
| $application = New-CMApplication @applicationParams | |
| } catch { | |
| throw $_ | |
| } | |
| $deploymentParams = @{ | |
| ApplicationName = $application.LocalizedDisplayName | |
| ProductCode = "{$($installers.x86MsiProductCode)}" | |
| DeploymentTypeName = "$($installers.VersionInfo.ProductName) - Script Installer" | |
| InstallCommand = "powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Install-Java.ps1" | |
| ContentLocation = $package.FullName | |
| EstimatedRuntimeMins = 5 | |
| MaximumRuntimeMins = 15 | |
| LogonRequirementType = 'WhereOrNotUserLoggedOn' | |
| UserInteractionMode = 'Hidden' | |
| } | |
| try { | |
| Write-Verbose -Message 'Creating deployment type.' | |
| $deployment = Add-CMScriptDeploymentType @deploymentParams | |
| } catch { | |
| throw $_ | |
| } | |
| if ($PSBoundParameters.ContainsKey('ApplicationFolder')) { | |
| try { | |
| Write-Verbose -Message "Moving application to appropriate folder." | |
| $applicationID = Get-WmiObject -Namespace Root\SMS\Site_$SiteCode -Class SMS_ApplicationLatest -Filter "LocalizedDisplayName='$($installers.VersionInfo.ProductName)'" -ComputerName $ComputerName | |
| $targetFolderID = Get-WmiObject -Namespace Root\SMS\Site_$SiteCode -Class SMS_ObjectContainerNode -Filter "Name='$($ApplicationFolder)' and ObjectType='6000'" -ComputerName $ComputerName | |
| $currentFolderID = 0 | |
| $wmiConnection = [WMIClass]"\\$($ComputerName)\root\SMS\Site_$($SiteCode):SMS_objectContainerItem" | |
| $moveItem = $wmiConnection.psbase.GetMethodParameters("MoveMembers") | |
| $moveItem.ContainerNodeID = $currentFolderId | |
| $moveItem.InstanceKeys = $applicationID.ModelName | |
| $moveItem.ObjectType = 6000 | |
| $moveItem.TargetContainerNodeID = $targetFolderID.ContainerNodeID | |
| $wmiConnection.psbase.InvokeMethod("MoveMembers",$moveItem,$null) | Out-Null | |
| } catch { | |
| throw $_ | |
| } | |
| } | |
| Write-Verbose -Message 'Application created succsesfully in the root application folder.' | |
| #endregion CreateSccmApplication | |
| #endregion Main |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Gets the product code from a Windows Installer Database. | |
| .DESCRIPTION | |
| Opens a Windows Installer Database (.msi) and querys for the product code. | |
| .INPUTS | |
| System.String. | |
| .OUTPUTS | |
| System.Guid. | |
| .EXAMPLE | |
| PS C:\> Get-MsiProductCode -Path C:\my.msi | |
| .LINK | |
| http://dotps1.github.io | |
| #> | |
| Function Get-MsiProductCode { | |
| [OutputType([Guid])] | |
| Param ( | |
| [Parameter( | |
| Mandatory = $true, | |
| ValueFromPipeLine = $true | |
| )] | |
| [String] | |
| $Path | |
| ) | |
| try { | |
| $windowsInstaller = New-Object -com WindowsInstaller.Installer | |
| $database = $windowsInstaller.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstaller, @((Get-Item -Path $Path).FullName, 0)) | |
| $view = $database.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $database, ("SELECT Value FROM Property WHERE Property = 'ProductCode'")) | |
| $view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null) | |
| $record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null) | |
| return $($record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1)) | |
| $view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null) | |
| [Void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($windowsInstaller) | |
| } catch { | |
| throw $_ | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Downloads and extracts the latest version of Java Runtime Environment. | |
| .DESCRIPTION | |
| Download the x86 and x64 offline installer executables for the Java Website. | |
| Runs each exeacuatble, which then extracts the MSIs to the current users APPDATA. | |
| .INPUTS | |
| None. | |
| .OUTPUTS | |
| System.Management.Automation.PSCustomObject. | |
| .EXAMPLE | |
| Invoke-JavaDownloadAndExtraction | |
| .EXAMPLE | |
| Invoke-JavaDownloadAndExtraction -Verbose | |
| .NOTES | |
| The current Java Installer Staging directory will be removed then recreated. | |
| .LINK | |
| http://www.java.com/en/download/manual.jsp | |
| #> | |
| Function Invoke-JavaDownloadAndMsiExtraction { | |
| [CmdletBinding()] | |
| [OutputType( | |
| [PSCustomObject] | |
| )] | |
| Param ( | |
| ) | |
| Begin { | |
| # Verify Admin Rights before running. | |
| if (-not ([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]'Administrator')) { | |
| throw 'This cmdlet cannot be used in this context. Restart PowerShell using the Run As Administrator option.' | |
| } | |
| } | |
| Process { | |
| # Download offline installers. | |
| $downloadPage = Invoke-WebRequest -Uri 'http://www.java.com/en/download/manual.jsp' | |
| $x86Download = ($downloadPage.Links | Where-Object { $_.innerText -eq 'Windows Offline' }).href | |
| $x64Download = ($downloadPage.Links | Where-Object { $_.innerText -eq 'Windows Offline (64-Bit)' }).href | |
| $downloader = New-Object -TypeName System.Net.WebClient | |
| try { | |
| Write-Verbose -Message "Downloading Java x86 Offline Installer. URL: $x86Download" | |
| $downloader.DownloadFile($x86Download, "$env:USERPROFILE\Downloads\Java_x86.exe") | |
| Write-Verbose -Message "Downloading Java x64 Offline Installer. URL: $x64Download" | |
| $downloader.DownloadFile($x64Download, "$env:USERPROFILE\Downloads\Java_x64.exe") | |
| $x86Exe = Get-Item -Path "$env:USERPROFILE\Downloads\Java_x86.exe" | |
| $x64Exe = Get-Item -Path "$env:USERPROFILE\Downloads\Java_x64.exe" | |
| } catch { | |
| throw $_ | |
| } | |
| # Delete Java Install staging directory. | |
| try { | |
| $stagingDirectory = "$env:USERPROFILE\AppData\LocalLow\Oracle" | |
| if (Test-Path -Path $stagingDirectory) { | |
| Write-Verbose -Message "Removing existing Java Install Staging Directory: $stagingDirectory." | |
| Remove-Item -Path $stagingDirectory -Recurse -Force -ErrorAction Stop | |
| } | |
| # Recreate the directory to make sure the path exists for the get child item. | |
| Write-Verbose -Message "Creating new Java Install Staging Directory: $stagingDirectory." | |
| $stagingDirectory = New-Item -Path $stagingDirectory -Name 'Java' -ItemType Directory -Force | |
| } catch { | |
| throw $_ | |
| } | |
| # Trigger x86 .exe to extract msi to install staging directory. | |
| Write-Verbose -Message "Starting Java 32-bit Installer to extract msi to $stagingDirectory." | |
| Write-Warning -Message 'DO NOT CLOSE THE JAVA INSTALLER WINDOW, IT WILL CLOSE IT SELF AFTER THE MSI IS EXTRACTED.' | |
| Start-Process -FilePath $x86Exe.FullName | |
| do { | |
| $x86Msi = Get-ChildItem -Path "$($stagingDirectory.FullName)\jre*" -Filter 'jre*.msi' -Recurse | |
| Start-Sleep -Milliseconds 2500 | |
| } until ($x86Msi.Exists) | |
| Write-Verbose -Message "32-bit msi extracted, terminating Java processes." | |
| do { | |
| $processes = Get-WmiObject -Class Win32_Process | Where-Object { $_.Path -match 'Java' } | |
| foreach ($process in $processes) { | |
| Invoke-WmiMethod -InputObject $process -Name Terminate | Out-Null | |
| } | |
| Start-Sleep -Milliseconds 2500 | |
| } until ($processes.Count -eq 0) | |
| Write-Verbose -Message "Starting Java 64-bit Installer to extract msi to $stagingDirectory." | |
| Write-Warning -Message 'DO NOT CLOSE THE JAVA INSTALLER WINDOW, IT WILL CLOSE IT SELF AFTER THE MSI IS EXTRACTED.' | |
| Start-Process -FilePath $x64Exe.FullName | |
| do { | |
| $x64Msi = Get-ChildItem -Path "$($stagingDirectory.FullName)\jre*x64" -Filter 'jre*.msi' -Recurse | |
| Start-Sleep -Milliseconds 2500 | |
| } until ($x64Msi.Exists) | |
| Write-Verbose -Message "64-bit msi extracted, terminating Java processes." | |
| do { | |
| $processes = Get-WmiObject -Class Win32_Process | Where-Object { $_.Path -match 'Java' } | |
| foreach ($process in $processes) { | |
| Invoke-WmiMethod -InputObject $process -Name Terminate | Out-Null | |
| } | |
| Start-Sleep -Milliseconds 2500 | |
| } until ($processes.Count -eq 0) | |
| [PSCustomObject]$psCustomObject = @{ | |
| x86Msi = $x86Msi | |
| x86MsiProductCode = [Guid]::New((Get-MsiProductCode -Path $x86Msi.FullName)) | |
| x64Msi = $x64Msi | |
| x64MsiProductCode = [Guid]::New((Get-MsiProductCode -Path $x64Msi.FullName)) | |
| VersionDisplayName = $x86Msi.PSParentPath.Substring($x86Msi.PSParentPath.LastIndexOf([System.IO.Path]::DirectorySeparatorChar) +1) | |
| VersionInfo = $x86Exe.VersionInfo | |
| } | |
| } | |
| End { | |
| Write-Verbose -Message "Deleting Java Offline Installers." | |
| Remove-Item -Path $x86Exe.FullName -Force | |
| Remove-Item -Path $x64Exe.FullName -Force | |
| return $psCustomObject | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
running .New-SccmJavaApplication.ps1 :
I get error:
The term 'Invoke-JavaDownloadAndMsiExtraction' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
Suggestion [3,General]: The command Invoke-JavaDownloadAndMsiExtraction was not found, but does exist in the current
location. Windows PowerShell does not load commands from the current location by default. If you trust this command,
instead type: ".\Invoke-JavaDownloadAndMsiExtraction". See "get-help about_Command_Precedence" for more details.
After doing the change in New-SccmJavaApplication.ps1, I get:
ScriptHalted
At .... .New-SccmJavaApplication.ps1:38 char:5
Any Idea ?