从Windows服务(C#)播放wav文件

时间:2010-01-26 23:15:43

标签: c# windows-services

我需要从作为Windows服务运行的C#应用​​程序中播放wav文件。我已经尝试了System.Media.SoundPlayer和对WinMM.dll的P / Invoke调用(这可能是SoundPlayer正在做的事情)。

[DllImport("WinMM.dll")]
private static extern bool PlaySound(string fname, int Mod, int flag); 

如果我将我的代码作为控制台应用程序运行,则声音会播放。当我从服务中运行它时,没有运气,我想我并不感到惊讶。

那么有没有办法从Windows服务播放声音? DirectSound会有帮助吗?或者我是否会被困在编写控制台应用程序并让Windows服务应用程序与它作为中介进行通信?

提前致谢

4 个答案:

答案 0 :(得分:9)

通过使用Windows Core Audio API,至少在Windows 7(很可能是Vista)上播放来自服务的wav文件肯定是可能的。我最近通过使用NAudio制作小型测试服务来验证这一点。我刚刚下载了NAudio源并从他们的NAudioDemo项目中复制了“Wsapi”部分。这是在Windows 7企业版64位上,但我认为不重要。该服务使用的是LocalSystem帐户 为了记录,在嵌入式设置中播放来自服务的声音是完全合法的事情。

答案 1 :(得分:1)

答案 2 :(得分:0)

您选择了错误的应用类型。 Windows服务适用于以非交互方式执行的较长时间运行的应用程序,无论是否有人登录到计算机。例如SQL Server,IIS等。

在Windows Vista及更高版本中,您也无法通过Windows服务显示用户界面窗口。对于Windows XP,2000 Server,您可以显示MessageBox,但不建议大多数服务使用。

因此,一般来说,服务不允许“互动”,包括播放声音,多媒体等。

您需要将应用程序类型更改为普通的控制台/ Windows窗体应用程序,或者在不播放服务声音的情况下直播。

有关详细信息,请参阅interactive services上的此页面以及MSDN上的相关页面。

答案 3 :(得分:0)

您可以通过Windows Vista或更高版本中的winmm.dll通过PlaySound API执行此操作。微软为“系统声音”添加了单独的会话。即使只是添加一个标志,它甚至可以从服务中使用。

我已经正确地格式化了这个,以避免c#2017 IDE在DllImport上摆动的问题不在名为' NativeMethods'。

的类中。
using System.Runtime.InteropServices;
namespace Audio
{
    internal static class NativeMethods
    {
        [DllImport("winmm.dll", EntryPoint = "PlaySound", SetLastError = true, CharSet = CharSet.Unicode, ThrowOnUnmappableChar = true)]
        public static extern bool PlaySound(
            string szSound,
            System.IntPtr hMod,
            PlaySoundFlags flags);

        [System.Flags]
        public enum PlaySoundFlags : int
        {
            SND_SYNC = 0x0000,/* play synchronously (default) */
            SND_ASYNC = 0x0001, /* play asynchronously */
            SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
            SND_MEMORY = 0x0004, /* pszSound points to a memory file */
            SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */
            SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */
            SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
            SND_ALIAS = 0x00010000,/* name is a registry alias */
            SND_ALIAS_ID = 0x00110000, /* alias is a pre d ID */
            SND_FILENAME = 0x00020000, /* name is file name */
            SND_RESOURCE = 0x00040004, /* name is resource name or atom */
            SND_PURGE = 0x0040,  /* purge non-static events for task */
            SND_APPLICATION = 0x0080, /* look for application specific association */
            SND_SENTRY = 0x00080000, /* Generate a SoundSentry event with this sound */
            SND_RING = 0x00100000, /* Treat this as a "ring" from a communications app - don't duck me */
            SND_SYSTEM = 0x00200000 /* Treat this as a system sound */
        }
    }
    public static class Play
    {
        public static void PlaySound(string path, string file = "")
        {            
            NativeMethods.PlaySound(path + file, new System.IntPtr(), NativeMethods.PlaySoundFlags.SND_ASYNC | NativeMethods.PlaySoundFlags.SND_SYSTEM);
        }
    }
}