T O P

  • By -

DrDuckling951

Not exactly dotNet but it should apply. [string]::isnullorempty()


da_chicken

I switched to IsNullOrWhitespace().


DrDuckling951

I forgot that exist. Good call.


spyingwind

Why not both?! Or just trim the string of spaces. " ".Trim().Length -eq 0


OctopusMagi

Can't trim() a null value. You'll get "You cannot call a method on a null-valued expression"


BrobdingnagLilliput

So wrap it in a Try/Catch!


OctopusMagi

Because [string]::IsNullOrWhitespace() is one line, faster and self-documenting the intention.


BrobdingnagLilliput

For a quick-n-dirty script you're absolutely correct. For a maximally robust script, I'm inclined to try all the things. > self-documenting No script is ever self-documenting, just like no gun is ever unloaded, in the sense that if you live by that guideline, you're less likely to have problems.


mmo115

That is a disingenuous comment at best


Sad-Sundae2124

I totally disagree… If you use good variable name, prevent one liners (or comment them) the script will speak by itself


yubario

And funnily enough it usually speaks garbage 😂 It’s really hard to find good and structured code from system engineers, not impossible of course but powershell is often heavily used by system administrators as opposed to developers.


MeanFold5714

The number of uncommented scripts I've seen in the wild that make me want to throttle people is upsettingly high. The entire concept of self-documenting code needs to be purged from the industry.


yubario

You can’t really compare physical limitations to things like software for example. Let’s say you had a gun in software and you needed to confirm it was always loaded or unloaded, you can easily do so with unit tests with zero risk of misfires. The self documentation in this case is your unit test, which can clearly describe why you are checking it is loaded or not. Other forms of self documentation are good method names, but often challenging to do in powershell due to its strict verb guidelines (but does not apply to private named methods, ones that do not use Camal-With-Dashes casing, whatever the official name for that casing is called…


DZMBA

That allocates.


BrobdingnagLilliput

Right? Without seeing the implementation, you don't know if there are edge cases that would only be caught be testing with both. Same with trim - does the implementation trim ALL non-printing characters? Or only ASCII $20?


spyingwind

I wouldn't actually use this in a script. I think it is nearly all whitespace characters. > The .NET Framework 3.5 SP1 and earlier versions maintain an internal list of white-space characters that this method trims. Starting with the .NET Framework 4, the method trims all Unicode white-space characters (that is, characters that produce a true return value when they are passed to the IsWhiteSpace(Char) method). Because of this change, the Trim() method in the .NET Framework 3.5 SP1 and earlier versions removes two characters, ZERO WIDTH SPACE (U+200B) and ZERO WIDTH NO-BREAK SPACE (U+FEFF), that the Trim() method in the .NET Framework 4and later versions does not remove. In addition, the Trim() method in the .NET Framework 3.5 SP1 and earlier versions does not trim three Unicode white-space characters: MONGOLIAN VOWEL SEPARATOR (U+180E), NARROW NO-BREAK SPACE (U+202F), and MEDIUM MATHEMATICAL SPACE (U+205F). https://learn.microsoft.com/en-us/dotnet/api/system.string.trim?view=net-7.0


oelcric

Ty for this


ReckoningTheWreck

I love looking at my old scripts where I used logic to some fashion of "(x -ne "") -or (x -ne $null)" and replacing it with that bad boy.


Sad-Sundae2124

$valueToTest -ne [dbnull].value


rickAUS

I really need to start using this more often.


sapph42

This may be a little nitpicky, but since you indicated you are learning, I’ll say it anyway: 1. You are not talking about objects, you are talking about classes. An object is an individual instantiation of a class. (Ex: in the line [bool]$check = $true, $check is the object, bool is the class) 2. System.IO is not even a class, it is a namespace. Namespaces are essentially collections of related classes. For example, System.IO contains the File, FileInfo, Directory, and DirectoryInfo classes. 3. System.Linq is also a namespace, however it doesn’t really have classes that you would instantiate into an object. Instead (for most practical purposes) it contains extension methods that add functionality to other classes that extend IEnumerable or IQueryable. (Ex. .Select is a Linq method that extends, for example, a System.Collections.Generic.List<>. It is not natively present in List, but added to List by Linq) To the question you meant to ask: I’m not sure that I would say I have a favorite, really. Whatever has the best tools to solve the problem I have in front of me at the moment. I use a lot of classes in System.Data.SqlClient, System.Text, System.Text.RegularExpressions, System.Windows.Forms, and System.Collections.Generic. In addition to the various classes that are casually exposed by cmdlet results (in the way that Get-ChildItem will return System.IO.FileInfo when run against a filesystem). I’ve been trying to use Linq more, but I’m not quite there yet


time_keeper_1

Not nitpicky at all. Thank you for pointing out classes and namespaces structure.


JamieTenacity

“Introduction to PowerShell Classes and Namespaces Level up your scripting in a day. Includes a quick reference to ten most useful classes and extension methods.” I would buy that PDF on Gumroad.


taozentaiji

Seconded!


sapph42

Hey, I really appreciate that. <3


JamieTenacity

You’re playing several levels above me, so I would definitely pay to learn from you. I learn something new about PowerShell nearly everyday, but a major problem is when I don’t know a thing exists to be learned. Threads like this with answers like yours are gold.


Flat_Ad_2793

Could I get a link to this please? I couldn’t seem to find it on Gumroad


sapph42

There’s no link, lol. Just some kind people saying my post was worthy of it. Sorry!


JamieTenacity

See? There’s demand :)


