-
-
Save p0w3rsh3ll/10f8d42d599a772a050b675fa4ff467b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -RunAsAdministrator | |
#Requires -PSEdition Desktop | |
[CmdletBinding(SupportsShouldProcess)] | |
Param() | |
DynamicParam { | |
$Dictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary | |
#region helper function | |
Function New-ParameterAttributCollection { | |
[CmdletBinding()] | |
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] | |
Param( | |
[Switch]$Mandatory, | |
[Switch]$ValueFromPipeline, | |
[Switch]$ValueFromPipelineByPropertyName, | |
[String]$ParameterSetName, | |
[Parameter()] | |
[ValidateSet( | |
'Arguments','Count','Drive','EnumeratedArguments','Length','NotNull', | |
'NotNullOrEmpty','Pattern','Range','Script','Set','UserDrive' | |
)][string]$ValidateType, | |
[Parameter()] | |
$ValidationContent | |
) | |
Begin { | |
}Process { | |
$c = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$a = New-Object System.Management.Automation.ParameterAttribute | |
if ($Mandatory) { | |
$a.Mandatory = $true | |
} | |
if ($ValueFromPipeline) { | |
$a.ValueFromPipeline = $true | |
} | |
if ($ValueFromPipelineByPropertyName) { | |
$a.ValueFromPipelineByPropertyName=$true | |
} | |
if ($ParameterSetName) { | |
$a.ParameterSetName = $ParameterSetName | |
} | |
$c.Add($a) | |
if ($ValidateType -and $ValidationContent) { | |
try { | |
$c.Add((New-Object "System.Management.Automation.Validate$($ValidateType)Attribute"( | |
$ValidationContent | |
))) | |
} catch { | |
Throw $_ | |
} | |
} | |
$c | |
} | |
End {} | |
} | |
#endregion | |
try { | |
$audioDevices = Get-PnpDevice -ErrorAction Stop | | |
Where-Object {$_.Class -eq 'AudioEndpoint' } | | |
Select-Object -Property Caption,Status,DeviceID | | |
Foreach-Object { | |
[PSCustomObject]@{ | |
DeviceName = $_.Caption | |
Status = $_.Status | |
Id = ($_.DeviceID -split '\.')[4] | |
} | |
} | |
} catch { | |
Throw 'Failed to enumerate audio devices' | |
} | |
#region param DeviceName | |
$Dictionary.Add( | |
'DeviceName', | |
(New-Object System.Management.Automation.RuntimeDefinedParameter( | |
'DeviceName', | |
[string], | |
(New-ParameterAttributCollection -Mandatory -ValidateType Set -ValidationContent ( | |
$audioDevices | ForEach-Object { $_.DeviceName } | |
)) | |
)) | |
) | |
$Dictionary | |
} | |
Begin {} | |
Process {} | |
End { | |
#Source: https://github.com/SomeProgrammerGuy/Powershell-Default-Audio-Device-Changer/blob/master/Set-DefaultAudioDevice.ps1 | |
$cSharpSourceCode = @" | |
using System; | |
using System.Runtime.InteropServices; | |
// eConsole: Games, system notification sounds, and voice commands. // | |
// eMultimedia: Music, movies, narration, and live music recording. // | |
// eCommunications: Voice communications (talking to another person). // | |
// ERole_enum_count: The number of members in the ERole enumeration // | |
// (not counting the ERole_enum_count member). // | |
public enum ERole : uint | |
{ | |
eConsole = 0, | |
eMultimedia = 1, | |
eCommunications = 2, | |
ERole_enum_count = 3 | |
} | |
// Undocumented COM-interface IPolicyConfig. // | |
// Use to set default audio Capture / Render endpoint. // | |
[Guid("F8679F50-850A-41CF-9C72-430F290290C8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
internal interface IPolicyConfig | |
{ | |
// HRESULT GetMixFormat(PCWSTR, WAVEFORMATEX **); | |
[PreserveSig] | |
int GetMixFormat(); | |
// HRESULT STDMETHODCALLTYPE GetDeviceFormat(PCWSTR, INT, WAVEFORMATEX **); | |
[PreserveSig] | |
int GetDeviceFormat(); | |
// HRESULT STDMETHODCALLTYPE ResetDeviceFormat(PCWSTR); | |
[PreserveSig] | |
int ResetDeviceFormat(); | |
// HRESULT STDMETHODCALLTYPE SetDeviceFormat(PCWSTR, WAVEFORMATEX *, WAVEFORMATEX *); | |
[PreserveSig] | |
int SetDeviceFormat(); | |
// HRESULT STDMETHODCALLTYPE GetProcessingPeriod(PCWSTR, INT, PINT64, PINT64); | |
[PreserveSig] | |
int GetProcessingPeriod(); | |
// HRESULT STDMETHODCALLTYPE SetProcessingPeriod(PCWSTR, PINT64); | |
[PreserveSig] | |
int SetProcessingPeriod(); | |
// HRESULT STDMETHODCALLTYPE GetShareMode(PCWSTR, struct DeviceShareMode *); | |
[PreserveSig] | |
int GetShareMode(); | |
// HRESULT STDMETHODCALLTYPE SetShareMode(PCWSTR, struct DeviceShareMode *); | |
[PreserveSig] | |
int SetShareMode(); | |
// HRESULT STDMETHODCALLTYPE GetPropertyValue(PCWSTR, const PROPERTYKEY &, PROPVARIANT *); | |
[PreserveSig] | |
int GetPropertyValue(); | |
// HRESULT STDMETHODCALLTYPE SetPropertyValue(PCWSTR, const PROPERTYKEY &, PROPVARIANT *); | |
[PreserveSig] | |
int SetPropertyValue(); | |
// HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(__in PCWSTR wszDeviceId, __in ERole role); | |
[PreserveSig] | |
int SetDefaultEndpoint( | |
[In] [MarshalAs(UnmanagedType.LPWStr)] string wszDeviceId, | |
[In] [MarshalAs(UnmanagedType.U4)] ERole role); | |
// HRESULT STDMETHODCALLTYPE SetEndpointVisibility(PCWSTR, INT); | |
[PreserveSig] | |
int SetEndpointVisibility(); | |
} | |
[ComImport, Guid("870AF99C-171D-4F9E-AF0D-E63DF40C2BC9")] | |
internal class _CPolicyConfigClient | |
{ | |
} | |
public class PolicyConfigClient | |
{ | |
public static int SetDefaultDevice(string deviceID) | |
{ | |
IPolicyConfig _policyConfigClient = (new _CPolicyConfigClient() as IPolicyConfig); | |
try | |
{ | |
Marshal.ThrowExceptionForHR(_policyConfigClient.SetDefaultEndpoint(deviceID, ERole.eConsole)); | |
Marshal.ThrowExceptionForHR(_policyConfigClient.SetDefaultEndpoint(deviceID, ERole.eMultimedia)); | |
Marshal.ThrowExceptionForHR(_policyConfigClient.SetDefaultEndpoint(deviceID, ERole.eCommunications)); | |
return 0; | |
} | |
catch | |
{ | |
return 1; | |
} | |
} | |
} | |
"@ | |
try { | |
Add-Type -TypeDefinition $cSharpSourceCode -ErrorAction Stop | |
} catch { | |
Write-Error 'Failed to add cSharp Code' | |
} | |
Function Set-DefaultAudioDevice { | |
[CmdletBinding(SupportsShouldProcess)] | |
[OutputType([System.Int32])] | |
Param ( | |
[parameter(Mandatory)] | |
[string]$deviceId | |
) | |
Begin {} | |
Process {} | |
End { | |
try { | |
if ($pscmdlet.ShouldProcess("$($deviceId)", 'Set default audio device to:')) { | |
[PolicyConfigClient]::SetDefaultDevice("{0.0.0.00000000}.$($deviceId)") | |
} | |
} catch { | |
Write-Error "Failed to set $($DeviceName) as default because $($_.Exception.Message)" | |
} | |
} | |
} | |
$d = $audioDevices | Where-Object { $_.DeviceName -eq "$($PSBoundParameters['DeviceName'])" } | |
try { | |
if ($pscmdlet.ShouldProcess("$($d.DeviceName)", 'Set default audio device to:')) { | |
$r = Set-DefaultAudioDevice -deviceId $d.Id | |
If ($r -eq 0) { | |
Write-Verbose -Message "Successfully set $($d.DeviceName) as default audio device" | |
} else { | |
Write-Warning -Message "Failed to set $($DeviceName) as default audio device, return code was $($r)" | |
} | |
} | |
} catch { | |
Write-Error -Message "Failed to set $($DeviceName) as default" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment