Whenever we install a software, Windows OS will keep a backup copy of installer *.msi at C:\Windows\Installer\ location.
So I am iterating through all the msi file present at "C:\Windows\Installer\"
I want to prepare a mapping list where list will have *.msi file and its default location.
Let say C:\Windows\Installer[some product key]\123xR23.msi
Consider "123xR23.msi" is backup file for WinZip installation. And installer has install WinZip at location "C:\Program Files(x86)\WinZip"
So list will have following entry
"123xR23.msi","C:\Program Files(x86)\WinZip"
Please help me.
Thanks
First off, why do you even need this?
There is a mapping of these *.msi files already in existence in the registry at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\\Products\\InstallerProperties then the value of the msi is under LocalPackage
The S-1-5-18 is the Security ID of Local System.
The ProductGUID is also a bit weird here. In your installer you will see something like
2F7DBBE6-8EBC-495C-9041-46A772F4E311
but the product GUID in the registry path will look like this
6EBBD7F2CBE8C5940914647A274F3E11
There's definitely a reason for this but I don't know what it is. You'll just have to transform your product guid to this other representation when looking in the registry.
There is also a registry key called InstallLocation which should contain the install location of the msi package. This isn't always filled in though. Perhaps the install directory is stored somewhere else in the registry I don't know you'll have to look around probably.
Edit: Looks like each component of the install gets an entry by GUID in the registry as well which contains the path it was installed to. This could help you find the install location of a specific MSI if it is not listed under InstallLocation mentioned above. Per Micheal's comment, I would suggest taking advantage of the Msi related functions (https://msdn.microsoft.com/en-us/library/windows/desktop/aa372420(v=vs.85).aspx)
Related
I installed an MSI buillder tool on my visual studio 2017 and started deploying my desktop application with generated MSIs. The istaller is able to copy vital files and adds registery keys but it does not copy some additional config files which are required for logger. According to this page, switching "Copy to Output Directory Property" to "Copy always" supposed to take care the issue however, it still does not copy the config file into output directory on client's computer.
Can somebody give an advice about how I can diagnose this problem ?
Edit:
I think I can explicitly add logs files into MSI with following method but I have two concerns on this. Would I add the file into MSI with its global or relative path ? Secondly will it be a good practice ?
Edit 2:
For the reference for developers who has the same issue, looks like the method stated above adds files with its relative path. I added screenshot of difference page at source control.
It is completely normal to add individual files to a VS setup project. Every tool that generates an MSI works this way. VS setups are probably the exception with their "project output" type of input choice, where you get little idea of the actual files that will be installed. So you get the best control of the MSI content by adding each file individually, including that config file. Also, some files really don't belong in the Application Folder (that defaults to Program Files) because they are data files that belong somewhere like the User's Application Data.
The path where the MSI build gets its files from is nothing to do with where that file is deployed on the target system. You tell the MSI build where files will be deployed on the target system by using the File System view on target machine, where you get a list of destination folders to add files to.
Also, the copy to output directory stuff is nothing to do with the build of the MSI file. As far as I know, its main reason is to allow you to have all dependencies at the output build location of the code so that the program will work correctly from that location, and it happens to give you the opportunity to get all the files going into a setup from the same place. It does not mean "copy this file somewhere in such a way that it is automatically included in the MSI build and the deployed on the target system".
Once you get the MSI working and installing the config file, you may run into Windows Installer file overwrite rules that prevent you from overwriting files that have been updated after they were installed.
I recently took charge of a new system, it is a windows application written in C#, an installer (.MSI) file is created for its distribution. When I install the software it installs properly but it crashes on start. Then if I run the .exe file once for the application, the installed software starts working.
My observation is that .EXE installs some missing bit which is required by .MSI file. Is there a way I can find what files are missing in .MSI file ?
UPDATE on 09-08-2014:
I have found WER4A29.tmp.WERInternalMetadata.xml file which talks about System.Net.WebException
-<ProblemSignatures>
<EventType>CLR20r3</EventType>
<Parameter0>test.exe</Parameter0>
<Parameter1>1.0.3.33</Parameter1>
<Parameter2>53dca4f6</Parameter2>
<Parameter3>System</Parameter3>
<Parameter4>4.0.30319.18408</Parameter4>
<Parameter5>52311185</Parameter5>
<Parameter6>21b0</Parameter6>
<Parameter7>1fb</Parameter7>
<Parameter8>System.Net.WebException</Parameter8>
</ProblemSignatures>
First run an admin install via command line (cmd.exe) to extract the files from your MSI:
msiexec /a File.msi
Then inspect the extracted files to determine if there are configuration EXE files that perform configuration tasks. Determine what configuration files are there, if any. For example INI or XML files. Check for per user / user profile files.
In case you don't have the tool to view the MSI file, get hold of Orca or install a trial version of a commercial packaging tool. You will need this to see what is happening inside the MSI file. If you list the content of the Custom Action table there may be clues there as to what is going on. Also look in the Registry table for per user data to go into the registry. Debugging an MSI properly takes a lot of domain knowledge, but looking through it like this is useful too. Just post follow-up questions. I assume you have the Wix source code too?
To debug the application launch use Process Monitor (procmon.exe) to determine what is going on during the successful launch. The logging is a bit verbose, but with flags you will get to narrow it down.
- For native applications (Win32, or non-.net), I like to use Dependency Walker (depends.exe) too. It can be used for .NET too, but I find it less useful. I am not aware what the best dependency scanner for .NET is at the moment.
If manual debugging fails, several tools used for application repackaging are able to scan the system and determine the state before and after something is done and capture it as a list of differences. Advanced Installer's trial version should be able to do this. With some technical insight you should be able to identify what is needed from the diff image.
The .msi file is the installation set-up it include the installation script and the actual executable .exe file and other required dlls and configuration files.
I think the issue is with how the set-up is created. when you start the application after installation it is not performing the start up tasks like configuration of environment.
And the when you run the .exe it takes care of these configruations by it self.
I suggest that the testing of setup files .msi files and its generation scripts should be revisited.
I want to invoke custom action to execute set of .sql files against given database. I am able to do that using custom action code(in c#) if I hardcode path of folder where my sql files are available.
I want to put this sql scripts folder in same location where my .msi is present. How can I access/find this folder-path from custom action during the time of installation?
I am using Wix 3.6.
I am using dot net bootstrapper to create my setup.exe.
The SqlScript element in the WiX toolset may do a lot of what you are asking for. It actually stores the scripts as Binary streams in the MSI instead of relying on files relative to the MSI. This is an important design decision because there are many cases where your MSI will execute but not have access to the original source media so it would not find the scripts. For example, repair operations can be launched from the cached MSI package. If your custom action was to repair, it would need the original media to get the scripts. This is not very desirable.
If you really want to go down this path, then you'll want to look at using the SourceDir directory to get the "source location" of your MSI. As noted above, the source media may not always be available and SourceDir will be blank in those cases. To force SourceDir to be set, you'll need to add a ResolveFiles action. Be careful when scheduling ResolveFiles because that will require the original media. If that can't be found, the user will be prompted to insert it again.
The worst case of poor sequencing of ResolveFiles is a prompt from source when the user is attempting to uninstall their product. User's are trying to get your application of the machine and they are prevented unless they can find how they originally installed it. Good way to really upset your users. :)
I highly recommend looking at the SqlScript element instead or the source code if you are really interested. It's in the WiX toolset at src\ca\serverca (look for files with "sql" in the name below there).
I'm trying to get the location of an installation so that I can perform an upgrade, I am using a WiX installer but I cannot use WiX's own upgrade mechanics because it nukes the config files and does not do the checks that happen in the Custom Action's UI.
I have a bootstrapper which calls the .msi and I can easily get and set parameters within that .msi.
In this situation- how could I get from a known, but dynamic, GUID to the file location of its install within the bootstrapper before the .msi runs and nukes everything.
N.B. I cannot assume that the config file will remain the same between installs, or that I can grab the file faster than the uninstall can kill it.
You have quite a bit control over the upgrade mechanics that you should be able to do what you want during upgraded. In particular, I would have the new MSI read the config settings then write them back to the config file (your new MSI will definitely run before the old config file is removed). This would make your install idempotent (the ideal).
To answer your question, there are a number of ways to do what you want. The following is how I would probably go about it:
Write ARPINSTALLLOCATION - this old blog entry of mine has details.
If you know the ProductCode of your old MSI, skip to step 3. If you do not now the ProductCode, then use the UpgradeCode of the MSI (you'll know that if you are doing upgrades at all) and use ::MsiEnumRelatedProducts() to find the ProductCode of your previously installed MSI.
If you know the ProductCode of your MSI, then call ::MsiGetProductInfo() and ask for the INSTALLPROPERTY_INSTALLLOCATION property.
I have a Visual studio C# project and I have an installer that installs the files into whatever directory the user specifies. I also have another installer with localized language resources and I want that to be installed in the aforementioned directory.
Can anyone point me in the right direction on this? I think I have to do something with registry keys but I don't know what to do.
Edit: For the record, I found this page: How to: Use a Registry Launch Condition to Specify a Target Directory. And I followed the instructions and it did what I wanted it to do.
Typically, you would create a registry subkey and value of HKEY_LOCAL_MACHINE\SOFTWARE\ and then just read that key back in your second installer to decide where to put that.
Something like HKLM\SOFTWARE\MyApplication,
Then you make a string value called InstallPath and write the path from your first installer there.
Depending on what you're doing, you may want to have a look at merge modules for installing several components with one MSI.
You are on the right track. Your first installer would write it's install path to a well known registry key. The second installer would read the path from that well known key and put it's dlls in the appropriate sub folders.
Here is one way to go at it:
Assembly a = Assembly.GetExecutingAssembly();
string folder = System.IO.Path.GetDirectoryName(a.CodeBase);