AWOL members from a dynamic group

I’m not a big fan of query based distribution lists as its not easy to locate the groups in AD and its not easy to see who the members are.  I prefer to use Active Roles Dynamic Groups.

Strangely you can’t create a dynamic group you have to convert an existing group.

Any way back in January 2015 ( and I only just found it to blog about when cleaning up my mail box ) I emailed my self a note to blog about a problem I was having because the dynamic group was missing users that as far as I could see should have been in the group.

If you are having this problem then  here are two links to help out.

Members missing from Dynamic Groups (40873)
and
User not showing up in Dynamic Group membership (145947)

By default dynamic groups only include users who have email addresses.

In short you need to un-check this box and you might want to increase the maximum number of members too.

DynamicGroupConfig

 

Advertisements

Why can’t ARS manage these users?

Just a quick post about something that caught me out the other day.  In short I had some users that a custom ARS script policy was not applying to, even though they were in scope of the policy.  I even linked the policy directly to a user object and still the policy was not applying.  ARRRGHGHHH, OK I didn’t really scream out loud, I’m British so I stayed calm and drank some more tea :-).

The quick answer, as my post ended up a little longer than intended and I know some people are so impatient they want answers immediately,  is that ARS does not manage deprovisioned users.

I first noticed what appeared to be a strange anomaly when I realised that the users were out of scope because they had been moved to a different OU by the deprovision steps.

Now the smart reader will know what my issue was but it took me a few more steps before the penny actually dropped and I realised why it wasn’t working.

I had a script policy to allow the service desk to set a custom out of office reply without needing to delegate access to the users mailbox.  I added a custom attribute to store the OOO message in and a second attribute that when changed would trigger the script.

This worked well until they noticed that a leaver had the default message on not the custom one they had set.  When I looked I realised that the user was no longer in scope of the policy as it was not linked to the disabled users OU.  My policy only worked if the user was enabled and in the correct OU which was fine as they normally did this for users who rang up from home and needed the OOO set.

I didn’t want to link the policy to the disabled OU as there were a lot of legacy account in it so I thought I’d create a Managed Unit with a query to hold the recently disabled users.  Then I’d link the ARS script policy to this MU.

Hmm, no matter what rule I applied, even adding the user explicitly to the MU the user was still not showing in the MU.  Have you figured out the problem yet?  I hadn’t quite yet but that’s because I didn’t stop to think about the unexpected behavior.  I had HR chasing me  to fix this users OOO.  I then tried to link the policy direct to the specific user and then set the OOO.  This didn’t work either.

Why?  OK so this is what I figured out and hadn’t realised before.  ARS ignores deprovisioned users for everything except an undo deprovision policy.  I’m sure there is a good reason for this, I’m not sure what it is though, does anyone know.

Anyway the work around to get a policy to work is to set the edsvaDeprovisionStatus attribute to zero.  ARS will then think it is a normal account and start processing it.

Don’t forget to switch the attribute value back to 1 when you have finished.

Bottom line here is that ARS does not manage deprovisioned accounts.  My workaround is not going to scale as there is no way of automating the attribute being toggled between 0 and 1, not using ARS anyway as it’s its 1 then ARS won’t manage it, catch 22 right there! Use my work around as a last resort and at least now if you do have the same problem you will know why.

 

 

 

PosH remoting in ARS

I haven’t posted for a while as I’ve been too busy at home and at work and sorry to say my blog has not had the priority it probably should have.
I seem to remember promising some follow ups on posts with more detail so I’ll try and do this soon ( I’ll have to read my own blog now to find them :-).
In the mean time Here’s a script snippet showing how I use PowerShell remoting within an ARS policy script. I thought this might be useful to post.

The snippet does not show the event handlers but hopefully you know how to use those, if not hust ask. There are examples elsewhere in my blog and
it’s well documented by Dell in the SDK.

function onInit($context) {
# Initialisation function (sets the available script parameters and sensible defaults)
$par02 = $context.AddParameter("debugging")
$par02.MultiValued = $false
$par02.PossibleValues = "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
$par02.DefaultValue = "1"
$par02.Description = "Debugging EventLog Level where: 0 is no debugging; 9 is the most verbose; 1 is the least verbose"
$par02.Required = $false
#
$par05 = $Context.AddParameter("SMTP Server")
$par05.MultiValued = $false
$par05.Description = "Specify the SMTP gateway server to use"
$par05.Defaultvalue = "smtp.clan8.com"
#
#
$par09 = $Context.AddParameter("ExchangeServers")
$par09.MultiValued = $true
$par09.DefaultValue = "ExchangeServer1;ExchangeServer2;ExchangeServer3"
$par09.Description = "Exchange Servers to connect to when setting the Out Of Office Message"
$par09.Required = $false
#
$par10 = $Context.AddParameter("ScriptOwner")
$par10.MultiValued = $false
$par10.DefaultValue = "lee.andrews@MyDomain.com"
$par10.Description = "Email Address to send error messages to"
$par10.Required = $false
}

$scriptVersion = 1.0
$debugLevel = [string]$PolicyEntry.Parameter("debugging")

function Get-PSSessionStatus {
[CmdletBinding(SupportsShouldProcess=$true)]
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No snapin name specified!")]
[string]$moduleName,
[string]$remoteServerName,
[int]$debugLevel
)
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> in Get-PSSessionStatus ... session name: $moduleName ") }
Get-PSSession | Where-Object { ( ( $_.ConfigurationName -eq "$moduleName" ) -and ( $_.state -ne "Opened" )) } | Remove-PSSession | Out-Null
if(!(Get-PSSession | Where-Object {$_.ConfigurationName -eq "$moduleName"})) {
try {
$ExSession = New-PSSession -Name $remoteServerName -ConfigurationName "$moduleName" -ConnectionUri "http://$remoteServerName.clan8.com/powershell" -Authentication Kerberos -ErrorAction Stop
$importedSession = Import-PSSession $ExSession -DisableNameChecking
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> PS Session $moduleName was imported ") }
return $ExSession
} # try
catch {
$EventLog.ReportEvent($Constants.EDS_EVENTLOG_ERROR_TYPE,"_v$scriptVersion >>>>>>> ERROR: PS Session $moduleName failed to be imported : Server $remoteServerName" )
$ScriptOwner = [string]$PolicyEntry.Parameter("ScriptOwner")
$SMTPServer = [string]$PolicyEntry.Parameter("SMTP Server")
Send-MailMessage -To $ScriptOwner -From $ScriptOwner -Subject "ERROR: PS Session $moduleName failed to be imported on $($env:COMPUTERNAME)" -SmtpServer $SMTPServer -Body "Failed to add server $remoteServerName from $($env:COMPUTERNAME)" -Encoding ([System.Text.Encoding]::UTF8)
} # catch
} #if(!(Get-PSSession | Where-Object {$_.ConfigurationName -eq "$moduleName"})) {
else {
#if (
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> PS Session $moduleName was already imported") }
return $(Get-PSSession | Where-Object {$_.ConfigurationName -eq "$moduleName"})
}
} # Function to check if a PS session is loaded.

# use this code to connect to the ExchangeServer hosting the powershell comandlets
# You could hard code these as an array of server names $ExchangeServers = @("ExchangeSvr1","ExchangeSvr2")

$ExchangeServers = $([string]$PolicyEntry.Parameter("ExchangeServers")).split(";",[System.StringSplitOptions]::RemoveEmptyEntries)

# I use multiple server in case one is unavailable
$numberOfExchangeServers = $ExchangeServers.count
# create Exchange PowerShell remote session - set error flag if unable to do this and email support
$ExchangeServerUsed = ""
for ($serverNumber = 0; $serverNumber -lt $numberOfExchangeServers; $serverNumber ++) {
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> in : Getting Remote PS Session on $($ExchangeServers[$serverNumber]) ") }
$sessionData = Get-PSSessionStatus "Microsoft.Exchange" $ExchangeServers[$serverNumber] $debugLevel
if ( $sessionData ) {
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> in : GOT Remote PS Session on $($ExchangeServers[$serverNumber])") }
$ExchangeServerUsed = $sessionData.Name
$SnapinError = $false
break
}
else {
if ( $debugLevel -ge 9 ) { $EventLog.ReportEvent($Constants.EDS_EVENTLOG_INFORMATION_TYPE,"_v$scriptVersion >>>>>>> in : ERROR Getting Remote PS Session on $($ExchangeServers[$serverNumber])") }
$SnapinError = $true
}
}

# now you can use the $SnapinError variable to abort if you were unable to establish a remote PosH session - sending alerts etc as part of the exit routine
if ( $SnapinError ) {
# abort code goees here
}
# otherwise put you script her to do whatever you wanted with the exchange commandlets
# e.g. $recipient = Get-Recipient $groupName

# and when you finished close the session - this is IMPORTANT or your ARS server will run out of reource and so will your exchange server!
Remove-PSSession $sessionData

Blogging 101 Day One: Introduce yourself to the world

Having enrolled in the blogging 101 to see if I can improve my blog here’s the first assignment.

  • Why are you blogging publicly, rather than keeping a personal journal?

So this one is easy, it’s to shorten my google search to just my blog for anything ARS / Powershell or AD related.  Like that’s going to happen any time soon.  This is where I’m posting all the things I find out in the hope that other people can make use of it and save them the pain of solving it themselves

  • What topics do you think you’ll write about?

Another easy one, come on surely you can think of a harder question?  ARS, PowerShell and AD related topics oh and my new app Password Manager Pro.  There’s lots of things wrong with PMP so I can see a lot of posts on this in the coming months.

  • Who would you love to connect with via your blog?

Other IT people working in the same area as me.  I’d actually like, in some instances to get feed back on possible solutions that I post.

  • If you blog successfully throughout the next year, what would you hope to have accomplished?

Actually I’m not that organised in that I have a goal that I want to achieve with the blog.  Which is good, right as I can’t fail either.  Who said if you fail to plan you plan to fail.  They got that wrong didn’t they 🙂

Anyways, Happy New Year!

Lee

 

 

 

 

Enabling Debug Log on an ARS server

To enable the debug log on an ARS server you add a new DWORD value ‘debug’ to the Enterprise Directory Manager key and set it to 1.

Watch out though the log gets large very quickly and the default location is the install directory which is probably on your C drive.  In other words it’s about to crash your server because you will run out of space on the C: drive. 

Why Dell didn’t dell allow this to be redirected?  Also they should break the file up into smaller chunks.  

Realising the second issue Dell do provide a script to limit the log file size.  I modified this script a little to allow me to have a little more control over the log files. 

My script uses a loop to prompt you to archive the log and also automates splitting the log into smaller chunks.  I plan to use a powershell job to allow the script to keep running in the back ground but this version just waits for you to respond.  Assuming I get it working using a powershell job then I can also automate a maximum size.

it also does some other stuff like deleting any existing logs before you start and also it allows you to name the files using the incident number.  It’s written as a standalone function but I’ve included the code I used to manage enabling, capturing and archiving the logs ready to send off to Dell.

The function has two switches -stop to stop the logging and -initialise which will start the logging and delete any existing logfile.

I can see that I didn’t quite finish writing a standalone function so I’ll need to revisit it later when I have time. It’s easy to fix but I have some objectives to update before my end of year review 😦 so it will have to be some other time. It’s fully functional though so you can always take this as it is and modify it to fit your requirements.



