免费的删除文档中的VBA程序的工具及源码

前一段时间我写了篇文章”关于以前写的VBA在新版本64位Inventor中无法使用的问题”,然后就对Structure Storage API似乎有一发不可收拾的兴趣。

这一次我打算使用Structure Storage API来做个有效、方便的工具来删除Inventor文件中的VBA。Inventor文件是基于Structure Storage的,或者说IStorage/IStream。这类文件有些人翻译成复合文件。这一类型的文件都支持structure storage API,因此我们就可以用structure storage API来修改文件(内部包含的属性、信息)。IStorage是一种COM接口,能用C++调用,如果你对如何用C++调用IStorage接口来删除VBA程序感兴趣,我建议你看看Brian的博客:

http://modthemachine.typepad.com/my_weblog/2009/01/removing-vba-document-projects-from-inventor-files.html

我今天要讲的是C#调用IStorage接口。为了调用IStorage接口,我们要先给这个COM接口做一个.NET封装(wrapper),下面我会贴出C#的封装源代码,以及我的程序中主要的实现代码供大家参考:

IStorage 的C#封装:

[DllImport(“ole32.dll”)]

static extern int

StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)]

string pwcsName);

[DllImport(“ole32.dll”)]

static extern int

StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)]

string pwcsName, STGM grfMode, uint reserved, out IStorage

ppstgOpen);

[DllImport(“ole32.dll”)]

static extern int StgOpenStorage(

[MarshalAs(UnmanagedType.LPWStr)] string pwcsName

, IStorage pstgPriority

, STGM grfMode

, IntPtr snbExclude

, uint reserved

, out IStorage ppstgOpen);

private ArrayList fileList = new ArrayList();

public SSProcessor(ArrayList _fileList)

{

SetFileList(_fileList);

}

private void SetFileList(ArrayList _fileList)

{

fileList = _fileList;

}

public void CullFiles()

{

int count = 0;

foreach (FileSystemInfo file in fileList)

{

try

{

StgIsStorageFile(file.FullName);

count++;

}

catch

{

fileList.RemoveAt(count);

//add code to log non-storagefile items

}

}

}

public enum STGM : uint

{

STGM_READ = 0x00000000,

STGM_WRITE = 0x00000001,

STGM_READWRITE = 0x00000002,

STGM_SHARE_DENY_NONE = 0x00000040,

STGM_SHARE_DENY_READ = 0x00000030,

STGM_SHARE_DENY_WRITE = 0x00000020,

STGM_SHARE_EXCLUSIVE = 0x00000010,

STGM_PRIORITY = 0x00040000,

STGM_CREATE = 0x00001000,

STGM_CONVERT = 0x00020000,

STGM_FAILIFTHERE = 0x00000000,

STGM_DIRECT = 0x00000000,

STGM_TRANSACTED = 0x00010000,

STGM_NOSCRATCH = 0x00100000,

STGM_NOSNAPSHOT = 0x00200000,

STGM_SIMPLE = 0x08000000,

STGM_DIRECT_SWMR = 0x00400000,

STGM_DELETEONRELEASE = 0x04000000,

}

public enum STGC : uint

{

STGC_DEFAULT = 0,

STGC_OVERWRITE = 1,

STGC_ONLYIFCURRENT = 2,

STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,

STGC_CONSOLIDATE = 8

}

public enum STATFLAG : uint

{

STATFLAG_DEFAULT = 0,

STATFLAG_NONAME = 1

}

[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]

out 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 )]

public interface IStorage

{

void CreateStream(

/* [string][in] */ string pwcsName,

/* [in] */ STGM grfMode,

/* [in] */ uint reserved1,

/* [in] */ uint reserved2,

/* [out] */ out IStream ppstm);

void OpenStream(

/* [string][in] */ string pwcsName,

/* [unique][in] */ IntPtr reserved1,

/* [in] */ STGM grfMode,

/* [in] */ uint reserved2,

/* [out] */ out IStream ppstm);

void CreateStorage(

/* [string][in] */ string pwcsName,

/* [in] */ STGM grfMode,

/* [in] */ uint reserved1,

/* [in] */ uint reserved2,

/* [out] */ out IStorage ppstg);

void OpenStorage(

/* [string][unique][in] */ string pwcsName,

/* [unique][in] */ IStorage pstgPriority,

/* [in] */ STGM grfMode,

/* [unique][in] */ IntPtr snbExclude,

/* [in] */ uint reserved,

/* [out] */ out IStorage ppstg);

void CopyTo(

/* [in] */ uint ciidExclude,

///* [size_is][unique][in] */ Guid rgiidExclude,

//Guid[] rgiidExclude,

IntPtr rgiidExclude,

///* [unique][in] */ IntPtr snbExclude,

//string[] snbExclude,

//IntPtr[] snbExclude,

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] */ STGC 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] */ ComTypes.FILETIME pctime,

