Powershell command run on CMD with if condition - powershell

Example 1:
for /F "tokens=3 delims= " %%A in ('manage-bde -status %systemdrive% ^| findstr " Encryption Method:"') do (
if "%%A"=="AES" goto EncryptionCompleted
)
:EncryptionCompleted
Example 2:
for /F %%A in ('wmic /namespace:\\root\cimv2\security\microsofttpm path win32_tpm get IsEnabled_InitialValue ^| findstr "TRUE"') do (
if "%%A"=="TRUE" goto nextcheck
)
:nextcheck
Please help to find the below code as run on .bat to stop script execution.
The command is:
powershell.exe (Get-Tpm | Select -Property TpmReady).TpmReady -eq $False
then goto Failed
:Failed

Since you're only looking to act on a Boolean value, you can communicate that via the PowerShell process' exit code, with 0 corresponding to $true and 1 to $false, given that the widely observed convention is that exit code 0 signals success, whereas any nonzero exit code signals an error condition.
Boolean values in PowerShell can directly be converted to integers, which, however, performs the opposite mapping: [int] $true is 1 and [int] $false is 0.
Therefore, the logic must be reversed with -not before passing the Boolean to PowerShell's exit statement.
On the cmd.exe (batch-file) side, this allows you to act on the exit code with the || operator, which only executes the RHS in case of failure, i.e. if the LHS command reported a nonzero exit code (such as 1).
powershell.exe -noprofile -c "exit -not (Get-Tpm).TpmReady" || goto :FAILED
echo "TPM is ready."
exit /b 0
:FAILED
echo "TPM is NOT ready." >&2
exit /b 1
Note that I've added the following CLI parameters to the PowerShell call: -noprofile to potentially speed up execution, and -c (-Command) to explicitly signal that a command (piece of PowerShell code) is being passed.

A demo of doing everything in powershell.
(get-bitlockervolume $env:systemdrive).encryptionmethod
None
(get-ciminstance -namespace root\cimv2\security\microsofttpm win32_tpm).
IsEnabled_InitialValue
True
(get-tpm).TpmReady
True

Related

When running powershell in batch file facing error