Function Move-DSLog {
 param (
  $outputLogFileName,
  $dsLogFile,
  $regkey,
  [switch]$initialise,
  [switch]$stop
 )
 Write-host "Debug currently set to : $(Get-ItemProperty -path $regkey -name Debug | select -ExpandProperty debug)"
 if ( $initialise ) {
  if ( $(Get-ItemProperty -path $regkey -name Debug | select -ExpandProperty debug) -eq 1 ) {
   Write-Host "DEBUG already enabled"
   Write-Host "Disabling Debug so we can clear any old log files"
   set-itemproperty -path $regkey -name Debug -value 0
   sleep -Seconds 1
  }
  if ( $(Get-ItemProperty -path $regkey -name Debug | select -ExpandProperty debug) -eq 0 ) {
   Write-Host "Deleting any existing log file"
   if ( Test-Path $dsLogFile ) {
    Remove-Item $dsLogFile
   }  
   Write-Host "Setting DEBUG reg Key to 1"
   try { 
    set-itemproperty -path $regkey -name Debug -value 1 
   }
   catch { 
    Write-Host "FATAL ERROR: Failed to set debug reg key to 1 "
    exit 
   }
  }
  else {
   Write-Host "FATAL ERROR: Failed to set debug reg key to 0"
   exit   
  }
  Return 
 }
 if ( Test-Path $dsLogFile ) {
  Write-Host "Moving DEBUG Log"
  try { 
   set-itemproperty -path $regkey -name Debug -value 0 
   sleep -Seconds 1
  }
  catch { 
   Write-Host "FATAL ERROR: Failed to set debug reg key to 0" 
   exit 
  }
  if ( Test-Path $dsLogFile )  {
   $fileMovedSuccesfully = $false
   $loopCount = 0 
   while ($fileMovedSuccesfully -eq $false ) {
    $loopCount++
    try { 
     move-item $dsLogFile $outputLogFileName -ErrorAction SilentlyContinue
     $fileMovedSuccesfully = $true
    }
    catch { 
     $fileMovedSuccesfully = $false
    }
    if ( $loopCount -gt 10 ) {
     Write-Host "FATAL ERROR: unable to move logfile!"
     exit
    }
   }
  }
 }
 if ( $stop ) {
  exit 
 } # stop  
 else { 
  Write-Host "Setting DEBUG reg Key to 1"
  try { 
   set-itemproperty -path $regkey -name Debug -value 1 
  }
  catch { 
   Write-Host "FATAL ERROR: Failed to set debug reg key to 1 "
   exit 
  }
 }
} # end function 
  
# user definable parameters
$maxLogFileSize = 1          # max filesize in Meg 
$regkey = "HKLM:\SOFTWARE\Aelita\Enterprise Directory Manager"
$installationFolder = Get-ItemProperty -Path $regkey | Select -Expand InstallPath
$dsLogfileName = "ds.log"
$dsLogfileName = $InstallationFolder + $dsLogfileName

$destpath = "d:\ARSDSlogs\"  # folder must exit 
$destinationFileName = "ds"  # example file name
$destinationFileName = Read-Host -Prompt "Enter the SRNumber"

 
cls
Move-DSLog -initialise -dsLogFile $dsLogfileName -regkey $regkey
$logsize = 0
$continue = $true
$logNumber = 0
while ($continue ) {
 try { 
  $info = Get-ItemProperty $dsLogfileName -ErrorAction SilentlyContinue | select -expand length 
  [int]$logsize = $info/1MB
 }
 catch { 
  $logsize = 0 
 }
 write-output "Logsize is currently $logsize"
 try { $answer = Read-Host -Prompt "Archive Log Y/N - NOTE: log file size is still growing...." }
 catch { 
  $breakPoint = 0 
 }
 if ( ( $answer -ne $null ) -and ( $answer.ToLower() -eq "y" ) ) {
  $logNumber++
  Write-Host "USER RESPONSE: $answer"
  Write-Host "Moving log to $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date))"
  Move-DSLog -dsLogFile $dsLogfileName -outputLogFileName $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date)) -regkey $regkey   
  try { $answer = Read-Host -Prompt "Continue Logging Y/N" }
  catch { 
   $breakPoint = 0 
  }
  if ( ( $answer -ne $null ) -and ( $answer.ToLower() -eq "n" ) ){
   $logNumber++
   Write-Host "USER RESPONSE: $answer"
   Write-Host "Moving log to $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date))"
   Write-Host "And then stopping log capture"   
   Move-DSLog -dsLogFile $dsLogfileName -outputLogFileName $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date)) -regkey $regkey -stop 
   exit
  }
 }
 if ( ($logsize -gt $maxLogFileSize) -and ( $logsize -ne 0 ) ) {
  $logNumber++
  Write-Host "Max log file limit exceeded...."
  Write-Host "Moving log to $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date))"  
  Move-DSLog -dsLogFile $dsLogfileName -outputLogFileName $($destpath + "DSLog-$logNumber-" +$destinationFileName + "-{0:yyyy-MM-dd-HHmm-ss}.log" -f (get-date)) -regkey $regkey
 }
}


