Я пытаюсь использовать COM-объект ImageMagick (ImageMagickObject) в библиотеке .NET. Эта библиотека предназначена для вызова из IronRuby, но это не так уж важно. Я хочу использовать этот подход, потому что он будет соответствовать моим существующим вызовам, которые в настоящее время вызывают двоичные файлы ImageMagick как внешние процессы. COM-объект будет принимать те же аргументы, что и двоичные файлы, но сохранит процесс создания и будет примерно в 5 раз быстрее.
Мое единственное препятствие заключается в том, что метод «Сравнить» для COM-объекта возвращает свой результат в STDERR. Это также проблема с двоичным файлом, но это легко передать обратно в STDOUT, где я и ожидал. С COM-объектом я получаю свои результаты из возвращаемых значений функции.
Как я могу перенаправить результат из «Сравнить» в строковый буфер или даже файл вместо STDERR?
Я попробовал следующее, что не позволяет выводу достигнуть STDERR, но не записывает в файл, как ожидалось:
using ImageMagickObject;
...
public class ImageMagickCOM
{
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern int SetStdHandle(int device, IntPtr handle);
private const int STDOUT_HANDLE = -11;
private const int STDERR_HANDLE = -12;
private ImageMagickObject.MagickImage magickImage = null;
private FileStream filestream = null;
private StreamWriter streamwriter = null;
public ImageMagickCOM()
{
IntPtr handle;
int status;
filestream = new FileStream("output.txt", FileMode.Create);
streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
//handle = filestream.Handle; // deprecated
handle = filestream.SafeFileHandle.DangerousGetHandle(); // replaces filestream.handle
status = SetStdHandle(STDOUT_HANDLE, handle);
status = SetStdHandle(STDERR_HANDLE, handle);
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
magickImage = new ImageMagickObject.MagickImage();
}
public string Compare()
{
object[] args = new object[] { "-metric", "AE", "-fuzz", "10%", "imageA.jpg", "imageB.jpg", "diff.png" };
return (string)this.magickImage.Compare(ref args);
}
public void Close()
{
if (this.magickImage != null)
{
Marshal.ReleaseComObject(magickImage);
this.magickImage = null;
}
if (this.streamwriter != null)
{
this.streamwriter.Flush();
this.streamwriter.Close();
this.streamwriter = null;
this.filestream = null;
}
}
}
Кажется, только действие «Сравнить» использует STDERR для отправки результата (в качестве индикатора успеха используется возвращаемое значение). Все остальные методы (определение, преобразование, Mogrify и т. Д.) Работают так, как вы ожидаете.
Для справки, его называют примерно так (из IronRuby):
require 'ImagingLib.dll'
im = ImagingLib::ImageMagickCOM.new
im.compare # returns nil
im.close
И output.txt создан, но пуст. Ничего не печатается в STDOUT или STDERR.
РЕДАКТИРОВАТЬ: для ясности относительно смыва / закрытия потокового устройства и того, как образец используется из IronRuby.