Loading
Software reassignment between workstations
We are facing the following situation:   We would like to get all the software that is installed on a particular computer 1 (Software Portal)   and reinstall them on another computer 2.   Thus, all software on computer 1 would be installed on computer 2 and removed from computer 1.   We use SCCM to have computers included in installation and uninstallation collections   for each service (Software).

  • Sounds like the situation when someone gets a new system and migration from one to the other.  This can be automated or requested and is a combination of install on one & harvest on the other.
  • Ricardo, If understand this correctly your wanting to assign the same collections that one machine is in to a new machine? If so I think I have the script to do that. I don't yet have it set up to make the relationship in AP but that is on my list. Let me know any I can provide. Jerry
    • Jerry, Exactly, I have configured a field in the inventory that categorizes the software as "Specific Software", and you can find this information in the table tabCID_cf_a_1 . Each software that has this flag marked has an application in SCCM, both for installation and for uninstallation, the idea is to put "computer 1" in all the uninstallation collection of the respective software, and that "computer 2" is added collection collections. So we would have a software migration specific to each computer, thus avoiding unnecessary software.
      Expand Post
  • ? I'm thinking of doing something along those lines, plus my knowledge of snow and limited, could you help me? Script Shell: param ( [Parameter(Mandatory=$true)][string]$SCCMUserName, [Parameter(Mandatory=$true)][string]$SCCMServer, [Parameter(Mandatory=$true)][string]$SCCMSiteCode, [Parameter(Mandatory=$true)][string]$ComputadorOrigem, [Parameter(Mandatory=$true)][string]$ComputadorDestino ) $SCCMServiceAccountName = Get-APSetting SCCMServiceAccountName $SCCMServiceAccount = Get-ServiceAccount -Name $SCCMServiceAccountName -Scope 0 $SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName,$SCCMServiceAccountPassword $extragwmiParameters = [ordered]@{ "Namespace" = "Root\SMS\Site_$SCCMSiteCode" "ComputerName" = $SCCMServer "Credential" = $Credentials "ErrorAction" = 'Stop' } $server = "SERVER" $db = "DB" $user = "USER" $pass = "PASS" $Computer = $ComputadorOrigem $sql = " select A.NAME AS SOFTWARE, CASE WHEN sccmuninstallid IS THEN '' ELSE sccmuninstallid END AS Collection_Uninstall, CASE WHEN ComputerGroupName IS THEN '' ELSE ComputerGroupName END AS Collection_Install from tblApplication AS A left join tabCID_cf_a_1 AS B on a.ApplicationID = b.ElementID LEFT JOIN tblComputerApplications AS C ON C.ApplicationID = A.ApplicationID LEFT JOIN tblComputer AS D ON D.ComputerID = C.ComputerID left join tblApplicationStoreData as E on e.ApplicationID = a.ApplicationID where OperatingSystem in ('Microsoft Windows 7 Enterprise','Microsoft Windows 10 Enterprise') and [Software Específco] = 1 and HostName ='"+$Computer+"'" $search = Invoke-SqlCommand -Server $server -Database $db -Username $user -Password $pass -Query $sql Return: CollectionName | Collection_Instalacao | Collection_Desinstalacao XXXXXXXXXXX    XXXXXXXXXXXXXXX    XXXXXXXXXXXXXXX XXXXXXXXXXX    XXXXXXXXXXXXXXX    XXXXXXXXXXXXXXX $List = $search | select Collection_Install, Collection_Uninstall foreach($L in $List){ Add-CMDeviceCollectionDirectMembershipRule -CollectionId $l.Collection_Install -ResourceId $(get-cmdevice -Name $ComputadorDestino).ResourceID Set-CMDeviceCollection -CollectionId $l.Collection_Install Start-Sleep -s 5 Add-CMDeviceCollectionDirectMembershipRule -CollectionId $l.Collection_Uninstall -ResourceId $(get-cmdevice -Name $ComputadorOrigem).ResourceID Set-CMDeviceCollection -CollectionId $l.Collection_Uninstall Start-Sleep -s 5 Remove-CMDeviceCollectionDirectMembershipRule -CollectionId $l.Collection_Install -ResourceId $(get-cmdevice -Name $ComputadorOrigem).ResourceID -force Set-CMDeviceCollection -CollectionId $l.Collection_Install Start-Sleep -s 5 } Running the script inside SCCM runs perfectly, now I would like to know how to make use of this script within the software portal. So that the user can pass the parameters and the script execute correctly.
    Expand Post
    • Ricardo, Below is the PW we developed that can be executed from within the App Store. Should be super easy to setup. Let me know if you have any questions. Jerry <# .SYNOPSIS Transfers from a SCCM resource (device or user) to another for all Direct Membership SCCM collections .DESCRIPTION The script transfers a direct membership rule from selected collections. If the resource is a member based on any other criteria e.g query rule the resource cannot be transfered with this script. Both device and user direct rules can be transfered. .PARAMETER Resource The SCCM resource (device/computer) the direct membership rule is based on. Supported formats are: Computer formats: * Computername * Domainname\Computername User formats: * Username (SamAccountName * Down-level logon name (domainname\username) * UPN (username@domainName) or mail. .PARAMETER IncludeUpdateCollectionMembership This is a True/False value if the collection should run an update collection membership after the SCCM resource is removed. .NOTES #> param ( [Parameter(Mandatory = $true)] [string]$SCCMUserName, [Parameter(Mandatory = $true)] [string]$SCCMServer, [Parameter(Mandatory = $true)] [string]$SCCMSiteCode, [Parameter(Mandatory = $true)] [string]$OldResource, [Parameter(Mandatory = $true)] [string]$NewResource ) [bool]$IncludeUpdateCollectionMembership -eq $true #region Declare Credentials, default parameters and variables $SCCMServiceAccountName = Get-APSetting "SCCMServiceAccountName" $SCCMServiceAccount = Get-ServiceAccount -Name $SCCMServiceAccountName -Scope 0 $SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName, $SCCMServiceAccountPassword $extragwmiParameters = [ordered]@{ "Namespace" = "Root\SMS\Site_$SCCMSiteCode" "ComputerName" = $SCCMServer #"Credential" = $Credentials "ErrorAction" = 'Stop' } #endregion #region Validate Old SCCM resource try { #Firsts checks if the resource is a device (computer) if ($OldResource.Contains('\')) { $OldDomainPart = $OldResource.Split('\')[0] $OldComputerNamePart = $OldResource.Split('\')[1] $OldResObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$OldComputerNamePart' AND ResourceDomainORWorkgroup = '$OldDomainPart' AND Client = '1'" @extragwmiParameters) } else { $OldResObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$OldResource' AND Client = '1'" @extragwmiParameters) } if ($OldResObj.Count -gt 1) { throw "More than one device/computer with name $OldResource found (with Client = 1)" } #If found, validates what collection type was detected, and based on that if script will continue to search users or not if ($OldResObj.Count -eq 1 -and $OldCollObj.CollectionType -eq 2) { $OldResObj = $OldResObj[0]; Write-Host "Found computer $($OldResObj.Name) with resource id $($OldResObj.ResourceId)" } if ($OldResObj.Count -eq 1 -and $OldCollObj.CollectionType -eq 1) { Write-Warning "Found SCCM device/computer $($OldResObj[0].Name). But because collection $($OldCollObj.Name) is a user collection, device can not be added and search will continue for user objects" $OldResObj = @() } #Continues to check if the resource is a SCCM user #Checks the format of the user name. Supported formats: username, down-level logon name (domainname\username), UPN (username@domainName) or mail. if ($OldResource.Contains('@')) { $OldSCCMAttribute = "UserPrincipalName" } elseif ($OldResource.Contains('\')) { #Backslash in WMI is an escape character, needs to add one more $OldSCCMAttribute = "UniqueUserName"; $OldResourceWithBackslack = $OldResource.Replace("\", "\\") } else { $OldSCCMAttribute = "UserName" } #Tries to automatically find the SCCM user based on resource format if ($OldResObj.Count -eq 0) { if ($OldResource.Contains('\')) { $OldResObj = @(Get-WmiObject -Class SMS_R_User -Filter "$OldSCCMAttribute = '$OldResourceWithBackslack'" @extragwmiParameters) } else { $OldResObj = @(Get-WmiObject -Class SMS_R_User -Filter "$OldSCCMAttribute = '$OldResource'" @extragwmiParameters) } } #If nothing is found and UserPrincipalName was used, it could also be mail.. search on attribute mail if ($OldResObj.Count -eq 0 -AND $OldSCCMAttribute -eq "UserPrincipalName") { $OldResObj = @(Get-WmiObject -Class SMS_R_User -Filter "mail = '$OldResource'" @extragwmiParameters) } if ($OldResObj.Count -eq 0) { throw "No user where $OldSCCMAttribute is $OldResource was found" } if ($OldResObj.Count -gt 1) { throw "More than one user with attribute $OldSCCMAttribute was found" } if ($OldResObj.Count -eq 1) { $OldResObj = $OldResObj[0]; Write-Host "Found user $($OldResObj.Name) with resource id $($OldResObj.ResourceId)" } } catch { Write-Error "Error occurred when getting SCCM resource ($OldResource). Exception: $($_.Exception.Message)" } #endregion #region Validate New SCCM resource try { #Firsts checks if the resource is a device (computer) if ($NewResource.Contains('\')) { $NewDomainPart = $NewResource.Split('\')[0] $NewComputerNamePart = $NewResource.Split('\')[1] $NewResObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$NewComputerNamePart' AND ResourceDomainORWorkgroup = '$NewDomainPart' AND Client = '1'" @extragwmiParameters) } else { $NewResObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$NewResource' AND Client = '1'" @extragwmiParameters) } if ($NewResObj.Count -gt 1) { throw "More than one device/computer with name $NewResource found (with Client = 1)" } #If found, validates what collection type was detected, and based on that if script will continue to search users or not if ($NewResObj.Count -eq 1 -and $NewCollObj.CollectionType -eq 2) { $NewResObj = $NewResObj[0]; Write-Host "Found computer $($NewResObj.Name) with resource id $($NewResObj.ResourceId)" } if ($NewResObj.Count -eq 1 -and $NewCollObj.CollectionType -eq 1) { Write-Warning "Found SCCM device/computer $($NewResObj[0].Name). But because collection $($NewCollObj.Name) is a user collection, device can not be added and search will continue for user objects" $NewResObj = @() } #Continues to check if the resource is a SCCM user #Checks the format of the user name. Supported formats: username, down-level logon name (domainname\username), UPN (username@domainName) or mail. if ($NewResource.Contains('@')) { $NewSCCMAttribute = "UserPrincipalName" } elseif ($NewResource.Contains('\')) { #Backslash in WMI is an escape character, needs to add one more $NewSCCMAttribute = "UniqueUserName"; $NewResourceWithBackslack = $NewResource.Replace("\", "\\") } else { $NewSCCMAttribute = "UserName" } #Tries to automatically find the SCCM user based on resource format if ($NewResObj.Count -eq 0) { if ($NewResource.Contains('\')) { $NewResObj = @(Get-WmiObject -Class SMS_R_User -Filter "$NewSCCMAttribute = '$NewResourceWithBackslack'" @extragwmiParameters) } else { $NewResObj = @(Get-WmiObject -Class SMS_R_User -Filter "$NewSCCMAttribute = '$NewResource'" @extragwmiParameters) } } #If nothing is found and UserPrincipalName was used, it could also be mail.. search on attribute mail if ($NewResObj.Count -eq 0 -AND $NewSCCMAttribute -eq "UserPrincipalName") { $NewResObj = @(Get-WmiObject -Class SMS_R_User -Filter "mail = '$NewResource'" @extragwmiParameters) } if ($NewResObj.Count -eq 0) { throw "No user where $NewSCCMAttribute is $NewResource was found" } if ($NewResObj.Count -gt 1) { throw "More than one user with attribute $NewSCCMAttribute was found" } if ($NewResObj.Count -eq 1) { $NewResObj = $NewResObj[0]; Write-Host "Found user $($NewResObj.Name) with resource id $($NewResObj.ResourceId)" } } catch { Write-Error "Error occurred when getting SCCM resource ($NewResource). Exception: $($_.Exception.Message)" } #endregion $CollRules = (Get-WmiObject -Class sms_fullcollectionmembership -Fi
      Expand Post
      • ? Many thanks for the reply. I needed to query the SLM database to know the collections associated with the source computer, in this query I have the return of the application name, the installation collection and the uninstallation collection. That way I matured the script still in PowerShell so that I could carry out this whole process. param ( [Parameter(Mandatory=$true)][string]$SCCMUserName, [Parameter(Mandatory=$true)][string]$SCCMServer, [Parameter(Mandatory=$true)][string]$SCCMSiteCode, [Parameter(Mandatory=$true)][string]$SourceComputer, [Parameter(Mandatory=$true)][string]$CumputerDestination ) region Declare Credentials, default parameters and variables $SCCMServiceAccountName = Get-APSetting SCCMServiceAccountName $SCCMServiceAccount = Get-ServiceAccount -Name $SCCMServiceAccountName -Scope 0 $SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName,$SCCMServiceAccountPassword $extragwmiParameters = [ordered]@{ "Namespace" = "Root\SMS\Site_$SCCMSiteCode" "ComputerName" = $SCCMServer "Credential" = $Credentials "ErrorAction" = 'Stop' } Valida Origem try{ if($SourceComputer.Contains('\')){ $Domain = $SourceComputer.Split('\')[0] $Hostname = $SourceComputer.Split('\')[1] $ResSComp = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$Hostname' AND ResourceDomainORWorkgroup = '$Domain' AND Client = '1'" @extragwmiParameters) } else{ $ResSComp = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$SourceComputer' AND Client = '1'" @extragwmiParameters) } if($ResSComp.Count -gt 1){ throw "More than one device/computer found with name $SourceComputer (where Client attribute = 1)" } if($ResSComp.Count -eq 1){ $ResSComp = $ResSComp[0]; Write-Host "Found computer $($ResSComp.Name) with resource id $($ResSComp.ResourceId)" } } catch{ Write-Error "Error occurred when getting SCCM resource ($SourceComputer). Exception: $($_.Exception.Message)" } Fim Origem Valida Destino try{ if($CumputerDestination.Contains('\')){ $Domain = $CumputerDestination.Split('\')[0] $Hostname = $CumputerDestination.Split('\')[1] $ResCompDes = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$Hostname' AND ResourceDomainORWorkgroup = '$Domain' AND Client = '1'" @extragwmiParameters) } else{ $ResCompDes = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$CumputerDestination' AND Client = '1'" @extragwmiParameters) } if($ResCompDes.Count -gt 1){ throw "More than one device/computer found with name $CumputerDestination (where Client attribute = 1)" } if($ResCompDes.Count -eq 1){ $ResCompDes = $ResCompDes[0]; Write-Host "Found computer $($ResCompDes.Name) with resource id $($ResCompDes.ResourceId)" } } catch{ Write-Error "Error occurred when getting SCCM resource ($CumputerDestination). Exception: $($_.Exception.Message)" } Fim Destino SQL procurar softwares específicos no SLM $server = SERVIDOR $db = DB $user = USER $pass = PASS $connection = New-Object System.Data.SqlClient.SqlConnection $connection.ConnectionString = "Server = $Server; Database = $db; User ID = $user; Password = $pass;" $connection.Open() $command = New-Object System.Data.SQLClient.SQLCommand $command.Connection = $connection $command.CommandText = " SELECT A.NAME AS SOFTWARE, CASE WHEN sccmuninstallid IS THEN '' ELSE sccmuninstallid END AS Collection_Desinstalacao, CASE WHEN ComputerGroupName IS THEN '' ELSE ComputerGroupName END AS Collection_Instalacao FROM tblApplication AS A LEFT JOIN tabCID_cf_a_1 AS B on a.ApplicationID = b.ElementID LEFT JOIN tblComputerApplications AS C ON C.ApplicationID = A.ApplicationID LEFT JOIN tblComputer AS D ON D.ComputerID = C.ComputerID LEFT JOIN tblApplicationStoreData as E on e.ApplicationID = a.ApplicationID WHERE OperatingSystem in ('Microsoft Windows 7 Enterprise','Microsoft Windows 10 Enterprise') and [Software Específco] = 1 and HostName ='"+$ResSComp.NetbiosName+"'" $Reader = $command.ExecuteReader() $DataTable = New-Object System.Data.DataTable $DataTable.Load($Reader) $Lista = $DataTable | select software, Collection_Instalacao, Collection_Desinstalacao | Where-Object{$_.Collection_Instalacao -notlike ''} foreach($Collection in $Lista){ $Coll_Install_ID = $Collection.Collection_Instalacao $Coll_Uninstall_ID = $Collection.Collection_Desinstalacao try{ $Coll_Install_Obj = @(Get-WmiObject -Class SMS_Collection -Filter "CollectionID = '$Coll_Install_ID' AND CollectionType = 2" @extragwmiParameters) if($Coll_Install_Obj.Count -eq 0){ $Coll_Install_Obj = @(Get-WmiObject -Class SMS_Collection -Filter "Name = '$Coll_Install_ID' AND CollectionType = 2" @extragwmiParameters) } if($Coll_Install_Obj.Count -eq 0){ throw "Device collection $Coll_Install_ID not found" } if($Coll_Install_Obj.Count -gt 1){ throw "More than one device collection with name $Coll_Install_ID found" } if($Coll_Install_Obj.Count -eq 1){ $Coll_Install_Obj = $Coll_Install_Obj[0];Write-Host "Found device collection $($Coll_Install_Obj.Name)"} } catch{ Write-Error "Error occurred when getting SCCM device Collection ($Coll_Install_ID). Exception: $($_.Exception.Message)" } try{ $Coll_Uninstall_Obj = @(Get-WmiObject -Class SMS_Collection -Filter "CollectionID = '$Coll_Uninstall_ID' AND CollectionType = 2" @extragwmiParameters) if($Coll_Uninstall_Obj.Count -eq 0){ $Coll_Uninstall_Obj = @(Get-WmiObject -Class SMS_Collection -Filter "Name = '$Coll_Uninstall_ID' AND CollectionType = 2" @extragwmiParameters) } if($Coll_Uninstall_Obj.Count -eq 0){ throw "Device collection $Coll_Uninstall_ID not found" } if($Coll_Uninstall_Obj.Count -gt 1){ throw "More than one device collection with name $Coll_Uninstall_ID found" } if($Coll_Uninstall_Obj.Count -eq 1){ $Coll_Uninstall_Obj = $Coll_Uninstall_Obj[0];Write-Host "Found device collection $($Coll_Uninstall_Obj.Name)"} } catch{ Write-Error "Error occurred when getting SCCM device Collection ($Coll_Uninstall_ID). Exception: $($_.Exception.Message)" } Adicionar computador de destino nas collection de instalação if($ResCompDes -ne $){ try{ $NewRule = (Get-WmiObject -List -Class SMS_CollectionRuleDirect @extragwmiParameters).CreateInstance() $NewRule.ResourceClassName = "SMS_R_System" $NewRule.ResourceID = $ResCompDes.ResourceID $NewRule.Rulename = $ResCompDes.Name $Coll_Install_Obj.AddMemberShipRule($NewRule) | Out- $Coll_Install_Obj.RequestRefresh() | Out- Write-Host "Added computer $($ResCompDes.Name) to collection $($Coll_Install_Obj.Name)" } catch{ Write-Error "Error occurred when adding $ResPatDest.netbiosname to collection $Collection. Exception: $($_.Exception.Message)" } } Start-Sleep -s 5 Adicionar computador de origem nas collection de Desinstalação if($ResSComp -ne $){ try{ $NewRule = (Get-WmiObject -List -Class SMS_CollectionRuleDirect @extragwmiParameters).CreateInstance() $NewRule.ResourceClassName = "SMS_R_System" $NewRule.ResourceID = $ResSComp.ResourceID $NewRule.Rulename = $ResSComp.Name $Coll_Uninstall_Obj.AddMemberShipRule($NewRule) | Out- $Coll_Uninstall_Obj.RequestRefresh() | Out- Write-Host "Added computer $($ResSComp.Name) to collection $($Coll_Uninstall_Obj.Name)" } catch{ Write-Error "Error occurred when adding $ResSComp.netbiosname to collection $Collection. Exception: $($_.Exception.Message)" } } Start-Sleep -s 5 Remover computador das collectins de instalação if($Coll_Install_Obj.Name -ne $ -and $ResSComp.Name -ne $){ if($Coll_Install_Obj.CollectionType -eq 2 -and $ResSComp.ResourceType -eq 5){ Applies to Computer/Device try{ $CollRule = (Get-WmiObject -List -Class SMS_CollectionRuleDirect @extragwmiParameters).CreateInstance() $CollRule.ResourceClassName = "SMS_R_System" $CollRule.ResourceID = $ResSComp.ResourceId $CollRule.Rulename = $ResSComp.Name $CollRule $Coll_Install_Obj.DeleteMemberShipRule($CollRule) At that point I got an e
        Expand Post
        • We decided to not query SLM and instead just use the collections identified in SCCM for a machine. I do have Powershell that looks at what installs are associated with a machine in SLM and puts that machine in those SCCM collections to try to clean up any installs that occurred manually outside of SCCM.  Let me know if you need anything. Jerry
          Expand Post
          • ‌ Without consulting SLM you risk adding and / or removing collection that are not specific software, otherwise I'm using SLM to specifically identify categorized software within SNOW, so I work in a reduced and controlled collection space. thanks!
            Expand Post
          • ‌ Without consulting SLM you risk adding and / or removing collection that are not specific software, otherwise I'm using SLM to specifically identify categorized software within SNOW, so I work in a reduced and controlled collection space. thanks!
            Expand Post
  • Hello Ricardo, depending on your specific environment, this will not be an easy one. You have three levels of "all the software that is installed on a particular computer": Software that has been ordered through AP service and all information available Software that has been automatically installed through SCCM AP most likely has no information on this deployment and needs to read the SCCM database Manually installed software No automation possible here Basically, the process will be to get the list of installed software from SCCM inventory link this to the corresponding AD groups used in SCCM decide what software comes with the base installation and what has been deployed individually remove the old computer and add the new computer from each AD group. No rocket science but depends on many organisation specific parameters, from my perspective this is nothing where we can deliver an easy solution here in the forum. Kind regards, Axel
    Expand Post
10 of 13

Loading
Software reassignment between workstations