Rob*_*vey 11 c# powershell imapi
首先,对术语进行一些澄清.通过敲定,我并不是指关闭会话; 我的意思是写一个CD或DVD的引出方式,以便不再通过常用手段(Roxio,Nero,Windows资源管理器等)添加信息.
我对此做了大量的研究.有一些开源程序,如InfraRecorder,我们可以从中吸取一些灵感,但它们似乎都涉及使用IMAPI相当精细的C++代码,这似乎是一种非常低级的做事方式.我们都没有C++或IMAPI专业知识来支持这样的代码库.
互联网上最有前途的资源似乎就是这个,但似乎并没有包含最终化功能.这是"编写图像"的代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
代码的关键部分似乎是这样的:
discFormatData = new MsftDiscFormat2Data
{
Recorder = recorder,
ClientName = ClientName,
ForceMediaToBeClosed = finalize // <-- Here
};
Run Code Online (Sandbox Code Playgroud)
但这不是最终确定的功能; 它是将实际数据刻录到磁盘上的功能.您是否必须实际创建新会话以在现有磁盘上执行最终化?
Cy *_*nol 11
控制IMAPI在下次写入后是否完成光盘的ForceMediaToBeClosed属性:IDiscFormat2Data
设置为VARIANT_TRUE以将光盘标记为已关闭,以在下一个写入会话结束时禁止其他写入.
Image Mastering API不提供专门用于完成光盘的抽象,因此我们需要执行写操作.如果我们打开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
}
Run Code Online (Sandbox Code Playgroud)
这会设置一些我们将在下面用来刻录光盘的样板.我们需要添加错误处理和功能检测以供实际使用,但它可以作为演示工作正常.如果我们将此代码粘贴或点源到PowerShell会话中,我们可以交互式地使用COM对象.
在这一点上,如果我们检查空白或打开光盘的状态,我们应该看到的值2,4或6对应于"空白"或"追加"位掩码(6列举的两个)IMAPI_FORMAT2_DATA_MEDIA_STATE.
PS> $disc.CurrentMediaStatus # 4 for an open, multi-session disc
Run Code Online (Sandbox Code Playgroud)
然后,我们可以添加一些文件.如果我们只想关闭多会话光盘,我们不需要向图像添加任何内容.API使用空数据轨道记录会话的引入和引出.
PS> $image.Root.AddTree('path\to\root\folder', $false)
Run Code Online (Sandbox Code Playgroud)
最后,我们将更改刻录到光盘.因为我们设置$disc.ForceMediaToBeClosed为$true,此操作最终确定光盘,并且不允许进一步的写操作:
PS> $disc.Write($image.CreateResultImage().ImageStream)
Run Code Online (Sandbox Code Playgroud)
如果我们现在检查光盘状态,它应该表明光盘不可写:
PS> $disc.CurrentMediaStatus # 16384 or 40960
Run Code Online (Sandbox Code Playgroud)
对于单会话光盘,我们应该看到16384(0x4000,"最终确定").我的系统报告40960封闭的多会话光盘,其中包含位0x2000("写保护")和0x8000("不支持的媒体").我们可能需要弹出或重新启动某些硬件才能在刻录后查看准确的值.
备注:
通常,多会话光盘上的每个会话都以引入线开始,以引出线结束.当我们敲定光盘时,上一次会话的导入将永久关闭媒体以进一步写入.这就是为什么即使我们没有更多数据需要添加,我们也需要在未封闭的光盘上追加一个额外的会话.
如果可用空间低于2%,IMAPI将自动完成光盘.
InfraRecorder--问题中提到的工具 - 不使用IMAPI.此应用程序为cdrtools提供了一个直接控制设备IO 的前端.如果我们只需要完成未封闭的光盘,我们可能希望使用此软件包附带的cdrecord CLI程序,以避免维护额外的代码库:
PS> cdrecord -scanbus # Show <drive> IDs to choose from
PS> cdrecord -fix dev=<drive> # Close an open session
Run Code Online (Sandbox Code Playgroud)
作为一个简短的起点,这里是我们如何最终确定多会话光盘:
PS> $session = cdrecord -msinfo dev=<drive>
PS> mkisofs -rJ -C $session -M <drive> 'path\to\root' | cdrecord dev=<drive> -
Run Code Online (Sandbox Code Playgroud)
这与使用IMAPI的PowerShell脚本实现了相同的结果:我们导入上一个会话,创建映像,然后刻录一个新的会话,最终确定光盘.通过省略cdrecord的-multi参数,该命令不会以允许继续多会话光盘的方式写入引入.
虽然我们通常在类Unix系统上看到此工具集,但构建可用于Windows.
对于更高级的应用程序,我们可以使用较低级别的实现IDiscRecorderEx来查询并向记录设备发送命令.
ForceMediaToBeClosed在IMAPI2.MsftDiscFormat2Data对象上设置标志,并在启用关闭标志的情况下写出光盘.
方法在这里描述:https://social.msdn.microsoft.com/Forums/en-US/ce1ff136-39a1-4442-bc5c-61c119b6f4f2/finalize-question?for==windowsopticalplatform#2e968a94-7347-4d94-9332-00fe7cd0ba89
下面是一个很好的Powershell刻录脚本的链接,当你准备好结束写入时,你所要做的就是更新Out-CD一个新param设置$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 ;
Run Code Online (Sandbox Code Playgroud)