1

我有一个控制台应用程序可以手动运行,但是当它由 SQL Server 代理执行时,它根本无法运行,并且还会吐出一条奇怪的错误消息,如下所示:-

Executed as user: I01SVTD21\SYSTEM.
Unhandled Exception: System.IO.IOException: The handle is invalid.       
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)     
     at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
     at System.Console.Clear()
     at ActiveDirectoryImport.Program.SendReports()
     at ActiveDirectoryImport.Program.GetUserInfo()
     at ActiveDirectoryImport.Program.Main(String[] args).
Process Exit Code 255.  The step failed.

现在这可能看起来不像一个奇怪的错误消息,直到您意识到 ActiveDirectoryImport.Program.SendReports() 是 ActiveDirectoryImport.Program.GetUserInfo() 调用的最后一个方法,所以看起来大部分代码已经运行。然而,情况并非如此,因为代码所做的第一件事就是更新数据库表中的记录,这并没有发生......

所以我有两个问题。当手动从同一位置正常运行时,为什么作业完全失败?而且,为什么它告诉我它在代码中很晚才失败,而它显然还没有那么远?

控制台应用程序确实写入控制台屏幕,但不接受用户输入。它基本上将应用程序的状态写入屏幕,这似乎是错误的......

任何帮助表示赞赏。

4

1 回答 1

2

也许这应该是一条评论,但从异常(以及一些心理调试)来看,这是非常“明显”的:

System.Console.Clear()当进程的标准输出未附加到控制台的输出时,这将导致您看到的异常。当您从命令行调用应用程序并重定向其输出时,最容易重现:

MyConsoleApplication.exe > NUL

检查您的 SQL 代理命令行是否不包含这样的重定向 - 实际上,我不确定,但 SQL 代理可能会自动重定向您的进程的输出以将其显示在它的日志中。所以最好的办法是System.Console.Clear()完全删除调用,可以说无论如何在这种情况下它没有多大意义。或者,只需像这样包装它

   try
   {
      System.Console.Clear();
   }
   catch (IOException)
   {
   }

忽略此特定错误。请注意,在这种情况下,其他控制台功能/属性(如CursorVisible, )也可能会抛出一个IOException

顺便说一句,CursorVisible实际上是编写这样一个辅助函数的“好”候选人:

 bool ConsoleInputIsRedirected
 {
     get
     {
         try
         {
             bool f = System.Console.CursorVisible;
             return false;
         }
         catch (IOException)
         {
             return true;
         }
     }
 }

如果需要,您可以使用此函数有条件地执行仅在输出未重定向时才有效的代码(如Clear())。

于 2012-07-04T12:07:32.223 回答