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

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

Related

Run bat file via PowerShell

I am trying to run a batch file from remote computer but it also doesn't work locally
Invoke-Command -ComputerName $remoteComputer -ScriptBlock {
Start-Process "C:\Users\Administrator\Desktop\version\Installer\Installer.bat" -NoNewWindow -Wait
} -Credential $credentials -ErrorAction Stop
There is no errors but nothing happens
The installer.bat is located under C:\Users\Administrator\Desktop\version\Installer
The batch file contain setup.exe that also located at the same folder.
I am searching for hours the solution
For local I used this:
Start-Process "cmd.exe" "/c C:\Users\Administrator\Desktop\version\Installer\Installer.bat" -NoNewWindow
Seems that its working locally when i am going to the right folder (cd c:..)
and run
Invoke-Expression -Command 'cmd.exe /C C:\Users\Administrator\Desktop\version\Installer\Installer.bat'
So how can i do it remotely (I mean to go to the right path first)

How can I stop a program on another computer using CMD with Powershell

I want to stop Pulse Secure before uninstalling it and installing a newer version using Powershell
In CMD from a computer you can type this to stop it:
"C:\Program Files (x86)\Common Files\Pulse Secure\JamUI\Pulse.exe" -stop
But I can't seem to get it stopped from Powershell. I've tried a few different variants, but can't seem to get it.
$PC = (Read-Host "Enter Computer Name").ToUpper()
ICM $PC {& cmd.exe /c '"C:\Program Files (x86)\Common Files\Pulse Secure\JamUI\Pulse.exe" -stop'}
.
$PC = (Read-Host "Enter Computer Name").ToUpper()
$STOP = "C:\Program Files (x86)\Common Files\Pulse Secure\JamUI\Pulse.exe"
ICM $PC {& cmd.exe /c "$STOP -stop"}
The second option returns '-stop' is not recognized as an internal or external command... Any suggestions or better ways to stop it?
invoke-command -ComputerName $pc -ScriptBlock {Stop-process -name Pulse -force}
This did it.

using cmd in powershell properly

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
}

Trying to run commands remote with powershell but not luck

