因此,我知道现在有点晚了;但是,我知道其他人一定也有类似的问题。
我联系了微软关于这个问题,他们花了大约一个月左右的时间,但最终给了我一个答案。我有一个
解决方案的压缩包。它相当详尽,下面可以看到纯源代码。
首先是一些说明:
1)创建一个 PowerPoint 演示文稿并嵌入一些文件(视频、mp3、zip 等)
2)将文件保存到以下位置:C:\Temp\Temp.pptx
3)关闭文件
4)在“C:\Temp”下创建一个名为“GeneratedFiles”的文件夹
5)打开应用程序并运行它。
所以唯一的缺点就是 PPTX 文件必须关闭。话虽如此,人们可能能够将打开的 PPTX 文件复制到其他地方,然后从该位置提取文件,而不是从实际正在使用的 PPTX 中提取。然后只需删除临时文件即可。我们会看到的。这就是这个解决方案所能达到的最接近的程度。
没有更多的拖延:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Packaging;
using System.Runtime.InteropServices;
using System.IO;
namespace ExtractOLEPowerPoint
{
class Program
{
#region IEnumSTATSTG
[ComImport]
[Guid("0000000d-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATSTG
{
[PreserveSig]
uint Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] System.Runtime.InteropServices.ComTypes.STATSTG[] rgelt, out uint pceltFetched);
void Skip(uint celt);
void Reset();
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSTATSTG Clone();
}
#endregion
#region STATFLAG
[Flags]
public enum STATFLAG : uint
{
STATFLAG_DEFAULT = 0,
STATFLAG_NONAME = 1,
STATFLAG_NOOPEN = 2
}
#endregion
#region IStorage
[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IStorage
{
void CreateStream(
string pwcsName,
uint grfMode,
uint reserved1,
uint reserved2,
out System.Runtime.InteropServices.ComTypes.IStream ppstm);
void OpenStream(
string pwcsName,
IntPtr reserved1,
uint grfMode,
uint reserved2,
out System.Runtime.InteropServices.ComTypes.IStream ppstm);
void CreateStorage(
string pwcsName,
uint grfMode,
uint reserved1,
uint reserved2,
out IStorage ppstg);
void OpenStorage(
string pwcsName,
IStorage pstgPriority,
uint grfMode,
IntPtr snbExclude,
uint reserved,
out IStorage ppstg);
void CopyTo(
uint ciidExclude,
Guid rgiidExclude, // should this be an array?
IntPtr snbExclude,
IStorage pstgDest);
void MoveElementTo(
string pwcsName,
IStorage pstgDest,
string pwcsNewName,
uint grfFlags);
void Commit(
uint grfCommitFlags);
void Revert();
void EnumElements(
uint reserved1,
IntPtr reserved2,
uint reserved3,
out IEnumSTATSTG ppenum);
void DestroyElement(
string pwcsName);
void RenameElement(
string pwcsOldName,
string pwcsNewName);
void SetElementTimes(
string pwcsName,
System.Runtime.InteropServices.ComTypes.FILETIME pctime,
System.Runtime.InteropServices.ComTypes.FILETIME patime,
System.Runtime.InteropServices.ComTypes.FILETIME pmtime);
void SetClass(
Guid clsid);
void SetStateBits(
uint grfStateBits,
uint grfMask);
void Stat(
out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg,
uint grfStatFlag);
}
#endregion
#region STGM
[Flags]
public enum STGM : int
{
DIRECT = 0x00000000,
TRANSACTED = 0x00010000,
SIMPLE = 0x08000000,
READ = 0x00000000,
WRITE = 0x00000001,
READWRITE = 0x00000002,
SHARE_DENY_NONE = 0x00000040,
SHARE_DENY_READ = 0x00000030,
SHARE_DENY_WRITE = 0x00000020,
SHARE_EXCLUSIVE = 0x00000010,
PRIORITY = 0x00040000,
DELETEONRELEASE = 0x04000000,
NOSCRATCH = 0x00100000,
CREATE = 0x00001000,
CONVERT = 0x00020000,
FAILIFTHERE = 0x00000000,
NOSNAPSHOT = 0x00200000,
DIRECT_SWMR = 0x00400000,
}
#endregion
#region StgIsStorageFile
[DllImport("Ole32.dll")]
static extern int StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)]string filename);
#endregion
#region StgOpenStorage
[DllImport("Ole32.dll")]
static extern int StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)]string pwcsName, IStorage pstgPriority, STGM grfmode, IntPtr snbExclude, uint researved, out IStorage ppstgOpen);
#endregion
static void Main(string[] args)
{
Package pkg = Package.Open("C:\\Temp\\Temp.pptx");
foreach (PackagePart pkgprt in pkg.GetParts())
{
if(pkgprt.Uri.ToString().StartsWith("/ppt/embeddings/"))
{
System.IO.Stream strm = pkgprt.GetStream();
byte[] buffer = new byte[strm.Length];
strm.Read(buffer, 0, (int)strm.Length);
strm.Close();
string targetFile = "C:\\Temp\\GeneratedFiles\\" + pkgprt.Uri.ToString().Remove(0, "/ppt/embeddings/".Length);
System.IO.File.WriteAllBytes(targetFile, buffer);
IStorage Is;
StgOpenStorage(targetFile, null, STGM.READWRITE | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out Is);
ProcessPackage(Is);
Marshal.ReleaseComObject(Is);
Is = null;
GC.Collect();
GC.WaitForPendingFinalizers();
File.Delete(targetFile);
}
}
}
static void ProcessPackage(IStorage pStg)
{
System.Runtime.InteropServices.ComTypes.IStream pStream;
IEnumSTATSTG pEnumStatStg;
uint numReturned;
pStg.EnumElements(0, IntPtr.Zero, 0, out pEnumStatStg);
System.Runtime.InteropServices.ComTypes.STATSTG[] ss = new System.Runtime.InteropServices.ComTypes.STATSTG[1];
do
{
pEnumStatStg.Next(1, ss, out numReturned);
if (numReturned != 0)
{
byte[] bytT = new byte[4];
if (ss[0].pwcsName.Contains("Ole10Native") == true)
{
pStg.OpenStream(ss[0].pwcsName, IntPtr.Zero, (uint)STGM.READ | (uint)STGM.SHARE_EXCLUSIVE, 0, out pStream);
IntPtr position = IntPtr.Zero;
pStream.Seek(6, 0, position);
IntPtr ulRead = new IntPtr();
char[] filename = new char[260];
int i;
for (i = 0; i < 260; i++)
{
pStream.Read(bytT, 1, ulRead);
pStream.Seek(0, 1, position);
filename[i] = (char)bytT[0];
if (bytT[0] == 0)
{
break;
}
}
string path = new string(filename, 0, i);
for (i = 0; i < 260; i++)
{
pStream.Read(bytT, 1, ulRead);
pStream.Seek(0, 1, position);
filename[i] = (char)bytT[0];
if (bytT[0] == 0)
{
break;
}
}
string fullpath = new string(filename, 0, i);
pStream.Seek(4, 1, position);
pStream.Read(bytT, 4, ulRead);
ulong dwSize, dwTemp;
dwSize = 0;
dwTemp = (ulong)bytT[3];
dwSize += (ulong)(bytT[3] << 24);
dwSize += (ulong)(bytT[2] << 16);
dwSize += (ulong)(bytT[1] << 8);
dwSize += bytT[0];
pStream.Seek((long)dwSize, 1, position);
pStream.Read(bytT, 4, ulRead);
dwTemp = 0;
dwSize = 0;
dwTemp = (ulong)bytT[3];
dwSize += (ulong)(bytT[3] << 24);
dwSize += (ulong)(bytT[2] << 16);
dwSize += (ulong)(bytT[1] << 8);
dwSize += (ulong)bytT[0];
byte[] byData = new byte[dwSize];
pStream.Read(byData, (int)dwSize, ulRead);
System.IO.BinaryWriter bWriter = new System.IO.BinaryWriter(System.IO.File.Open("C:\\temp\\GeneratedFiles\\" + path, System.IO.FileMode.Create));
bWriter.Write(byData);
bWriter.Close();
}
}
}
while (numReturned > 0);
}
}
}