In my MainWindow
I have a button that can be used to open a Process
(native OpenProcess
call) and perform some checks on it's memory, but the method called on Click
is asynchronous:
<Button Content="Attach" Click="OnClickAttach"/>
private async void OnClickAttach(Object sender, RoutedEventArgs e)
{
AttachmentResult result = await m_ViewModel.Attach();
switch (result)
// Different MessageBox depending on the result.
}
Now, let's see the ViewModel
portion of code...
// MemoryProcess class is just a wrapper for Process' handle and memory regions.
private MemoryProcess m_MemoryProcess;
public async Task<AttachmentResult> Attach()
{
AttachmentResult result = AttachmentResult.Success;
MemoryProcess memoryProcess = NativeMethods.OpenProcess(m_SelectedBrowserInstance.Process);
if (memoryProcess == null)
result = AttachmentResult.FailProcessNotOpened;
else
{
Boolean check1 = false;
Boolean check2 = false;
foreach (MemoryRegion region in memoryProcess)
{
// I perform checks on Process' memory regions and I eventually change the value of check1 or check2...
await Task.Delay(1);
}
if (!check1 && !check2)
{
NativeMethods.CloseHandle(memoryProcess.Handle);
result = AttachmentResult.FailProcessNotValid;
}
else
{
// I keep the Process opened for further use. I save it to a private variable.
m_MemoryProcess = memoryProcess;
m_MemoryProcess.Check1 = check1;
m_MemoryProcess.Check2 = check2;
}
}
return result;
}
Now... here comes the problem. When the user closes the application, if a Process
is opened, I must properly close its handle. So in my MainWindow
I have the following code:
protected override void OnClosing(CancelEventArgs e)
{
m_ViewModel.Detach();
base.OnClosing(e);
}
And in my ViewModel
I have the following code:
public void Detach()
{
if (m_MemoryProcess != null)
{
if (m_MemoryProcess.Check1)
// Do something...
if (m_MemoryProcess.Check2)
// Do something...
NativeMethods.CloseHandle(m_MemoryProcess.Handle);
m_MemoryProcess = null;
}
}
The Attach()
method can take very long time, more than 2 minutes sometimes. I need to find a solution for the following issues:
- If the user closes the application while
Attach()
method is running and beforememoryProcess
is saved to the private variable, theProcess
handle will not be closed. - If I save the MemoryProcess instance to the private variable just at the beginning of the
Attach()
method, there is a risk for the user to get aNullReferenceException
if he closes the application while theAttach()
method is processing its foreach loop. - I absolutely don't want to make the user wait for
Attach()
method to complete before letting him close the application. That's horrible.
How can I do this?
IMO, if you do not explicitly and specifically target to create separate detached/independent processes like, for example, through:
using
or maintaining child process alive upon app closing by launching them through separate shell scripts or other processes remaining to run after app closing;
CreateRemoteThread
or finding already run independently processes, you don't need to and probably should not "close" or dispose spawned by app processes. Windows (operting system) will close any unclosed spawned by app processes.
Also, I believe that it is impossible to execute any code in an application once it has started exiting or being closed.
PS (off-topic comment):
I do not even see that you close (really one should kill) or dispose your processes in your code...