MI_RESULT_FAILED on Copy-Item in PowerShell Script - powershell

I am running PowerShell on CentOS 7.x. I converted working individual commands when running within PowerShell via pwsh to a PowerShell script and then it no longer works. Can someone please shed me some light on what I did wrong?
Here's the working individual commands when running within PowerShell via pwsh.
PS /home/user1/Downloads> $userPw = ConvertTo-SecureString -String "user1password" -AsPlainText -Force
PS /home/user1/Downloads> cd
PS /home/user1> $userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "user1win", $userPw
PS /home/user1> $s = New-PSSession -computerName 192.168.20.143 -credential $userCredential -Authentication Negotiate
PS /home/user1> Copy-Item -Path /home/user1/Downloads/gssntlmssp-0.7.0-1.el7.x86_64.rpm -Destination "C:\users\user1win\Desktop" -ToSession $s
PS /home/user1> exit
Here's the script when I converted to a PowerShell script so I can pass arguments into it. remote-copy.ps
$remoteHost = $args[0]
$username = $args[1]
$pwp = $args[2]
$source = $args[3]
$destination = $args[4]
Write-Host "Remote Host: '$remoteHost'"
Write-Host "Username: '$username'"
Write-Host "Password: '$pwp'"
Write-Host "Source: '$source'"
Write-Host "Destination: '$destination'"
$pw = ConvertTo-SecureString -String $pwp -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pw
$s = New-PSSession -computerName $remoteHost -credential $cred -Authentication Negotiate
Copy-Item -Path $source -Destination $destination -ToSession $s
When I run the script, I got the following error.
[user1#rhel7-tm PowerShell]$ pwsh -File ./remote_copy.ps 192.168.20.143 user1win user1password /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm "C:\\users\user1win\Desktop"
Remote Host: '192.168.20.143'
Username: 'user1'
Password: 'user1password'
Source: '/home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm'
Destination: 'C:\users\user1win\Desktop'
Copy-Item:
Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Starting a command on the remote server failed with the following error message : MI_RESULT_FAILED For more information, see the about_Remote_Troubleshooting Help topic.
Copy-Item: Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Failed to copy file /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm to remote target destination.
I would be greatly appreciate if someone can point me to where I did wrong. Thanks!

It's a false alarm. The script does work. The issue is by default the MaxEnvelopeSizekb in winrm/config is only 500kb. I need to set to a bigger value if I want to send a bigger file. To set MaxEnvelopSizekb to 500mb, you need to open PowerShell on Windows as Administrator and run the following command.
PS C:\WINDOWS\system32> Set-WSManInstance -ResourceUri winrm/config -ValueSet #{MaxEnvelopeSizekb = "500000"}

Related

Connect to server that requires authentication using PowerShell 5.1?

I am new to PowerShell. I can't connect to a server that requires a username and password.
I wrote a script that moves files from 5 different servers to 5 different sources.
Out of these 5 source servers, one of them requires a username and password to connect to it.
This script is supposed to run every hour. I want the authentication to go through so when it comes to transferring files the script runs as is without errors.
The code below gives the following error:
Connecting to remote server xx.xx.xx.x failed with the following error message : The WinRM client cannot
process the request. Default authentication may be used with an IP address under the following conditions: the transport
is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use winrm.cmd to configure
TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated.
The complete code block is:
$logPath = "C:\Users\Log.txt"
$trancriptPath = "C:\Users\LogTranscript.txt"
$getDate = Get-Date -Format "dddd MM/dd/yyyy HH:mm "
$counter = 0
Start-Transcript -Path $trancriptPath -Append
Add-Content -Path $logPath -Value ("LOG CREATED $getDate") -PassThru
#Credentials For Server5
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
Enter-PSSession -ComputerName "xx.xx.xx.x" -Credential $cred
#Sources
$srcMt01 = "\\Server2\programs\RECEIVE\*"
$srcMt01NameChg ="\\Server2\programs\RECEIVE"
$srcMC2o = "\\Server3\Predator\Revised Programs\MC2o\*"
$srcMC2oNameChg ="\\Server3\Predator\Revised Programs\MC2o"
$srcHm03 = "\\Server4\Predator\Revised Programs\H3\*"
$srcHm03NameChg ="\\Server4\Predator\Revised Programs\H3"
$srcMca = "\\Server5\Public\NcLib\FromNC\*"
$srcMcaNameChg ="\\Server5\Public\NcLib\FromNC"
$srcMt02 = "\\Server6\programs\RECEIVE\*"
$srcMt02NameChg ="\\Server6\programs\RECEIVE"
#Destination
$destMt01 = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$destMC2o = "\\Server1\MfgLib\RevisedPrograms\MC2old"
$destHm03 = "\\Sever1\MfgLib\RevisedPrograms\H3"
$destMca = "\\Sever1\MfgLib\RevisedPrograms\MC-A"
$destMt02 = "\\Sever1\MfgLib\RevisedPrograms\MT02"
Function MoveFiles{
Param(
[string]$src,
[string]$dest,
[string]$srcNameChange
)
Get-ChildItem -Force -Recurse $src -ErrorAction Stop -ErrorVariable SearchError | ForEach-Object{
$counter++
$fileName = $_.Name
# Check for duplicate files
$file = Test-Path -Path $dest\$fileName
Write-Output $file
if($file)
{
"$srcNameChange\$fileName" | Rename-Item -NewName ("Copy_"+$fileName);
Add-Content -Path $logPath -Value ("$fileName exists in destination folder. Name change was successful") -PassThru
}
}
Move-Item -Path $src -Destination $dest -Force
Add-Content -Path $logPath -Value ("$counter file(s) moved to $dest") -PassThru
}
MoveFiles -src $srcMt01 -dest $destMt01 -srcNameChange $srcMt01NameChg
MoveFiles -src $srcMC2o -dest $destMC2o -srcNameChange $srcMC2oNameChg
MoveFiles -src $srcHm03 -dest $destHm03 -srcNameChange $srcHm03NameChg
MoveFiles -src $srcMca -dest $destMca -srcNameChange $srcMcaNameChg
MoveFiles -src $srcMt02 -dest $destMt02 -srcNameChange $srcMt02NameChg
Stop-Transcript
Any help is appreciated.
You might find it easier to remote into the server using Invoke-Command and then running your file copy using a script block on the remote server. You will probably need to use CredSSP authentication so the copy process can connect to the destination server.
The server running the script will need to be configured as a WinRM client and the remote servers will need WinRM configured to accept connections. This is most likely where your current WinRM error is coming from. That's a pretty involved discussion so do some research and post specific questions as you uncover them.
Ex.
$Destination = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$SourceServer = "Server2"
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
$ScriptBlock = {
param ( [string]$dest )
Code to move the files from source to $dest
}
Invoke-Command -ComputerName $SourceServer -ScriptBlock $ScriptBlock -Authentication CredSSP -Credentials $Cred -ArgumentList $Destination

Failing to install MSI using ps1 script on remote using another PowerShell script

I am trying to install software (MSI) on remote server using a PowerShell script. The script was able to download the MSI file from the Internet, but fails to install the MSI.
When the remote script is executed directly by logging in to remote server it works fine and installs the MSI.
Script to be executed on remote servers (remote.ps1):
$base_url = "https://www.python.org/ftp/python/2.7.13/python-2.7.13.amd64.msi"
$python_filename = [System.IO.Path]::GetFileName($base_url)
$output_filepath = "D:\Temp\$python_filename"
Remove-Item -Path "C:\python27" -Force -Verbose
$installation_path = New-Item -ItemType directory -Path "C:\python27"
$get_pip_url = "https://bootstrap.pypa.io/get-pip.py"
$pip_name = [System.IO.Path]::GetFileName($get_pip_url)
$get_pip_path = "D:\Temp\$pip_name"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest $base_url -OutFile "D:\Temp\$python_filename"
Start-Process "msiexec.exe" -arg "/qn /i $output_filepath InstallAllUsers=1 TargetDir=$installation_path" -Wait
Script to be executed on the local computer (local.ps1):
$username = "user1"
$password = "password" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $password)
$script = {
Param(
[String]$Application,
[String]$Environment,
[String]$Region,
[String]$Service,
[String]$Node_Number,
[String]$proxy_sec_method,
[String]$proxy_url
)
$pyinstall = D:\Temp\remote.ps1
$pyinstall
}
Copy-Item -Path "\\localServerName\d$\Monitoring\*" -Destination "\\remoteServerName\d$\Temp" -Force -Recurse
$s = New-PSSession -ComputerName remoteServerName -Credential $cred
Invoke-Command -Session $s -ScriptBlock $script -ArgumentList $Application, $Environment, $Region, $Service, $Node_Number, $proxy_sec_method, $proxy_url -Verbose
In the local script I have tried changing the code lines $pyinstall = D:\Temp\remote.ps1 to $pyinstall = Invoke-Expression -Command 'D:\Temp\pythoninstallation.ps1' But was unable get the MSI installed.