/* [unique][in] */ ComTypes.FILETIME patime,

/* [unique][in] */ ComTypes.FILETIME pmtime);

void SetClass(

/* [in] */ Guid clsid);

void SetStateBits(

/* [in] */ uint grfStateBits,

/* [in] */ uint grfMask);

void Stat(

/* [out] */ out ComTypes.STATSTG pstatstg,

/* [in] */ STATFLAG grfStatFlag);

}

调用IStorage来删除VBA代码的函数(节点RSeStorage/RSeEmbeddings/apc) :

public void ProcessFiles()

{

foreach (FileSystemInfo file in fileList)

{

// Open the file as a storage.

IStorage stg;

IStorage stg_new;

int result = StgOpenStorage(file.FullName, null, STGM.STGM_DIRECT | STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE, IntPtr.Zero, 0, out stg);

// Find the storage with the path “RSeStorage/RSeEmbeddings/apc”

stg.OpenStorage(“RSeStorage”, null, STGM.STGM_DIRECT | STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE, IntPtr.Zero, 0, out stg_new);

if (stg_new == null)

{

System.Windows.Forms.MessageBox.Show(“can’t find RSeStorage node”);

return;

}

stg_new.OpenStorage(“RSeEmbeddings”, null, STGM.STGM_DIRECT | STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE, IntPtr.Zero, 0, out stg);

if (stg == null)

{

System.Windows.Forms.MessageBox.Show(“can’t find RSeEmbeddings node”);

return;

}

ComTypes.STATSTG s1 = new ComTypes.STATSTG();

IEnumSTATSTG SSenum;

stg.EnumElements(0, IntPtr.Zero, 0, out SSenum);

uint NumReturned = 0;

do

{

SSenum.Next(1, out s1, out NumReturned);

if (NumReturned > 0)

{

if (s1.pwcsName == “apc”)

{

// Delete the storage

stg.DestroyElement(“apc”);

stg.Commit(STGC.STGC_DEFAULT);

break;

}

}

} while (NumReturned > 0);

}

System.Windows.Forms.MessageBox.Show(“VBA project has been deleted!”);

}

调用上面的函数的代码:

ArrayList fileList;

// Open the storage and read from storage

if (fileList.Count > 0)

{

SSProcessor ssProc = new SSProcessor(fileList);

ssProc.ProcessFiles();

}

实现选择文件功能:

try

{

FolderBrowserDialog folderDlg = new FolderBrowserDialog();

folderDlg.Description = “选择文件夹”;

DialogResult res = folderDlg.ShowDialog(this);

if (res == DialogResult.OK)

{

fileList.Clear();

this.listBox1.Items.Clear();

//Get the Directory Info using Directory Name

DirectoryInfo dirInfor = new DirectoryInfo(folderDlg.SelectedPath);

FileInfo[] partFiles = dirInfor.GetFiles(“*.ipt”);

foreach (FileInfo fInfo in partFiles)

{

this.listBox1.Items.Add(fInfo.FullName);

fileList.Add(fInfo);

}

FileInfo[] assFiles = dirInfor.GetFiles(“*.iam”);

foreach (FileInfo fInfo in assFiles)

{

this.listBox1.Items.Add(fInfo.FullName);

fileList.Add(fInfo);

}

FileInfo[] drFiles = dirInfor.GetFiles(“*.idw”);

foreach (FileInfo fInfo in drFiles)

{

this.listBox1.Items.Add(fInfo.FullName);

fileList.Add(fInfo);

}

}

}

catch (Exception ex) { MessageBox.Show(ex.Message); }

简单的执行界面图:

你也可以到我的资源中心(http://barbarahan.download.csdn.net/)去下载完整的源码deleteVBA_C#_source和执行程序deleteVBA_C#_exe。(我刚才上传了exe资源,但是CSDN没有显示,也许等你看的时候就出来了。)

每一件事都要用多方面的角度来看它

免费的删除文档中的VBA程序的工具及源码

相关文章:

你感兴趣的文章:

标签云: