如何以自动方式将OLEObject的内容保存为文件?

Par*_*ris 7 .net c# powerpoint vsto

我在powerpoint中为幻灯片添加了一些不同的文件类型.这些类型包括mp4,zip,swf和其他格式.我不是想找回一种播放这些文件类型的方法; 但是,我想在一个powerpoint中存储和检索文件.

我通过执行以下操作成功存储了这些不同的文件类型:

currentSlide.Shapes.AddOLEObject(0, 0, -1, -1, "", this.filePath);
Run Code Online (Sandbox Code Playgroud)

我也可以通过右键单击对象 - >选择编辑包 - >文件 - >保存内容来手动检索它们.

我希望复制或使用此功能将OLEObject的内容保存回其原始状态和我指定的路径.我有办法找到那个形状,我认为这个对象包含了内容:slideShape.OLEFormat.Object我只是不知道现在该做什么.想法?谢谢.

哦,我正在使用Office 2010,如果这有任何区别.

Par*_*ris 3

所以,我知道现在已经晚了;不过,我知道其他人一定也有类似的问题。

\n\n

我就这个问题联系了微软,他们花了大约一个月的时间,但他们终于给了我答案。我有一个解决方案的压缩包。它相当广泛,请查看下面的简单源代码。

\n\n

首先是一些说明:

\n\n

1) 创建 PowerPoint 演示文稿并在其中嵌入一些文件(视频、mp3、zip 等)
\n2) 将文件保存到以下位置 C:\\Temp\\Temp.pptx
\n3) 关闭文件
\n4) 创建\xe2\x80\x9cC:\\Temp\xe2\x80\x9d
\n5) 打开应用程序并运行它。

\n\n

所以唯一的缺点是 PPTX 文件必须关闭。话虽如此,人们也许能够将打开的 PPTX 文件复制到其他位置,然后从该位置提取文件,而不是实际正在处理的 PPTX。然后把临时的删除就可以了。我们会看到。这已经是该解决方案最接近的结果了。

\n\n

无需进一步告别:

