Delete a SCCM collection from the command-line - powershell

When using the UI (SCCM 2012), to be able to delete a collection (let's say CollA), you need first to ensure it is not linked by any rule to another (let's say CollB, etc..) such as :
CollB includes CollA
CollC excludes CollA
When dealing with a lot of collections, deleting a collection can be time-consuming. For that reason, I have created a script,
usable remotely to avoid the need to connect through RDP
which checks that CollA has no rule left (even if that is not a problem if we want to delete CollA)
which checks if CollA is "linked" to other collections (include or exclude rules)
which deletes any rule found (between CollB and CollA, between CollC and CollA)
I'm stuck now for I can not find a way to delete CollA.
For authentication matters and for remote purpose, I use a lot Powershell and WMI.
$CollA=Get-WmiObject -computername servername -namespace root\sms\site_111 -credential $cred -query "select * from SMS_Collection where Name='Tartempion'"
$CollA.get()
At that point, I found a method Delete(), which when I try to use it, it gives me :
Exception calling "Delete" with "0" argument(s): "Generic failure "
At line:1 char:1
+ $coll.delete()
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
If that is the method that I should use, what are the arguments to be passed ?
EDIT 1
As pointed by theMadTechnician, the SCCM collection, once retrieved in $CollA, a System.Management.ManagementObject.
I should, as described in the MSDN pages, be able to use the following method :
Delete() > produces the error mentioned above
Delete(DeleteOptions) > I can not find the specs for the required options
Delete(ManagementOperationObserver) > I can not find the specs for the required options
To ensure I properly understood the MSDN page regarding *.Delete(), i tried (successfully) the following:
PS C:\> Set-WmiInstance -Class win32_environment -argument #{Name="testvar";VariableValue="testvalue";UserName="<SYSTEM>"}
PS C:\> (gwmi -class win32_environment -filter "Name='testvar'").gettype()
PS C:\> (gwmi -class win32_environment -filter "Name='testvar'").delete()
EDIT 2
The fact is that when deleting a SCCM collection through the console, the collection is not the only thing removed from the inventory : the assignments for instance, are too removed. It reminds of the CASCADE switch when dealing with MySQL or ORACLE. Maybe what I'm trying to do is not possible
without using the console
without using the SCCM cmdlets
If it can not be done that way, I just need to be sure.
EDIT 3
After some maturing, I am starting to wonder if it could be a authorization matter. I mean, the account I am using with the "-credential" switch or when connecting to the server, to open a SCCM console, allows me to create/update/delete collection but, for instance, it does not allow me to delete a device. I would expect the error message to be different but who knows ?
More or less about the same matter (sorry for the digression), trying to remove a device from the commandline, I found this and I have the same error message (see above). If it works for others and not me, could it be authorization related ?
EDIT 4
I requested a service account with more "privileges" than I have with my technical account.
I tested and I have the same error. I am putting aside the authorization hypothesis.

I just tested this in our SCCM 2012 environment by using the following command:
$CollA=Get-WmiObject -computername servername -namespace root\sms\site_111 -query "select * from SMS_Collection where Name='Tartempion'"
Basically, take the -credential out of there. Does it work now?

You could potentially setup a script like so:
#if the delete command fails...
if(!($?))
{
$limitedcollectionName = $colla.LimitedCollectionName
$limitedcollection = Get-WmiObject -computername servername -namespace root\sms\site_111 -query "select * from SMS_Collection where Name=`'$limitedcollectionname`'"
$limitedcollectionname.delete()
}

Related

How do I attach a debugger to a process using Invoke-WmiMethod?

