SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Putting files to path with environment variables

I am currently testing Advanced Installer and want to use an XML search in order to look for a certain path. In this path, I want to put a file.
In the XML file there is a part that looks like this:

Code: Select all

<setting name="DataLocation" serializeAs="String">
        <value>%public%\Documents\COMPANY\PRODUCT\Data</value>
</setting>
When I test the search on my machine, everything works fine and the path is being displayed.
When I run the setup on a VM, I get the following error message:


What can I do to put files to this folder?

I even tried changing the value to "C:\temp" in the XML to see if the putting works with another path. With C:\Temp, I don't receive an error message any more. However, the file is not coppied to C:\temp, but is being put to the default location of my variable (I simply put here "C:\").

So in total, I have two problems: Files not being put and the installer not being able to handle "%public%".
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello and welcome to Advanced Installer forums,

In what regards the error your receive, could you please re-attach the screenshot as it seems you forgot to attach it?

Additionally, could you please add a screenshot of the xml search as well?

In what regards the installer not being able to handle the environment variable, could you please try to replace %public% with [%PUBLIC] and let me know if that helps? The above is the way environment variables should be written so the Windows Installer framework knows to handle them.

Hope this helps.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

I receive the error right after the launch of the setup: (noaccess.png)
In the logs, I found the following lines:

Code: Select all

MSI (c) (90:A8) [08:31:53:888]: Note: 1: 1314 2: %public%\Documents\Company\Product\Data 
MSI (c) (90:A8) [08:31:53:888]: Note: 1: 1606 2: %public%\Documents\Company\Product\Data 
Fehler 1606. Zugriff auf die Netzwerkadresse %public%\Documents\Company\ProductData war nicht möglich.
MSI (c) (90:A8) [08:33:07:937]: Produkt: Product-- Fehler 1606. Zugriff auf die Netzwerkadresse %public%\Documents\Company\Product\Data war nicht möglich.
This translates to: "Access to the network path was not possible".

To see my xml search configuration, please have a look at search.png.

After having altered the entry to "[%PUBLIC], the error has changed slightly: Access to the network path "C:\Users\Public\..." was not possible. It seems like the resolution of the environment variable is working now, however, the installer does not have access to the path. What can I do?
Attachments
search.PNG
search.PNG (30.17 KiB) Viewed 7542 times
noaccess.PNG
noaccess.PNG (26.94 KiB) Viewed 7542 times
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

Any help on this would be appreciated.
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello,

That most probably happens because during the "Paths Resolution" action group, the path is not a valid one.

In order for me to further investigate this, could you please forward me a copy of your .AIP file by e-mail at support at advancedinstaller dot com?
After having altered the entry to "[%PUBLIC], the error has changed slightly: Access to the network path "C:\Users\Public\..." was not possible. It seems like the resolution of the environment variable is working now
In what regards this, I have actually tested this just now and I was not able to achieve this. It seems that all the time [%PUBLIC] (not its resolved value) is written in the resulted property of the search.

Did you just replace the "%public%" from your .XML file with "[%PUBLIC]" and it worked?

Looking forward to hearing from you.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

Hi,

I will email the file after having finished my post.

Yes, i changed the value in my XML file from "%public%" to "[%PUBLIC]" as you suggested. Then the error was not "could not access %public%\Data\...", but it changed to "could not access C:\Users\public\Data...". So, in total, the variable "[%PUBLIC] now has been correctly resolved to "C:\Users\public".
Nevertheless, the installer was not able to access this path.

And overall, this does not explain why, even when changing the path in the XML file to "C:\Temp", the installer does not put a file there.

Maybe you can find out something using my .aip file

Best regards,
Simon
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello Simon,

