Powershell command-line with Autologon.exe - powershell

Has anyone made the 'Autologon.exe for Windows v3.10' work with PowerShell v5.1?
Execution 1:
As administrator the following is run:
.\Autologon.exe -n guest10 -d test.com -p Password1 -accepteula yes
Error 1:
Execution 2:
As administrator in powershell the following is run:
.\Autologon.exe guest10 test.com Password1
Error2: Nothing happens
Execution 3:
As administrator in powershell the following is run:
$obj=.\Autologon.exe
$name ="guest10"
$domain="test"
$pass="Password1"
& $obj $name $domain $pass
Error3:
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object.

I generally use Start-Process with the ArgumentList parameter to run programs with arguments:
$autologon = "C:\folder\Autologon.exe"
$username = "guest10"
$domain = "domain"
$password = "Password1"
Start-Process $autologon -ArgumentList $username,$domain,$password
Or you can put them directly into the command:
Start-Process "C:\folder\Autologon.exe" -ArgumentList "guest10","domain","Password1"

This worked for me:
Start-Process -FilePath $exePath -ArgumentList "/accepteula", $user, $domain, $password -Wait
It's very picky about quote placement.

Related

Trying to catch the exitcode from PowerShell Invoke-command with a BAT file

I'm trying to catch the exitcode from a PowerShell script that uses a Invoke-Command to run a scriptblock on a remote machine.
First the BAT file:
The BAT file is run with a variable. The script looks like this:
powershell.exe -noninteractive -noprofile -command "& {E:\Scripts\Check-Services_XXX.ps1 %1 }"
EXIT /B %errorlevel%
The PowerShell script looks like this:
param(
[string] $ip #IP address van server
)
$username = "DOMAIN\DOMAIN_USER"
$secpasswdfile = "E:\Location\DOMAINUSER_encrypted_password.txt"
$secpasswd = Get-Content $secpasswdfile | ConvertTo-SecureString
$credentials = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$soptions = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck
Invoke-Command -ComputerName $ip -UseSSL -SessionOption $soptions -Credential $credentials -ScriptBlock `
{
# Start services
Start-Service -InputObject (Get-Service -Name IAS)
# Check services status
$checkservice = (get-service -Name IAS -ErrorAction SilentlyContinue)
if($checkservice.status -ne "Running"){$host.SetShouldExit(1)}
exit
}
The problem is that the ExitCode is not captured back, so when the BAT file ends, it ends with 0. That would be the case if everything is running. But i deliberately changed the service name in the check service section to something that does not exist for sure, but still it the BAT file ends with Exitcode 0
Done so far: Tried this solution:
catching return code of a command with "invoke-command" - Powershell 2
But didn't work: got the following error "is not equal to Open, you cannot run a command in the session. The session state is Closing"
Apparently, when it exited with a error, the session was closed, thus couldn't get the exitcode
Also tried this one: Capture Write-Host output and exit code from Invoke-Command on a Remote System
But also the same result; no correct exitcode (expected 1 instead of 0 in the BAT file)
SOLUTION!
Thanks to #js2010 and #mklement0 ; it works now like a charm!
This is the BAT file:
powershell.exe -noprofile -File "E:\Scripts\Check-Services_XXX.ps1" "%1" "%2"
EXIT /B %errorlevel%
And here is the PowerShell code that eventually worked out for me:
param(
[string] $ip, #IP address of checked server
[string] $service ) #Service name
$username = "DOMAIN\USER"
$secpasswdfile = "E:\Scripts\Credentials\DOMAIN-USER_encrypted_password.txt"
$secpasswd = Get-Content $secpasswdfile | ConvertTo-SecureString
$credentials = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$soptions = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck
$session = New-PSSession -ComputerName $ip -UseSSL -SessionOption $soptions -Credential $credentials
# Start services
Invoke-Command -Session $session -ScriptBlock { Start-Service -Name $using:service }
# Check services status
$checkservice = Invoke-Command -Session $session { Get-Service -name $using:service | where status -eq running }
if (! $checkservice) {
write-output ("Error 1, Service '" + $service + "' not running or not found.")
exit 1
}
I had some issues with passing variables to remote commands, this link helped me out (https://powershellexplained.com/2016-08-28-PowerShell-variables-to-remote-commands/)
You would have to run the exit command outside of invoke-command.
# check-service.ps1
$result = invoke-command localhost { get-service appxsvc |
where status -eq running }
if (! $result) {
exit 1
}
Change your invocation of powershell.exe to use the -File CLI parameter:
powershell.exe -NoProfile -File "E:\Scripts\Check-Services_XXX.ps1" "%1"
EXIT /B %errorlevel%
That way, the .ps1 script's exit code is properly relayed as powershell.exe's exit code.
Additionally, as js2010's answer notes, you'll need to use your $host.SetShouldExit(1) call out of the Invoke-Command script block, given that the latter executes remotely. For the reasons explained below, exit 1 is preferable.
Generally speaking:
There's no reason to use the -Command (-c) CLI parameter with "& { ... }" in order to invoke code - just use "..." directly. Older versions of the CLI documentation erroneously suggested that & { ... } is required, but this has since been corrected.
Not only is "& { ... }" unnecessary, it invariably resets the exit code to 0.
As for your use of $host.SetShouldExit(1) to request exiting with an exit code of 1 (leaving aside that in a remote call it isn't effective):
It generally isn't designed to be called from user code, as explained in this answer.
For general information about exit codes in PowerShell, see this answer.

Powershell: Start-Process doesn't pass arguments to cmd.exe

These are the commands run in a powershell console (Windows 10):
$username = 'Username'
$password = 'Password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process powershell.exe -Credential $credential -WindowStyle Hidden -ArgumentList "Start-Process cmd.exe -Verb RunAs -ArgumentList 'value'"
These commands work fine except that once you open cmd.exe as administrator via another user, by running this command:
echo %1
It gives me back:
%1
Literally. Instead I expect:
value
What am I doing wrong?
I just answered a question where the solution can be found using the script I provided there, with a few modifications, and invoking the chain of commands in a particular way:
RunAsProxy.ps1
# First arg should be the script path
$script = $args[0]
# Rest of args should be any script parameters
$scriptArgs = $args[1..$args.Count] -join ' '
$startProcessArgs = #{
Wait = $true
Verb = 'RunAs'
FilePath = 'cmd.exe'
ArgumentList = "/c ""$script"" $scriptArgs"
}
Start-Process #startProcessArgs
exit $LASTEXITCODE
Then call RunAsProxy.ps1 as follows as the user you want to run as, then elevate:
$command = "Command_you_want_to_run_from_cmd.exe"
$arguments = "any arguments to the program"
Start-Process -Cred $credential powershell.exe "-File ./RunAsProxy.ps1 $command $arguments"
The way this works is pretty much what you attempted, but using a pre-defined script to handle the elevation. But as you discovered you cannot call -Credential and -Verb in the same invocation on Start-Process. So this works more easily than defining the code in-line:
Run RunAsProxy.ps1 as the target user
RunAsProxy.ps1 will run cmd.exe with the provided arguments and elevate the process.
Note that if RunAsProxy.ps1 is not in the current directory you would need to provide the relative or full path to it.

Issues with colon (:) in when next to variable in PowerShell

I am trying to get the following to work so I can automate some SCP uploads I need to do. I believe the problem is how ${user}#${device} is being interpreted.
$user = "user1"
$device = "server1"
Start-Process 'C:\Program Files\PuTTY\pscp.exe' `
-ArgumentList ("c:\temp\myfile.txt ${user}#${device}:/shared/tmp/") -NoNewWindow
I've tried $user#$device (powershell barks about syntax), $user#${device}and ${user}#${device} (these tell me you can't copy from local to local which indicates in is not parsing the :/shared/tmp/ correctly.)
You can also escape the : with `:
"c:\temp\myfile.txt ${user}#${device}`:/shared/tmp/"
As always, unless you have a specific reason for using Start-Process: don't bother. Use the call operator (&) instead.
This worked perfectly fine when I just tested it:
$user = 'user1'
$device = 'server1'
$params = 'c:\temp\myfile.txt', "${user}#${device}:/shared/tmp/"
& 'C:\Program Files\PuTTY\pscp.exe' #params
Try this:
$user = "user1"
$device = "server1"
Start-Process 'C:\Program Files\PuTTY\pscp.exe' `
-ArgumentList ("c:\temp\myfile.txt {$($user)}#{$($device)}:/shared/tmp/") -NoNewWindow
try this:
$user = "user1"
$device = "server1"
$Program='C:\Program Files\PuTTY\pscp.exe'
$Arguments="c:\temp\myfile.txt {0}#{1}:/shared/tmp/ -NoNewWindow" -f $user, $device
Start-Process $Program $Arguments

Start-Process cannot execute psexec.exe

I have working script that use Invoke-Expression to execute psexec in Powershell ISE
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$enable_command = "D:\PSTools\PsExec.exe $comp -u Administrator -p $str -accepteula powershell.exe c:\share\ps_enable.ps1"
Invoke-Expression $enable_command
I don't want to use Invoke-Expression because it outputs data, including PLAINTEXT password onto Powershell ISE console. But this script with Start-Process doesn't work
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
Start-Process -FilePath D:\PSTools\PsExec.exe -ArgumentList '$comp', '-u', 'Administrator', '-p', '$str', '-accepteula', 'powershell.exe', 'c:\share\ps_enable.ps1'
How to fix?
How about just capturing the Invoke-Expression in a variable, or piping it to Out-Null?
$CmdOutput = Invoke-Expression $enable_command
or
Invoke-Expression $enable_command | Out-Null
Edit: Ok, I forgot that PSExec likes to use StdErr as a method for displaying some of it's text, and that portion would not be captured by these. What you can do is redirect StdErr to StdOut, and either pipe to Out-Null or capture it as suggested. Try this:
$CmdOutput = Invoke-Expression $enable_command 2>&1

PSExec never completes when run inside start-job

I'm trying to execute a cmd file on a list of 48 computers. I don't want to execute and wait for completion sequentially because each cmd takes about 10 minutes to complete. WinRM isn't an option. Neither is WMI. PSExec is an option....but I can't seem to make it work inside of Start-Job.
I'm doing something like:
$sb = {
param
(
$computer = "serverw01",
$userid = "domain2\serviceid",
$password = 'servicepw',
$command = "cd /d d:\ && updateAll.cmd"
)
d:\eps\pstools\PsExec.exe -u $userid -p $password "\\$($computer)" cmd /c $command
}
foreach ($computer in Get-Content "D:\Data\serverlist.txt") {
Start-Job $sb -ArgumentList $computer
}
This creates a bunch of jobs....but the never complete and if I Receive-Job on any of them i get back
PS> get-job | receive-job -Keep
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com
it executes just fine if I run the function like:
& $sb -computer "serverw01"
Initiating script is run in Powershell v2.0 on Server 2008r2 box
I've tried it on a box in domain2 while logged in with a domain admin userid (same result).
Try this for the psexec command, ensuring you include "-d" to not wait for response, and put the computer variable right after psexec:
d:\eps\pstools\psexec "\\$($computer)" /accepteula -u $userid -p $password -d cmd /c $command
This hanging issue occurs on Win2003 and Win2008 servers.
Most people solve this issue with a workaround like echoing and piping so that powershell gets some input from STDIN.
But there exists a solution within powershell. Just start powershell with the option -inputformat none like:
powershell -inputformat none -command ...
please try the -accepteula parameter to psexec
like
d:\eps\pstools\PsExec.exe -accepteula -u $userid -p $password
from
$computerList = Get-Content "D:\Data\serverlist.txt"
$sb =
{
param($name)
}
$computer = $name
$userid = "domain2\serviceid"
$password = 'servicepw'
$command = "cd /d d:\ && updateAll.cmd"
d:\eps\pstools\PsExec.exe -u $userid -p $password \\$computer cmd /c $command
{
}
foreach ($computer in $computerLinst) {
Start-Job $sb -ArgumentList $computer
}