none
關於VB寫的DLL在WEB上引用API:CreateProcessA在WINDOWS 2003 SERVER會得到不正確的結果 RRS feed

  • 問題

  • 親愛的大大:
    小弟遇到一個問題一直找不到解決方式
    由於我需要將使用者透過WEB上傳的影片檔(.WMV,.AVI,....)即時轉成FLV檔
    找了很久找到一個DOS命令列的轉檔程式
    mencoder.exe

    在 DOS 實驗了一下可以正確轉檔
    他的語法為
    D:\transfer\mplayer\mencoder.exe D:\transfer\temp\test2.wmv -o D:\transfer\flv\20080103172040625430855.flv -of lavf -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=1:mv0:trell:v4mv:cbp:last_pred=1Big Smileia=-1:cmp=6:vb_strategy=1 -vf scale=300:-3 -ofps 12 -srate 22050
    意思是將 D:\transfer\temp\test2.wmv 轉檔成為 D:\transfer\flv\20080103172040625430855.flv

    後來我用VB寫了一個CODE
    =====================================
    底下這段程式碼位於Module1.bas
    =====================================
    Option Explicit

    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 Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
    End Type

    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type

    Private Declare Function WaitForSingleObject Lib _
    "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds _
    As Long) As Long

    Declare Function CreateProcessA Lib "kernel32" _
    (ByVal lpApplicationName As Long, ByVal lpCommandLine As _
    String, ByVal lpProcessAttributes As Long, ByVal _
    lpThreadAttributes As Long, ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, lpStartupInfo As _
    STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) _
    As Long

    Declare Function CloseHandle Lib "kernel32" (ByVal hObject _
    As Long) As Long

    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const INFINITE = -1&
    Private Const STARTF_USESHOWWINDOW = &H1
    Private Const SW_MINIMIZE = 6

    Public Sub ExecCmd(cmdline$)
        Dim proc As PROCESS_INFORMATION
        Dim start As STARTUPINFO
        Dim ret&
        'Initialize the STARTUPINFO structure:
        start.cb = Len(start)
       
        start.dwFlags = STARTF_USESHOWWINDOW
        start.wShowWindow = SW_MINIMIZE
       
        'Start the shelled application:
        ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
        NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
        'Wait for the shelled application to finish:
        ret& = WaitForSingleObject(proc.hProcess, INFINITE)
        ret& = CloseHandle(proc.hProcess)
    End Sub

    =====================================
    底下這段程式碼位於Form1.frm
    =====================================
    Private Sub Command1_Click()
      Dim Str1 As String
      Str1 = "D:\transfer\mplayer\mencoder.exe D:\transfer\temp\test1.wmv -o D:\transfer\flv\1.flv -of lavf -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=1:mv0:trell:v4mv:cbp:last_pred=1Big Smileia=-1:cmp=6:vb_strategy=1 -vf scale=300:-3 -ofps 12 -srate 22050"
      ExecCmd Str1
      MsgBox Err.LastDllError
    End Sub

    經過WINDOWS 2000 SERVER上測試執行可以正確轉換 可以將 D:\transfer\temp\test1.wmv 正確轉換為 D:\transfer\flv\1.flv 查看它的檔案SIZE是 868KB (這個是正確的)
    經過WINDOWS 2003 SERVER上測試執行可以正確轉換 可以將 D:\transfer\temp\test1.wmv 正確轉換為 D:\transfer\flv\1.flv 查看它的檔案SIZE是 868KB (這個是正確的)

    接著我將這個CODE包成DLL
    我用VB寫了xxx.vbp如下:
    =====================================
    底下這段程式碼位於DOS.bas
    =====================================
    Option Explicit

    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 Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
    End Type

    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type

    Private Declare Function WaitForSingleObject Lib _
    "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds _
    As Long) As Long

    Declare Function CreateProcessA Lib "kernel32" _
    (ByVal lpApplicationName As Long, ByVal lpCommandLine As _
    String, ByVal lpProcessAttributes As Long, ByVal _
    lpThreadAttributes As Long, ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, lpStartupInfo As _
    STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) _
    As Long

    Declare Function CloseHandle Lib "kernel32" (ByVal hObject _
    As Long) As Long

    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const INFINITE = -1&
    Private Const STARTF_USESHOWWINDOW = &H1
    Private Const SW_MINIMIZE = 6

    Public Sub ExecCmd(cmdline$)
        Dim proc As PROCESS_INFORMATION
        Dim start As STARTUPINFO
        Dim ret&
        'Initialize the STARTUPINFO structure:
        start.cb = Len(start)
       
        start.dwFlags = STARTF_USESHOWWINDOW
        start.wShowWindow = SW_MINIMIZE
       
        'Start the shelled application:
        ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
        NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
       
        'Wait for the shelled application to finish:
        ret& = WaitForSingleObject(proc.hProcess, INFINITE)
        ret& = CloseHandle(proc.hProcess)
    End Sub

    =====================================
    底下這段程式碼位於DoTransferFLV.cls
    =====================================
    Public Function DoExecCmd(ByVal s0)
      Dim Str1 As String
      Str1 = s0
      ExecCmd Str1
      DoExecCmd = Err.LastDllError
    End Function


    然後我寫了一ASP程式來測試
    Set Executor = Server.CreateObject("fuu.DoTransferFLV")
    R = Executor.DoExecCmd("D:\transfer\mplayer\mencoder.exe D:\transfer\temp\test1.wmv -o D:\transfer\flv\1.flv -of lavf -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=1:mv0:trell:v4mv:cbp:last_pred=1Big Smileia=-1:cmp=6:vb_strategy=1 -vf scale=300:-3 -ofps 12 -srate 22050")
    response.write "R=" & R & "<BR>"
    Set Executor = nothing

    好玩的事情發生了
    在WINDOWS 2000 Server上我可以正確的轉換成功 可以看到 D:\transfer\flv\1.flv 查看它的檔案SIZE是 868KB (這個是正確的)
    但在WINDOWS 2003 Server上我可以正確轉換, 可以看到 D:\transfer\flv\1.flv 但是查看它的檔案SIZE是 0KB (這個是錯誤的)

    我在想是不是WINDOWS 2003 透過DLL取處理程序時,權限問題把他擋住了 ,
    但我一直找不到什麼原因擋住了
    可否請大大幫我這個忙呢

     

    2008年1月3日 上午 09:54

