bat脚本外部调用cmd_使用脚本控制外部流程-CMD

bat脚本外部调用cmd

介绍。

许多人问我是否可以从Access中控制外部过程。 通过外部流程,我说的是在Access外部运行脚本。 这将包括BAT,CMD和PowerShell脚本,甚至包括使用Windows的FTP.EXE命令行界面的FTP脚本。

这些脚本接口的功能很难加以限制。 CMD.EXE尤其可以控制几乎所有命令的整个脚本文件。 可以在Access中将其自动化。

这种脚本的我最喜欢的用途之一是升级项目的当前版本。 我会在启动时自动更新前端数据库,并且还提供了以后随时进行升级以防损坏的选项(不幸的是,某些Access数据库很容易出现)。

这就是我将在本文中解释的内容。 在同一主题领域中的另一个是

使用Scripts-FTP控制外部进程总体概念。

这个概念依赖于一个表,最简单的设计为:

表格= [ tblCMD ]
 Field Name  Type        PK (Compound) 
Template    Boolean     #1
Type        String(1)   #2
LineNo      Long        #3
Cmd         String(255)
在某些情况下,我在此数据库升级CMD脚本期间遇到了问题,单行中的命令长度有可能超过允许的255个字符。 因此,在这种情况下,在我所附的示例中,我使用两个字段[Cmd1]和[Cmd2]代替了单个[Cmd]。

在处理要输入到脚本表中的数据时,要记住的一个非常重要的观点是,数据中具有可替换参数的能力带来了额外的优势。 在我的示例中,我使用百分比(%)后跟两个字母字符来标记数据中要从代码中插入值的点。 升级CMD脚本的一个示例是%Ac,它用于Access可执行文件的全名。 FTP脚本的用法不同,因此请注意不要混淆两者。 这是升级CMD脚本替换以及FTP脚本使用的值的列表。 替换参数与其相关变量具有相同的名称,除了%替换str。 所以,

代码中的strBa用于替换数据中%Ba的出现。

下一步是为同一表中的特定脚本创建模板的更新副本。 由于[Template]值为False,因此可以识别此新数据。 更新内容是用所需的值替换前面提到的参数。 然后(通过查询)将此新数据(仅)导出到脚本文件。导出后,该数据将从表中删除。

完成所有操作并准备好脚本文件后,我们需要调用它。

示例数据。 表格= [ tblCMD ]
 Template  Type  Order  Cmd1                            Template  Type  Order  Cmd1 
  TRUE     U      10   @ECHO OFF                         FALSE    U      10   @ECHO OFF
  TRUE     U      20   IF NOT EXIST "%Fo\%Ba" GOTO RENAMEBACKUP
                                                         FALSE    U      20   IF NOT EXIST "D:\Scratch\Access\ControlExternalProcesses\ContEx_Last.Accdb" GOTO RENAMEBACKUP
  TRUE     U      30   ATTRIB -R "%Fo\%Ba" >NUL          FALSE    U      30   ATTRIB -R "D:\Scratch\Access\ControlExternalProcesses\ContEx_Last.Accdb" >NUL
  TRUE     U      40   DEL "%Fo\%Ba" >NUL                FALSE    U      40   DEL "D:\Scratch\Access\ControlExternalProcesses\ContEx_Last.Accdb" >NUL
  TRUE     U      50   IF ERRORLEVEL 1 GOTO BADBACKUP    FALSE    U      50   IF ERRORLEVEL 1 GOTO BADBACKUP
  TRUE     U      60   :RENAMEBACKUP                     FALSE    U      60   :RENAMEBACKUP
  TRUE     U      70   ECHO Attempting to rename '%Fo\%Or' to '%Ba'
                                                         FALSE    U      70   ECHO Attempting to rename 'D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb' to 'ContEx_Last.Accdb'
  TRUE     U      80   ECHO Needs "%Fo\%Or" to be closed before continuing...
                                                         FALSE    U      80   ECHO Needs "D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb" to be closed before continuing...
  TRUE     U      90   :START                            FALSE    U      90   :START
  TRUE     U     100  REN "%Fo\%Or" "%Ba" >NUL           FALSE    U     100   REN "D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb" "ContEx_Last.Accdb" >NUL
  TRUE     U     110  IF ERRORLEVEL 1 GOTO START         FALSE    U     110   IF ERRORLEVEL 1 GOTO START
  TRUE     U     120  ATTRIB +R "%Fo\%Ba" >NUL           FALSE    U     120   ATTRIB +R "D:\Scratch\Access\ControlExternalProcesses\ContEx_Last.Accdb" >NUL
  TRUE     U     130  ECHO Attempting to copy '%Ne' to '%Fo\%Or'
                                                         FALSE    U     130   ECHO Attempting to copy 'D:\Scratch\Access\ControlExternalProcesses\Release\ContEx01.00.00.Accdb' to 'D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb'
  TRUE     U     140  COPY /B /V /Y "%Ne" "%Fo\%Or" >NUL FALSE    U     140   COPY /B /V /Y "D:\Scratch\Access\ControlExternalProcesses\Release\ContEx01.00.00.Accdb" "D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb" >NUL
  TRUE     U     150  IF ERRORLEVEL 1 GOTO BADCOPY       FALSE    U     150   IF ERRORLEVEL 1 GOTO BADCOPY
  TRUE     U     160  ATTRIB -R -S -H "%Fo\%Or" >NUL     FALSE    U     160   ATTRIB -R -S -H "D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb" >NUL
  TRUE     U     170  IF ERRORLEVEL 1 GOTO BADCOPY       FALSE    U     170   IF ERRORLEVEL 1 GOTO BADCOPY
  TRUE     U     180  ECHO Restarting Access with the updated file.
                                                         FALSE    U     180   ECHO Restarting Access with the updated file.
  TRUE     U     190  START "Dummy Title" /D"%Fo" "%Ac"
[Cmd2]                "%Fo\%Or" ;%BE
                                                         FALSE    U     190   START "Dummy Title" /D"D:\Scratch\Access\ControlExternalProcesses" "C:\Program Files (x86)\Microsoft Office\Office14\MSAccess.Exe"
[Cmd2]                                                                        "D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb" ;
  TRUE     U     200  GOTO CMDEND                        FALSE    U     200   GOTO CMDEND
  TRUE     U     210  :BADBACKUP                         FALSE    U     210   :BADBACKUP
  TRUE     U     220  ECHO Unable to delete existing backup file '%Fo\%Ba'.
                                                         FALSE    U     220   ECHO Unable to delete existing backup file 'D:\Scratch\Access\ControlExternalProcesses\ContEx_Last.Accdb'.
  TRUE     U     230  GOTO CMDERROR                      FALSE    U     230   GOTO CMDERROR
  TRUE     U     240  :BADCOPY                           FALSE    U     240   :BADCOPY
  TRUE     U     250  ECHO Unable to copy '%Ne' to '%Fo\%Or' successfully.
                                                         FALSE    U     250   ECHO Unable to copy 'D:\Scratch\Access\ControlExternalProcesses\Release\ContEx01.00.00.Accdb' to 'D:\Scratch\Access\ControlExternalProcesses\ContEx.Accdb' successfully.
  TRUE     U     260  :CMDERROR                          FALSE    U     260   :CMDERROR
  TRUE     U     270  ECHO Please refer this problem to Support.
                                                         FALSE    U     270   ECHO Please refer this problem to Support.
  TRUE     U     280  PAUSE                              FALSE    U     280   PAUSE
  TRUE     U     290  :CMDEND                            FALSE    U     290   :CMDEND
  TRUE     U     300  DEL "%Fo\UPGRADE.CMD" >NUL         FALSE    U     300   DEL "D:\Scratch\Access\ControlExternalProcesses\UPGRADE.CMD" >NUL
