ShellExecute (OpenInsight 32-Bit)
At 01 AUG 2006 09:49:58PM Steve Epstein wrote:
Bob Carten's example of using ShellExcute intrigued me.
I have tried to use it instead of uitlity('RUNWIN', …., however I am having some problems and would like advise in general:
1. Is ShellExecute better than RUNWIN?
2. After searching MSDN, I could find no indormation on the form of the parameter string, ie. if the program is a .bat file, should the paramemters simply be space delimited terminated by /00/?
3. Can ShellExcute run modally (the -1 flag for RUNWIN does not work here). I need to run a program from Basic+ which must wait for results. I would hate to resort to writing a wait-loop.
Also, when I use VB6 to open an OEngine and run a Basic+ function, RUNWIN does not seem to work (hence my desire to use ShellExecute).
At 02 AUG 2006 03:26AM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
Steve,
1. Is ShellExecute better than RUNWIN?
It's not that one is better than the other, it all depends on what you want to do.
If you know the exact program you need to execute use RUNWIN (which is a thin wrapper around the CreateProcess() API call). If you only have a document name then use ShellExecute which queries the registry to find out which exe to launch.
2. After searching MSDN, I could find no indormation on the form of the parameter string, ie. if the program is a .bat file, should the paramemters simply be space delimited terminated by /00/?
Yes - exactly the same as if you'd typed them in at the command line prompt.
3. Can ShellExcute run modally (the -1 flag for RUNWIN does not work here). I need to run a program from Basic+ which must wait for results. I would hate to resort to writing a wait-loop.
Neither CreateProcess() or ShellExecute() support modality intrinsically. The RUNWIN call in PS adds some extra code to support the modal setting, so you'd need to do something similar with ShellExecute.
In fact this isn't as straightforward as it sounds - to check for modality you'd need a handle to the process you start. ShellExecute doesn't return this, so you'd need to use ShellExecuteEx() instead (which is a bit more complex). Even then you are not guaranteed to get a process handle returned as the application you need may already be started - e.g if IE is open and you launch a .htm file you probably won't get a new copy of IE, so no new process is created, so no handle is returned.
Also, when I use VB6 to open an OEngine and run a Basic+ function, RUNWIN does not seem to work (hence my desire to use ShellExecute).
Do you get any information returned from the RUNWIN call? I assume it executes fine from the command line? Any example code you can provide?
World leaders in all things RevSoft
At 02 AUG 2006 05:03AM Steve Epstein wrote:
Dear Sprezz,
I think I may have found the answer. I wrote a simple program like this:
Function remote_test()
declare function utility
status=utility('RUNWIN','test.bat',-1)
return status
When I execute this program from VB6 (after all of the appropriate engine and queue setups) there is no value to status.
When I execute the program from the cmmonad line in the system editor, I get 'Must be executed from an event context'.
This is probably the same reason why start_window cannot be executed to a remote engine also.
Any ideas for a work around
At 02 AUG 2006 05:49AM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
Yes - don't use Utility, Get_Property, Set_property, Send_Message, Yield ,Run_Event, Post_Event, Send_Event, Start_Window etc etc etc as they all rely on the PS.
So use ShellExecute or WinExec directly.
World leaders in all things RevSoft
At 02 AUG 2006 09:51PM Steve Epstein wrote:
Dear Sprezz,
One of my colleauges uses this C++ function to acheive a modal call to an outside program from C++:
My new question is: can this (or a similar function) be made into a DLL for OI as it is written, or do we have to do some extra stuff to run in the OI environment?
void CRISKMANView::CallProcess(char *runfile, char *lpCommandLine, bool bWait)
{
STARTUPINFO StartupInfo;::ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));StartupInfo.cb=sizeof(STARTUPINFO);StartupInfo.lpTitle=NULL;StartupInfo.dwFlags=STARTF_USESHOWWINDOW;StartupInfo.wShowWindow=SW_MINIMIZE;PROCESS_INFORMATION ProcessInformation;if(::CreateProcess(runfile, lpCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation)){if (bWait){::WaitForSingleObject(ProcessInformation.hProcess, INFINITE);}::CloseHandle(ProcessInformation.hThread);::CloseHandle(ProcessInformation.hProcess);}else{LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language(LPTSTR) &lpMsgBuf,0,NULL );// Display the string.AfxMessageBox( (LPCTSTR)lpMsgBuf, MB_OK|MB_ICONINFORMATION );// Free the buffer.LocalFree( lpMsgBuf );}}
At 03 AUG 2006 04:00AM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
Steve,
If you're comfortable with using Structures (via var_to_struct(), define_struct() etc) and API calls in Basic+ then there's no reason why you can't do that within OI.
However, if you simply wanted to put that functionality in a DLL callable from Basic+ you would have to expose it as an exported function. In the case of your example that means you would have to extract the code from the class method it's currently wrapped in, or create an instance of that class in your exported function and call the method from there.
World leaders in all things RevSoft