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: Capturing stdOutput and stdError from LaunchApplication
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
‎Jun 22, 2010
05:58 PM
Capturing stdOutput and stdError from LaunchApplication
I'm attempting to capture the output from an executable launched from LaunchApplication, but all I'm getting is a blank file created. I've put together a sample project to try to get anything outputting to a text file, but no luck. All I get is the file created but with no contents. Here's my current Setup.rul:
Anyone have any luck capturing the stdout and stderr from InstallScript? I'm able to get the return code just fine, but I need more info than that.
Thanks
#include "ifx.h"
export prototype MyFunction(HWND);
prototype Kernel32.CloseHandle(HWND);
prototype HWND Kernel32.CreateFileA(STRING, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER);
///////////////////////////////////////////////////////////////////////////////
// Function: MyFunction
///////////////////////////////////////////////////////////////////////////////
function MyFunction(hMSI)
HWND stdOutput;
STRING szDir, szProgram, szCmdLine;
begin
LAAW_PARAMETERS.bInheritHandles = TRUE;
stdOutput = Kernel32.CreateFileA("C:\\temp\\log.log", GENERIC_WRITE, 2, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
LAAW_STARTUPINFO.dwFlags = LAAW_STARTUPINFO.dwFlags | STARTF_USESTDHANDLES;
LAAW_STARTUPINFO.hStdOutput = stdOutput;
LAAW_STARTUPINFO.hStdError = stdOutput;
szProgram = "c:\\windows\\system32\\getmac.exe";
szCmdLine = "";
LaunchApplication(szProgram, szCmdLine, "c:\\temp", SW_SHOWNORMAL, 1000, LAAW_OPTION_WAIT);
Kernel32.CloseHandle(stdOutput);
MessageBox("Check file", INFORMATION);
end;
Anyone have any luck capturing the stdout and stderr from InstallScript? I'm able to get the return code just fine, but I need more info than that.
Thanks
(5) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 22, 2010
09:21 PM
I really don't reccomend screen scraping the output of out of process exe's in an installer. If you really need the MAC address ( I'm guessing on your requirements here ) it's far easier to just query WMI and get it back as a string.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 22, 2010
09:53 PM
sorry, forgot to mention that it's our own .exe that we're launching and wanting to get the output from. I just picked getmac.exe for the example above that I'm trying to at least get working since it's simple.
I'm mainly looking to use this for troubleshooting installs. I can grab the error code that we return, but the output (both stdoutput and stderror) gives some extra info that would be handy.
I'm mainly looking to use this for troubleshooting installs. I can grab the error code that we return, but the output (both stdoutput and stderror) gives some extra info that would be handy.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 28, 2010
03:27 PM
Hi Ed,
I've not yet been able to work out how to get this going without an intermediate file. But, the "Easy Way" methods you can probably use:
1. Passing an output redirect on the commandline:
getmac.exe > c:\myfile.txt
Then reading in from the file after it's done. This looks like it's what you're already trying by redirecting STDOUT via setting handles and such.
2. Using C#, which is much simpler. Here's an except from something I have working, reading from a child process's STDOUT and writing to the parent process's console window:
string tmpFolder, stdOut;
tmpFolder = System.Environment.GetEnvironmentVariable("TEMP");
string AppPath = Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName;
AppPath = System.IO.Path.GetDirectoryName(AppPath);
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = AppPath + "\\sftinfo.exe";
p.StartInfo.Arguments = "\"" + manifest + "\" -M \"" + tmpFolder + "\\sftinfo.xml.nfo\"";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
stdOut = p.StandardOutput.ReadToEnd();
Console.Write(stdOut);
I've not yet been able to work out how to get this going without an intermediate file. But, the "Easy Way" methods you can probably use:
1. Passing an output redirect on the commandline:
getmac.exe > c:\myfile.txt
Then reading in from the file after it's done. This looks like it's what you're already trying by redirecting STDOUT via setting handles and such.
2. Using C#, which is much simpler. Here's an except from something I have working, reading from a child process's STDOUT and writing to the parent process's console window:
string tmpFolder, stdOut;
tmpFolder = System.Environment.GetEnvironmentVariable("TEMP");
string AppPath = Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName;
AppPath = System.IO.Path.GetDirectoryName(AppPath);
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = AppPath + "\\sftinfo.exe";
p.StartInfo.Arguments = "\"" + manifest + "\" -M \"" + tmpFolder + "\\sftinfo.xml.nfo\"";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
stdOut = p.StandardOutput.ReadToEnd();
Console.Write(stdOut);
Anonymous
Not applicable
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 30, 2012
05:41 PM
I was able to get this working by calling cmd.exe and passing the target program as parameters to cmd.exe using the /K or /C switches. I saw this implicitly referenced in another post. It made sense after I pondered it for a second. I/O redirection is a service provided by the shell, while the various LaunchApplication() functions directly spawn the processes via the Windows API. No screen output and hence the need to wrap the target CLI program... That is unless there's some undocumented LaunchApp() variant that attaches to the stdin/stdout pipes...
-Russ
-Russ
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Apr 27, 2020
06:07 PM
Here's how I got it to work:
NUMBER stdOutHandle;
NUMBER stdErrHandle;
SECURITY_ATTRIBUTES securityAttributes;
begin
// redirect stdout and stderror. need to use the win32 CreateFile
// because the installshield functions return non-win32 handles
securityAttributes.nLength = SizeOf(securityAttributes);
securityAttributes.bInheritHandle = TRUE;
stdOutHandle = KERNEL32.CreateFileA(stdOutFile, (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ,
&securityAttributes, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
stdErrHandle = KERNEL32.CreateFileA(stdErrFile, (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ,
&securityAttributes, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
LAAW_STARTUPINFO.hStdInput = NULL;
LAAW_STARTUPINFO.hStdOutput = stdOutHandle;
LAAW_STARTUPINFO.hStdError = stdErrHandle;
LAAW_STARTUPINFO.dwFlags = LAAW_STARTUPINFO.dwFlags | STARTF_USESTDHANDLES;
LAAW_PARAMETERS.bInheritHandles = TRUE;
launchAppResult = LaunchAppAndWait(app, args, LAAW_OPTION_WAIT | LAAW_OPTION_HIDDEN);
CloseFile(stdOutHandle);
CloseFile(stdErrHandle);