2011-02-07 73 views
5

我想在.NET庫中使用ImageMagick COM對象(ImageMagickObject)。該庫旨在從IronRuby中調用,但這並不重要。我想採用這種方法,因爲它適合於我現有的調用,它將當前調用ImageMagick二進制文件作爲外部進程。 COM對象將採用與二進制文件相同的參數,但會保存進程創建,整體速度大約快5倍。重定向STDERR從.NET中的COM對象包裝器輸出

我唯一的障礙是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。

EDITS:爲了清晰有關Streamwriter刷新/關閉以及IronRuby如何使用示例。

回答

0

你試過處理(或沖洗)作家和流?它可能死於緩衝區。使用塊可能會有幫助。

using(filestream = new FileStream("output.txt", FileMode.Create)) 
    using(streamwriter = new StreamWriter(filestream)) 
    { 

... }

+0

我試過在調用Compose之前和之後顯式清空緩衝區,但沒有運氣。 – cgyDeveloper 2011-02-07 20:29:06

0

看起來.Handle已被棄用,你有沒有試過.SafeFileHandle.DangerousGetHandle()呢?

編號:http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.dangerousgethandle.aspx

(另外:你能確認你關閉StreamWriter的數據已經寫入之後一樣,如果你把它移動到應用程序關閉之前,看看數據使得其出路何在? ?)

+0

關於關閉Streamwriter的積極態度。我也嘗試了兩種處理方法,因爲VS給了我棄用警告(他們似乎是等價的)。 – cgyDeveloper 2011-02-10 16:41:26

1

添加debug選項後,我終於在文件中獲得了一些文本。

這是你期待的結果嗎?如果是這樣,請參閱compare命令行工具的debug選項。

請注意,如果您嘗試直接或間接使用上述屬性記錄任何內容,則將Console.ErrorConsole.Out設置爲streamwriter會導致異常。

如果您確實需要設置這些屬性,請將它們設置爲另一個實例StreamWriter。如果您不需要它們,請忽略對Console.SetOutConsole.SetError的呼叫。

我也注意到,一旦創建了ImageMagickObject.MagickImage實例,就不可能重定向標準錯誤。如果標準錯誤重定向需要撤消或執行多次,請嘗試在另一個應用程序域中執行代碼。

+0

比較肯定寫入STDERR。如果我拿出SetStdHandle調用,它將每次都寫入STDERR。有了這些調用,它永遠不會(也不會寫入文件)。 – cgyDeveloper 2011-02-14 16:01:30

+0

這並不意味着要從命令行運行,所以解決方案將無效。它需要作爲圖書館電話提供。 – cgyDeveloper 2011-02-14 16:03:04

0

根據文檔「FileShare.Read是沒有FileShare參數的那些FileStream構造函數的默認值」......也許可以幫助將FileAccess.Read,FileAccess.Write,FileShare.Read和FileShare.Write設置爲on在FileStream c-tor中?

我沒有ImageMagick exe來玩...如果你可以發佈鏈接,它會很棒。