Output all Invoke-Expression in PowerShell v2 - powershell

Trying to run an command-line executable from within a PowerShell script, unfortunately the current limitation is the host running only version 2.
The command runs fine, however it appears to only be partial output that is added to the variable, and just by chance the most important information is being missed. Is there anyway to capture everything into the output?
$output = Invoke-Expression ($itemCommand)
Write-Output $output
Testing on v3 and v4 works just fine, in fact was able to get away without using $output.
Anyone know if it is possible to have a portable copy of PowerShell v3 or v4 on a host running v2?

Related

PowerShell Script Running Issues - Has to be ran twice in ISE and does not work when executed from file explorer location

I'm currently experiencing some problems with importing/editing existing registry keys into a printer driver location.
After some searching I found that Set-ItemProperty is the exact thing I need to rewrite subkey areas within the registry, however, I've had a lot of trouble running it.
When the code is put directly into the PowerShell console it works perfectly and updates the file in just the way I want it to.
When the code is open and ran in Powershell ISE it has to run several times consecutively (spammed around 3 times) for it works.
When the code is ran from its PS1 file from its file explorer location (C:\user\RW Sandbox\Documents\Printerscripts) then it doesn't work at all, regardless of whether or not I've spammed the run invocation.
This is the code I was using (although mine includes a lot more hex than this example):
Set-ItemProperty -Path "HKLM:\SOFTWARE\Xerox\PrinterDriver\V5.0\Xerox Global Print Driver PCL6\DeviceSettings" -Name "CachedXrxDeviceSettings" -Type "binary" -Value ([byte[]](0x10,0x00,0x00,0x00,0x01,0x00,0x07,0x20,0x2b,0x16,0x58,0x02,0x00,0x00,0x00,0x00,0x4d,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x70,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03))
Within the PowerShell, the execution policy is currently unrestricted as initially, I believed that this might have been a permission issue.

PowerShell code behaving differently under SCCM and MDT TaskSequences

