调用外部应用程序并等待结果,而不会阻止其他任务

时间:2019-04-01 16:57:42

标签: c#

我有一个VBA类,需要进入C#.net世界,以支持将供应商迁移到后端Web API。在VBA中为Web服务添加API调用不能有效利用资源。实践证明,将C#用于显式COM接口比使用VB.Net隐式COM工具要好。类中没有用户界面。

当前解决方案使用本地EXE处理文件并提供响应文件。供应商正在努力消除EXE并替换为Web API。此应用程序(EXE)具有一些我已编写的怪癖,以使其能够执行任务。这使用一系列Sleep和DoEvents调用来允许应用程序运行。在供应商另有规定之前,我必须继续支持并使用EXE。

EXE的古怪之处在于,它一次只能处理1个文件,在处理完成后不会关闭,如果保持打开状态就不会处理另一个文件,并且如果跌落到后台也不会运行。

我必须重新编码现有功能,然后一旦供应商迁移帐户,便能够“切换到”新的Web API。

除等待响应文件外,已转换了大多数功能,并且仍将时间片分配给启动的EXE,尝试睡眠并获得启动的APP的死锁。因此,寻找如何正确启动EXE的方法,让其进行处理并检查对响应文件的独占访问。这需要在x秒后超时,以便操作员可以强制退出或继续重试。

下面是用于处理需求的VBA代码

      'Vars are set elsewhere removed as not code in question.

  ReturnValue = Shell((sDazPath & sDazEXE & " " & mPrintFileIn), vbMinimizedFocus)
  On Error Resume Next
  AppActivate ReturnValue
  On Error GoTo 0

  DoEvents
  Count1 = 0
  Wait4File = True
  Do While Wait4File And Count1 < lWaitCnt 'lWaitCount is set elsewhere
    Count1 = Count1 + 1
    Wait4File = Not FileDoneGrowing(mPrintFileOut) 'function returns true if done
    If Wait4File And Count1 >= lWaitCnt Then
      sTemp = "Unsuccessful import of Postage results. " & vbCrLf
      sTemp = sTemp & "You may wait to see if a label prints and then retry import. "
      sTemp = sTemp & " If no label prints check internet access and/or Endicia Network "
      sTemp = sTemp & "Status." & vbCrLf & vbCrLf & "Do you wish to re-try Endicia import?"
      sPopAsk = PSI.msg(sTemp, "Processing Result Import", psiMsgHelp, "Yes", "No")
      If sPopAsk = "Yes" Then
        Wait4File = Not FileDoneGrowing(mPrintFileOut) 'function returns true if done
        Count1 = 0
      End If
    End If
  Loop


  '============================== END Code that Starts and waits

  Private Function FileDoneGrowing(sPathFilename As String) As Boolean

  Dim fs As Object
  Dim f As Object
  Dim lLastSize As Long
  Dim lCurSize As Long
  Dim i As Long
  Dim iFileNo As Integer
  Dim bOk As Boolean

  bOk = False
  lLastSize = 0
  If ValidFile(sPathFilename) Then

    'get initial sizes
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFile(sPathFilename) 'processing from this one
    lLastSize = f.Size
    DoEvents 'give other things a chance
    Set f = Nothing
    For i = 0 To 500 'just pause a moment
      DoEvents 'Let system think
    Next
    Set f = fs.GetFile(sPathFilename) 'processing from this one
    lCurSize = f.Size
    Set f = Nothing

    Do While (lLastSize <> lCurSize) Or (lCurSize = 0)
      lLastSize = lCurSize
      For i = 0 To 500 'just pause a moment
        DoEvents 'Let system think
      Next
      Set f = fs.GetFile(sPathFilename) 'processing from this one
      lCurSize = f.Size
      Set f = Nothing
      DoEvents
    Loop

    bOk = IIf(lLastSize = lCurSize, True, False)
  Else 'no file not done!
    bOk = False
  End If

  DoEvents

  If bOk Then 'we think the file is done growing, can we get exclusive access?
    On Error Resume Next
    iFileNo = FreeFile(0)
    Open sPathFilename For Binary Lock Read Write As #iFileNo
    If Err.Number Then 'if no error we have exclusive access
      bOk = False
    Else
      Close #iFileNo
    DoEvents
    End If
  End If
  FileDoneGrowing = bOk

End Function

以下是我到目前为止在C#中所拥有的内容:

/// <summary>
/// Calls the Daz application to process the XML file, sets return properities as available.
/// </summary>
/// <returns>0=Success; -#=Internal fail; #=Result/error from call</returns>
private int DazLabelRequest()
{

  Message = "";
  int iOk = -299;
  int iDazRunning = -200;

  //ToDo: Build out Daz Label Request call
  Message = "Not Implemented DazLabelRequest"; //Debug only (Not Implemented)
  iDazRunning = LaunchDazApp("");

  //Debug: Blow off about a minute then kill app.
  Thread.Sleep(10000);

  //Todo: add code to verify we've received response file.
  //Don't add response time with just sleep check for result file done growing, then verify readability
  //then close Daz and parse results.

  if (iDazRunning == 0)
  {
    iDazRunning = CloseDazApp();
  }
  return iOk;
}

private int FindDazWindow()
{
  Process[] DazProc = Process.GetProcessesByName("Daz");
  return (DazProc.Length > 0) ? 0 : -1;
}

/// <summary>
/// Launces the Daz Exe with a parameter of XML file to process
/// </summary>
/// <returns>Integer: 0=Success, -# failed</returns>
private int LaunchDazApp(string XML_FQN)
{

  long lRetries = 0;
  int iDazFound = -201;

  Daz = new Process();
  ProcessStartInfo StartInfo = new ProcessStartInfo();

  StartInfo.FileName = DazAppFQN;
  StartInfo.UseShellExecute = true;
  if (!NED.IsBlankStr(XML_FQN))
  {
    StartInfo.Arguments = XML_FQN;
  } 
  Daz = Process.Start(StartInfo);

  //if (!Daz.HasExited)
  //{
    lRetries = 0;
    while (FindDazWindow() != 0 && lRetries <= RetryCount)
    {
      Thread.Sleep(250);
      lRetries++;
    }

    iDazFound = FindDazWindow();
    if (iDazFound != 0)
    {
      Message = "Daz window not found, either took too long or failed to launch.";
      return -201;
    } //Daz should launch within a timely manner. Fail safe check here.
  //} //if(Daz.Start())

  return 0; //we're good to go.
}

private int CloseDazApp()
{
  int iOK = 0;

  try
  {
    Daz.Kill();
    Daz.Close();
    return 0;
  }
  catch (Exception ex)
  {

    iOK = -99;
  }
  return iOK;
}

0 个答案:

没有答案