注意 左边的数据是原始模板数据。 右边的数据是更新后的数据,这就是为创建实际脚本文件而导出的数据。 数据说明。

这是一个CMD脚本,在Access数据库随后关闭之前,Access代码将很快(但延迟很小)调用它。 总体目的是用新版本替换Access数据库文件,然后像旧文件一样调用新文件。 为了安全起见,当前文件将以相同的名称保存,但要附加“ _Last”。 如果有任何问题,只需在新文件上重命名即可重新启用该文件。

许多生产线对于整个过程而言都不那么重要,而仅仅是为了提供尽可能可靠的过程。 我将我的解释限于基本原则。

  1. 第20行到第50行确保在重命名现有的_Last文件之前,将其删除。
  2. 从#60行到#110行尝试将当前文件重命名为_Last文件。
    仅当当前文件成功关闭后,此功能才能起作用。 这个过程会不断尝试,直到成功为止。
    此概念的另一个变体是简单地在循环中将文件重命名为其自身。 一旦成功,您就知道该文件是免费的。
  3. 从#120行到#170行复制文件的新版本来代替当前版本。
  4. 从#180行到#190行再次将Access重新启动,直接进入当前数据库。
    它使用[Cmd2],因为它还将参数传递给数据库,告诉数据库要链接到的后端文件。 通常不需要这样做,但这说明了如何做到这一点。
  5. 从#210行到#280行处理错误情况。
  6. #290和#300行通过删除脚本文件并结束来结束该过程。
码。

尽管我展示的某些代码行将引用我自己的一些例程,但这只是代码的一小部分,即使未显示代码,也应很清楚它的作用。 因此,我将展示和解释主要代码,并将整个数据库包括在附件中,以便在需要时可以探索其他任何例程。 如果需要,我的代码始终可以重复使用。 我唯一声称的是版权。 其他人可以自由使用和更改代码。

我先解释一下

MultiReplace()是我的功能之一,它通过允许多对from和to替换而简单地扩展了VBA.Replace()函数。 不过,我不在SQL中使用此功能,正如您从第26行至第37行中的Replace()函数调用的笨拙用法中看到的那样。 这是替换参数的地方。 要查看其效果,请在第60行上放置一个断点,并在代码中的该位置打印strSQL的值。

我已经包含了

下面的SetStrings() 。 它基本上用于获取我们正在运行项目的文件夹以及其他所需的值。
  1. 到#19行的位置进行设置并清除所有文件。
  2. 第20行确定是否存在可用于替换当前文件的升级文件。
    此逻辑与该概念无关。 这只是使用它的一种方式的示例。
  3. 第22行使用找到的文件中的版本号设置变量strVersion。
  4. 第23行查找当前文件名的最后一个点(。)。 IE浏览器 扩展名在哪里。
  5. 第24行到#25行设置了strBa,它是数据(%Ba)中使用的可替换参数之一。
  6. 第26行到第37行设置了strCmd的值,该值用于将所有可替换参数替换为SQL中的值。
  7. 第38行至第59行使用strCmd两次设置了SQL。 一次用于[Cmd1],另一次用于[Cmd2]。
  8. 第60行设置dbVar指向当前数据库。
  9. 第62行保存“ 自动压缩”属性的值。 如果过程失败并需要恢复,这一点很重要。
  10. 第62行至第63行使用strSQL中SQL将实时数据添加到表中,但是仅在清除了之前可能遗留的所有数据之后。
    此数据将用于创建CMD文件。
  11. #64和#75行设置了intErr,以向ErrorHandler指示在进程崩溃时需要执行哪些操作来恢复。
  12. 第65行到第71行首先删除任何文件(如果存在),然后使用DoCmd.TransferText将新数据导出到该DoCmd.TransferText
    注意 该文件必须是.TXT文件,此文件才能起作用。
  13. 第72行至第73行首先清除实际CMD文件(如果存在),然后将.TXT文件重命名为.CMD。
  14. 第74行现在已导出并且不再需要删除表中的新数据。
  15. 第76行将“ 自动压缩”属性设置为off,以避免任何延迟关闭当前数据库。
  16. 从#76行到#83行提示操作员,并警告他们即将发生的事情。
  17. 第84行调用了我们刚刚创建的CMD文件。
    这将一直循环运行直到成功关闭数据库为止,然后它将复制和重命名文件,然后最终在Access中调用新数据库并删除自身(CMD文件)。
'UpgradeProject() prepares to upgrade from strN and returns true if all ok.
'  If all ok then calling code needs to close and quit the whole application
'  in order for the process to continue.
'12/09/2012 strBE used to ensure the upgraded FE uses the current BE or one
'           passed in the shortcut.
Public Function UpgradeProject() As Boolean
    Dim intX As Integer, intErr As Integer, intCompact As Integer
    Dim strNe As String, strVersion As String, strSQL As String
    Dim strMsg As String, strMode As String, strCmd As String
    Dim dbVar As DAO.Database 
    On Error GoTo Error_UpgradeProject
    strMode = SwitchMode(strType:="Process")
    Call SetStrings
    'Before we go any further, and regardless of whether or not an upgrade is
    '  even required, let's clear away any existing copy of UPGRADE.CMD.
    '  It's checked again immediately prior to being created.
    If Exist(strFo & "\UPGRADECMD.Txt") Then _
        Call KillFile(strFo & "\UPGRADECMD.Txt")
    strNe = GetUpgradeFile()
    If strNe = "" Then Exit Function
    strVersion = FormatVersion(strNe, "Display")
    intX = InStrRev(StringCheck:=strOr, StringMatch:=".")
    strBa = MultiReplace("%S_Last%F", "%S", Left(strOr, intX - 1), _
                                      "%F", Mid(strOr, intX))
    strCmd = "Replace(Nz([~C],''),'%Ac','%sAc')"
    strCmd = Replace("Replace(%C,'%Ba','%sBa')", "%C", strCmd)
    strCmd = Replace("Replace(%C,'%BE','%sBE')", "%C", strCmd)
    strCmd = Replace("Replace(%C,'%Fo','%sFo')", "%C", strCmd)
    strCmd = Replace("Replace(%C,'%Ne','%sNe')", "%C", strCmd)
    strCmd = Replace("Replace(%C,'%Or','%sOr')", "%C", strCmd)
    strCmd = MultiReplace(strCmd, "%sAc", strAc, _
                                  "%sBa", strBa, _
                                  "%sBE", "", _
                                  "%sFo", strFo, _
                                  "%sNe", strNe, _
                                  "%sOr", strOr)
    strSQL = "INSERT INTO [tblCMD]%L" _
           & "       ([Template]%L" _
           & "      , [Type]%L" _
           & "      , [Order]%L" _
           & "      , [Cmd1]%L" _
           & "      , [Cmd2])%L" _
           & "SELECT  [Template]%L" _
           & "      , [Type]%L" _
           & "      , [Order]%L" _
           & "      , [C1] AS [Cmd1]%L" _
           & "      , IIf([C2]='',Null,[C2]) AS [Cmd2]%L" _
           & "FROM    (SELECT False AS [Template]%L" _
           & "              , [Type]%L" _
           & "              , [Order]%L" _
           & "              , %C1 AS [C1]%L" _
           & "              , %C2 AS [C2]%L" _
           & "         FROM   [tblCMD]%L" _
           & "         WHERE  ([Template])%L" _
           & "           AND  ([Type]='U')) AS [qC]"
    strSQL = MultiReplace(strSQL, "%C1", Replace(strCmd, "~C", "Cmd1") _
                                , "%C2", Replace(strCmd, "~C", "Cmd2") _
                                , "%L", vbNewLine)
    Set dbVar = CurrentDb()
    intCompact = dbVar.Properties("Auto Compact")
    Call ClearTable(strTable:="tblCMD", strWhere:="(NOT [Template])")
    Call dbVar.Execute(Query:=strSQL, Options:=dbFailOnError)
    intErr = &H1
    If Exist(strFo & "\UPGRADECMD.Txt") Then _
        Call KillFile(strFo & "\UPGRADECMD.Txt")
    Call DoCmd.TransferText(TransferType:=acExportDelim, _
                            SpecificationName:="Upgrade Spec", _
                            TableName:="qryUpgrade", _
                            FileName:=strFo & "\UPGRADECMD.Txt", _
                            HasFieldNames:=False)
    If Exist(strFo & "\UPGRADE.CMD") Then Call KillFile(strFo & "\UPGRADE.CMD")
    Name strFo & "\UPGRADECMD.Txt" As strFo & "\UPGRADE.CMD"
    Call ClearTable(strTable:="tblCMD", strWhere:="(NOT [Template])")
    intErr = &H0
    dbVar.Properties("Auto Compact") = 0
    strMsg = MultiReplace("Upgrading from '%N'.%L%L" _
                        & "This process should be very quick (<1 minute).%L" _
                        , "%N", strNe _
                        , "%L", vbNewLine)
    Call MsgBox(Prompt:=strMsg, _
                Buttons:=vbInformation Or vbOKOnly, _
                TITLE:=CurrentProject.NAME)
    Call Shell(PathName:=strFo & "\UPGRADE.CMD", WindowStyle:=vbNormalFocus)
    Call SwitchMode(strType:=strMode)
    UpgradeProject = True
    Exit Function 
