Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Thursday, 25 January 2024

Sunday, 16 April 2023

Read the offersum box for SVF Files- PowershellScript

 ##Read the offersum box for SVF Files

$configMgrBoxpath = "E:\Temp\offersum Files TO scan"

$count = O

Get-ChildItem -Path $configMgrBoxpath -Include *.SVF -Recurse -Force -ErrorAction

Silentlycontinue -outBuffer 1000 | ForEach-Object {

$File = $_.FullName;

$count = $count + 1

If (($count % 1000) -eg 0) {

   write-host $count "files scanned"

try {


     ( ##Search for the non-existing deployment id passed in below select string within the SVF File


       Get-content _ReadCount 1 _TotalCount 6 -Path $_.FullName _ErrorAction Stop |

       select-String _Pattern ('2147024894') -ErrorAction stop

      ).Matches.Result($File)

} catch {

       ##write-warning -Message "Given deployment id not found in SFi1e"

}

     ##Write the non-existing deployment SVF file location on a text file

} | move-iten -Force -destination "E:\Temp|Offersum Files Irrelvent"

write-host "Script Finished !!!"

Share:

Monday, 4 April 2022

Evaluate ConfigMgr Client Policy with PowerShell

Evaluate ConfigMgr Client Policy with PowerShell

$trigger = "{00000000-0000-0000-0000-000000000021}"
Invoke-CimMethod -Namespace 'root\ccm' -ClassName 'sms_client' -MethodName TriggerSchedule -Arguments @{sScheduleID=$trigger}
Start-Sleep -Seconds 10

WMI Triggers for policy evaluation

{00000000-0000-0000-0000-000000000001} Hardware Inventory
{00000000-0000-0000-0000-000000000002} Software Inventory 
{00000000-0000-0000-0000-000000000003} Discovery Inventory 
{00000000-0000-0000-0000-000000000010} File Collection 
{00000000-0000-0000-0000-000000000011} IDMIF Collection 
{00000000-0000-0000-0000-000000000012} Client Machine Authentication 
{00000000-0000-0000-0000-000000000021} Request Machine Assignments 
{00000000-0000-0000-0000-000000000022} Evaluate Machine Policies 
{00000000-0000-0000-0000-000000000023} Refresh Default MP Task 
{00000000-0000-0000-0000-000000000024} LS (Location Service) Refresh Locations Task 
{00000000-0000-0000-0000-000000000025} LS (Location Service) Timeout Refresh Task 
{00000000-0000-0000-0000-000000000026} Policy Agent Request Assignment (User) 
{00000000-0000-0000-0000-000000000027} Policy Agent Evaluate Assignment (User) 
{00000000-0000-0000-0000-000000000031} Software Metering Generating Usage Report 
{00000000-0000-0000-0000-000000000032} Source Update Message
{00000000-0000-0000-0000-000000000037} Clearing proxy settings cache 
{00000000-0000-0000-0000-000000000040} Machine Policy Agent Cleanup 
{00000000-0000-0000-0000-000000000041} User Policy Agent Cleanup
{00000000-0000-0000-0000-000000000042} Policy Agent Validate Machine Policy / Assignment 
{00000000-0000-0000-0000-000000000043} Policy Agent Validate User Policy / Assignment 
{00000000-0000-0000-0000-000000000051} Retrying/Refreshing certificates in AD on MP 
{00000000-0000-0000-0000-000000000061} Peer DP Status reporting 
{00000000-0000-0000-0000-000000000062} Peer DP Pending package check schedule 
{00000000-0000-0000-0000-000000000063} SUM Updates install schedule 
{00000000-0000-0000-0000-000000000071} NAP action 
{00000000-0000-0000-0000-000000000101} Hardware Inventory Collection Cycle 
{00000000-0000-0000-0000-000000000102} Software Inventory Collection Cycle 
{00000000-0000-0000-0000-000000000103} Discovery Data Collection Cycle 
{00000000-0000-0000-0000-000000000104} File Collection Cycle 
{00000000-0000-0000-0000-000000000105} IDMIF Collection Cycle 
{00000000-0000-0000-0000-000000000106} Software Metering Usage Report Cycle 
{00000000-0000-0000-0000-000000000107} Windows Installer Source List Update Cycle 
{00000000-0000-0000-0000-000000000108} Software Updates Assignments Evaluation Cycle 
{00000000-0000-0000-0000-000000000109} Branch Distribution Point Maintenance Task 
{00000000-0000-0000-0000-000000000110} DCM policy 
{00000000-0000-0000-0000-000000000111} Send Unsent State Message 
{00000000-0000-0000-0000-000000000112} State System policy cache cleanout 
{00000000-0000-0000-0000-000000000113} Scan by Update Source 
{00000000-0000-0000-0000-000000000114} Update Store Policy 
{00000000-0000-0000-0000-000000000115} State system policy bulk send high
{00000000-0000-0000-0000-000000000116} State system policy bulk send low 
{00000000-0000-0000-0000-000000000120} AMT Status Check Policy 
{00000000-0000-0000-0000-000000000121} Application manager policy action 
{00000000-0000-0000-0000-000000000122} Application manager user policy action
{00000000-0000-0000-0000-000000000123} Application manager global evaluation action 
{00000000-0000-0000-0000-000000000131} Power management start summarizer
{00000000-0000-0000-0000-000000000221} Endpoint deployment reevaluate 
{00000000-0000-0000-0000-000000000222} Endpoint AM policy reevaluate 
{00000000-0000-0000-0000-000000000223} External event detection
Share:

Tuesday, 10 August 2021

Show memberships of Software Updates via (a) PowerShell (Form)


<#
.SYNOPSIS
    Shows the information about the deployment packages and Software update groups of which asoftware update is a member.
.DESCRIPTION
    This script creates a form that requires a article id, a software update group, or a deployment package as input. Based on the input it will show information about 
    the specific software update, or all the software updates in a software update group, or a deployment package. When used for a software update it will show in which
    software update group and deployment package it exists. When used for a software update group it will show in which deployment packages those updates also exists. 
    When used for a deployment package it will show in which software update groups those updates exist.
.PARAMETER SiteCode
    The site code of the primary site.
.PARAMETER SiteServer
    The site server of the primary site.
.NOTES     
    Author: Peter van der Woude - pvanderwoude@hotmail.com  
    Date published: 19-06-2014  
.LINK   
    http://www.petervanderwoude.nl
.EXAMPLE
    Get-SoftwareUpdateInformation.ps1 -SiteCode PCP -SiteServer CLDSRV02  
#>
[CmdletBinding()]

param (
[string]$SiteCode,
[string]$SiteServer
) 

#Function to load the form
function Load-Form {
    $Form1.Controls.Add($Button1)
    $Form1.Controls.Add($Button2)
    $Form1.Controls.Add($ComboBox1)
    $Form1.Controls.Add($DataGridView1)
    $Form1.Controls.Add($DataGridView2)
    $Form1.Controls.Add($Label1)
    $Form1.Controls.Add($Label2)
    $Form1.Controls.Add($LinkLabel1)
    $Form1.Controls.Add($LinkLabel2)
    $Form1.Controls.Add($TextBox1)
    $Form1.Controls.Add($GroupBox1)
    $Form1.Controls.Add($GroupBox2)
    $Form1.Controls.Add($GroupBox3)
    $ComboBox1.Items.add("Software Update")
    $ComboBox1.Items.add("Deployment Package")
    $ComboBox1.Items.add("Software Update Group")
	$Form1.ShowDialog()
}

#Function to get the software update group membership of updates
function Get-SoftwareUpdateGroupMembership {
    param (
    [array]$Updates
    )  
    foreach ($Update in $Updates) {
        $UpdateCIID = $Update.CI_ID
        $UpdateGroupNames = (Get-WmiObject -Namespace root/SMS/site_$($SiteCode) -ComputerName $SiteServer -Query "SELECT DISTINCT ALI.* from SMS_AuthorizationList ALI `
            JOIN SMS_CIRelation CIR on ALI.CI_ID = CIR.fromCIID WHERE CIR.ToCIID='$UpdateCIID'").LocalizedDisplayName
        if ($UpdateGroupNames -ne $null) {
            foreach ($Name in $UpdateGroupNames) {
                $UpdateGroupName = $Name
                $DataGridView1.Rows.Add($UpdateGroupName,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
            }
        }
        else {
            $UpdateGroupName = "<NoSoftwareUpdateGroup>"
            $DataGridView1.Rows.Add($UpdateGroupName,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
        }        
    }
}

#Function to get the deployment package membership of updates
function Get-DeploymentPackageMembership {
    param (
    [array]$Updates
    )
    foreach ($Update in $Updates) {
        $UpdateCIID = $Update.CI_ID
        $UpdatePackageNames = (Get-WmiObject -Namespace root/SMS/site_$($SiteCode) -ComputerName $SiteServer -Query "SELECT DISTINCT sup.* FROM SMS_SoftwareUpdatesPackage AS sup `
            JOIN SMS_PackageToContent AS pc ON sup.PackageID=pc.PackageID JOIN SMS_CIToContent AS cc ON pc.ContentID = cc.ContentID WHERE CC.CI_ID='$UpdateCIID'").Name
        if ($UpdatePackageNames -ne $null) {
            foreach ($UpdatePackageName in $UpdatePackageNames) {
                $DataGridView2.Rows.Add($UpdatePackageName,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
            }
        }
        else {
            $UpdatePackageName = "<NoDeploymentPackage>"
            $DataGridView2.Rows.Add($UpdatePackageName,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
        }
    }
}

#Function to get the members of a software update group
function Get-SoftwareUpdateGroupMembers {
    param (
    [string]$Group
    )
    $UpdateGroupCIID = (Get-WmiObject -ComputerName $SiteServer -Namespace root/SMS/site_$($SiteCode) -Class SMS_AuthorizationList -Filter "LocalizedDisplayName='$Group'").CI_ID
    $Updates = Get-WmiObject -Namespace root/SMS/site_$($SiteCode) -ComputerName $SiteServer -Query "SELECT upd.* FROM SMS_SoftwareUpdate upd, SMS_CIRelation cr WHERE cr.FromCIID='$UpdateGroupCIID' AND cr.RelationType=1 AND upd.CI_ID=cr.ToCIID"
    if ($Updates -ne $null) {
        foreach ($Update in $Updates) {
            $DataGridView1.Rows.Add($Group,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
        }
    }
    else {
    }
    return $Updates
}

#Function to get the members of a deployment package
function Get-DeploymentPackageMembers {
    param (
    [string]$Package
    )
    $UpdatePackageID = (Get-WmiObject -ComputerName $SiteServer -Namespace root/SMS/site_$($SiteCode) -Class SMS_SoftwareUpdatesPackage -Filter "Name='$Package'").PackageID
    $Updates = Get-WmiObject -Namespace root/SMS/site_$($SiteCode) -ComputerName $SiteServer -Query "SELECT DISTINCT su.* FROM SMS_SoftwareUpdate AS su JOIN SMS_CIToContent AS cc `
        ON  SU.CI_ID = CC.CI_ID JOIN SMS_PackageToContent AS pc ON pc.ContentID=cc.ContentID  WHERE  pc.PackageID='$UpdatePackageID' AND su.IsContentProvisioned=1"
    if ($Updates -ne $null) { 
        foreach ($Update in $Updates) {
            $DataGridView2.Rows.Add($Package,$Update.ArticleId,$Update.LocalizedDisplayName) | Out-Null
        }
    }
    else {
    }
    return $Updates
}

#Button1 OnClick event
$Button1_OnClick= {
	$Form1.Close()
}

#Button2 OnClick event
$Button2_OnClick= {
    Try {
        if ($DataGridView1 -ne $null) {
            $DataGridView1.Rows.Clear()
            $DataGridView2.Rows.Clear()
            $Form1.Refresh()
        }   
        
        $ErrorProvider1.SetError($TextBox1,"")
        $ErrorProvider1.SetError($ComboBox1,"")

        if($TextBox1.Text.Length -eq 0 -or $ComboBox1.SelectedItem -eq $null) {
            if($TextBox1.Text.Length -eq 0) {
                $ErrorProvider1.SetError($TextBox1, "Please provide a valid name")           
            }
            if ($ComboBox1.SelectedItem -eq $null) {
                $ErrorProvider1.SetError($ComboBox1, "Please select a valid type")
            }
        }
        else {
            $Name = $TextBox1.Text
            $Type = $ComboBox1.SelectedItem

            if ($Type -eq "Software Update") {
                $GroupBox1.Text = "Software Update Group"
                $GroupBox2.Text = "Deployment Package"
                $TextBox1.Enabled = $false
                $ComboBox1.Enabled = $false

                $Updates = Get-WmiObject -ComputerName $SiteServer -Namespace root/SMS/site_$($SiteCode) -Class SMS_SoftwareUpdate -Filter "ArticleID='$Name'"
                if ($Updates -ne $null) {
                    Get-SoftwareUpdateGroupMembership $Updates
                    Get-DeploymentPackageMembership $Updates
                }
                else {
                    $ErrorProvider1.SetError($TextBox1, "Please provide a valid article id of a software update")
                }
                $ComboBox1.Enabled = $true
                $TextBox1.Enabled = $true
            }
            elseif ($Type -eq "Software Update Group") {
                $GroupBox1.Text = "Software Update Group: $Name"
                $GroupBox2.Text = "Deployment Package"
                $TextBox1.Enabled = $false
                $ComboBox1.Enabled = $false

                $Updates = Get-SoftwareUpdateGroupMembers $Name
                if ($Updates -ne $null) {
                    Get-DeploymentPackageMembership $Updates
                }
                else {
                    $ErrorProvider1.SetError($TextBox1, "Please provide a valid name of a software update group")
                }
                $ComboBox1.Enabled = $true
                $TextBox1.Enabled = $true
            }
            elseif ($Type -eq "Deployment Package") {
                $GroupBox1.Text = "Software Update Group"
                $GroupBox2.Text = "Deployment Package: $Name"
                $TextBox1.Enabled = $false
                $ComboBox1.Enabled = $false

                $Updates = Get-DeploymentPackageMembers $Name
                if ($Updates -ne $null) {
                    Get-SoftwareUpdateGroupMembership $Updates
                }
                else {
                    $ErrorProvider1.SetError($TextBox1, "Please provide a valid name of a deployment package")
                }
                $ComboBox1.Enabled = $true
                $TextBox1.Enabled = $true
            }
        }
    }
    Catch {
        [Windows.Forms.MessageBox]::Show(“Please provide a valid combination of a name and type”, “Software Update Information”, [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Error)
    }
}

#LinkLabel1 event
$LinkLabel1_OpenLink= {
    [System.Diagnostics.Process]::start($LinkLabel1.text)
}

#LinkLabel2 event
$LinkLabel2_OpenLink= {
    [System.Diagnostics.Process]::start("http://twitter.com/pvanderwoude")
}

#Load Assemblies
[Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null

#Create ErrorProvider
$ErrorProvider1 = New-Object System.Windows.Forms.ErrorProvider
$ErrorProvider1.BlinkStyle = "NeverBlink"

#Create Form1
$Form1 = New-Object System.Windows.Forms.Form    
$Form1.Size = New-Object System.Drawing.Size(700,590)  
$Form1.MinimumSize = New-Object System.Drawing.Size(700,590)
$Form1.MaximumSize = New-Object System.Drawing.Size(700,590)
$Form1.SizeGripStyle = "Hide"
$Form1.Text = "Software Update Information"
$Form1.ControlBox = $true
$Form1.TopMost = $true

#Create Button1
$Button1 = New-Object System.Windows.Forms.Button
$Button1.Location = New-Object System.Drawing.Size(510,490)
$Button1.Size = New-Object System.Drawing.Size(150,25)
$Button1.Text = "Close"
$Button1.add_Click($Button1_OnClick)

#Create Button2
$Button2 = New-Object System.Windows.Forms.Button
$Button2.Location = New-Object System.Drawing.Size(510,30)
$Button2.Size = New-Object System.Drawing.Size(150,25)
$Button2.Text = "Execute"
$Button2.add_Click($Button2_OnClick)

#Create ComboBox1
$ComboBox1 = New-Object System.Windows.Forms.ComboBox
$ComboBox1.Location = New-Object System.Drawing.Size(255,30)
$ComboBox1.Size = New-Object System.Drawing.Size(150,25)
$comboBox1.Text = "<Select Type>"

#Create DataGriView1
$DataGridView1 = New-Object System.Windows.Forms.DataGridView
$DataGridView1.Location = New-Object System.Drawing.Size(20,95)
$DataGridView1.Size = New-Object System.Drawing.Size(640,170)
$DataGridView1.ColumnCount = 3
$DataGridView1.ColumnHeadersVisible = $true
$DataGridView1.Columns[0].Name = "Software Update Group"
$DataGridView1.Columns[0].AutoSizeMode = "Fill"
$DataGridView1.Columns[1].Name = "Article ID"
$DataGridView1.Columns[1].AutoSizeMode = "Fill"
$DataGridView1.Columns[2].Name = "Software Update"
$DataGridView1.Columns[2].AutoSizeMode = "Fill"
$DataGridView1.AllowUserToAddRows = $false
$DataGridView1.AllowUserToDeleteRows = $false
$DataGridView1.ReadOnly = $True
$DataGridView1.ColumnHeadersHeightSizeMode = "DisableResizing"
$DataGridView1.RowHeadersWidthSizeMode = "DisableResizing"
$DataGridView1.SelectionMode = "FullRowSelect"

#Create DataGridView2
$DataGridView2 = New-Object System.Windows.Forms.DataGridView
$DataGridView2.Location = New-Object System.Drawing.Size(20,305)
$DataGridView2.Size = New-Object System.Drawing.Size(640,170)
$DataGridView2.ColumnCount = 3
$DataGridView2.ColumnHeadersVisible = $true
$DataGridView2.Columns[0].Name = "Deployment Package"
$DataGridView2.Columns[0].AutoSizeMode = "Fill"
$DataGridView2.Columns[1].Name = "Article ID"
$DataGridView2.Columns[1].AutoSizeMode = "Fill"
$DataGridView2.Columns[2].Name = "Software Update"
$DataGridView2.Columns[2].AutoSizeMode = "Fill"
$DataGridView2.AllowUserToAddRows = $false
$DataGridView2.AllowUserToDeleteRows = $false
$DataGridView2.ReadOnly = $True
$DataGridView2.ColumnHeadersHeightSizeMode = "DisableResizing"
$DataGridView2.RowHeadersWidthSizeMode = "DisableResizing"
$DataGridView2.SelectionMode = "FullRowSelect"

#Create Groupbox1
$GroupBox1 = New-Object System.Windows.Forms.GroupBox
$GroupBox1.Location = New-Object System.Drawing.Size(10,75) 
$GroupBox1.Size = New-Object System.Drawing.Size(660,200) 
$GroupBox1.Text = "Software Update Group"

#Create GroupBox2
$GroupBox2 = New-Object System.Windows.Forms.GroupBox
$GroupBox2.Location = New-Object System.Drawing.Size(10,285) 
$GroupBox2.Size = New-Object System.Drawing.Size(660,200) 
$GroupBox2.Text = "Deployment Package"

#Create GroupBox3
$GroupBox3 = New-Object System.Windows.Forms.GroupBox
$GroupBox3.Location = New-Object System.Drawing.Size(10,10) 
$GroupBox3.Size = New-Object System.Drawing.Size(660,55) 
$GroupBox3.Text = "Required Information"

#Create Label1
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Font = New-Object System.Drawing.Font("Tahoma",8.25,0,3,0)
$Label1.Location = New-Object System.Drawing.Size(20,530) 
$Label1.Size = New-Object System.Drawing.Size(48,23)
$Label1.Text = "My blog:"
        
#Create Label2
$Label2 = New-Object System.Windows.Forms.Label
$Label2.Font = New-Object System.Drawing.Font("Tahoma",8.25,0,3,0)
$Label2.Location = New-Object System.Drawing.Size(460,530) 
$Label2.Size = New-Object System.Drawing.Size(111,23)
$Label2.Text = "Follow me on twitter:"

#Create LinkLabel1
$LinkLabel1 = New-Object System.Windows.Forms.LinkLabel
$LinkLabel1.Font = New-Object System.Drawing.Font("Tahoma",8.25,0,3,0)
$LinkLabel1.Location = New-Object System.Drawing.Size(68,530) 
$LinkLabel1.Size = New-Object System.Drawing.Size(142,23) 
$LinkLabel1.Text = "www.petervanderwoude.nl"
$LinkLabel1.add_click($LinkLabel1_OpenLink)

#Create LinkLabel2
$LinkLabel2 = New-Object System.Windows.Forms.LinkLabel
$LinkLabel2.Font = New-Object System.Drawing.Font("Tahoma",8.25,0,3,0)
$LinkLabel2.Location = New-Object System.Drawing.Size(569,530) 
$LinkLabel2.Size = New-Object System.Drawing.Size(90,23)
$linkLabel2.Text = "@pvanderwoude"
$LinkLabel2.add_click($LinkLabel2_OpenLink)

#Create TextBox1
$TextBox1 = New-Object System.Windows.Forms.TextBox
$TextBox1.Location = New-Object System.Drawing.Size(20,30)
$TextBox1.Size = New-Object System.Drawing.Size(150,25)
$TextBox1.Text = "<Provide Name>"

#Load form
Load-Form
Share:

PowerShell-Scripts/Delete old SCCM Deployments

#############################################################################
# Author  : Benoit Lecours 
# Website : www.SystemCenterDudes.com
# Twitter : @scdudes
#
# Version : 1.0
# Created : 2018/06/05
# Modified : 
#
# Purpose : This script delete deploymentsolder than the specified date
#
#############################################################################

#Load Configuration Manager PowerShell Module
Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')

#Get SiteCode
$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-location $SiteCode":"
Clear-Host

Write-host "--------------- SYSTEM CENTER DUDES - DELETE OLD DEPLOYMENTS ----------------`n"
Write-host "This script deletes SCCM deployments older than the number of days specified.`n"
Write-Host "The script is based on Creation Date. The user will be prompted before each deletion.`n" -ForegroundColor Yellow
$SCCMServer = Read-Host "Enter your SCCM server Name"
$UserDate = Read-Host "Delete deployments older than how many days ? (ex: 365 = 1 year)"
$DeleteDate = (Get-Date).AddDays(-$UserDate)
Write-Host ""
Write-host "-------------------------------------------------------------------------------------"
Write-Host "Building Deployment List older than " -NoNewline; Write-Host $DeleteDate.ToShortDateString() -ForegroundColor Red -NoNewline; Write-Host " This may take a couple of minutes...";
Write-host "-------------------------------------------------------------------------------------`n"

$DeploymentList = Get-CMDeployment | Where-Object {$_.CreationTime -le $Deletedate}
$DeploymentNumber=0
Write-Host ("Found " + $DeploymentList.Count + " deployments older than specified date`n") -ForegroundColor Yellow

foreach ($Deployment in $DeploymentList)
{
    $DeploymentID = $Deployment.DeploymentID
    $DeploymentName = $Deployment.ApplicationName
    $DeploymentNumber++
               
    # User Prompt
    Write-Host ""
    Write-host "--------------- " -NoNewline; Write-host "DEPLOYMENT #"$DeploymentNumber -ForegroundColor Red -NoNewline; Write-host " ---------------------------------------------------------"
    Write-Host ("Deployment Name: " + $DeploymentName) 
    Write-Host ("Targetted Collection: " + $Deployment.CollectionName)
    Write-Host ("Deployment ID: " + $Deployment.DeploymentID)
    Write-Host ("Creation Date: " + $Deployment.CreationTime)
    Write-Host ("Deployment Time: " + $Deployment.DeploymentTime)
    Write-Host ("Enforcement Deadline: " + $Deployment.EnforcementDeadline)
    Write-Host ("Feature Type: " + $Deployment.FeatureType)
    Write-host "----------------------------------------------------------------------------------------`n"

    # User Confirmation
    If ((Read-Host -Prompt "Type `"Y`" to delete the deployment, any other key to skip") -ieq "Y")
    {
      Try
            {
                #Delete the deployment based on the Deployment Feature Type
                Switch ($Deployment.FeatureType) 
                {
                    #Application
                    1{Remove-CMDeployment -DeploymentId $DeploymentID -ApplicationName $DeploymentName -ErrorAction Stop -Force
                    Write-Host "Sucessfully Deleted Application Deployment #"$DeploymentNumber -ForegroundColor Green -BackgroundColor Black}
                    
                    # Package/Program
                    2{                
                    $AdvertFilter = "AdvertisementID='$DeploymentID'"
                    #gwmi sms_advertisement -Namespace $SiteNamespace -ComputerName $SiteServer -filter $advertFilter | % {$_.Delete()}
                    Get-WmiObject -Namespace "root\sms\site_$sitecode" -ComputerName $SCCMServer -class SMS_Advertisement -filter $advertFilter -ErrorAction stop | % {$_.Delete()}
                    Write-Host "Sucessfully Deleted Program Deployment #"$DeploymentNumber -ForegroundColor Green -BackgroundColor Black}
                    
                    #Software Update
                    5{   
                    $AdvertFilter = "AssignmentUniqueID='$DeploymentID'"
                    #gwmi SMS_UpdatesAssignment -Namespace $SiteNamespace -ComputerName $SiteServer -filter $advertFilter | % {$_.Delete()}
                    Get-WmiObject -Namespace "root\sms\site_$sitecode" -ComputerName $SCCMServer -class SMS_UpdatesAssignment -filter $advertFilter -ErrorAction stop | % {$_.Delete()}
                    Write-Host "Sucessfully Deleted Software Update Deployment #"$DeploymentNumber -ForegroundColor Green -BackgroundColor Black}

                    #Baseline
                    6{
                    $AdvertFilter = "AssignmentUniqueID='$DeploymentID'"
                    #gwmi sms_baselineassignment -Namespace $SiteNamespace -ComputerName $SiteServer -filter $advertFilter | % {$_.Delete()}
                    Get-WmiObject -Namespace "root\sms\site_$sitecode" -ComputerName $SCCMServer -class SMS_baselineassignment -filter $advertFilter -ErrorAction stop | % {$_.Delete()}
                    Write-Host "Sucessfully Deleted Baseline Deployment #"$DeploymentNumber -ForegroundColor Green -BackgroundColor Black}

                    #Task Sequence
                    7{
                    $AdvertFilter = "AdvertisementID='$DeploymentID'"
                    #gwmi sms_advertisement -Namespace $SiteNamespace -ComputerName $SiteServer -filter $advertFilter | % {$_.Delete()}
                    Get-WmiObject -Namespace "root\sms\site_$sitecode" -ComputerName $SCCMServer -class SMS_Advertisement -filter $advertFilter -ErrorAction stop | % {$_.Delete()}
                    Write-Host "Sucessfully Deleted Task Sequence Deployment #"$DeploymentNumber -ForegroundColor Green -BackgroundColor Black}

                    Default {
                    Write-Host ("Feature Type not supported" + $Deployment.FeatureType)}
                 }
            }
       Catch{Write-Host "Can't delete deployment #"$DeploymentNumber -ForegroundColor Red -BackgroundColor Black }    
    }
}

Share:

PowerShell-Scripts/Delete devices collections with no members and no deployments

#############################################################################
# Author  : Benoit Lecours 
# Website : www.SystemCenterDudes.com
# Twitter : @scdudes
#
# Version : 1.1
# Created : 2017/04/05
# Modified : 2017/08/31
#
# Purpose : This script delete collections without members and deployments
#
#############################################################################

#Load Configuration Manager PowerShell Module
Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')

#Get SiteCode
$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-location $SiteCode":"
Clear-Host

Write-host "This script delete device collections without members and deployments. You will be prompted before each deletion.`n"
Write-host "Built-in collections and users collections are excluded`n"
Write-host "------------------------------------------------------------------------"
Write-Host ("Building Devices Collections List. This may take a couple of minutes...")
Write-host "------------------------------------------------------------------------`n"

$CollectionList = Get-CmCollection | Where-Object {$_.CollectionID -notlike 'SMS*' -and $_.CollectionType -eq '2' -and $_.MemberCount -eq 0} | Select-Object -Property Name,MemberCount,CollectionID,IsReferenceCollection
#$DeploymentList = Get-CMDeployment | Select-Object -Property CollectionID

Write-Host ("Found " + $CollectionList.Count + " collections without members (MemberCount = 0) `n")
Write-Host ("Analyzing list to find collection without deployments... `n")

foreach ($Collection in $CollectionList)
{
    $NumCollectionMembers = $Collection.MemberCount
    $CollectionID = $Collection.CollectionID
    $GetDeployment = Get-CMDeployment | Where-Object {$_.CollectionID -eq $Collection.CollectionID}
        
    # Delete collection if there's no members and no deployment on the collection
    If ($GetDeployment -eq $null) #$NumCollectionMembers -eq 0 -and 
    {
        # User Prompt
        Write-Host ("Collection " + $Collection.Name +" (" + $Collection.CollectionID + ")" + " has no members and deployments")

        # User Confirmation
        If ((Read-Host -Prompt "Type `"Y`" to delete the collection, any other key to skip") -ieq "Y")
        {
            #Check if Reference collection           
            Try
            {
                #Delete the collection object    
                Remove-CMCollection -Id $CollectionID -Force
                Write-Host -ForegroundColor Green ("Collection: " + $Collection.Name + " Deleted")
            }
            Catch{Write-Host -ForegroundColor Red ("Can't delete " + $Collection.Name + " collection. Possible cause : There's referenced collection or a custom security scope assigned to the collection.")}    
        }
    }
}
Share:

Powershell-Create SCCM Collections based on Active Directory OU



<#############################################################################
Author  : Benoit Lecours 
Website : www.SystemCenterDudes.com
Twitter : @scdudes
Version : 1.0
Created : 2019/12/10

The purposes of this script:
1. Create SCCM device collections based on Active Directory Organisational Unit
2. Define the Refresh Schedule of collection to 7 days
3. Create Query Rule for collection membership
4. Move created collection to custom folder
5. Updates collection membership at once.
##############################################################################>

# Import PS modules
Import-Module ActiveDirectory
Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'

# SCCM Site
$Site = (Get-PSDRive -PSProvider CMSite).Name
CD ${Site}:

# Defining refresh interval for collection - 7 days
$Schedule = New-CMSchedule –RecurInterval Days –RecurCount 7

##Get User Inputs for Base OU
$Users = Get-ADOrganizationalUnit -Filter * -Properties DistinguishedName,CanonicalName |Select-Object DistinguishedName,CanonicalName
Clear-Host
Write-Host "Here's the list of all OU in your Organisation".ToUpper()
Write-Host ""

For ($i=0; $i -lt $Users.Count; $i++)  {
  Write-Host "$($i+1): $($Users[$i].CanonicalName)"
}

Write-Host ""
[int]$number = Read-Host "Select the number corresponding to the desired top-most OU".ToUpper()
Write-Host ""
Write-Host -ForegroundColor Green "You've selected $($users[$number-1].CanonicalName). The script will create 1 collection for each OU under the selected OU.:".ToUpper()
$SearchBase = $($Users[$number-1]).DistinguishedName


#Get User Input for folder
Write-Host ""
$folderName = Read-Host "Enter the desired folder name. The folder will be created under the Device Collection Node and all collections will be moved to the folder"
New-Item -Name $folderName -Path "${Site}:\DeviceCollection"
$TargetFolder = "${Site}:\DeviceCollection\$folderName"


#Getting Canonical name and GUID from AD OUs based on user input
$ADOUs = Get-ADOrganizationalUnit -SearchBase "$SearchBase" -Filter * -Properties Canonicalname |Select-Object DistinguishedName,CanonicalName

#Create Collections

foreach ($OU in $ADOUs)
{
    $O_Name = $OU.CanonicalName
    $O_GUID = $OU.ObjectGUID

Try
{
    New-CMDeviceCollection -LimitingCollectionName 'All Systems' -Name $O_Name -RefreshSchedule $Schedule -Comment $O_GUID | Out-Null
    Write-host *** Collection $O_Name created ***
}
Catch
{
    Write-host -ForegroundColor Red ("There was an error creating the: " + $O_Name + " collection. Possible cause is that there's already a collection with that name.")
}

# Creating Query Membership rule
Add-CMDeviceCollectionQueryMembershipRule -CollectionName $O_Name -QueryExpression "select *  from  SMS_R_System where SMS_R_System.SystemOUName = '$O_Name'" -RuleName "OU Membership" | Out-Null

# Getting collection ID
$ColID = (Get-CMDeviceCollection -Name $O_Name).collectionid

# Moving collection to folder
Try
{
    Move-CMObject -FolderPath $TargetFolder -ObjectId "$ColID"
    Write-host *** Collection $O_Name moved to the $folderName folder ***
}
Catch
{
    Write-host -ForegroundColor Red ("There was an error moving the: " + $O_Name + " collection.")
}

# Updating collection membership
Invoke-CMDeviceCollectionUpdate -Name $O_Name
}
Write-Host ""
Write-host *** SCRIPT COMPLETED ***
Share:

Saturday, 7 August 2021

Move Software Updates between Software Update Groups in SCCM using Powershell

How does the Powershell script work?
If you want to move a Software Update between different Software Update Groups, you don’t move them, but rather change the membership.

The script that I have provided will take the latest created Software Update Group and add those members to a defined Software Update Group.

The Powershell script
Below is the script I have created for editing the membership of a Software Update Group.

<#
.SYNOPSIS
This script will add all updates from the latest Software Update Group to a defined Software Update Group.
    
.DESCRIPTION
This script will add all updates from the latest Software Update Group to a defined Software Update Group.

Author: Daniel Classon (www.danielclasson.com)
Version: 1.0
Date: 2018-12-18
    
.EXAMPLE
.\Add-SUGMembers -DestinationSUG SUG1
This will add all updates contained in the latest Software Updates Group to SUG1.
    
.DISCLAIMER
All scripts and other powershell references are offered AS IS with no warranty.
These script and functions are tested in my environment and it is recommended that you test these scripts in a test environment before using in your production environment.
#>


PARAM(
    [string]$DestinationSUG
    )

#Load SCCM Powershell module
Try {
    Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) -ErrorAction Stop
}
Catch [System.UnauthorizedAccessException] {
    Write-Warning -Message "Access denied" ; break
}
Catch [System.Exception] {
    Write-Warning "Unable to load the Configuration Manager Powershell module from $env:SMS_ADMIN_UI_PATH" ; break
}

#Set current drive to SCCM drive

$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-Location -Path "$($SiteCode.Name):\"

Function Write-Log
{
 
    PARAM(
        [String]$Message,
        [int]$Severity,
        [string]$Component
    )
        $LogPath = $PSScriptRoot
        $TimeZoneBias = Get-WMIObject -Query "Select Bias from Win32_TimeZone"
        $Date= Get-Date -Format "HH:mm:ss.fff"
        $Date2= Get-Date -Format "MM-dd-yyyy"
        $Type=1
         
        "<![LOG[$Message]LOG]!><time=$([char]34)$Date$($TimeZoneBias.bias)$([char]34) date=$([char]34)$date2$([char]34) component=$([char]34)$Component$([char]34) context=$([char]34)$([char]34) type=$([char]34)$Severity$([char]34) thread=$([char]34)$([char]34) file=$([char]34)$([char]34)>"| Out-File -FilePath "$LogPath\Add-SUGMembers.log" -Append -NoClobber -Encoding default
}

#Change membership of Software Update to new Software Update Group

$LatestSUG = Get-CMSoftwareUpdateGroup | Select-Object LocalizedDisplayName,DateCreated | Sort-Object DateCreated | Select-Object -Last 1 
$Updates = Get-CMSoftwareUpdate -UpdateGroupName $LatestSUG -Fast
$Count = 0

Foreach ($Update in $Updates) {
    $Count++
    Try {
        Add-CMSoftwareUpdateToGroup -SoftwareUpdateId $($Update.CI_ID) -SoftwareUpdateGroupId $($DestinationSUG.CI_ID)
        Write-Progress -Activity "Adding $($Update.LocalizedDisplayName) to $($DestinationSUG.LocalizedDisplayName)" -Status "Adding $Count of $($Updates.Count) updates to $($SourceSUG.LocalizedDisplayName)" -PercentComplete ($Count / $Updates.count * 100)
        Write-Log -Message "Adding $($Update.LocalizedDisplayName) to $($DestinationSUG.LocalizedDisplayName)" -Severity 1 -Component "Add SU to SUG"
    }
    Catch {
        Write Warning "$_.Exception.Message"
        Write-Log -Message "$_.Exception.Message" -Severity 3 -Component "Add SU to SUG"
    }
}
Set-Location $PSScriptRoot


Share:

Configure Collection Updates in MEMCM (SCCM) using a Powershell Script

Configure Collection Updates in MEMCM (SCCM) using a Powershell Script
If you want to configure device collections in collections.txt to only update on a schedule, you run this command:

.\Set-CollectionUpdates.ps1 -CollectionType Device -RefreshType 2
Source code:
<#
.PARAMETER COLLECTIONTYPE
Define the type of collections in the collections.txt file. Valid inputs are Device and User

.PARAMETER REFRESHTYPE
Define the Refresh type for the collection. Valid inputs are:

# The following refresh types exist for ConfigMgr collections 
# 6 = Incremental and Scheduled Updates 
# 4 = Incremental Updates Only 
# 2 = Scheduled Updates only 
# 1 = Manual Update only 
    
.DESCRIPTION
Sets the collection refresh type for all collections defined in a text file.

.NOTES
Author: Daniel Classon
Version: 1.0
Date: 2015/05/18
    
.EXAMPLE
.\Set-Collection_Updates.ps1 -CollectionType Device -RefreshType 2
Will set the collections in collections.txt to "Scheduled Updates only".

.DISCLAIMER
All scripts and other powershell references are offered AS IS with no warranty.
These script and functions are tested in my environment and it is recommended that you test these scripts in a test environment before using in your production environment.
#>

[CmdletBinding()]

Param(
    [Parameter(Mandatory=$True, Helpmessage="Enter the Collection Type")]
    [string]$CollectionType,
    [Parameter(Mandatory=$True, Helpmessage="Enter the Refresh Type")]
    [string]$RefreshType
)

Begin {
    #Checks if the user is in the administrator group. Warns and stops if the user is not.
    if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        Write-Warning "You are not running this as local administrator. Run it again in an elevated prompt." ; break
    }
    try {
        Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1)
    }
    catch [System.UnauthorizedAccessException] {
        Write-Warning -Message "Access denied" ; break
    }
    catch [System.Exception] {
        Write-Warning "Unable to load the Configuration Manager Powershell module from $env:SMS_ADMIN_UI_PATH" ; break
    }
}
Process {
    try {
        $CollectionIDs = Get-Content "collections.txt" -ErrorAction Stop
    }
    catch [System.Exception] {
        Write-Warning "Unable to find collections.txt. Make sure to place it in the script directory."
    }
    $SiteCode = Get-PSDrive -PSProvider CMSITE
    Set-Location -Path "$($SiteCode.Name):\"
    
    $Count = 0

    Foreach ($CollectionID in $CollectionIDs) {
        $Count++
        if ($CollectionType -eq "Device") {
            $Collection = Get-CMDeviceCollection -CollectionId $CollectionID
            $Collection.RefreshType = $RefreshType
            $Collection.Put()
            if ($RefreshType -eq 1) {
                Write-Progress -Activity "Enabling Manual Update only  on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Manual Update only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 2) {
                Write-Progress -Activity "Enabling Scheduled Updates only on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Scheduled Updates only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 4) {
                Write-Progress -Activity "Enabling Incremental Updates only on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Incremental Updates Only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 6) {
                Write-Progress -Activity "Enabling Incremental and Scheduled Updates on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Incremental and Scheduled Updates on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
        }
        } 
        if ($CollectionType -eq "User") {
            $Collection = Get-CMUserCollection -CollectionId $CollectionID
            $Collection.RefreshType = $RefreshType
            $Collection.Put()
            if ($RefreshType -eq 1) {
                Write-Progress -Activity "Enabling Manual Update only  on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Manual Update only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 2) {
                Write-Progress -Activity "Enabling Scheduled Updates only on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Scheduled Updates only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 4) {
                Write-Progress -Activity "Enabling Incremental Updates only on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Incremental Updates Only on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
            }
            elseif ($RefreshType -eq 6) {
                Write-Progress -Activity "Enabling Incremental and Scheduled Updates on $CollectionType Collection ID: $CollectionID" -Status "Modified $Count of $($CollectionIDs.Count) collections" -PercentComplete ($Count / $CollectionIDs.count * 100)
                Write-Host "Enabling Incremental and Scheduled Updates on: " $Collection.CollectionID "`t" $Collection.Name -ForegroundColor Yellow
        }
        } 
} 
}  
End {
    Write-Host "$Count $CollectionType collections were updated"  
    Set-Location -Path $env:SystemDrive
}
Share:

Powershell Application detection method example

Powershell detection method example
Modify the Powershell script

Modify the below script to suit your needs. The example below will look at strings in 3 different files. You will need to make the following modifications:

  • String variables
  • String<number>Location variables

#Define strings and their location. Also include the filename.

$String1 = ""
$String1Location = ""

$String2 = ""
$String2Location = ""

$String3 = ""
$String3Location = ""

# Detect presence of String1 in String1 Location
try {
    $String1Exists = Get-Content $String1Location -ErrorAction Stop
}
catch {
}

# Detect presence of String2 in String2 Location
try {
    $String2Exists = Get-Content $String2Location -ErrorAction Stop
}
catch {
}

# Detect presence of String3 in String3 Location
try {
    $String3Exists = Get-Content $String3Location -ErrorAction Stop
}
catch {
}

if (($String1Exists -match $String1) -and ($String2Exists -match $String2) -and ($String3Exists -match $String3)) {
    Write-Host "Installed"
}
else {
}
Share:

Monday, 26 July 2021

Using Scripts to trigger software updates remotely from the software center

The following is the PowerShell script which will check for the windows updates (it can be Microsoft or 3rd party), and trigger the installation. Doing this action, will ignore the maintenance window ONLY (if you have any) and follow the reboot schedule as per the assignment.

$MissingUpdates = Get-WmiObject -Class CCM_SoftwareUpdate -Filter ComplianceState=0 -Namespace root\CCM\ClientSDK
$MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}})
if ( $MissingUpdatesReformatted)
{
$InstallReturn = Invoke-WmiMethod -ComputerName $env:computername -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\clientsdk
write-host "Updates found, initiated"
}
else
{
write-host "No updates found"
}
http://eskonr.com/2021/05/using-scripts-to-trigger-software-updates-remotely-from-the-sccm-console/


Share: