Kaseya Community

Agent procedure for Windows 10 pre-upgrade compatibility scan

  • Hello,

    I'm extremely new to Kaseya and this is my first time venturing down the Agent Procedures path. I probably should've picked an easier first task, but this is our need right now.

    I'm trying to create an agent procedure that will run a Windows 10 prescan based on this TechNet article


    I have the setup.exe on a remote drive that is accessible to all users, and I've tested this command from a command prompt and it works as it should

    > start /wait \\<remote server>\prog\PCSETU~1\ISO\WINDOW~1\setup.exe /Auto Upgrade /Quiet /NoReboot /DynamicUpdate Enable /Compat ScanOnly

    I also added this line to get the ErrorLevel results added to a text file, although I could never get the carriage return working at the end.

    > echo %errorlevel% > c:\Win10.txt

    But I'd like to harness the power of Kaseya procedures to run the compatibility scan and then add the %ErrorLevel% results to the system info, or something inside of Kaseya so that I can run reports and filter by machines with certain %ErrorLevel% codes.

    I set this procedure up in Kaseya and it works on my machine but it fails on regular users with Failed THEN in step 1 (Line 1) 

    > executeFile("\\crnvault\prog\PCSETU~1\ISO\WINDOW~1\setup.exe", "/Auto Upgrade /Quiet /NoReboot /DynamicUpdate Enable /Compat ScanOnly", "Execute as User and Wait", "Windows 10 / Windows 8.1 / Windows 8 / Windows 7 / 2012 / 2008 / Vista / 2003 / XP / 2000 / NT4", "Halt on Fail")

    I tried changing it to Execute as system and wait, but it still failed.

    I'm assuming it's a security issue, but I'm still testing.

    At that point, I'm stuck. Even if I can get the procedure to run, I'm at a loss when it comes to saving the results.

    I considered using executeShellCommandtToVariable, but then I have no idea how to take that variable and write it to system info.

    Testing updateSystemInfo just inserts whatever I type in the string value.

    Am I even heading in the right direction on this?

  • You are definitely heading the right direction. You might have better luck copying that exe to a local folder first. I'm pretty sure the System account doesn't have network access, so execute as system won't work.

    *all of this is off the top of my head, so may not be 100% accurate, but should point you in the right direction*

    So first, I would get the temp path: GetVariable("Agent Working Directory", temp)

    Then copy the file: CopyFile("\\crnvault\prog\PCSETU~1\ISO\WINDOW~1\setup.exe", "#temp#\setup.exe")

    Then call your execute line: ExecuteFile("#temp#\setup.exe", "all of your args....")

    Then call your echo: ExecuteShellCommand("echo %errorlevel% > #temp#\Win10.txt")

    Get the results: GetVariable("File Contents", "#temp#\Win10.txt", "output")

    The last part is up to you. I see you have 3 options, a custom field, the procedure log, or an e-mail. They all have advantages and disadvantages.

    You could use an If statement to only e-mail you ones that are or are not compatible. That would be the easiest. Just remember to use #output# any time you want to use the contents of Win10.txt.

    If it were me, I would probably write it to the procedure log and then use a custom SSRS report to query the database directly, searching for that field. WriteProcedureLog("Win10 Check: #output#")

    A custom field works well for this type of thing, but too many custom fields can get messy so I would use them a little sparingly.

    Final note, don't forget to clean house:



  • When you select executeShellCommandToVariable, at the top of the pane where you can input or modify results you should see verbiage that says "Attempts to return results of a shell command to a global variable '#global:cmdresults#'". This is the variable that you use in subsequent steps to report the output of the command. However, this will report the results of STDERR and STDOUT, not the ERRORLEVEL returned by the executable.

    What I typically do is use writeProcedureLogEntry("#GLOBAL:cmdresults#", "All Operating Systems", "Halt on Fail") or updateSystemInfo("CustomFieldName", "#GLOBAL:cmdresults#", "Halt on Fail") to put the results into either the agent procedure log or a custom field I have. You can produce reports on either of these locations.

    If you need to capture the errorlevel, you may need to create a batch script, then in the script echo the errorlevel to STDOUT, which Kaseya could then use as stated above.

    Regarding "Execute as system" this would run the command as the NT AUTHORITY\SYSTEM account, which doesn't have network access, so access to the shared location would fail -- that is expected.

    Another approach to the problem would be to put your executable in Kaseya, then use the writeFile command to have the client download it locally before execution. Then you're execute command would change from \\server\share\...\setup.exe to C:\somefolder\...\setup.exe


  • ,

    A few general tips:

    1. Copy the setup.exe file to each endpoint, then execute from there.  You can use the copyFile step or executeShellCommand and use a standard cmd line string to copy the file.  I would generally recommend copying to the working directory.  You can delete the file from the working directory at the end of your script to clean up.  You're probably running into credential issues.  You might need to use the useCredential step to invoke account defined in Agent > Set Credential.  Even if all users have access to the share, authentication is still generally required.  System cannot usually authenticate across the network.

    2.  Determine the full failure error.  The AP page gives you a high-level reference of the failure, but not the full error.  Check Agent > Agent Logs > select the endpoint > choose the Agent Procedure log.  Find the entry related to your script.  The full detail will say something along the lines of "Failed THEN in Step 1 with <actual cause of the error inserted here...permissions, missing file, etc.>.

    3.  When using executeShellCommandToVariable, the info will be temporarily held.  You can output the collected information by inserting #global:cmdresults# in the place where you want the results of the execute to be placed.  For example, use the sendEmail step to email the results of the shell command.  In the email body section of the AP editor, type #global:cmdresults#.  An email will be sent to the address you provide with the results of the cmd.  Alternatively, use the writeProcedureLogEntry step to write the results to the Agent Procedure log of the endpoint.  There are several other options, but these two are good places to start.  This only works, of course, if the script gets far enough to successfully execute the cmd.

    4.  Start simple.  Build a script that does just ONE thing - copy your file from the share to the endpoint.  Once that is working, add another step.  Don't try to build the entire AP and then test - troubleshooting becomes an unnecessarily difficult task.  If you start with a simple structure and then add in complexity in small doses, it will make the overall process much easier.  This advice is both for those new to APs and those experienced.  It is really easy to make a minor error in an AP that prevents the whole thing from working, even for experts.  

    5.  updateSystemInfo inserts whatever you define into a Custom Field.  If you want to take the output of the executeShellCommandToVariable into a Custom Field, enter #global:cmdresults# into the "String value..." field.  If you want to enter another value, enter the value or the called variable into this field.  (Define a variable by name; call that variable by surrounding the case-sensitive variable name with hashtags.)

    Give the above a shot - starting simply.  If you get stuck, feel free to post your full procedure here.  The community will help as it can, and seeing what you've put together can help folks identify where you might be running into specific issues.

    Good luck!

  • SadThank you all for the replies. I have a little better understanding of the process now, but I'm still not having any luck with even a basic file copy.

    I did setup credentials that have access to these files and I've applied them to all of the agents in our desktop PC machine group. They've all tested successful.

    This is my script for copying the file from the remote share to the local machine

    Note: I can't figure out how to copy and paste the code out of Kaseya either. This program is beating me at every turn.

    When I had short file path names, it would fail. So I changed it to long names and it says it's completed and the file was copied, but I cannot find it on the one machine I've been testing.

    Thought it might be hidden, but it's still not there.

    I'm also logged into that machine as the same user in the credentials.

    For giggles I went ahead and tried to execute the local setup, since it says it copied.

  • What I do is put my files on the Kaseya server like this:

    Then use the writeFile procedure like this:

    This writes the file from the VSA to the local machine (using a LAN Cache, if you have one set up) at the location specified. It requires no permissions or agent credentials.


    Inserted images, as they didn't save properly the first time.
    [edited by: nate-pgn at 11:39 AM (GMT -7) on Jun 23, 2016]
  • ,

    I'd start with a simple copyFile (or copyFileUseCredentials) step and then manually check whether the file copied.  If it did, move on to add additional steps.  If it does not, you know the issue must be with the copy and can troubleshoot the cause.  I also for testing purposes only will allow "everyone" read/write and full access to the share to make sure rights to the folder aren't the issue.  Once the copy works, limit the share to just the intended accounts.

    Your script/AP log:  What it's saying is that the script step to send some instruction via cmd line (copyfile) successfully executed and then the script moved on to the next step.  That next step is just instruction to write an entry to the log - but there's nothing actually checking that the file was copied.  It isn't that the script is failing - it's doing exactly what you asked of it - but there is just a bit of logic that needs to be worked out.

    As far as the step to copy, spaces in file paths are generally not friendly.  Additionally, some systems don't like to write to C, regardless of admin level.  I recommend you try putting the setup.exe file in a 'friendlier' file path on your share.  For simplicity, try the root of your share (you can add child folders to the path once the basic function of the script is working).  Drop the file into the defined working directory on the endpoint.   Here's an example that copies a simple text file from a share to a hard-coded working directory:

    In the above script, I used the copyFileUseCredentials step just because it simplifies what I have to create.  You could alternatively use the useCredential step followed by the copyFile step and end up with the same result - just in more steps.  The file exists on the root of my shared folder and is copied to the working directory of the selected endpoint.  

    I then added the testFile step to check for the existence of the file and write to the AP log based on whether the file does or does not exist in the expected location.  This is more reliable than just writing a writeProcedureLogEntry after the copy step since I'm actually verifying the file exists before writing the AP log entry.  My personal preference is to put all of my AP entries in caps so i can very easily identify my notation steps from the system notation steps when i'm scanning through the log.  Not required, of course - I just find it easier (though I will sometimes convert them to standard sentence case once I'm done testing).  

    The file i'm copying is very small.  For larger files, you might consider adding a pause or a recursive check to allow for copy time before you write the AP log entries. (Start with a simple pause - add complexity once it's working as expected.)


    's advice is also a very valid way of doing what you're trying to do.  writeFile is like copyFile but smarter.  It doesn't need special access rights to the share becuase writeFile is taking a file directly from either the KServer or the defined LANCache, both of which the Kaseya system knows and trusts - it's Kaseya propriatery.  copyFile is a simple cmd line command that traverses your network using standard network protocols, so authentication is necessary because your network infrastructure doesn't inherently 'trust' the script instructions.  There are some considerations to using writeFile, especially if you are NOT using LanCache.  For example, writeFile from KServer puts the burden on the KServer to store and deliver the requested file, and that request will not take advantage of increased speeds of local LAN networking (unless the KServer happens to be on the same LAN as the endpoints - not common).  If you're using the SaaS solution, there may be some additional considerations in using writeFile.  These can be avoided by using a LANCache, which is really just a file share that Kaseya creates and manages the credentials on your behalf.

    Let us know how it goes and whether you run into any other roadblocks.  You might also consider looking into some of the training options available for VSA (as well as other Kaseya products).  We do offer both free and paid training, as well as paid consulting services, depending on your needs.  Contact your Customer Success Manager for details regarding our paid programs or visit http://university.kaseya.com to create an account to free training offerings.  A general info sheet is available here:  http://www.kaseya.com/sites/kaseya.com/files/downloads/Kaseya_Services_Brief_K_University_2-18-16A.pdf

    Give another shot with the info above and see if you can get the basic functions working.  The more simply you start (and test), the easier the overall build will be.  It does get easier as you work with it :)   Good luck!

    [edited by: Brande Schweitzer at 10:57 PM (GMT -7) on Jun 22, 2016]
  • Success! Well, at least on the file copy procedure.

    I created a new folder on the root of the share and opened up access. This worked.

    On to the next steps.

    Thanks again!

    Edit: I'm actually in the middle of the introduction training for Kaseya. But so far it hasn't covered any details on Agent Procedure. And this project has gotten pushed up the priority chain so we can take advantage of the free upgrades before they expire. But I'm going to look into more detailed training.

    Added notes about Kaseya University.
    [edited by: sboehm at 1:33 PM (GMT -7) on Jun 23, 2016]
  • nate-pgn

    What I do is put my files on the Kaseya server like this:

    Then use the writeFile procedure like this:

    This writes the file from the VSA to the local machine (using a LAN Cache, if you have one set up) at the location specified. It requires no permissions or agent credentials.


    Nate, I can't see your examples for some reason. But now you've got me interested in this whole LAN Cache and adding the file to Kaseya. I'm going to research that too.

  • It looks like it didn't like the way I copied and pasted my images the first time. I have tried updating my post in a different way that hopefully allows the images to come through.

    Regarding the writeFile procdure, there are a couple of nice automagic things that it does for you without any work on your part (Brande, correct me if I'm wrong here):

    1. If you have a LAN cache set up, it automatically uses that LAN cache with no additional configuration on your part. Note that LAN caches are basically a file share with Kaseya-managed credentials for access.
    2. If you are not using a LAN cache, it pulls directly from the kserver.
    3. If it detects that the file was already downloaded and hasn't been changed (based on checksum) it doesn't re-download the file.

    Hope this helps.


  • ,

    No correction needed.  Dead-on correct. :)