This website uses cookies. By clicking Accept, you consent to the use of cookies. Click Here to learn more about how we use cookies.
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
- Revenera Community
- :
- InstallShield
- :
- InstallShield Forum
- :
- Re: C# Custom Action Crashing in ControlEvent
Subscribe
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
11:42 AM
C# Custom Action Crashing in ControlEvent
Hey guys,
Has anyone tried the combination of a C# custom action launched from a ControlEvent?
I have been finding that attempting to use MsiGetProperty() will crash Msiexec when my function exits for some reason. It is completely fine when the action inserted directly in the sequence, or if I pass parameters explicitly instead of using MsiGetProperty().
Here's how I have MsiGetProperty PInvoke'd:
public static extern UInt32 MsiGetProperty(IntPtr install, string name, [Out] StringBuilder value, ref uint valueSize);
(And, yes yes, I am sure it works in DTF...)
Has anyone tried the combination of a C# custom action launched from a ControlEvent?
I have been finding that attempting to use MsiGetProperty() will crash Msiexec when my function exits for some reason. It is completely fine when the action inserted directly in the sequence, or if I pass parameters explicitly instead of using MsiGetProperty().
Here's how I have MsiGetProperty PInvoke'd:
public static extern UInt32 MsiGetProperty(IntPtr install, string name, [Out] StringBuilder value, ref uint valueSize);
(And, yes yes, I am sure it works in DTF...)
(5) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
12:08 PM
Your P/Invoke is incorrect (see http://pinvoke.net/default.aspx/msi.MsiGetProperty), but I would only expect that to manifest in 64-bit code. But what's probably more important is how you're calling it. Note that MSI is particularly picky about its buffer handling. Have you cross-referenced the implementation in InstallShield.Interop.Msi.dll?
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
12:31 PM
MichaelU wrote:
Your P/Invoke is incorrect (see http://pinvoke.net/default.aspx/msi.MsiGetProperty), but I would only expect that to manifest in 64-bit code. But what's probably more important is how you're calling it. Note that MSI is particularly picky about its buffer handling. Have you cross-referenced the implementation in InstallShield.Interop.Msi.dll?
Thanks Mike,
I actually had made the change you recommended prior to posting (cross referencing the Wix implementation, actually). The issue still persists.
[DllImport("msi", CharSet = CharSet.Auto)]
public static extern int MsiGetProperty(int install, string name, [Out] StringBuilder value, ref int valueSize);
As far as how I'm calling it, it's as simple as you'd expect:
int buffer = 1000;
int retCode;
retCode = MsiGetProperty(hMSI, "IS_SQLSERVER_CONNSTRING", SqlServerConnString, ref buffer);
//some stuff
return ERROR_SUCCESS;
Now, the strange thing is that it works fine like this--it gets the property value and returns ERROR_SUCCESS. It is when the function exits, and control is passed back to the install is when Msiexec.exe crashes. I can use MsiSetProperty to write debug messages to the logfile without incident--it seems to only relate to the use of MsiGetProperty().
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
01:17 PM
How do you initialize SqlServerConnString? Are you calling something like EnsureCapacity on it? Without that or possibly some further annotations in your P/Invoke, you're telling MSI it's okay to write to memory that you don't actually own.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
01:30 PM
Here's the whole thing I have set up to test this issue, as of this writing:
So, nothing particularly fancy--just the default StringBuilder Constructor.
public int CA(int hMSI)
{
Debugger.Launch();
StringBuilder SqlServerConnString = new StringBuilder();
int buffer = 10000;
int retCode;
try
{
retCode = MsiInterop.MsiGetProperty(hMSI, "IS_SQLSERVER_CONNSTRING", SqlServerConnString, ref buffer);
}
catch (Exception e)
{
MsiInterop.CELog(hMSI, "Exception: " + e.Message);
}
return 0;
}
So, nothing particularly fancy--just the default StringBuilder Constructor.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 19, 2013
01:34 PM
But, this does indeed seem to help resolve the issue.
Thanks much, Mike! Your explanation makes sense as to why to do it this way, but it seems strange that it only causes a problem from a ControlEvent.
public int CA(int hMSI)
{
StringBuilder SqlServerConnString = new StringBuilder();
SqlServerConnString.EnsureCapacity(1000);
int buffer = 1000;
int retCode;
try
{
retCode = MsiInterop.MsiGetProperty(hMSI, "IS_SQLSERVER_CONNSTRING", SqlServerConnString, ref buffer);
}
catch (Exception e)
{
MsiInterop.CELog(hMSI, "Exception: " + e.Message);
}
return 0;
}
Thanks much, Mike! Your explanation makes sense as to why to do it this way, but it seems strange that it only causes a problem from a ControlEvent.