powershell Command Works When run alone, but note when scripted - powershell

I am working on a deployment script for some software, and my script is working on probably 90% of the machines it runs on, but on the other 10%, I get a failure in the download portion. Here is what I have:
$tls = "Tls";
$Token = "#ZorusKey#";
[System.Net.ServicePointManager]::SecurityProtocol = $tls;
$source = <Source>
$destination = "C:\installers\ZorusInstaller.exe";
$WebClient = New-Object System.Net.WebClient
$WebClient.DownloadFile($source, $destination)
I have created the C:\installers folder on all target machines, so I don't think that's the problem. When run as a script, I get the following exception:
Exception calling "DownloadFile" with "2" argument(s): "An exception occurred during a WebClient request."
At C:\Windows\system32\config\systemprofile\AppData\Local\f1e96243cb9c4ef0b0336a152ed8827f.ps1:8 char:1
+ $WebClient.DownloadFile($source, $destination)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Which then causes the following steps to fail, as the downloaded file doesn't exist.
I have also taken the step on several of the failing machines of running each line of the script above one at a time (copied / pasted from the same Powershell ISE window) and the download works without issue. looking for a possible reason / resolution.
Thanks in advance.

Related

Powershell script throwing error while calling an API using ssl

We have a powershell script which is used to call an API by establishing connection over SSL. The certificates are placed along powershell script to be used by it. And the password is mentioned in an ini file which script reads. It was working fine earlier but suddenly it has started giving below error:
Exception calling "Import" with "3" argument(s): "The specified network password is not correct.
"
At C:\Users\Administrator\Desktop\NewInstallIssue\Download\win\installCDWindows.ps1:70 char:3
+ $cert.Import($CertificatePath, $KeyStore_Password ,'DefaultKeySet')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CryptographicException
The part of powershell script throwing this error is:
$cert= New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$CertificatePath = Join-Path -Path $PSScriptRoot -ChildPath 'cdCert.pfx'
$cert.Import($CertificatePath, $KeyStore_Password ,'DefaultKeySet')
$KeyStore_Password contains correct password as I tested what is stored in this variable just before $cert.Import using echo.

Using MAPI to create a PST file with WinRM

I have the following PowerShell code which creates a PST file
enter code Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -comobject Outlook.Application
$namespace = $Outlook.GetNameSpace("MAPI")
$namespace.AddStore("C:\tmp\file.pst")
Running this code locally works excellent, but I have to run this code remotely. The script is sitting on the Windows machine and I'm starting it from Linux using WinRM (python) in that setup, it hangs on AddStore(). I assume this is related to user/security context but I can't find the resolution or info if it is possible to run it with some configuration changes.
EDIT: Ok, it is not hanging it just taking a long time before it will fail with the following error:
New-Object : Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed
due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005
(CO_E_SERVER_EXEC_FAILURE)).
At C:\\tmp\\pst.ps1:3 char:12
+ $Outlook = New-Object -comobject Outlook.Application
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\\tmp\\pst.ps1:4 char:1
+ $namespace = $Outlook.GetNameSpace("MAPI")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\\tmp\\pst.ps1:6 char:1
+ $namespace.AddStore("C:\\tmp\\file.pst")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
'
CO_E_SERVER_EXEC_FAILURE means Outlook.exe and your code are running in different security contexts, and hence the COM system refuses to marshal calls between the two processes.
Firstly, Outlook cannot be used from anything that runs outside of an interactive user context (such as service or a scheduled task). Secondly, does it work if Outlook is not yet running on the target machine?
That being said, Extended MAPI (C++ or Delphi only) code runs in-proc might be able to do the job. If C++ or Delphi are not an option, you can try Redemption (any language - I am its author) - RDOSession.LogonPstStore is probably what you need - it creates and deletes a temporary profile that loads the specified PST file.

Take Ownership of Registry Subkey and Delete It via SYSTEM Account