How can I get PowerShell to use the arguments passed on the script to run successfully?

I have written a script to remotely update a machine and am currently passing the username,password and path on the script itself as arguments but it still prompts me for the username and password to connect to the remote machine. Where am i going wrong?
[string][ValidateNotNullOrEmpty()]$credentials=$args[0]
[string][ValidateNotNullOrEmpty()]$password=$args[1]
$destination =$args[2]
$destinationHome =$args[3]
$sourcePathBat = $args[4]
$sourcePathZip = $args[5]
$command = "cmd.exe /c \\192.168.50.23\deployment\deploy-smartcheck-kiosk.bat upgrade"
$secPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$Params = New-Object System.management.automation.PSCredential($credentials, $secPassword)
Write-Host $args[0]
Write-Host $args[1]
Write-Host $args[2]
Write-Host $args[3]
Write-Host $args[4]
Write-Host $args[5]
net use $destination $secPassword /USER:$credentials
Copy-Item -Path $sourcePathBat -Destination $destinationHome;
Copy-Item -Path $sourcePathZip -Destination $destinationHome;
Write-Host "Performing remote command..."
Write-Host $command
Invoke-Command -ComputerName 192.168.50.23 -Credential $Params -ErrorAction Stop -ScriptBlock {
param($command)
Write-Host "Trying to execute remote command ($command)"
Invoke-Expression -Command: "$command"
} -ArgumentList $command
Read-Host -Prompt "Press Enter to exit..."
Updated script with a couple of changes
This is how i am currently running the script:
& '.\execute-copy-and-command - Copy.ps1' test test2 test3 test4
Any help will be appreciated.
[PSCredential] object requires password as securesctring...here $args1 should be of type System.Security.SecureString.
Enter-PSSession is used for interactive PowerShell sessions and using it in a script doesn't make sense. Whatever you kept after that will not be running in the remote machine(PS V 2), if running will be running in localmachine.
you can have a check here
Regards,
Kvprasoon

