Pregunta

Intentando escribir un cmdlet de PowerShell que silenciará el sonido al inicio, a menos que ya esté silenciado, y lo deshabilitará al final (solo si no estaba silenciado, para empezar). No se pudo encontrar ningún objeto PoweShell o WMI que pudiera usar. Estaba jugando con el uso de funciones de Win32 como auxGetVolume o auxSetVolume , pero no lograba hacerlo trabajo (¿cómo leer los valores de un IntPtr?).

Estoy usando V2 CTP2. ¿Alguna idea, gente?

¡Gracias!

¿Fue útil?

Solución

Parece que no hay una manera rápida y fácil de ajustar el volumen ... Si tiene experiencia con c ++, podría hacer algo con esta publicación de blog , donde Larry Osterman describe cómo llamar a Interfaz IAudioEndpointVolume desde la plataforma api (para Vista, XP puede ser más difícil de lo que he encontrado en algunas búsquedas).

V2 le permite compilar el código en línea (a través de Add-Type), por lo que podría ser una opción.

Otros consejos

A partir de Vista, debe usar Core Audio API para controlar el volumen del sistema. Es una API de COM que no admite la automatización y, por lo tanto, requiere una gran cantidad de repeticiones para usar desde .NET y PowerShell.

De todos modos, el código de abajo le permite acceder a las propiedades [Audio] :: Volume y [Audio] :: Mute de PowerShell. Esto también funciona en una computadora remota que podría ser útil. Simplemente copie y pegue el código en su ventana de PowerShell.

Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
  // f(), g(), ... are unused COM method slots. Define these if you care
  int f(); int g(); int h(); int i();
  int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
  int j();
  int GetMasterVolumeLevelScalar(out float pfLevel);
  int k(); int l(); int m(); int n();
  int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
  int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
  int f(); // Unused
  int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }

public class Audio {
  static IAudioEndpointVolume Vol() {
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioEndpointVolume epv = null;
    var epvid = typeof(IAudioEndpointVolume).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  }
  public static float Volume {
    get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
    set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
  }
  public static bool Mute {
    get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
    set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
  }
}
'@

Ejemplo de uso:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>

Hay envoltorios .NET más completos que existen para la API de Core Audio si los necesita, pero no conozco un conjunto de cmdlets compatibles con PowerShell.

P.S. La respuesta de Diogo parece inteligente pero no funciona para mí.

Use los siguientes comandos en una secuencia de comandos de PowerShell ps1:

$obj = new-object -com wscript.shell 
$obj.SendKeys([char]173)

La respuesta de Alexandre se ajusta a mi situación, pero su ejemplo no funciona debido a errores de compilación relacionados con el espacio de nombres de 'var'. Parece que las versiones más nuevas / diferentes de .net pueden hacer que el ejemplo no funcione. Si descubrió que recibió errores de compilación, esta es una versión alternativa que puede probar en esos casos:

Add-Type -Language CsharpVersion3 -TypeDefinition @'
using System.Runtime.InteropServices;

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
  // f(), g(), ... are unused COM method slots. Define these if you care
  int f(); int g(); int h(); int i();
  int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
  int j();
  int GetMasterVolumeLevelScalar(out float pfLevel);
  int k(); int l(); int m(); int n();
  int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
  int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
  int f(); // Unused
  int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }

public class Audio {
  static IAudioEndpointVolume Vol() {
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioEndpointVolume epv = null;
    var epvid = typeof(IAudioEndpointVolume).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  }
  public static float Volume {
    get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
    set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
  }
  public static bool Mute {
    get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
    set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
  }
}
'@

El uso es el mismo:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>

Podría disimular al gato de otra manera simplemente administrando el servicio de audio de Windows. Deténgalo para silenciar, inícielo para dejar de silenciar.

No encontré cómo hacer esto en PowerShell, pero hay una utilidad de línea de comandos llamada NirCmd que hará el truco ejecutando este comando:

C: \ utils \ nircmd.exe mutesysvolume 2

NirCmd está disponible gratis aquí: http://www.nirsoft.net/utils/nircmd.html

Solución en vbscript:

Set WshShell = CreateObject("WScript.Shell")
For i = 0 To 50
  WshShell.SendKeys(chr(174))
  WScript.Sleep 100
Next

Las teclas reducen el volumen en 2 cada vez.

Sé que no es PowerShell, pero la combinación de las respuestas de Michael y Diogo ofrece una solución VBScript de una línea:

CreateObject("WScript.Shell").SendKeys(chr(173))

Bofetea esto en mute.vbs , y puedes hacer doble clic para activar el silencio

  • todavía funciona en Windows 10 (10586.104)
  • no es necesario que Set-ExecutionPolicy como lo haría con PowerShell

Echa un vistazo a mi respuesta a ¿Cambiar el nivel de audio desde powershell?

Set-DefaultAudioDeviceMute
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top