I am doing some testing to run powershell script in cmd. I encountered the error when running the powershell script. Please advise how to rectify it.
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
Set "WinVerAct="
For /f "tokens=*" %%W in ('
cscript /Nologo "C:\Windows\System32\slmgr.vbs" /xpr
') Do Set "WinVerAct=!WinVerAct! %%W"
if Not defined WinVerAct (
Echo:No response from slmgr.vbs
Exit /B 1
)
Echo Windows Version Activation Status:
Echo:"%WinVerAct:~1%"
ping /n 5 localhost>nul 2>&1
Echo Check Status thru PowerShell
powershell -Command "Get-CimInstance SoftwareLicensingProduct -Filter "partialproductkey is
not null" | ? name -like windows*"
ping /n 5 localhost>nul 2>&1
wmic csproduct
ping /n 5 localhost>nul 2>&1
You're using two sets of double quotes in the powershell command calling Get-CimInstance and obviously as soon as you use the second one it closes that part rather than encompassing the whole expression.
Probably the easiest fix is to just use single quotes for the internal part:
powershell -Command "Get-CimInstance SoftwareLicensingProduct -Filter 'partialproductkey is not null' | ? name -like windows*"

Getting a variable from a powershell script, in a batch file

I have seen some similar questions on this here on stack overflow, but I cannot get any of the answers to far to work.
I have this .ps1 file that mounts a drive and echos the drive letter (expected $driverLetter = "G" || "H" || "I"):
$mountDisk = Mount-DiskImage -ImagePath $args[0] -Passthru
$driveLetter = ($mountDisk | Get-Volume).DriveLetter
echo $driveLetter
I'm running it from this batch file:
FOR /F "usebackq delims=" %%i IN (`powershell -File ./mountDisk.ps1 "%1"`) DO SET "d=%%i"
Echo %d%
Each time I get an empty variable. I've tried setting environment variables, but yield same result.
Here's how I'd probably do it, assuming that the initial path passed to the batch file is double-quoted as necessary.
#Echo Off & SetLocal EnableExtensions & Set "ISODrv="
If /I Not "%~x1" == ".iso" (Exit /B 1) Else For %%G In ("%~1") Do If "%%~aG" GEq "d" Exit /B 2
For /F %%G In ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Mount-DiskImage -ImagePath \"%~1\" -PassThru | Get-Volume).Driveletter" 2^>NUL') Do Set "ISODrv=%%G"
If Not Defined ISODrv (Exit /B 3) Else Echo %ISODrv%
Doing it this way eliminates the need for pre-creating a PowerShell script, and then any subsequent modifications to the execution policy. It only proceeds with the image mount if the received input value was an existing ISO file too. If you're running this batch file from a process which retrieves its exit code, 1 means that the input did not end with the case insensitive string .iso, 2 would mean that the input did end with the case insensitive string .iso, but it was a directory, not a file, and 3 would indicate that there was an error returning the mounted ISO image drive letter.
Try the following to run the cmd from the PowerShell and pathing their variables to it
# The command to pass to cmd.exe /cript
$var = "echo hello world & ping $ip & pause"
$ip = "192.168.1.1"
$var2 = "ping $ip & pause"
# Start the process asynchronously, in a new window,
# as the current user with elevation (administrative rights).
# Note the need to pass the arguments to cmd.exe as an *array*.
Start-Process -Verb RunAs cmd.exe -Args '/c', $var2, $var

cmd.exe throws error "& was unexpected at this time."

so my problem is that when i just ran cmd.exe in terminal, i get "& was unexpected at this time." Error at the end - looks like this
So the problem is that i'm getting erros in Unity 3D when it wants to run the unity_csc.bat file and compile solution. These errors are exactly the same as the one when i just run cmd.exe - therefore i suspect its not an Unity3D based problem (if you want you can check the Unity3D specific thread here https://forum.unity.com/threads/2-empty-errors-in-console-was-unexpected-at-this-time.799110/ )
Does anyone know why this might be happening ? This also happens when i try to run a .bat file - which I suspect is why i cant compile Unity project
I'm running Windows 10 with all of the latest updates
EDIT:
Since cmd /d does not throw the error, might there be some problem with this registry record ?
In User Folder i do have this Autorun record
#mode 20,5 & tasklist /FI "IMAGENAME eq SoundMixer.exe" 2>NUL | find /I /N "SoundMixer.exe">NUL && exit & if exist " ( start /MIN "" " & tasklist /FI "IMAGENAME eq explorer.exe" 2>NUL | find /I /N "explorer.exe">NUL && exit & explorer.exe & exit ) else ( tasklist /FI "IMAGENAME eq explorer.exe" 2>NUL | find /I /N "explorer.exe">NUL && exit & explorer.exe & exit )
Stephan has provided the crucial pointer:
It sounds like you have a broken autorun command defined for cmd.exe; that is, your registry defines a command that is automatically executed whenever you call cmd.exe, and that command causes the syntax error you're seeing.
Note that such commands are executed irrespective of whether you open an interactive cmd session or invoke via a batch file or pass a command to cmd with /C.
Passing /D to cmd bypasses any autorun commands.
There are two locations in the registry where such a command can be defined, one at the local-machine level (which applies to all users), HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor, and another for the current user only, HKEY_CURRENT_USER\Software\Microsoft\Command Processor, in a value named AutoRun.
If commands are defined in both locations, the HKEY_LOCAL_MACHINE's commands run first.
To list any defined autorun commands:
Get-ItemProperty -ea Ignore ('HKCU:', 'HKLM:' -replace '$', '\Software\Microsoft\Command Processor') AutoRun
You can use the following PowerShell snippet to remove autorun commands from both locations, but note that you'll have to run it with elevation (as administrator), if a local-machine value is present:
Get-ItemProperty -ea Ignore ('HKCU:', 'HKLM:' -replace '$', '\Software\Microsoft\Command Processor') AutoRun |
Remove-ItemProperty -Name AutoRun -WhatIf
Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf, once you're sure the operation will do what you want.

Powershell via batch file multiple statements

This code is very close to being finished, however I cannot get the last statement (psexec \\%PC% -i -d -s "\.exe) that I wish to run, to run only if the device pings.
The aim is, if a device pings then write to host that it pings and run the psexec command else write to host that it hasn't been able to ping.
Code:
#ECHO OFF
cls
Clear-Host
set /p PC=PC no?:
FOR %%i IN (
%PC%
) DO (
PowerShell -NoProfile -Command "If (Test-Connection %%i -Count 1 -Quiet) { Write-Host "%%i - successfully pinged" -F Green } (psexec \\%PC% -i -d -s "\.exe that i wish to run")
else { Write-Host "%%i FAILED" -F Red}"
)
pause
This is like Spanglish or something. Clear-Host isn't a command that cmd understands, and it'd be easier just to ping.
#echo off
setlocal
if "%~1"=="" (
set /P "PC=PC no? "
) else (
set "PC=%~1"
)
ping -n 1 %PC% | find /i "TTL=" >NUL 2>NUL && (
powershell "Write-Host '%PC% passed' -f Green"
psexec \\%PC% -i -d -s "\.exe that i wish to run"
) || (
powershell "Write-Host '%PC% failed' -f Red"
)
For what it's worth, if you don't need the output of the command that psexec runs, I generally find wmic process call create to be faster than psexec.
wmic /node:%PC% process call create "exe that you wish to run"
If you need to supply auth info, add the /user:username and /password:password switches before process call create.
There are several problems with your code above. When executing a PowerShell command within a batch script, you can't break the line very easily. You should also include your psexec command within the if code block, rather than after it as you have now. You can separate commands with your braced code block with semicolons if needed. And finally, you need to be careful mixing double quotes as part of the powershell command token with the double quotes within the command. It could be fixed so that powershell handles the conditional flow, but my solution above works just as well and is more readable I think.

Returning an error code from CMD to Powershell

I'm working on a Mssql install script and I want to get the results of a silent mssql installation. In my PowerShell script I run this command:
$result = (start cmd "/c D:\SQL2008R2\SQL2008R2\setup.exe /CONFIGURATIONFILE=sqlconfig.ini && exit 0 || exit 1")
Which should return 0 on fail and 1 on pass. Unfortunately, I don't get any output back. Any ideas?
An alternative to Start-Process is the more syntactically terse call operator &.
& cmd.exe /c 'ping.exe doesnotexist && exit 0 || exit 1'
The exit code will be contained in the built-in variable $LASTEXITCODE so:
Write-Host $LASTEXITCODE
This will contain the exit code of the program run so you don't necessary have to run it with CMD.exe you could just do:
& ping.exe doesnotexist ; Write-Host $LASTEXITCODE
Applied to your command line program:
& cmd.exe /c 'D:\SQL2008R2\SQL2008R2\setup.exe /CONFIGURATIONFILE=sqlconfig.ini && exit 0 || exit 1'
Or just:
& D:\SQL2008R2\SQL2008R2\setup.exe /CONFIGURATIONFILE=sqlconfig.ini
In both cases $LASTEXITCODE should be 0 for success, non-zero otherwise (if the external program was written correctly).
This is how you do it: start is actually an alias Start-Process, so you have to look at it's documentation, which is a lot different than cmd.exe's start. So you can do this:
(Start-Process -FilePath "cmd.exe /c ..." -Wait -Passthru).ExitCode
So easy!
Too late maybe but does this help?
start /WAIT cmd.exe /C "YOUR-COMMAND-HERE" & if errorlevel 1 echo 'error occurred'
you can also explicitly return an error code like this:
start /WAIT cmd.exe /C "YOUR-COMMAND-HERE & exit MY-ERROR-CODE" & if errorlevel 1 echo 'error occurred'