ManagedWimgApi
ManagedWimgApi copied to clipboard
handling cancellation during ApplyImage
hi
When creating an image I can handle cancel button and abort the process
But for ApplyImage I cannot get it to work, and even if I click Stop Debugging in Visual Studio it freezes up the system until I reboot or disconnect drive I am writing too
You'll need your progress callback to return WimMessageResult.Abort
like this unit test. Depending on your application, you'll need to implement IDisposable
which should get called when your process is killed.
Hi Jeff I have spent hours today using that exact unit test as an example and I just can't get it to work - had no problems with handling it for capture, it seems apply is different?
Okay, using example you posted here = https://github.com/jeffkl/ManagedWimgApi/wiki/Message-Callbacks
I did the same as I did for capture and added
case WimMessageType.QueryAbort
Return WimMessageResult.Abort
but unlike for "capture" - it seems QueryAbort never gets called for "apply"
so instead I tried it under case WinMessageType.Process just as a test and at least here it does then Return WimMessageResult.Abort
I then catch the "OperationCanceledException" which now fires - but even using your example it doesn't stop the "applying" of the image, it just locks up the whole interface and Visual Studio gives following error if I click stop debugging
System.ComponentModel.Win32Exception: 'The process cannot access the file because it is being used by another process'
System.ComponentModel.Win32Exception HResult=0x80004005 Message=The process cannot access the file because it is being used by another process Source=Microsoft.Wim StackTrace: at Microsoft.Wim.WimHandle.ReleaseHandle() at System.Runtime.InteropServices.SafeHandle.InternalFinalize() at System.Runtime.InteropServices.SafeHandle.Finalize()
nothing will then bring system back to life unless I unplug drive I am writing too, or wait for it to finish the "apply"
I wrote a simple console application with cancellation and it appears to work with my simple test image. Debugging in Visual Studio worked if I stopped it as well.
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Wim;
namespace ConsoleApplication
{
internal static class Program
{
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
public static int Main(string[] args)
{
Console.CancelKeyPress += (sender, eventArgs) =>
{
Console.WriteLine("Cancelling...");
CancellationTokenSource.Cancel();
eventArgs.Cancel = true;
};
string wimPath = "test.wim";
string applyPath = Directory.CreateDirectory("wimapply").FullName;
using (WimHandle wimHandle = WimgApi.CreateFile(wimPath, WimFileAccess.Read, WimCreationDisposition.OpenExisting, WimCreateFileOptions.None, WimCompressionType.None))
{
WimgApi.SetTemporaryPath(wimHandle, Path.GetTempPath());
WimMessageResult MessageCallback(WimMessageType messageType, object message, object userData)
{
if (CancellationTokenSource.IsCancellationRequested)
{
Console.WriteLine("Aborting...");
return WimMessageResult.Abort;
}
Console.WriteLine("Sleeping...");
try
{
Task.Delay(1000, CancellationTokenSource.Token).Wait();
}
catch (TaskCanceledException)
{
}
return WimMessageResult.Done;
}
WimgApi.RegisterMessageCallback(wimHandle, MessageCallback);
try
{
using (WimHandle imageHandle = WimgApi.LoadImage(wimHandle, 1))
{
WimHandle imageHandleCopy = imageHandle;
try
{
Console.WriteLine("Applying...");
WimgApi.ApplyImage(imageHandleCopy, applyPath, WimApplyImageOptions.DisableDirectoryAcl | WimApplyImageOptions.DisableFileAcl | WimApplyImageOptions.Index);
Console.WriteLine("Applied");
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled");
return 1;
}
}
}
finally
{
WimgApi.UnregisterMessageCallback(wimHandle, MessageCallback);
}
return 0;
}
}
}
}
Result
D:\ManagedWimgApi\src\ConsoleApplication\bin\Debug> ConsoleApplication.exe
Applying...
Sleeping...
Sleeping...
Cancelling...
Aborting...
Cancelled
If a particular file is very large I don't think the message callback would be called until later.
Hi Jeff
Thank you very much for the example which helped me prove that my interpretation of how to do it was correct
It turns out the problem is not the cancellation aspect, it is to do with destinations
In your example the destination is a folder on an internal hard drive I assume
Whereas during testing I was writing to a drive connected via USB
If I run your code it works fine as is, but if I change destination to be a external USB drive then I get same problem as reported
Can confirm from much more testing that problem is when writing (applying) to external USB devices, as even when you cancel API it still locks the drive causing app to hang in debugger or also explorer to hang as well - will find way of prompting or ejecting USB device to prevent this in future - problem doesn't occur when writing to internal drives
I'll try to find some time to test it out and see if there's anything I can get to work in regards to cancellation