Hacker News new | past | comments | ask | show | jobs | submit login

PM on PowerShell here: if you have any of those small C# apps handy, I'd love to take a look at them to see what you're doing that's difficult in PowerShell.

Similarly, we're trying to make some improvements to debugging right now with PowerShell 6.0 [1] (the one that's cross-plat and built on .NET Core), and I'm very interested in hearing your feedback on how we can do a better job there.

Even if it's "fix your docs" or "too hard to learn", that's great info, especially coming from a C# guru.

[1]: https://github.com/powershell/powershell/issues?utf8=%E2%9C%...




Writing a robust, idiomatic PowerShell function of any complexity is deceptively challenging, and the background required to do it correctly is almost all unique to PowerShell. PS is a weird amalgamation of C#, Bash, Perl, VB and cmd-isms that ends up being incredibly confusing to basically everyone.

Try getting an experienced C# developer to write a PS function that:

- Initializes an IDisposable resource and deterministically disposes of it when the function terminates (successfully, with an error, or due to ctrl+C). - Honors the caller's $ErrorActionPreference/-ErrorAction. - Understands that catches won't catch "non-terminating" errors. - Throws errors without trashing the ErrorRecord so that the caller gets a meaningful stacktrace. - Copes with the difference between process working directory and PS working directory if a .NET method and a relative path are involved. - Doesn't blow up on a square bracket because someone didn't realize they needed -LiteralPath. - Doesn't accidentally write an unintended object to the pipeline. - Does something reasonable with pipeline input. - Doesn't get tripped up by type coercion magic - $a = @(); $a -eq $null - Uses multiple ParameterSets without creating ambiguity problems. - Doesn't get tripped up by PS silently swallowing exceptions thrown by property getters. - Uses some appropriate subset of language features and modules available across different versions of the OS and WMF. The OS based limitations are understandable. The hard dependencies that Microsoft's own products have on specific PS versions are not. - Is not super-slow.

It's not impossible, but it sure is hard (and takes a ton of boilerplate), and there aren't many resources out there to teach you how. It's all quick and dirty "how to do X" recipes for sysadmins that don't care about more than what they need to paste into a console.

To be clear, I actually mostly like PS I'm just trying to express a set of pain points here.


That list you just provided is actually an AWESOME list of things we should make more accessible/understandable in our documentation. There's a few that would also make great rules for PSScriptAnalzyer[1] (basically our linter; the LiteralPath one in particular would probably be easy to write as a warning).

At this point I should also plug our tooling improvements. First, our VS Code Extension[2] is AWESOME, debugging there has massively improved, there's snippet support for boilerplate with best practices, it integrates directly with PSScriptAnalzyer, and even enables some "quick fix" of linter warnings. We've also got something called Plaster[3] that does templating to encourage best practices (think of it like a "Yeoman for PowerShell").

But yeah, as we craft new docs for writing the best "cross-CLR, cross-platform" (aka universal, aka portable) PowerShell modules, I want to make sure we tick all these boxes.

Oh, and we believe we addressed the whole "different singleton version on different versions of Windows/WMF" thing by making sure that PowerShell 6[4] is x-copyable, fully side-by-side, and supported downlevel to Windows 7/2008 R2 (though Win7 support is currently busted, we're working through fixing it). If you've got a workload or an application that depends on a new feature of PowerShell, you can include PowerShell 6 app-local, or you can distribute it to machines in an environment through either MSI or a ZIP-based file copy.

As for Microsoft products that support specific versions: again, I totally hear you. The best thing you can do is push on those products their respective feedback mechanisms (almost everything is on the Feedback Hub or some product-specific UserVoice now) to support all versions of PowerShell. In the meantime, the side-by-side nature of PowerShell 6 means you can install the latest version without fear that you'll void your support or break existing scripts/workloads.

[1] https://github.com/PowerShell/PSScriptAnalyzer

[2] https://github.com/PowerShell/vscode-powershell

[3] https://github.com/PowerShell/Plaster

[4] https://github.com/PowerShell/PowerShell


As a touch-and-go end user I'll take you up on that at least with some anecdotes:

In 2007 I joined the powershell enthusiasts excited by the notion of a bash-like capability treating .NET constructs as a first-class citizen. I invested time into learning common use cases. Certain things you would THINK would be easy like loading a DLL as well as it's corresponding config file were actually quite difficult in practice which was a shame because the primary vision for powershell was to be flexible glue between compiled assemblies. Have you ever tried to invoke ms-test with powershell on a DLL which has a config xml?

I had a touch-and-go relationship with poweshell. I returned to use it a few years later to find that many of my powershell V1 scripts were obseleted by the powershell V2 runtime. Writing C#/.NET code to execute on many versions of windows this is rarely an issue. Writing powershell code to execute on many versions of windows you have a serious problem on your hands as the commands syntax and general practices vary significantly between versions.

To this day googling for examples on how to accomplish something basic such as running a dos command line call with parameters constructed within powershell is not only highly vexing for the occasional casual user such as myself but many of the answers I see in blogs or stackoverflow are completely temporal and you need to be careful to look for results dating around 2013 for powershell v2 because anything before that wont work, but not too new because v4 has a new approach and that would require a service pack not all my users can currently procure. Not to mention everyone writes powershell in a different style. You often end up with a handful of different code examples that look wildly different each with their own issues as well.

Sure there are expert powershell users out there with muscle memory that can write elegant solutions for version incompatibility issues and common gotchas, however for the casual seldom user the overall experience that too much frustration, less than intuitive approach and 10 ways to solve a common problem. It feels sort of like running perl in a dos prompt that is constantly changing. Compare this with zen of python where [There should be one-- and preferably only one --obvious way to do it.] I find myself installing python runtime and avoiding powershell when I'm required to make something of significant complexity and high compatibility.


I've tried to use PS for some system automation glue using .NET libraries I was also developing, the biggest irritation was that code written with some common C#/.NET idioms are awkward to interop with via Powershell. It's been a while (and this was with PS v4 I think so some of this may have gotten better in later versions) but off the top of my head the problematic stuff included:

* Referencing dependencies (if you're used to "add reference" and "using" it's awkward having to write a bunch of Assembly.Load that then needs to be maintained redundantly with the C#; it would be nice if PS could somehow work with VS/MSBuild projects)

* Calling extension methods (ties in with above since in C# they depend on "using")

* Calling generic methods

* Calling overloaded methods

* Calling async methods

There are workarounds for all the above but put together they definitely make PS less pleasant/useful for me.

Also, much of the above also applies to interop with WinRT which I think is becoming important (as much of the value of PS comes from good access to the underlying system, and more and more Windows functionality is being exposed through WinRT APIs).

The other problem I've had is performance - for example, PS could be useful for some of the same text processing tasks for which Bash is often used (and I'd prefer it for its stronger programming language/object system), but in my experience is dramatically and prohibitively slower when dealing with large amounts of text.


One thing I'm having conniptions over is the inability to automate the installation of TLS certificates into stores other than the local machine or user. I'm referring specifically to the NTDS store, where I need to replace certs used for LDAPS, and I can find no way to do this outside of using MMC certificate store snapins.

If PowerShell could support this, it would allow fully automated cert replacement for those of us who use Let's Encrypt on Windows (ducks)


If I could make a suggestion about debugging scripts.

It doesn't seem that I can currently debug scripts that are contained in a module folder, but not directly the script being called.

If I have a module file that looks like this:

Get-ChildItem -Path $PSScriptRoot\.ps1 | ForEach-Object{ .$_.FullName } # source the script files Export-ModuleMember -function -* # export those sourced scripts

I am not sure how it works exactly, but if I am writing a new cmdlet, Get-HackerNews.ps1, the breakpoints aren't hit in ISE. It would be super cool if it did.

------

Also is there guidance on module structure? Right now it looks like the docs indicate that all the cmdlets should be placed in the .psm1 file, but to me that sounds like it would get rather unmaintainable very quickly. Just looking at the one my dev team has created, we have nearly 50 exported functions. Maybe our our module could be broken up, but that would still leave us ~10 cmdlets per module.


Here is an example of a real project that uses PowerShell to help DBA automation, you dont include them in your psm1, just dot source them, see https://github.com/sqlcollaborative/dbatools/blob/master/dba... for an example.


Awesome, that is similar to what I do right now.


I have a bunch of scripts that I use for various things.

- One which stops IIS app pools before a deployment (30 of them). I wanted to stop them all in parallel but found this far more difficult than executing a list of Tasks in c#. So I now just run c# console app to do it

- one which runs msdeploy commands against a web server and had many issues dealing with passing parameters down to msdeploy. I can't quite recall but I think it was either quotes or spaces related.

The ISE as it's called is very very basic. Not what I'd expect from MS. I'd like a full debugger.

There also seems to be a potential security risk of having editable text file scripts on a server Vs a compiled exe.


Off-topic, but if I say "1..10 | Get-Widget" and Get-Widget doesn't have an InputObject parameter, the input object should be bound to the first positional parameter. Likewise, "dir | $_.length" should be semantically equivalent to "dir | %{$_.length}". Right now the former is an error because the second pipeline element is an expression, but you could implicitly make it a foreach. You could do either of these without a breaking change.


One major complaint I have with powershell is just how completely horribly slow the UI is.

Compared to what cygwin’s bash does, it’s like an entirely different world.


Different guy but same conclusion here (write it in C# instead of powershell). The main pain points I run into:

1) Powershell mingles "process stdout" and "function return" to be one and the same. While this kind of makes sense, unless I'm extremely fastidious about redirecting everything I call to $null, chances are I'm not returning what I expect to return. The end result is I shy away from doing anything that needs to return values (rather than output) in Powershell, which is kind of important for anything nontrivial. I tend to set globals like I've gone back to the Apple 2 and started programming in BASIC again as a result, which gets messy real quick. Processing stdout/stderr in C# is a little annoying by comparison, but easily fixed.

2) Syntax changes in updates. When I installed powershell tools for VS, my scripts broke - to fix them I had to replace e.g.:

  info "$vmGuid: has BuildMatrix tags: $tags"
With:

  info "${vmGuid}: has BuildMatrix tags: $tags"
And:

  logCmd {& $VBM -- clonevm $OriginalVmGuid --register --name $NewCloneId}
  logCmd {& $VBM -- modifyvm $NewCloneId --natpf1 "ssh,tcp,$SshHost,$SshPort,,22"}
  logCmd {& $VBM -- startvm $NewCloneId --type headless}
  waitUpTo 60 3 -Sensitive $true {& $VBM -- guestcontrol $NewCloneId run --exe "/bin/sh" --username "$Username" --password "$Password" -- '/bin/sh' -c "mkdir ~/.ssh; echo '$PubKey' >> ~/.ssh/authorized_keys"}
  waitUpTo 60 3 {& $Ssh -- -o NoHostAuthenticationForLocalhost=yes -o ConnectTimeout=60 -o BatchMode=yes -p $SshPort $Username@$SshHost -- '/bin/sh' -c "echo Server ready" 2>&1}
With:

  logCmd {& $VBM clonevm $OriginalVmGuid --register --name $NewCloneId}
  logCmd {& $VBM modifyvm $NewCloneId --natpf1 "ssh,tcp,$SshHost,$SshPort,,22"}
  logCmd {& $VBM startvm $NewCloneId --type headless}
  waitUpTo 60 3 -Sensitive $true {& $VBM guestcontrol $NewCloneId run --exe "/bin/sh" --username "$Username" --password "$Password" -- '/bin/sh' -c "mkdir ~/.ssh; echo '$PubKey' >> ~/.ssh/authorized_keys"}
  waitUpTo 60 3 {& $Ssh -o NoHostAuthenticationForLocalhost=yes -o ConnectTimeout=60 -o BatchMode=yes -p $SshPort $Username@$SshHost -- '/bin/sh' -c "echo Server ready" 2>&1}
Those "--"s I removed were mandatory in PowerShell 2 for at least some of these commands, yet caused problems in later versions - I don't even know how to write this in a way that will work on multiple powershell versions. I guess I have to explicitly pin -Version when invoking PowerShell all the time? The now simple problem of "How do I get this running consistently on multiple computers" has now turned into an IT and debugging headache. Meanwhile, C# projects get consistently built with a single VS and C# compiler version, and machines I install to are just running the even more stable bytecode.

3) Default installs lag way behind - e.g. Windows 7 only comes with PowerShell 2 by default, so you don't even have things like Invoke-WebRequest, forcing you to write your own or get your IT department to install an updated version for everyone. C# just feels like it has more "batteries included" even for older .NET targets.

4) Figuring out exactly what types are expected vs what I happen to be using is a general muddle in Powershell for any sort of collection in my experience. C#'s static typing, clear errors, and intellisense in general is just extremely hard to beat.


Yes...lots of frustration when I write a script and co-workers can't use it. I'm glad they're adding stuff, but the default installs are ancient in a lot of companies.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: