簡體   English   中英

是否有一種相對簡單的方法來在 C# 或 PowerShell 中完成 CD 或 DVD?

[英]Is there a relatively straightforward way to finalize a CD or DVD in C# or PowerShell?

首先,一些術語的澄清。 完成,我的意思不是關閉會話; 我的意思是將導引寫入 CD 或 DVD,這樣信息就不能再通過通常的方式(Roxio、Nero、Windows 資源管理器等)添加到其中

我對此進行了大量研究。 有一些像InfraRecorder這樣的開源程序,我們可以從中汲取一些靈感,但它們似乎都涉及使用 IMAPI 的大量 C++ 代碼,這似乎是一種非常低級的做事方式。 我們團隊中的所有開發人員都不具備支持此類代碼庫的 C++ 或 IMAPI 專業知識。

互聯網上最有前途的資源似乎是this ,但它似乎不包含 finalize 功能。 這是“寫入圖像”的代碼:

public void WriteImage(BurnVerificationLevel verification, bool finalize, bool eject)
{
    if (!_recorderLoaded)
        throw new InvalidOperationException("LoadMedia must be called first.");

    MsftDiscRecorder2 recorder = null;
    MsftDiscFormat2Data discFormatData = null;

    try
    {
        recorder = new MsftDiscRecorder2();
        recorder.InitializeDiscRecorder(_recorders.SelectedItem.InternalUniqueId);

        discFormatData = new MsftDiscFormat2Data
        {
            Recorder = recorder,
            ClientName = ClientName,
            ForceMediaToBeClosed = finalize
        };

        //
        // Set the verification level
        //
        var burnVerification = (IBurnVerification)discFormatData;
        burnVerification.BurnVerificationLevel = IMAPI_BURN_VERIFICATION_LEVEL.IMAPI_BURN_VERIFICATION_NONE;

        //
        // Check if media is blank, (for RW media)
        //
        object[] multisessionInterfaces = null;
        if (!discFormatData.MediaHeuristicallyBlank)
            multisessionInterfaces = discFormatData.MultisessionInterfaces;

        //
        // Create the file system
        //
        IStream fileSystem;
        _CreateImage(recorder, multisessionInterfaces, out fileSystem);

        discFormatData.Update += _discFormatWrite_Update;

        //
        // Write the data
        //
        try
        {
            discFormatData.Write(fileSystem);
        }
        finally
        {
            if (fileSystem != null) Marshal.FinalReleaseComObject(fileSystem);                    
        }

        discFormatData.Update -= _discFormatWrite_Update;

        if (eject) recorder.EjectMedia();
    }
    finally
    {
        _isWriting = false;
        if (discFormatData != null) Marshal.ReleaseComObject(discFormatData);
        if (recorder != null) Marshal.ReleaseComObject(recorder);                
    }
}

代碼的關鍵部分似乎是這樣的:

discFormatData = new MsftDiscFormat2Data
{
    Recorder = recorder,
    ClientName = ClientName,
    ForceMediaToBeClosed = finalize // <-- Here
};

但這不是一個 finalize 函數; 它是一種將實際數據刻錄到磁盤上的功能。 您是否必須實際創建一個新會話才能在現有磁盤上執行終結?

ForceMediaToBeClosed財產IDiscFormat2Data 控制是否將IMAPI定型盤下一個寫操作后:

設置為 VARIANT_TRUE 以將磁盤標記為關閉以在下一個寫入會話結束時禁止額外寫入。

Image Mastering API 沒有提供專門用於定型光盤的抽象,因此我們需要執行寫入操作。 如果我們使用主映像ForceMediaToBeClosed器打開ForceMediaToBeClosed ,API 將在初始刻錄期間完成一張空白光盤。 對於現有的多會話光盤,我們需要附加另一個會話。

這是一個簡單的 PowerShell 示例,我們可以嘗試使用它,因此我們不需要構建項目。 這些概念在 C# 中是相似的:

$drives = New-Object -ComObject 'IMAPI2.MsftDiscMaster2'
$recorder = New-Object -ComObject 'IMAPI2.MsftDiscRecorder2'
$recorder.InitializeDiscRecorder($drives[0])  # Choose a drive here

$disc = New-Object -ComObject 'IMAPI2.MsftDiscFormat2Data'
$disc.ClientName = 'PowerShell Recorder'
$disc.Recorder = $recorder
$disc.ForceMediaToBeClosed = $true  # Finalize the next session

$image = New-Object -ComObject 'IMAPI2FS.MsftFileSystemImage'

