D Paste by Clay Smith
Description: Create Process
Hide line numbers

Create new paste
Post a reply
View replies

Paste:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
module createprocess; 

import windows; 

import std.string;
import std.signals;
import globals;


/// run new program as child process and return the exit code of the program when it's finished
uint execProcess(char[] program, char[] args, bool requireExitCode=true)
{
    uint retcode; 
    
    LPCTSTR lpApplicationName = .toStringz(program);
    LPCTSTR lpCommandLine = .toStringz(" " ~ args);  
    LPCTSTR lpCurrentDirectory = .toStringz(globals.programDir); 

    // collect startup info 
    STARTUPINFOA startup;
    GetStartupInfoA(&startup);
    startup.dwFlags = STARTF_USESTDHANDLES;
    startup.cb = STARTUPINFOA.sizeof;
    
    PROCESS_INFORMATION* info = new PROCESS_INFORMATION();

    if (CreateProcessA(lpApplicationName, lpCommandLine, 
                        null,    null, false, 
                        CREATE_NEW_CONSOLE, null,null,
                        &startup,
                        info) != 0)
    {
        GetExitCodeProcess(info.hProcess, &retcode);
        
        // wait for the program to finish to get the exit code of the program 
        if (requireExitCode)
        {
            // while loop until program is done
            while (retcode == STILL_ACTIVE)
            {
                GetExitCodeProcess(info.hProcess, &retcode);
                Sleep(100);
            }
        }
            
        CloseHandle(info.hProcess);
        CloseHandle(info.hThread);
        
        return retcode; 
    }
    
    return 0; 
}


// Hook ChildProcess up to a timer so that process is called once every .5 seconds, 
// which the only thing it will really do is to call the return code emitter if it is found
class ChildProcesses
{
    // process all processes
    void process()
    {
        // process each process to emit the return code if it has it
        foreach(char[] key; processes.keys)
        {
            uint retcode = 0; 
            
            // get the state of the process
            GetExitCodeProcess(processes[key].process.info.hProcess, &retcode);
            
            // if the process is still running, just let it run
            if (retcode == STILL_ACTIVE)
            {
                processes[key].running = true; 
            }
            // process is done running and we havn't gotten the return code, get the return code  
            else if (!processes[key].hasRetCode)
            {
                processes[key].running = false; 
                processes[key].process.emit(retcode);  
                processes[key].hasRetCode = true; 
                processes[key].started = false;
                processes[key].retCode = retcode; 
                
                // close program handles
                CloseHandle(processes[key].process.info.hProcess);
                CloseHandle(processes[key].process.info.hThread);
            }
        }
    }
    
    // start process identified by program name with arguments
    void start(char[] progName, char[] args, void delegate(int) retCodeCall)
    {
        // our key will be combo of program and arg names 
        char[] key = progName ~ args; 
        
        Process p; 
        
        // store program name so we can easily kill it 
        p.programName = progName; 
        
        // init our class 
        p.process = new PHandle;

        // set program name, args, and current directory 
        p.process.lpApplicationName = .toStringz(progName);
        p.process.lpCommandLine = .toStringz(" " ~ args);
        p.process.lpCurrentDirectory = .toStringz(globals.programDir); 
        
        // get startup information
        GetStartupInfoA(&p.process.startup); 
        p.process.startup.dwFlags = STARTF_USESTDHANDLES;
        p.process.startup.cb = STARTUPINFOA.sizeof;
        
        // create new process information
        p.process.info = new PROCESS_INFORMATION();

        // start running the new process 
        CreateProcessA(p.process.lpApplicationName, 
                       p.process.lpCommandLine, 
                       null, null, false, CREATE_NEW_CONSOLE, null,null,
                       &p.process.startup,
                        p.process.info); 
        
        p.started = true; 
        
        // hook up code that will do something with our return function
        p.process.retCodeSignal.connect(retCodeCall); 
        p.hasRetCode = false;
        
        // add it to our associative array 
        processes[key] = p;
    }
    
    // simply terminate all running processes 
    void terminateAll()
    {
        foreach(char[] key; processes.keys)
        {
            terminate(key);
        }
    }
    
    // terminate process identified by program name with arguments 
    void terminate(char[] key)
    {
        uint retcode = 0;
        
        // get it's exit code and then terminate the process 
        GetExitCodeProcess(processes[key].process.info.hProcess, &retcode);
        TerminateProcess(processes[key].process.info.hProcess, retcode);

        // close program handles 
        CloseHandle(processes[key].process.info.hProcess);
        CloseHandle(processes[key].process.info.hThread);
    }

    // all information about a process is stored here
    class PHandle
    {
        LPCTSTR lpApplicationName;
        LPCTSTR lpCommandLine;
        LPCTSTR lpCurrentDirectory; 

        STARTUPINFOA startup;
        PROCESS_INFORMATION* info; 
        
        mixin Signal!(int) retCodeSignal; // signal emitted when found the return code 
    }

    struct Process
    {
        bool started = false; // whether or not process was started 
        bool running = false; // whether or not process is running
        int retCode=0; // return code of the process 
        bool hasRetCode = false; // whether or not process has the proper return code 
        PHandle process; // process information structure 
        char[] programName; 
    }
    
    // store in an assoc array
    Process[char[]] processes; 
}


Replies:

    (some replies deleted)