I'm developing a VB.NET Windows service which is costantly checking a BMS database for new alarms and making phone calls to warn operators remotely. I'm currently using a .NET TAPI wrapper and the SAPI 5.3 interop assembly, and the steps I'm taking to speak over the phone are:
- Initialize TAPI interface;
- Make the call to the operator's number;
- Take the voice modem waveOut device id
- Set the voice output to that device id;
- Let SAPI do the magic.
This is all working fine if I compile the code as a Windows console or forms application, but as soon as I compile and run it as a Windows Service, step 5 never occurs - voice modem calls but stays silent; everything else works, even digit monitoring. Now I know windows services are not supposed to interact with the desktop, so things like UI elements and playing sounds are a no-no, but I'm struggling to find an alternative which doesn't involve using the wave API and can be developed in a reasonable timeframe. Any ideas?
SAPI typically needs some sort of message pump and a window handle, which Windows services typically don't have. You could create a message-only window to handle the messages in a slightly safer manner (note that any hwnd in a service will open you up to a shatter attack, so make sure you're running your service as a user, and not as SYSTEM or LocalMachine to reduce the attack surface). You'll also need to pump the messages (via Application.Run or Application.DoEvents or the like) as well.
I ended up referencing the windows forms project in my Windows Service project, and creating the form in the OnStart sub:
The form isn't showing up of course (but I don't need it to), and SAPI is working as expected. I reckon this is not the cleanest way to accomplish that, but I'm kinda running out of time :)