zipアーカイブ内からクリップボードにファイルをコピーしてそのデータを処理した後のAccessViolationException

M.メルチャー

問題が発生しているので、ここの誰かが助けてくれることを願っています。

このOutlookDataObjectプロジェクトから多少変更されたコードを使用して、Outlookなどのさまざまなメールクライアントからドロップされたファイルと、クリップボードを介したファイルの一般的なコピー貼り付けを処理してファイルシステムに保存します。

ほとんどの場合は正常に機能しますが、ユーザーがWindowsエクスプローラーでZIPファイルを開き、そこからファイルをコピーして追加しようとすると、FileContentDataObjectのGetDataメソッドの次の部分でAccessViolationExceptionが発生します。

//marshal the unmanaged memory to to FILEGROUPDESCRIPTORW struct
object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORW));

これは、この問題を再現できるはずの問題のコード全体の縮小版です。

// Starting Method
public void InsertFromClipboard()
{ 
    FileContentDataObjectBase dataObject = GetDataObject();
    if(dataObject!= null)
    {
        dataObject.SaveToFileSystem("C:/temp");
    }
}

private FileContentDataObjectBase GetDataObject()
{
    var dataObject = System.Windows.Forms.Clipboard.GetDataObject();

    return new FileContentDataObject(System.Windows.Forms.Clipboard.GetDataObject());
}

public class FileContentDataObject : FileContentDataObjectBase
{
    /// <summary>
    /// Initializes a new instance of the <see cref="OutlookDataObject"/> class.
    /// </summary>
    /// <param name="underlyingDataObject">The underlying data object to wrap.</param>
    public FileContentDataObject(System.Windows.Forms.IDataObject underlyingDataObject)
        : base(underlyingDataObject) { }

    public override void SaveToFileSystem(string path)
    {
        string[] filenames;

        //get the names and data streams of the files dropped
        if (this.GetFormats().Contains("FileGroupDescriptor"))
            filenames = (string[])this.GetData("FileGroupDescriptor", true);
        else if (this.GetFormats().Contains("FileGroupDescriptorW"))
            filenames = (string[])this.GetData("FileGroupDescriptorW", true);
        else
            return;

        MemoryStream[] filestreams = (MemoryStream[])this.GetData("FileContents");

        SaveToFileSystem(filenames, filestreams, path);
     }

     public new object GetData(string format, bool autoConvert)
     {
         switch (format)
         {
            case "FileGroupDescriptorW":
                //override the default handling of FileGroupDescriptorW which returns a
                //MemoryStream and instead return a string array of file names
                IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
                try
                {
                    //use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
                    MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData("FileGroupDescriptorW");
                    byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];
                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    //copy the file group descriptor into unmanaged memory
                    fileGroupDescriptorWPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorWPointer, fileGroupDescriptorBytes.Length);

                    //marshal the unmanaged memory to to FILEGROUPDESCRIPTORW struct
                    object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORW));
                    NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;

                    //create a new array to store file names in of the number of items in the file group descriptor
                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    //get the pointer to the first file descriptor
                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));

                    //loop for the number of files acording to the file group descriptor
                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        //marshal the pointer top the file descriptor as a FILEDESCRIPTORW struct and get the file name
                        NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORW));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        //move the file descriptor pointer to the next file descriptor
                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    //return the array of filenames
                    return fileNames;
                }
                finally
                {
                    //free unmanaged memory pointer
                    Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
                }
        }

            //use underlying IDataObject to handle getting of data
            return this.underlyingDataObject.GetData(format, autoConvert);
        }
    }

    public abstract class FileContentDataObjectBase : System.Windows.Forms.IDataObject
    {
        #region NativeMethods

        protected class NativeMethods
        {
            [DllImport("kernel32.dll")]
            static extern IntPtr GlobalLock(IntPtr hMem);

            [DllImport("ole32.dll", PreserveSig = false)]
            internal static extern ILockBytes CreateILockBytesOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease);

            [DllImport("OLE32.DLL", CharSet = CharSet.Auto, PreserveSig = false)]
            internal static extern IntPtr GetHGlobalFromILockBytes(ILockBytes pLockBytes);

            [DllImport("OLE32.DLL", CharSet = CharSet.Unicode, PreserveSig = false)]
            internal static extern IStorage StgCreateDocfileOnILockBytes(ILockBytes plkbyt, uint grfMode, uint reserved);

            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000000B-0000-0000-C000-000000000046")]
            internal interface IStorage
            {
                [return: MarshalAs(UnmanagedType.Interface)]
                IStream CreateStream([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, [In, MarshalAs(UnmanagedType.U4)] int grfMode, [In, MarshalAs(UnmanagedType.U4)] int reserved1, [In, MarshalAs(UnmanagedType.U4)] int reserved2);
                [return: MarshalAs(UnmanagedType.Interface)]
                IStream OpenStream([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, IntPtr reserved1, [In, MarshalAs(UnmanagedType.U4)] int grfMode, [In, MarshalAs(UnmanagedType.U4)] int reserved2);
                [return: MarshalAs(UnmanagedType.Interface)]
                IStorage CreateStorage([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, [In, MarshalAs(UnmanagedType.U4)] int grfMode, [In, MarshalAs(UnmanagedType.U4)] int reserved1, [In, MarshalAs(UnmanagedType.U4)] int reserved2);
                [return: MarshalAs(UnmanagedType.Interface)]
                IStorage OpenStorage([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, IntPtr pstgPriority, [In, MarshalAs(UnmanagedType.U4)] int grfMode, IntPtr snbExclude, [In, MarshalAs(UnmanagedType.U4)] int reserved);
                void CopyTo(int ciidExclude, [In, MarshalAs(UnmanagedType.LPArray)] Guid[] pIIDExclude, IntPtr snbExclude, [In, MarshalAs(UnmanagedType.Interface)] IStorage stgDest);
                void MoveElementTo([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, [In, MarshalAs(UnmanagedType.Interface)] IStorage stgDest, [In, MarshalAs(UnmanagedType.BStr)] string pwcsNewName, [In, MarshalAs(UnmanagedType.U4)] int grfFlags);
                void Commit(int grfCommitFlags);
                void Revert();
                void EnumElements([In, MarshalAs(UnmanagedType.U4)] int reserved1, IntPtr reserved2, [In, MarshalAs(UnmanagedType.U4)] int reserved3, [MarshalAs(UnmanagedType.Interface)] out object ppVal);
                void DestroyElement([In, MarshalAs(UnmanagedType.BStr)] string pwcsName);
                void RenameElement([In, MarshalAs(UnmanagedType.BStr)] string pwcsOldName, [In, MarshalAs(UnmanagedType.BStr)] string pwcsNewName);
                void SetElementTimes([In, MarshalAs(UnmanagedType.BStr)] string pwcsName, [In] System.Runtime.InteropServices.ComTypes.FILETIME pctime, [In] System.Runtime.InteropServices.ComTypes.FILETIME patime, [In] System.Runtime.InteropServices.ComTypes.FILETIME pmtime);
                void SetClass([In] ref Guid clsid);
                void SetStateBits(int grfStateBits, int grfMask);
                void Stat([Out]out System.Runtime.InteropServices.ComTypes.STATSTG pStatStg, int grfStatFlag);
            }

            [ComImport, Guid("0000000A-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            internal interface ILockBytes
            {
                void ReadAt([In, MarshalAs(UnmanagedType.U8)] long ulOffset, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, [In, MarshalAs(UnmanagedType.U4)] int cb, [Out, MarshalAs(UnmanagedType.LPArray)] int[] pcbRead);
                void WriteAt([In, MarshalAs(UnmanagedType.U8)] long ulOffset, IntPtr pv, [In, MarshalAs(UnmanagedType.U4)] int cb, [Out, MarshalAs(UnmanagedType.LPArray)] int[] pcbWritten);
                void Flush();
                void SetSize([In, MarshalAs(UnmanagedType.U8)] long cb);
                void LockRegion([In, MarshalAs(UnmanagedType.U8)] long libOffset, [In, MarshalAs(UnmanagedType.U8)] long cb, [In, MarshalAs(UnmanagedType.U4)] int dwLockType);
                void UnlockRegion([In, MarshalAs(UnmanagedType.U8)] long libOffset, [In, MarshalAs(UnmanagedType.U8)] long cb, [In, MarshalAs(UnmanagedType.U4)] int dwLockType);
                void Stat([Out]out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, [In, MarshalAs(UnmanagedType.U4)] int grfStatFlag);
            }

            [StructLayout(LayoutKind.Sequential)]
            internal sealed class POINTL
            {
                public int x;
                public int y;
            }

            [StructLayout(LayoutKind.Sequential)]
            internal sealed class SIZEL
            {
                public int cx;
                public int cy;
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            internal sealed class FILEGROUPDESCRIPTORA
            {
                public uint cItems;
                public FILEDESCRIPTORA[] fgd;
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            internal sealed class FILEDESCRIPTORA
            {
                public uint dwFlags;
                public Guid clsid;
                public SIZEL sizel;
                public POINTL pointl;
                public uint dwFileAttributes;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
                public uint nFileSizeHigh;
                public uint nFileSizeLow;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
                public string cFileName;
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            internal sealed class FILEGROUPDESCRIPTORW
            {
                public uint cItems;
                public FILEDESCRIPTORW[] fgd;
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            internal sealed class FILEDESCRIPTORW
            {
                public uint dwFlags;
                public Guid clsid;
                public SIZEL sizel;
                public POINTL pointl;
                public uint dwFileAttributes;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
                public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
                public uint nFileSizeHigh;
                public uint nFileSizeLow;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
                public string cFileName;
            }
        }

        #endregion

        #region Property(s)

        /// <summary>
        /// Holds the <see cref="System.Windows.Forms.IDataObject"/> that this class is wrapping
        /// </summary>
        protected System.Windows.Forms.IDataObject underlyingDataObject;

        /// <summary>
        /// Holds the <see cref="System.Runtime.InteropServices.ComTypes.IDataObject"/> interface to the <see cref="System.Windows.Forms.IDataObject"/> that this class is wrapping.
        /// </summary>
        protected System.Runtime.InteropServices.ComTypes.IDataObject comUnderlyingDataObject;

        /// <summary>
        /// Holds the internal ole <see cref="System.Windows.Forms.IDataObject"/> to the <see cref="System.Windows.Forms.IDataObject"/> that this class is wrapping.
        /// </summary>
        protected System.Windows.Forms.IDataObject oleUnderlyingDataObject;

        /// <summary>
        /// Holds the <see cref="MethodInfo"/> of the "GetDataFromHGLOBLAL" method of the internal ole <see cref="System.Windows.Forms.IDataObject"/>.
        /// </summary>
        protected MethodInfo getDataFromHGLOBLALMethod;

        #endregion

        #region Constructor(s)

        /// <summary>
        /// Initializes a new instance of the <see cref="OutlookDataObject"/> class.
        /// </summary>
        /// <param name="underlyingDataObject">The underlying data object to wrap.</param>
        public FileContentDataObjectBase(System.Windows.Forms.IDataObject underlyingDataObject)
        {
            //get the underlying dataobject and its ComType IDataObject interface to it
            this.underlyingDataObject = underlyingDataObject;
            this.comUnderlyingDataObject = (System.Runtime.InteropServices.ComTypes.IDataObject)this.underlyingDataObject;

            //get the internal ole dataobject and its GetDataFromHGLOBLAL so it can be called later
            FieldInfo innerDataField = this.underlyingDataObject.GetType().GetField("innerData", BindingFlags.NonPublic | BindingFlags.Instance);
            this.oleUnderlyingDataObject = (System.Windows.Forms.IDataObject)innerDataField.GetValue(this.underlyingDataObject);
            this.getDataFromHGLOBLALMethod = this.oleUnderlyingDataObject.GetType().GetMethod("GetDataFromHGLOBLAL", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        #endregion

        #region IDataObject Members

        /// <summary>
        /// Retrieves the data associated with the specified class type format.
        /// </summary>
        /// <param name="format">A <see cref="T:System.Type"></see> representing the format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param>
        /// <returns>
        /// The data associated with the specified format, or null.
        /// </returns>
        public object GetData(Type format)
        {
            return this.GetData(format.FullName);
        }

        /// <summary>
        /// Retrieves the data associated with the specified data format.
        /// </summary>
        /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param>
        /// <returns>
        /// The data associated with the specified format, or null.
        /// </returns>
        public object GetData(string format)
        {
            return this.GetData(format, true);
        }

        /// <summary>
        /// Retrieves the data associated with the specified data format, using a Boolean to determine whether to convert the data to the format.
        /// </summary>
        /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param>
        /// <param name="autoConvert">true to convert the data to the specified format; otherwise, false.</param>
        /// <returns>
        /// The data associated with the specified format, or null.
        /// </returns>
        public object GetData(string format, bool autoConvert)
        {
            return this.underlyingDataObject.GetData(format, autoConvert);
        }

        /// <summary>
        /// Retrieves the data associated with the specified data format at the specified index.
        /// </summary>
        /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param>
        /// <param name="index">The index of the data to retrieve.</param>
        /// <returns>
        /// A <see cref="MemoryStream"/> containing the raw data for the specified data format at the specified index.
        /// </returns>
        public MemoryStream GetData(string format, int index)
        {
            //create a FORMATETC struct to request the data with
            FORMATETC formatetc = new FORMATETC();
            formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id;
            formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT;
            formatetc.lindex = index;
            formatetc.ptd = new IntPtr(0);
            formatetc.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL;

            //create STGMEDIUM to output request results into
            STGMEDIUM medium = new STGMEDIUM();

            //using the Com IDataObject interface get the data using the defined FORMATETC
            this.comUnderlyingDataObject.GetData(ref formatetc, out medium);

            //retrieve the data depending on the returned store type
            switch (medium.tymed)
            {
                case TYMED.TYMED_ISTORAGE:
                    //to handle a IStorage it needs to be written into a second unmanaged
                    //memory mapped storage and then the data can be read from memory into
                    //a managed byte and returned as a MemoryStream

                    NativeMethods.IStorage iStorage = null;
                    NativeMethods.IStorage iStorage2 = null;
                    NativeMethods.ILockBytes iLockBytes = null;
                    System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat;
                    try
                    {
                        //marshal the returned pointer to a IStorage object
                        iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember);
                        Marshal.Release(medium.unionmember);

                        //create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store
                        iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                        iStorage2 = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                        //copy the returned IStorage into the new IStorage
                        iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
                        iLockBytes.Flush();
                        iStorage2.Commit(0);

                        //get the STATSTG of the ILockBytes to determine how many bytes were written to it
                        iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                        iLockBytes.Stat(out iLockBytesStat, 1);
                        int iLockBytesSize = (int)iLockBytesStat.cbSize;

                        //read the data from the ILockBytes (unmanaged byte array) into a managed byte array
                        byte[] iLockBytesContent = new byte[iLockBytesSize];
                        iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null);

                        //wrapped the managed byte array into a memory stream and return it
                        return new MemoryStream(iLockBytesContent);
                    }
                    finally
                    {
                        //release all unmanaged objects
                        Marshal.ReleaseComObject(iStorage2);
                        Marshal.ReleaseComObject(iLockBytes);
                        Marshal.ReleaseComObject(iStorage);
                    }

                case TYMED.TYMED_ISTREAM:
                    //to handle a IStream it needs to be read into a managed byte and
                    //returned as a MemoryStream

                    IStream iStream = null;
                    System.Runtime.InteropServices.ComTypes.STATSTG iStreamStat;
                    try
                    {
                        //marshal the returned pointer to a IStream object
                        iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember);
                        Marshal.Release(medium.unionmember);

                        //get the STATSTG of the IStream to determine how many bytes are in it
                        iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                        iStream.Stat(out iStreamStat, 0);
                        int iStreamSize = (int)iStreamStat.cbSize;

                        //read the data from the IStream into a managed byte array
                        byte[] iStreamContent = new byte[iStreamSize];
                        iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero);

                        //wrapped the managed byte array into a memory stream and return it
                        return new MemoryStream(iStreamContent);
                    }
                    finally
                    {
                        //release all unmanaged objects
                        Marshal.ReleaseComObject(iStream);
                    }

                case TYMED.TYMED_HGLOBAL:
                    //to handle a HGlobal the exisitng "GetDataFromHGLOBLAL" method is invoked via
                    //reflection

                    return (MemoryStream)this.getDataFromHGLOBLALMethod.Invoke(this.oleUnderlyingDataObject, new object[] { DataFormats.GetFormat((short)formatetc.cfFormat).Name, medium.unionmember });
            }

            return null;
        }

        /// <summary>
        /// Returns a list of all formats that data stored in this instance is associated with or can be converted to.
        /// </summary>
        /// <returns>
        /// An array of the names that represents a list of all formats that are supported by the data stored in this object.
        /// </returns>
        public string[] GetFormats()
        {
            return this.underlyingDataObject.GetFormats();
        }

        /// <summary>
        /// Gets a list of all formats that data stored in this instance is associated with or can be converted to, using a Boolean value to determine whether to retrieve all formats that the data can be converted to or only native data formats.
        /// </summary>
        /// <param name="autoConvert">true to retrieve all formats that data stored in this instance is associated with or can be converted to; false to retrieve only native data formats.</param>
        /// <returns>
        /// An array of the names that represents a list of all formats that are supported by the data stored in this object.
        /// </returns>
        public string[] GetFormats(bool autoConvert)
        {
            return this.underlyingDataObject.GetFormats(autoConvert);
        }

        #endregion

        #region methods

        public static void SaveToFileSystem(string[] filenames, MemoryStream[] filestreams, string path)
        {

            for (int fileIndex = 0; fileIndex < filenames.Length; fileIndex++)
            {
                try
                {
                    //use the fileindex to get the name and data stream
                    string filename = filenames[fileIndex];
                    MemoryStream filestream = filestreams[fileIndex];

                    //save the file stream using its name to the application path
                    FileStream outputStream = File.Create(Path.Combine(path, GetStrippedFileName(filename)));
                    filestream.WriteTo(outputStream);
                    outputStream.Close();
                }
                catch (IOException ex)
                {
                    throw new Exception(ex.Message, ex);
                }
                catch (SecurityException ex)
                {
                    throw new Exception(ex.Message, ex);
                }
            }

        }

        public static void SaveToFileSystem(FileContentDataObjectBase dataObject, string path)
        {
            dataObject.SaveToFileSystem(path);
        }

        public abstract void SaveToFileSystem(string path);

        private static string GetStrippedFileName(string input)
        {
            foreach (var chr in Path.GetInvalidFileNameChars())
                input = input.Replace(chr.ToString(), String.Empty);
            return input;
        }

        #endregion

}

なぜそれが起こるのか、そしてどうすれば問題を解決できるのかを理解したいと思います。

どんな助けや洞察も歓迎します。

前もって感謝します。

M.メルチャー

かなりの時間を探した後、この有益なコメントのおかげでようやく問題を見つけました

使用した元のコードのFILEGROUPDESCRIPTORA宣言とFILEGROUPDESCRIPTORW宣言が間違っていることが判明したため、場合によってはAccessViolation例外が発生する可能性があります。

だから私はから説明されたコメンターのような宣言を変更しました...

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEGROUPDESCRIPTORA
{
    public uint cItems;
    public FILEDESCRIPTORA[] fgd;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public sealed class FILEGROUPDESCRIPTORW
{
    public uint cItems;
    public FILEDESCRIPTORW[] fgd;
}

に...

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEGROUPDESCRIPTORA
{
    public uint cItems;
    public FILEDESCRIPTORA fgd;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public sealed class FILEGROUPDESCRIPTORW
{
    public uint cItems;
    public FILEDESCRIPTORW fgd;
}

その後、AccessViolation Exceptionsはなくなり、質問でリンクした元のコードをもう少し変更するだけで機能しました。

クリップボードファイルの「FileContents」形式の処理中に、2つのFILEGROUPDESCRIPTORの正しいものが毎回使用されていることを確認するために、いくつかのチェックを追加する必要がありましたが、今では完全に機能します。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Puppeteerを使用してファイルをWebサイトにアップロードするためのダイアログボックスの処理

分類Dev

Http POSTリクエストを介してAndroidからファイルやその他のデータをアップロードする

分類Dev

フォルダとサブフォルダ/ファイルを繰り返し処理し、スプレッドシートデータをアーカイブシートにコピーします

分類Dev

AutoHotKey:アクティブなフォルダ内のファイルの数を数えてクリップボードにコピーする方法は?

分類Dev

ファイルがGoogleドライブにアップロードされたとき、そのイベント(呼び出しスクリプト)をどのように処理しますか?

分類Dev

Nodejs ExpressMulterファイルのアップロード-フォームデータに基づいてルート内の応答を処理します

分類Dev

指定されたディレクトリからファイル情報を取得し、Nファイルを処理してサーバーに同時にかつ順番にアップロードします

分類Dev

Azure BLOBからExcelファイルをダウンロードし、ファイルをローカルディレクトリに保存せずにそのデータを処理します

分類Dev

ファイルの内容をWSLからWindowsにクリップボードにコピーしますか?

分類Dev

変数からのデータをXMLファイルに保存し、プログラムの再起動後にそれをコード化したい

分類Dev

FTPサーバーからCSVファイルをダウンロードしてローカルに保存し、アップロードを処理します

分類Dev

Rails 4とペーパークリップ-:originalスタイルのファイルのアップロードを停止して、S3リモートディレクトリからコピーします

分類Dev

sshを介してリモートマシンのファイルからローカルクリップボードにファイルの内容をコピーする方法

分類Dev

「送信先...」を使用してファイルをFTPにアップロードし、そのURLをクリップボードにコピーします

分類Dev

特定の形式のファイルを破棄しながら、zipアーカイブを再帰的に処理してファイルを抽出します

分類Dev

ANTを使用して、ローカルディレクトリからマップされたドライブにファイルをコピーします

分類Dev

最後の「コピー」をクリップボードからファイルに保存

分類Dev

arcpyクリップ管理を使用してファイル内の複数のラスターを処理するためのforループを作成します

分類Dev

データベースSQLサーバーから特定のテーブルをバックアップし、vb.netコードを使用して.bakファイルをコンピューターに保存する方法

分類Dev

そのポップアップボックスのルックアンドフィールを変更する(コンピューターからファイルを選択するために開くウィンドウ)

分類Dev

スクリプトディレクトリからすべてのユーザーのデスクトップにファイルをコピーします

分類Dev

ファイルをバッチ処理してサブフォルダー内の.tsファイルを見つけ、それらをディレクトリに移動しますか?

分類Dev

クリップボードからの同じコピーを使用してクリップボードの内容を処理し、フォームに入力するようにブックマークレットを修正します

分類Dev

フィルター処理されたデータの範囲をコピーしてExcelVBAの新しいワークシートに貼り付ける方法(クリップボードを使用せずに)

分類Dev

7-Zipを使用してアーカイブ内のファイルパーミッションとシンボリックリンクを保持する

分類Dev

ワイルドカード文字を使用して、あるドッカー ボリュームから別のドッカー ボリュームにすべてのファイルをコピーしますか?

分類Dev

FlaskからPILイメージのコピーを作成した後にバイトが欠落している-データをアップロードする

分類Dev

スプレッドシートスクリプト:ボタンをアクティブにし、セルからシートにデータをコピーしてから、データの範囲をクリアします

分類Dev

ZIPをパイプ処理し、アーカイブ内に使用可能なファイル名を含める方法

Related 関連記事

  1. 1

    Puppeteerを使用してファイルをWebサイトにアップロードするためのダイアログボックスの処理

  2. 2

    Http POSTリクエストを介してAndroidからファイルやその他のデータをアップロードする

  3. 3

    フォルダとサブフォルダ/ファイルを繰り返し処理し、スプレッドシートデータをアーカイブシートにコピーします

  4. 4

    AutoHotKey:アクティブなフォルダ内のファイルの数を数えてクリップボードにコピーする方法は?

  5. 5

    ファイルがGoogleドライブにアップロードされたとき、そのイベント(呼び出しスクリプト)をどのように処理しますか?

  6. 6

    Nodejs ExpressMulterファイルのアップロード-フォームデータに基づいてルート内の応答を処理します

  7. 7

    指定されたディレクトリからファイル情報を取得し、Nファイルを処理してサーバーに同時にかつ順番にアップロードします

  8. 8

    Azure BLOBからExcelファイルをダウンロードし、ファイルをローカルディレクトリに保存せずにそのデータを処理します

  9. 9

    ファイルの内容をWSLからWindowsにクリップボードにコピーしますか?

  10. 10

    変数からのデータをXMLファイルに保存し、プログラムの再起動後にそれをコード化したい

  11. 11

    FTPサーバーからCSVファイルをダウンロードしてローカルに保存し、アップロードを処理します

  12. 12

    Rails 4とペーパークリップ-:originalスタイルのファイルのアップロードを停止して、S3リモートディレクトリからコピーします

  13. 13

    sshを介してリモートマシンのファイルからローカルクリップボードにファイルの内容をコピーする方法

  14. 14

    「送信先...」を使用してファイルをFTPにアップロードし、そのURLをクリップボードにコピーします

  15. 15

    特定の形式のファイルを破棄しながら、zipアーカイブを再帰的に処理してファイルを抽出します

  16. 16

    ANTを使用して、ローカルディレクトリからマップされたドライブにファイルをコピーします

  17. 17

    最後の「コピー」をクリップボードからファイルに保存

  18. 18

    arcpyクリップ管理を使用してファイル内の複数のラスターを処理するためのforループを作成します

  19. 19

    データベースSQLサーバーから特定のテーブルをバックアップし、vb.netコードを使用して.bakファイルをコンピューターに保存する方法

  20. 20

    そのポップアップボックスのルックアンドフィールを変更する(コンピューターからファイルを選択するために開くウィンドウ)

  21. 21

    スクリプトディレクトリからすべてのユーザーのデスクトップにファイルをコピーします

  22. 22

    ファイルをバッチ処理してサブフォルダー内の.tsファイルを見つけ、それらをディレクトリに移動しますか?

  23. 23

    クリップボードからの同じコピーを使用してクリップボードの内容を処理し、フォームに入力するようにブックマークレットを修正します

  24. 24

    フィルター処理されたデータの範囲をコピーしてExcelVBAの新しいワークシートに貼り付ける方法(クリップボードを使用せずに)

  25. 25

    7-Zipを使用してアーカイブ内のファイルパーミッションとシンボリックリンクを保持する

  26. 26

    ワイルドカード文字を使用して、あるドッカー ボリュームから別のドッカー ボリュームにすべてのファイルをコピーしますか?

  27. 27

    FlaskからPILイメージのコピーを作成した後にバイトが欠落している-データをアップロードする

  28. 28

    スプレッドシートスクリプト:ボタンをアクティブにし、セルからシートにデータをコピーしてから、データの範囲をクリアします

  29. 29

    ZIPをパイプ処理し、アーカイブ内に使用可能なファイル名を含める方法

ホットタグ

アーカイブ