I'm looking for help to run commands on remote computers regarding a line with mcafee agent to get it command run remotely.
$Machines = Get-Content -Path "C:\server_list.txt"
foreach ($computer in $Machines){
Write-host "Executing Events on $computer" -b "yellow" -foregroundcolor "red"
$command = Start-Process -NoNewWindow -FilePath "C:\Program Files\McAfee\Agent\cmdagent.exe" -ArgumentList "/e /l C:\temp"
Invoke-Command -ComputerName $computer -ScriptBlock {$command}
}
When I executed this command run locally but not remotely.
I'm looking for help here I have not full experience but I'm started automating some task on my job.
Please suggest some tips
I really appreciate it
Thanks
$command = Start-Process -NoNewWindow -FilePath "C:\Program Files\McAfee\Agent\cmdagent.exe" -ArgumentList "/e /l C:\temp"
This doesn't define a command for later execution with Invoke-Command, it instantly executes the Start-Process command, which is not your intent, and it is the reason it runs locally.
To fix that, you'd have to define it as a script block ({ ... }):
$command = { Start-Proces ... }, and then pass it as-is to Invoke-Command's -ScriptBlock parameter (Invoke-Command -ComputerName $computer -ScriptBlock $command) (don't enclose it in { ... } again).
Additionally, I suggest taking advantage of Invoke-Command's ability to target multiple computers at once, in parallel, and to avoid using Start-Process for synchronous invocation of an external program in the same window.
To put it all together:
$machines = Get-Content -Path "C:\server_list.txt"
Write-host "Executing Events on the following computers: $machines" -b "yellow" -foregroundcolor "red"
# Define the command as a script block, which is a piece of PowerShell code
# you can execute on demand later.
# In it, execute cmdagent.exe *directly*, not via Start-Process.
$command = { & "C:\Program Files\McAfee\Agent\cmdagent.exe" /e /l C:\temp }
# Invoke the script block on *all* computers in parallel, with a single
# Invoke-Command call.
Invoke-Command -ComputerName $machines -ScriptBlock $command
Note the need to use &, the call operator, to invoke the cmdagent.exe executable, because its path is quoted (of necessity, due to containing spaces).
Alternatively, you can define the script block directly in the Invoke-Command call:
Invoke-Command -ComputerName $machines -ScriptBlock {
& "C:\Program Files\McAfee\Agent\cmdagent.exe" /e /l C:\temp
}
A notable pitfall when targeting remote computers is that you cannot directly reference local variables in the (remotely executing) script block, and must instead explicitly refer to them via the $using: scope; e.g., $using:someLocalVar instead of $someLocalVar - see this answer for more information.
The problem is that $command is only valid for your local session - if you try to use it in a remote session, $command is $null and does nothing. Additionally, you are actually assigning $command whatever Start-Process returns, not what you want the command to be.
Just put the command in the script block (and while you're at it you can run this on every machine with a single command without having to loop over each one synchronously):
Invoke-Command -ComputerName $Machines -ScriptBlock { Start-Process -NoNewWindow -FilePath "C:\Program Files\McAfee\Agent\cmdagent.exe" -ArgumentList "/e /l C:\temp" }

WMI Query Script as a Job

I have two scripts. One calls the other with a list of servers as parameters. The second query is designed to execute a WMI query. When I run it manually, it does this perfectly. When I try to run it as a job it hangs forever and I have to remove it.
For the sake of space here is the relevant part of the calling script:
ProcessServers.ps1
Start-Job -FilePath .\GetServerDetailsLight.ps1 -ArgumentList $sqlsrv,$destdb,$server,$instance
GetServerDetailsLight.ps1
param($sqlsrv,$destdb,$server,$instance)
$password = get-content C:\SQLPS\auth.txt | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist "DOMAIN\MYUSER",$password
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO')
$box_id = 0;
if ($sqlsrv.length -eq 0) {
write-output "No data passed"
break
}
function getinfo {
param(
[string]$svr,
[string]$inst
)
"Entered GetInfo with: $svr,$inst"
$cs = get-wmiobject win32_operatingsystem -computername $svr -credential $credentials -authentication 6 -Verbose -Debug |
select Name, Model, Manufacturer, Description, DNSHostName, Domain, DomainRole, PartOfDomain,
NumberOfProcessors, SystemType, TotalPhysicalMemory, UserName, Workgroup
write-output "WMI Results: $cs"
}
getinfo $server $instance
write-output "Complete"
Executed as a job it will show as 'running' forever:
PS C:\sqlps> Start-Job -FilePath .\GetServerDetailsLight.ps1 -ArgumentList DBSERVER,LOGDB,SERVER01,SERVER01
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
21 Job21 Running True localhost param($sqlsrv,$destdb,...
GAC Version Location
--- ------- --------
True v2.0.50727 C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.Smo\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Smo.dll
getinfo MSDCHR01 MSDCHR01
Entered GetInfo with: SERVER01,SERVER01
The last output I ever get is the 'Entered GetInfo with: SERVER01,SERVER01'. If I run it manually like so: PS C:\sqlps> .\GetServerDetailsLight.ps1 DBSERVER LOGDB SERVER01 SERVER01
The WMI query executes just as expected.
I am trying to determine why this is, or at least a useful way to trap errors from within jobs.
Thanks!
This is one instance I could find. http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/a6c816dd-2c2c-47bc-a2d0-238fbb9d66a6
There are many other discussions I have seen around the same.
Anyway, to make sure your WMI respository isn't corrupt, just try re-compiling it. Put the following lines in a batch file and run:
net stop winmgmt
c:
cd c:\windows\system32\wbem
rd /S /Q repository
regsvr32 /s %systemroot%\system32\scecli.dll
regsvr32 /s %systemroot%\system32\userenv.dll
mofcomp cimwin32.mof
mofcomp cimwin32.mfl
mofcomp rsop.mof
mofcomp rsop.mfl
for /f %%s in ('dir /b /s *.dll') do regsvr32 /s %%s
for /f %%s in ('dir /b *.mof') do mofcomp %%s
for /f %%s in ('dir /b *.mfl') do mofcomp %%s
mofcomp exwmi.mof
mofcomp -n:root\cimv2\applications\exchange wbemcons.mof
mofcomp -n:root\cimv2\applications\exchange smtpcons.mof
mofcomp exmgmt.mof
Do yourself a favor and check WinRM. If remoting is turned off, you'll experience this exact set of symptoms.
Can *.ps1 scripts run as background jobs themselves execute *.ps1 scripts?
How do I debug a PowerShell background job?
Your script worked fine for me with the write credentials, but blocked when the credentials were wrong.