I have chained multiple Msi/exec packages in my Bundle.wxs. In my managed Bootstrapper code, I would like to get the parameters (such as DisplayName, Vital, etc) of the current package that is being executed.
Right now, I have only found events that provide the packageID. Can I use this to somehow access other properties of the package?
Yes. A file called BootstrapperApplicationData.xml is created during the build process and included with your Bootstrapper Application. The BootstrapperApplicationData.xml has lots of information about the bundle and packages included in your Bundle Chain, including the DisplayName and sizes and vital.
You'll find the BootstrapperApplicationData.xml right next to your .dll. In managed code you can get it using the following code:
string folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dataXmlPath = Path.Combine(folder, "BootstrapperApplicationData.xml");
In native code, it is easier to use the helper functions provided in the balutil.lib. Namely BalManifestLoad() then BalInfoParseFromXml() to parse the XML file into a bunch of handy structs. You can see the code in src\ext\BalExtension\balutil\balinfo.cpp.
Finally, the BootstrapperApplicationData.xml can be extended by using CustomTable elements and setting the BootstrapperAppplicationData='yes' attribute.
Related
I have a PPC2003 project in VS2005. I have added a resource file (SomeResources.resx) to the project. I can access the test string I have in the file by using My.Resources.SomeResources.MyTestString (I am using the default Custom Tool Name that VS provides).
When the Build Action property of the is set to Embedded Resource, the application references the MyTestString successfully.
But I do not want to embed the file, so that it's string values can be modified after it has been deployed/installed.
I, therefore, changed the Build Action to Content, so that the file gets copied out to the device for potential future manipulation. When I call MyTestString I get the following error:
MissingManifestResourceException Stack Trace: at System.Resources.ResourceManager.InternalGetResourceSet() at System.Resources.ResourceManager.InternalGetResourceSet() at System.Resources.ResourceManager.InternalGetResourceSet() at System.Resources.ResourceManager.GetString() at MyApp.My.Resources.SomeResources.get_MyTestString() at MyApp.fMain.fMain_Load() at System.Windows.Forms.Form.OnLoad() at System.Windows.Forms.Form._SetVisibleNotify() at System.Windows.Forms.Control.set_Visible() at System.Windows.Forms.Application.Run() at MyApp.fMain.Main()
As the file is not embedded, do I maybe need to manually load it first? If so, how? Any other ideas? Is it not possible to do what I'm after achieving and should I just create my own XML file/reader?
Resources (resx files) are specifically designed to be compiled into the application. If you want it to be an editable content file on the target, then you have to approach it differently and use something like an XML file and wrap that with accessors (akin to the Configuration namespace stuff in the full framework).
I'm working on a service that will download a .NET solution from a repository and build it (not unlike a continuous-integration build service). What I want to know is, using MSBuild programmatically via the Microsoft.Build namespace classes, can I can load the solution and project(s) into memory and build it without first saving them to disk in a temporary folder?
I'm still learning MSBuild and trying things, but I figure someone on Stack Overflow has tried this and has some insight.
I can't speak to whether this is a good idea or not, but it's possible to do.
ProjectInstance has a constructor that accepts a ProjectRootElement, which can be constructed via the Create(XmlReader) method. And as you may know, XmlReader can be attached to various Streams including a MemoryStream.
Here's how something like this may look:
var xmlReader = XmlTextReader.Create([your existing memory stream]);
var project = ProjectRootElement.Create(xmlReader);
var buildParams = new BuildParameters();
var buildData = new BuildRequestData(new ProjectInstance(project),
new string[] { "Build", "Your Other Target Here" });
var buildResult = BuildManager.DefaultBuildManager.Build(buildParams, buildData);
After researching MSBuild and all the involved components, it appears as though it's necessary to have the entire project set up on the file system before being able to build it. Unfortunately, what I'm trying to do just can't be done with the provided toolset.
For a Windows 8 application in C#/XAML I need to access a specific ressource file. In WP7 I used resx file and now it seems that we need to use resw file. It's not a language resource file.
My file is called ConfigResources.resw, it just contains one key : "ConfigFile" and a value : a string.
How can I access it from my code? I tried this without any luck:
var storedConfigFile = Application.Current.Resources["ConfigResources"];
Then how can I edit the value of the key inside from my code?
Thank you
I created a project on CodePlex recently called ResW File Code Generator that simplifies using localized resources in code in windows store app project. It's a custom tool that automatically generates and updates a helper class similar to what ResX files used in the full version of .NET
According to here, you need to use the Windows.ApplicationModel.Resources.ResourceLoader and the Windows.ApplicationModel.Resources.Core namespace provide interaction with resw files.
It should look something like this:
var loader = new Windows.ApplicationModel.Resources.ResourceLoader();
var text = loader.GetString("Farewell");
Alternately, if you're creating a cross-platform library you could also do it using the System.Resources.ResourceManager:
Although the System.Resources.ResourceManager class is included in the
.NET for Windows Store apps, we do not recommend its use. Use
ResourceManager only in libraries that are developed as Portable Class
Library projects and that target multiple platforms.
Like this from here:
ResourceManager rm = new ResourceManager("Strings", typeof(Example).Assembly);
string timeString = rm.GetString("TimeHeader");
There is a sample that shows the different ways to read the resources in WinRT apps (i.e. from resw files).
Given:
Wix 3.0 is used to create MSI.
The product consists of multiple feature.
Each feature has few sub features. It’s a standard MSI feature tree.
Each feature or sub feature depend on multiple external components.
E.g. .NET 4, ASP.NET etc
Custom action written in C# using Wix 3.0 SDK processes these
dependency and evaluates if components are present or not for a
given set of features.
At time of install if dependent component is missing for given
selection of features, installation fails.
To achieve:
Ability to execute prerequisite check, which is already done in MSI as custom action during installation, without installing MSI on a given machine.
Failed Attempts:
1)
Custom action have function signature like this
[CustomAction]
public static ActionResult ProcessFeaturePrerequisite(Session session);
In order to get session object I used following API present in Wix 3.0 SDK
Session session = Installer.OpenPackage("Pathto\\Product.msi", true); // true doesn’t install it. Also tried with false, but didn’t work.
When I invoke the above method with above session following things fail.
session.Features["SomeFeature"].CurrentState;
This throws exception.
System.ArgumentException was unhandled by user code
Message=Feature ID not registered. SomeFeature
Source=Microsoft.Deployment.WindowsInstaller
StackTrace:
at Microsoft.Deployment.WindowsInstaller.FeatureInfo.get_CurrentState()
Also below critical API which determines prerequisite status always returns false.
session.EvaluateCondition(prereq);
2)
I know a command line way to specify features to the above MSI and install it. It goes like this
msiexec /i "Product.msi" ADDLOCAL=ALL REMOVE="Foo,Bar "
I couldn’t find any API in SDK which allows me to pass additional params which returns session object without starting installation. My guess is passing such param will make session.Features more valid.
Questions:
So how do I achieve above goal?
Is there
any API in Wix SDK which allows me to call custom action without
invoking installation?
any way to invoke custom action from command line for a given MSI
without installing?
any way to make Wix to change MSI into accepting a command string
containing custom action name which only evaluates the action?
any better way to do the same?
I suppose you're trying to solve the problem with the wrong tool. As far as I understand, you would like to check the installation prerequisites from inside a certain tool, but not from the installation. As long as the functionality is implemented as a custom action in the MSI package, you'd like to utilize that functionality in order not to duplicate the code.
I would choose a different way in your situation:
Extract the functionality which actually checks for prerequisites into a separate assembly, e.g. checkprereq.dll
Refactor your custom action to reference checkprereq.dll. Note that you'll have to add checkprereq.dll to your Binary table as well as the customaction.dll. You should divide the responsibility here: the custom action part works with MSI stuff - in your case, it's defining which prerequisites to check based on the combination of features a user selected - and the functional part - the actual prerequisites verification, which is done by checkprereq.dll
Use checkprereq.dll separately when you need to check prerequisites not triggering the installation process
The attempts you've outlined here demonstrate an important false assumption: the session object at install time is the same as the installation object you get by just opening the MSI database for read only purpose. IT'S NOT TRUE! Actually, I doubt it makes any sense to reference the session object outside the installation transaction. As its name states, it is an installation session, that is, available in process - not a static thing.
The MSI package should be treated just as a database when it is just a file and not a running installation. Hence, only static information living in MSI package can be queried and used when you just open it for reading and not installing. I mean you can query the Feature table, for instance, but don't expect it to contain information which makes sense in installation time only, like whether a user chose a feature for installation or not.
Hope this makes sense and shows you the right direction.
my solution has multiple projects and in one of them I have the code to get the embedded resource (an xml file) from another project. All this works fine when all the projects are seperate. However when all the class libraries are embedded into a single dll, the code to get the resource file does not work i.e. it cannot get the emebedded resource.
I was wondering if the references to the emebedded resource get mixed up when they are combined together in a single dll??
I use the method Assembly.GetCallingAssembly().GetManifestResourceStream("namespace..filename");
I would not use Assembly.GetCallingAssembly(). I would use typeof(SomeClassNextToXmlFile).Assembly that way if you are calling the dll with the embedded resource from a exe file it won't go looking in the exe for the resource. Also you may want to try using Reflector and make sure the resource you are looking for is where you think it is.