2010-06-18 63 views
2

我正在开发一个VB.NET Windows服务,它正在审核BMS数据库中的新警报,并打电话远程警告操作员。我目前使用的是.NET TAPI封装和SAPI 5.3互操作程序集,并且我正在通过电话说话的步骤如下:通过调制解调器从Windows服务播放语音

  1. 初始化TAPI接口;
  2. 拨打运营商号码;
  3. 取语音调制解调器波形输出设备编号
  4. 将语音输出设置为该设备编号;
  5. 让SAPI发挥神奇功效。

如果我将代码编译为Windows控制台或表单应用程序,但只要将它编译并作为Windows服务运行,第5步就不会发生 - 语音调制解调器调用但保持静音;一切工作,甚至数字监控。 现在我知道windows服务不应该与桌面交互,所以诸如UI元素和播放声音之类的东西是否定的,但我正在努力寻找一种不涉及使用wave API的替代方案,并且可以在合理的时间内开发。有任何想法吗?

回答

0

SAPI通常需要某种类型的消息泵和窗口句柄,而这些Windows服务通常不具有。您可以创建一个message-only window以稍微安全的方式处理这些消息(请注意,服务中的任何hwnd都会为您打开一个shatter attack,因此请确保您以用户的身份运行服务,而不是SYSTEM或LocalMachine减少攻击面)。您还需要抽取消息(通过Application.Run或Application.DoEvents等)。

+0

该服务现在在启动时创建一个消息窗口,如你所建议的。现在我该怎么做?我如何告诉SAPI使用该窗口的句柄?一旦窗口创建或稍后再启动消息循环?谢谢你的帮助。 – Samuele 2010-06-23 10:49:24

+0

通常情况下,您需要启动一个线程,该线程除了泵送消息外(并且知道何时关闭)。 SAPI是自由线程的,因此您可以跨线程传递SAPI接口指针而不会出现任何问题。 – 2010-06-23 16:52:46

0

最后我引用我的Windows服务项目的Windows窗体项目,并创建在子的OnStart形式:

Protected Overrides Sub OnStart(ByVal args() As String) 
     HelperThread = New Threading.Thread(AddressOf CreateMOWindow) 
     HelperThread.TrySetApartmentState(Threading.ApartmentState.STA) 
     HelperThread.Start() 
End Sub 

Private Sub CreateMOWindow() 
     Dim frm As New AlarmVoiceTest.AlarmVoiceTest 
     Windows.Forms.Application.Run(frm) 
End Sub 

形式没有显示出来,当然(但是我不需要它)和SAPI按预期工作。我认为这不是最简单的方法来完成,但我有点时间:)