I have a process already running on a remote computer and I'd like to attach a debugger to it. I would like to use Invoke-WMIMethod so that when I disconnect from that remote session, the debugger will remain attached to the process in the background.
So far I have:
$Qry = "Select * from Win32_Process where ProcessID like $ID"
$CimIO = Get-WMIObject -Query $Qry
Invoke-WMIMethod -InputObject $CimIO -Class Win32_Process -Name AttachDebugger -AsJob
And I'm getting the following error:
Invoke-WmiMethod : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ Invoke-WmiMethod -InputObject $CimIO -Class Win32_process -Name Attac ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-WmiMethod], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWmiMethod
Am I on the right track? When I try other Methods from Win32_Process (like GetOwner), I get the same error message. What's going on here?
EDIT:
Perhaps I am going about this all wrong: My understanding was that the query would return a pointer to the running process which could then be used as an input object to Invoke-WmiMethod.
Debug-Process requires that a separate debugger already be downloaded and installed on the machine whereas "AttachDebugger" as a method is installed by default (at least I'm assuming since it was on a fresh copy of Windows 10). The reason why I want to use built-in methods only is because I would like this script to be usable in a production environment where I will not have control over what's installed on the computers.
I found the method by running the script found here which found the method residing in Win32_Process. I went with Invoke-WmiMethod because when -AsJob is invoked, it creates a job locally on the remote computer where the process I'm sending to a debugger resides.
Thank you for the help and I'm sorry for the confusion: this is part of my first powershell script.
The use case is follows:
In a SIEM environment the user sees a program on the network acting suspicious. The user then remotely logs into the victim computer and freezes the suspicious thread by sending it to a debugger. The user then logs out and will get back to analyzing the thread later. The thread will remain frozen until that time.
I've personally never tried or had a reason to try this use case.
However, AsJob is used for long running tasks. You are only querying to get a listing of a single Process ID and once that listing is provided, the job is done / stopped / completed.
There is nothing to attach to. Lastly, where are you getting this method --- AttachDebugger -- from?
There is no such method using the Get-WmiObject or Invoke-WmiMethod cmdlet parameters. That is what the error is about
Why are you not just using the built-in cmdlet for this effort.
# get function / cmdlet details
(Get-Command -Name Debug-Process).Parameters
Get-help -Name Debug-Process -Examples
Get-help -Name Debug-Process -Full
Get-help -Name Debug-Process -Online

Tigger installation in software center using SCCM 2012 & Powershell

I would need some directions where to look for an solution.
I need to trigger install on a few programs in SCCM 2012 software center on Windows 10 clients through Powershell. I guess some of those are User Based Packages(not sure about this at all) but when i run the following.
$Application = Get-CimInstance -Namespace "root\ccm\clientSDK" -ClassName CCM_application
$Application
I get some of the programs, but many of them is missing.
If I open software center and click install on any programs manually it will then appear when I use the command above.
I've been reading about CCM-Application I found something about you only get device based packages.
I cannot access any servers so accessing CMApplicationCatalog is not possible. Like in the links below.
Trigger available application catalog
install-user-based-application-or-packages
In my case using CCM_Application Client WMI Class seems to be hard, I've not found any other solutions then creating New-WebServiceProxy to do this, and I´m not allowed/have permissions to.
I've tried to get the needed parameters for one of the programs that don't appear with the code above from a computer I've installed it on through Software Center.
When I try to run it with the needed parameters on an new installed computer.
$Program = #{"EnforcePreference"=[UInt32]0
"Id" = [String]"ScopeId_MyScopeID, will leave this out for company rules."
"IsMachineTarget" = [Boolean]$false
"IsRebootIfNeeded" = [Boolean]$false
"Priority" = [String]"High"
"Revision" = [String]"7"
}
Invoke-CimMethod -Namespace Root\ccm\clientSDK -ClassName CCM_application -MethodName "Install" -Arguments $Program
I then get error below
Invoke-CimMethod : Not found At line:1 char:1
+ Invoke-CimMethod -Namespace Root\ccm\clientSDK -ClassName CCM_applica ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Root\ccm\clientSDK:CCM_application:String) [Invoke-CimMethod],
CimException
+ FullyQualifiedErrorId : HRESULT 0x80041002,Microsoft.Management.Infrastructure.CimCmdlets.InvokeCimMethodCommand
Maybe I am doing something wrong or what I am trying to do is not possible.
I've also tried uiresource.uiresourcemgr but It returns empty.
I used this much in SCCM 2007 and it worked great. But now it's not giving me anything.
$RunAdvProg = New-Object -ComObject uiresource.uiresourcemgr
$RunAdvProg.GetAvailableApplications();
With this said, Is there anyway way around this or does it exist another function/Method from another class or DLL?

How to set Assigned Access for Edge Browser

