免费的删除文档中的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#封装:static extern intStgIsStorageFile(string pwcsName);static extern intStgCreateDocfile(string pwcsName, STGM grfMode, uint reserved, out IStorageppstgOpen);
static extern int StgOpenStorage( 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}
public interface IEnumSTATSTG{// The user needs to allocate an STATSTG array whose size is celt.uintNext(uint celt,//out ComTypes.STATSTG rgelt,out uint pceltFetched);
void Skip(uint celt);
void Reset();
IEnumSTATSTG Clone();}
public interface IStorage{void CreateStream(/* */ string pwcsName,/* */ STGM grfMode,/* */ uint reserved1,/* */ uint reserved2,/* */ out IStream ppstm);
void OpenStream(/* */ string pwcsName,/* */ IntPtr reserved1,/* */ STGM grfMode,/* */ uint reserved2,/* */ out IStream ppstm);
void CreateStorage(/* */ string pwcsName,/* */ STGM grfMode,/* */ uint reserved1,/* */ uint reserved2,/* */ out IStorage ppstg);
void OpenStorage(/* */ string pwcsName,/* */ IStorage pstgPriority,/* */ STGM grfMode,/* */ IntPtr snbExclude,/* */ uint reserved,/* */ out IStorage ppstg);
void CopyTo(/* */ uint ciidExclude,///* */ Guid rgiidExclude,//Guid[] rgiidExclude,IntPtr rgiidExclude,///* */ IntPtr snbExclude,//string[] snbExclude,//IntPtr[] snbExclude,IntPtr snbExclude,/* */ IStorage pstgDest);
void MoveElementTo(/* */ string pwcsName,/* */ IStorage pstgDest,/* */ string pwcsNewName,/* */ uint grfFlags);
void Commit(/* */ STGC 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,/* */ ComTypes.FILETIME pctime,/* */ ComTypes.FILETIME patime,/* */ ComTypes.FILETIME pmtime);
void SetClass(/* */ Guid clsid);
void SetStateBits(/* */ uint grfStateBits,/* */ uint grfMask);
void Stat(/* */ out ComTypes.STATSTG pstatstg,/* */ 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 storagestg.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 storageif (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 NameDirectoryInfo 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://hi.csdn.net/attachment/201005/25/0_12747613755zFi.gif
你也可以到我的资源中心(http://barbarahan.download.csdn.net/)去下载完整的源码deleteVBA_C#_source和执行程序deleteVBA_C#_exe。(我刚才上传了exe资源,但是CSDN没有显示,也许等你看的时候就出来了。)
文章来源:http://blog.csdn.net/barbarahan
什么时候学习都不晚 ☆⌒(*^-゜)v THX!! 路过!!!
不发表意见…… 顶!!!!!!!!!!!!!!!!!!!!!!!!! (*^__^*) 嘻嘻…… (*^__^*) 嘻嘻…… 顶!!!!!!!!!! 顶!!!!!!!!!! (*^__^*) 嘻嘻…… 路过!!!
不发表意见…… (*^__^*) 嘻嘻…… 顶起来………… (*^__^*) 嘻嘻…… 顶起来………… 顶......
楼下跟上..... (*^__^*) 嘻嘻…… 顶......
楼下跟上.....