Extended controls

Hi 

i discovered Extended Controls a while ago in Active Role Web Gui and i thought that might be a good way to control code but i guess i havent really thought about using it with onGetEffectivePolicy.

  1. For Example i have simple Form with onGetEffectivePolicy (Key=Form / Value=Enable_Phone)
  2. some code that is generating dropdowns by searching some azure groups and adding result to User drop down
  3. User can choose group and the group is used in some further code

main goal is only to trigger the code when the form is started. In this Use Case we are searching Azure License Groups and we only want to display the manual License groups. 

After Extended Controles are defined this is the code to read the Form from request and use it

function onGetEffectivePolicy($Request)
	{
$Form = $Request.GetInControl("Form")
$FormName = "Enable_Phone"
if ($Form -eq $FormName)
	{
	}
	}

Problem now is onGetEffectivePolicy of cource means every operation in AR, so if you change somethings else in Active Directory for a user onGetEffectivePolicy tries to read the request which provides only NULL Values

Exception calling "GetInControl" with "1" argument(s): "Value cannot be null."

Its only an error in the Event Viewer and maybe you might be able to do something else for the Use Case we have but does anyone have good example for what you are using Extende Controles or what it might be for because it seems like using it with onGetEffectivePolicy might be a misconception.

  • A simple Try-Catch might be able to help you out here.

       try
       {
          # Obtain the form name from the Request object
          $FormName = $Request.GetInControl("FormName")
       }
       catch
       {
          # An error will occur if there is no GetInControl value, which means a modification occurred in another interface or form, exit this function
          return
       }

  • Actually i have an try/catch but i'm not using it yet for this scenario. Try/Catch was implemented for syntax errors initial so i can generat a Custom Event ID.

    I'm actually not sure if "Exception calling "GetInControl" with "1" argument(s): "Value cannot be null."" goes into the catch because AR is generating Event ID 2001 Events.

    If my catch is working it should generate an Event ID 1000 in this case but maybe i need some more testing and understanding

    this is the example code

    try
    {
    	function onGetEffectivePolicy($Request)
    	{
    		if ($Request.GetInControl("Form"))
    		{
    			######### Controlled Attributes #########
    			$AttAzureLicenseGroups = "edsvaUserAzureLicenseGroups"
    			
    			######### Request auslesen #########
    			$Form = $Request.GetInControl("Form")
    			
    			######### VAR #########
                $FormNameAzure = "Add_Azure_License"
    		    $CredsName = "****"
    		
    			
    			######### Funktionen #########
    			
    			if ($Form -eq $FormNameAzure)
    			{
    				Import-Module "E:\Scripts\PoweshellModule\CredentialManager\2.0\CredentialManager.psd1"
    				$Creds = Get-StoredCredential -Target $CredsName
    				
    				Import-Module azuread
    				Connect-AzureAD -Credential $Creds
    				
    				$Group = get-azureadgroup -SearchString "License" -All $true
    				$Group = $Group | Where-Object { $_.DisplayName.EndsWith('(Assigned) | LIC') }
    				$AssignedGroup = $Group.DisplayName
    				
    				Disconnect-AzureAD
    				
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $Constants.EDS_EPI_UI_RESTRICTED, "TRUE")
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $Constants.EDS_EFFECTIVE_POLICY_DEFAULT_VALUES, $DefaultGroup)
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $Constants.EDS_EPI_UI_GENERATED_VALUE, $DefaultGroup)
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $Constants.EDS_EPI_UI_POSSIBLE_VALUES, [string[]]$AssignedGroup)
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $Constants.EDS_EPI_UI_VALUE_REQURIED, "TRUE")
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $constants.EDS_EPI_UI_POLICY_RULE, $DefaultGroup)
    				$Request.SetEffectivePolicyInfo($AttAzureLicenseGroups, $constants.EDS_EPI_UI_AUTO_GENERATED, $true)
    			}
    		}
    	}
    	
    	function onPostModify($Request)
    	{
    		######### Controlled Attributes #########
    		$attuserPrincipalName = "userPrincipalName"
    		$attCreateSharedMailbox = "edsva-MsExch-CreateSharedMailbox"
    		$attCreateUserMailbox = "edsaCreateMsExchMailbox"
    		$AttAzureLicenseGroups = "edsvaUserAzureLicenseGroups"
    		
    		######### Request auslesen #########
    		$UPN = $DirObj.Get($attuserPrincipalName)
    		$AzureLicenseGroups = $Request.Get($AttAzureLicenseGroups)
    		$Form = $Request.GetInControl("Form")
    		
    		######### VAR #########
    		$FormNameAzure = "Add_Azure_License"
    		$CredsName = "****"
    		
    		######### Funktionen #########
    		if ($Form -eq $FormNameAzure)
    		{
    			Import-Module "E:\Scripts\PoweshellModule\CredentialManager\2.0\CredentialManager.psd1"
    			$Creds = Get-StoredCredential -Target $CredsName
    			
    			Import-Module azuread
    			Connect-AzureAD -Credential $Creds
    			
    			$Group = Get-AzureADGroup -SearchString $AzureLicenseGroups
    			$Members = $Group | Get-AzureADGroupMember -All $true
    			$User = Get-AzureADUser -ObjectId $UPN
    			$IsUserInGroup = $Members.ObjectID -contains $User.ObjectID
    			
    			if (-NOT $IsUserInGroup)
    			{
    				Add-AzureADGroupMember -ObjectId $Group.ObjectId -RefObjectId $User.ObjectId
    				
    			}
    			Disconnect-AzureAD
    		}
    	}
    }
    catch
    {
    	# Erstellung von Error Events
    	$InitiatorSam = ""
    	$InitiatorDistinguishedName = ""
    	$Request.WhoAmi([ref]$InitiatorSam, [ref]$InitiatorDistinguishedName)
    	
    	$Event = @{
    		Source    = 'CatchErrorAddAzureLicense'
    		EventID   = 116
    		EntryType = 'Error'
    		Message   = $_[0]
    		InitiatorSam = $InitiatorSam
    		Category  = 1000
    	}
    	
    	Log $Event
    }

  •  is very much on the right track with his suggestion.  I will elaborate on the "why".

    When it comes to using custom Controls, you HAVE to use a try / catch for reading back the value of the control because if there is no value in the Control, then your code will abort (which is what you seem to be seeing).  Yes, it's weird but that's just how the platform works.   So unless you are providing this form control ALL THE TIME, you need to implement a try / catch for the initial read back of its value in your code.  And you should anyway just in case something weird happens and no value gets sent.

  • Do you have maybe a simple Example how to catch propely $Request.GetInControl("XXX").

    Everything i tried so far is still generating Event ID 2000/2001 

  • You should be able to substitute your own code into this simple example.

    function onGetEffectivePolicy($Request)
    {
       # Exit function if request is not for a user
       if ($Request.Class -ne 'user') {return}
    
       # Check if the web interface was used to create a contractor account
       try
       {
          # Try to obtain the form name from the Request object
          $FormName = $Request.GetInControl("FormName")
       }
       catch
       {
          # An error will occur if there is no GetInControl value, which means a modification occurred in another web interface, MMC or Sync Service
          # Exit function
          return
       }
    
       if ($FormName -eq "ContractorRequestForm")
       {
          # Set the Contractor Vitrual Attribute flag to true
          $Request.SetEffectivePolicyInfo("edsva-UHS-ContractorRequest", $Constants.EDS_EPI_UI_GENERATED_VALUE, "True")
       }
    }

  • thx for your feedback, it helped me to understand the problem better.

    In my example i used $Request.GetInControl in onGetEffectivePolicy and onPostModify. 

    One error was caused whenever any attribute on the user was changed. This triggered the onPostModify and logically it came to a NULL in $Request.GetInControl because of the missing Form. Here I just don't understand from a powershell point of view why I can't put onGetEffectivePolicy and onPostModify both in a try/catch and the catch works in all situations. as far as i understand correctly you should use try/catch only once in powershell script.

    I think I don't get any more errors when I build it this way, I'm just not quite happy that the try/catch doesn't go over the whole script. Smile

    $global:Form = $null
    
    function onGetEffectivePolicy($Request)
    {
    	# Exit function if request is not for a user
    	if ($Request.Class -ne 'user') { return }
    	
    	######### Controlled Attributes #########
    	$AttAzureLicenseGroups = "edsvaUserAzureLicenseGroups"
    	
    	try
    	{
    		######### Request  #########
    		$global:Form = $Request.GetInControl("Form")
    	}
    	catch
    	{
    		return
    	}
    	# Continue function if request GetInControl not NULL and Forms Name
    	if ($global:Form -eq $FormNameAzure)
    	{
    	    Do something
    	}
    }
    
    function onPostModify($Request)
    {
    	# Exit function if request is not for a user
    	if ($Request.Class -ne 'user') { return }
    	
    	# Exit function if request GetInControl is NULL
    	if (!$global:Form) { return }
    	
    	# Continue function if request GetInControl is NULL
    	if ($global:Form -eq $FormNameAzure)
    	{
    	  Do something
    	}

  • I think where you are going off track is concerning usage of try/catch.  You can use try/catch as much as you like in a Powershell script.  I use it liberally for gracefully handling potential error conditions throughout my code.