I'm calling pInvoke to call the Kernel's CreateProcess() and passing it the UninstallString of some app I'd like to uninstall. This UninstallString is the same thing Add/Remove Programs executes when you try to Uninstall an application. This call to CreateProcess() seems to work for all MSI UninstallStrings such as:
MsiExec.exe /I{88BAE373-00F4-3E33-828F-96E89E5E0CB9}
but doesn't launch anything for InstallShield UninstallStrings such as: RunDll32 C:\PROGRA~2\COMMON~1\INSTAL~1\PROFES~1\RunTime\10\50\Intel32\Ctor.dll,LaunchSetup "C:\Program Files (x86)\InstallShield Installation Information{34B37A74-125E-4406-87BA-E4BD3D097AE5}\setup.exe" -l0x9 -removeonly
What am I missing? If I run the same UninstallString inside a command line window it runs and launches the uninstaller. I tried ShellExecute() but doesn't seem to work either. I know I could parse the Uninstall string into the executable (Rundll32) and the rest as arguments and pass them to the managed Process class as StartInfo but I woud like to avoid having a special case just for InstallShield strings, especially since the command line runs the string fine.
Any ideas?
[DllImport("kernel32.dll")]
public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment,string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
PROCESS_INFORMATION pi = new ProcessUtils.PROCESS_INFORMATION();
STARTUPINFO si = new ProcessUtils.STARTUPINFO();
CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si, out pi);
int pID = pi.dwProcessId;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}