The Origin Forum
File Exchange
Try Origin for Free
The Origin Forum
Home | Profile | Register | Active Topics | Members | Search | FAQ | Send File to Tech support
Username:
Password:
Save Password
Forgot your Password? | Admin Options

 All Forums
 Origin Forum for Programming
 Forum for Origin C
 ShellExecute, WinExec and CreateProcess
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic

Alexander N

Germany
18 Posts

Posted - 09/29/2009 :  2:08:17 PM  Show Profile  Edit Topic  Reply with Quote  View user's IP address  Delete Topic
Origin Ver. and Service Release (Select Help-->About Origin): 8.0 SR5&6
Operating System: Windows XP Pro SP3

Hi guys,

since quite a long time I try to start an external program (which has only commandline inputs, no gui) out of OriginC.

I declared the MS C++ native methods shellExecute / Winexec and CreateProcess in a header file. Then I could start the program using WinExec and shellExecute, but Origin always crashes after this command and the external program is also stopped.

With createProcess I even could not call the program since I could not imagine how to redeclare the pointers for ProcessInformation and Security_Attr in native OriginC datatypes.

I hope that someone could please explain this program breakdown or even has a snipet for using createProcess with Origin!?


My header looks like this (switching the pragma regarding the method to use):

//#pragma dll(kernel32, system)
#pragma dll(shell32, system)


#include <common.h> // must always include this
#include <string.h> // most likely you will also need strings
#include <mswin.h>
#include <Origin.h>

BOOL WINAPI CreateProcessA(
  string lpApplicationName,
  string lpCommandLine,
  void * lpProcessAttributes,
  void * lpThreadAttributes,
  bool bInheritHandles,
  int dwCreationFlags,
  void * lpEnvironment,
  string lpCurrentDirectory,
  void * lpStartupInfo,
  void * lpProcessInformation
);

int WinExec(
  string lpCmdLine,
  int uCmdShow
);

void ShellExecuteA (    
    void * hwnd,
    string lpOperation,
    string lpFile,
    string lpParameters,
    string lpDirectory,
    int nShowCmd
);


And my code snippet for calling the method like this:

	void * start;
	void * info;
	
	
	try {
		//CreateProcessA(NULL, app, ¶ms, NULL, FALSE, 0, NULL, "", &start, &info);
		//out_str(info);
		//WinExec(app, 1);
		ShellExecuteA(NULL, "open", "TEST.EXE", params, path, 1);
		//out_str(GetLastError());
	}
	catch(int nErr) {
		out_int("Error Calling External DLL = ", nErr);
	}


Thanks in advance,

Alexander

cpyang

USA
1406 Posts

Posted - 10/02/2009 :  2:41:12 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
The following has been added to mswin.h in upcoming Origin 8.1 and you can copy and paste into your own header in Origin 8. After #pragma dll(kernel32, system)

CP









//
// dwCreationFlags (Process Creation Flags) used in CreateProcess 
//
#define DEBUG_PROCESS               0x00000001
#define DEBUG_ONLY_THIS_PROCESS     0x00000002

#define CREATE_SUSPENDED            0x00000004

#define DETACHED_PROCESS            0x00000008

#define CREATE_NEW_CONSOLE          0x00000010

#define NORMAL_PRIORITY_CLASS       0x00000020
#define IDLE_PRIORITY_CLASS         0x00000040
#define HIGH_PRIORITY_CLASS         0x00000080
#define REALTIME_PRIORITY_CLASS     0x00000100

#define CREATE_NEW_PROCESS_GROUP    0x00000200
#define CREATE_UNICODE_ENVIRONMENT  0x00000400

#define CREATE_SEPARATE_WOW_VDM     0x00000800
#define CREATE_SHARED_WOW_VDM       0x00001000
#define CREATE_FORCEDOS             0x00002000

#define CREATE_BREAKAWAY_FROM_JOB	0x01000000
#define CREATE_PRESERVE_CODE_AUTHZ_LEVEL 0x02000000
#define CREATE_DEFAULT_ERROR_MODE   0x04000000
#define CREATE_NO_WINDOW            0x08000000
//probably don't need these in OC
//#define PROFILE_USER                0x10000000
//#define PROFILE_KERNEL              0x20000000
//#define PROFILE_SERVER              0x40000000

