diff --git a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
index 54c0307c..d8ee355a 100644
--- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
+++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
@@ -233,6 +233,39 @@ namespace SabreTools.Serialization.Wrappers
return set;
}
+ ///
+ /// Open the numbered cabinet set volume
+ ///
+ /// Filename pattern for matching cabinet files
+ /// Volume ID, 1-indexed
+ /// Wrapper representing the volume on success, null otherwise
+ public static InstallShieldCabinet? OpenVolume(string? pattern, ushort volumeId)
+ {
+ // Normalize the volume ID for odd cases
+ if (volumeId == ushort.MinValue || volumeId == ushort.MaxValue)
+ volumeId = 1;
+
+ // Try to open the file as a stream
+ var volumeStream = OpenFileForReading(pattern, volumeId, CABINET_SUFFIX);
+ if (volumeStream == null)
+ {
+ Console.Error.WriteLine($"Failed to open input cabinet file {volumeId}");
+ return null;
+ }
+
+ // Try to parse the stream into a cabinet
+ var volume = Create(volumeStream);
+ if (volume == null)
+ {
+ Console.Error.WriteLine($"Failed to open input cabinet file {volumeId}");
+ return null;
+ }
+
+ // Set the volume ID and return
+ volume.VolumeID = volumeId;
+ return volume;
+ }
+
///
/// Open a cabinet file for reading
///