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.
Related
Say my program is as follows
#ECHO Off
start "" "Notepad.exe"
pause
After it opens notepad the windows focus is on notepad so whatever I type is on there, but I want the focus to go back to cmd; is this possible? How?
The specific program i'm trying to run it on, is below:
#ECHO OFF
title SortV8
SETLOCAL ENABLEDELAYEDEXPANSION
cd "C:\img\Unsorted"
:SORT
FOR /R %%f IN (*.jpg *.png *.gif *.jpeg) DO (
echo Current file is: %%f
start "" "D:\Downloads\ImageGlass_Kobe_8.6.7.13_x64\ImageGlass.exe" %%f
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
CHOICE /N /C 1234 /M "PICK A NUMBER (1 (Photo), 2 (Video), or 3(Delete), 4 (Terminate Program)"%1
IF ERRORLEVEL 4 goto END
IF ERRORLEVEL 3 echo "To the trash it goes!" && move %%f "C:\img\Delete"
IF ERRORLEVEL 2 echo "Video" && move %%f "C:\img\Videos"
IF ERRORLEVEL 1 echo "Photo" && move %%f "C:\img\Photos"
taskkill /IM ImageGlass.exe
cls
GOTO SORT
)
:END
taskkill /IM ImageGlass.exe
cls
echo "Goodbye!"
pause
:eol
You can use PowerShell via its CLI to reactivate your console window, but note that the execution overhead is not insignificant.
Note: This solution is not fully robust, but may work well enough in practice:
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).SendKeys('%%{tab}')"
pause
The above simulates user input, namely an Alt-Tab keypress, in order to reactivate the current console window.
This relies on:
Notepad's window already having been activated (which is likely, given the execution overhead of calling powershell.exe)
the user not manually activating other windows while the batch file runs.
The following variant is more robust, but has a prerequisite that is unlikely to be met:
Rather than sending keystrokes, it properly tries to reactivate the current console window via its process ID.
However, this programmatic window activation only succeeds if the effective SPI_GETFOREGROUNDLOCKTIMEOUT value as reported by the SystemParametersInfo WinAPI function WinAPI function in the current OS uses session is 0, which is not the case by default.
While it is possible in principle to set this value to 0 on demand with PowerShell code, executing such code from cmd.exe (a batch file) inexplicably fails with an Access denied error (whereas direct execution of the same code works fine from PowerShell) - I haven't found a way around this (if someone has an explanation or solution, please tell us).
Certain third-party software - notably AutoHotkey - itself sets the value to 0 once it has run in a session, so if you happen to have a run-on-login AutoHotkey script (it doesn't matter what it does), the code below will work. That said, if you have AutoHotkey already installed, you could try to solve the problem at hand with a specific AutoHotkey script.
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: !! SEE LIMITATION DISCUSSED ABOVE
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "$null = (New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
pause
I am writing a Windows batch file that automatically escalates itself to administrative permissions, provided the user clicks "Yes" on the User Access Control dialog that appears.
I am using a technique I learned here to detect whether we already have admin rights and another from here to escalate. When appropriate, the following script, let's call it foo.bat, re-launches itself via a powershell-mediated call to runas:
#echo off
net session >NUL 2>NUL
if %ERRORLEVEL% NEQ 0 (
powershell start -wait -verb runas "%~dpfx0" -ArgumentList '%*'
goto :eof
)
echo Now we are running with admin rights
echo First argument is "%~1"
echo Second argument is "%~2"
pause
My problem is with escaping quotes in the -ArgumentList. The code above works fine if I call foo.bat one two from the command prompt, but not if one of the arguments contains a space, for example as in foo.bat one "two three" (where the second argument should be two words, "two three").
If I could even just get the appropriate behavior when I replace %* with static arguments:
powershell start -wait -verb runas "%~dpfx0" -ArgumentList 'one "two three"'
then I could add some lines in foo.bat that compose an appropriately-escaped substitute for %*. However, even on that static example, every escape pattern I have tried so far has either failed (I see Second argument is "two" rather than Second argument is "two three") or caused an error (typically Start-Process: A positional parameter cannot be found that accepts argument 'two'). Drawing on the docs for powershell's Start-Process I have tried all manner of ridiculous combinations of quotes, carets, doubled and tripled quotes, backticks, and commas, but there's some unholy interaction going on between batch-file quoting and powershell quoting, and nothing has worked.
Is this even possible?
You've run into a perfect storm of two quoting hells (cmd and PowerShell), garnished with a PowerShell bug (as of PowerShell Core 6.2.0).
To work around the bug, the batch file cannot be reinvoked directly and must instead be reinvoked via cmd /c.
LotPings' helpful answer, which takes that into account, typically works, but not in the following edge cases:
If the batch file's full path contains spaces (e.g., c:\path\to\my batch file.cmd)
If the arguments happen to contain any of the following cmd metacharacters (even inside "..."): & | < > ^; e.g., one "two & three"
If the reinvoked-with-admin-privileges batch file relies on executing in the same working directory it was originally called from.
The following solution addresses all these edge cases. While it is far from trivial, it should be reusable as-is:
#echo off
setlocal
:: Test whether this invocation is elevated (`net session` only works with elevation).
:: If already running elevated (as admin), continue below.
net session >NUL 2>NUL && goto :elevated
:: If not, reinvoke with elevation.
set args=%*
if defined args set args=%args:^=^^%
if defined args set args=%args:<=^<%
if defined args set args=%args:>=^>%
if defined args set args=%args:&=^&%
if defined args set args=%args:|=^|%
if defined args set "args=%args:"=\"\"%"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
" Start-Process -Wait -Verb RunAs -FilePath cmd -ArgumentList \"/c \"\" cd /d \"\"%CD%\"\" ^&^& \"\"%~f0\"\" %args% \"\" \" "
exit /b
:elevated
:: =====================================================
:: Now we are running elevated, in the same working dir., with args passed through.
:: YOUR CODE GOES HERE.
echo First argument is "%~1"
echo Second argument is "%~2"
pause
This is my batch for that purpose:
::ElevateMe.cmd::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#echo off & setlocal EnableExtensions DisableDelayedExpansion
Set "Args=%*"
net file 1>nul 2>&1 || (powershell -ex unrestricted -Command ^
Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~f0 %Args:"=\""%'
goto :eof)
:: Put code here that needs elevation
Echo:%*
Echo:%1
Echo:%2
Pause
Sample output:
one "two three"
one
"two three"
Drücken Sie eine beliebige Taste . . .
If you want the elevated cmd to stay open, use -ArgumentList '/k %~f0 %Args:"=\""%
The only approved way to elevate is to use a manifest. This emulates Unix's SUDO.EXE.
To run a command and stay elevated
RunAsAdminconsole <Command to run>
To elevate current cmd window or create a new elevated one
RunAsAdminconsole
From https://pastebin.com/KYUgEKQv
REM Three files follow
REM RunAsAdminConsole.bat
REM This file compiles RunAsAdminconsole.vb to RunAsAdminconsole.exe using the system VB.NET compiler.
REM Runs a command elevated using a manifest
C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\RunAsAdminconsole.vb" /win32manifest:"%~dp0\RunAsAdmin.manifest" /out:"%~dp0\RunAsAdminConsole.exe" /target:exe
REM To use
rem RunAsAdminconsole <Command to run>
pause
RunAsAdmin.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="Color Management"
type="win32"
/>
<description>Serenity's Editor</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
'RunAsAdminConsole.vb
'Change cmd /k to cmd /c to elevate and run command then exit elevation
imports System.Runtime.InteropServices
Public Module MyApplication
Public Sub Main ()
Dim wshshell as object
WshShell = CreateObject("WScript.Shell")
Shell("cmd /k " & Command())
End Sub
End Module
----------------------------------------
I'm currently trying to run a batch file as a startup script to detect and remove whatever version of office a user has installed and then to install Office 365. I have the install working however, when I attempted to uninstall Office 2013 I received the following error:
Input Error: Can not find script file "C:\Windows\OffScrub_O15msi.vbs"
The Offscrub file is in the same location as the script, is someone able to tell me why it's looking in C:\Windows for it?
Update
Please find my current script which now works for Office 2013, I previously added the line Remove2016Installs $true when using -Command to remove Office 2016, this worked. Since using -File to work around my initial problem I've been unable to get the script to remove Office 2016 and would like some advice on how to do this, I've read that whatever command is after -File needs to be the last which I believe might be why it's failing.
My full script is below:
start "----NOTICE----" cmd.exe /t:ec /Q /k "echo OFFICE 365 IS BEING INSTALLED. THIS WINDOW WILL CLOSE WHEN COMPLETE&&prompt $h"
#echo off
pushd "%~dp0"
powershell.exe -executionpolicy bypass -NoExit -File "Remove-PreviousOfficeInstalls.ps1"
popd
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT
if %OS%==32BIT "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\setup.exe" /configure "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\configuration-Office365-x86.xml"
if %OS%==64BIT "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\setup.exe" /configure "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\configuration-Office365-x64.xml"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ ----NOTICE----"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ Administrator: ----NOTICE----"
echo %date% %time% Setup ended with error code %errorlevel%. >> %LogLocation%\%computername%.txt
Update Finished
There's a line that calls the Powershell script Remove-PreviousOfficeInstalls, this is a file from GitHub that is very popular for the removal of whichever Office version you have installed.
I can run this command if say I copy these files to the desktop and amend the locations in the scripts, I'm not sure what this reference to C:\Windows is though when run from \domain\SYSVOL\domain\Policies{Policy Number}\Machine\Scripts\Startup\?
If you run a default instances of PowerShell it always starts in a certain directory. It depends on how and who it is started by. For instance an administrative PowerShell usually starts in C:\Windows\System32. If you use any paths that are not absolute they're applied relative to this directory.
To work around this you need to change the directory it's using. For instance by using cd to change the directory. My guess would be that your script Remove-PreviousOfficeInstalls.ps1 contains a relative call to the VBS.
An easy fix would be to run a script block instead of a single command and just cd to \\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\ prior to running the ps1.
The PowerShell help you can view by following [this] link or running powershell -h has the following information in regards to using the -Command switch.
...
Script blocks must be enclosed in braces ({}). You can specify a script block only when running PowerShell.exe in PowerShell. If you want to use a script block when running from another shell you must use the format:
"& {}"
...
The other important parameter for your use case is -File.
Runs the specified script in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session. Enter the script file path and any parameters.
...
Your batch contains the following line:
powershell.exe -executionpolicy bypass -Command "\\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\Remove-PreviousOfficeInstalls.ps1 -Remove2016Installs $true"
What you do is run a single command to invoke a script with a parameter. The problems is that said script checks its locations based on certain function and with your invocation that location is wrongly detected.
There are multiple ways to fix this. One would be to change the directory before invoking the script. To do this you'd need to use a script block as the parameter for -Command. An example for this would be:
powershell.exe -Command "& {Write-Output 'Hello'; Write-Output 'World';}"
As you can see there are two independent Write-Output commands being run. You'd change this to a cd \\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\ and the invocation of your script. As a bonus you wouldn't need to put the whole path in front of the script anymore.
The other option would be to run powershell -File with your current invocation of the script. That should also mean that the script is read from the file and the corresponding parameters are populated accordingly.
If neither of these options work you will have to check what $PSScriptRoot is being populated with and/or what the return of (Get-Item -Path ".\").FullName is as those are the two commands used to determine the location of the script that's being executed. To do this you could use a script block.
thanks for your help regarding this. My resolution was to use the following bat command:
`start "----NOTICE----" cmd.exe /t:ec /Q /k "echo OFFICE 365 IS BEING INSTALLED. THIS WINDOW WILL CLOSE WHEN COMPLETE&&prompt $h"`
#echo off
pushd "%~dp0"
powershell.exe -executionpolicy bypass -File Remove-PreviousOfficeInstalls.ps1 -Remove2016Installs
popd
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT
if %OS%==32BIT "\\Server\Folder\Folder\setup.exe" /configure "\\Server\Folder\Folder\configuration-Office365-x86.xml"
if %OS%==64BIT "\\Server\Folder\Folder\setup.exe" /configure "\\Server\Folder\Folder\configuration-Office365-x64.xml"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ ----NOTICE----"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ Administrator: ----NOTICE----"
echo %date% %time% Setup ended with error code %errorlevel%. >> %LogLocation%\%computername%.txt
I had to amend the Remove-PreviousOfficeInstalls powershell script to include the switch command:
[Parameter(ValueFromPipelineByPropertyName=$true)]
[switch]$Remove2016Installs = $false,
This then did exactly what I was after, it detected the current version of Office, removed it and installed the correct bit version of Office 365 for that PC\Laptop.
Thanks for all your help
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.
I have following PowerShell script:
cmd /c script1.bat
cmd /c script2.bat
script1.bat at the end of execution have "pause" command, so the execution of my PS script stops.
How can send any key cmd.exe to avoid stopping script execution?
NOTE: I can't change batch scripts - they are 3rd party.
You can pipe input to the program (cmd.exe) like this:
"X" | cmd /c script1.bat
You could put an empty file called pause.bat in the same directory. Then it would do nothing instead of pause.
The batch scripts may be 3rd party, but surely you can just a copy/backup and edit the content to remove the PAUSE command?
I sometimes put a PAUSE in if I am testing something and don't want the window to close, but otherwise I can't think of a good reason to keep that in.
I had trouble getting the accepted answer to work for me due having an expression in the bat file path.
"x" | $Env:WRAPPER_HOME\bat\installService.bat $LOGFILE
Error is "Expressions are only allowed as the first element of a pipeline."
Here's what I got working (finally):
[PS script code]
& runner.bat bat_to_run.bat logfile.txt
[runner.bat]
#echo OFF
REM This script can be executed from within a powershell script so that the bat file
REM passed as %1 will not cause execution to halt if PAUSE is encountered.
REM If {logfile} is included, bat file output will be appended to logfile.
REM
REM Usage:
REM runner.bat [path of bat script to execute] {logfile}
if not [%2] == [] GOTO APPEND_OUTPUT
#echo | call %1
GOTO EXIT
:APPEND_OUTPUT
#echo | call %1 1> %2 2>&1
:EXIT