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):
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;
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
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)
Please log in to answer
Posted by:
WSPPackager
14 years ago
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
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
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') [;)]
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
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
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.
Posted by:
AngelD
14 years ago
Posted by:
anonymous_9363
14 years ago
have you tried:You have a fundamental misunderstanding of what these two keywords mean.
Using ByRef instead of ByVal,
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
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.
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
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
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
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 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
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:
iusefirefox
14 years ago
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
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
Posted by:
Jsaylor
14 years ago
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
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
Posted by:
WSPPackager
14 years ago
Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.
so that the conversation will remain readable.