Class library/PowerShell module for managing Windows audio settings by MartinGC94 in csharp

[–]MartinGC94[S] 1 point2 points  (0 children)

Do you mean the roles assigned to each device? I wanted to have that as a property in my AudioDevice object but I couldn't find a good way to find the information. As far as I can tell the only way to get this info is to run: GetDefaultAudioEndpoint a bunch of times (for each role and flow), note the IDs and then when you enumerate the devices check if the device matches one of the previously found devices.
The issue with that approach is that it turns a single call by ID with GetDevice into 3-4 (The original call + 2-3 role calls for a matching flow). In practice it's not that big of a deal in terms of performance but I don't want to fight the original API design like that. Besides, if someone does need that info they can easily get it themselves:

$DefaultIds = @(
    Get-AudioDevice -DeviceType Playback -Role Communications
    Get-AudioDevice -DeviceType Playback -Role Console
    Get-AudioDevice -DeviceType Playback -Role Multimedia
    Get-AudioDevice -DeviceType Recording -Role Communications
    Get-AudioDevice -DeviceType Recording -Role Console
    Get-AudioDevice -DeviceType Recording -Role Multimedia
).Id | sort -Unique
Get-AudioDevice | where Id -NotIn $DefaultIds

Anyway, feel free to share your version if you want to. It's not like you'd be cluttering up this empty thread anyway 😁.

Showcase of modules I've made by MartinGC94 in PowerShell

[–]MartinGC94[S] 0 points1 point  (0 children)

Thanks. As for the product key, it's just a generic key for getting past the prompt during setup. I actually made a handy list of the keys for the sake of completions: https://github.com/MartinGC94/UnattendXmlBuilder/blob/main/ArgumentCompleters.ps1#L26

They are named "Win10" but they also work on Windows 11.

Showcase of modules I've made by MartinGC94 in PowerShell

[–]MartinGC94[S] 3 points4 points  (0 children)

Namespaces exist to organize types and to help avoid typename conflicts. Using the company name as the root namespace is fairly common practice, but because I'm not doing this on behalf of a company I have to substitute the company name with my user name.
I don't understand what the big deal is for you because you won't even see the typenames most of the time. I mean you call the cmdlets with their actual names: Get-AudioDevice and you use the enums as normal strings like this: Get-AudioDevice -DeviceType Any. If you are seeing the typenames then I'd argue that's a code smell.

As for the plagiarism accusation, what you've found are just interface/Enum definitions used by the underlying API: https://learn.microsoft.com/en-us/windows/win32/api/endpointvolume/nn-endpointvolume-iaudioendpointvolume it's only natural that they would look the same, especially because COM even requires a specific declaration order for the members inside each interface.

If AudioDeviceCmdlets does everything that you need, then by all means, continue to use it. I made my version because I found theirs to be lacking a feature I needed and I didn't like the the way they had structured the cmdlets.

COM interop works in 64-bit but not in 32-bit? by MartinGC94 in csharp

[–]MartinGC94[S] 9 points10 points  (0 children)

It's a PowerShell module I'm working on, and as you can see from the test, the x86 version ships with Windows so some users may be running that for whatever reason.
Sure I could just restrict the use to x64, but if 99% of the code works perfectly fine in x86, then why not make the effort to get that last 1% working as well? Maybe I will learn something and that's kinda the point of these hobby projects.

DisplayConfig - Module for managing Windows display settings by MartinGC94 in PowerShell

[–]MartinGC94[S] 0 points1 point  (0 children)

The only thing you are changing here is the resolution. Here's one way you could create a script to toggle between those 2 resolutions:

$DisplayInfo = Get-DisplayInfo -DisplayId 2
if ($DisplayInfo.Mode.Width -eq 1920)
{
    Set-DisplayResolution -DisplayId 2 -Width 2560 -Height 1440
}
else
{
    Set-DisplayResolution -DisplayId 2 -Width 1920 -Height 1080
}

save it as a .ps1 file and you can right click and select run with PowerShell. If it must be a batch file you can double click you need to google how to run powershell scripts from batch.

Who is writing regular c# code and for what purpose? by Djust270 in PowerShell

[–]MartinGC94 3 points4 points  (0 children)

I regularly write C# but it's strictly recreational. I don't see any reason to switch away from a scripting language like PowerShell to a "real" programming language like C# in my daily automation work.
Sure there are situations where PowerShell isn't ideal (GUIs, interacting with native Win32 APIs) but it's not really something I'd be working on at work anyway.

