How to get MST properties from vbscript - vbscript

So, I am creating a vbscript that will read an MSI and MST file. The idea is that if the user that will run the script is testing an MSI with an MST file involved, the script should create a "report" of the new properties that this MST have.
I am able to get the properties from a regular MSI, the problem is when I am trying to get into the MST section. While doing research I found out about the _TransformView Table and this should help me to obtain this information but I think I am not sure I know how to handle that table.
Const msiTransformErrorViewTransform = 256
Const msiOpenDB = 2
Dim FS, TS, WI, DB, View, Rec
Set WI = CreateObject("WindowsInstaller.Installer")
Set DB = WI.OpenDatabase(msiPath,msiOpenDB)
DB.ApplyTransform mstPath, msiTransformErrorViewTransform
If Err.number Then
Exit Function
End If
For i = 0 To 24 'Number of properties on the arrPropertyList
Set View = DB.OpenView("Select `Value` From Property WHERE `Property` = " & "'" & arrPropertyList(i) & "'")
View.Execute
Set Rec = View.Fetch
If Not Rec Is Nothing Then
objLog.WriteLine arrPropertyList(i) & " = " & Rec.StringData(1)
End If
Next
That code will display the msi properties that I have added on the arrPropertyList. The thing is that I am looking for the MST properties and I am only getting the MSI ones. I know that I should change the Query to access the _TransformView Table when calling the DB.OpenView but not sure how can I get to this information! Any knowledge you can share would be welcome.