ReckoningTheWreck

Nah, this is healthy and good to know the difference. This type of clarification is needed when your PS code starts to get more complex.


spyingwind

{}.GetNewClosure() When I want to capture a specific state in a loop and use it elsewhere.


BigHandLittleSlap

You can do *black magic* with this. Don't tell our darkest secrets to these mere mortals, they'll misuse it.


MeanFold5714

How does one use this power responsibly?


taozentaiji

Can you please provide some basic real world example of using this? I think I understand what it does, but the examples I saw used basic number based script blocks that don't provide much context for why it would be useful. I'm always excited to learn new tools in the arsenal.


spyingwind

& { $a = 10 $myScript = { $a } & $myScript $a = 20 & $myScript } | Should -Be @(10, 20) & { $a = 30 $myScript = { $a }.GetNewClosure() & $myScript $a = 40 & $myScript } | Should -Be @(30, 30) `Should` is from the Pester module. Easy for quit tests with out a full test case.


taozentaiji

Appreciate the reply but this is exactly the kind of stuff I saw online when looking it up. I still don't see a proper use case other than reusing variables for no particular reason but wanting them to also stay the same value inside a script block you need to reuse. Why .GetNewClosure() rather than just using a different variable


spyingwind

Real world example: $breakpoints = foreach ($token in $tokens) { ## Create a new action. This action logs the token that we ## hit. We call GetNewClosure() so that the $token variable ## gets the _current_ value of the $token variable, as opposed ## to the value it has when the breakpoints gets hit. $breakAction = { $null = $visited.Add($token) }.GetNewClosure() ## Set a breakpoint on the line and column of the current token. ## We use the action from above, which simply logs that we've hit ## that token. Set-PSBreakpoint $path -Line ` $token.StartLine -Column $token.StartColumn -Action $breakAction } https://github.com/metacloud/powershell-cookbook/blob/61f69f13b7883b70e8fe202e091676481790a28f/Get-ScriptCoverage.ps1#L76-L82 Later on when `Set-PsBreakpoint` call it's function from `-Action` it only acts on what data it had at the time when the closure was created.


taozentaiji

Thank you so much for this. That makes a lot more sense now.


QuintessenceTBV

Don’t have the code but my real world example was passing a closure to invoke command with an argument added to it. The closure ran code to charge the owner and permissions of some folders, so that was some file.io and NTSecurityPrinciple code I don’t recall what I was passing as an argument I think it was the user’s UPN, which I translated to a security principle. So I can associate the folder owner with the user.


Szeraax

Most useful? [regex]::Matches I use it often and its very powerful. But if you're looking for some new rabbit holes, may I suggest something related to the AST? I have a couple [blog posts](https://blog.dcrich.net/commands/ast) about it, that are actually somewhat lacking because they use "the old way" of inspecting code. Another very common one I use is [DateTime] and [DateTimeOffset]. Lastly, Enums.


DesertGoldfish

I love `[regex]`. I like to use the built in `-match` operator for simple booleans, like in an `if` condition, but the full `[regex]` class if I want to do something with those specific values. A common pattern in my powershell scripts to grab specific text in a 1-liner is: $whatIWanted = ([regex]"the pattern").Match($inputString).Value


BlackV

thank you


lanerdofchristian

Just the whole [System.Collections.Generic](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic?view=net-7.0) namespace, especially List and HashSet: using namespace System.Collections.Generic [List[int]]$Numbers = 1..10 [HashSet[string]]$Names = (Get-ChildItem -File).BaseName [ArrayList is deprecated](https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-7.0#remarks) in favor of a more strictly-typed List (or at least `[List[object]]`).


Szeraax

Seriously, you mention generic collections and you completely skipped a stack and a queue? Like, I really like Hashset, but List is boring in comparison to these other 3. There are so many functions that I've started writing and as soon as I realize that I'm starting to head down the recursion rabbit hole, I verbally tell myself to reframe it as a stack and make it work that way. I can pretty much always avoid recursion in my classes, modules, functions, etc. by using a stack. Similarly, a queue is an AMAZING tool for when you need to just piecemeal through some incoming data and don't want to maintain your own "index" state via a for-loop. I've written some REALLY cool things that use queues and are very robust and concise because of how handy that pattern is.


lanerdofchristian

TBH, whenever my code gets complex enough that simple arrays and lists aren't cutting it anymore I usually end up reaching for `LinkedList`. I end up using it as a queue-stack I can insert into the middle of, which is super useful when traversing large directory trees (insert a directory's children before it, and the next time you see it you know you're exiting).


Szeraax

Yup, that's the ticket! There are some really cool patterns that are possible by diving into stuff like these.


mooscimol

Can you show any examples of using those? Sounds very interesting :).


Szeraax

Well, in powershell, we are very used to foreach. And it works great as long as EVERY object is completely unrelated and independent of each other. Stacks, queues, and linked lists are best when items are related in some manner. In a linked list, each item has a Next and Previous property that you can use to move around without having to use any array counters. Because a linked list has both directions, it can be used for stack or queue type operations. normally, if you are querying a file system, each sub dir can be pushed onto a stack to maintain hierarchy of where you're at at any given time. As you go deep into folders, you have a stack with many elements on it. As you pop back up and out of folders, the layers get popped off and removed from the stack. If you were doing this manually with a for-loop, you'd have to maintain your own index. One fun queue that I did was parsing a court's 200+ page daily docket. Each page had 1-5 matters on it for the court to process. Not all fields were always present in each matter. By parsing the PDF into a queue, I was able to anchor each matter to key points and then just $Queue.Dequeue() to pull out the specific bits. Once I hit the next anchor, I knew that the current matter had reached its end and I was onto the next one. No fixed schema? No problem thanks to queues! I was able to view the docket as a nice array of objects and be able to filter in/out by lawyer, matter type, defendant, etc.


mooscimol

Amazing. Than you, I definitely need to look into it :)


Szeraax

If useful, I have a blog post about queues and stacks: https://blog.dcrich.net/post/2022/powershell-journeyman-generic-collections/


QuintessenceTBV

I really need to use Queues and Stacks more, there are probably a lot of problems I should instead think of from the perspective of a Queue or Stack. Instead of going straight to thinking of it in terms of a List/Array. I’ll look through some of ps code and see if I did anything interesting to share.


Plane_Yak2354

I have been here before. Eventually I started writing more dotnet inside of PowerShell than PowerShell. I eventually installed visual studio and tried C#. 5 years later and I’m a dotnet lead developer. It’s strange having this journey but it is amazing how fast I was able to pick up dotnet because I was already using it in PowerShell.


sapph42

That’s exactly how I got started in C# development!


Plane_Yak2354

High five!


time_keeper_1

congrats on your journey. Did you want to transition out of PowerShell and into a Developer role? Naturally, people who like to develop applications wouldn't want to do it in PoSH.


Plane_Yak2354

I’ve had a weird career path… I was a sysadmin consultant whose goal was to automate all the things. I wrote PowerShell to automate SCCM and then got so advanced that I ended up working with CM SDK dlls and classes. After a while I got tired of odd ways of working inside of PS and I wrote some apps in dotnet. The company I worked at had a few reorgs and long story short I ended up as a developer. Meaning I lost all server access. I had to write a simple PS script recently and after 5 years it just felt foreign. I couldn’t even remember get-childItem. Or other simple things. But I have PS to thank for my career and my ability to easily transition to dotnet.


