using cmd in powershell properly - powershell

at the moment i install a programm to a remote machine with batch. thats already working fine.
but how can i use or "convert" the batch command below in powershell using the specific command for the prgramm to install it silent on the remote machine?
this is my batch code.
set /p target=hostname
echo.
copy /z "\\server1\tool.exe" "\\%target%\C$\temp"
echo.
PsExec.exe \\%target% cmd /c "\\%target%\C$\temp\tool.exe" /verysilent

$target=hostname
Copy-Item -Path "\\server1\tool.exe" -Destination "\\$target\C$\temp"
Invoke-Command -ScriptBlock \\%target%\C$\temp\tool.exe -ComputerName $target -credential (USERNAME)
for the Invoke-Command -Scriptblock is the command you want to run, -ComputerName is the computer you want to start a process on, -Credential is the username to use to run the command. You will automatically be prompted to enter your password.

Thanky guys for your answers.
i did like that
$target = Read-Host "hostname"
Copy-Item -Path "\\server1\tool.exe" -Destination "\\$target\C$\temp"
PsExec.exe \\$target -s winrm.cmd quickconfig -q
Invoke-Command -ComputerName $target -ScriptBlock {
cmd /c "C:\temp\tool.exe" /verysilent
}

Related

Powershell remote execution of Oracle installer Silent from unc

