Is there any builtin functionality with Powershell that allows you to examine system processes in great detail, and view/manipulate its I/O stream? Are there any community modules? Has anybody worked with process streams and know of any good references for such work?
The standard cmdlets provided by powershell allows you basic operations on processes. Get-Process cmdlet returns all running processes objects with detailed information about the process. You can also get the modules that the process loaded using the parameter -Module. You can use start/stop process cmdlets to manage the list of running processes.
However, the returned objects give you all information you may search for. Get-Process returns objects as System.Diagnostics.Process, while Get-Process -Module returns objects as System.Diagnostics.ProcessModule.
Related
I am using powershell to manage a benchmark of Autodesk's Revit product. It uses Start-Process -wait to run Revit with a journal file as an argument, and the journal file allows for consistently repeating the same test. The issue I am seeing is that often either the Revit startup is very slow, compared to a "manual" startup, or there is a VERY long (sometimes a minute or more) pause between Revit closing and Powershell continuing. Since I sometimes repeat this process with as many as 20 journals, it leads to a very long test process.
What I wonder is, is there a more performant replacement for Start-Process. Often in Powershell there is a less performant but very syntactically convenient native Powershell cmdlet, and there is a much more performant but syntactically fussy .NET version. Is this true for Start-Process too?
Or is there perhaps some addressable issue related to how quickly Powershell responds after control is returned?
9/10 times if you are trying to use the Invoke-Expression cmdlet, there is a better way. Building the arguments to a command dynamically? Use an array of arguments. Building the arguments to a cmdlet? Use splatting with an array or hashtable. Your command has a space in the path to it? Use the call operator (&).
This might seem open ended, but Invoke-Expression is an easily accessible cmdlet where the answer is almost always to never use it. But the cmdlet exists for a reason, is not deprecated, and most criticisms of its use state something similar to, "it's almost never the right answer", but never states when it is acceptable to use it. In what case is it acceptable to use Invoke-Expression? Or to word it a bit less openly, how was Invoke-Expression designed to be used?
To quote from a PowerShell team blog post titled Invoke-Expression considered harmful (emphasis added):
The bottom line: Invoke-Expression is a powerful and useful command for some scenarios such as creating new scripts at runtime, but in general, if you find yourself using Invoke-Expression, you should ask yourself, or maybe a respected colleague if there is a better way.
EBGreen notes:
Or to phrase it another way, It [Invoke-Expression] is ok to use as long as a user is never involved in any part of generating the string that will be invoked. But even then, not using it will enforce better habits than using it would.
In short:
As a matter of habit, always consider a different (usually more robust and secure) solution first.
If you do find that Invoke-Expression is your only choice, carefully consider the security implications: if a string from an (untrusted) outside source (e.g., user input) is passed directly to Invoke-Expression, arbitrary commands may be executed.
Therefore: Only use Invoke-Expression if you fully control or implicitly trust the input.
Note: As of Windows PowerShell v5.1 / PowerShell Core v6.1.0, the official Invoke-Expression help topic doesn't provide such guidance; this GitHub issue suggests rectifying that.
Rare examples of justified (safe) use of Invoke-Expression:
Creating PSv5+ custom classes dynamically:
so that the class can be used in a remote session.
so that the set of properties can be created based on conditions at runtime.
Using Invoke-Expression in combination with Write-Output:
to parse a string with embedded quoting, with extra precautions.
to parse command lines stored in a file, if trusted.
Using Invoke-Expression for nested property access:
via a property path stored in a string.
There is an Exchange Online/Exchange 2016 Powershell Cmdlet Update-DistributionGroupMember which is supposed to ...replace all members of distribution groups... (https://technet.microsoft.com/en-us/library/dd335049(v=exchg.160).aspx). Does anyone know if I can trust it to be atomic/transactional, meaning that it will either complete its task or give me an error and leave the distribution group membership as it was? Or do I have to be prepared for the scenario in which it only does part of its task and leaves the DG in a halfway state?
thanks!
Martin
This cmdlet notwithstanding. The same can be said for any code you run. Out of box or self created.
You must always be prepared for failure. Just like the old adage, the only good backup up is a tested and validated one. The number of times, I've seen org do backups and never test the restore and then realize that backup was crap, I've stopped counting.
Trust is on the process, validations in that process, and intimate knowledge of the actions about to be taken, not the code alone.
Bulk updates, like this, are always an one an done thing. It either works or it doesn't. Which is why they should always be approached with caution, to avoid corruption. Otherwise, you need to chunk the update and validate success of a chunk before you attempt to process another chunk.
There is no out of box concept of apply a change, validate the change before moving to the next without you writing that logic in to you code.
PowerShell does have the concept of transactions, but not all things support it.
# Get parameters, examples, full and Online help for a cmdlet or function
(Get-Command -Name Start-Transaction).Parameters
Get-help -Name Start-Transaction -Examples
Get-help -Name Start-Transaction -Full
Get-help -Name Start-Transaction -Online
So, you have to manually look at each of the planned cmdlets and see if it supports the -UseTransaction option and if that meets your needs. You can do that this way...
Get-Help * -parameter UseTransaction
After writing a Powershell script to build a list of servers and then perform some maintenance activity on each, I decided to split it into two parts. The inner script, call it scriptB, does its thing on the server whose name is passed in; the outer script, scriptA, builds the list of servers and runs scriptB on each. The idea is that scriptA will someday be able to run a choice of scripts -- scriptB or scriptC, for instance -- against each server, depending on a control parm. And the maintenance script (B or C) can also be run by itself, i.e. by passing it the name of the target server.
I call scriptB from scriptA using invoke-command with the -filepath option, and this appears to work just fine. Except that, for each iteration, the content of scriptB appears in the output. If I call it three times then I have three copies of scriptB in the output. I already have write-output statements in scriptB that explain what's going on, but those messages are hard to spot amid all the noise.
I have tried assigning the output to a variable, for instance:
$eatthis = invoke-command -computername sqlbox -filepath c:\dba\scriptB.ps1
and then it was quiet, but the variable ate the good output along with the unwanted listings ... and it is large enough that I would prefer not to parse it. I tried reading up on streams, but that didn't look like a promising direction either. At this point I'm ready to convert scriptB to a function and give up the benefits of having it be a standalone script, but if anyone knows an easy way to suppress the listing of an invoke-command scriptblock specified via -filepath then that would be helpful.
Alternatively, a good way to phrase this for Google would be welcome. Search terms like "listing," "echo," and "suppress" aren't getting me what I need.
Convert your scripts into advanced functions. They can be stored in separate files and dotsourced in the master script. This loads the function and makes it available.
e.g.
c:\scripts\ComplicatedProcessfunctions.ps1
(which contains function Run-FunctionB {...} and later function RunFunctionC {...})
Then call the function
$dataResults = RunFunctionA
or even
$dataResults += RunFunctionA
if you're running within a loop and building a collection of results. Which sounds like you might be.
Make sure each function returns its data as an object or collection of objects. Probably a custom powershell object of your creation.
The master script then processes the results.
I would recommend Get-Help about_advanced_functions, the scripting guys blog, and the Powershell Scripting Games website for information on how to build advanced functions, and how to do it right.
Approaching cmdlets in a conceptual way,
How are they made? Are they compiled?
Is it the equivalent of a batch file for PowerShell? Is it a script or a binary?
What is the structure used for storing these cmdlets?
A PowerShell cmdlet is a compiled piece of .NET code, more precisely a single class if I am not mistaken. Cmdlets are kind of the "native" commands in PowerShell land, being able to handle object input and output as well as usually playing nice and well with the (object-based) pipeline.
Cmdlets have no direct representation in the file system, as they are not programs or similar. They exist solely within PowerShell. You can use the Get-Command cmdlet to query all available cmdlets, functions, etc.
You can write cmdlets with a .NET language, such as C#. With PowerShell v2 there is also the possibility to write so-called advanced functions which behave similarly to cmdlets and have comparable capabilities but are interpreted PowerShell code, instead of compiled classes. This may incur a run-time overhead.
This link may help in understanding powershell cmdlet:
http://www.powershellpro.com/powershell-tutorial-introduction/tutorial-powershell-cmdlet/
See Scripting with Windows PowerShell.
A PowerShell cmdlet is a user-created extension to the PowerShell scripting language. The Cmdlet itself is a .NET class extending from PSCmdlet. Usually, additional components are included with the cmdlet to provide help and registering the cmdlet.
A cmdlet allows you to access to all functions accessible through the .NET virtual machine. This can range from simple script aids to fully functional programs.