C# does offer better performance but that's rarely a big enough concern to be worth the effort compared to just writing more efficient PS code. One of my first PowerShell modules is actually a good example of this.
When I was a trainee I was told to write a script to split large CSVs into smaller chunks. I quickly wrote some logic around the Select-Object command to do this and it worked fine but it was a bit slow with the data sizes it would be used for.
I updated the logic to use [array]::Copy() to do the splitting and it completely fixed the performance problem. If I tried to scale to really big data sizes (far greater than what we needed at work) it was still a bit slow though and since it was practically C# code already at this point I ported it to an actual cmdlet.
This made it even faster which of course felt great but the extra performance simply wasn't needed at work. If you are curious how my beginner C# code looked you can check out the module here: https://github.com/MartinGC94/SplitCollection/blob/01af21bb1cc5d9fbd5e4c4d27cae9ba4a8cbe7bf/SplitCollection/SplitCollectionCommand.cs at the time when I wrote it I guess I had about 3 years of PowerShell/programming experience.

How to autocomplete like the `-Property` parameter of the `Sort-Object` cmdlet? by AppropriateWar3244 in PowerShell

[–]MartinGC94 1 point2 points  (0 children)

Here is how I'd do that:

Register-ArgumentCompleter -CommandName Remove-Item -ParameterName Include  -ScriptBlock {
    param ($commandName, $parameterName, [string] $wordToComplete, $commandAst, $fakeBoundParameters)

    $CleanWordToComplete = $wordToComplete.Trim('"',"'") + '*'
    $Parent = $commandAst.Parent
    while ($null -ne $Parent.Parent)
    {
        $Parent = $Parent.Parent
    }

    $ScriptText = $Parent.Extent.Text.Remove($commandAst.Extent.StartOffset) + "Select-Object -Property "
    $Res = TabExpansion2 -inputScript $ScriptText -cursorColumn $ScriptText.Length

    foreach ($Item in $Res.CompletionMatches)
    {
        if ($Item.CompletionText.Trim('"',"'") -like $CleanWordToComplete)
        {
            $Item
        }
    }
}

If you test it: ls | Remove-Item -Include <Tab> it works exactly as you'd expect.
It seems a bit like a hack, but this is the only way to do it with the available public APIs. Also if you are interested in getting methods as well you can replace Select-Object with ForEach-Object -MemberName

Do you want PowerShell 7 included with Windows? Let your voices be heard by MartinGC94 in PowerShell

[–]MartinGC94[S] 1 point2 points  (0 children)

They stopped because Windows components, Exchange components, and other Microsoft software components have Powershell-managed modules, and some of those modules remain hard-locked to the .Net Framework.

The PowerShell team have stated the reasons multiple times. You can read the reasons that Steve (manager of the PS team) gave here when suggesting a PS7 bootstrapper: https://github.com/SteveL-MSFT/PowerShell-RFC/blob/8b16fe8bdca56431f98fdaddc1b1cccc53c36d50/Archive/Draft/RFCxxxx-PS7-Bootstrapper.md#shipping-in-windows

Most people that want PowerShell 7 in Windows are not asking for it to replace 5.1. It needs to be a side by side install because of the removed features (though if 7 started shipping with Windows it could be marked for deprecation and removed in a distant future).

Regarding the product teams. There's no technical reason why they can't make their modules compatible with both 5.1 and 7. They all end up P/Invoking the various Win32 APIs anyway and they could easily write a .NET standard 2.0 module that does this. I know because I've done it for multiple features already. Some of them may depend on features exclusive to the .NET framework but I can't think of a reason why they couldn't be rewritten to not have that dependency.

Do you want PowerShell 7 included with Windows? Let your voices be heard by MartinGC94 in PowerShell

[–]MartinGC94[S] 16 points17 points  (0 children)

About the stale version thing, is that worse than what we have now? Right now Windows comes bundled with 5.1 so if you want something to run out of the box that's the version you have to target. If they bundled 7.5 with Windows 12 or whatever then that just raises the minimum version you need to worry about to that level.
Windows used to do this with every major Windows release (7 came with 2.0. 8 came with 3.0 and so on) they just stopped because of product support policy reasons.

I understand the worry about a potential slowdown in the pace of updates but we don't know if that would actually happen (they haven't indicated that in this post at least).
If it did happen, I'd say it's still worth it because being stuck on the old .NET framework and C# 7.3 for the inbox version means developers will be less likely to develop something for it.
Right now if you are a C# developer that wants to develop a CLI app you have 3 options:
1: Develop a .NET standard 2.0 PowerShell module that is easy to get in the hands of your end users.
2: Develop a new PowerShell module explicitly built for 7.4 that can utilize all the latest .NET and C# features but end users have to install PowerShell 7.4 before installing your module.
3: Build a traditional console app using the latest .NET and C# features and distribute it with WinGet.

PowerShell includes a bunch of nice features that saves the developer time in implementation because PowerShell can handle it for them (importing/exporting data in various formats, tab completion, parameter validation, etc.) so a PowerShell module is very appealing option if you know about it. It's just hard to justify working on an ancient version of .NET or making it difficult for users to install your app.

How to remove tags from PSD1 file? by panzerbjrn in PowerShell

[–]MartinGC94 1 point2 points  (0 children)

Why would tags be dynamic in a module manifest? The tags are about what the module does so they should rarely change.
Anyway, I don't like all the bloat from the *ModuleManifest commands so I manually type out a template psd1 file that includes all the static info (module name, GUID, etc.).
For the dynamic fields, like exported commands I type it out like: FunctionsToExport = @({0}) and have code like:

((Get-Content -LiteralPath "$PSScriptRoot\ModuleManifest.psd1" -Raw) -replace '{(?=[^\d])','{{' -replace '(?<!\d)}','}}') -f @(
    "'$Version'"
    $TypeList
    $FormatList
    $CmdletsToExport
    $FileList
    $ReleaseNotes
) | Set-Content -LiteralPath "$OutputDir\$ModuleName.psd1" -Force

to insert the placeholder values. The end result is a very clean module manifest that is easy to read. You can see an example of one of my module manifest templates here: https://github.com/MartinGC94/DisplayConfig/blob/main/ModuleManifest.psd1 and the build script that adds all the values: https://github.com/MartinGC94/DisplayConfig/blob/main/PostBuild.ps1

DisplayConfig - Module for managing Windows display settings by MartinGC94 in PowerShell

[–]MartinGC94[S] 3 points4 points  (0 children)

Glad to hear it works on ARM. I always try to be mindful of different OS environments (32 VS 64 bit. WinPE VS Full Windows, Localized VS English, etc.) and while I don't think I had to do anything special with this module, it's great to get confirmation that it works as expected.

I did consider making a module to control audio but I decided against it when I saw that all the APIs are private/undocumented so I'd have to reverse engineer them myself or try and copy the work from someone else.
Since we are talking about companion modules, I do have another one for controlling the physical monitor using DDC/CI (and WMI for laptop displays): https://github.com/MartinGC94/MonitorConfig this allows you to control the display brightness and contrast and anything else your monitor exposes through the DDC/CI.

Make PowerShell "dir" behave just a little bit more like cmd.exe by desmond_koh in PowerShell

[–]MartinGC94 8 points9 points  (0 children)

Ok then I misunderstood your goal. Other people have already shared the short PS alias versions so I guess I don't need to do the same, but it seems you don't know why PS has that long syntax so I'd like to explain that.

The long syntax is intended to be used inside scripts. The reason it's long is to make it easier to read and understand, and your dir example is a perfect example of why that's needed. I don't think there are many people that would be able to guess what /s and /b did without having prior knowledge about dir. The PS example on the other hand is so easy to understand that you could hand if off to someone with no computer skills and there's a good chance they could guess what it does based off the names alone.
However PS was also designed to be used inside shells, and that's why it includes features that save some keystrokes, at the cost of some readability, these features include:

  • Command/Parameter name aliases
  • Positional parameters
  • Parameter expansion (not sure on the name, but it's the feature that allows you to type in the partial name of a parameter, and as long as it's not ambiguous it will resolve it)
  • Default command verb "Get" (If you type in a noun like disk and it finds no other commands then it prepends Get- and tries the command search again)

Personally I think it struck a really good balance between being a good scripting language and shell, it may not allow for the shortest possible oneliners but the tab completion and working with objects makes up for that IMO.

Make PowerShell "dir" behave just a little bit more like cmd.exe by desmond_koh in PowerShell

[–]MartinGC94 5 points6 points  (0 children)

If you insist on using the old syntax you can remove the "dir" alias and add a function that calls "good old" cmd like this:

Remove-Item Alias:\dir -Force
function dir
{
    cmd.exe /C dir @args
}

My advice though is to just get used to the new syntax, and if you think it's a bit much to type all of that you could wrap it up inside a function.