Greets,
I found a similar question at Opening OLE Compound Documents read-only with StgOpenStorage but that solution didn't work for me.
I try to open an outlook .msg file with StgOpenStorage(). My problem is, that StgOpenStorage always locks my file.
So, how can I avoid/remove the lock StgOpenStorage() adds to my file?
(see last method of code OpenStorage())
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace IStorageLock
{
[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();
}
[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IStorage
{
void CreateStream(string pwcsName, uint grfMode, uint reserved1,
uint reserved2, out IStream ppstm);
void OpenStream(string pwcsName, IntPtr reserved1, uint grfMode,
uint reserved2, out 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, 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);
}
class Lock
{
[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,
}
[DllImport("ole32.dll")]
private static extern int StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)]
string pwcsName);
[DllImport("ole32.dll")]
static extern int StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)]
string pwcsName,
IStorage pstgPriority,
STGM grfMode,
IntPtr snbExclude,
uint reserved,
out IStorage ppstgOpen);
public IStorage OpenStorage(string fileName)
{
if (StgIsStorageFile(fileName) != 0) {
return null;
}
IStorage storage = null;
//
// StgOpenStorage() locks file 'fileName'
//
// Set flags like:
// [http://stackoverflow.com/questions/1086814/opening-ole-compound-documents-read-only-with-stgopenstorage]
//
int stgOpenStorage = StgOpenStorage(fileName, null,
STGM.READ |
STGM.SHARE_DENY_NONE |
STGM.TRANSACTED,
IntPtr.Zero, 0,
out storage);
//
// Try to rename file (for testing purposes only)
//
try {
File.Move(fileName, fileName + @".renamed");
} catch (Exception ex) { // exception: file alreay in use by another process
throw;
}
if (stgOpenStorage != 0) {
return null;
} else {
return storage;
}
}
}
}
Hope you can help me.
Regards,
inno