/build/static/layout/Breadcrumb_cap_w.png

How to pass value to vbs-function in binary table?

Hi!

I've been searching this forum for some help about passing values to a vbscript function that is stored in the binary table, but I haven't had any luck besides this thread, http://itninja.com/question/faulttree-101167
My intention is to have a "script library" file with a numerous of vbs functions in it for later use in Custom Actions.
I started off with a simple test-function, but obviously I have done something wrong.
Ok, here is my setup (I'm using AdminStudio 7.5, btw);

VBScript (Test.vbs):

Function Test(ByVal strMSG)
MsgBox strMSG
Test = 1
End Function

VBscript -> Stored in binary table
VBScript Filename = <PATH_TO_SCRIPT_FILES>\Test.vbs
Script Function = Test("Hello")
Return Processing = Synchronous (Check exit code)
In-Script Execution = Deferred Execution in System Context (CA Type 3078)
Install Exec Sequence = After PublishProduct

When I try to install the MSI I get the following error message: "Product: CA -- 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 script error , : Line , Column , "

The code above works if I don't have any arguments in the function, like this;

Function Test()
MsgBox "Hello"
Test = 1
End Function

and call it with Script Function = Test

I have also tried calling the function by passing a public property (which has been pre-defined in the Property table) to it, like this;
Test([MYPROP])

Any ideas?

/Regards Mathias

0 Comments   [ + ] Show comments

Answers (15)

Posted by: WSPPackager 14 years ago
Senior Purple Belt
2
Hi,

You can set the value to the property (in Execute Immediate) and same can be accessed thru VBScript function (in Execute Deferred).

1. Set Property in Execute Immediate. (This should be after InstallInitializeSequence)

EX: Set Property CA_PropertyName_Name to [INSTALLDIR];[TARGETDIR] (CA_Action_Name)

2. Call VBScription From Installation Function in Execute Deferred.(This should be after schedulereboot)

EX : Call VBScript From Installation Function FunctionName1 (CA_Propert_Name)

3. In VBSCription Function

Function FunctionName1()

arrMyParameters = split(Session.Property("CustomActionData"),";")

InstallDirectory = arrMyParameters(0)
TargetDirectory = arrMyparameters(1)
....
.......
.......

End Function
Posted by: captain_planet 14 years ago
Black Belt
2
WSPPackager has the right idea, but there are a few things which in my opinion are incorrect and will not make it work. First of all the sequencing. Immediate CAs should go BEFORE InstallInitialize. Deferred CAs should be sequenced BETWEEN InstallInitialize and InstallFinalize.

Another really important typo from that post is that, if i recall, it's HIGHLY important that the deferred CA (the Type 38 one....) is named correctly. So, in the example above, if the property is called 'CA_PropertyName_Name' then the deferred type 38 CA needs to be called 'CA_PropertyName_Name' (although i suspect WSPPackager put one too many '_Name' in the property name, and also missed a 'y' off 'CA_Propert_Name') [;)]
Posted by: captain_planet 14 years ago
Black Belt
1
To be honest....and with the risk of 'raining' on your parade, i didn't think passing parameters to a VBScript function in the Binary table was possible? I think that your error is coming from your Target column in your CA table as opposed to anything in your script. Though I'm open to people proving me wrong, gladly. Same with DLLs if i recalled......hmmm. Maybe I need to get Googling myself! [;)]
I don't think it matters if you use Subs or Functions, though if you're wanting to return values then you obviously want to be looking at Functions. And yes, you should be able to use the script again, but, if you use the wizard to create the CA it will probably create another entry in the binary table. So you may need to create your CA directly using the tables instead.

RE your last statement, there are some properties you can access from deferred mode (CustomActionData, ProductCode, UserSID) but none that you'd probably find useful. Read here for more info: http://www.symantec.com/connect/articles/how-access-windows-installer-property-deferred-execution
Posted by: AngelD 14 years ago
Red Belt
1
Mr captain is correct,
You cannot pass parameters to a vbscript function, so if you must retrieve a value then read-in the value as a property (or CustomActionData if in deferred execution)
Posted by: anonymous_9363 14 years ago
Red Belt
1
have you tried:
Using ByRef instead of ByVal,
You have a fundamental misunderstanding of what these two keywords mean.

ByVal means that the variable is passed 'By Value', i.e. the variable will contain the data to be manipulated. ByRef means that it's passed 'By Reference', i.e. a pointer to the data is passed. By default, VBScript uses ByVal.

Using the example variable 'strMsg', if it were declared 'ByRef' then if the function were to alter 'strMsg' in any way, the caller would see the changed data. I use referenced variables - as opposed to the function name itself - to pass data back to the caller. For example, lots of people do this kind of thing:Function GetSIDFromUser(ByVal strDomainName, ByVal strAccountName)
Dim objWMI

GetSIDFromUser = ""

On Error Resume Next
Set objWMI = GetObject("winmgmts:{impersonationlevel=impersonate}!" & "/root/cimv2:Win32_UserAccount.Domain='" & strDomainName & "'" & ",Name='" & strAccountName & "'")
If Err <> 0 Then
On Error Goto 0
Exit Function
End If

On Error GoTo 0

GetSIDFromUser = objWMI.SID
End Function
with a caller like this:strSID = GetSIDFromUser("MyDomain", "JoBlow")I prefer to code like this:Function GetSIDFromUser(ByVal strDomainName, ByVal strAccountName, ByRef strSID)
Dim objWMI

GetSIDFromUser = False

On Error Resume Next
Set objWMI = GetObject("winmgmts:{impersonationlevel=impersonate}!" & "/root/cimv2:Win32_UserAccount.Domain='" & strDomainName & "'" & ",Name='" & strAccountName & "'")
If Err <> 0 Then
On Error Goto 0
Exit Function
End If

On Error GoTo 0

strSID = objWMI.SID
GetSIDFromUser = True
End Function
with a call like this:blnResult = GetSIDFromUser("MyDomain", "JoBlow", strUserSID)
If Not blnResult Then
'// Handle the error however you want
End If

'// Continue with code which processes 'strUserSID'
You can see that the latter function directly changes the referenced variable 'strUserSID'. To avoid confusion, I use different names in the caller and the called procedure.
Posted by: Jsaylor 14 years ago
Second Degree Blue Belt
0
I don't typically use functions or subs in embedded CA's, mostly because if something is that complicated I feel like it's more appropriate to leverage windows installer to make it happen instead. However, have you tried:

Using ByRef instead of ByVal, or just leaving it undeclared? Embedded VBS can sometimes behave differently than you expect because the wscript object is called implicitly during a windows installer session. Common tasks have to be approached differently because of it. You also might try creating it as a sub instead of a function.

Also keep in mind that you can't pass properties to a script in execute deferred, so any functions you try to use with property calls in system context will fail.
Posted by: iusefirefox 14 years ago
Senior Yellow Belt
0
Thank you for your quick reply, Jsaylor!

Good point there about using ByRef instead of ByVal - I'll test it asap tomorrow. I've left it underclared once with the same result.
I thought it could be a nice thing to just point out a specific function amongst others in the embedded vbscript file, and also pass properties or just string values to functions for execution.
Say, if I could manage to actually make the darn thing work, can the same embedded vbscript file be reused by another custom action, or will it create another entry in the binary table (e.g. a copy of the existing vbscript file)?
So, if I run the custom action in deferred mode I will not be able to pass any kind of properties, not even private properties?

Please advise!
/Mathias
Posted by: iusefirefox 14 years ago
Senior Yellow Belt
0
Thank you all for your replies!

But... according to Mr VBScab it should be possible (referring to http://itninja.com/question/faulttree-101167), or am I missing something here?

The best approach would be to move the code which does the work and processes the variables into a function. Then, pass the properties to the function in the call.

Assuming:
- your function is called 'Main' and takes two parameters
- the Binary table entry is called MyScript
- you want to pass 2 properties, THISPROPERTY and THATPROPERTY

the Custom Action table would look like:
Action,Type,Source,Target
CA_ED_Whatever,3078,MyScript,Main([THISPROPERTY], [THATPROPERTY])

The quote is taken from the above link.
Is it because the vbscript is embedded it won't work, or will it never work?

Regards, Mathias
Posted by: AngelD 14 years ago
Red Belt
0
Ian must be referring to Custom Action Type 38.
Posted by: iusefirefox 14 years ago
Senior Yellow Belt
0
Thank you for your clarification VBScab, but is it possible to do the thing I try to achieve?
I.e. Add a vbscript file with a numerous functions in it to the binary table, and then, in a custom action, call a specific function by passing parameters to it, either in deferred or in immediate execution mode?

/Mathias
Posted by: iusefirefox 14 years ago
Senior Yellow Belt
0
Thank you WSPPackager!!

This seems to be a clever (and the only possible?) way to get access to properties in a VBS CA running in deferred mode.
(I'm still interested in VBScab's solution, though ;))

Regards, Mathias
Posted by: Jsaylor 14 years ago
Second Degree Blue Belt
0
ORIGINAL: VBScab
You have a fundamental misunderstanding of what these two keywords mean.

ByVal means that the variable is passed 'By Value', i.e. the variable will contain the data to be manipulated. ByRef means that it's passed 'By Reference', i.e. a pointer to the data is passed. By default, VBScript uses ByVal.


I was actually trying to conjure up ideas that might get around the odd behavior he was experiencing by referencing the fact that VBscript simply acts differently when called from inside an MSI. You can't do common things that you might do in a script called "normally" from wscript or cscript. Using a reference instead of a value might have been one of those things, but I simply don't embed functions into MSI's, so I had no idea that you just can't pass variables into a function.

It was really more of a "Well, you might try these weird things, and other weird things like it!" Rather than an absolute solution.

Also, VBscript uses ByRef as its default, not ByVal. You sure I'm the one with a fundamental misunderstanding? ;)
Posted by: AngelD 14 years ago
Red Belt
0
ORIGINAL: iusefirefox
but is it possible to do the thing I try to achieve?
I.e. Add a vbscript file with a numerous functions in it to the binary table, and then, in a custom action, call a specific function by passing parameters to it, either in deferred or in immediate execution mode?

I'll say it one last time; NO, you cannot declare arguments to the function call by the CustomAction table
Posted by: anonymous_9363 14 years ago
Red Belt
0
Also, VBscript uses ByRef as its default, not ByVal. You sure I'm the one with a fundamental misunderstanding? ;) LOL...quite right. It was early morning...what can I say? [sidestep]Of course, any half-decent programmer removes all doubt by declaring one or the other.[/sidestep]
Posted by: WSPPackager 14 years ago
Senior Purple Belt
0
Hi Captain,

You deserve the name Captain. Thanks for correcting the typo and other stuff. I agree with you.

Regards,
Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.
 
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