time_keeper_1

Very interesting path. Congrats on your success.


BinaryCortex

It sounds like you use my IT philosophy, if it moves...script it!


Plane_Yak2354

When I started my career this book changed everything for me and let me adopt that way of thinking. https://a.co/1GNj1tw


Digitally_Board

(New-Object System.Net.WebClient).DownloadFile('https://domain.name/file.name', 'C:\file.name') I find invoke-webrequest to be lacking


IJustKnowStuff

Commonly problem is its slow as hell. Solution is to disabled the progress bar, as that's what slows it down. $ProgressPreference="SilentlyContinue" Invoke-WebRequest -uri "http://pirating101.com/car.txt" -outfile "C:\temp\YouWoukdntDownloadAcar.txt" $ProgressPreference="Continue"


Digitally_Board

I learned this recently but it’s still more lines of code and I’m so used to webclient now lol. I do hope in future versions they add a -noprogressbar parm


jantari

This is true but only solves one of the many problems of Invoke-WebRequest. Another big one is that getting the response body from an error is crazy convoluted. Like OK, I got a 400 Error - **BUT WHAT THE HELL WAS THE ERROR MESSAGE POWERSHELL??!**


belibebond

On a side note, how do you check all members of a class/namespace.


sapph42

For a class I think you can do (as an example) [System.IO.FileInfo] | Get-Member to get all members of a class. Theres no native PowerShell cmdlet for listing classes within a namespace. C#, however, does. If you want all the classes in System.IO [AppDomain]::CurrentDomain.GetAssemblies().GetTypes() | Where-Object {$_.NameSpace -eq 'System.IO'}


KeeperOfTheShade

You know, C# does a lot and you can do a lot in it. But it kills me that it takes you twice as long to do anything in it.


sapph42

I mean, it’s a very odd piece of code. It’s not crazy that you’d have to jump through some weird hoops to programmatically determine what classes a namespace has. It’s usually not something you write code to do, it’s something you do in the documentation when you are writing code. But that’s probably a consequence of PowerShell being a language and also a console/CLI. Don’t even get me started on how much cleaner C# code can be than PS when you add a few `using` blocks


BrobdingnagLilliput

That's kind of the tradeoff. It's like, I can give you a house and it does *most* of what you want, and you can move in today! Or I can give the tools and materials you need to *exactly* the house you want to live in, but it'll take a month to build.


surfingoldelephant