\n\n
using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing System.IO.Packaging;\nusing System.Runtime.InteropServices;\nusing System.IO;\n\nnamespace ExtractOLEPowerPoint\n{\nclass Program\n{\n\n    #region IEnumSTATSTG\n    [ComImport]\n    [Guid("0000000d-0000-0000-C000-000000000046")]\n    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n    public interface IEnumSTATSTG\n    {\n        // The user needs to allocate an STATSTG array whose size is celt.\n        [PreserveSig]\n        uint Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] System.Runtime.InteropServices.ComTypes.STATSTG[] rgelt, out uint pceltFetched);\n\n        void Skip(uint celt);\n\n        void Reset();\n\n        [return: MarshalAs(UnmanagedType.Interface)]\n        IEnumSTATSTG Clone();\n    }\n    #endregion\n\n    //#region IStream\n\n    //[ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n    //public interface IStream\n    //{\n    //    void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbRead);\n    //    void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbWritten);\n    //    void Seek(long dlibMove, uint dwOrigin, out long plibNewPosition);\n    //    void SetSize(long libNewSize);\n    //    void CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten);\n    //    void Commit(uint grfCommitFlags);\n    //    void Revert();\n    //    void LockRegion(long libOffset, long cb, uint dwLockType);\n    //    void UnlockRegion(long libOffset, long cb, uint dwLockType);\n    //    void Stat(out STATSTG pstatstg, uint grfStatFlag);\n    //    void Clone(out IStream ppstm);\n    //}\n\n    //#endregion\n\n    #region STATFLAG\n\n    [Flags]\n    public enum STATFLAG : uint\n    {\n        STATFLAG_DEFAULT = 0,\n        STATFLAG_NONAME = 1,\n        STATFLAG_NOOPEN = 2\n    }\n\n    #endregion\n\n    #region IStorage\n    [ComImport]\n    [Guid("0000000b-0000-0000-C000-000000000046")]\n    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n    interface IStorage\n    {\n        void CreateStream(\n            /* [string][in] */ string pwcsName,\n            /* [in] */ uint grfMode,\n            /* [in] */ uint reserved1,\n            /* [in] */ uint reserved2,\n            /* [out] */ out System.Runtime.InteropServices.ComTypes.IStream ppstm);\n        void OpenStream(\n            /* [string][in] */ string pwcsName,\n            /* [unique][in] */ IntPtr reserved1,\n            /* [in] */ uint grfMode,\n            /* [in] */ uint reserved2,\n            /* [out] */ out System.Runtime.InteropServices.ComTypes.IStream ppstm);\n\n        void CreateStorage(\n            /* [string][in] */ string pwcsName,\n            /* [in] */ uint grfMode,\n            /* [in] */ uint reserved1,\n            /* [in] */ uint reserved2,\n            /* [out] */ out IStorage ppstg);\n\n        void OpenStorage(\n            /* [string][unique][in] */ string pwcsName,\n            /* [unique][in] */ IStorage pstgPriority,\n            /* [in] */ uint grfMode,\n            /* [unique][in] */ IntPtr snbExclude,\n            /* [in] */ uint reserved,\n            /* [out] */ out IStorage ppstg);\n\n        void CopyTo(\n            /* [in] */ uint ciidExclude,\n            /* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array?\n            /* [unique][in] */ IntPtr snbExclude,\n            /* [unique][in] */ IStorage pstgDest);\n\n        void MoveElementTo(\n            /* [string][in] */ string pwcsName,\n            /* [unique][in] */ IStorage pstgDest,\n            /* [string][in] */ string pwcsNewName,\n            /* [in] */ uint grfFlags);\n\n        void Commit(\n            /* [in] */ uint grfCommitFlags);\n\n        void Revert();\n\n        void EnumElements(\n            /* [in] */ uint reserved1,\n            /* [size_is][unique][in] */ IntPtr reserved2,\n            /* [in] */ uint reserved3,\n            /* [out] */ out IEnumSTATSTG ppenum);\n\n        void DestroyElement(\n            /* [string][in] */ string pwcsName);\n\n        void RenameElement(\n            /* [string][in] */ string pwcsOldName,\n            /* [string][in] */ string pwcsNewName);\n\n        void SetElementTimes(\n            /* [string][unique][in] */ string pwcsName,\n            /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pctime,\n            /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME patime,\n            /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pmtime);\n\n        void SetClass(\n            /* [in] */ Guid clsid);\n\n        void SetStateBits(\n            /* [in] */ uint grfStateBits,\n            /* [in] */ uint grfMask);\n\n        void Stat(\n            /* [out] */ out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg,\n            /* [in] */ uint grfStatFlag);\n    }\n\n    #endregion\n\n    #region STGM\n    [Flags]\n    public enum STGM : int\n    {\n        DIRECT           = 0x00000000,\n        TRANSACTED       = 0x00010000,\n        SIMPLE           = 0x08000000,\n        READ             = 0x00000000,\n        WRITE            = 0x00000001,\n        READWRITE        = 0x00000002,\n        SHARE_DENY_NONE  = 0x00000040,\n        SHARE_DENY_READ  = 0x00000030,\n        SHARE_DENY_WRITE = 0x00000020,\n        SHARE_EXCLUSIVE  = 0x00000010,\n        PRIORITY         = 0x00040000,\n        DELETEONRELEASE  = 0x04000000,\n        NOSCRATCH        = 0x00100000,\n        CREATE           = 0x00001000,\n        CONVERT          = 0x00020000,\n        FAILIFTHERE      = 0x00000000,\n        NOSNAPSHOT       = 0x00200000,\n        DIRECT_SWMR      = 0x00400000,\n    }\n\n    #endregion\n\n    #region StgIsStorageFile\n\n    [DllImport("Ole32.dll")]\n    static extern int StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)]string filename);\n\n    #endregion\n\n    #region StgOpenStorage\n\n    [DllImport("Ole32.dll")]\n    static extern int StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)]string pwcsName, IStorage pstgPriority, STGM grfmode, IntPtr snbExclude, uint researved, out IStorage ppstgOpen);\n\n    #endregion\n\n    static void Main(string[] args)\n    {\n        Package pkg = Package.Open("C:\\\\Temp\\\\Temp.pptx");\n        foreach (PackagePart pkgprt in pkg.GetParts())\n        {\n            if(pkgprt.Uri.ToString().StartsWith("/ppt/embeddings/"))\n            {\n                System.IO.Stream strm = pkgprt.GetStream();\n                byte[] buffer = new byte[strm.Length];\n                strm.Read(buffer, 0, (int)strm.Length);\n                strm.Close();\n\n                // Create a temporary file\n                string targetFile = "C:\\\\Temp\\\\GeneratedFiles\\\\" + pkgprt.Uri.ToString().Remove(0, "/ppt/embeddings/".Length);\n                System.IO.File.WriteAllBytes(targetFile, buffer);\n\n                // Extract the contents.\n                IStorage Is;\n                StgOpenStorage(targetFile, null, STGM.READWRITE | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out Is);\n                ProcessPackage(Is);\n\n                // Need to release the IStorage object and call GC.Collect() to free the object\n                Marshal.ReleaseComObject(Is);\n                Is = null;\n                GC.Collect();\n                GC.WaitForPendingFinalizers();\n\n                // Delete the temporary binary file extracted\n                File.Delete(targetFile);\n            }\n        }\n    }\n    static void ProcessPackage(IStorage pStg)\n    {\n        System.Runtime.InteropServices.ComTypes.IStream pStream;\n        IEnumSTATSTG pEnumStatStg;\n        uint numReturned;\n        pStg.EnumElements(0, IntPtr.Zero, 0, out pEnumStatStg);\n        System.Runtime.InteropServices.ComTypes.STATSTG[] ss = new System.Runtime.InteropServices.ComTypes.STATSTG[1];\n        // Loop through the STATSTG structures in the storage.\n        do\n        {\n            // Retrieve the STATSTG structure\n            pEnumStatStg.Next(1, ss, out numReturned);\n            if (numReturned != 0)\n            {\n                //System.Runtime.InteropServices.ComTypes.STATSTG statstm;\n                byte[] bytT = new byte[4];\n                // Check if the pwcsName contains "Ole10Native" stream which contain the actual embedded object\n                if (ss[0].pwcsName.Contains("Ole10Native") == true)\n                {\n                    // Get the stream objectOpen the stream\n                    pStg.OpenStream(ss[0].pwcsName, IntPtr.Zero, (uint)STGM.READ | (uint)STGM.SHARE_EXCLUSIVE, 0, out pStream);\n                    //pStream.Stat(out statstm, (int) STATFLAG.STATFLAG_DEFAULT);\n\n                    IntPtr position = IntPtr.Zero;\n                    // File name starts from 7th Byte.\n                    // Position the cursor to the 7th Byte.\n                    pStream.Seek(6, 0, position);\n\n                    IntPtr ulRead = new IntPtr();\n                    char[] filename = new char[260];\n                    int i;\n\n                    // Read the File name of the embedded object\n                    for (i = 0; i < 260; i++)\n                    {\n                        pStream.Read(bytT, 1, ulRead);\n                        pStream.Seek(0, 1, position);\n                        filename[i] = (char)bytT[0];\n                        if (bytT[0] == 0)\n                        {\n                            break;\n                        }\n                    }\n                    string path = new string(filename, 0, i);\n\n                    // Next part is the source path of the embedded object.\n                    // Length is unknown. Hence, loop through each byte to read the 0 terminated string\n                    // Read the source path.\n                    for (i = 0; i < 260; i++)\n                    {\n                        pStream.Read(bytT, 1, ulRead);\n                        pStream.Seek(0, 1, position);\n                        filename[i] = (char)bytT[0];\n                        if (bytT[0] == 0)\n                        {\n                            break;\n                        }\n                    }\n                    // Source File path\n                    string fullpath = new string(filename, 0, i);\n\n                    // Unknown 4 bytes\n                    pStream.Seek(4, 1, position);\n\n                    // Next 4 byte gives the length of the temporary file path \n                    // (Office uses a temporary location to copy the files before inserting to the document)\n                    // The length is in little endian format. Hence conversion is needed\n                    pStream.Read(bytT, 4, ulRead);\n                    ulong dwSize, dwTemp;\n                    dwSize = 0;\n                    dwTemp = (ulong)bytT[3];\n                    dwSize += (ulong)(bytT[3] << 24);\n                    dwSize += (ulong)(bytT[2] << 16);\n                    dwSize += (ulong)(bytT[1] << 8);\n                    dwSize += bytT[0];\n\n                    // Skip the temporary file path\n                    pStream.Seek((long)dwSize, 1, position);\n\n                    // Next four bytes gives the size of the actual data in little endian format.\n                    // Convert the format.\n                    pStream.Read(bytT, 4, ulRead);\n                    dwTemp = 0;\n                    dwSize = 0;\n                    dwTemp = (ulong)bytT[3];\n                    dwSize += (ulong)(bytT[3] << 24);\n                    dwSize += (ulong)(bytT[2] << 16);\n                    dwSize += (ulong)(bytT[1] << 8);\n                    dwSize += (ulong)bytT[0];\n\n                    // Read the actual file content \n                    byte[] byData = new byte[dwSize];\n                    pStream.Read(byData, (int)dwSize, ulRead);\n\n                    // Create the file\n                    System.IO.BinaryWriter bWriter = new System.IO.BinaryWriter(System.IO.File.Open("C:\\\\temp\\\\GeneratedFiles\\\\" + path, System.IO.FileMode.Create));\n                    bWriter.Write(byData);\n                    bWriter.Close();\n                }\n            }\n        }\n        while (numReturned > 0);\n    }\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n