Preventing non admin accounts being added to a group using Active Roles

Here is a function I use to prevent non admin users being added to a group

You can modify this to get the user object and then take appropriate action –

In my case the DN was CN=admin- so I realised I didn;t need to actuially bind to the user object but I left in my original code should I need it later – you can see my original get-qaduser call is commented out

# $member will be the DN
# $user = Get-QADUser $member

NOTE: if you are allowing changes externally to the group as is the case in my environment you also need an onPostModify ($Request)  function to deal with changes syncing in from other DCs.

function onPreModify($Request)
{
# this function handles updates carried out in ARS – prevents non admin user being added
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> Check if this was a group modification”
if ($Request.class -eq “group”)
{
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> Group object modified”
if ( $(Get-IsAttributeModified -AttributeName ‘member’ -Request $Request) )
{
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> Checking if member attribute was modified”
for ($i = 0; $i -lt $Request.PropertyCount; $i++) {
$item = $Request.Item($i)
$Name = $item.Name
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> item = $($item) name = $($name)”
# enumerate the objects attributes until we locate the “member” attribute
if ($Name -eq “member”)
{
# check that the member attribute was modified
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> Found Member Attribute so processing ”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> item control code = $($item.ControlCode) ”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> Constant APEND =  $($Constants.ADS_PROPERTY_APPEND) ”
if($item.ControlCode -eq $Constants.ADS_PROPERTY_APPEND )
{
# iterate through the group members
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> item control code was APPEND so processing…… ”
foreach ($member in $item.Values) {
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> member = $($member)”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> left(member,9) = $($member.substring(0,9))”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> left(member,10) = $($member.substring(0,10))”
# $member will be the DN
#$user = Get-QADUser $member
#if ( $($user.sAMAccountName).substring(0,6) -ne “admin-” )
if ( ( $member.substring(0,9) -ne “CN=Admin-” ) -and  ( $member.substring(0,10) -ne “CN=Admin -” ) -and ( $member.substring(0,7) -ne “CN=svc-” ) ) {
$groupName = Get-AttributeValue -AttributeName “Name” -ADSIObject $Request
$groupDN = Get-AttributeValue -AttributeName “DN” -ADSIObject $Request
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PreModify >>> >> Grp Name : $($groupname) DN: $($groupDN)”
throw “******************************************************`nYou cannot add non ‘admin-<logon name>’ accounts `nto this group`n******************************************************`nNOTE: Script Policy Checks the DN of the user not the logon name”
}
} # end for each
} # end if property changed
} # end if member found
} # end for iterate group members
} # end Check if group members updated
} # end if modified object was a group
} # end function

 