解答

  •  

    感謝璉璉大大的回應

    IUSR_servername有完整權限這個已經開啟了 但還是失敗

     

    不過經過許多朋友一起努力測試後 , 終於找到解決方法

    將 2003 Server IIS 中新增一個應用程式集區 並 在身份識別頁簽中 的第一個選項 預先定義的 原本是網路服務

    我將下拉式清單內容改為 本機系統一切都正常了

     

    感謝指教

     

     

    2008年1月8日 下午 05:06

所有回覆

  • 為了證明是不是 mencoder.exe 造成的問題

    我寫了一個批次檔 叫做 test.bat

    COPY D:\transfer\temp\20071222053146542489821.wmv D:\transfer\flv\2.wmv

     

    然後透過我包的DLL

    寫了一隻ASP

    Set Executor = Server.CreateObject("fuu.DoTransferFLV")
    R = Executor.DoExecCmd("D:\transfer\temp\test1.bat")
    response.write "R=" & R & "<BR>"
    Set Executor = nothing

     

    在WINDOS2000 SERVER可以正確複製檔案

    在WINDOS2003 SERVER無法正確複製檔案

     

    所以更讓我覺得 在 WINDOWS 2003 SERVER上面是不是有些權限設定或是什麼原因擋起來了

    但是就一直找不到

    可不可以請大大幫忙我呢

    2008年1月3日 上午 10:38
  • ActiveX DLL 本身權限是繼承呼叫端,不需要另外設定,所以建議你檢查

    D:\transfer\temp 這個目錄是否有授權給 IUSR_servername有完整權限

     

    這種東西用 ASPNET 會比較簡單吧... 也不用寫個 ActiveX DLL ,直接用代理帳號來跑~

    2008年1月3日 下午 04:25
    版主
  •  

    感謝璉璉大大的回應

    IUSR_servername有完整權限這個已經開啟了 但還是失敗

     

    不過經過許多朋友一起努力測試後 , 終於找到解決方法

    將 2003 Server IIS 中新增一個應用程式集區 並 在身份識別頁簽中 的第一個選項 預先定義的 原本是網路服務

    我將下拉式清單內容改為 本機系統一切都正常了

     

    感謝指教

     

     

    2008年1月8日 下午 05:06