Click here to Skip to main content
15,877,967 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am writing code in C#.
My code has a command to run an exe from a shell command:
$"/C {hospitalPath} /R {bdbPath} /M {bmiPath}";

It is a very obscure app called 'hospital'. The bdbPath and bmiPath are paths to files.

If any of the files are corrupt it produces a pop-up window which needs the user to click 'ok' for the code to continue and not stay in a stuck state. I woudl like to prevent this by killing the process if this happens but I do not know how to do this.

What I have tried:

Here is my code:
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                    startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    startInfo.FileName = "cmd.exe";
                    startInfo.Arguments = HospitalCommand(hospitalPath, bdbPath, bmiPath);
                    process.StartInfo = startInfo;
bool processStarted = process.Start();
process.WaitForExit();


I use WaitForExit() because if the hospital.exe runs successfully it must finish before the code continues.

I have tried to create the process with a cancellation token, and then create a new thread which checks to see if the process has produced some output files which shows it is running. If these are not produced then I call process.Kill().
However, I cannot get the code to run to the thread creation because it is stuck at the point where it runs the shell command.
I have also tried different flags in the command, none of which prevent the pop-ups stopping the execution.

I have not yet tried to create the checking thread before the command thread runs. I could create the checking thread, put in a delay, kick off the command then see if the process needs to be killed. Would this work? It doesn't seem like a great solution even if it works.

Any suggestion please?
Posted
Updated 18-Nov-22 1:56am
Comments
Richard Deeming 18-Nov-22 3:47am    
Have you tried creating the "checking" thread after process.Start and before process.WaitForExit? The WaitForExit will block the current thread until the process exits, so anything after that won't run until the process has closed.
Jackie Lloyd 18-Nov-22 3:59am    
Hi Richard, thank you for that suggestion, I will try that, funny I was just wondering if I should try that, now that I have posted my problem my brain has unstuck slightly with the relief of a asking for help! It's good to know its something worth trying. I will give it a go, many thanks!
Jackie Lloyd 18-Nov-22 5:45am    
Hi Richard, I tried this and while it did allow me to get the code to create the checking thread it still did not help the situation. When the process is stuck by a pop-up, even if I kill the process the pop-up remains, and is still hogging the resources, so I can't get it out of its stuck state :(
Jackie Lloyd 18-Nov-22 5:51am    
I'm wondering if I could get the pid when I set the process running by the command. And then later use the pid in another shell command to exit it?
Jackie Lloyd 18-Nov-22 6:49am    
My progress so far is that this enables me to kill the actual process including any pop-ups:
int pid = Process.GetProcessesByName("hospital").Single().Id;
Process p = Process.GetProcessById(pid);
p.Kill();

I just need to get it all working togther correctly

Maybe you can use something like this:
Process.Exited Event (System.Diagnostics) | Microsoft Learn[^]
 
Share this answer
 
Comments
Jackie Lloyd 18-Nov-22 5:48am    
Hi Rick, thanks for reading my question and offering a solution.
Unless I have misunderstood this, this enables me to put a time limit on the task, so if it runs longer than I think it should, it is forced to end.
If this is the case, it won't help me. The process could take a very long time to run. I know some files that are created early on so I can use these as a check to see if it is running ok, but I can't use any time limit to end the process.
Also, I have discovered that killing the process doesn't get rid of the pop ups from the exe that has been kicked off, or stop the exe :(
I've used something like the following to automate the clicking of OK on some named window.
Spin up a thread which polls for the existence of the pop-up and click it if it does.

C#
[
    System.Runtime.InteropServices.DllImportAttribute
    (
        "User32"
    ,
        SetLastError=true
    ,
        EntryPoint="FindWindow"
    )
]
private static extern System.IntPtr
API_FindWindow
(
    string lpClassName
,
    string lpWindowName
) ;

public static System.IntPtr
FindWindow
(
    string WindowName
)
{
    return ( API_FindWindow
    (
        null
    ,
        WindowName
    ) ) ;
}


C#
public enum WindowsMessage : uint
{
    EM_GETPARAFORMAT = 61
,
    EM_SETPARAFORMAT = 71
,
    WM_LBUTTONDOWN   = 0x0201
,
    WM_LBUTTONUP     = 0x0202
} ;

[
    System.Runtime.InteropServices.DllImportAttribute
    (
        "User32"
    ,
        SetLastError=true
    ,
        EntryPoint="SendMessage"
    )
]
private static extern System.Int32
API_SendMessage
(
    System.IntPtr hWnd
,
    System.UInt32 Msg
,
    System.Int16  wParam
,
    System.Int32  lParam
) ;

public static System.Int32
SendMessage
(
    System.IntPtr  Window
,
    WindowsMessage Message
)
{
    return ( API_SendMessage
    (
        Window
    ,
        (System.UInt32) Message
    ,
        0
    ,
        0
    ) ) ;
}


C#
System.IntPtr hTemp ;

if ( ( hTemp = PIEBALD.Lib.LibApi.FindWindow ( k.Caption ) ) != System.IntPtr.Zero )
{
    PIEBALD.Lib.LibApi.SetActiveWindow ( hTemp ) ;

    System.IntPtr hok   ;

    if ( ( hok = PIEBALD.Lib.LibApi.FindWindowEx ( hTemp , k.Press ) ) != System.IntPtr.Zero )
    {
        PIEBALD.Lib.LibApi.SendMessage ( hok , PIEBALD.Lib.LibApi.WindowsMessage.WM_LBUTTONDOWN ) ;
        PIEBALD.Lib.LibApi.SendMessage ( hok , PIEBALD.Lib.LibApi.WindowsMessage.WM_LBUTTONUP   ) ;
    }
}
 
Share this answer
 
Comments
Jackie Lloyd 18-Nov-22 10:37am    
Thank you, this looks like an interesting and useful solution, I am still digesting!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900