VBScript Custom Action 38 GetParentFolderName Will Not Resolve

Hi folks,

I dare say this can be done more simply and/or more elegantly and/or even better than what I have thrown together here, but we all start somewhere right?

This is my situation:

I have 3 different files, that need to be copied to 3 different folders. I'm using a transform on the Firefox ESR MSI, which will be installed via ConfigMgr. Previously when running other *.BAT or *.CMD files I've used '%~dp0' to resolve the path, but I can't use that with a CA 38! I know I don't have to, but I would like to try and use a MSI in my ConfigMgr Deployment Type rather than a BAT/CMD file. I started by trying to run 3 separate CA FileCopies, but ran into CA Target length limits. Then I thought to use my CA to call a CMD file which has the 3 FileCopy commands in it and so now, this is my CA Target:

dim filesys, DIR  :  Set filesys = CreateObject("Scripting.FileSystemObject")  :  DIR = filesys.GetParentFolderName("Wscript.ScriptFullName")  :  Set shell = CreateObject("WScript.Shell")  :  shell.Run DIR & "\filecopy.cmd"

And this is what my MSI log yells back at me:

MSI (s) (00:1C) [04:43:21:447]: Product: Mozilla Firefox 68.7.0esr x64 en-GB -- Error 1720. There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor.  Custom action CA_CustFileCopy script error -2147024894, :  Line 1, Column 193,  

Column 193 brings me to:

shell.Run DIR & "\filecopy.cmd"

In it's own *.VBS file, my CA Target above - without quotes around Wscript.ScriptFullName - works a treat and does what I want it to!

I've been running in cirlces for ages now and just don't know what else to try because, well, I just don't know enough.

Would someone mind either helping a noob out or pointing a noob towards some useful resources to read up or both, please?

Thanks in advance,
Dodgy Bob

0 Comments   [ + ] Show comments

Answers (2)

Posted by: anonymous_9363 1 year ago
Red Belt


The (let's call it) interpreter for MSI Custom Actions isn't Windows Scripting Host so any use of that object (as in "WScript[dot]something") will fail. If you were to include the script in a transform and external CAB and execute it using CScript, it would work. If you had included error-trapping and logging in the script, you'd have seen the appropriate error in the log. Also, because I'm paranoid, I have each statement separate and each is error-trapped. In scripting, always assume that NOTHING is going to work, even stuff like creating FileSystemObject. Now, adding reams of "If err.number <>0 Then..." statements is a nuisance so get hold of the excellent BugAssert code: it's used by quite a few scripts that Microsoft pushed out.

In any event, why are you using script to copy files? Why not simply include the required files in a transform and external CAB?

  • Well, I had tried adding the files to the transform, but whatever I was doing, it was obviously wrong because it wouldn't work!

    I didn't try the compressed CAB method - can't remember why now! - but leaving them as uncompressed files alongside the MSI, I just never got to work ... and that would be my preferred way to do it :)

    So moving from one thing to the next, in the hopes to get finished and get something working, was why I went this route. It was just the next thing I tried.

    Righto then, so let me see if I've got this right...

    GetParentFolderName("Wscript.ScriptFullName") will fail within a MSI CA because the part ("Wscript.ScriptFullName") is Windows Scripting Host and the MSI CA cannot read/access Windows Scripting Host - correct?

    If that is right, then whatever the MSI CA is reading/accessing in, what is that eqivalent for ("Wscript.ScriptFullName") in the GetParentFolderName part of my CA? - Dodgy Bob 1 year ago
Posted by: anonymous_9363 1 year ago
Red Belt
If that is right, then whatever the MSI CA is reading/accessing in, what is that eqivalent for ("Wscript.ScriptFullName") in the GetParentFolderName part of my CA?

It is correct, yes. I don't know what the equivalent is, if indeed there is one. For CAs that required WScript objects, I've always added them as separate files. You could load the DLL into an object explorer and browse it but wouldn't it be simpler to debug why the transform didn't work?

First things first: what tool are you using to create the transform? If it's Orca/InstEdit, this is going to be uphill! You need to create the component(s), make additions to the File and Media tables, etc., etc. There are a few free MSI editing tools arouind if you Google long and deep enough.

Second: what did the verbose log tell you when you tested the transform? You took a log, right?

  • First of all, you cannot embed files into a transform, it has to be either an uncompressed external file or a compressed CAB file. It's actually not that difficult to add an uncompressed external file using ORCA but as VBScab mentioned, you do need to remember all the different tables that need editing.
    As for getting parent folder name, where exactly is this in relation to the MSI ? For example, there are a huge number of already defined properties that the MSI can use and therefore can be referenced within a VBScript custom action, such as [OriginalDatabase] which points to the location that the original MSI was executed from. Does this assist? - EdT 1 year ago
    • @EdT - Thanks for joining the party :)
      By embed, do you mean just calling the files from within the TRANSFORM?

      At the moment how I have it and how I was hoping to leave it is all within a single folder. In this single folder is the MSI, the TRANSFORM and the three (3) individual files that I need to copy to three (3) different, individual locations after install. Since I was running into issues, I now also have a .CMD file in this same single folder that has the copy commands in it for the three (3) files. The plan was to "call" the .CMD file, from this folder, from a single line of VBScript in a CA entry in the TRANSFORM.

      Is this what you are saying can't be done from a TRANSFORM?

      The purpose of wanting to use GetParentFolderName is because I am using Configuration Manager as our deployment tool and it pushes out software into a randomly generated folder on the user's computer or is already in a randomly generated folder on the network from Configuration Manager itself, after being distributed. Using GetParentFolderName was because I can't use %~DP0 in VBScript, in the CA.

      The only reason for not wanting to CAB up the files was so as to be able to edit them quickly and easily, as they probably will need to be edited from time to time. - Dodgy Bob 1 year ago
      • By Embed, I mean that you cannot embed files into the transform in the way that files are embedded into the MSI. They must always be external to the transform, either uncompressed or in CAB format. In a normal deployment scenario, you would have the MSI, MST and external files all in the same folder. When you execute the MSI, the location of the folder containing the MSI, and therefore the external files, is contained in the property [OriginalDatabase], which you can reference in your vbscripts.
        If you intend to edit the configuration files then it would be sensible to avoid adding the files to the transform, as any change would need you to update a long list of tables, such as the file table, the MSI hash table, the component table, and so on. So the simplest strategy is to use VBScripts in your transform, with the appropriate conditions on them, to copy the local instance of the configuration file to the required destination.
        You need to think about the repair and uninstall scenarios, and also installing a newer version where existing configuration files may already exist. You may want to either rename any existing configuration file, or delete it, before copying the new one. If your configuration files are standard text files, the other approach I have used is to employ a VBScript to actually write the configuration files line by line, as this is easily embedded in a transform. Often, the configuration files are 90%+ common in content with just a small number of differences, and this can be handled by passing an argument into the vbscript so that it writes in the differences based on your requirements for each destination. - EdT 1 year ago
  • Sorry for not getting back here yesterday, got caught up with "real" work! Not that this isn't real work, but sadly, its not my priority work at the moment.

    @VBScab - thanks for persevering with me!
    In light of your comment about Orca/InstEd, I decided to chase up our licensing for AdminStudio! Turns out we were licensed up until last year - maintenance wise - so I've got a hold of what we were licensed up to and will get that setup shortly, but yes, I was only doing this with Orca/InstEd.

    I was following a couple of doco pieces I had found RE adding files...




    ...so am aware of having to edit multiple tables, but yeah, we all know how that turned out!

    And yes, I was creating logs as I went, but not necessarily keeping them! -BUT- I have been keeping the transforms after every edit. So going back to square one, I can reproduce the first lot of errors from the first transform...

    MSI (c) (E0:A8) [15:46:06:876]: Note: 1: 2205 2: 3: Error
    MSI (c) (E0:A8) [15:46:06:876]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 2705
    DEBUG: Error 2705: Invalid table: Directory; Could not be linked as tree.
    MSI (c) (E0:A8) [15:46:20:048]: Product: Mozilla Firefox 68.7.0esr x64 en-GB -- The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2705. The arguments are: Directory, , - Dodgy Bob 1 year ago
    • Reading this reminded me of something I forgot to mention. Where are you sequencing the custom actions to copy the files? Personally, I would put the actions after InstallFinalize, as any error during the MSI installation will roll back before these files are installed and also you don't need to think about whether to run the action as Immediate or Deferred (you do understand the difference?).
      To be honest, although before I retired I was working in an environment with licenses for Adminstudio, I still preferred using the Wise products as they give clearer results. Your log above shows an error in the directory table which is indicating that an entry cannot be resolved to a valid path. Do bear in mind that Windows Installer will create missing directories, but ONLY when installing files. For anything else you need to ensure that the directory path is created with the CreateFolder table or a custom action, before a file is created or copied in that destination. Also, be aware that property values are only available in the Immediate sequence and not the Deferred sequence. Let us know if you have any questions. - EdT 1 year ago
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