I've been trying to set DCOM authorities via powershell (specifically for the 10016 error often reported here on Tenforums).

I've no problem making them look the same when looked at through both through the GUI and powershell but adding this by powershell breaks all modern apps (and and so on) whereas doing the same through GUI doesn't.
Code:
function Add-DACL($domain, $name)
{
$trusteeObj = ([wmiclass]'Win32_Trustee').psbase.CreateInstance()
$trusteeObj.Name = $name 
$trusteeObj.Domain = $domain
$ace = ([wmiclass]'Win32_ACE').psbase.CreateInstance()
$ace.AccessMask = 11
$ace.AceFlags = 0
$ace.AceType = 0
$ace.trustee = $trusteeObj
$descL.DACL += [System.Management.ManagementBaseObject]$ace
Write-Host "Set local activation DCOM authority for"$trusteeObj.Domain"/"$trusteeObj.Name
}

When I look everything is the same - same DACL (except my change), same SACL, same control flags

Before
Code:
__GENUS          : 2
__CLASS          : Win32_SecurityDescriptor
__SUPERCLASS     : __SecurityDescriptor
__DYNASTY        : __SecurityRelatedClass
__RELPATH        : 
__PROPERTY_COUNT : 6
__DERIVATION     : {__SecurityDescriptor, __SecurityRelatedClass}
__SERVER         : 
__NAMESPACE      : 
__PATH           : 
ControlFlags     : 32788
DACL             : {}
Group            : System.Management.ManagementBaseObject
Owner            : System.Management.ManagementBaseObject
SACL             : {}
TIME_CREATED     : 
PSComputerName   :
After
Code:
__GENUS          : 2
__CLASS          : Win32_SecurityDescriptor
__SUPERCLASS     : __SecurityDescriptor
__DYNASTY        : __SecurityRelatedClass
__RELPATH        : 
__PROPERTY_COUNT : 6
__DERIVATION     : {__SecurityDescriptor, __SecurityRelatedClass}
__SERVER         : 
__NAMESPACE      : 
__PATH           : 
ControlFlags     : 32788
DACL             : {System.Management.ManagementBaseObject, System.Management.ManagementBaseObject}
Group            : System.Management.ManagementBaseObject
Owner            : System.Management.ManagementBaseObject
SACL             : {}
TIME_CREATED     : 
PSComputerName   :

Is there some other security I'm not aware of? I've many times restored and made the same changes through wmi and the gui but whereas the gui works the powershell doesn't.