if (!$disc.IsCurrentMediaSupported($recorder)) {
    throw 'Disc is not writeable.'
} elseif ($disc.MediaHeuristicallyBlank) {
    $image.ChooseImageDefaults($recorder)
} else {
    $image.MultisessionInterfaces = $disc.MultisessionInterfaces
    $image.ImportFileSystem() > $null
}

這將設置一些樣板,我們將在下面使用它們來刻錄光盤。 我們需要為實際使用添加錯誤處理和功能檢測,但它作為演示工作正常。 如果我們將此代碼粘貼或點源到 PowerShell 會話中,我們就可以交互地使用 COM 對象。

在這一點上,如果我們檢查空白或開放光盤的狀態,我們應該看到的值24 ,或6 ,其對應於“空白”或“追加”位掩碼( 6列舉對兩者) IMAPI_FORMAT2_DATA_MEDIA_STATE

PS> $disc.CurrentMediaStatus  # 4 for an open, multi-session disc 

然后,我們可以添加一些文件。 如果我們只想關閉多會話光盤,我們不需要向圖像添加任何內容。 API 使用空數據軌道記錄會話的導入和導出。

PS> $image.Root.AddTree('path\to\root\folder', $false)

最后,我們將更改刻錄到光盤上。 因為我們將$disc.ForceMediaToBeClosed設置$disc.ForceMediaToBeClosed $true ,此操作完成了磁盤,並且不允許進一步的寫入操作:

PS> $disc.Write($image.CreateResultImage().ImageStream)

如果我們現在檢查光盤狀態,應該表明該光盤不可寫:

PS> $disc.CurrentMediaStatus  # 16384 or 40960

對於單會話光盤,我們應該看到16384 ( 0x4000 ,“已完成”)。 對於包含位0x2000 (“寫保護”)和0x8000 (“不受支持的媒體”)的封閉式多會話光盤,我的系統報告40960 我們可能需要彈出或重啟某些硬件才能看到刻錄后的准確值。

評論:

  • 通常,多區段光盤上的每個區段以導入開始並以導出結束。 當我們完成光盤時,最后一個會話的導入將永久關閉媒體以進一步寫入。 這就是為什么即使我們沒有更多數據要添加,我們也需要將附加會話附加到未關閉的磁盤。

  • 如果可用空間低於 2%,IMAPI 將自動終結光盤。

  • InfraRecorder(問題中提到的工具)不使用 IMAPI。 此應用程序為cdrtools提供了一個前端,它直接控制設備 IO。 CLI program included with this package to avoid maintaining an extra codebase:如果我們只需要完成未封閉的光盤,我們可能需要使用此包中包含的 CLI 程序來避免維護額外的代碼庫:

     PS> cdrecord -scanbus # Show <drive> IDs to choose from PS> cdrecord -fix dev=<drive> # Close an open session

    作為一個簡短的起點,以下是我們如何完成多區段光盤:

     PS> $session = cdrecord -msinfo dev=<drive> PS> mkisofs -rJ -C $session -M <drive> 'path\\to\\root' | cdrecord dev=<drive> -

    這實現了與使用 IMAPI 的 PowerShell 腳本相同的結果:我們導入最后一個會話,創建映像,然后刻錄一個新會話來完成光盤。 , the command won't write the lead-in in a way that allows for continuation of a multi-session disc.通過省略-multi參數,該命令不會以允許連續多會話光盤的方式寫入導入。

    雖然我們通常在類 Unix 系統上看到此工具集,但構建可用於 Windows。

  • 對於更高級的應用程序,我們可以使用較低級別的IDiscRecorderEx來查詢並向記錄設備發送命令。

IMAPI2.MsftDiscFormat2Data對象上設置ForceMediaToBeClosed標志,並在啟用關閉標志的情況下寫出光盤。

  • 如果您已經知道它的最后一個會話,請設置標志,添加要寫入的數據,然后將其寫出,它就會關閉。
  • 如果您已經編寫了最后一個會話,請導入最后一個會話,設置標志並寫入關閉。

方法在這里描述: https : //social.msdn.microsoft.com/Forums/en-US/ce1ff136-39a1-4442-bc5c-61c119b6f4f2/finalize-question?forum=windowsopticalplatform#2e968a94-7347-4d94-ba09322

下面是一個很好的 Powershell 刻錄腳本的鏈接,當您准備好結束寫入時,您所要做的就是使用新param更新Out-CD以設置$DiscFormatData.ForceMediaToBeClosed = true

鏈接: https : //www.adamtheautomator.com/use-powershell-to-automate-burning-cds/

供參考:

# this fetches all the properties (as you probably already know)
$DiscFormatData  = New-Object -com IMAPI2.MsftDiscFormat2Data ;
$DiscFormatData | Get-Member ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM