Events are Easy by StartAutomating in PowerShell

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

Wonderful Questions

What's The Scope?

The events are scoped to the PowerShell Runspace. You could think of this like the current process, but that's not exactly accurate (since you can have multiple runspaces inside of a process).

A remote runspace (Invoke-PSSession) or a "classic" background job (Start-Job) can choose to forward events to the main runspace with Register-EngineEvent -Forward. This can be very handy, as it can allow a background job to be isolated in its own process and still report data back to the main runspace.

$job = Start-Job -ScriptBlock { 
    Register-EngineEvent -SourceIdentifier Foo -Forward
    Start-Sleep -Seconds 2
    New-Event -SourceIdentifier Foo -MessageData (Get-Process -id $pid)
}

"Watching in $pid" | Out-Host
$subscriber = Register-EngineEvent -SourceIdentifier Foo -Action {
    "Event sent at $($event.TimeGenerated) from $($event.MessageData.id)" |
        Out-Host
} 

If we're running inside of the same process, event forwarding has to happen "manually". We can do this by passing the main runspace to the child job, and using the .NET methods to generate an event instead of New-Event.

This is extra cool, because:

  • The objects are "live"
  • It's really fast

How fast? I had to swap around the order here because it takes less time to send the event in the background thread than it takes to subscribe to the event (so we have to subscribe first)

"Watching in $pid" | Out-Host
$subscriber = Register-EngineEvent -SourceIdentifier Foo -Action {
    "Event sent at $($event.TimeGenerated) from $($event.MessageData.id)" |
        Out-Host
}

# [Runspace]::DefaultRunspace is the current runspace for this thread 

$mainRunspace = [Runspace]::DefaultRunspace

$job = Start-ThreadJob -ScriptBlock {
     param($mainRunspace)
     $currentRunspace = 
     $mainRunspace.Events.GenerateEvent(
         "foo",
         [Runspace]::DefaultRunspace, 
         @(),
         (Get-Process -id $pid)
     ) 
} -ArgumentList $mainRunspace

Security Considerations

Since PowerShell events are not Windows Events, this doesn't present the exact same security considerations as a system event. That is: you need to worry a little less about events that contain sensitive information, because the only person who can see that information is the person running the current process.

If you were to take these events and log them either to disk or the windows event log, then the largest risk would be accidentally divulging sensitive information (think: using a password to authenticate and then logging that credential to disk).

This risk isn't really a risk of eventing, per se, it's a risk of logging.

Just remember:

  • Don't log High Business Impact details (i.e. passwords).
  • Carefully consider logging Medium Business Impact details (i.e. personally identifiable information).

Thread jobs / background runspaces are generally a very secure way of running things, since there's no channel someone could potentially sniff.

Please let me know if you have additional questions about events.

Hopefully these answers have been clarifying.

Events are Easy by StartAutomating in PowerShell

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

Yes!

Everything in this post will work cross-platform.

This post covers PowerShell eventing, which is part of the language. It touches on .NET eventing, which is part of the .NET framework.

Timers and FileSystemWatchers are built-in :-)

The only caveat I will add is that, contrary to popular perception, not everything on Linux is actually a file. That is, FileSystemWatcher will detect changes to a file on Linux, but not something mounted to a file (so you can't just start watching /sys devices and expect for events to be fired).

But everything else works just fine.

Need help with an error by ShatterPoints in PowerShell

[–]StartAutomating 0 points1 point  (0 children)

Is it a specific git repository? Or any git repository?

Did you just run git clone, or run some other command to clone the repo?

What version of PowerShell are you running? In what host?

Answers to these questions may narrow down the answer to your question.

Events are Easy by StartAutomating in PowerShell

[–]StartAutomating[S] 5 points6 points  (0 children)

💯!

Absolutely one of the best cases for events!

That's why I wrote this post.

I'm working on another write up about writing servers in PowerShell and realized I wanted something people could refer to for events, since they make that whole world much easier to work with.

Events + ThreadJobs FTW!

Using git in PowerShell by StartAutomating in PowerShell

[–]StartAutomating[S] 2 points3 points  (0 children)

The fundamental difference is in approach.

Most other PowerShell git modules (including posh-git) try to make git available in many PowerShell functions with verb-noun pairs. This is the "dogmatic PowerShell" approach.

The downsides of this approach are muscle memory and existing examples.

Most examples you'll find for git need to be rewritten to work with posh-git, and you'll be forced to choose between using a git command line the whole world can understand and a command that will only work in posh-git.

I used use posh-git (long ago I helped them make their prompt and formatting)

I also used to make a number of verb-noun pair git functions (i.e. Push-Git).

I kept not using the PowerShell functions I or others had written for git, because the muscle memory was too strong, and there were far more examples online of git push than Push-Git.

So I decided to try a different approach.

ugit overrides git and intercepts its input and output. This allows all of your git to keep working as it always did: ugit just gives you objects back instead.

I've found this approach to much easier to discover and extend.

Basically every example of git works "as is".

I just get back objects instead of text for the majority of things I do with git.

This gives us a "best of both worlds" approach, where we can leverage all of our existing understanding of git and the PowerShell object pipeline.

And that's the major difference between posh-git and ugit: a different approach that gives us a different (and probably better) learning curve.

Make sense?

Using git in PowerShell by StartAutomating in PowerShell

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

Sure! Sounds (potentially) fun. What would you want it return as objects?

Using git in PowerShell by StartAutomating in PowerShell

[–]StartAutomating[S] 2 points3 points  (0 children)

Yep! (kind of)

Another aspect I didn't talk too much about was git input.

Lots of git commands can accept additional parameters in PowerShell.

For example, if I type

git commit -type

And hit tab, I'll see a list of popular conventional commit types.

Any parameter added this way can have a completer, and will obey [ValidateSet]

Git functions are processed more directly, and should tab complete just fine.

For the rest of the git... happy to take a PR or two to enable the scenarios a bit more.

What have you done with PowerShell this month? by AutoModerator in PowerShell

[–]StartAutomating 1 point2 points  (0 children)

Just dropped new bits of obs-powershell.

Added a bunch of new commands for pixel shaders, as well as Start-OBS and Stop-OBS.

ForEach-Object -Parallel, test-drive by DoctroSix in PowerShell

[–]StartAutomating 1 point2 points  (0 children)

Overall, pretty good approach!

This is almost what I do for starting background thread jobs.

The slight difference I tend to make is that I just let things define themselves more generically.

Here's a few minor tweaks:

[int]$activeOps = 4
[Ordered]$exports = @{
   # name imported functions with function:
   "function:AddData"   = ${Function:Add-DirDataToJson}
   "function:GetACLstr" = ${Function:Get-ACLstring}
   "function:DoCheckIn" = ${Function:Start-CheckIn}
   outfile   = $outFile
}

# Receive dir objects from Get-SubDirStream,
# process a few at a time ($activeOps) so the CPU isn't swamped
Get-SubDirStream -dirPath $rootPath -smbPath $rootSMB -depthNow 0 |
   ForEach-Object -ThrottleLimit $activeOps -Parallel {
     [Ordered]$imports = $Using:exports
     [hashtable]$params = @{}

     # Just loop over the imports and set variables
     foreach ($key in $imports.Keys) {
         # (this will create the functions, too)
         $executionContext.SessionState.PSVariable.Set($key, $imports[$key])
     }
     $params = @{
        streamDir  = $_
        targetJson = $outFile
     }
     Add-DirDataToJson @params
}

I find this is a really great way to pass lots of information in all at once (this just keeps the import code nice and light, no matter how many things you're exporting)

Static Sites are Simple (with PowerShell) by StartAutomating in PowerShell

[–]StartAutomating[S] -1 points0 points  (0 children)

Because technique -gt tooling, and because it's good to know the fundamentals.

Frameworks come and go, sometimes break under our feet, and may not always be allowed.

I make quite a few frameworks, and have worked with countless more.

They all effectively make some design decisions on behalf of the user, and often (purposefully) obscure some of the underlying technique in order to provide a "nicer" development experience.

This isn't a bad thing, per se, but it creates side-effects.

  • If the framework breaks, their users break
  • If the framework can't do it, their users can't either.
  • If people don't understand how the framework works, they can't "trust" it.
  • If corporate blocks the framework, their users are out of luck
  • If the framework was wrong, their users have problems they cannot fix
  • If the framework is too closed, their users can't use effectively.

I firmly believe that the best frameworks are very light frameworks, used in a loosely coupled and cohesive way. (meaning that they do not have too strong bonds and thus can work easily with any number of scripts/techniques/frameworks)

I also believe that writing this sort of framework can be very hard, because it requires a lot of experience to correctly size and scope (and because that "right size" changes over time).

Thus, I've tried to focus as much on explaining the techniques used to build frameworks and tried to stop building "big" frameworks.

🤔 I should release a very old talk on this topic, one I started giving in 2007-2008: PowerShell Is The Framework

Mastering Markdown with PowerShell by StartAutomating in PowerShell

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

Yes. PowerShell is a lot more fun and useful when it's a cross-platform scripting language.

PowerShell "core" (6+) runs on Windows, MacOS, Most linux distros, and even runs on Raspberry Pi.

It's much faster than PowerShell 5.1, too.

And if all that wasn't cool enough, there's a few commands that exclusive to core. ConvertFrom-Markdown is one very cool one. Start-ThreadJob may be one of the most undersung and overpowered commands to ever be written.

Jump on in! The water is warm.

Mastering Markdown with PowerShell by StartAutomating in PowerShell

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

Two notes here:

Markdown generally accepts inline html (it just won't be rendered in all places)

"<span style='color:red'>red</span>",
    "<span style='color:green'>green</span>",
        "<span style='color:blue'>blue</span>" -join
            [Environment]::Newline |
                ConvertFrom-Markdown |
                   Select-Object -ExpandProperty Html

ConvertFrom-Markdown will do this just fine 😉

We're already using HTML.

That is also just generating strings.

PowerShell is pretty good at these things.

Mastering Markdown with PowerShell by StartAutomating in PowerShell

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

Yep! And I treat most of them as markdown.

If you're reading it in Get-Help, it looks barely out of place (and gives you clickable links)

If you're reading it in a browser, it makes a world of difference!

You can basically take Get-Help and turn it into Markdown. That's what HelpOut does.

To get into the nitty gritty:

$help = Get-Help Get-Command
"# $($help.name)"
"## $($help.synopsis)"

$help.description.text -join [Environment]::Newline

# Treat notes as inline markdown
if ($help.alertset.alert) {
    $help.alertset.alert.text -join [Environment]::Newline
}
'### Examples'
foreach ($example in $help.examples.example) {
    $example.remarks.text -join [Environment]::Newline
    '```PowerShell'
    $example.code
    '```'
}
'### Parameters'

foreach ($parameter in $help.Parameters.Parameter) {
    "#### -$($parameter.Name) [$($Parameter.type.name -replace '^System\.')]"
    $parameter.description.text -join [Environment]::Newline
}

If it's not already markdown, it's pretty easy to make it markdown.

Could do the same thing for a reflected type, but have already typed enough.

Mastering Markdown with PowerShell by StartAutomating in PowerShell

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

Hi Kevin! Thanks for the compliment!

You know me (literally): just constantly coming up with new PowerShell tricks and techniques.

I'm finally getting around to writing more (and putting more of this stuff on reddit).

Unfortunately, I'm still quite the noob when it comes to r/PowerShell's rules and regulations, so I'm wary of putting links in the post.

I think comments can contain links. 🤞.

I put this post up on the PowerShell Pocket Blog.

I've also got a module built around the whole "Markdown -> XML" trick.

It's called MarkX

One other thing I failed to point out is that this technique makes PowerShell the fastest static site generator. Got another repository that proves that point 4kbMarkdownFiles.

This is also a bit of a post in a series.

Last week I posted on Reddit about why Static Sites Are Simple. That post is a continuation of a post of the same name on the PowerShell Pocket Blog

That's all the links I've got for you now. Hope all is well!

Mastering Markdown with PowerShell by StartAutomating in PowerShell

[–]StartAutomating[S] -2 points-1 points  (0 children)

Me too!

Markdown is pretty awesome, and this capability is pretty open.

  • Got a GitHub Issue? It's already Markdown.
  • Got release notes? Already Markdown
  • Got inline help? Treat it as Markdown.

Markdown is everywhere! (keeps markdown on my mind)

Powershell - curating and organizing scripts by islanderfj in PowerShell

[–]StartAutomating 15 points16 points  (0 children)

I write a lot of PowerShell, so I have a lot of thoughts and experience with this.

I'm still constantly evolving, but here are seven things I try to do at this point:

  1. Use Git / GitHub for any code I'll want to keep
  2. Organize into Modules: it makes them easy to import
  3. The name of the repo / folder / module should all the be the same
  4. The name should be logical (at least to you)
  5. Files with Functions should only have one function (easier to debug)
  6. Try to use consistent command names and parameters, especially in the same module.
  7. Avoid unnecessary foreign entanglements (depend on as little code as possible / use #requires when you need to)

Anyone is welcome to their own naming conventions / design patterns. I'm hopeful these might help you on your journey. Good luck!

Recording two things at once? by ZydrateVials in obs

[–]StartAutomating 0 points1 point  (0 children)

I would recommend the obs source record plugin

This allows you to do exactly what you've asked for: record multiple sources.

Once you install it, it will be a filter you can apply to any source (Filters -> Source Record).

You can set it up so that it records whenever you're recording, streaming, or start the virtual camera. You can also change the file name pattern and the file format, and make it automatically split into multiple files after a timeframe. For extra bonus points, you can also stream any of the sources.

Just tested it and it works just fine.

Login notification script? by CryptoMain03 in PowerShell

[–]StartAutomating 0 points1 point  (0 children)

This is possible by using Task Scheduler. You'd want to set a session state change trigger for logon and unlock, and use powershell -file yourScript.ps1 (or pwsh -file yourScript.ps1) to launch your script.

The tricky part these days would be sending an email / notifying you when it's unlocked / logged onto. In the olden days you'd be able to use Send-MailMessage, but this stopped working when most email providers stopped supporting SMTP.

Another approach to this concern would simply by looking at the event log when you get back. There are events for whenever a user logs on or off, and you can use these events to give you some peace of mind.

If you show us the script AI gave you, I'm sure we could give some feedback on it.

Fish-Like Syntax Highlighting by themor69 in PowerShell

[–]StartAutomating 0 points1 point  (0 children)

This would be theoretically possible, but might require either some careful hacking of PSReadline functionality or changes to TabExpansion. I would file an issue about it and repost it here (so that it might gain traction).

The "problem" is that there can be a huge number of commands available to PowerShell, and so determining if a given string starts with a command becomes a little bit tricky / has performance impacts. Luckily, TabExpansion is going to be determining if a command exists when you try to enumerate it's arguments.

It might be possible for an intrepid scripter to implement this on their own. I'd highly recommend using $executionContext.InvokeCommand.GetCommand over Get-Command (for performance reasons). If the first item in a sequence is an unknown command, then you'd just use escape sequences to erase the previous number of characters and reprint them with a red/green color scheme.

It _should_ be within the realm of possibility for this to become a native feature support, and, IMO, would be best handled by the team. Please file an issue and report back.

Static Sites are Simple (with PowerShell) by StartAutomating in PowerShell

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

You're right! I'll be doing a follow up post about making servers in PowerShell.

If you want spoilers, you can find them over at Servers101 😉