//
// dwFlags in STARTUPINFO Structure
//
#define STARTF_USESHOWWINDOW    0x00000001
#define STARTF_USESIZE          0x00000002
#define STARTF_USEPOSITION      0x00000004
#define STARTF_USECOUNTCHARS    0x00000008
#define STARTF_USEFILLATTRIBUTE 0x00000010
#define STARTF_RUNFULLSCREEN    0x00000020  // ignored for non-x86 platforms
#define STARTF_FORCEONFEEDBACK  0x00000040
#define STARTF_FORCEOFFFEEDBACK 0x00000080
#define STARTF_USESTDHANDLES    0x00000100
#define STARTF_USEHOTKEY        0x00000200

typedef struct _STARTUPINFO {
    DWORD   cb;
    LPSTR   lpReserved;
    LPSTR   lpDesktop;
    LPSTR   lpTitle;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
    BYTE	*lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFO, *LPSTARTUPINFO;

typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess;
    HANDLE hThread;
    DWORD dwProcessId;
    DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

#define CreateProcess  CreateProcessA
/**
		The CreateProcess function creates a new process and its primary thread. The new process executes the specified executable file.
	Remarks:	
		For more info please check: http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
	Example:
	void test_create_process()
	{
		STARTUPINFO			sinfo;		
		PROCESS_INFORMATION	pinfo;		
		memset(&sinfo, 0, sizeof(STARTUPINFO));
		memset(&pinfo, 0, sizeof(PROCESS_INFORMATION));
		// test control wShowWindow
		sinfo.dwFlags = STARTF_USESHOWWINDOW;
		sinfo.wShowWindow = SW_SHOWMAXIMIZED;
		BOOL bSucess = CreateProcess("C:\\Windows\\notepad.exe", NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo);
	}
*/
BOOL WINAPI CreateProcess(
  LPCSTR lpApplicationName,
  LPSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,
  DWORD dwCreationFlags,
  LPVOID lpEnvironment,
  LPCSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);



Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/05/2009 :  10:54:00 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
quote:
Originally posted by cpyang

BOOL WINAPI CreateProcess(
  LPCSTR lpApplicationName,
  LPSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,
  DWORD dwCreationFlags,
  LPVOID lpEnvironment,
  LPCSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);




Here I get an compiler error regarding syntax of the variables and type of variables. I tried a debug but could not distinguish which variable is affected.


Edit: Comparing your solution with your mswin.h, I suggest, that LPSECURITY_ATTRIBUTES should be replaced with a pointer SECURITY_ATTRIBUTES * ?? Then the code compiles successfully...

Edited by - Alexander N on 10/05/2009 11:02:28 AM
Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/05/2009 :  11:43:30 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Ok, now it works properly without break down. But how can I determine when the process has finished? Is it sufficient to copy all the definitions from MSDN:GetExitCodeProcess to my header and then execute GetExitCodeProcess?
Go to Top of Page

cpyang

USA
1406 Posts

Posted - 10/05/2009 :  4:13:36 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
We have modified LPSECURITY_ATTRIBUTES in the Origin 8.1 mswin.h, sorry I forgot to mention.


Sure, we will add GetExitCodeProcess to mswin.h as well, and that function is simple so you can add to yours.

CP
Go to Top of Page

cpyang

USA
1406 Posts

Posted - 10/05/2009 :  4:48:03 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
The following added to 8.1 mswin.h

//a subset of the status values that you might see in GetExitCodeProcess
#define STATUS_TIMEOUT                   0x00000102    
#define STATUS_PENDING                   0x00000103    
#define STATUS_ACCESS_VIOLATION          0xC0000005    
#define STATUS_IN_PAGE_ERROR             0xC0000006    
#define STATUS_INVALID_HANDLE            0xC0000008    
#define STATUS_NO_MEMORY                 0xC0000017    

BOOL WINAPI TerminateProcess(HANDLE hProcess, UINT uExitCode);
BOOL WINAPI GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);


And the following example added as well


void create_and_terminate_process()
{
	STARTUPINFO			sinfo;
	
	PROCESS_INFORMATION	pinfo;
	
	memset(&sinfo, 0, sizeof(STARTUPINFO));
	memset(&pinfo, 0, sizeof(PROCESS_INFORMATION));
	// test control wShowWindow
	sinfo.dwFlags = STARTF_USESHOWWINDOW;
	sinfo.wShowWindow = SW_SHOWMAXIMIZED;
	BOOL bSucess = CreateProcess("C:\\Windows\\notepad.exe", NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo);
		
	DWORD dwCode;
	
	if(GetExitCodeProcess(pinfo.hProcess, &dwCode))
	{
		if(dwCode == STATUS_PENDING)
			out_str("still alive");
		else
			printf("code = %X\n", dwCode);
	}
	else
		out_str("Failed to get exit code");

	//wait 1 sec
	LT_execute("sec -p 1");
	TerminateProcess(pinfo.hProcess, 2);
	if(GetExitCodeProcess(pinfo.hProcess, &dwCode))
		printf("After terminated, code = %X\n", dwCode);
	else
		out_str("Failed to get exit code");
		
}



If you need to wait for process to be terminated by the user, then maybe build your own loop with LT_execute("sec -p 0.2") in the loop.

CP

Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/06/2009 :  03:43:31 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply

	DWORD dwCode;
	int timer = 0;
	
	if(GetExitCodeProcess(pinfo.hProcess, &dwCode)) {
		while(&dwCode == STATUS_PENDING) {
			Sleep(0.1);
			timer++;
			if (timer > 100) {
			  TerminateProcess(pinfo.hProcess, 2);
			  printf("After terminated, code = %X\n", dwCode);
			  break;
			}
			GetExitCodeProcess(pinfo.hProcess, &dwCode);
		}
	}
	else {
		out_str("Failed to get exit code");
	}



Hi,
I now used a loop. It seems to work. Thanks for the improvements to the code base!

Alexander
Go to Top of Page

cpyang

USA
1406 Posts

Posted - 10/06/2009 :  07:57:03 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
you mean to use


while(dwCode == STATUS_PENDING) 


right?
CP
Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/06/2009 :  10:14:43 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
No, by reference &dwCode is possible. call by value does not exit the loop... Perhaps I'm wrong, but I thought this works.
Go to Top of Page

cpyang

USA
1406 Posts

Posted - 10/06/2009 :  2:00:49 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
How about this,


void create_and_terminate_process(int max = 100)
{
	STARTUPINFO			sinfo;
	
	PROCESS_INFORMATION	pinfo;
	
	memset(&sinfo, 0, sizeof(STARTUPINFO));
	memset(&pinfo, 0, sizeof(PROCESS_INFORMATION));
	
	sinfo.dwFlags = STARTF_USESHOWWINDOW;
	sinfo.wShowWindow = SW_SHOWMAXIMIZED;

	BOOL bSucess = CreateProcess("C:\\Windows\\notepad.exe", NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo);
		
	DWORD dwCode;
	
	if(GetExitCodeProcess(pinfo.hProcess, &dwCode))
	{
		if(dwCode == STATUS_PENDING)
			out_str("lunch successfully.");
		else
			printf("code = %X\n", dwCode);
	}
	else
		out_str("Failed to get exit code");
	
	if(dwCode != STATUS_PENDING)// something is wrong
		return;
	
	dwCode = 1;//init to some other values
	int timer = 0;
	while(GetExitCodeProcess(pinfo.hProcess, &dwCode) && dwCode == STATUS_PENDING) {
		Sleep(100);//0.1 sec, Origin will be totally dead
		timer++;
		if (timer == max)
		  TerminateProcess(pinfo.hProcess, 2);
	}
	printf("%d:final exit code = %X\n", timer, dwCode);		
}



I tested this and works by either user closing Notepad, or wait for 10 sec to terminate and you see the correct exit code for both cases.


CP
Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/07/2009 :  02:25:22 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Yeap. Both seems to work. Your way could be more stable or "more right". So I followed your solution instead of call by reference. So, thanks again!
Go to Top of Page

alexander.steppke

Germany
10 Posts

Posted - 10/19/2009 :  09:28:59 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Hi everybody,

it would be very helpful if you could summarize a complete working example, so that we know which files need to be changed to use the CreateProcess function with Origin 8 SR 6. I tried different approaches and at the end still have the error "Error, external DLL cannot find function shell32 : CreateProcess".

Thank you and greetings
Alexander
Go to Top of Page

Alexander N

Germany
18 Posts

Posted - 10/20/2009 :  04:05:05 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Yes, that's a mistake in my upper example. This line is correct according to MSDN (error came from switching between CreateProcess and ShellExecute / WinExec):

#pragma dll(kernel32, system) // for CreateProcess


or


#pragma dll(shell32, system) // for WinExec and ShellExecute
Go to Top of Page
  Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
The Origin Forum © 2020 Originlab Corporation Go To Top Of Page
Snitz Forums 2000