I have been following a solution to add a checkBox at the end of a MSI installation that opens the installed product :
Run exe after msi installation?
So far, so good.
However, I'd like to add another checkBox that opens a simple text file which contains the release notes. The file is already included in the setup project, along with the main output. I'm able to add a new checkBox. The only problem is how to open that text file : no custom action seems to fit this need as I can see here :
http://msdn.microsoft.com/en-us/library/windows/desktop/aa372048%28v=vs.85%29.aspx
Here's my current JS code :
var sql
var view
var checkboxTextForReleaseNotes = "See release notes";
var fileReleaseNotes = "ReleaseNotes.txt";
try
{
var fileIdForReleaseNotes = FindFileIdentifier(database, fileReleaseNotes);
if (!fileIdForReleaseNotes)
throw "Unable to find '" + fileReleaseNotes + "' in File table";
[ ... some actions to include another control as seen in link above ... ]
// Insert the new CheckboxReleaseNotes control
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxReleaseNotes', 'CheckBox', '18', '140', '343', '12', '3', 'LAUNCH_RN', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxTextForReleaseNotes + "', 'CloseButton', '|')";
view = database.OpenView(sql);
view.Execute();
view.Close();
// Modify the Order of the EndDialog event of the FinishedForm to 1
sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(6) = 1;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the Event to launch the release notes
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'OPEN_RN', 'LAUNCH_RN=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();
// Insert the custom action to open the release notes when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('OPEN_RN', '210', '" + fileIdForReleaseNotes + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();
database.Commit();
}
catch (e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
I know that type "210" for custom action is not the proper one ... but is there any ? Or must I really get through my way by launching a Jscript or VBScript ?
Editing : end of code completed. Tried also to add a custom action through the "vdproj" properties but it refuses because the file is not compatible.
All of the following is untested.
I think you want the custom action type 34 and also msidbCustomActionTypeAsync + msidbCustomActionTypeContinue to run it ASync/NoWait. So custom action type 34+192=226.
Source, according to the docs, doesn't have to be the same directory as the target executable.
Target is...
The Target column of the CustomAction table contains the full path and name of the executable file followed by optional arguments to the executable. The full path and name to the executable file is required. Quotation marks must be used around long file names or paths. The value is treated as formatted text and may contain references to properties, files, directories, or other formatted text attributes.
You can use the "start" shell command to load the text file using the shell. That will open the text file using the user's default text file viewer. You need the full path to start.exe and the full path to the release notes. Note how the docs say it will do string replacement on the Target field. There's a string format to get the full path to the a file given its File table key.
If a substring of the form [#filekey] is found, it is replaced by the full path of the file, with the value filekey used as a key into the File table.
Putting that all together, the following might work for Target:
"[SystemFolder]start.exe" "[#someFileKey]"
That all being said, if you're going to be doing more of these custom actions I would really look into Wix and authoring your own custom actions. Wix would save you from running this javascript post build. Authoring your own custom actions gives you direct access to either .NET or the Windows API. Opening a file with the shell in C#, for example, is pretty straight forward.
Related
I am using TIA portal V13, with WinCC RT Advanced. I have been given a running project and need to export some values to excel for the client daily, monthly and yearly using a script. I have a screen with a table control that displays values of tags. The values are logged periodically.
How can I access the values from the screen or data logs using vbs? There is this command in the manual for accessing the dataLogs
HMIRuntime.Logging.DataLogs
But I cannot find how to access the data and save it to a file.
There is already a vbs script in the project(begin and end times are defined earlier in the script)but it just exports an empty csv with the column names but no values.
Set obj1 = obj.ScreenItems("Table view_1")
obj1.TimeColumnRangeType = 1
obj1.TimeColumnBeginTime = sBeginTime
obj1.TimeColumnEndTime = sEndTime
FolderName = "C:\Folder_name"
FileDate = sDay &"_" &sMonth &"_" &sYear
obj1.ExportDirectoryChangeable = True
obj1.ExportDirectoryname = FolderName
obj1.ExportFilenameChangeable = True
obj1.ExportFilename = "Filename " &FileDate
obj1.Export()
I'm using an action inside a form to create a Word document, using the CreateObject("Word.application") method, then I modify it to my liking and save it in a temp directory.
I can show the Word document as soon as it is created by calling nameOfTheDocument.visible(true), and by modifying the Save action I can save the newly created document as a PDF, however I can't find a way to show it to the user.
Trying to call visible(true) on the PDF object results in error "Instance member VISIBLE does not exist"
Hmmm... The best and right way - use OS file association.
I'm use java way:
//Win
Process p = Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + filePath);
p.waitFor();
//MacOS.*Nix
Process p = Runtime.getRuntime().exec("/usr/bin/open " + filePath);
p.waitFor();
But you can call this command on Lotusscript:
Shell({rundll32 url.dll,FileProtocolHandler } & fullFilePath,1)
'or
Shell({/usr/bin/open } & fullFilePath,1)
We have used the Shell command to launch PDFs in the past. Something like the below. The only downside to this is if the location of the executable changes (whether from upgrade or change to a different program) the code breaks.
Dim ProgPath$, FilePath$
Dim result As Integer
'Path of the executable
ProgPath$ = |"C:\Program Files (x86)\Adobe\Acrobat 7.0\Acrobat\Acrobat.exe"|
'Path of the file to open
FilePath$ = | "C:\TestFile.PDF"|
result = Shell(ProgPath$ & FilePath$,1)
I'm building MSi using visual studio setup project. I want to have different custom action run depending on /norstart option. What condition should I use to detect if /norestart is provided or not?
If this is impossible, I'm thinking about setting a property. Here is my theory. Use Orca to set REBOOT=Force. If I want to suppress reboot, run msi as
foo.msi /quiet REBOOT=ReallySuppress
And read the property from code, like
String inputFile = #"C:\Users\Administrator\Desktop\foo.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer) Activator.CreateInstance(installerType);
// Open the MSI database in the input file
var database = installer.OpenDatabase(inputFile, 0);
// Open a view on the Property table for the version property
var view = database.OpenView("SELECT * FROM `Property`");
//View view = database.OpenView("SELECT * FROM Property");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
// Get the version from the data
//string version = record.get_StringData(2);
while (record != null)
{
logger.LogMessage(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
}
This doesn't work, because it always read REBOOT=Force.
I have figured this out by myself.
Set CustomActionData to be /reboot=[REBOOT].
Then read the value:
Context.Parameters["reboot"]
If /norestart option is provided, value of reboot will be ReallySuppress
Tried set/get the INSTALLDIR property using MsiSetProperty/MsiGetProperty methods. But it wouldn't work in case of InstallscriptMSI projects . What am I missing here?
Came across in an other forum that, Installshield properties have limited access in some cases.
NOTE:
MsiGetProperty and MsiSetProperty properties cannot be used for deferred InstallScript custom actions, which do not have access to the active .msi database and do not recognize any Windows Installer properties. They can access only the information that has been written into the execution script.
EXAMPLE:
// Include header file for built-in functions
#include "isrt.h"
// Include header file for MSI API functions and constants
#include "iswi.h"
export prototype Func1(HWND);
function Func1(hMSI)
STRING svName;
NUMBER nvSize, nResponse;
begin
// Retrieve the user's name from the MSI database
nvSize = 256;
MsiGetProperty (hMSI, "USERNAME", svName, nvSize);
nResponse = AskYesNo ("Your name will be registered as " +
svName + ". Is this correct?", YES);
if nResponse = NO then
AskText ("Enter the name that will be registered for " +
"this product.", svName, svName);
MsiSetProperty(hMSI, "USERNAME", svName);
endif;
end;
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