How to set an executable to run with administrator rights in powershell

I need a help
I have trouble to set a script in powershell that give DOMAIN adminsitrator rights to an User to an executable . Because I need to install a program in many desktops, plus I need to check if the program is already installed.
This seams to be easy but I know how to program in shell script not much powershell.
$SPAdmin = "DOMAIN\ADMIN"
$Password="FooBoo"|ConvertTo-SecureString -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $SPAdmin, $Password
Get-WmiObject -Class Win32_Service -ComputerName "Server" -Filter "Name='ServiceName'" -Credential $Credential
$name = "CagService"
if (Get-Service $name -ErrorAction SilentlyContinue)
{
Write-Host "O Servico do Agente conhecido como $name ja esta Instalado na Maquina com Hostname: $env:computername"
sleep 5
}
Else
{
$storageDir = $pwd
$source = "https://source"
$destination = "$storageDir\agent.exe"
Invoke-WebRequest $source -OutFile $destination
$exec = New-Object -com shell.application
$exec.shellexecute($destination);
}
Is there any reason that you can't simply do:
Start-Process powershell -Verb runAs
From a PS console? That launches a new ps window with admin privileges....
PowerShell: Running a command as Administrator

Powershell OnlyInJobError

Weird problem I saw today and I don't understand.
Is there a difference beetween running a script manually in the ISE or Pshell, and as a job?
If I run it manually the code doesn't throw an error - runs smoothly:
Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where {$_.creationtime -lt (Get-Date).AddDays(-35)} | Remove-Item -Force -Include *.conf
But if I run it via Job and let the it export the $error to a txtfile this happens:
Are the rights of my running machine different to the rights of the scheduled job?
Get-ChildItem : Zugriff verweigert
In Zeile:81 Zeichen:1
+ Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where
{$_.creati ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], UnauthorizedA
ccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Pow
erShell.Commands.GetChildItemCommand
Zugriff verweigert = Access denied
Oh, totally forgot to tell about my windows rights.
Normally the Server I am connecting to is blocked for everybody - except for login with credentials ofc. But somehow my manual powershell script is able to delete and create files?
In "job-mode" it loses it's abilities.
Edit:
Same for the Test-Path commandlet. Manually it shows me true or false. Via job it throws an error.
EDIT - SAME PROBLEM COMPLETELY DIFFERENT Commandlets:
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
This works!
This does not:
$jobname = "Test5"
$JobTrigger = New-JobTrigger -Daily -At "00:18 PM"
$MyOptions = New-ScheduledJobOption -ContinueIfGoingOnBattery -HideInTaskScheduler -RunElevated
Register-ScheduledJob -name "$jobname" -scriptblock {
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
} -trigger $JobTrigger –ScheduledJobOption $MyOptions
You probably have the job running under the SYSTEM account. Use the -Credential parameter to provide your account credentials (whatever account you're logged in with when you successfully run the command interactively).
BTW, Register-ScheduledJob uses the Task Scheduler. You can check the properties of the job in Task Scheduler to see what account it's configured to run as.
Well, it is not exactly an answere to my original question, but I was able to work around my problem by using the invoke-command and test-path from there and giving argument via the -arg.
Invoke-Command -ComputerName $FTPADRESS -ArgumentList $DIRECTORY -ScriptBlock {param ($DIR)
$check = Test-Path -Path "\\SERVER\ROOT\$DIR"
if ($check -ne $true) {New-Item -ItemType directory -Path "\\SERVER\ROOT\$DIR"}
}
Same works with the get-childitem.