After several hours of investigations, I have finally hit a dead end. This seems to be a Windows Installer limitation (as far as I could've seen).

Even though the messagebox spawned pretty much states that the [%PUBLIC] property has been expanded, in fact, it has not.

To be fully honest with you, this is really strange and I honestly can not explain (not even to myself) why this happens.

Fortunately, after some more investigations, I was able to find a workaround for this issue. To achieve what we need here, we will need a custom action that will do the job for us. Basically, the custom action will do the following:

- get the content of our XML file

- get the desired value and save it in a variable

- convert the string (our value) to an array and eliminate the first element from it (i.e. [%PUBLIC])

- convert the array back to a string ==> the resulted string will look something like this: Documents\...\...

- set a property to that value

We will schedule this custom action in the "Wizard Dialogs Stage", right before the "Searches" action group.

The script I've created for such a task is a PowerShell script and it looks like it follows:

Code: Select all

# Block for declaring the script parameters.
Param()

# Your code goes here.

[XML]$appConfigFile = Get-Content -Path "C:\Users\Catalin\Desktop\LOGINventory.config"
$var = $appConfigFile.configuration.userSettings.'Login.Ventory.Common.Properties.Settings'.setting | Where-Object {$_.name -eq "DataLocation"} | Select-Object value
$var = $var.value
$var = $var.Split("\") | Select-Object -Skip 1
$var = $var -join "\"
AI_SetMsiProperty MY_PROP_PS $var
In order to implement this in Advanced Installer, you can go to "Custom Actions" page --> add a "Run PowerShelll inline script" custom action. Copy paste the above content into the custom action. What to be kept in mind here is that you must change the path to your configuration file in the script.

After doing so, please create a new SetProperty custom action (add it from the predefined list of custom actions), as it follows:

Code: Select all

Property: YOUR_PROPERTY
Value: [%PUBLIC]\[MY_PROP_PS]
where "YOUR_PROPERTY" is the property that is assigned to your property based folder. It is recommended to use a public property here (all uppercase letters, e.g.: instead of DataDir ==> DATADIR)

This way, the error will go away and your files will correctly be installed in the desired location.

Hope this helps.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

Hi Catalin,

thank you for your detailed reply. Unfortunately, I was ill last week, so I couldn't test your solution. However, now I was able to test your approach and it is working as long as the specified file exists. The file will only be existent, when my program is already installed. For new installations, the xml file won't be available.
How can I handle this? When I now remove the file from the path specified, I get the following file not found exception and the setup ist not able to run.

I would like it to behave the following way:
1. Look for the file and parse the path
2. If the file is not available copy a certain file to a default path (e.g. C:\Temp)
3. If the path could be extracted, copy a certain file to the extracted path

Here comes my error, in case you need it:

Code: Select all

MSI (c) (C4:64) [13:55:21:889]: PROPERTY CHANGE: Adding CustomActionData property. Its value is 'Is64BitIsFallback32BitParamsScript# Block for declaring the script parameters.
Param()

# Your code goes here.

[XML]$appConfigFile = Get-Content -Path "C:\ProgramData\Login\LOGINventory\9.0\LOGINventory.config"
$var = $appConfigFile.configuration.userSettings.'Login.Ventory.Common.Properties.Settings'.setting | Where-Object {$_.name -eq "DataLocation"} | Select-Object value
$var = $var.value
$var = $var.Split("\") | Select-Object -Skip 1
$var = $var -join "\"
AI_SetMsiProperty MY_PROP_PS $var'.
Aktion beendet um 13:55:21: AI_DATA_SETTER_1. Rückgabewert 1.
MSI (c) (C4:64) [13:55:21:889]: Doing action: PowerShellScriptInline
Aktion 13:55:21: PowerShellScriptInline. 
Aktion gestartet um 13:55:21: PowerShellScriptInline.
MSI (c) (C4:A4) [13:55:21:967]: Invoking remote custom action. DLL: C:\Users\$sl\AppData\Local\Temp\MSI3B0C.tmp, Entrypoint: RunPowerShellScript
Dumping PowerShell invoke log ...
--> Found PowerShell path: C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
--> PowerShell Script Execution Result Code: 574
--> PowerShell Script Execution log: 
Get-Content : Der Pfad "C:\ProgramData\Login\LOGINventory\9.0\LOGINventory.config" kann nicht gefunden werden, da er 
nicht vorhanden ist.
In C:\Users\$sl\AppData\Local\Temp\pss3B60.ps1:6 Zeichen:23
+ ... onfigFile = Get-Content -Path "C:\ProgramData\Login\LOGINventory\9.0\ ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\ProgramData\...Nventory.config:String) , ItemNotFoundEx 
   ception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
 
ERROR: Es ist nicht m”glich, eine Methode fr einen Ausdruck aufzurufen, der den NULL hat.
MSI (c) (C4!BC) [13:55:30:296]: PROPERTY CHANGE: Adding POWERSHELL_EXECUTION_LOG property. Its value is 'Get-Content : Der Pfad "C:\ProgramData\Login\LOGINventory\9.0\LOGINventory.config" kann nicht gefunden werden, da er 
nicht vorhanden ist.
In C:\Users\$sl\AppData\Local\Temp\pss3B60.ps1:6 Zeichen:23
+ ... onfigFile = Get-Content -Path "C:\ProgramData\Login\LOGINventory\9.0\ ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\ProgramData\...Nventory.config:String) [Get-Content], ItemNotFoundEx 
   ception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
 
ERROR: Es ist nicht m”glich, eine Methode fr einen Ausdruck aufzurufen, der den NULL hat.'.
CustomAction PowerShellScriptInline returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Aktion beendet um 13:55:30: PowerShellScriptInline. Rückgabewert 3.
MSI (c) (C4:64) [13:55:30:296]: Doing action: FatalError
Aktion 13:55:30: FatalError. 
Aktion gestartet um 13:55:30: FatalError.
Aktion beendet um 13:55:40: FatalError. Rückgabewert 1.
MSI (c) (C4:64) [13:55:40:688]: Doing action: AI_SHOW_LOG
Aktion 13:55:40: AI_SHOW_LOG. 
Aktion gestartet um 13:55:40: AI_SHOW_LOG.
MSI (c) (C4:D4) [13:55:40:766]: Invoking remote custom action. DLL: C:\Users\$sl\AppData\Local\Temp\MSI847A.tmp, Entrypoint: LaunchLogFile
Aktion beendet um 13:55:42: AI_SHOW_LOG. Rückgabewert 1.
MSI (c) (C4:64) [13:55:42:766]: Doing action: FatalError
Best regards,

Simon
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello Simon,
Unfortunately, I was ill last week, so I couldn't test your solution.
No worries about this. I hope you feel better now.

I am really glad the solution worked for you.

Now let's address your issue. Indeed, if the file is not present, then the PowerShell script will fail (this is the expected behavior).
1. Look for the file and parse the path
In what regards the first part of the problem, could you please give me some more details as to how you would like to look for the file? Here, I would say that we should be pretty straightforward.

Since the setup installs your configuration file, I believe we should straight up test that location, instead of doing a recursive search (which will take a lot of time - i.e. search for your file in the entire C:\ directory).

Please let me know if you see anything wrong with this approach. If not, let's get started:

We can test if a file exist by using the "Test Path" cmdlet. Here is how we can achieve this:

Code: Select all

$path = "C:\Users\Catalin\Desktop\testFile.txt"

Test-Path -Path $path
If the file exists, the above should return $true, otherwise it should return $false. To verify such a condition, we can proceed as it follows:

Code: Select all

if ((Test-Path -Path $path) -eq $true){

#do-something

}
In what regards the parsing part, could you please give me some more details about it, as I am not quite sure how you would like to parse it.
2. If the file is not available copy a certain file to a default path (e.g. C:\Temp)
For this, please refer to what I've written above, as I believe that will help.

In what regards the copying of a file, there are two ways that I can think of:

1. you can use the "Copy-Item" cmdlet. This can look something similar to this:

Code: Select all

Copy-Path -Path "your_path_here" -Destination "your_destination_here"
2. you can use our predefined support Temporary Files. Temporary files are files that are copied on the machine at the beginning of an installation and deleted at the end of it.

Temporary files location is the %temp% folder, which resolves to:

%windowsvolume%\Users\<username_here>\AppData\Local\Temp

Here is how we can achieve what you need:

We will add the file you want to be copied as a temporary file in the "Files and Folders" page (using the "Add temporary file" button from the ribbon). After doing so, if you double click on it, you will notice that it has a "Condition" field. We can condition this based on the result of our custom action. Here is how your script may look like:

Code: Select all

if(your_condition -eq $true){

# we set an installer property that we will use for our condition

AI_SetMsiProperty YOUR_PROPERTY "YourPropertyValue"

}
The condition for your temporary file may look like this:

Code: Select all

YOUR_PROPERTY = "YourPropertyValue"
In this case, the custom action should take place before the files are copied in the temporary location (this happens during the "CostFinalize" standard action --> "Paths Resolution" action group)
3. If the path could be extracted, copy a certain file to the extracted path
Not quite sure I understand what you want to achieve here. Would be gread if you could give me some more details so I can better understand this.


Also, least but not last (because I forgot to mention this in my last thread) - we will start working on a method that will allow you to achieve your scenario much easier (without having to work it around using a custom action). I will update this thread as soon as that improvement will be added to Advanced Installer.

Hope this helps.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

Hi Catalin,

thank you for your detailed explanations. After some research, I managed to find a solution that works best for me:

Code: Select all

$path="C:\ProgramData\Product\name.config"
#Default value of $var
$defaultVar = "%public%\Documents\Product\Data"
$var=$defaultVar

if (Test-Path -Path $path){

[XML]$appConfigFile = Get-Content -Path $path
$dataLocation = $appConfigFile.configuration.userSettings.'Login.Ventory.Common.Properties.Settings'.setting | Where-Object {$_.name -eq "DataLocation"} | Select-Object value

if ($dataLocation.value){
    $var = $dataLocation.value
    }
}
$var=[System.Environment]::ExpandEnvironmentVariables($var)


if (!(Test-Path -Path $var)){
    $var=[System.Environment]::ExpandEnvironmentVariables($defaultVar)
}

AI_SetMsiProperty MY_PROP_PS $var
Best regards,

Simon
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

You are always welcome, Simon!

Always my pleasure to help.

I am really glad you found a solution that fits your needs.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello,

This improvement has been added in Advanced Installer 17.3, released on July 29th, 2020.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube
SimLoe
Posts: 66
Joined: Thu Mar 12, 2020 11:37 am

Re: Putting files to path with environment variables

Hi Catalin,

can you tell me a bit more about this new feature? Where can I select what? Do you have a link to the changed part of the documentation?

Best regards,

Simon
Catalin
Posts: 6608
Joined: Wed Jun 13, 2018 7:49 am

Re: Putting files to path with environment variables

Hello Simon,

For this particular case, we have created a new predefined custom action (Resolve Formatted Property). You can find more information about it in our "Custom Actions List" article.

Hope this helps.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube

Return to “Common Problems”