It works slightly differently to what you think. Run the following to see what I mean (maybe force the VBS to run with Cscript.exe from a command prompt if you're expecting a lot of output):
'create 2 constants - one for when we want to just query the MSI (read) and one for when we want to make changes (write)
Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1
Const msiTransformErrorViewTransform = 256
'create WindowsInstaller.Installer object
Dim oInstaller : Set oInstaller = CreateObject("WindowsInstaller.Installer")
'open the MSI (the first argument supplied to the vbscript)
Dim oDatabase : Set oDatabase = oInstaller.OpenDatabase("C:\Temp\Temp.msi",msiOpenDatabaseModeReadOnly)
oDatabase.ApplyTransform "C:\Temp\Temp.mst", msiTransformErrorViewTransform
'create a view of the registry we want to see
Dim sql : sql = "SELECT * FROM `_TransformView`"
Dim regView : Set regView = oDatabase.OpenView(sql)
'execute the query
regView.Execute
'fetch the first row of data (if there is one!)
Dim regRecord : Set regRecord = regView.Fetch
'whilst we've returned a row and therefore regRecord is not Nothing
While Not regRecord Is Nothing
'print out the registry key
wscript.echo "Table: " & regRecord.StringData(1)
wscript.echo "Column: " & regRecord.StringData(2)
wscript.echo "Row: " & regRecord.StringData(3)
wscript.echo "Data: " & regRecord.StringData(4)
wscript.echo "Current: " & regRecord.StringData(5)
wscript.echo "***"
'go and fetch the next row of data
Set regRecord = regView.Fetch
Wend
regView.Close
Set regView = Nothing
Set regRecord = Nothing
Set oDatabase = Nothing
Set oInstaller = Nothing
So if you only wanted to see changes in the Property table, you would change the SQL query to:
Dim sql : sql = "SELECT * FROM `_TransformView` WHERE `Table` = 'Property'"
As well as storing the column names of the changed entries, the 'Column' column in the '_TransformView' table also stores whether the value was inserted, removed etc by using the values:
INSERT, DELETE, CREATE, or DROP.
You can find lots of VBScript Windows Installer tutorials for reference - don't forget to set your objects to Nothing otherwise you'll leave handles open. And of course use the link you provided for further reference.

WiLstXfm.vbs: Are you familiar with the MSI SDK sample: wilstxfm.vbs (View a Transform)? It can be used to view transform files. Usage is as follows:
cscript.exe WiLstXfm.vbs MySetup.msi MySetup.mst
Mock-up output:
Property Value [INSTALLLEVEL] {100}->{102}
File DELETE [Help.chm]
I think all you need is in there? Maybe give it a quick look. There is a whole bunch of such MSI API Samples - for all kinds of MSI purposes.
Github.com / Windows SDK: These VBScripts are installed with the Windows SDK, so you can find them on your local disk if you have Visual Studio installed, but you can also find them on Github.com:
Github: WiLstXfm.vbs - Microsoft repository on github.com.
Disk: On your local disk, search under Program Files (x86) if you have Visual Studio installed. Current Example: %ProgramFiles(x86)%\Windows Kits\10\bin\10.0.17763.0\x86.

Related

Using HP-UFT, is Is there anyway to tell whether or not an object in the object repository is being used in other tests?

I'm currently using UFT -- I have a GUI test, and there's a web element object in one of my tests I'd like to delete/update, but I'm worried it's being referenced by another test in our test suite. (I am coming into a test suite that someone else built)
Is there anyway to tell whether or not an object in the object repository is being used in other tests? (Without having to go into each individual test and action to find out?)
My way would be simple recursive file search.
Open EditPlus
Search -> Find In Files
Find What =
File Type = *.mts | *.vbs | *.qfl
Folder =
Select the Include Sub Folder Check Box
Click Find
You can use Search>View>Find (or ctrl+F) from UFT and select to look in entire solution
Open "Script.mts" file from every action and search for your object name. If you find the object, write the script name and line number where your object exists, in a file.
Use the below code:
'strScriptsPath is the path where your test script folders are placed.
Set strScripts = objFSO.GetFolder(strScriptsPath).SubFolders
For Each Script In strScripts
strAction = strScriptsPath & "\" & Script.Name & "\Action1\Script.mts"
If objFSO.FileExists(strAction) Then
'Open Script in NotePad
Set strFile = objFSO.OpenTextFile(strAction, 1)
Do While Not (strFile.AtEndOfStream)
strLine = strFile.ReadLine
If InStr(1, strLine, strObjectName) > 0 Then
iVerificationCount = objSheet.UsedRange.Rows.Count
iCurrentRow = iVerificationCount + 1
objSheet.Cells(iCurrentRow, 1) = Script.Name
objSheet.Cells(iCurrentRow, 2) = strLine
If strFile.AtEndOfStream Then
objSheet.Cells(iCurrentRow, 3) = strFile.Line
Else
objSheet.Cells(iCurrentRow, 3) = strFile.Line - 1
End If
End If
Loop
strFile.Close
Set strFile = Nothing
End If
Next
Set strScripts = Nothing
To be able to use this code, declare objFSO object and write a piece of code to create an excel and get objSheet.
You can also replace the object name using the below code:
Use the For Each Loop as mentioned above
strScript = strScriptsPath & "\" & strScriptName & "\Action1\Script.mts"
strFind = "Old Object Name"
strReplace = "New Object Name"
Set strFile = objFSO.OpenTextFile(strScript, 1)
strData = strFile.ReadAll
strNewData = Replace(strData, strFind, strReplace)
strFile.Close
Set strFile = Nothing
Set strFile = objFSO.OpenTextFile(strScript, 2)
strFile.Write strNewData
strFile.Close
Set strFile = Nothing
** You just need to write this entire code in a .vbs file and run that file.

SAP GUIXT - Pass Variable and run script

I would like to create an "input field" in SAP that uses the passed value within a vb script. To give a specific example, I would like to open FBL5N, pass an invoice into a field and view the invoice in VF03. The script to do that is ready and works for a hardcoded value of invoice or thru VBA.
Here is the GUI script part
inputfield (2,35) "inv" (2,45) size=10 name="V_inv"
pushbutton (toolbar) "print_inv" process="InvoiceScript.txt"
using MYINV = "V_inv"
Now, I don't know what to do for the inputscript part. I would like your assistance in this matter. Here is my first attempt:
Screen SAPLSLVC.0500
ApplyGuiScript template="VF03INV.vbs"
Enter
Thank you for your help and let me know if you need any precision.
Here are my sources of inspiration to get the above code :
http://www.synactive.com/tutor_e/lessonia03.html
http://www.synactive.com/docu_e/docia_process2.html
***if its possible to have a version that reads a value in clipboard, that would even be better.
After many attempts here is a solution:
Script(SAPLSLVC.0500.txt):
inputfield (2,35) "inv" (2,45) size=10 name="V_inv"
pushbutton (toolbar) "script" "/OVF03" process="startvf03.txt"
using INV = [V_inv] ' need this when opening new screen
InputScript (startvf03.txt):
parameter INV
Screen SAPMV60A.0101 'this is the VF03 screen
SET F[VBRK-VBELN] "&U[INV]" 'pass invoice # parameter
ApplyGuiScript "C:\guiXT\scripts\VF03INV.vbs"
VBScript (VF03INV.vbs):
inv = session.findById("wnd[0]/usr/ctxtVBRK-VBELN").text
session.findById("wnd[0]/mbar/menu[0]/menu[11]").Select
session.findById("wnd[1]/tbar[0]/btn[37]").press
session.findById("wnd[0]/tbar[0]/okcd").Text = "pdf!"
session.findById("wnd[0]").sendVKey 0
'with some little extra here on how to save a pdf in SAP
'get new strings for locations (specific to my situation)
abc = session.findById("wnd[1]/usr/cntlHTML/shellcont/shell").Browserhandle.locationURL
beg = instr(abc,"C:")
cde = mid(abc,beg,9999)
dest = "C:\111\invoices\" & inv & ".pdf"
'changing from temp to a specific folder
Set FSO = CreateObject("Scripting.FileSystemObject")
FSO.copyfile cde, dest
'close the open file
session.findById("wnd[1]").close
session.findById("wnd[0]").close
Set fso = nothing
*the several If Not IsObject(application) Then you usually see were not necessary, but doesn't hurt to have them.
I hope this helps everyone learn Guixt
Within the VB script with the parameter "template" can you address a GuiXT variable as follows.
for example:
msgbox "&V[V_inv]"

VBScript get SNMP OID values

I'm trying to use access SNMP via VBScript to access a few OID values as it's a climate monitor which has figures for temperature, humidity and airflow. I know which OID's I need to use but cannot find any script or piece of code which effectively connects and pulls out out this information.
Has anyone got anything that fits the bill?
I tried using this code but keep getting an error: ActiveX component can't create object: 'Scripting.SNMPManager'
Set oSNMPManager = CreateObject("Scripting.SNMPManager")
oSNMPManager.Agent = "unitip"
oSNMPManager.Community = "public"
'Add Variable objects to Variables collection
Call oSNMPManager.Variables.Add( "1.3.6.1.4.1.17373.2.2.1.6.1" )
Result = oSNMPManager.Get( ErrorIndex )
WScript.Echo "Get result: " & Result
If Result = 10 Then
WScript.Echo "ErrorIndex: " & ErrorIndex
End If
'Display properties of all Variable objects
WScript.Echo "OID, Type, Value"
For Each SNMPVariable in oSNMPManager.Variables
WScript.Echo SNMPVariable.OID & ", " & SNMPVariable.Type & ", " & SNMPVariable.Value
next
'Remove all Variable objects from the Variables collection
oSNMPManager.Variables.RemoveAll
Set objSnmpManager = CreateObject( "AxNetwork.SnmpManager" )
Set objConstants = CreateObject( "AxNetwork.NwConstants" )
' A license key is required to unlock this component after the trial period has expired.
' Call 'Activate' with a valid license key as its first parameter. Second parameter determines whether to save the license key permanently
' to the registry (True, so you need to call Activate only once), or not to store the key permanently (False, so you need to call Activate
' every time the component is created). For details, see manual, chapter "Product Activation".
'
' objSnmpManager.Activate "XXXXX-XXXXX-XXXXX", False

How do I display an image from Sql Server with Microsoft Access?

I upsized an Access 2007 database to SQL Server 2008 R2. The images are in SQL Server as image type. Access has link to the table containing the image. When I try to display from within Access, it won't do it. It still has the OLE Object wrapper.
How can I get that image and display it on my forms in Access? I do not have the option, at the moment, to remove the images, put them in a directory and point to them (the best way I know but not an option). I need to read the image / blob file directly from SQL Server and display it on an Access form.
Thank you for any ideas.
I saw this but it did not help:
How to display image from sql server in ms access
http://access.bukrek.net/documentation looks like the file in folder method
Since Access 2010, you can use the PictureData property to store and display images from SQL Server. You will need a bound control for an SQL Server data type varbinary(max), which can be hidden, and an unbound Image control in MS Access. You can now simply say:
Private Sub Form_Current()
Me.MSAccessImageControl.PictureData = Me.SQLServerImage
End Sub
And vice versa. You will need to add some error management to that, but very little else.
Below is a function I have successfully used called BlobToFile. And I also posted the code that I use to test it. The picture gets dumped to a so-called temp file but its not truly temp because it isn't in the temp directory. You can manually delete the image file or else you'll have to write it to your temp folder instead. Then I have an image control where I display the picture.
Private Sub Command1_Click()
Dim r As DAO.Recordset, sSQL As String, sTempPicture As String
sSQL = "SELECT ID, PictureBlobField FROM MyTable"
Set r = CurrentDb.OpenRecordset(sSQL, dbSeeChanges)
If Not (r.EOF And r.BOF) Then
sTempPicture = "C:\MyTempPicture.jpg"
Call BlobToFile(sTempPicture, r("PictureBlobField"))
If Dir(sTempPicture) <> "" Then
Me.imagecontrol1.Picture = sTempPicture
End If
End If
r.Close
Set r = Nothing
End Sub
'Function: BlobToFile - Extracts the data in a binary field to a disk file.
'Parameter: strFile - Full path and filename of the destination file.
'Parameter: Field - The field containing the blob.
'Return: The length of the data extracted.
Public Function BlobToFile(strFile As String, ByRef Field As Object) As Long
On Error GoTo BlobToFileError
Dim nFileNum As Integer
Dim abytData() As Byte
BlobToFile = 0
nFileNum = FreeFile
Open strFile For Binary Access Write As nFileNum
abytData = Field
Put #nFileNum, , abytData
BlobToFile = LOF(nFileNum)
BlobToFileExit:
If nFileNum > 0 Then Close nFileNum
Exit Function
BlobToFileError:
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
"Error writing file in BlobToFile"
BlobToFile = 0
Resume BlobToFileExit
End Function

How do I add/update a property inside an MSI from the command-line?

I have an MSI installer in which I need to add or modify a short text property from the command-line.
This has to be done after the installer is built; I cannot modify the process that produces the installer in the first place. It also has to be executed headless from a script.
When I say "property," it could be an MSI property, a value that gets written to the registery at install-time, or any other mechanism that can get this short custom text into the installed application when it runs.
Example VBScript that you could use to update (or add) a property post-build...
Option Explicit
Const MSI_FILE = "myfile.msi"
Dim installer, database, view
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (MSI_FILE, 1)
' Update
Set view = database.OpenView ("UPDATE Property SET Value = '" & myproperty & "' WHERE Property = 'MYPROPERTY'")
' .. or Add (Insert)
Set view = database.OpenView ("INSERT INTO Property (Property, Value) VALUES ('MYPROPERTY', '" & myproperty & "')")
view.Execute
database.Commit
Set database = Nothing
Set installer = Nothing
Set view = Nothing
For more information check out the Windows Installer SDK (part of the Windows SDK)
There's a bunch of example scripts that you can use from the command line to do various MSI manipulation tasks
For example WiRunSQL.vbs lets you execute arbitrary SQL against an MSI.
c:\> msiexec /i yourmsi.msi THEPROPERTYNAME=valueofproperty
For more information type msiexec at the commandline.
EDIT: or change the .msi file itself by using sql statements and updating the property in the properties table:
http://msdn.microsoft.com/en-us/library/aa372021(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa368568(VS.85).aspx
This is to add to #saschabeaumont 's answer in '09. Currently using dotNet 4.0
Option Explicit
Const MSI_FILE = "myFilePath.msi"
Const PROPERTY_STRING_Value = "FooBar"
Dim installer, database, view
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (MSI_FILE, 1)
' Update
Set view = database.OpenView ("UPDATE Property SET Value = '" & PROPERTY_STRING_Value & "' WHERE Property = 'MYPROPERTY'")
' .. or Add (Insert)
Set view = database.OpenView ("INSERT INTO Property (Property, Value) VALUES ('MYPROPERTY', '" & PROPERTY_STRING_Value & "')")
view.Execute()
database.Commit()
Set database = Nothing
Set installer = Nothing
Set view = Nothing

Resources