我有一个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;
}