Meanwhile I've read and tried so many options and none of them worked for me.
I need to run a command on a remote machine that will install an application.
The setup.exe is an Oracle installer and is able to accept silent parameters.
"\\SVR1\Share\remote application Install\install\Setup.exe" -silent -force -nowait -waitforcompletion PACKAGE_NAME=abcde INSTALL_MODE=Typical ORACLE_HOME=C:\some_dir ORACLE_HOME_NAME=some_dir_Client1 APP_USER=itsmeagain APP_PASSWORD=surexxx
When I paste this command in a cmd it works as expected
When I put this in a ps1 script and run it, it works too:
cmd /c "\\SVR1\Share\remote application Install\install\Setup.exe" -silent -force -nowait -waitforcompletion PACKAGE_NAME=abcde INSTALL_MODE=Typical ORACLE_HOME=C:\some_dir ORACLE_HOME_NAME=some_dir_Client1 APP_USER=itsmeagain APP_PASSWORD=surexxx
However trying to run this 1 line script from a remote computer, it fails with: [Start-Process], InvalidOperationException
$svr="mach1"
$cmdFile="install.ps1"
$RemDir = "\\${svr}\C$\All_files\Scripts\"
$fn = "${RemDir}\${cmdFile}"
$password = ConvertTo-SecureString "${pazwd}" -AsPlainText -Force
# can't change the remote dir without spaces
"cmd /c `"\\SVR1\Share\remote application Install\install\Setup.exe`" -silent -force -nowait -waitforcompletion PACKAGE_NAME=abcde INSTALL_MODE=Typical ORACLE_HOME=C:\some_dir ORACLE_HOME_NAME=some_dir_Client1 APP_USER=itsmeagain APP_PASSWORD=surexxx " | Out-File -FilePath $fn
$cred = New-Object System.Management.Automation.PSCredential($user,$password)
$sb = { Start-Process -FilePath "${LocalDir}\${cmdFile}" }
Invoke-Command -ComputerName $svr -Credential $cred -ScriptBlock $sb
Suggestions? what Am I doing wrong here?

Accessing cmd remotely using PowerShell

I need to run a couple of bcdedit commands on a remote computer's cmd using a PowerShell script that runs on my computer. I am able to create a PSSession but I'm not sure how I can run cmd on the remote computer. When I run the code in the 'Invoke-Command' line, I get an error Connection to remote server failed with the following error message: Access is denied. When I just run Invoke-Command, I am prompted to enter the ScriptBlock, but when I do, I get yet another error: "Cannot bind parameter 'ScriptBlock' Cannot convert the "cmd /c 'bcdedit /copy {current} /d "Description"'} value of type System.String to type System.Management.Automation.ScriptBlock
I have never worked with PowerShell before. I need to do this in a couple of hours, and I am absolutely clueless right now.
Enable-PSRemoting -Force
Set-Item WSMan:\localhost\Client\TrustedHosts $ip -Concatenate -Force
$session = New-PSSession -ComputerName $ip -Credential $cred -ConfigurationName $config -UseSSL -SessionOption $sessopt
#problematic code
Invoke-Command -ComputerName $ip -ScriptBlock {cmd /c 'bcdedit /copy {current} /d "Description"'}
#works fine
Restart-Computer -ComputerName $ip -Force
ping.exe -t $ipaddr | Foreach{"{0}-{1}" -f (Get-Date -f "yyyy/MM/dd HH:mm:ss"), $_}
Assume that $ip, $ipaddr, $config, $sessopt and $cred store valid parameters.
You can run bcedit.exe directly in PowerShell, but because in PowerShell { and } are metacharacters, you need to quote identifiers such as {current}:
bcdedit /copy '{current}' /d 'Description'
See this answer for a discussion and list of PowerShell's metacharacters.
If you get an error on connecting to a remote computer, the implication is that your user account either doesn't have sufficient privileges to connect remotely or the target computer isn't set up for PowerShell remoting.
Note that Enable-PSRemoting -Force must be run on the target (server) machine, not on the calling (client) machine.
See the conceptual about_Remote_Troubleshooting topic.
The Restart-Computer cmdlet's -ComputerName parameter does not use PowerShell remoting, so the fact that it succeeds does not imply that PowerShell remoting, such as via Invoke-Command, works.
When I just run Invoke -Command, I am prompted to enter the ScriptBlock
PowerShell's automatic prompting feature for mandatory parameter values that weren't specified on the command line has severe limitations, and not being able to prompt for a script-block parameter value is one of them - see GitHub issue #4068; however, this additional problem is incidental to your real problem.
Thanks for all the suggestions, I was able to fix the error by adding -Credential to the Invoke-Command and Restart-Computer commands:
#problematic code
Invoke-Command -ComputerName $ip -Credential $cred -ScriptBlock {cmd /c 'bcdedit /copy {current} /d "Description"'}
Restart-Computer -ComputerName $ip -Credential $cred -Force

Power shell Invoke remote script is not working

I am trying to invoke a remote bat file from my local machine that should start and run the bat in a remote machine terminal. My script is able to connect and show me the output. However, it is invoking the remote bat file but waiting on my screen with bat file output. and my idea is the bat file should invoke and running in the remote machine rather than showing the output on my terminal local terminal. What should be the way here?
loop{
Invoke-Command -ComputerName $computer -credential $cred -ErrorAction Stop -ScriptBlock { Invoke-Expression -Command:"cmd.exe /c 'C:\apacheserver.bat'" }
}
From what I understand you want the .bat file to not show you the result. If so, you should do it with the Out-Null or by redirecting STDOUT and STDERR to NULL.
IE: Invoke-Expression -Command:"cmd.exe /c 'C:\apacheserver.bat'" | Out-Null
If I'm understanding correctly, you want to suppress the output from the .bat file inside your local console? If so, redirecting to some form of $null is the way to go. You also shouldn't need Invoke-Expression as Invoke-Command can run the file directly:
Invoke-Command -ComputerName $computer -Credential $cred -ErrorAction Stop -Scriptblock {
cmd.exe /c 'C:\apacheserver.bat' | Out-Null
}
You could also use > $null instead of Out-Null if you prefer.
If you want to redirect the output of the Invoke-Command call to the remote console instead, that kind of defeats the purpose of the cmdlet. You could try redirecting the console output to a file on the remote computer if you want a local record:
$remoteFile = '\\server\C$\Path\To\Output.txt'
Invoke-Command -ComputerName $computer -Credential $cred -ErrorAction Stop -Scriptblock {
cmd.exe /c 'C:\apacheserver.bat' > $remoteFile
}
If I understand you, you want to run the script in the background and not wait for it:
Invoke-Command $computer -Credential $cred { start-process C:\apacheserver.bat }

Using PSRemoting to Install Dell Updates using dcu-cli.exe

First, this is not the same question as this question.
I am trying to use PSRemoting to run dcu-cli.exe on a remote system first to gather the version number and later to actually install the updates. PSEXEC is not an option for me. The version of dcu-cli.exe I am using is 3.1. For right now I just want to capture the output of the /version parameter.
Running the following command from PowerShell on my local machine produces the following output:
& "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" /version
Output:
Version information displayed: Dell Command | Update v3.1 Program exited with return code: 0
Here is what I've tried so far. Unless otherwise specified, the output is as follows. Sometimes the output is in a log file (depending on the command line):
An unexpected fatal error occurredProgram exited with return code: 2
From watching Process Explorer, it is actually running, but something somewhere is going wrong and I'm baffled as to what. Explicit credentials are not supplied as I am running the script as an administrator account and that account exists and is an administrator on the remote machine.
Any help would be appreciated.
Attempts:
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock {& "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" /version}
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock {& cmd.exe /c '"C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" /version'}
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock {& cmd.exe /c 'start "" /Wait "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" /version'}
No output
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock {& cmd.exe /c 'start "" /B /Wait "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" /version'}
$ScriptBlock={Start-Process -FilePath "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" -ArgumentList "/version" -Wait -Verb "RunAs"}
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock $ScriptBlock
No output
$ScriptBlock={Start-Process -FilePath "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" -ArgumentList "/version" -Wait -RedirectStandardOutput C:\temp\version.log}
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock $ScriptBlock
$ScriptBlock={Start-Process -FilePath "C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe" -ArgumentList "/version" -Wait -PassThru -RedirectStandardOutput C:\temp\version.log}
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock $ScriptBlock
Process information is returned in addition to the normal erroneous output.
$ScriptText=#'
$ProcessInfo=[System.Diagnostics.ProcessStartInfo]::new("C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe")
$ProcessInfo.RedirectStandardError=$true
$ProcessInfo.RedirectStandardOutput=$true
$ProcessInfo.UseShellExecute=$false
$ProcessInfo.Arguments="/version"
$Process=[System.Diagnostics.Process]::new()
$Process.StartInfo=$ProcessInfo
$Process.Start() > $null
$Version=$Process.StandardOutput.ReadToEnd()
$Process.WaitForExit()
$Version
'#
$ScriptBlock=[System.Management.Automation.ScriptBlock]::Create($ScriptText)
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock $ScriptBlock
$ScriptText=#'
$ProcessInfo=[System.Diagnostics.ProcessStartInfo]::new("C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe")
$ProcessInfo.RedirectStandardError=$true
$ProcessInfo.RedirectStandardOutput=$true
$ProcessInfo.UseShellExecute=$false
$ProcessInfo.Arguments="/version"
$ProcessInfo.Verb="RunAs"
$Process=[System.Diagnostics.Process]::new()
$Process.StartInfo=$ProcessInfo
$Process.Start() > $null
$Version=$Process.StandardOutput.ReadToEnd()
$Process.WaitForExit()
$Version
'#
$ScriptBlock=[System.Management.Automation.ScriptBlock]::Create($ScriptText)
Invoke-Command -ComputerName $Destinations[0] -EnableNetworkAccess -ScriptBlock $ScriptBlock
(late answer... I know...)
You can run dcu-cli.exe remotely using either powershell or psexec
Powershell
the problem I had was figuring out how to pass "/applyUpdates" to dcu-cli instead of having it interpreted by powershell
Breaking the dcu-cli invocation into two separate steps works (cd ..., then .\dcu-cli)
I am logged in to my workstation as a user with local admin rights on the remote computer.
$pcname="ss-frontdesk"
$exePath="\program files\dell\commandupdate"
invoke-command -computername $pcname {cd "$using:exePath"; .\dcu-cli /applyUpdates -reboot=enable}
 
PSEXEC
now being blocked by sophos endpoint -- hence my research into powershell...
again, my local windows user is an admin on the remote workstation
set pcname=ss-frontdesk
set EXE=dcu-cli.exe
set DIR=C:\Program Files\Dell\CommandUpdate
set ARGS=/applyUpdates -reboot=enable
psexec \\%pcname% -s "%DIR%\%EXE%" %ARGS%
 
Notes
I've been using a batch file w/ psexec to update the bios on my dell workstations for 2 - 3 years
about 15% of the time, the bios will not update using dcu-cli. Sometimes it can then be updated by running Dell Command|Update manually over RDP, sometimes that doesn't work but running Dell Command|Update directly on the system works, and sometimes that doesn't work and I have to update the bios from a USB drive
You can get the bios version (if that's all you're looking for) using:
set pcname=ss-frontdesk
wmic /node:"%pcname%" bios get smbiosbiosversion |findstr /v "SMBIOSBIOSVersion" |findstr /r /v "^$"
wmic needs quotes around %pcname% if the name contains a dash as in the example
The "findstr" commands eliminate everything from the output except the bios version
Some of my systems have dcu-cli in "\Program Files (x86)" instead of in "\Program Files"...
[edit]
You can also use "sigcheck" from sysinternals to check the version of Dell Command|Update on remote systems if you have SMB access to C:\
#echo off
: F:\software\sysinternals contains sigcheck.exe...
set PATH=F:\software\sysinternals;%PATH%
setlocal enabledelayedexpansion
set PATHTOCHECK32=Program Files (x86)\Dell\CommandUpdate
set PATHTOCHECK64=Program Files\Dell\CommandUpdate
set FILETOCHECK=dcu-cli.exe
: Loop through all pc names included on the command line...
:start
if "%1"=="" goto :eof
call :checkit %1
shift
goto :start
:checkit
: note: PCNAME ends in 20 spaces (plus "x") for output formatting
ping -n 1 -w 1 %1 >nul 2>&1
if ERRORLEVEL 1 goto :noping
if exist "\\%1\c$\!PATHTOCHECK64!\!FILETOCHECK!" (
set PCNAME=%1 x
echo |set /p=!PCNAME:~0,20!
sigcheck -nobanner -n "\\%1\c$\!PATHTOCHECK64!\!FILETOCHECK!"
goto :eof
)
if exist "\\%1\c$\!PATHTOCHECK32!\!FILETOCHECK!" (
set PCNAME=%1 ^(x86^) x
echo |set /p=!PCNAME:~0,20!
sigcheck -nobanner -n "\\%1\c$\!PATHTOCHECK32!\!FILETOCHECK!"
goto :eof
)
set PCNAME=%1 x
echo |set /p=!PCNAME:~0,20!
echo dcu-cli.exe not found
goto :eof
:noping
set PCNAME=%1 x
echo |set /p=!PCNAME:~0,20!
echo not responding to PING
goto :eof
:eof

How to run command on list and have PsExec or Powershell automatically jump to the next item on this list

I have a list of computers in 'computers.txt'.
I am trying to run an .exe on each remote computer name in a list. I have to execute a .ps1 script on each computer that installs the .exe properly. In PsExec, I have to press enter after a minute or 2 in between each computer name. This will go through the list of remote computers and run an .exe that is on each computer.
In PowerShell, only the first computer runs the .exe and the rest don't do anything.
Is there any way to go through the list without having to press Enter between computer name when the script is running? I want it all to run automatically.
Here is what I am using in PsExec.
psexec -s #C:\App\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\SpeedInstall.ps1""
Here is what I am trying in PowerShell
$a = Get-Content "C:\App\computers.txt"
foreach($line in $a) {
psexec -s \\$line cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file C:\SpeedInstall.ps1"
}
You can use the /d switch with PSExec to make it not wait for the previous command to finish before moving on to the next one. There is a tradeoff in that you don't get to see any error messages that the command may generate, but it allows you to get through your list much much more quickly. Your command will look like this:
$a = Get-Content "C:\App\computers.txt"
foreach($line in $a) {
psexec -s -d \\$line cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file C:\SpeedInstall.ps1"
}
Why do you even want to use psexec? How about PSRemoting?
$Computers = Get-Content -Path C:\computers.txt
foreach ($Computer in $Computers) {
Copy-Item -Path C:\install.exe -Destination \\$Computer\c$\Windows\Temp\install.exe
}
$Script =
#"
# Write down your installation script here
& C:\install.exe /silent
Set-ItemProperty -Path HKLM:\SOFTWARE\Install -Name Setting -Value 1 -Type DWord
"#
$ScriptBlock = [Scriptblock]::Create($Script)
$PSSession = New-PSSession -ComputerName $Computers -SessionOption (New-PSSessionOption -NoMachineProfile)
Invoke-Command -Session $PSSession -ScriptBlock $ScriptBlock