{"id":115,"date":"2017-07-22T00:20:32","date_gmt":"2017-07-22T04:20:32","guid":{"rendered":"http:\/\/ziviz.us\/WP\/?p=115"},"modified":"2017-07-24T22:18:09","modified_gmt":"2017-07-25T02:18:09","slug":"deploy-applications-via-sccm-2016-powershell-cmdlets","status":"publish","type":"post","link":"https:\/\/www.ziviz.net\/WP\/2017\/07\/22\/deploy-applications-via-sccm-2016-powershell-cmdlets\/","title":{"rendered":"Deploy Applications via SCCM 2016 PowerShell cmdlets"},"content":{"rendered":"<p>Continuing my PowerShell automation notes for SCCM. Below is a rough example on how to deploy Applications in SCCM 2016 using PowerShell. The real meat of it comes down to 5 cmdlets. As an extra goodie, also included the cmdlet to remove old deployments as well. Note: If you are using these cmdlets on a new machine or account, the account that is to run these cmdlets should open the SCCM console on that machine, and click the &#8220;Connect with PowerShell&#8221; option first. If the account has not performed these steps, the SCCM drive will not be available when the SCCM cmdlets are imported. You will see errors such as &#8220;A drive with the name &#8216;xyz&#8217; does not exist.&#8221;<\/p>\n<h3>Command Run Down<\/h3>\n<p>The core commands we are interested in are<\/p>\n<pre><code>New-CMApplication # Creates a new application in SCCM<\/code><\/pre>\n<pre><code>Add-CMScriptDeploymentType # Adds a script based deployment type or optionally\r\nAdd-\u200bCM\u200bMsi\u200bDeployment\u200bType # Which will add an MSI deployment type<\/code><\/pre>\n<p>An additional note here on these two. These are currently your only deployment options and this directly limits your installation detection options. MSI is locked down to using the MSI product GUID for installation detection. If you need anything more complex than that, you are pretty much stuck with using a script based detection method and the script deployment type. The registry key and file options are not currently available. Luckily you can do nearly any detection method in PowerShell. The script below for example checks a registry key. For more information on creating a script for PowerShell based installation detection methods see the relevant <a href=\"https:\/\/docs.microsoft.com\/en-us\/sccm\/apps\/deploy-use\/create-applications#use-a-custom-script-to-check-for-the-presence-of-a-deployment-type\">docs.microsoft.com<\/a> article and also <a href=\"https:\/\/david-obrien.net\/2013\/12\/configmgr-powershell-application-detection-methods\/\">David O&#8217;Brien&#8217;s blog<\/a>.<\/p>\n<pre><code>Start-CMContentDistribution # Distributes our content to our Distribution Points<\/code><\/pre>\n<pre><code>Start-CMApplicationDeployment # Actually deploys our finished application package to end users<\/code><\/pre>\n<pre><code>Remove-CMDeployment # Removes deployments. Useful if you have an older deployment you are replacing<\/code><\/pre>\n<pre><code>Move-CMObject # Moves your Application to a different folder within the SCCM console<\/code><\/pre>\n<h3>Example Script<\/h3>\n<pre><code>\r\nParam\r\n(\r\n    [string]$PackageDirectory=\"\\\\Path\\To\\Package\\Source\\\",#Package source\r\n    [string]$IconPath=\"C:\\SomePath\\SomeIcon.ico\",#Icon to show in software center\r\n    [string]$SCCMDrive=\"SCM:\\\",#Should be your 3 character site code generally\r\n    [string]$SCCMAdmin=\"john.doe\",#Owning admin\r\n    [string]$TargetCollection=\"All Windows Workstations\",#Collection to deploy to\r\n    [string]$LogPath=\"C:\\Logs\\somelog.log\",#Path to save log\r\n    [string]$TargetDPs = \"All Distribution Points\"#Distribution point group to deploy to\r\n)\r\n#Start a log\r\n$Log = \"Starting Package Script`r`n\"\r\ntry\r\n{\r\n    #Import SCCM Module\r\n    Import-Module \"C:\\Program Files (x86)\\Microsoft Configuration Manager\\AdminConsole\\bin\\ConfigurationManager.psd1\" -ErrorAction Stop\r\n    if (-not (Test-Path -Path $SCCMDrive))\r\n    {\r\n        $Log+=\"SCCM PowerShell cmdlets provider is not initialized for this account, on this machine. Please open the SCCM console and select 'Connect with PowerShell' at least once before using this script on thise machine.`r`n\"\r\n        throw \"SCCM PSProvider does not have a drive assigned\"\r\n}\r\ncatch\r\n{\r\n    #End script if we could not add module\r\n    $Log += \"Failed to add required module!`r`n\"\r\n    $Log += \"----End Package Script----`r`n\"\r\n    $Log | Out-File -FilePath $LogPath -Append\r\n    exit 1\r\n}\r\n\r\n#TODO: Prepare files as needed here\r\n#Maybe dynamically get file verison, or application name, unzip files if needed, etc\r\n$Version = \"1.0.0.0\"\r\n$ProductName = \"Sample Application\"\r\n$ApplicatioName = \"$ProductName $Version\"\r\n$Publisher = \"ACME\"\r\n$InstallCommand = \"`\"SomeInstaller.exe`\" \/s\"\r\n$DetectScript = \"if (Test-Path `\"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MyProdct`\"){ if ((Get-ItemProperty -Path `\"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MyProduct`\" -Name `\"DisplayVersion`\").DisplayVersion -eq `\"$Version`\") { Write-Host `\"Installed`\" } } exit 0\"\r\n\r\ntry\r\n{\r\n    $Log += \"Creating `\"$ApplicationName`\"`r`n\"\r\n    #Change to SCCM powershell provider, SCCM cmdlets generally do not work otherwise, however, some cmdlets may fail in the SCCM drive. Keep this in mind, you may need to switch between providers\r\n    CD $SCCMDrive\r\n    #Create a new application. (Won't deploy, won't distribute, won't create deployment type. Just the application info)\r\n    $MyNewApp = New-CMApplication -Name $ApplicationName -Description \"Auto-Added by Packager.ps1\" -Publisher $Publisher -SoftwareVersion $Version -LocalizedName $ApplicationName `\r\n        -Owner $SCCMAdmin -SupportContact $SCCMAdmin -IconLocationFile $IconPath -ErrorAction Stop\r\n\r\n    #Move the application\r\n    $Log += \"Moving`\"$ApplicationName`\"`r`n\"\r\n    $MyNewApp | Move-CMObject -FolderPath \"$($SCCMDrive)Application\\SomePath\\ToPlace\"\r\n\r\n    $Log += \"Creating `\"$ApplicationName`\" - Install`r`n\"\r\n    #Add a deployment type to the new application, this won't distribute or deploy it\r\n    Add-CMScriptDeploymentType -ApplicationName $ApplicationName -ContentLocation $PackageDirectory -ContentFallback -EnableBranchCache -InstallCommand $InstallCommand `\r\n        -LogonRequirementType WhetherOrNotUserLoggedOn -SlowNetworkDeploymentMode Download -UserInteractionMode Hidden -InstallationBehaviorType InstallForSystem `\r\n        -DeploymentTypeName \"Install\" -ScriptLanguage PowerShell -ScriptText $DetectScript -ErrorAction Stop\r\n    #If you are doing an MSI install, look into \"Add-\u200bCM\u200bMsi\u200bDeployment\u200bType\" \r\n    #https:\/\/docs.microsoft.com\/en-us\/powershell\/sccm\/configurationmanager\/vlatest\/add-cmmsideploymenttype\r\n\r\n    $Log += \"Distributing `\"$ApplicationName`\" - Install`r`n\"\r\n    #Distribute the content, doesnt deploy\r\n    Start-CMContentDistribution -ApplicationName $ApplicationName -DistributionPointGroupName $TargetDPs\r\n\r\n    $Log += \"Deploying `\"$ApplicationName`\" - Install`r`n\"\r\n    #Deploy the new application\r\n    Start-CMApplicationDeployment -CollectionName $TargetCollection -Name $ApplicationName -DeadlineDateTime ([DateTime]::Now) -AvailableDateTime ([DateTime]::Now) `\r\n        -DeployAction Install -DeployPurpose Required -OverrideServiceWindow $true -TimeBaseOn LocalTime -UseMeteredNetwork $true\r\n\r\n    $Log += \"Stopping old deployments`r`n\"\r\n    #Additionally, we can stop any old deployments.\r\n    #Grab all apps similiarly named to what we just deployed, but are not what we deployed\r\n    $Apps = @()+(Get-CMApplication -Fast | Where-Object -FilterScript {$_.LocalizedDisplayName -like \"$ProductName *\" -and $_.LocalizedDisplayName -ne $ApplicationName -and $_.IsDeployed})\r\n    foreach ($App in $Apps)\r\n    {\r\n        Write-Log \"Deployment for $($App.LocalizedDisplayName) stopped`r`n\"\r\n        #And remove their deployment rule\r\n        #You may need to change application name. My ApplicationName and LocalizedDisplayName usually match\r\n        Remove-CMDeployment -CollectionName $TargetCollection -ApplicationName $App.LocalizedDisplayName -Force \r\n    }\r\n}\r\ncatch\r\n{\r\n    Write-Log \"Failed to create package. $($_.ToString())\"\r\n}\r\n\r\n#Return to filesystem provider\r\ncd \"$($env:SystemDrive)\\\"\r\n\r\n$Log += \"----End Package Script----`r`n\"\r\n$Log | Out-File -FilePath $LogPath -Append\r\nexit 0\r\n<\/code><\/pre>\n<p>For additional information on the cmdlets, please see the 2016 cmdlet reference at <a href=\"https:\/\/docs.microsoft.com\/en-us\/powershell\/sccm\/configurationmanager\/vlatest\/configurationmanager\">docs.microsoft.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing my PowerShell automation notes for SCCM. Below is a rough example on how to deploy Applications in SCCM 2016 using PowerShell. The real meat of it comes down to 5 cmdlets. As an extra goodie, also included the cmdlet to remove old deployments as well. Note: If you are using these cmdlets on a &hellip; <a href=\"https:\/\/www.ziviz.net\/WP\/2017\/07\/22\/deploy-applications-via-sccm-2016-powershell-cmdlets\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Deploy Applications via SCCM 2016 PowerShell cmdlets&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,8,7],"tags":[],"class_list":["post-115","post","type-post","status-publish","format-standard","hentry","category-powershell","category-sccm","category-sysadmin"],"_links":{"self":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":4,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"predecessor-version":[{"id":120,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/115\/revisions\/120"}],"wp:attachment":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}