• 0

[VB.NET] MSI Manipulation


Question

Hi Guys,

I'm trying to write an app that works with MSI files. What I'm wanting to do is be able to open up the MSI and pull out some key pieces of data such as the GUID, ProductName, ProductVersion etc.

Does anyone know of a class or library that can help me work with MSI files?

Regardz :)

Link to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 0

There are a couple of ways to do this:

1) P/Invoke into the Windows Installer API functions.

2) Use COM

A good reason to move away from VB .NET is that pretty much nobody uses it, so if you switch to C# you'll find a lot more support in terms of these kinds of things.

Here's a start, but I'd probably use P/Invoke, primarily because I hate everything about COM:

Imports WindowsInstaller

Dim retVal As String = String.Empty
Dim classType As Type = Type.GetTypeFromProgID("WindowsInstaller.Installer")
Dim installerObj As Object = Activator.CreateInstance(classType)
Dim installer As Installer = installerObj

Dim database As Database = installer.OpenDatabase(PATH_TO_MSI, 0)
//If you just want ProductVersion, then use "SELECT * FROM Property WHERE Property='ProductVersion'"
Dim view As View = database.OpenView("SELECT * FROM Property")
view.Execute()

Dim record As Record = view.Fetch()

While Not record Is Nothing
	retVal += String.Format("{0}: {1}\n", record.StringData(1), record.StringData(2))
	record = view.Fetch()
End While

Console.WriteLine(retVal)

Here's a C# P/Invoke Version:

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiOpenDatabase(string path, int persistMode, out IntPtr handle);

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiDatabaseOpenView(IntPtr database, string query, out IntPtr view);

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiViewExecute(IntPtr view, IntPtr record);

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiViewFetch(IntPtr view, ref IntPtr record);

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiViewClose(IntPtr view);

[DllImport("msi")]
extern static public int MsiCloseHandle(IntPtr handle);

[DllImport("msi", CharSet = CharSet.Auto)]
extern static public int MsiRecordGetString(IntPtr record, uint field, StringBuilder value, ref uint valueSize);

private void button1_Click(object sender, EventArgs e)
{
	IntPtr hDb = IntPtr.Zero;
	IntPtr hView = IntPtr.Zero;
	IntPtr hRecord = IntPtr.Zero;
	uint valueSize = 256;

	int err = MsiOpenDatabase(PATH_TO_MSI, 0, out hDb);
	err = MsiDatabaseOpenView(hDb, "SELECT * FROM Property"/* WHERE Property='ProductVersion'"*/, out hView);
	err = MsiViewExecute(hView, IntPtr.Zero);

	var name = new StringBuilder(256);
	var value = new StringBuilder(256);
	var final = new StringBuilder();

	while (MsiViewFetch(hView, ref hRecord) == 0)
	{
		err = MsiRecordGetString(hRecord, 1, name, ref valueSize);
		valueSize = 256;
		err = MsiRecordGetString(hRecord, 2, value, ref valueSize);
		valueSize = 256;
		if (err == 0)
			final.AppendLine(String.Format("{0}: {1}", name.ToString(), value.ToString()));
		else
			final.AppendLine("****");

		MsiCloseHandle(hRecord);
	}

	MsiViewClose(hView);
	MsiCloseHandle(hView);
	MsiCloseHandle(hDb);

	MessageBox.Show(final.ToString());
}

Link to comment
Share on other sites

  • 0

@BoogerJones

What are you talking about? You can find the same resources for VB.NET and C# (and for the very few ones that aren't around you can find translators to deal with the language symantics). Since the languages are exactly the same when compiled...

Microsoft claims the usage of the two language is rougly 50/50 in the .NET developer base... That's why they merged the VB.NET Language Team and the C# Language Team into the new "Managed Language Team"... As the differences between the two languages are symantical in nature.

http://www.infoworld...g-languages-831

Link to comment
Share on other sites

  • 0

Microsoft claims the usage of the two language is rougly 50/50 in the .NET developer base...

OK, maybe my "nobody uses it" statement was out-of-bounds. Still, I have a very hard time believing that usage is 50/50, but even if it's true it's irrelevant because I'm speaking to the number of resources/tutorials/support/examples/etc, not the number of devs. For example, the number of C#-tagged questions on StackOverflow is 138,412 versus 2,521 for VB .NET. Or are VB devs so good that they never have questions for SO? I'll admit that MS did a good job by not ignoring VB on MSDN, which some people thought they were going to do.

Sure, you could make an argument that intermediate code is the same for both or that the C# code above can easily be translated to VB with an online converter. But again, I'm talking about availability of support. And that makes life much easier when you're looking for help.

I didn't mean to turn this thread into a VB vs C# debate. I learned the little that I know starting out with VB (back then Excel VBA was one of the easiest ways to get started), so it's got a special place in my heart. But it's a huge downside (to me) to have such a harder time finding example code for it.

Link to comment
Share on other sites

  • 0

For the record I converted the P/Invoke code to VB and am using that. Works great. Thanks for all the help guys.

I do plan on moving to C#. I've just got a serious case of cbf at the moment until I get the syntax into my head.

Regardz :)

Link to comment
Share on other sites

  • 0

For example, the number of C#-tagged questions on StackOverflow is 138,412 versus 2,521 for VB .NET. Or are VB devs so good that they never have questions for SO? I'll admit that MS did a good job by not ignoring VB on MSDN, which some people thought they were going to do.

As someone who (involuntarily) writes VB.NET, I find that most of my VB support actually comes from C# questions on StackOverflow, and that I will often ask for VB help in C# since (IMO) the C# syntax is prettier and easier to follow. It could be argued as well that C# developers tend to be working on more... adventurous projects too, whereas VB developers in my experience are more often ASP.NET developers, which requires less p/Invoke and other extraordinary stuff that's likely to end up on SO.

I would agree that the ratio is probably not 60/40 (at least not with VB.NET alone, perhaps with VB.NET and VB classic), but I think it tends to be misrepresented.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.