Here is the whole lot btw
Code:
#------------------------------------------------------------------------------------------------------------------------------------------------------
# Functions
#------------------------------------------------------------------------------------------------------------------------------------------------------
function enable-privilege
{	param(
	## The privilege to adjust. This set is taken from http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
 	[ValidateSet(
	"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege",
	"SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
	"SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
	"SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege",
	"SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege",
	"SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
	"SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege",
	"SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
	$Privilege,
	## The process on which to adjust the privilege. Defaults to the current process.
	$ProcessId = $pid,
	## Switch to disable the privilege, rather than enable it.
	[Switch] $Disable
	)
	## Taken from P/Invoke.NET with minor adjustments.
 $definition = @'
 using System;
 using System.Runtime.InteropServices;
  
 public class AdjPriv
 {
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
   ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
  
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid
  {
   public int Count;
   public long Luid;
   public int Attr;
  }
  
  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = new IntPtr(processHandle);
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   if(disable)
   {
    tp.Attr = SE_PRIVILEGE_DISABLED;
   }
   else
   {
    tp.Attr = SE_PRIVILEGE_ENABLED;
   }
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
 }
'@
 $processHandle = (Get-Process -id $ProcessId).Handle
 $type = Add-Type $definition -PassThru
 $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}
#------------------------------------------------------------------------------------------------------------------------------------------------------
function Takeown-Registry($key) 
{	switch ($key.split('\')[0])
	{	"HKEY_CLASSES_ROOT" 
		{	$reg = [Microsoft.Win32.Registry]::ClassesRoot
			$key = $key.substring(18)
		}
        "HKEY_CURRENT_USER"
		{	$reg = [Microsoft.Win32.Registry]::CurrentUser
			$key = $key.substring(18)
		}
		"HKEY_LOCAL_MACHINE"
		{	$reg = [Microsoft.Win32.Registry]::LocalMachine
			$key = $key.substring(19)
		}
	}

	# set owner
	$key = $reg.OpenSubKey($key, "ReadWriteSubTree", "TakeOwnership")
	$owner = [Security.Principal.NTAccount]"Administrators"
	$acl = $key.GetAccessControl()
	$acl.SetOwner($owner)
	$key.SetAccessControl($acl)

	# set FullControl
	$acl = $key.GetAccessControl()
	$rule = New-Object System.Security.AccessControl.RegistryAccessRule("Administrators", "FullControl", "Allow")
	$acl.SetAccessRule($rule)
	$key.SetAccessControl($acl)

    # reset owner
    $owner = [Security.Principal.NTAccount]"NT SERVICE\TrustedInstaller"
    $acl = $key.GetAccessControl()
    $acl.SetOwner($owner)
    $key.SetAccessControl($acl)
}
#------------------------------------------------------------------------------------------------------------------------------------------------------
function Add-DACL($domain, $name)
{
$trusteeObj = ([wmiclass]'Win32_Trustee').psbase.CreateInstance()
$trusteeObj.Name = $name 
$trusteeObj.Domain = $domain
$ace = ([wmiclass]'Win32_ACE').psbase.CreateInstance()
$ace.AccessMask = 11
$ace.AceFlags = 0
$ace.AceType = 0
$ace.trustee = $trusteeObj
$descL.DACL += [System.Management.ManagementBaseObject]$ace
Write-Host "Set local activation DCOM authority for"$trusteeObj.Domain"/"$trusteeObj.Name
}
#------------------------------------------------------------------------------------------------------------------------------------------------------
# Grant authority to registry key

Write-Host "Elevating priviledges for this process" -f yellow
do {$result = enable-privilege SeTakeOwnershipPrivilege } 
until ($result -eq $true)
do {$result = enable-privilege SeRestorePrivilege } 
until ($result -eq $true)

$key="HKEY_CLASSES_ROOT\AppID\{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}"
Write-Host "Take ownership of $key" -f yellow
Takeown-Registry($key)

$key="HKEY_CLASSES_ROOT\CLSID\{D63B10C5-BB46-4990-A94F-E40B9D520160}"
Write-Host "Take ownership of $key" -f yellow
Takeown-Registry($key)
# Get current DCOM authorities (Based on https://gallery.technet.microsoft.com/Set-DCOM-ACL-with-650fa48d)

$wmi = Get-WmiObject -Class Win32_DCOMApplicationSetting -Filter 'caption="RuntimeBroker"' -EnableAllPrivileges
$descL  = $wmi.GetLaunchSecurityDescriptor().descriptor

# Reset default authorities

$trusteeObj = ([wmiclass]'Win32_Trustee').psbase.CreateInstance()
$trusteeObj.Name = "ALL APPLICATION PACKAGES" 
$trusteeObj.Domain = "APPLICATION PACKAGE AUTHORITY"
$TrusteeObj.SIDString = "S-1-15-2-1"
$ace = ([wmiclass]'Win32_ACE').psbase.CreateInstance()
$ace.AccessMask = 11
$ace.AceFlags = 0
$ace.AceType = 0
$ace.trustee = $trusteeObj
$descL.DACL = [System.Management.ManagementBaseObject]$ace
Write-Host "Set local activation DCOM authority for"$trusteeObj.Domain"/"$trusteeObj.Name

Add-DACL "NT AUTHORITY" "Self"

# Extra authorities
Add-DACL "NT AUTHORITY" "LocalService" 
Add-DACL "NT AUTHORITY" "System"

# Update DCOM authorities

$Update = $wmi.SetLaunchSecurityDescriptor($descL)

if ($Update.ReturnValue)
{
    Write-Host "Updated DCOM local activation authorities failed" -f Red
}
else
{
    Write-Host "Updated DCOM local activation authorities" -f Yellow
}
Read-Host


I'd appreciate any suggestions as I'm stuck.

Changing the registry permissions works, changing the DCOM permissions breaks everything.

I hope I've included above everywhere I copied bits of the code from.. I'm not a programmer - I'm just trying to learn by picking a problem and trying to solve it. I think it is nearly there but there is some security in Windows I don't know about.

Thanks for your time.