function onPostModify ($Request)
{
# this fucntion deals with changes made outside of ARS…
if ($Request.class -eq “group”)
{
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> Group object modified”
if ( $(Get-IsAttributeModified -AttributeName ‘member’ -Request $Request) )
{
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> Group membership changed”
for ($i = 0; $i -lt $Request.PropertyCount; $i++) {
$item = $Request.Item($i)
$Name = $item.Name
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> item = $($item) name = $($name)”
# enumerate the objects attributes until we locate the “member” attribute
if ($Name -eq “member”)
{
# check that the member attribute was modified
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> Found Member Attribute so processing ”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> item control code = $($item.ControlCode) ”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> Constant ADS_PROPERTY_APPEND =  $($Constants.ADS_PROPERTY_APPEND) ”
if( $item.ControlCode -eq $Constants.ADS_PROPERTY_APPEND )
{
# iterate through the group members
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> item control code was APPEND so processing…… ”
foreach ($member in $item.Values) {
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> member = $($member)”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> left(member,9) = $($member.substring(0,9))”
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only PostModify >>> left(member,10) = $($member.substring(0,10))”
# $member will be the DN
if ( ( $member.substring(0,9) -ne “CN=Admin-” ) -and  ( $member.substring(0,10) -ne “CN=Admin -” ) -and ( $member.substring(0,7) -ne “CN=svc-” ) ) {
$groupName = Get-AttributeValue -AttributeName “Name” -ADSIObject $Request
Out-DebugString -verbosity 9 -str “group-Enforce-Admin-Only postModify >>> GroupName = $($groupname)”
Remove-QADGroupMember -Member $member -Proxy -Identity $groupName -Control @{OperationReason=”Group – Enforce Admin Users Only_v1.1″}
} # end check if the user is not an admin- user
} # end processing each member added
} # end if members were added – ADS_PROPERTY_APPEND = 3
} # end if member found
} # end for iterate group members updated
} # end check that the group membership was updated
} # end check that request object was a group object
}

I’ve included my debug function for you here too – this writes to the event log – these go at the top of the script file

function onInit($Context)
{
$par01 = $context.AddParameter(“debugging”)
$par01.MultiValued = $false
$par01.PossibleValues = “0”, “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”
$par01.DefaultValue = “1”
$par01.Description = “Debugging EventLog Level where: 0 is no debugging; 9 is the most verbose; 1 is the least verbose”
$par01.Required = $false
#
#
}

function Out-DebugString([int]$verbosity, [string]$str )
{
# outputs debug info to the EDM event log
if ( [string]$PolicyEntry.Parameter(“debugging”) -ne ‘0’ )
{
$strDebuggingSwitch = [string]$PolicyEntry.Parameter(“debugging”)
if ( $verbosity -le [int]$strDebuggingSwitch )
{
$EventLog.ReportEvent(2,$str)
}
}

function Get-IsAttributeModified ([string]$AttributeName, $Request)
{
$objEntry = $Request.GetPropertyItem($AttributeName, $Constants.ADSTYPE_CASE_IGNORE_STRING)
if ($objEntry -eq $null) { return $false }
if ($objEntry.ControlCode -eq 0) { return $false }
return $true
} #– Get-IsAttributeModified

Copying an ARS scheduled task

Ok so I have to admit right up front I failed – I can’t create an ARS scheduled task but I can copy the parameters and schedule from one task to another which was why I was trying to do this in the first place.  Back in June 2014 I’d tried to copy a task and posted on the Quest ( now Dell software ) support site a question http://en.community.dell.com/techcenter/iam/f/4817/t/19589175 but this got ZERO responses :-(.

Anyway creating a task is relatively simple, what I wanted really was a way to copy the parameter list and their values.  This is reasonably simple:

Grab the task you want to clone:

$TaskObj = Get-QADObject `
  -Identity $Global:taskDN `
-Connection $ARSConnection `
-IncludedProperties edsaParameters,edsaXMLSchedule,edsaModule

the edsaModule is the script that the scheduled task runs the other two attributes store the parameters and the schedule should you want to copy those too.

Once you have the existing task and you have created the new task just issue this command and the values are copied over for you:

Set-QADObject `
-Identity $NewTaskObj.DN `
-ObjectAttributes @{edsaParameters=$TaskObj.edsaParameters}