<# .SYNOPSIS Creates a Configuration Manager package and program for a script, then sends it to your distribution points. .DESCRIPTION Connects to a ConfigMgr (MECM) site, checks the content folder, creates a legacy package with a single standard program, and starts content distribution to one or more distribution point groups. If a package with the same name already exists, the script stops rather than creating a duplicate. Supports -WhatIf. .PARAMETER SiteCode Your three-character site code, for example ABC. .PARAMETER ProviderMachineName The SMS Provider server. Defaults to this computer. .PARAMETER PackageName Name for the new package. .PARAMETER SourcePath UNC path to the package content. It must already contain the file your command line runs. .PARAMETER CommandLine The program's command line, relative to the package content. .PARAMETER DistributionPointGroupName One or more distribution point groups to send the content to. Leave it off to skip distribution. .EXAMPLE .\New-CMScriptPackage.ps1 -SiteCode ABC -PackageName 'Set Power Plan' -SourcePath '\\sccm01\Sources\Scripts\PowerPlan' -CommandLine 'powershell.exe -ExecutionPolicy Bypass -NoProfile -File .\Set-PowerPlan.ps1' -DistributionPointGroupName 'All DPs' #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][ValidatePattern('^[A-Za-z0-9]{3}$')][string]$SiteCode, [string]$ProviderMachineName = $env:COMPUTERNAME, [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$PackageName, [string]$Description = '', [Parameter(Mandatory)][ValidatePattern('^\\\\')][string]$SourcePath, [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$CommandLine, [ValidateLength(1, 50)][string]$ProgramName = 'Install', [ValidateSet('OnlyWhenUserIsLoggedOn', 'WhetherOrNotUserIsLoggedOn', 'OnlyWhenNoUserIsLoggedOn')] [string]$ProgramRunType = 'WhetherOrNotUserIsLoggedOn', [ValidateSet('Normal', 'Minimized', 'Maximized', 'Hidden')][string]$RunType = 'Hidden', [string[]]$DistributionPointGroupName ) $ErrorActionPreference = 'Stop' # Check the content before we touch ConfigMgr. The site server reads this path, not your PC. if (-not (Test-Path -LiteralPath $SourcePath -PathType Container)) { throw "Source path '$SourcePath' doesn't exist or isn't reachable." } $firstFile = ($CommandLine -split '\s+' | Where-Object { $_ -match '\.(ps1|cmd|bat|exe|msi|vbs)"?$' } | Select-Object -Last 1) if ($firstFile) { $candidate = '{0}\{1}' -f $SourcePath.TrimEnd('\'), ($firstFile.Trim('"') -replace '^\.\\', '') if (-not (Test-Path -LiteralPath $candidate)) { Write-Warning "Couldn't find '$candidate'. Check the command line matches the content." } } # Load the ConfigMgr module from the console install and map the site drive. if (-not (Get-Module ConfigurationManager)) { if (-not $env:SMS_ADMIN_UI_PATH) { throw 'The Configuration Manager console is not installed on this machine.' } Import-Module (Join-Path $env:SMS_ADMIN_UI_PATH '..\ConfigurationManager.psd1') } if (-not (Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue)) { New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName | Out-Null } Push-Location "$($SiteCode):\" try { if (Get-CMPackage -Name $PackageName -Fast) { throw "A package named '$PackageName' already exists. Pick another name or update the existing one." } if ($PSCmdlet.ShouldProcess($PackageName, "Create package from $SourcePath")) { $package = New-CMPackage -Name $PackageName -Description $Description -Path $SourcePath Write-Verbose "Created package $($package.PackageID)" $programArgs = @{ PackageId = $package.PackageID StandardProgramName = $ProgramName CommandLine = $CommandLine ProgramRunType = $ProgramRunType RunType = $RunType RunMode = 'RunWithAdministrativeRights' } New-CMProgram @programArgs | Out-Null Write-Verbose "Added program '$ProgramName'" $distributed = @() foreach ($group in $DistributionPointGroupName) { try { Start-CMContentDistribution -PackageId $package.PackageID -DistributionPointGroupName $group $distributed += $group } catch { Write-Warning "Distribution to '$group' failed: $($_.Exception.Message)" } } [pscustomobject]@{ PackageName = $PackageName PackageId = $package.PackageID Program = $ProgramName CommandLine = $CommandLine SourcePath = $SourcePath DistributedTo = $distributed -join ', ' } } } finally { Pop-Location }