Welcome to the Liquidware Community Site.
Current and Future Clients/Partners are Welcome.

FlexApp: Working with Applications that Utilize %ProgramData%

lwl_gpeck ✭✭✭
edited October 2019 in FlexApp General Questions


With just a bit of computer slight of hand, you can package applications with Liquidware FlexApp Packager that write to files in %ProgramData%. First it is true, FlexApp Packing Console captures the %ProgramData% folder except for a few sub folders; However, when the folder is captured it is added to the package and essentially becomes read-only and changes are not saved. Immediately, ProfileUnity Portability might come to mind capturing user changes and lay them back down, and that might work with some inconsistency. The inconsistency comes because of timing. If Portability is restored prior to the package attaching, then the user’s changes will not be saved. Following the process below, you can ensure the users have their data. 

Real Life Scenario

Liquidware recently addressed this situation while packaging a virtual panic button. The software seems to be written for a static persistent environment where a user logs into the same machine every day. However, that didn’t fit into the non-persistent refresh of log off environment our customer was going toward. The application writes configuration and licensing information to a folder under %ProgramData%. 

Initial Application Testing

We first installed the application and identified the application behavior. Detecting application behavior can be assisted with the use of Process Explorer. In the testing, there were several files being modified in the %ProgramData%\Software\XYZ folder.  “Software” being replaced with the software company name that created the virtual panic button, and “XYZ” replaced with the software name.  


After identifying there is more than one file that is written to in %ProgramData% and that the folder needed to be unique per user, we decided to utilize a symbolic link on the folder to let the application work as intended, but put data where we wanted it, in the user’s profile. The application would be package, the folder in %ProgramData% moved to a staging area, and a post-activation script that would copy the folder and create the symlink.  We would then capture this data with a ProfileUnity Portability configuration. 

Packaging the Application

Liquidware packaged the application as normal within its own package (VHD stored on the network). After the application was installed, but before the package was finished, the following steps were taken:

  1. Create a folder outside of %ProgramData% that we don’t mind the users seeing. In case C:\MISC\Software was created.
  2. The Software folder was MOVED from %ProgramData% to C:\MISC\Software resulting in a folder structure like C:\MISC\Software\XYZ

The package was then finished following standard processes. 

Create the Script

On the FlexApp Packing Console, a batch script called ProgramData-SymLink.bat was created at C:\Temp.  The contents of the script were similar to the following.

if not exist "%USERPROFILE%\ProUSymLink-XYZ\" (mkdir "%USERPROFILE%\ProUSymLink-XYZ")

xcopy "c:\Misc\Software" "%USERPROFILE%\ProUSymLink-XYZ" /E /H /D

REM Create the folder link in ProgramData

REM Using a folder symlink rather than file symlinks since there are multiple files

REM needing updated.

REM Folders are also more consistent when trying to redirect.

mklink /d "c:\ProgramData\Software\XYZ" "%USERPROFILE%\ProUSymLink-XYZ\XYZ"

Note: For this article, most comments of the script were removed. 

Adding the Script to the Package

  1. Activate the package by clicking the play button on the application package
  2. Click the Editing Drop Down next to the activated package
  3. Click the Add Script button
  4. In the Package Scripts window, specify the following settings:
    1. Package Script App: Select “appdir-1”
    2. Package Script Execution Time: Select Post Activation 
    3. Package Script Path: Browse to the location of the script to be run (C:\temp), select it (ProgramData_SymLink.bat), and click OK.
  5. Confirm the script settings, then click OK to the script part of the package and deactivate the package. Scripts can be edited in the future on this window with the edit button.

Package Testing

The software package can now be tested. When attached, the package runs the script, copying the folder from the staging area to the user’s profile. This copy process only copies newer files, to retain user configuration as well as giving administrators the ability to update these files when a new package is created. A symbolic link for the %ProgramData%\Software\XZY folder is created pointing to %userProfile%\ProUSymLink-XYZ\XYZ. This symlink allows the application to think it is writing to %ProgramData%, but the changes are being saved to %UserProfile%. Multiple attachments should be tested. 


  • Any Chance this works for packaging Tableau Desktop and Prep? I have found they install FlexNet licensing service under C:\Program Files\Common Files\Macrovision Shared\FlexNet Publisher. And am having trouble post playback when a user is not an administrator of the desktop.

  • @NoBrentsAllowed I believe that one of our SEs is looking into this and is in direct email with you. He respond when he has an answer to your question.

  • LukaszM
    edited March 2020


    Is a Problem app because it sets custom security on its licensing service here are the steps to address post playback issue for non admin users:

    If a service is installed with an installer during the packaging phase and the user needs permissions on that service post package deploy you need to install the software outside of the packaging phase on the desktop then run an sc sdshow “service-name”. Then save the output as output1. Run the same command on a different desktop that has the package overlay-ed and if the SDDL output is different create a post license activation batch script that runs the following

    1) Temporary install the software outside of FPC packaging software

    2) Run sc sdshow "servicename" save the output as you will need it later. (output1)

    3) Check the sc sdshow "servicename" on the service that was DIA playback it most likely will be different (that is the problem)

    4) To address create DIA post license activation batch script that runs the fallowing:

    @echo off

    Sc sdset “servicename” output1

    This would reset the service post playback to original settings set by the application.

    This was created with help from Eirc Rosen! Thank you Eric!