2012-01-24 15 views
6

Tôi đang thêm một vài loại tệp khác nhau vào trang trình bày trong powerpoint. Các loại này bao gồm mp4, zip, swf và các định dạng khác. Tôi không tìm cách để phát các loại tệp này; tuy nhiên, tôi muốn lưu trữ và lấy các tập tin từ bên trong một preso powerpoint.Làm cách nào để lưu nội dung của OLEObject dưới dạng tệp tự động?

Tôi đã được lưu trữ thành công các loại tập tin khác nhau bằng cách làm như sau:

currentSlide.Shapes.AddOLEObject(0, 0, -1, -1, "", this.filePath); 

Tôi cũng có thể lấy chúng bằng tay bằng cách bấm chuột phải vào Object -> Chọn Chỉnh sửa Package -> File -> Save Content.

Tôi đang tìm cách sao chép hoặc sử dụng chức năng này để lưu nội dung của OLEObject về trạng thái ban đầu và đến đường dẫn mà tôi chỉ định. Tôi có một cách để tìm hình dạng đó và tôi nghĩ rằng đối tượng này có chứa các nội dung: slideShape.OLEFormat.Object Tôi chỉ không biết phải làm gì bây giờ. Ý tưởng? Cảm ơn.

Ồ tôi đang sử dụng văn phòng năm 2010, nếu điều đó tạo ra bất kỳ sự khác biệt nào.

+0

Vì bạn đang sử dụng Office 2010, nó là an toàn để giả định rằng chiếu của bạn là một PPTX? –

+0

Vâng, nó là một pptx – Parris

+0

Tôi không nghĩ rằng bạn có thể lấy trực tiếp từ trình bày và hình dạng trong bộ nhớ của Powerpoint, vì OLEFormat của Powerpoint là lỗi (ngay cả trong COM/Tự động thuần túy, không chỉ với .NET) khi đối tượng là gói/lưu trữ như một Gói (điều cũ OLE 1 từ 20 năm trước). Bạn có thể lấy nó từ tập tin, không phải từ bộ nhớ không? –

Trả lời

2

Vì vậy, tôi biết điều này là muộn; tuy nhiên, tôi biết những người khác phải có những câu hỏi tương tự.

Tôi đã liên hệ với Microsoft về vấn đề này và mất khoảng một tháng hoặc lâu hơn, nhưng cuối cùng họ cũng có câu trả lời cho tôi. Tôi có một số zip of the solution. Nó khá rộng, nhìn bên dưới chỉ với mã nguồn đơn giản.

Đầu tiên một số hướng dẫn:

1) Tạo một bài thuyết trình PowerPoint và nhúng một số tập tin trong nó (Video, mp3, zip vv)
2) Lưu tập tin vào thư mục C: \ Temp \ Temp. pptx
3) Đóng tệp
4) Tạo thư mục “GeneratedFiles” trong “C: \ Temp”
5) Mở ứng dụng và chạy nó.

Do đó, nhược điểm duy nhất là tệp PPTX phải được đóng. Điều đó đang được nói, người ta có thể có thể sao chép các tập tin PPTX mở ở nơi khác và sau đó trích xuất các tập tin từ vị trí đó chứ không phải là PPTX mà thực sự đang được làm việc trên. Sau đó, chỉ cần xóa tạm thời. Chúng ta sẽ thấy. Điều này là gần như giải pháp này được mặc dù.

Without adieu thêm:

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 
    { 
     // The user needs to allocate an STATSTG array whose size is celt. 
     [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 IStream 

    //[ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    //public interface IStream 
    //{ 
    // void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbRead); 
    // void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbWritten); 
    // void Seek(long dlibMove, uint dwOrigin, out long plibNewPosition); 
    // void SetSize(long libNewSize); 
    // void CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten); 
    // void Commit(uint grfCommitFlags); 
    // void Revert(); 
    // void LockRegion(long libOffset, long cb, uint dwLockType); 
    // void UnlockRegion(long libOffset, long cb, uint dwLockType); 
    // void Stat(out STATSTG pstatstg, uint grfStatFlag); 
    // void Clone(out IStream ppstm); 
    //} 

    //#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][in] */ string pwcsName, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved1, 
      /* [in] */ uint reserved2, 
      /* [out] */ out System.Runtime.InteropServices.ComTypes.IStream ppstm); 
     void OpenStream(
      /* [string][in] */ string pwcsName, 
      /* [unique][in] */ IntPtr reserved1, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved2, 
      /* [out] */ out System.Runtime.InteropServices.ComTypes.IStream ppstm); 

     void CreateStorage(
      /* [string][in] */ string pwcsName, 
      /* [in] */ uint grfMode, 
      /* [in] */ uint reserved1, 
      /* [in] */ uint reserved2, 
      /* [out] */ out IStorage ppstg); 

     void OpenStorage(
      /* [string][unique][in] */ string pwcsName, 
      /* [unique][in] */ IStorage pstgPriority, 
      /* [in] */ uint grfMode, 
      /* [unique][in] */ IntPtr snbExclude, 
      /* [in] */ uint reserved, 
      /* [out] */ out IStorage ppstg); 

     void CopyTo(
      /* [in] */ uint ciidExclude, 
      /* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array? 
      /* [unique][in] */ IntPtr snbExclude, 
      /* [unique][in] */ IStorage pstgDest); 

     void MoveElementTo(
      /* [string][in] */ string pwcsName, 
      /* [unique][in] */ IStorage pstgDest, 
      /* [string][in] */ string pwcsNewName, 
      /* [in] */ uint grfFlags); 

     void Commit(
      /* [in] */ uint grfCommitFlags); 

     void Revert(); 

     void EnumElements(
      /* [in] */ uint reserved1, 
      /* [size_is][unique][in] */ IntPtr reserved2, 
      /* [in] */ uint reserved3, 
      /* [out] */ out IEnumSTATSTG ppenum); 

     void DestroyElement(
      /* [string][in] */ string pwcsName); 

     void RenameElement(
      /* [string][in] */ string pwcsOldName, 
      /* [string][in] */ string pwcsNewName); 

     void SetElementTimes(
      /* [string][unique][in] */ string pwcsName, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME patime, 
      /* [unique][in] */ System.Runtime.InteropServices.ComTypes.FILETIME pmtime); 

     void SetClass(
      /* [in] */ Guid clsid); 

     void SetStateBits(
      /* [in] */ uint grfStateBits, 
      /* [in] */ uint grfMask); 

     void Stat(
      /* [out] */ out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, 
      /* [in] */ 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(); 

       // Create a temporary file 
       string targetFile = "C:\\Temp\\GeneratedFiles\\" + pkgprt.Uri.ToString().Remove(0, "/ppt/embeddings/".Length); 
       System.IO.File.WriteAllBytes(targetFile, buffer); 

       // Extract the contents. 
       IStorage Is; 
       StgOpenStorage(targetFile, null, STGM.READWRITE | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out Is); 
       ProcessPackage(Is); 

       // Need to release the IStorage object and call GC.Collect() to free the object 
       Marshal.ReleaseComObject(Is); 
       Is = null; 
       GC.Collect(); 
       GC.WaitForPendingFinalizers(); 

       // Delete the temporary binary file extracted 
       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]; 
     // Loop through the STATSTG structures in the storage. 
     do 
     { 
      // Retrieve the STATSTG structure 
      pEnumStatStg.Next(1, ss, out numReturned); 
      if (numReturned != 0) 
      { 
       //System.Runtime.InteropServices.ComTypes.STATSTG statstm; 
       byte[] bytT = new byte[4]; 
       // Check if the pwcsName contains "Ole10Native" stream which contain the actual embedded object 
       if (ss[0].pwcsName.Contains("Ole10Native") == true) 
       { 
        // Get the stream objectOpen the stream 
        pStg.OpenStream(ss[0].pwcsName, IntPtr.Zero, (uint)STGM.READ | (uint)STGM.SHARE_EXCLUSIVE, 0, out pStream); 
        //pStream.Stat(out statstm, (int) STATFLAG.STATFLAG_DEFAULT); 

        IntPtr position = IntPtr.Zero; 
        // File name starts from 7th Byte. 
        // Position the cursor to the 7th Byte. 
        pStream.Seek(6, 0, position); 

        IntPtr ulRead = new IntPtr(); 
        char[] filename = new char[260]; 
        int i; 

        // Read the File name of the embedded object 
        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); 

        // Next part is the source path of the embedded object. 
        // Length is unknown. Hence, loop through each byte to read the 0 terminated string 
        // Read the source path. 
        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; 
         } 
        } 
        // Source File path 
        string fullpath = new string(filename, 0, i); 

        // Unknown 4 bytes 
        pStream.Seek(4, 1, position); 

        // Next 4 byte gives the length of the temporary file path 
        // (Office uses a temporary location to copy the files before inserting to the document) 
        // The length is in little endian format. Hence conversion is needed 
        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]; 

        // Skip the temporary file path 
        pStream.Seek((long)dwSize, 1, position); 

        // Next four bytes gives the size of the actual data in little endian format. 
        // Convert the format. 
        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]; 

        // Read the actual file content 
        byte[] byData = new byte[dwSize]; 
        pStream.Read(byData, (int)dwSize, ulRead); 

        // Create the file 
        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); 
    } 
} 
} 
+0