I've got code that has been extensively tested across multiple PowerShell sessions, multiple machines, etc all doing exactly what I expect.
switch ($e.Data.Type) `
{
{$_ -in [Policy.Reg]::SZ, [Policy.Reg]::EXPAND_SZ} `
{
$e.Data[$e.Data.Type] = ([string]$e.Data[$e.Data.Type]) -replace "{PC}", "$PC"
}
{$_ -in [Policy.Reg]::MULTI_SZ} `
{
$e.Data[$e.Data.Type] = [string[]]($e.Data[$e.Data.Type] | % { $_ -replace "{PC}", "$PC" })
}
}
[Policy.Reg] is an Enum that $e.Data.Type is a variable of that enum
Running the code from the ISE or the Powershell command line code works every time.
When I add it as a RunPowerShell task sequence step (MDT 2012/2013 and SCCM 2012 all tried) the task sequence fails with
you must provide a value expression on the right-hand side of the '-' operator. [Policy.Reg]::SZ, [Policy.Reg]::EXPAND_SZ
I'm at a complete loss what is going on when a TaskSequence runs a Powershell script that makes it different than when I manually execute the some code.
So really quick it seems my issue was with MDT itself.
The standard wsf and vbs files that control PowerShell Execution check for the existence in the registry for the currently installed version and then runs one of two executables that sets up a unique PowerShell environment.
One of the Exes just runs the most recent version of powershell.
The other forces it to run in powershell 2.0 (for compatibility i'm guessing)
Here's the issue the LOGIC in the script file is all wrong
Instead of being something like
if (PSVersion >= 2.0) then
Run newest PowerShell
else
Run PowerShell 2.0
end if
It looks like
if (PSVersion = 3.0 then
Run newest Powershell
else
Run Powershell 2.0
end if
So since all my images have PowerShell 4.0 installed on them, well as LOGIC dictates 4.0 is NOT equal to 3.0 so off to PowerShell 2.0 we go and toss out ALL the things we have gotten used to having since we spent a LONG time ensuring every system in our environment is at least on PowerShell 4.0
So in the end a little code change to the code Launching the PowerShell Scripts fixed the issue.

CmdLet works in PowerShell but not in PowerShell ISE

Lately I have been developing PowerShell scripts on a Window 8 machine instead of on a Windows Server 2012R2 which I normally do.
I have encountered two very strange things that never happened on the server.
I know, two questions in one post, but I believe they might be connected.
After a while cmdlets just stop producing any output whatsoever, no error messages, no verbose output. It doesn't matter if I run it in the "lower" command part or in the "upper" script editor, and no difference if I run a selected part of the script or the whole thing. If I switch to a "normal" PowerShell the cmdlet works fine. If I restart PowerShell ISE, the cmdlet start working again, but only for a like 2-5 execution (not at all exact number) after which it stops working again. Not all cmdlets behave this way, mostly had problems with Storage related cmdlets (Format-Partition, Get-Disk, Get-Volume and so on).
After a while cmdlets that used to work fine in the "upper" script part of PowerShell ISE just stops working. The cmdlets still work fine in the "lower" command part of the ISE GUI, but does not work when used in the "upper" script editor, even though they did just a second ago. And it doesn't matter if I run the whole script or just a selected part. And by not working I mean it can't even find the cmdlet (The term '' is not recognized as the name of a cmdlet). The cmdlet is available in the Commands Side-Bar where it show up without any problem and I can access help for it.
So any ideas what is going on here?

$MyInvocation.MyCommand.Path returning NULL

I have the following code as the beginning of a longer script:
$ScriptPath = Split-Path $MyInvocation.MyCommand.Path
& $ScriptPath\build_functions.ps1
& $ScriptPath\build_builddefs.ps1
The idea is to get the path of the script being run and use that path to call some supporting scripts. However when I went to test this out in isolation to make sure it could work (by highlighting that block and running just that code), I got the following error:
Split-Path: Cannot bind argument to parameter 'Path' because it is null.
Interestingly enough, when I run the entire script it seems to run these files separately. Is there something I'm missing about how the ISE handles running a selection rather than the full script? Does it not establish a file system context when you run a selection?
$MyInvocation is an automatic variable populated at script run time, then if you execute $MyInvocation.MyCommand.Path in a powershell console or ISE isn't populated;
that's why in your test the $ScriptPath has no value ($null)
I don't if what happened to me was why some where seeking null in $MyInvocation.MyCommand.Path, but I will explain how I found the solution.
I had scripts that were working in production, yet when I loaded the .ps1 file up and tried to get $MyInvocation.MyCommand.Path it was null. My version of Powershell was 4.0, but 1.0 for the ISE (%windir%\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe).
But it didn't occur to me at first why they should work, yet when I manually inspected $MyInvocation.MyCommand.Path or $MyInvocation in PowerShell why it was null, and why I was getting a null error for Split-Path -parent $MyInvocation.MyCommand.Path.
So I thought I needed to upgrade the powershell to 5.1 on my Windows 2012 R2 Server like on my desktop NUC PC.
The real problem was that I found that if I set a break point in my .ps1 file and ran it to the spot where I was doing:
$ScriptDir = Split-Path -parent $MyInvocation.MyCommand.Path
That it worked. Of course it worked, I had been using it for a while. Why didn't I see it before?
What went wrong? I was trying to manually run the PowerShell in pieces using the run step command, when I had never run the script before since PowerShell was open!
I have to say this is probably a No Duh moment.
But we had recently had a server crash and had it restored (VSphere Clustered) and reseeded, so I thought maybe I have an older version of PowerShell.
PowerShell allows you to have multiple files/windows open inside it, yet the variables are shared between them. Apparently until you actually try to run the script (not step by step run), it has no script file executing and can't get you the path.
I hope this post saves someone from wasting a bunch of time like I did!
i think you need write just:
& .\MySuperDuperScript.ps

My PowerShell script only works when running from ISE

I can't post all of the script contenet, but the basic idea is that it downloads JSON and converts it to objects using the ConvertFrom-Json cmdlet. Some objects are filtered out, and the rest are written to an XML/XLS document (in the Excel 2003 format). This file is then attached to an email and sent to various people.
The problem I'm having is that it only works when run from the Powershell ISE. Once I try setting up a scheduled task, calling it from cmd, or even calling it from powershell, the attached file is completely empty. It is as if some functions do not run (the one that loops through and creates all rows).
I can continue to run from ISE for the time being, but the idea of this script is to send out an automatic email that will require no intervention. Any ideas as to what could be causing this?
You need to run the script "dot sourced"
which can be done like this
powershell.exe -noexit -file c:\test.ps1
or
pwershell.exe -noexit ". c:\test.ps1"
See this link under the -File section
http://technet.microsoft.com/en-us/library/hh847736.aspx
Based on the answer from the comments to the original post, it seems that the script was (unexpectedly?) working in the ISE because of the bug/quirk/feature that allows scripts run in the ISE to be aware of variables used in the console window and vice-versa.
This can often cause logic problems or unexpected results when a script runs with a variable already defined (and not initialized carefully in the script).
Ways to avoid this problem:
Try to test your code in as clean an environment as possible.
http://powershell.com/cs/blogs/tips/archive/2015/02/12/getting-a-clean-powershell-environment.aspx
To make sure a script runs in a completely clean test environment, you
could of course restart the PowerShell ISE. A more convenient way is
to open another PowerShell tab: in the PowerShell ISE, choose File/New
PowerShell Tab.
Use Set-StrictMode 2 in your script to catch undefined variables, etc.
https://technet.microsoft.com/en-us/library/hh849692.aspx
Set-StrictMode -Version 2.0
Prohibits references to uninitialized variables (including uninitialized variables in strings).
Prohibits references to non-existent properties of an object.
Prohibits function calls that use the syntax for calling methods.
Prohibits a variable without a name (${}).
I have had this problem be for and for me executing the scrip using single-threaded function from powershell worked.
You could also try some other options, go to this link to find more info.
Example
powershell.exe -noexit c:\test.ps1 -sta
Change the missing variable or function to global.
function global:mycall{}
Start your Script with:
[cmdletbinding()]