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

我需要从作为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服务应用程序与它作为中介进行通信?

提前致谢

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

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

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

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

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

有关详细信息,请参阅MSDN上交互式服务和相关页面上的此页面。

您可以通过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); } } }