Loading
Computer Name from SLM
 I'm trying to figure out why the Powershell below seems to cause the memory consumption on the Server to go dramatically. I implemented the code on one Service and the memory with go up 10% but eventually go back down. If I implement it on all the Services it causes huge Memory issues. Any help is appreciated. function SLM_Computers   {   param($slmuser,$DeploymentType,$New_Hire,$BusinessArea, $AltUserID)     $apiAccountName = Get-APSetting "SLMApiAccountName"   $SLMServerName = Get-APSetting "SLMServerName"   $SLMCustomerId = Get-APSetting "CustomerId"       $apiUserAccount = Get-ServiceAccount -Name "$apiAccountName" -Scope 1   $securePassword = ConvertTo-SecureString $($apiUserAccount.Password) -AsPlainText -Force   $credential = New-Object Management.Automation.PSCredential ($($apiUserAccount.AccountName), $securePassword)   $version = 8         $cl = @()   #Verify Computer is in SCCM before placing in list   Function Search_Computer_SCCM   {   param ($Resource)     $SCCMServiceAccountName = Get-APSetting "SCCMServiceAccountName"   $SLMServerName = Get-APSetting "SCCMServer"   $SCCMUserName = Get-APSetting "SCCMUserName"   $SCCMServer = Get-APSetting "SCCMServer"   $SCCMSiteCode = Get-APSetting "SCCMSiteCode" $SCCMServiceAccount = Get-ServiceAccount -Name "$SCCMServiceAccountName" -Scope 0   $SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force   $SCCMCredentials = 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     #Firsts checks if the resource is a device (computer)   if ($Resource.Contains('\'))   {   $OldDomainPart = $Resource.Split('\')[0]   $OldComputerNamePart = $Resource.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 like '%$Resource%' AND Client = '1'" @extragwmiParameters) }     # if ($OldResObj.Count -gt 1) { throw "More than one device/computer with name $Resource found (with Client = 1)" } return $OldResObj.Name }   Function Search_Comp_SLM {   param($slmuser, $SnowAPICred)   $cl =@() $userapi =" http:// " + $SLMServerName + "/api/customers/1/users/?%24filter=endswith%28Username%2C%27" + $slmuser + "%27%29&`$top=100&`$format=json" $body = Invoke-RestMethod -Uri $userapi -Method Get -Credential $credential -disablekeepalive $SnowUserID = $body.Body.body.ID foreach ($s in $SnowUserID){   $compapi = " http:// "+ $SLMServerName + "/api/customers/1/users/" + $s + "/computers/?`$top=1000&`$format=json" $comptemp = Invoke-RestMethod -Uri $compapi -Method Get -Credential $credential -disablekeepalive $comps += $comptemp.body   }       #Evaluate parameter conditions   if ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "Commercial") {     $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -notlike "*T2017*") -and ($_.Body.Organization -notlike "*FED*") -and ($_.Body.Name -NOTlike "XD7-M*") }   ForEach($comp in $justcomps) {     #check if computer is in SCCM   $checkSCCM = Search_Computer_SCCM -Resource $comp.Body.Name   if ($checkSCCM) {   $cl += $comp.Body.Name     }   $checkSCCM = $   }   } elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "T2017"){     $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -like "*T2017*") -and ($_.Body.Name -NOTlike "FEDVDAP*") }   $cl += $justcomps.Body.Name   }     elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "T3"){     $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -like "*Fed*") }   $cl += $justcomps.Body.Name   }     elseif ($DeploymentType -eq 'MAC' -and $BusinessArea -eq "Commercial") {     $justcomps = $comps| ? {$_.Body.Manufacturer -like "*Apple*"}   $cl += $justcomps.Body.Name   } elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "Fidelis") {     $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -notlike "*T2017*") -and ($_.Body.Organization -notlike "*FED*") -and ($_.Body.Name -NOTlike "XD7-M*") }   $cl += $justcomps.Body.Name }   return $cl }   $complist =@()     if (($New_Hire -eq 'Yes') -and ($DeploymentType -ne 'AD')){   $cl = 'Unknown'   }     if ($DeploymentType -eq 'AD'){   $cl = 'Citrix'   }     Else{   $complist += Search_Comp_SLM -slmuser $slmuser   if ($AltUserID){   $complist += Search_Comp_SLM -slmuser $Altuserid   }       } $complist | Sort-Object | Get-Unique   }

  • Hi, I haven't been able to run your script myself, but perhaps I can help anyway. What happens if you run the script manually in PowerShell? Does the memory consumption look the same? Do you get a large amounts of objects from  Search_Comp_SLM ? What if you run the script without ever calling the SCCM function? Would that make it use less memory? I noticed that the function Search_Computer_SCCM refers to a variable called $Credentials which is never defined. The function Search_Comp_SLM refers to a variable called $credential which is not defined, but it has a parameter called $SnowAPICred which should probably be used instead. Perhaps a part of the script was not pasted in the post? In the end of the script I would suggest that you first filter the result before sorting it. Instead of: $complist | Sort-Object | Get-Unique‍ Do this: $complist | Get-Unique | Sort-Object‍ However, this should not affect performance much unless you are dealing with very large amounts of objects. Regards John
    Expand Post
    • Thanks for your help John!! I was working with the script when I posted it and trying different things so I had a bit of sloppiness .  I use the Search_Computer_SCCM to verify the asset is still in SCCM. I have found that with out that script computers return in the search that are not in SCCM anymore which causes errors when we try to add the machine to the collection. If there is a better way I'm open to ideas. I'm dealing with a very complicated environment where users have multiple LogonIDs in different domains (some isolated and some not), multiple computers in any of the domains which is why I use SLM as the source of the computers. Here is the updated Powershell and I tested it this morning and I went from 18% memory consumption to 27%. I see no noticeable memory usage when I run in on my client machine.  function SLM_Computers { param($slmuser,$DeploymentType,$New_Hire,$BusinessArea, $AltUserID) #<# $apiAccountName = Get-APSetting "SLMApiAccountName" $SLMServerName = Get-APSetting "SLMServerName" $SLMCustomerId = Get-APSetting "CustomerId" $apiUserAccount = Get-ServiceAccount -Name "$apiAccountName" -Scope 1 $securePassword = ConvertTo-SecureString $($apiUserAccount.Password) -AsPlainText -Force $credential = New-Object Management.Automation.PSCredential ($($apiUserAccount.AccountName), $securePassword) $version = 8 #> #test credientials <# $user = "apiuser" $secpasswd = ConvertTo-SecureString “Password" -AsPlainText -Force $customer = "1" $SLMServerName = "snow.centene.com" $credential = New-Object System.Management.Automation.PSCredential ($user, $secpasswd) #> $cl = @() #Verify Computer is in SCCM before placing in list Function Search_Computer_SCCM { param ($Resource) #<# $SCCMServiceAccountName = Get-APSetting "SCCMServiceAccountName" $SLMServerName = Get-APSetting "SCCMServer" $SCCMUserName = Get-APSetting "SCCMUserName" $SCCMServer = Get-APSetting "SCCMServer" $SCCMSiteCode = Get-APSetting "SCCMSiteCode" $SCCMServiceAccount = Get-ServiceAccount -Name "$SCCMServiceAccountName" -Scope 0 $SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force $SCCMCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName, $SCCMServiceAccountPassword #> #test credientials <# $SCCMServiceAccountName = " SnowWorkflowEngine_T@centene.com " $SLMServerName = "STLSCCM02P.centene.com" $SCCMUserName = "centene\SnowWorkflowEngine_T" $SCCMServer = "STLSCCM02P.centene.com" $SCCMSiteCode = "OFL" $SCCMServiceAccount = " SnowWorkflowEngine_T@centene.com " $SCCMServiceAccountPassword = "Password" | ConvertTo-SecureString -AsPlainText -Force $SCCMCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName, $SCCMServiceAccountPassword #> $extragwmiParameters = [ordered]@{ "Namespace" = "Root\SMS\Site_$SCCMSiteCode" "ComputerName" = $SCCMServer "Credential" = $SCCMCredentials "ErrorAction" = 'Stop' } #endregion #region Validate Old SCCM resource #Firsts checks if the resource is a device (computer) if ($Resource.Contains('\')) { $OldDomainPart = $Resource.Split('\')[0] $OldComputerNamePart = $Resource.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 like '%$Resource%' AND Client = '1'" @extragwmiParameters) } # if ($OldResObj.Count -gt 1) { throw "More than one device/computer with name $Resource found (with Client = 1)" } return $OldResObj.Name } Function Search_Comp_SLM { param($slmuser, $SnowAPICred) $cl =@() $userapi =" http:// " + $SLMServerName + "/api/customers/1/users/?%24filter=endswith%28Username%2C%27" + $slmuser + "%27%29&`$top=100&`$format=json" $body = Invoke-RestMethod -Uri $userapi -Method Get -Credential $SnowAPICred -disablekeepalive $SnowUserID = $body.Body.body.ID foreach ($s in $SnowUserID){ $compapi = " http:// "+ $SLMServerName + "/api/customers/1/users/" + $s + "/computers/?`$top=1000&`$format=json" $comptemp = Invoke-RestMethod -Uri $compapi -Method Get -Credential $SnowAPICred -disablekeepalive $comps += $comptemp.body } #Evaluate parameter conditions if ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "Commercial") { $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -notlike "*T2017*") -and ($_.Body.Organization -notlike "*FED*") -and ($_.Body.Name -NOTlike "XD7-M*") } ForEach($comp in $justcomps) { #check if computer is in SCCM $checkSCCM = Search_Computer_SCCM -Resource $comp.Body.Name if ($checkSCCM) { $cl += $comp.Body.Name } $checkSCCM = $ } } elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "T2017"){ $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -like "*T2017*") -and ($_.Body.Name -NOTlike "FEDVDAP*") } $cl += $justcomps.Body.Name } elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "T3"){ $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -like "*Fed*") } $cl += $justcomps.Body.Name } elseif ($DeploymentType -eq 'MAC' -and $BusinessArea -eq "Commercial") { $justcomps = $comps| ? {$_.Body.Manufacturer -like "*Apple*"} $cl += $justcomps.Body.Name } elseif ($DeploymentType -eq 'SCCM' -or $DeploymentType -eq 'Manual' -and $BusinessArea -eq "Fidelis") { $justcomps = $comps| ? {($_.Body.OperatingSystem -like "*Windows*") -and ($_.Body.OperatingSystem -notlike "*server*") -and ($_.Body.Organization -notlike "*T2017*") -and ($_.Body.Organization -notlike "*FED*") -and ($_.Body.Name -NOTlike "XD7-M*") } $cl += $justcomps.Body.Name } return $cl } $complist =@() if (($New_Hire -eq 'Yes') -and ($DeploymentType -ne 'AD')){ $cl = 'Unknown' } if ($DeploymentType -eq 'AD'){ $cl = 'Citrix' } Else{ $complist += Search_Comp_SLM -slmuser $slmuser -SnowAPICred $credential if ($AltUserID){ $complist += Search_Comp_SLM -slmuser $Altuserid -SnowAPICred $credential } } $complist | Get-Unique | Sort-Object }
      Expand Post
      • Hello Jerry. The only obvious thing i see here that could be a memory problem, and I believe that was what John as well noticed, is the use of += to add computers to an array. Each time you do this PowerShell will actually create a new array, assign all the old values and add the new ones to it, so if your SLM query would return a lot of results this could create a massive number of arrays held in memory. If you have large datasets I would suggest looking in to replacing it with an arraylist instead. You can find a quickstart for them here: https://powershell.org/2013/09/powershell-performance-the-operator-and-when-to-avoid-it/ Other than that, I would also suggest moving some functionality out of the helper functions, and in to the SLM_Computers function. For example, the Get-APSetting CmdLet uses an API call to get it's values. If the Search_Computer_SCCM function is run many times this will result in a lot of extra calls to get the same data. This should not be a huge memory problem though, but it might have some effect on general performance. Finally, a catch to sorting and using the get-unique CmdLet.. Get-Unique only filters on this and the next object inside an array, so while Johns suggestion might work, you should be aware of the behavior. for example: > 1,1,2,2,3,3  | Get-Unique 1 2 3 > 1,2,3,1,2,3  | Get-Unique 1 2 3 1 2 3 Another thing I was curious about is where this is used in AP? Is it as an Activity?
        Expand Post
        • The text is too long to be displayed. (Options -> Query settings -> TEXT -> 60000)
          • Hi, Does the memory consumption cause problems? Usually .Net is handling the garbage collection on the server so that it will use some additional memory if available, when needed, and reduce memory consumption when needed. Another thing you could try is to filter the wmi query a bit more. It might not affect the memory consumption that much, but it might make it a bit faster. Something like this: Get-WmiObject -Query "select Name from SMS_R_System where Name = '$OldComputerNamePart' AND ResourceDomainORWorkgroup = '$OldDomainPart' AND Client = '1'"‍ @extragwmiParameters‍ This would make it return only the Name property, which seem to be the one you need.
            Expand Post
            • Thanks John! Yes the memory will eventually get to 99% and the system will be unusable until the system does dumps and the memory resets and the memory will slowly starts to grow again. I have no clue what is causing this. My old code which is not pretty has no issues but it doesn't handle the SCCM check (i have tried commenting the SCCM check out to see if it was the cause) or users with multiple loginid's.   The SCCM code does seem faster! Jerry
              Expand Post

Loading
Computer Name from SLM