I would like to set Edge as an Assigned Access to a User.
I'm using the following PowerShell Command:
Set-AssignedAccess -AppUserModelId Microsoft.MicrosoftEdge -UserName xy
But I always get the following error (translated from German):
System error 1376 has occurred.
The specified local group does not exist.
New-CimInstance : A general error has occurred, for which
no specific error code is available.
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\AssignedAccess\AssignedAccess.psm1:300
Zeichen:13
+ New-CimInstance -ClassName WEDL_AssignedAccess -Property ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (WEDL_AssignedAccess:CimInstance) [New-CimInstance], CimException
+ FullyQualifiedErrorId : MI RESULT 1,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand
The local user exists, and the app exists too. I also logged in with the user I want to set the assignedaccess to make sure the profile is set u0p correctly
This happened on two different Windows 10 (build 14393) machines
I'm on PSVersion:
PS C:\WINDOWS\system32> $psversiontable.psversion.toString()
5.1.14393.1944
Does anybody know how to solve this?
Ran in to this yesterday. From what i could tell the "local group" thats referenced is actually the admin group.
I ran the following commands in an elevated powershell prompt:
Net localgroup administrators /add.
This creates a local Administrators group.
Net localgroup administratörer administrators /add.
This adds the administrators group to the local admin group (Administratörer is the Swedish localization of Administrators, use the local version depending on your country and replace it).
After this is done, run your previous commands.
Give it a try, hope it helps :)
//Chris
Set-AssignedAccess -UserName weakusername -AUMID Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge

Early filtering within the root\ccm\cliensdk namespace

I recently wrote a script that updates registry values on remote desktops after checking, for instance, that a certain application, MyApp, is properly installed.
The aforementioned application is installed/deployed by SCCM (2012, not R2 for the moment).
In the process of optimizing the script, I wanted to change the test of the install state of MyApp (from late to early filtering).
So far, no luck and so far, no explanation either.
I can't properly understand why it seems not possible to do some early filtering with the following command :
gwmi -ComputerName myserver -Namespace root\ccm\clientsdk -query "select * from ccm_application where Fullname='MyApp'"
Of course, nor can we use :
gwmi -ComputerName myserver -Namespace root\ccm\clientsdk -class ccm_application -filter "Fullname='MyApp'"
Late filtering, of course, works but I wanted (and expected) early filtering to work, especially since I am checking the Install state of an app for quite a lot of remote desktops.
Of course, I do know that I could (can) use SCCM for that purpose (executing a script only if ...) but that still does not explain why I can't do early filtering.
Whenever I try to query that class with my installation while specifying either properties or a filter, I get the error "Provider is not capable of the attempted operation". It doesn't matter if I use Get-WmiObject or Get-CimInstance.
I get the same error when I run this:
PS C:\> WMIC.EXE /NAMESPACE:\\root\ccm\clientsdk PATH ccm_application GET FullName
Node - <SERVERNAME>
ERROR:
Description = Provider is not capable of the attempted operation
PS C:\> wmic /NAMESPACE:\\root\ccm\clientsdk PATH ccm_application WHERE "FullName='Java 32-bit'"
Node - <SERVERNAME>
ERROR:
Description = Provider is not capable of the attempted operation
Although this works just fine:
WMIC.EXE /NAMESPACE:\\root\ccm\clientsdk PATH ccm_application
Seems like a limitation of the provider then, not a problem with your code. -Filter and -Property don't work by design.
Note that I am using 2012 R2 SP1 (5.00.8239.1000), so this may not perfectly apply. However, it seems unlikely that they would remove the functionality from the provider moving from 2012 to 2012 R2.

Powershell error/exception handling

I am having some problems with handling errors/exceptions regarding the invoke-command.
I am trying to catch errors when the target computer does not exist, however the message i am shown and the way the script in the catch block acts makes me think there is something i missed or miss understood.
this is the portion of the script with the problem:
$session = New-Pssession -computername $computerName
Invoke-Command -session $session -ScriptBlock $command -ArgumentList $sqlServerName, $userToGivePermisions
Remove-PSsession -session $session
Basically i want to handle errors when $computerName is not a valid computer on the network. I purposely gave it a wrong name to test it out and i get the following error:
[dcd] Connecting to remote server failed with the following error message : WinRM cannot process the request. The following error occured while using Kerberos authentication: The network path was not found.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionOpenFailed
[dcd] is the name of the non existing machine. I put the code in a try catch and did a check on the error message using a -contains. The condition ALWAYS came out false and i tried almost ever single word in the error above.
When i displayed the error message in the catch block using $_.exception.message i got a different error about $session being null.
When i did a -contains using words in the displayed error message about $session it still returned false for every word i tested.
I don't understand which of these is the error and why isn't the -contains ever returning true. I added the -ea stop to all 3 lines to catch all the non terminating errors but to no avail.
Anyone have any idea what is going on?
-contains checks whether an element is in an array or not. e.g:
1,2,3 -contains 2 # Is True
"a","bc","d" -contains "b" # Is False
Try the -match or the -like operators instead. Have a look at the comparison operator documentation.