Error_UpgradeProject:
    If Not dbVar Is Nothing Then dbVar.Properties("Auto Compact") = intCompact
    If Exist(strFo & "\UPGRADE.CMD") Then Call KillFile(strFo & "\UPGRADE.CMD")
    If Exist(strFo & "\UPGRADECMD.Txt") Then _
        Call KillFile(strFo & "\UPGRADECMD.Txt")
    If (intErr And &H1) Then _
        Call ClearTable(strTable:="tblCMD", strWhere:="(NOT [Template])")
    strMsg = MultiReplace("Error (%N) :%L%D%L%L" & _
                          "Unable to complete upgrade process", _
                          "%N", Err, _
                          "%D", Err.DESCRIPTION, _
                          "%L", vbNewLine)
    Call MsgBox(Prompt:=strMsg, Buttons:=vbCritical Or vbOKOnly, TITLE:=strOr)
    Call SwitchMode(strType:=strMode)
End Function
'SetStrings() prepares the global string variables strA, strB, strF & strO.
Public Sub SetStrings()
    If strAc = "" Then
        With CurrentProject
            strAc = BareFolder(SysCmd(acSysCmdAccessDir)) & "\MSAccess.Exe"
            strOr = .NAME
            strFo = Left(.Path, 1)
            If strFo >= "A" And strFo <= "Z" And strFo <> Left(CurDir, 1) Then _
                Call ChDrive(Drive:=strFo)
            strFo = BareFolder(.Path)
            If BareFolder(CurDir) <> strFo Then Call ChDir(Path:=strFo)
        End With
    End If
End Sub
结论。

在Access中可以控制的内容几乎没有限制。 我包括一个

附件 ,可以提取到任何文件夹并运行。 附件使用外接程序工具栏来访问要测试的项目。 第一次运行时,它可能会立即升级您。 不用担心 升级版本完全相同,只是内部存储了更高的版本号。 使用加载项工具栏手动测试升级过程。

翻译自: https://bytes.com/topic/access/insights/966089-control-external-processes-using-scripts-cmd

bat脚本外部调用cmd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值