I am deploying an update via WSUS to remove broken registry keys from Windows 10 systems running 1703 and 1709. The PowerShell code needs to open two registry keys, take ownership, set ownership to users, then delete them. The code below works when run from machines directly:
#Set our root registry key and new owner (Users)
$rootKey = "LocalMachine"
[System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545'
#First key
$key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileNotification\TDL"
#Take ownership and delete if it exists
if (Test-Path "HKLM:\$key") {
$regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')
$acl = New-Object System.Security.AccessControl.RegistrySecurity
$acl.SetOwner($sid)
$regKey.SetAccessControl($acl)
$acl.SetAccessRuleProtection($false, $false)
$regKey.SetAccessControl($acl)
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileNotification\TDL" -Force -Recurse
} else{
Add-content $txtLogLocation "Key 1 does not exist."
}
However, I receive the following error when this code is run as the SYSTEM user (I deploy it via Windows Update, which runs this as SYSTEM):
Exception calling "OpenSubKey" with "3" argument(s): "Requested registry
access is not allowed."
At C:\Windows\TEMP\7zSAA99.tmp\1809ReadinessScript.ps1:224 char:2
+ $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SecurityException
Exception calling "OpenSubKey" with "3" argument(s): "Requested registry
access is not allowed."
At C:\Windows\TEMP\7zSAA99.tmp\1809ReadinessScript.ps1:224 char:2
+ $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SecurityException
Any thoughts on why this might be happening? Is it due to the SYSTEM user running it, or is it some odd PowerShell issue that requires a different method to handle opening registry keys?
I was able to work around this issue by using PowerShell to create a scheduled task that then runs the script that is downloaded locally to the machine. The task runs as the local user, which has the ability to open the subkey and thus change the permissions. SYSTEM for whatever reason did not have read access to this particular key.

DownloadString Path error

I'm using the Invoke-Expression cmdlet in PowerShell to load modules.
The following code works as intended.
$url="http://pastebin.com/raw/FuxtpN69"
IEX (New-Object System.Net.Webclient).DownloadString($url)
But when I try using variables to split the domain and the page.
$u="http://pastebin.com"
$rl="/raw/FuxtpN69"
$url="$u$rl"
IEX (New-Object System.Net.Webclient).DownloadString($url)
I get the following path error:
Exception calling "DownloadString" with "1" argument(s): "The given path's format is not supported."
At line:8 char:53
+ IEX (New-Object System.Net.Webclient).DownloadString <<<< ($url)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Can someone help me? Thanks in advance.
I think you are running PowerShell as a different account (for example an administrator).
Maybe that account's proxy settings are different that your normal account's?
See the credentials part first,
$webClient.UseDefaultCredentials = $true
Then, Try setting
$client.Proxy = $null
before downloading and see if it helps.

Powershell scripts will not work with Jenkins plugin on Windows

I'm writing some pretty simple scripts in Powershell 32-bit and they are working fine.
For instance, I want to open internet explorer to a webpage and start typing in keys. The following code works fine when I run it in powershell ISE.
Add-Type –AssemblyName System.Windows.Forms
$url = "http://WebAddress"
$ie = New-Object -com "InternetExplorer.Application"
$ie.Navigate($url)
sleep 30
[System.Windows.Forms.SendKeys]::SendWait("{2}{tab}{H}{E}{L}{L}{O}")
I have downloaded a Windows PowerShell plugin and have executed the same code through it and received the following errors:
Building on master in workspace C:\Program Files\Jenkins\workspace\Jenkins Test
[Jenkins Test] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\WINDOWS\TEMP\hudson257018662776252417.ps1'"
New-Object : Creating an instance of the COM component with CLSID {0002DF01-000
0-0000-C000-000000000046} from the IClassFactory failed due to the following er
ror: 80004005.
At C:\WINDOWS\TEMP\hudson257018662776252417.ps1:4 char:17
+ $ie = New-Object <<<< -com "InternetExplorer.Application"
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMExcept
ion
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Comman
ds.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\WINDOWS\TEMP\hudson257018662776252417.ps1:5 char:13
+ $ie.Navigate <<<< ($url)
+ CategoryInfo : InvalidOperation: (Navigate:String) [], RuntimeE
xception
+ FullyQualifiedErrorId : InvokeMethodOnNull
Exception calling "SendWait" with "1" argument(s): "Access is denied"
At C:\WINDOWS\TEMP\hudson257018662776252417.ps1:9 char:42
+ [System.Windows.Forms.SendKeys]::SendWait <<<< ("{2}{tab}{H}{E}{L}{L}{O}")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Is there a reason why my code will not work through Jenkins like it does in Powershell? I tried some simple echo scripts which worked fine, but any more complex and it throws an error.
You may need to set execution policy once: https://technet.microsoft.com/library/hh849812.aspx
Set-ExecutionPolicy Unrestricted
Run PowerShell as admin and run that command. There may be security concerns using Unrestricted. But if it works, read the link above and find the policy that works best in your context. Options are (copy/pasted from the link):
Restricted. Does not load configuration files or run scripts. Restricted is the default execution policy.
AllSigned. Requires that all scripts and configuration files be signed by a trusted publisher, including scripts that you write on
the local computer.
RemoteSigned. Requires that all scripts and configuration files downloaded from the Internet be signed by a trusted publisher.
Unrestricted. Loads all configuration files and runs all scripts. If you run an unsigned script that was downloaded from the Internet,
you are prompted for permission before it runs.
Bypass. Nothing is blocked and there are no warnings or prompts.
Undefined. Removes the currently assigned execution policy from the current scope. This parameter will not remove an execution policy
that is set in a Group Policy scope.