Kaseya Community

Default Values for Variables in Agent Procedures

  • Just thought I would share this scripting technique I figured out today, its to do with assigning default values to procedure variables that might be missing and could cause your agent procedure to fail.

    Scenario 1: You have a procedure that uses Managed variables and the Agent Procedure sometimes fails because it gets executed on agents in new machine group where nobody bothered to fill out the Managed variables.

    Scenario 2: You have a "Universal" sub agent procedure that gets executed by other procedures and it is expecting a variable, you create a new procedure that uses this sub procedure but you forget about all the variable dependancies.

    In both scenarios it would be nice to have predefined default values for some variables, so how would you go about doing this?

    Most of us would try and use the "Check Variable"  If statement with a "Exist" Condition Option to check if the variable has a value, however because the variable has no value it causes the procedure to fail. I did this too and I think its rather silly to give us the "Exist" Condition Option if it does not work.

    So I tried several methods and came up with this;

    We have a Managed variable <CompanyName>, for this example it has no value assigned to it.

    1. Create a new variable using the "Create Variable" with the "Constant Value" step option, we will call it #global:Var1# and assign a value of "FALSE" to it, note that it is a global variable which is very important.
    2. Next we create/duplicate the same variable again and assign it a value of  <CompanyName> and (very important>) tick the "Continue on fail" check box.
    3. We then create a "Check Variable" IF statement with: "IF #global:Var1# Contains "FALSE"
    4. Under the THEN part of the new "Check Variable" IF statement we create/duplicate the #global:Var1# again and assign it the preferred default value of "Unknown"

    So how this work is;

    The first time you create the #global:Var1# variable with the value of "FALSE" it declares it and gives it a possible expected value that we can check for in our IF statement. The second time we assign the Managed Variable to it with the "Continue on fail" option, so if the Managed variable <CompanyName> has no value it won't stop the procedure if it fails and most importantly it won't overwrite the "FALSE" value you assigned to the first instance of the #global:Var1# due to the "Continue on fail" option. If the IF statement is triggered it then assigns the preferred default value of "Unknown" to the variable #global:Var1# in its 3rd instance.

    If the managed variable <CompanyName> does have a value then it will overwrite the #global:Var1# variable in the second instance and won't trigger the IF statement that will assign the default value of "Unknown" to the variable #global:Var1# in its 3rd instance.

    The same method works with procedure variables passed from one Agent Procedure to a sub agent procedure.

    Hope somebody can use it... Big Smile

     



    [edited by: HardKnoX at 7:56 PM (GMT -7) on 8-4-2011] typo
  • Great to mention this in the tips and tricks section of this forum, i already use this construction for quite a while, but then for custom fields.

    If a custom field is not populated yet, due to a new agent install etc, scripts could fail because the expected value is not there yet, so besides the two given scenarios it is alo very handy with custom fields.

  • @Bsis That's very true, I have only recently found the need to use Custom Fields myself and can see how you would use this method to make your procedures more robust.

    Thanks confirming the usefulness of this method and adding to it Smile

  • Just some more on using this method with Custom Fields.

    I found that if the Custom Field exists but has no value assigned to it then it's actually not empty (aka it has a NULL value) and then the above mentioned method will not work. I suspect if the Custom Field did not exist that the previously mentioned technique would work.

    To get around this problem what you do instead of pre-assigning a known value (e.g. #global:Var1# = FALSE) you use the IF statement of "IF #global:Var1# is Greater Than A*" which will filter the null valued variable and allow you to assign a default value. Note the "A*" filter value will only work if the variable starts with alphabetic character, if you know that the variable will start with a numeric character then you want to use "1*" filter value  instead.

    So an example of this is I made a MachineRole custom field and I made a procedure that I can update the custom field without overwriting any existing values. My MachineRole field was "blank" and when I used this Procedure it added the Role to the Field separating it with a comma instead of overwriting it. So what happened is I pre-assigned the #global:MachineRole# procedure variable with "FALSE" and then assigned the MachineRole custom field variable to it which is blank and it overwrote the pre-set value of FALSE so when I did my IF Check Variable #global:MachineRole# contains "FALSE" it did not contain FALSE anymore as it had a "NULL" value.

    Another example of this is NULL value is one of my customers wants to use Custom Fields for include Asset information (Vendor Name, Purchase Date, Purchase Value, etc...) so I created a procedure that the could use where it prompts them to enter the values. Now the problem is if they leave one of the fields empty because the existing value is  in the database is correct it will also be over written with NULL values as default value of the Get Prompt Variable line is also NULL

    I have learned heaps "playing" with custom fields and again I hope it makes sense if not let me know and I will try to explain it better. Confused



    [edited by: HardKnoX at 1:23 AM (GMT -7) on 9-22-2011] blah
  • Most of us would try and use the "Check Variable"  If statement with a "Exist" Condition Option to check if the variable has a value, however because the variable has no value it causes the procedure to fail. I did this too and I think its rather silly to give us the "Exist" Condition Option if it does not work.

    err um The Exist condition does work. 

     

    However like you i have had it were it stops working and that's because i copied the IF statement. It looks perfect but doesn't work i had to create a new if then the  "Exist"  works just fine.  



    [edited by: Michael Dixon at 5:20 PM (GMT -8) on 2-22-2012] l
  • So since I wrote this post some changes have happened making the method described null and void. I have learned a lot since then too and now with the SQLCMD being replaced with sqlRead and sqlWrite commands I came up with an updated solution for reading managed Variables;

    Add the following line to your Agent Procedure SQL read xml file or create one if needed;

    <queryDef label="GetManagedVarValue (MANAGEDVAR,DEFAULTVAL)" sql="SELECT ISNULL((SELECT varValue FROM scriptVar WHERE itemGuid=(SELECT machGroupGuid FROM vdb_Machines_General WHERE agentGuid='+++GETVARGUID:') AND varName LIKE '#MANAGEDVAR#.%'), '#DEFAULTVAL#')"/>

    To use in you agent procedure create to constant variables and name them MANAGEDVAR, DEFAULTVAL before you use the sqlRead line.

    The MANAGEDVAR variable value will contain the name of your managed variable note that it will only work with public ones if you intend to use private managed variables you will need to update the SQL query a bit.

    The DEFAULTVAL variable value will be a value like "FALSE" or if the managed variable could potentially contain the text "FALSE" the change it to something like "xFALSEX"

    Below is an example agent procedure of how to use the sqlRead command;


    I want to do something similar for Custom Fields at some point and I will add it to this post once I have figured out the query.

  • Old subject... but this thread gave me an idea: I prompt for a variable in a lot of my procedures... and sometimes I need to control that what's been entered is of a specific type: numerical, char, etc.

    Having read this thread, here is how I check the value provided is numerical...

    The variable #SO_number# is the one I want to check and make sure it's a numerical value passed.

    The GetVariable( " Expression Value" ...) only works if the expression return a numerical result...

  • You could run a 1 line powershell  command to accomplish this as well

    PS C:\> #SO_number# -is [int]

    This will tell you true or false..   If you use the #global:psresult# with this - you could then check if that variable = true..