簡體   English   中英

調用批處理文件后,服​​務在WaitForExit處掛起

[英]Service hangs up at WaitForExit after calling batch file

我有一個服務有時會調用批處理文件。 批處理文件需要5-10秒才能執行:

System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process
    proc.StartInfo.FileName = fileName;
    proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
    proc.StartInfo.CreateNoWindow = true;
    proc.Start();
    proc.WaitForExit();

當我在控制台中運行相同的代碼時,該文件確實存在並且代碼可以正常工作。 但是當它在服務中運行時,它會在WaitForExit()處掛起。 我必須從Process中刪除批處理文件才能繼續。 (我確定該文件存在,因為我可以在進程列表中看到它。)

我該如何修復這個掛斷?

更新#1:

凱文的代碼允許我獲得輸出。 我的一個批處理文件仍然掛起。

“C:\\ EnterpriseDB \\ Postgres \\ 8.3 \\ bin \\ pg_dump.exe”-i -h localhost -p 5432 -U postgres -F p -a -D -v -f“c:\\ backupcasecocher \\ backupdateevent2008.sql”-t “\\”public \\“。\\”dateevent \\“”“DbTest”

另一個批處理文件是:

“C:\\ EnterpriseDB \\ Postgres \\ 8.3 \\ bin \\ vacuumdb.exe”-U postgres -d DbTest

我檢查了路徑, postgresql路徑沒問題。 輸出目錄確實存在,仍然可以在服務外部運行。 有任何想法嗎?

更新#2:

我為proc.StartInfo.FileName編寫了“C:\\ EnterpriseDB \\ Postgres \\ 8.3 \\ bin \\ pg_dump.exe”而不是批處理文件的路徑,並將所有參數添加到proc.StartInfo.Arguments 結果沒有變化,但我在進程窗口中看到了pg_dump.exe 同樣,這只發生在服務中。

更新#3:

我已經與管理員組中的用戶一起運行該服務,但無濟於事。 我為服務的用戶名和密碼恢復了null

更新#4:

我創建了一個簡單的服務來在事件日志中編寫跟蹤並執行包含“dir”的批處理文件。 它現在將掛在proc.Start(); - 我嘗試將帳戶從LocalSystem更改為User ,我設置了admnistrator用戶和密碼,但仍然沒有。

這是我用來執行批處理文件的內容:

proc.StartInfo.FileName                 = target;
proc.StartInfo.RedirectStandardError    = true;
proc.StartInfo.RedirectStandardOutput   = true;
proc.StartInfo.UseShellExecute          = false;

proc.Start();

proc.WaitForExit
    (
        (timeout <= 0)
            ? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
                NO_SECONDS_IN_A_MINUTE
    );

errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();

outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();

我不知道是否會為你做這個伎倆,但我沒有懸掛的問題。

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    namespace VG
    {
        class VGe
        {
            [STAThread]
            static void Main(string[] args)
            {
                Process proc = null;
                try
                {                
                    string targetDir = string.Format(@"D:\adapters\setup");//this is where mybatch.bat lies
                    proc = new Process();
                    proc.StartInfo.WorkingDirectory = targetDir;
                    proc.StartInfo.FileName = "mybatch.bat";
                    proc.StartInfo.Arguments = string.Format("10");//this is argument
                    proc.StartInfo.CreateNoWindow = false;
                    proc.Start();
                    proc.WaitForExit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception Occurred :{0},{1}", ex.Message,ex.StackTrace.ToString());
                }
            }
        }
    }
            string targetDir = string.Format(@"D:\");//PATH
            proc = new Process();
            proc.StartInfo.WorkingDirectory = targetDir;
            proc.StartInfo.FileName = "GetFiles.bat";
            proc.StartInfo.Arguments = string.Format("10");//argument
            proc.StartInfo.CreateNoWindow = false;
            proc.Start();
            proc.WaitForExit();

經過測試,工作清晰。

批處理文件有什么作用? 您確定該進程是否已啟動並具有足夠的權限來執行批處理文件? 服務可以限制在允許的范圍內。

還要確保你是否正在使用copy命令來覆蓋你執行類似操作的文件:

echo Y | copy foo.log c:\backup\

此外,請確保您使用批處理命令的完整路徑等。如果批處理文件以某種“控制台”模式啟動GUI應用程序,這可能也是一個問題。 請記住,服務沒有“桌面”(除非您啟用“與桌面交互”)以繪制任何類型的窗口或消息框。 在您的程序中,您可能希望打開stdout和stderr管道並在執行期間從中讀取它們,以防您收到任何錯誤消息或任何內容。

Web服務可能正在作為IUSR帳戶或匿名帳戶執行,因此這可能是您的問題。 如果它在控制台中運行時有效,那只是第一步。 :)

我不記得是否有System.Diagnostics。 僅在調試時可用。 可能不是,但其中一些可能是。 我將不得不檢查你的情況。

希望這會給你一些想法。

拉里

pg_dump.exe可能會提示用戶輸入。 此數據庫是否需要身份驗證 您是否依賴於服務不存在的任何環境變量? 我不知道pg_dump但是它會提示輸入的其他可能原因是什么?

我將采取的下一步是啟動調試器,看看你是否可以告訴程序正在等待什么。 如果您在匯編中進行調試,則可以使用ProcExp,FileMon等工具獲取正在發生的事情的IDEA。

作為一個Windows服務,而不是一個Web服務,會產生很大的不同。 無論如何,您是否嘗試過設置“允許服務與桌面交互”的建議?

如果您絕望,可以嘗試啟動cmd.exe而不是批處理文件。 然后,使用cmd.exe的cmd行參數,您可以讓IT啟動批處理文件。 如果打開與桌面的交互,這可能會為您提供cmd提示窗口以查看實際輸出。

有關cmd.exe的完整幫助,只需鍵入cmd /? 在任何命令提示符下。

拉里

這是解決方案。 解決方案不明確,因為我已經改變了很多時間代碼,現在它正在工作!

我曾試圖使用一個用戶帳戶,但它不起作用。 使用LocalSystem。 這是執行的代碼,主要是Kevin給我的。

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = fileName;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.UseShellExecute = false;


            proc.Start();
            proc.WaitForExit();
            output1 = proc.StandardError.ReadToEnd();
            proc.WaitForExit();
            output2 = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();

謝謝大家,我會向所有人投票並接受凱文,因為他從一開始就幫助我。 非常奇怪,因為它現在有效......

Daok,看起來你唯一改變的是初始WaitForExit()的超時時間。 你需要非常小心。 如果事情確實發生掛起你的服務,它永遠不會返回(和好,喜歡它幾乎工作一直是你迄今..嘿嘿),但是它會不利於最終用戶...

現在,也許您知道是什么導致它掛起,您可以進一步調試並找到完整的解決方案......

那,或者在你可以監控的某個線程中將其關閉,如果掛起的時間過長就會終止。

只需要我2美分,這通常不是很多。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM