代码改变世界

[小玩具]HoDown,“请等一下!”

2010-07-28 17:22  Nana's Lich  阅读(1559)  评论(0编辑  收藏  举报

一直挺关心最终幻想14,前些日子开始封闭测试了,很多朋友也陆陆续续地拿到了测试资格。

但是封测的客户端安装包只装了个引导程序,其它东西都是要通过BT协议来下载的,而安装以后第一次更新的时候要下载的内容有3.35GB之大,很多人用官方的下载器要下载数天才行——而往往下载完成以后,又有新的版本了,又得重新下载。

 

要想跳出这个死循环,就得在启动补丁更新程序之前在上面做点手脚——无独有偶,一些精通Visual Basic 6的人也发现在Visual Basic 6编译、生成可执行文件的过程中也可以做点手脚来达到一些特殊目的,有的人甚至专门为这种情况写了一个辅助工具。

 

 

我没有想把东西弄得太复杂,对于更新最终幻想14来说,只要放一个程序在中间,然后把参数转交给真正的ffxivupdater.exe就可以了,所以我就用Visual Basic 6随便写了个东西用;但我一时兴起就试了一下替换LINK.EXE,然后发现不作额外处理调用真正的LINK.EXE的时候会有一个黑乎乎的控制台窗口一闪即逝。

考虑到以后用在其它地方的可能,我决定把它稍微完善一下,增加了传递窗体启动参数、重定向标准IO管道的能力。

 

原理比较简单,所以不再详细解释了。完整的代码如下:

Private Type PROCESS_INFORMATION
        hProcess   As Long
        hThread   As Long
        dwProcessId   As Long
        dwThreadId   As Long
End Type
Private Type STARTUPINFO
        cb   As Long
        lpReserved   As String
        lpDesktop   As String
        lpTitle   As String
        dwX   As Long
        dwY   As Long
        dwXSize   As Long
        dwYSize   As Long
        dwXCountChars   As Long
        dwYCountChars   As Long
        dwFillAttribute   As Long
        dwFlags   As Long
        wShowWindow   As Integer
        cbReserved2   As Integer
        lpReserved2   As Byte
        hStdInput   As Long
        hStdOutput   As Long
        hStdError   As Long
End Type
Const STARTF_USESHOWWINDOW = &H1
Const STARTF_USESTDHANDLES = &H100&
Private Declare Sub GetStartupInfo Lib "kernel32" Alias "GetStartupInfoW" (lpStartupInfo As STARTUPINFO)
Private Declare Function CreateProcess Lib "kernel32 " Alias "CreateProcessW" (ByVal p1 As Long, ByVal lpCommandLine As Long, _
    ByVal p3 As Long, ByVal p4 As Long, ByVal bInheritHandles As Long, ByVal p6 As Long, ByVal p7 As Long, _
    ByVal p8 As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const STD_INPUT_HANDLE = -10&
Private Const STD_OUTPUT_HANDLE = -11&
Private Const STD_ERROR_HANDLE = -12&
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
    
Dim mySI As STARTUPINFO

Private Sub cmdRun_Click()
    Dim cmd As String, si As STARTUPINFO, pi As PROCESS_INFORMATION
    cmd = txtCmd.Text
    si.cb = Len(si)
    si.dwFlags = (STARTF_USESHOWWINDOW And mySI.dwFlags) Or STARTF_USESTDHANDLES
    si.wShowWindow = mySI.wShowWindow
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE)
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
    'si.hStdError = GetStdHandle(STD_OUTPUT_HANDLE)
    
    If CreateProcess(0, StrPtr(cmd), 0, 0, _
        1, 0, 0, 0, si, pi) Then
        
        Me.Hide
        DoEvents
        
        WaitForSingleObject pi.hProcess, -1
        
        CloseHandle pi.hProcess
        CloseHandle pi.hThread
        
        Unload Me
    Else
        MsgBox "无法启动目标程序,请检查启动命令是否正确。"
    End If
        
End Sub

Function GetTarget() As String
On Error Resume Next
    Dim line As String
    
    Open App.Path & "\" & App.EXEName & ".cmd" For Input As #1
    Line Input #1, line
    Close #1
    
    If "" = line Then
        line = App.Path & "\" & App.EXEName & ".ex_"
    Else
        If InStr(1, line, "\") = 0 Then line = App.Path & "\" & line
    End If
    
    If """" <> Left$(line, 1) Then line = """" & line & """"
    
    GetTarget = line
End Function

Private Sub Form_Load()
    GetStartupInfo mySI
    
    Me.Caption = GetTarget
    txtCmd = Me.Caption & " " & Command$
End Sub

Private Sub Form_Resize()
On Error Resume Next

    txtCmd.Width = Me.ScaleWidth
    txtCmd.Height = Me.ScaleHeight - picBottom.Height
End Sub

 

你也可以直接下载编译好的可执行文件(打包为zip格式):https://files.cnblogs.com/NanaLich/HoDown.zip

 

使用方法很简单:

把希望暂停启动或者在其参数上做手脚的可执行文件的扩展名改为“.EX_”,然后把本程序放在那个路径下面改成原来那个可执行文件的名称。

另外,我不知道谁会希望用到这样的功能:也可以创建一个主文件名相同、但扩展名为“.cmd”的文件,在其中写入希望最终调用的可执行文件的名称(路径可以省略)。