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?
Related
I have a powershell script that I am converting from running as a fore-front infinite while-loop to a scheduled task. The biggest problem here is that I would still like to maintain a log. Start-Transcript was the bit that did the logging previously, but that doesn't work with the background task.
These links (1, 2) show similar questions, but they only give the information that start-transcript won't work. They don't give any indication as to how it could be done.
Basically you can do two things:
Add logging routines to your script (see for instance here).
Run the script like this:
powershell.exe -Command "&{your.ps1 *> your.log; exit $LASTEXITCODE}"
Personally I'd prefer the former, but it'd require more changes to your code.
In my scenario, I have a powershell script that receives standard input. What I would like to do is start a subprocess using an arbitrary command line and redirect the standard input from the powershell script to the subprocess. In other words, I simply want to pass down the standard input to the subprocess.
I have a few ideas on how to do this with loops, but is there a more elegant way?
Not a full answer, but you might have some trouble with this in certain cases, because PowerShell.exe waits for all of the input before it even begins executing your script. I ran into an issue where a process calling PowerShell didn't close its stream so PowerShell waited forever.
The solution was to use an undocumented option (powershell.exe -InputFormat None) and then read the input manually byte by byte; all methods that read more than 1 byte at a time are susceptible to blocking forever, at least as far as I could tell.
You could probably work around that with asynchronous methods.
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.
I know there has to be an easy solution to this but I have been searching for two days now with no luck.
Basic goal:
I want to query (and set) the state of Scheduled Defrag using PowerShell
Limitations: Must be able to work when run with the system set to any language, Must not require installing any additional software, packs, etc (ie clean system), Must be able to run on any system Windows 7+ (ideally even earlier)
Issues:
I can get the state using 'schtasks /query /TN
'\Microsoft\Windows\Defrag\ScheduledDefrag'' but this is (a)
directory language dependent, and more importantly (b) returns
everything as a string of some sort, meaning state is something
like 'Disabled'.. in English. But every language returns its own
word for 'Disabled', in its own character code, meaning hard-coding
over a hundred languages x the number of options
Windows 7 does not recognize Get-ScheduledTask (seems to be
Win8+), even if it did not sure how to query 'Disabled' as a state
without using the actual word
I have to be missing something very basic but all I am finding are suggestions to install Powershell packs, and responses dealing specifically with English. Any suggestions?
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.