Rất tuyệt vời !!! bạn đã cứu tôi rất nhiều đầu gãi !!! Cảm ơn!!!! –

1

Bạn có thể làm điều đó bằng cách gọi PowerShell từ .NET hoặc C#.

function Export-MediaFromPptx($pptxFile) 
{ 
    [void] [System.Reflection.Assembly]::LoadFrom("C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll") 
    $pkg = [System.IO.Packaging.Package]::Open($pptxFile) 

    $mediaDirectory = [System.IO.Path]::GetDirectoryName($pptxFile) + "\" + [System.IO.Path]::GetFileName($pptxFile) + "_media" 
    md $mediaDirectory | out-null 

    foreach ($mediaPart in ($pkg.GetParts() | where { $_.Uri.ToString().StartsWith("/ppt/media/") })) { 
     $sourceStream = $mediaPart.GetStream() 
     [byte[]]$buffer = new-object byte[] $sourceStream.Length 
     [void]$sourceStream.Read($buffer, 0, $sourceStream.Length) 
     $sourceStream.Close() 
     $targetFileName = $mediaDirectory + "\" + $mediaPart.Uri.ToString().Remove(0, "/ppt/media/".Length) 
     [System.IO.File]::WriteAllBytes($targetFileName, $buffer) 
    } 

    $pkg.Close() 
} 

Tập lệnh trên được lấy từ article này.

này article cho thấy làm thế nào để gọi nó từ .NET

article Điều này cho thấy làm thế nào để gọi nó là từ C#

Hope this helps.

+0

Điều này làm việc nhưng chiết xuất một tập tin định dạng OLE 1 (lưu trữ hợp chất) nếu đối tượng là một gói, vì vậy nó chỉ là một nửa của công việc. –

+0

Vậy điều gì sẽ xảy ra sau khi tôi trích xuất? – Parris

+0

Tôi nghĩ rằng điều này là thực sự chính xác, tôi nhận được sự giúp đỡ từ Microsoft hỗ trợ về việc chuyển đổi từ định dạng OLE 1 thành tiêu chuẩn. Hoặc là hoặc tôi đang cố gắng để họ đưa cho tôi một bản vá hoặc chỉ nói với tôi rằng điều đó là không thể. – Parris

2

Đối tượng slideShape.OLEFormat.Object phải hỗ trợ IPersistFile hoặc IPersistStream. Nếu có, bạn có thể dễ dàng làm cho nó ghi vào một tập tin mà bạn chọn. Để làm điều này, bạn cần sử dụng thư viện kiểu OLE để cho phép VB hiểu giao diện IPersistFile.

Tải OLELIB.TLB từ trang này, cài đặt nó, và thêm một tham chiếu đến PPTX của bạn:

Tài liệu cho IPersistFile::Save:

Ví dụ về số dặm:

Dim oPersist as IPersistFile 
Set oPersist = slideShape.OLEFormat.Object 
' Zero means save a copy as 
oPersist.Save(sFileName, 0) 
+0

Vấn đề gốc là OLEFormat.Object ném ngoại lệ khi đối tượng là một Gói. Không có gì bạn có thể làm về điều này, đây là một vấn đề cũ với việc thực hiện tự động hóa cơ bản. –

+0

Bạn có biết nếu tôi có thể sử dụng điều này cho C#? – Parris

+0

Tôi cần phải cung cấp cho ai đó các điểm. Tôi sẽ cung cấp cho bạn chúng. Chỉ vì điều này ngắn hơn và ngắn gọn hơn! Tôi cũng đã nghe về giải pháp này, nhưng không bao giờ tìm thấy bất kỳ mã nào. – Parris