Powershell script fails during remote execution but works locally - powershell

I am attempting to execute the code below. The errors are self-explanatory but only occur when run remotely. When run locally, all the code works and I can verify that they have the desired effect by pulling content from a web server that requires Tls12 and receiving an error when I have not changed the security protocol.
$tls12 = [Enum]::ToObject([Net.SecurityProtocolType], 3072)
[Net.ServicePointManager]::SecurityProtocol = $tls12
When run on the server, they execute flawlessly. When run remotely via Invoke-Command I receive this error.
Exception setting "SecurityProtocol": "The requested security protocol
is not supported."
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
+ PSComputerName : servername
Alternatively, this line of code which is fundamentally the same.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
This also works when run on the server directly but results in this error when run remotely.
Exception setting "SecurityProtocol": "Cannot convert null to type
"System.Net.SecurityProtocolType" due to invalid enumeration values. Specify one of the following enumeration values and
try again. The possible enumeration values are "Ssl3, Tls"."
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
+ PSComputerName : servername
The remote server Windows Server 2008 R2 and is running powershell 2.0. The latest Framework version installed is 4.5 release 378389. The machine I am executing from is Windows 10 running powershell 5.0 and Framework 4.6.2 in case it matters.
This is the code I am using to execute it remotely.
$webSession = New-PsSession -ComputerName servername
$cmd = {
#$tls12 = [Enum]::ToObject([Net.SecurityProtocolType], 3072)
#[Net.ServicePointManager]::SecurityProtocol = $tls12
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
Invoke-Command -ScriptBlock $cmd -Session $webSession
remove-pssession $webSession
If anyone has an idea or suggestion, I would greatly appreciate the help.

[Note: The remainder of this answer SHOULD be true, but ISN'T: Even though the Tls12 value is not defined in an interactive PSv2 session, it can be assigned and takes effect using the OP's workaround, [Net.ServicePointManager]::SecurityProtocol = [Enum]::ToObject([Net.SecurityProtocolType], 3072); by contrast, trying the same thing via PS remoting, using Invoke-Command -ComputerName fails for him. Upgrading PowerShell on the target machine may still be the answer, but this answer offers no explanation of the behavior.]
As Sambardo notes in a comment on the question, the symptom implies that the remote target machine doesn't support the Tls12 value:
PSv2 invariably uses a 2.0 version of the .NET framework, where TLS 1.2 is not supported - irrespective of the presence of newer .NET frameworks on a given machine.
If you run [enum]::GetNames([Net.SecurityProtocolType]) on a machine with PSv2 , you'll see that only the following values are supported:
# PSv2
> [enum]::GetNames([Net.SecurityProtocolType])
Ssl3
Tls
So the answer is to upgrade PowerShell on the remote machine.
As an aside: PowerShell's great flexibility around type conversions allows you to simply use string representations of [enum] values; e.g., the following 2 statements are equivalent:
[Net.ServicePointManager]::SecurityProtocol = 'Tls'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls

Related

Error downloading files with DownloadFile in powershell 2

I have the need to download files under powershell 2.
Since Invoke-WebRequest is not supported in version 2, I try to use DownloadFile but I always get the same error and I don't know how to fix it.
PS C:\Users\user> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
:: : Exception setting "SecurityProtocol": "Cannot convert null to type "System.Net.SecurityProtocolType" due to invali
d enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values ar
e "Ssl3, Tls"."
At line:1 char:28
+ [Net.ServicePointManager]:: <<<< SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
PS C:\Users\user> $client = new-object System.Net.WebClient
PS C:\Users\user> $client.DownloadFile("https://web.com/test.txt", "C:\Users\user\Desktop\test.txt")
DownloadFile : Exception calling "DownloadFile" with "2" argument(s): "The underlying connection was closed: An unexpec
ted error occurred on a send."
At line:1 char:21
+ $client.DownloadFile <<<< ("https://web.com/test.txt", "C:\Users\user\Desktop\test.txt")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
What I can do?
If you are getting an error setting the TLS version, you may want to check which protocols are available:
[Net.SecurityProtocolType]::GetValues( 'Net.SecurityProtocolType' )
However, I don't know how the protocol availability will be affected by using such an old version. Moreover, I don't know how specific protocol settings on a given system affect the availability of protocols either at large or as returned by the above command.
In fact, I would point out the error itself only reflects SSL3 & Tls. On my system when I enter an invalid enumerator the error reports Ssl3,Tls,Tls11,Tls12,Tls13 as choices. While my system is configured to disable everything below Tls12 and has no settings defined for Tls13.
The best assumption I can make is .Net 2.0 which is used with PowerShell 2.0 cannot use Tls12 as it's not present in the enumerators and based on comparison with my system the enums aren't affected by explicit enabling/disabling of protocols.
In any case, I think you have to clear up the first error before you worry about the second. The second error may well be due to the TLS incompatibility. The easiest way to do this would be to upgrade PowerShell (along with the required .Net version). PowerShell 2.0 can coexist with Windows PowerShell 5.1 though you may have to launch with the -Version 2.0 parameter. Also, make sure the engine is installed as a Windows feature. DISCLAIMER: verify all that on your own.
I know the Windows PowerShell 2.0 Engine (PowerShell-V2) was available as a feature at least as late as Windows 2012 R2.
I would also point out that PowerShell 7.x (aka PowerShell Core) can be installed side by side with Windows PowerShell. Potentially this could sidestep the aforementioned complications, allowing you to do run the task at hand...

Why do I get a "Get-WindowSize" not implemented error when using the PowerShell call Get-Service on a remote machine?

I have a Windows 10 host machine that connects to a Hyper-V Windows 10 VM hosted on the same box.
I've been following along the Pluralsight PowerShell tutorial.
I'm trying to get the services available on a remote computer.
I can start a session on the remote computer with the following command:
Enter-PSSession -ComputerName Client1 -Credential username
Once the session has started and I am connected, I attempt to call Get-Service to identify the services on the client computer.
[Client1]: PS C:\Users\username\Documents>Get-Service
When I run the above command, I get the following error message:
Remote host method get_WindowSize is not implemented.
+ CategoryInfo : ResourceUnavailable: (:) [out-lineoutput], PSRemotingDataStructureException
+ FullyQualifiedErrorId : System.Management.Automation.Remoting.PSRemotingDataStructureException,Microsoft.PowerShell.Commands.OutLineOutputCommand
I am running the same version of PowerShell on the host and client machines (5.1.18362.145).
I assume that somehow this is an issue on the client machine?
[Client1]: PS C:\Users\username\Documents>Get-Service | out-string
That should work, maybe a bug with PowerShell or new version of Windows 10
Other link : https://social.technet.microsoft.com/Forums/en-US/67142783-2acd-4d54-aef2-8d89d71457c5/powershell-remoting-broken-in-windows-10-1903?forum=winserverTS
"Remote host method get_WindowSize is not implemented."
This happens to all Remoting Sessions started With Powershell_ISE on the Client-Side.
The workaround with Out-String sucks, it destroys the Result-Object of that call.
Best fix so far is either using not ISE or embed your remote Procedure in a Script and call it with Powershell.exe
Really annoying...and not fixed by now.
Workaround Example: Instead of using enter-pssession and then asking for a result of running services, you could use: $YourServices=Invoke-command -ComputerName <computername> -ScriptBlock {get-service}. Then you have all Service-Stats in your Object $YourServices.

Schedule.Service erroring out while connecting to localhost

I have a PowerShell script that connects to a list of servers, and queries that scheduled tasks. (Something similar to https://community.spiceworks.com/scripts/show_download/2094-get-scheduled-tasks-from-a-computer-remote-or-local) It used to work fine on a Windows 2008R2 server. However, on a new Windows Server 2012 R2 server, it is giving the below error. Strange thing it only happens when connecting to the local machine, no errors to remote servers. And it doesn't raise any errors when running under my account using administrative privileges.
https://www.powershellmagazine.com/2015/04/10/pstip-retrieve-scheduled-tasks-using-schedule-service-comobject/
This article says
Unfortunately, unlike the Get-ScheduledTask cmdlet using this COMObject requires an elevated PowerShell console with administrative credentials.
But the script used to work just fine on Windows Server 2008 R2 servers.
Is there anything that can be tweaked to make the script work on 2012 R2 servers?
Exception calling "Connect" with "1" argument(s): "Access is denied. (Exception
from HRESULT: 0x80070005 (E_ACCESSDENIED))"
At C:\scripts\CheckSchedulers\CheckSchedulers.ps1:20 char:10
+ ($TaskScheduler = New-Object -ComObject Schedule.Service).Connect($curSe ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
The error is raised by my code, using the code from spiceworks, it is reproducible.
You're creating a Schedule.Service object, assign it to a variable, and then try to call a Connect() method on the result of that assignment. I would not expect this to work on any Windows or PowerShell version, and if it did on Server 2008 R2 that's most likely just incidental.
You need the Schedule.Service object in a variable (because you're going to need it for other operations as well), and you must call Connect() on that object, so you need to do this in two steps:
$TaskScheduler = New-Object -ComObject 'Schedule.Service'
$TaskScheduler.Connect($servername) # connect to remote Task Scheduler
If you're connecting to different servers in a loop you can re-use the object and just Connect() to the next server.
For connecting to the local Task Scheduler service just remove $servername and call the method without argument:
$TaskScheduler.Connect() # connect to local Task Scheduler

Powershell Invoke-RestMethod "Unable to connect to the remote server"

I write a very simple powershell script to post a json string to server. I have a strange issue when I execute the script.
The server is inside our intranet, the firewall is disable for all intranet server.
I tried to execute the script in different places:
Powershell window in my own computer (windows 7, powershel 5)
Powershell ISE in my computer
start powershell.exe in a command prompt in my own computer
start powershell.exe in a third party command prompt application in my own computer
Powershell window in a citrix seesion (windows 10, powershel 5)
start powershell.exe in a command prompt in a citrix seesion
I checked all of 6 places have ExecutionPolicy "RemoteSigned",
But, I can only successfully execute the script in last 3 places,
In first 3 place, I get an error
Invoke-RestMethod : Unable to connect to the remote server
At F:\Temp\test.ps1:46 char:9
+ $resp = Invoke-RestMethod -Method POST -Body $result ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Invoke-RestMethod],
WebException
+ FullyQualifiedErrorId : System.Net.WebException,Microsoft.PowerShell.Com
mands.InvokeRestMethodCommand
Besides, I also tried Invoke-WebRequest, I got same error message.
Any idea why this is happen? What should I do with it?
I solved same problem by disabling / commenting out proxy settings in the machine.config file which I enabled to intercept network calls from my .Net application in Fiddler.
Please note that you need to restart your computer after you make change in machine.config file. And also make sure you run editor as Administrator to edit config file.
Path:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config
Configuration Element:
configuration -> system.net -> defaultProxy
I had similar issue few days back and I resolved it by applying the proxy settings in the "Invoke-WebRequest" call.
Something like this;
Invoke-WebRequest -URI $url -Proxy 'http://10.10.7.11:80' -ProxyCredential $creds

Unzip with Powershell doesn't work on XP

I got the Request to unzip a .zip file with Powershell. On the Internet i found the following code multiple times:
param( [String]$newlocation, [String]$filepath)
if(($newlocation -and $filepath) -and ((test-path $newlocation) -and (test-path $filepath)))
{
Copy-Item $filepath $newlocation
$shell_app=new-object -com shell.application
$filename = $filepath.split("\")[-1]
if(Test-Path "$newlocation\$filename")
{
$zip_file = $shell_app.namespace("$newlocation\$filename")
$destination = $shell_app.namespace($newlocation)
$destination.Copyhere($zip_file.items())
}
}
As I implemented it into my script it changed a little bit. This above is the changed version. Now I've got an error:
Exception calling "NameSpace" with "1" argument(s): "The system cannot find the file specified. (Exception from HRESULT
: 0x80070002)"
At Z:\MyScripts\deploy.ps1:34 char:34
+ $zip_file = $shell_app.namespace <<<< ("$newlocation\$filename")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
And then another one, that is quite clear (caused by the first error
You cannot call a method on a null-valued expression.
At Z:\MyScripts\deploy.ps1:36 char:39
+ $destination.Copyhere($zip_file.items <<<< ())
+ CategoryInfo : InvalidOperation: (items:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The File and the destination Path both exist and I've got rights to acces them (I created both). I'm running on Windows XP with PowerShell 2.0
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
Here is my entire dump from Powershell when I run it directly on the console.
I hope you guys can help me or at least tell me where I can go to find an answer.
I tried already to unzip the zip file manually and it worked, I have got access to both, the file and the file path (as I created both).
I've found this one on the web:
Also the code looks to me like it's dependent on the Windows Explorer support for zipFolders, which you may have turned off
Unregister (disable) XP Zip folders
REGSVR32 /u C:\Windows\System32\zipfldr.dll
Register (enable) XP Zip folders
REGSVR32 zipfldr.dll
It's from here.
I came to it during testing my script on several machines, e.g. on a Windows Server 2008 and on a Windows 7 client. Both worked, so I came to the conclusion that it's not my script,but it's my PC. After the registration of XP Zip folders, it worked.
Many thanks to the guy who wrote this one, I dumped too much time into this problem.
You might be running into a problem with accessing the COM objects. If you are using 64-bit windows, make sure you execute your script from a 64-bit powershell.exe. This means the powershell.exe in c:\windows\system32...\v1.0.... This was counter-intuitive for me, having the '32' in system32. I was executing powershell from Console2, which was a 32bit process, and was therefore launching 32-bit powershell (from c:\windows\syswow64...). Also make sure your powershell.exe is being run with administrator privileges.
Instead of trying to automate the Windows Shell, now in .NET Framework 4.5 there is a ZipFile class that you can use like this:
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
[System.IO.Compression.ZipFile]::ExtractToDirectory($sourceFile, $targetFolder)
Edit: Oops, .NET Framework 4.5 is not supported on Windows XP.
Anyhow, this answer might still prove useful for anyone else with ZIP problems in Powershell…