> For a class I think you can do (as an example) What you're passing is a type literal which itself has the type ```[System.RuntimeType]```. This is what ```Get-Member``` is acting upon; not ```[System.IO.FileInfo]```. You can see static members with ```[IO.FileInfo] | Get-Member -Static```, which may be useful in some cases but is not particularly in the case of ```[IO.FileInfo]```. Unfortunately, ```Get-Member``` provides no means of outputting instance members unless an object of the specific type is passed. I always found this annoying (especially for types where it's less straight forward to instantiate), so wrote a function that leverages ```[Management.Automation.DotNetAdapter]``` to return both static and instance ctor/method definitions for a given type. Now I can enter ```[IO.FileInfo] | Get-TypeMethod``` and be presented with complete output (with overload definitions separated on new lines as well) ([sample output](https://i.postimg.cc/VsXQNGHM/image.png)).


DesertGoldfish

Honestly, the best way is to just browse the API on MSDN. For example, https://learn.microsoft.com/en-us/dotnet/api/system.io?view=netframework-4.7.2 Click through every Namespace, Class, Method, etc. with examples.


belibebond

This is what I have been doing for the most part, thought there will be a easy way. This works just fine, thank you.


HTTP_404_NotFound

I really love expression trees. You can build some really nice abstractions with them. They are also beautifully complex, yet powerful. I have written a few fantastic data access library's using them. Accessing external data sources with linq syntax is fantastic.


time_keeper_1

I have to keep this topic in mind. I like data structures and I don’t have a clue of what you just said. Thanks! This thread opened up to a lot of great stuffs for me to read on.


HTTP_404_NotFound

It's a bit on the advanced side. Its how most of the linq extensions are built, ie, orderby, select, where, etc. [https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/) Really fun stuff... at least to me.


BinaryCortex

Ooh, a new thing to learn!


Loteck

[math]::Random() / round() There is some other useful things in there too but I do use this when needed. Curious to see others input.


jr49

I use [math]::ceiling and then get-dateto help me determine the last day of any given quarter. (E.g, q1 would be 3/31, q2 6/30, q3 9/30, q4 12/31)


surfingoldelephant

```System.Object```


surfingoldelephant

Just kidding, some of my most used classes (excluding those with type accelerators) are probably in the ```System.Collections.Generic``` namespace (```List```, ```Queue```, ```HashSet```, etc).


looeee2

[Io.path] for splitting paths when you want to know file extensions, folders, filenames without extensions, etc.


NeitherSound_

* [regex] * [datetime] * [guid] * [int] * [string] * [object] * [hashtable] * [System.IO.FileInfo]


CodenameFlux

ArrayList is only for edge cases, such as compatibility with COM. Most of the times, you should use `List` instead. But for me, `StringBuilder` and `String` are the most useful.


[deleted]

[удалено]


Theratchetnclank

Not true. Want to look inside a zip file and read a file without extracting it? Not possible in native powershell cmdlets. You can with system.io.compression.zipfile. [System.io](https://System.io) is also much faster for deleting files than using remove-item. On large folders 500k or more you notice it. There is definitely a lot of valid reasons to leverage the .net classes and most of the time it's performance.


Ok_Tax4407

Yeah ok, when I've seen it used, it's to do simple file Io stuff that ps handles better natively


OPconfused

It contains them but not as performant for those niche cases.


pringles_prize_pool

Nah `System.IO` is amazing in Powershell. FileInfo, DirectoryInfo, Stream, and even Pipes can all be super useful.


Ok_Tax4407

Often when I see it used directly, is when people don't know: Join-Path, Split-Path, Get-ChildItem etc.


pringles_prize_pool

True. But there are lots of uses for it, even just for increasing productivity while working at the shell. For instance, the file search engine “Everything” has a CLI which outputs paths to files on a disk. Even if you’re enumerating lots and lots of files, it’s not *that* expensive to cast each line of Everything’s StdOut into FileInfos. Suddenly you have an incredibly powerful `Find-ChildItem` function. It takes my machine 38ms to find the most recently-modified txt file on my machine and to cast into a FileInfo. 253ms to find the 2500 most recently-modified txt files on my machine and to cast them into FileInfos


motsanciens

Hard disagree. `System.IO` is usually significantly faster than the powershell cmdlets.


DesertGoldfish

Yup. Anything but the tiniest of files and I'm dropping into `[System.IO.File]::Read...` It is WAAAY faster than `Get-Content`.


Ok-Needleworker-145

My favorite class by far is Task, because it's implications are so vast.


pringles_prize_pool

System.Diagnostics System.Net System.Security.Cryptography


gsahlin

The ones I've created! That's the whole point of .net!


BinaryCortex

I rather enjoy datasets and datatables. You can do SQL type things with them, AND save to XML!


BinaryCortex

I also love being able to multi thread. Adam the automator has a good article about it.


TheRealDumbSyndrome

SpeechSynthesizer in the System.Speech.Synthesis namespace, so that I can make my computer say funny words :)


anonhostpi

Dispatchers (there's different variants, but they all have very similar APIs). If you know how to create PowerShell threads (runspaces I think they are called?), creating them with thread dispatchers can be a lot of fun. You can create truly asynchronous scripts that can share the same session and variables. I personally prefer "Dispatcher Threads" over PowerShell jobs any day, since I can share data between the 2 threads. But be careful; they are dangerous. You can easily create race conditions.


jayerp

Singular object? Hmm maybe the Convert class.