SHELL命令在VBA中的妙用.docx
《SHELL命令在VBA中的妙用.docx》由会员分享,可在线阅读,更多相关《SHELL命令在VBA中的妙用.docx(7页珍藏版)》请在冰豆网上搜索。
SHELL命令在VBA中的妙用
SHELL命令在VBA中的妙用
SHELL命令在VBA中的妙用
SHELL命令在VBA中的妙用
想要文件关闭的时候进行备份?
想要把DOS命令加入到日常中的应用中来?
没问题,用SHELL就行了。
如你的前台一启动的时候就自动建立虚拟盘,可以在LOAD事件里加入:
shell"substX:
H:
\ushare\MRP"
这样就可以在文件打开的时候自动把H:
\ushare\MRP映射成X盘,有利于文件分发。
同理,也可以加入其它的如XCOPY命令来备份。
当然,你要是把DOS命令做成一个BAT文件执行,用SHEEL"PATH“,1来执行.SHEEL语句后面的那个1的意思如下:
常数 值 描述
vbHide 0窗口是隐藏的,并且焦点被传递给隐藏窗口。
vbNormalFocus 1窗口拥有焦点,并且恢复到原来的大小与位置。
vbMinimizedFocus 2窗口缩小为图符并拥有焦点。
vbMaximizedFocus 3窗口最大化并拥有焦点。
vbNormalNoFocus 4窗口被恢复到最近一次的大小与位置。
当前活动窗口仍为活动窗口。
vbMinimizedNoFocus 6窗口缩小为图符。
当前活动窗口仍为活动窗口。
VBASHELL语句用法心得--转录
一、关于Rundll32.exe
过去,你曾经为了自己编的文件管理器能Format磁盘、浏览器能自动拨号连接而求助于那位高傲的API。
现在,Rundll32.exe向你提供了更为平易近人的方法来实现这些功能。
例如,要调用关机程序则为:
shell“rundll32.exeuser.exe,exitwindOws”。
调用模块命令结果
rundll32.exeshell32.dll,Control_RunDLL打开控制面板
SHELL32.DLL
rundll32.exeshell32,SHHelpShortcuts_RundllPrintersFolder打开打印机文件夹
rundll32.exeshell32,SHHelpShortcuts_RundllFontsFolder打开字体文件夹
rundll32.exeshell32,SHHelpShortcuts_RundllAddPrinter添加新打印机向导
rundll32.exeshell32,SHformatDrive格式化软盘
SYSDM.CPL
rundll32.exeshell32,Control_RunDLLsysdm.cpl系统属性,常规
rundll32.exeshell32,Control_RunDLLsysdm.cpl,,l系统属性,设备管理器
rundll32.exeshell32,Control_RunDLLsysdm.cpl,,3系统属性,性能
rundll32.exeshell32,Control_RunDLLsysdm.cpl@1添加新硬件向导
APPWIZ.CPL
rundll32.exeshell32,Control_RunDLLappwiz.cpl,,1添加/删除程序
rundll32.exeshell32,Control_RunDLLappwiz.cpl,,2安装Windows部件
rundll32.exeshell32,Control_RunDLLappwiz.cpl,,3制作启动盘
DISKCOPY.DLL
rundll32.exediskcopy.dll,DiskcopyRundll复制磁盘
RNAUI.DLL
rundll32.exernaui.dll,RnaDialx(x为连接名称)打开拨号边接对话框,若已连接,则显示连接状态对话框
rundll32.exernaui.dll,RnaWizard新建拨号连接向导
DESK.CPL
rundll32.exeshell32,Control_RunDLLdesk.cpl,,0选择桌面背景
rundll32.exeshell32,Control_RunDLLdesk.cpl,,1选择屏幕保护
rundll32.exeshell32,Control_RunDLLdesk.cpl,,2选择外观
rundll32.exeshell32,Control_RunDLLdesk.cpl,,3设置显示属性
MAIN.CPL
rundll32.exeshell32,Control_RunDLLmain.cpl@0设置鼠标属性
rundll32.exeshell32,Control_RunDLLmain.cpl@1设置键盘属性,速度
rundll32.exeshell32,Control_RunDLLmain.cpl@1,,1设置键盘属性,语言
rundll32.exeshell32,Control_RunDLLmain.cpl@2打开打印机文件夹
rundll32.exeshell32,Control_RunDLLmain.cpl@3打开字体属性
rundll32.exeshell32,Control_RunDLLmain.cpl@4设置输入法
MODEM.CPL
rundll32.exeshell32,Control_RunDLLmodem.cpl,,add添加调制解调器向导
MMSYS.CPL
rundll32.exeshell32,Control_RunDLLmmsys.cpl@1设置声音属性(也可以加入,,0到,,4的参数以选择不同的标签)
UESR.EXE
rundll32.exeuser.exe,exitwindows关闭计算机
二、如何确定Shell语句调用的程序已经关闭
这个标题确实太长,但它确实概括了本节的内容。
当你需要等待由Shell启动的应用程序运行完毕时,便会发现Shell语句只管调用,之后就撒手不管了,于是我们不得不动用一下API函数了。
当然我们可以用API来完成全部的工作,但是如果那样的话,我们将要面临CreateProcess这个非常复杂的函数,光写下它和相关结构类型的宣告就超出一页纸了。
别误会,我说这些的目的只是为了让大家体会到下面我们将要做的是多么简单的事。
只需按以下步骤stepbystep,便OK了。
1.新建一个项目,在窗体上放一个command1,再添加一个Module。
2.在Module中写入如下代码:
OptionExplicit
以下声明了OpenProcess,GetExitCodeProcess和Closeandle三个API函数
PublicDeclareFunctionOpenProcessLib"kernel32"(ByValdwDesiredAccessAsLong,ByValbInheritHandleAsLong,ByValdwProcessIdAsLong)AsLong
PublicDeclareFunctionGetExitcodeProcessLib“kernel32”(ByValhProcessAsLong,1pExitcodeAsLong)AsLong
PublicDeclareFunctionClosellandleLib"Kernel32”(ByValhobjectAsLong)AsLong
PubliConstPROCESS_QUERY_INFORMATION=&H400
PublicConstSTATUS_PENDING=&H103&
3.打开窗体的代码窗口,写入如下代码:
OptionExplicit
PrivateSubRunShell(cmdlineAsString)这个自定义过程完成了所有工作
DimhProcessAsLong
DimProcessIdAsLong
DimexitCodeAsLong
ProcessId=Shell(cmdline,1)'此处利用了Shell当函数使用时返回的任务标识
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,False,ProcessId)
Do
Ca11GetExitCodeProcess(hProcess,exitcode)
DoEvents
LoopWhileexitCode=STATUS_PENDING
CallCloseHandle(hProcess)
MsgBoxcmdline&"已经关闭。
"
EndSub
PrivateSubCommand1_Click()
RunShell”notepad.exe”
EndSub
4·按F5运行,单击Command1运行计事本,关闭计事本将弹出对话框“notepad.exe已经关闭。
”
注意:
由于本程序是用一个Do..Loop循环来侦测进程的结束,所以那句DoEvents是绝不能少的,不然你就只能用Ctrl+Break来退出了。
三、激活一个正在运行的程序
让我们来考虑这样一种情况:
我们在程序中定义了某一操作是用Shell语句调用Windows的计算器,当用户重复这一操作时,计算器已经在运行了。
如果简单地再使用Shell语句将打开计算器的另一个进程。
这显然是不合理的。
这时我们需要做的是激活已运行的计算器,下面这段简单的代码帮我们达到了目的、相信大家一看就懂。
PrivateDeclareFunctionFindWindowLib“user32”Alias“FindWindowA”(ByVal1pClassNameAsString,ByVal1pWindowNameAsString)AsLong
PrivateDeclareFunctionBringWindowToToplib“user32”(ByValhwndAsLong)AsLong
'以上声明了FindWindow和BringWindowToTop两个API函数
PrivateSubCommand1-Click()
DimhCalcWndAsLong
hCalcwnd=Findwindow(“SciCalc”,”计算器”)
这里SciCalc是计算器的窗口类名,详见下一节
lfhCalcWnd=0Then
Shell("CALC.EXE",vbNormalFocus)
Else:
BringWindowToTop(hCalcWnd)
Endlf
Endsub
四、如何获得窗口的类名
只是看过上节的读者大部会对窗口的类名提出疑问,本节就是针对这个问题的。
通过本节的内容,你还能了解到如何跟踪鼠标,并找出它正经过哪个窗口。
好,让我们一步一步地来,这回代码可能稍多一些。
1.建立一个新项目,在窗体的GeneralDeclarations部分写入以下代码,这些语句定义了要用到的API函数、常量以及结构。
OptionExplicit
DimgbCancelAsBoolean
PrivateTypePOINTAPI
XAsLong
YAsLong
EndType
PrivateDeclareFunctionGetCursorPosLib“user32"(1pPointAsPOINTAPI)AsLong
PrivateDeclareFunctionWindowFromPointLib"user32”(ByValxPointAsLong,ByValyPointAslong)AsLong
PrivateDeClareFunctionGetClassNameLib“user32”Alias"GetClassNameA”(ByValhwndAsLong,ByVal1pClassNameAsString,ByValaMaxCountAsLong)AsLong
2.在窗体上放一个Command1,把标题改成“开始”,再放一个Label1,以下是事件的代码,也请大家在相应位置写上。
PrivateSubCommand1_CliCk()
IfCommand1.Caption="开始"Then
Command1.Caption="停止"
CallTrack
ElSe
Command1.Caption="开始"
gbCancel=True
EndIF
EndSub
PrivateSubForm_Load()
gbCancel=False'初始化循环取消变量
EndSub
PrivateSubForm_QueryUnload(CancelAsInteger,UnloadModeAsInteger)
gbCancel=True'确保循环中断
EndSub
3.最后是关键部分,自定义的过程Track。
SubTrack()
DimPT_MouseAsPOINTAPI
Dim1CurHwndAsLong
Dim1PrvHwndAsLong
DimIXAsLong,1YAsLong
DimtClassNameAsString
Dim1ResultAsLong
1PrvHwnd=0
Do
CallGetCursorPos(PT_Mouse)'获得鼠标位置
1X=PT_Mouse.x
1Y=PT_Mouse.Y
1CurHwnd=WindowFromPolnt(1X,1Y)'获得鼠标箭头下窗口的句柄
IfgbCancel=TrueThenExitDo
If1CurHwnd<>1PrvHWndThen'若两值不等则说明经过不同的窗口,保存新值
1PrvHwnd=1CurHwnd
tClassName=String$(256,"")'注意引号间是空格
1Result=GetClassName(1CurHwnd,tClassName,255)'这两句取出类名
tClassName=Left$(tClassName,InStr(tClassName,vbNullChar)-1)
Labell,Caption="鼠标通过:
”&tClassName
'也可写1CurHwnd以获得窗口句柄
Endlf
DoEvents'决不可少!
切记,切记!
Loop
Endsub
运行此程序,按下"开始”按钮后,鼠标所经过的窗口的类名将在Labell中显示出来。