user1240679
user1240679

Reputation: 6979

Alternative for using system() in C++ to prevent firing new processes

I came across a C++ program for my use, in which there was some processing being done using some files and exes. Inside my C++ program, I had a snippet like

system(exe1 exe2 > TestFile1.txt  exe3 > TestFile2.txt)
system(exe2 exe3 > TestFile3.txt  exe3 > TestFile4.txt)
system(exe3 exe2 > TestFile5.txt  exe3 > TestFile6.txt)
system(exe4 exe1 > TestFile7.txt  exe3 > TestFile8.txt)

Now, I generated a .dll out of this C++ program to use in my C# app through P/Ivoke (Dllimport) but since the C++ had these system being used, it fires different processes and new cmd windows when I use this .dll in my C# program.

I thought to get rid of this by generating the dll's of all the exes (exe1, exe2, exe3 etc.) and firing the main function from these dlls, but it doesn't strike to me about how will I do that in C++ program?

I can export the main function from the C++ (exe1 dll, exe2 dll, exe3 dll etc.) and call it through C# P/Invoke, but I want an alternative like this for C++. to replace the above 4 line snippet. How can that be done?

Upvotes: 0

Views: 320

Answers (2)

Dewfy
Dewfy

Reputation: 23624

If the matter of you post that console is shown, just make your exe1...exeN invisible. Simplest way - replace

int main(int argc, char **argv)

with

int WINAPI WinMain(
  HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

And change target from console application to windows application.

Another (and better solution) is convert you application to multiple DLLs with functions - this is more elegant and flexible.

EDITED

After clarification of problem: "how do I call the functions in these dll's then?" short answer is: you need export function from each dll exe1,..exeN. Full answer - follow instructions:

In your dll declare

extern "C" __declspec(dllexport) SameNameForAllDllFunction(LPCWSTR fileName){ ...

This will create function that can be exported by name _SameNameForAllDllFunction. Note that name of file is unicode - it will simplify communication with C#.

Now let's write C# part:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void DoSomeWithFile(String fileName);

This declares type of function. And code of invocation:

IntPtr pDll = NativeMethods.LoadLibrary(@"exe1.DLL");
//here MUST go error handlers
try{
    IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(
        pDll, "SameNameForAllDllFunction");
    //here MUST go error handlers
    DoSomeWithFile dllFunct = (DoSomeWithFile)Marshal.GetDelegateForFunctionPointer(
        pAddressOfFunctionToCall, typeof(DoSomeWithFile)); 
    dllFunct("TestFile1.txt"); //now call the function 
} finally {
    NativeMethods.FreeLibrary(pDll);
}

Upvotes: 0

datenwolf
datenwolf

Reputation: 162164

You can start processes (also those which operate in text mode) without them having opening a console window. Please don't bolt me down on the details, since it's been ages since I've done this the last time (on Windows, I do it on regular terms on *nix systems). What I can tell you is, that you have to look into the function CreateProcessEx. You'll also have to reimplement the redirection of stdout into those textfiles.

I strongly advise against putting those processes into DLLs because then they'll run into your main process address space and will mess things up (BTW: You can load EXEs as if they were DLLs, but calling their entry function will b0rk your main process, so don't do it).

Upvotes: 1

Related Questions