Scripting with bcdedit - command-line

After rebuilding a HDD using ImageX and a WIM, the BCD sometimes gets corrupted. I therefor need to rebuid the BCD from a script running unattended in a command prompt.
The below code does the job, when entered manually. I need help to automate it (see further below code example):
bootrec.exe /fixmbr
bootsect.exe /nt60 all /force
attrib -h -s C:\boot\BCD
del C:\boot\BCD
bcdedit.exe /createstore c:\boot\bcd.temp
bcdedit.exe /store c:\boot\bcd.temp /create {bootmgr} /d "Windows Boot Manager"
bcdedit.exe /import c:\boot\bcd.temp
bcdedit.exe /set {bootmgr} device partition=C:
bcdedit.exe /timeout 10
attrib -h -s C:\boot\bcd.temp
del c:\boot\bcd.temp
bcdedit.exe /create /d "Microsoft Windows" /application osloader
bcdedit.exe /set {GUID} device partition=C:
bcdedit.exe /set {GUID} osdevice partition=C:
bcdedit.exe /set {GUID} path \Windows\system32\winload.exe
bcdedit.exe /set {GUID} systemroot \Windows
bcdedit.exe /displayorder {GUID}
As started above, I need to run this in a unattended command prompt. The output from the 6th last statement "bcdedit.exe /create /d "Microsoft Windows" /application osloader" is a newly creates GUID. This ID is needed in the following commands.
How do I load this new GUID from bcdedit to a variable I can call in the following code?
Best Regards
Henrik V. Nielsen

If other should face the same problem, I solved it by adding the following line.
For /F "tokens=2 delims={}" %%i in ('bcdedit.exe') do (set _NEWGUID=%%i)
This works because there is only one GUID in the file.

there is an easier way.
When creating a new entry BCD accepts all GUIDs in the Form aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee (number of digits 8-4-4-4-12)
This means you can define an GUID an don´t have to search the GUID with the For-Loop.
It´s working for me.

This is a solution based on Henrik's code
This takes the GUID created from BCD into a text file and the for loop gets the GUID from the file
bootrec.exe /fixmbr
bootsect.exe /nt60 all /force
attrib -h -s C:\boot\BCD
del C:\boot\BCD
bcdedit.exe /createstore c:\boot\bcd.temp
bcdedit.exe /store c:\boot\bcd.temp /create {bootmgr} /d "Windows Boot Manager"
bcdedit.exe /import c:\boot\bcd.temp
bcdedit.exe /set {bootmgr} device partition=C:
bcdedit.exe /timeout 10
attrib -h -s C:\boot\bcd.temp
del c:\boot\bcd.temp
bcdedit.exe /create /d "Microsoft Windows" /application osloader>GUID.txt
For /F "tokens=2 delims={}" %%i in (GUID.txt) do (set _NEWGUID=%%i)
bcdedit.exe /set %_NEWGUID% device partition=C:
bcdedit.exe /set %_NEWGUID% osdevice partition=C:
bcdedit.exe /set %_NEWGUID% path \Windows\system32\winload.exe
bcdedit.exe /set %_NEWGUID% systemroot \Windows
bcdedit.exe /displayorder %_NEWGUID%

Dylan Grasha
Your answer has some errors and I have added some enhancements to make it more complete.
#Echo Off
bootrec.exe /fixmbr
bootsect.exe /nt60 C: /force
attrib -h -s C:\boot\BCD
del C:\boot\BCD
attrib -h -s C:\boot\bcd.temp >nul
del C:\boot\bcd.temp >nul
bcdedit /createstore c:\boot\bcd.temp
bcdedit.exe /store c:\boot\bcd.temp /create {bootmgr} /d "Windows Boot Manager"
bcdedit.exe /import c:\boot\bcd.temp
bcdedit.exe /set {bootmgr} device partition=C:
bcdedit.exe /timeout 10
attrib -h -s C:\boot\bcd.temp
del c:\boot\bcd.temp
bcdedit.exe /create /d "Microsoft Windows" /application osloader>GUID.txt
For /F "tokens=2 delims={}" %%i in (GUID.txt) do (set _NEWGUID=%%i)
bcdedit.exe /set {%_NEWGUID%} device partition=C:
bcdedit.exe /set {%_NEWGUID%} osdevice partition=C:
bcdedit.exe /set {%_NEWGUID%} path \Windows\system32\winload.exe
bcdedit.exe /set {%_NEWGUID%} systemroot \Windows
bcdedit.exe /displayorder {%_NEWGUID%}
del guid.txt
cmd

There is an easier way for fixing BCD.
bcdboot c:\windows
for example replaces all bcdedit commands from question.
See explanations for using bcdboot to fix BCD.
The utilities bcdboot and bootsect can fix all boot problems (regarding initial boot sequence).
sfc.exe can fix corrupted system files.

Related

Powershell start-process hidden wmplayer file with spaces

powershell Start-Process -WindowStyle Hidden 'C:\Program Files\Windows Media Player\wmplayer.exe' c:\windows\media\notify.wav
run ok.
powershell Start-Process -WindowStyle Hidden 'C:\Program Files\Windows Media Player\wmplayer.exe' c:\windows\media\windows background.wavrun bad.
powershell Start-Process -WindowStyle Hidden 'C:\Program Files\Windows Media Player\wmplayer.exe' 'c:\windows\media\windows background.wav'run bad.
powershell Start-Process -WindowStyle Hidden 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\windows\media\windows background.wav"run bad.
powershell "& 'C:\Program Files\Windows Media Player\wmplayer.exe' 'c:\windows\media\windows background.wav'" run ok but it's no hidden.
¿How fix the spaces in the arguments, please?
Do you need to do it with wmplayer.exe? The application will not be visible but it will stay loaded as a process to find in taskmanager or Get-Process. The powershell way is more in line with:
powershell (New-Object System.Media.SoundPlayer('c:\windows\media\Windows Battery Critical.wav')).PlaySync()
No visible player:
powershell (New-Object Media.SoundPlayer 'c:\windows\media\windows background.wav').PlaySync()
powershell $PLAYER = New-Object Media.SoundPlayer; $PLAYER.soundlocation='C:\windows\media\windows background.wav'; $PLAYER.PlaySync()
powershell Add-Type -AssemblyName presentationCore; $mediaPlayer = New-Object system.windows.media.mediaplayer; $mediaPlayer.open('c:\windows\media\windows background.wav'); $mediaPlayer.Play(); start-sleep 3
The sound file does not support spaces: *********************
powershell Start-Process -WindowStyle Hidden 'C:\Program Files\Windows Media Player\wmplayer.exe' c:\windows\media\notify.wav & timeout 3 >nul & taskkill /f /im wmplayer.exe>nul
Visible player:
"C:\Program Files\Windows Media Player\wmplayer.exe" "c:\windows\media\windows background.wav" & timeout 3 >nul & taskkill /f /im wmplayer.exe>nul
W10:
start "" "c:\windows\media\windows background.wav" & timeout 3 >nul & taskkill /f /im music.ui.exe>nul
start "explorer.exe shell:" "c:\windows\media\windows background.wav" & timeout 3 >nul & taskkill /f /im music.ui.exe>nul
W11:
start "" "c:\windows\media\windows background.wav" & timeout 3 >nul & taskkill /f /im microsoft.media.player.exe>nul
start "explorer.exe shell:" "c:\windows\media\windows background.wav" & timeout 3 >nul & taskkill /f /im microsoft.media.player.exe>nul

Run command If fails then run the other one if success then end

I'm trying to find a way to uninstall maya2019 from all studio workstation. We have 3 versions of maya2019 with different uninstall commands:
"C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {D4BE10F2-3E2D-4120-863A-765623D53264} /M MAYA /LANG en-us /q
"C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {77067FD9-800C-48B4-803D-569642ADABC5} /M MAYA /LANG en-us /q
"C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {1DB1AEB7-EDBD-4BB1-87DB-26C72576DA42} /M MAYA /LANG en-us /q
I need to make a script that runs the commands, if one fails then it runs the the next one down, if it succeed the it exits with complete and stops.
Right now I have this:
if "C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {D4BE10F2-3E2D-4120-863A-765623D53264} /M MAYA /LANG en-us /q; then
echo success && exit
else
if "C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {77067FD9-800C-48B4-803D-569642ADABC5} /M MAYA /LANG en-us /q; then
echo success && exit
else
if "C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe" /P {77067FD9-800C-48B4-803D-569642ADABC5} /M MAYA /LANG en-us /q; then
echo success && exit
but I'm not sure if I'm going in the right direction?
Thanks for your help
As suggested by Theo in the comments on the question, a more efficient solution would be to query the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall for uninstallation command lines based on the GUIDs in your commands.
This answer provides pointers as to how to do that.
If that is not an option, here'a PowerShell solution:
foreach ($guid in '{D4BE10F2-3E2D-4120-863A-765623D53264}',
'{77067FD9-800C-48B4-803D-569642ADABC5}',
'{1DB1AEB7-EDBD-4BB1-87DB-26C72576DA42}') {
$exe = 'C:\Program Files\Autodesk\Maya2019\Setup\Setup.exe'
$ps = Start-Process -PassThru -Wait $exe "/P $guid /M MAYA /LANG en-us /q"
if ($ps.ExitCode -eq 0) { "Success"; exit 0 }
}
Write-Warning "Uninstallation failed."
exit $ps.ExitCode
Start-Process -PassThru -Wait starts the installer process, waits for its termination, and then returns a System.Diagnostics.Process instance representing the terminated process, whose exit code (.ExitCode) can then be examined. An exit code of 0 signals success, any other value failure.

Windows 10 - How to delete temp files for network computer for each users profile

Hi I am trying to create a .bat script which deletes all the temp files in each user's profile and other temp folders
All of the computers (Windows 7, Windows 10) are networked.
Here is what I have done so far
set /P remotepc="What is the Remote PC Name? "
del \\%remotepc%\c$\Temp /S /Q /F
del \\%remotepc%\c$\Temp /S /Q /A:H
FOR /D %%p IN (\\"%remotepc%\c$\Temp\*") DO rmdir "%%p" /s /q
del \\%remotepc%\c$\Windows\Temp /S /Q /F
del \\%remotepc%\c$\Windows\Temp /S /Q /A:H
FOR /D %%p IN ("\\%remotepc%\c$\Windows\Temp\*") DO rmdir "%%p" /s /q
del \\%remotepc%\c$\Windows\Prefetch /S /Q /F
del \\%remotepc%\c$\Windows\Prefetch /S /Q /A:H
FOR /D %%p IN ("\\%remotepc%\c$\Windows\Prefetch\*") DO rmdir "%%p" /s /q
del \\%remotepc%\c$\Users\%USERNAME%\AppData\Local\Temp /S /Q /F
del \\%remotepc%\c$\Users\%USERNAME%\AppData\Local\Temp /S /Q /A:H
FOR /D %%p IN ("\\%remotepc%\c$\Users\%USERNAME%\AppData\Local\Temp\*") DO rmdir "%%p" /s /q
timeout /t 30 /nobreak
pause
In the last section %USERNAME% field only picks up the user currently logged into local machine from where the command is run.
example on Computer "Main" user is "Bravo", when I run the bat file it does this:
C:\Users\bravo\Desktop>del \\network-pc\c$\Users\bravo\AppData\Local\Temp /S /Q /F
The system cannot find the path specified.
C:\Users\sasar\Desktop>del \\network-pc\c$\Users\bravo\AppData\Local\Temp /S /Q /A:H
The system cannot find the path specified.
It runs the first three set of commands on the remote PC and clears off the Temp and Prefetch folder
My main concern is what command do I use in which I should be able to run this command from my computer which deletes all the temp files and skips any file that is in use for all the users on that networked PC.
This will save loads of time regarding doing a cleanup on each users profile one by one.
If there is a way in PowerShell please let me know how to in PS Script.

Issue with pushd/popd and rebooting

I write the following powershell, which create a bat installer for all drivers from a selected folder, and then should restart the pc.
New-Item C:\Tools\Drivers\DellLatitude3450.bat
Add-Content C:\Tools\Drivers\DellLatitude3450.bat -Value '
pushd C:\Tools\Drivers\
forfiles /p DellLatitude3450 /s /m *.inf /c "cmd /c pnputil -i -a #Path"
rmdir /s /q "C:\Tools\Drivers\DellLatitude3450"
rmdir /s /q "C:\Tools\Drivers\Elevate"
del /f "C:\Tools\Drivers\Elevate.zip"
del /f "C:\Tools\Drivers\DellLatitude3450.bat"
shutdown /r /t 15
popd
'
The bat generated is working great, except for the reboot.
I tried to do the same only creating the bat with shutdown and it works, so I'm missing something related with pushd/popd.
I tested the file creation. Had to add -ItemType 'file' to New-Item, else I got a prompt to enter type.
Main issue:
You are deleting the batch-file before the shutdown command is supposed to execute. Move the delete line down to the bottom of the batch-file code. That should then allow the shutdown command to execute as deleting the batch-file before it reaches the end, will immediately end the batch-file.
The code tested with the batch-file creation:
New-Item C:\Tools\Drivers\DellLatitude3450.bat -ItemType 'file'
Add-Content C:\Tools\Drivers\DellLatitude3450.bat -Value #'
pushd C:\Tools\Drivers\
forfiles /p DellLatitude3450 /s /m *.inf /c "cmd /c pnputil -i -a #Path"
rmdir /s /q "C:\Tools\Drivers\DellLatitude3450"
rmdir /s /q "C:\Tools\Drivers\Elevate"
del /f "C:\Tools\Drivers\Elevate.zip"
shutdown /r /t 15
popd
del /f "C:\Tools\Drivers\DellLatitude3450.bat"
'#
Note: I added here-doc syntax as mentioned at About Quoting Rules even though the single quotes alone seem to work.

How do I delete a printer driver using Powershell without the Remove-PrinterDriver cmdlet

I have a Citrix XenApp 6.5 Windows 2008 R2 server farm that does not have access to the Remove-PrinterDriver cmdlet. I want one server in the farm to monitor printer drivers on the other servers and delete bad printer drivers if found. So far I have tried the following wmi call, but I did not see a delete method in the objects returned.
Get-WmiObject -ComputerName otherServer -Class win32_printerdriver | Where-Object name -like "*PCL 5,3*"
I have also tried the following invoke expression line to try to delete a printer driver, but the driver still appears when I query printer drivers. Any help toward a solution is appreciated.
Invoke-Command -ComputerName otherServer -ScriptBlock { Invoke-Expression "rundll32 printui.dll,PrintUIEntry /dn /q /n`"HP Universal Printing PCL 5,3,Windows x64`"" }
Your second command has the wrong switches, but it should work in general. You used /dn where you should have used /dd. In general it looks like you're doing this the hard way by using Invoke-Command. You should be able to just do:
rundll32 printui.dll,PrintUIEntry /dd /c\\otherserver /m "HP Universal Printing PCL 5" /h "x64" /v 3
Here's the full usage description as shown by printui.exe /?:
Usage: rundll32 printui.dll,PrintUIEntry [options] [#commandfile]
/a[file] binary file name
/b[name] base printer name
/c[name] unc machine name if the action is on a remote machine
/dl delete local printer
/dn delete network printer connection
/dd delete printer driver
/e display printing preferences
/f[file] either inf file or output file
/F[file] location of an INF file that the INF file specified with /f may depend on
/ga add per machine printer connections (the connection will be propagated to the user upon logon)
/ge enum per machine printer connections
/gd delete per machine printer connections (the connection will be deleted upon user logon)
/h[arch] driver architecture one of the following, x86, x64 or Itanium
/ia install printer driver using inf file
/id install printer driver using add printer driver wizard
/if install printer using inf file
/ii install printer using add printer wizard with an inf file
/il install printer using add printer wizard
/in add network printer connection
/ip install printer using network printer installation wizard
/j[provider] print provider name
/k print test page to specified printer, cannot be combined with command when installing a printer
/l[path] printer driver source path
/m[model] printer driver model name
/n[name] printer name
/o display printer queue view
/p display printer properties
/q quiet mode, do not display error messages
/r[port] port name
/s display server properties
/Ss Store printer settings into a file
/Sr Restore printer settings from a file
Store or restore printer settings option flags that must be placed at the end of command:
2 PRINTER_INFO_2
7 PRINTER_INFO_7
c Color Profile
d PrinterData
s Security descriptor
g Global DevMode
m Minimal settings
u User DevMode
r Resolve name conflicts
f Force name
p Resolve port
i Driver name conflict
/u use the existing printer driver if it's already installed
/t[#] zero based index page to start on
/v[version] driver version one of the following, "Type 2 - Kernel Mode" or "Type 3 - User Mode"
/w prompt the user for a driver if specified driver is not found in the inf
/y set printer as the default
/Xg get printer settings
/Xs set printer settings
/z do not auto share this printer
/Y do not auto generate a printer name
/K changes the meaning of /h to accept 2, 3, 4 for x86, x64, or Itanium (respectively), and /v to accept 3 for "Type 3 - User Mode"
/Z share this printer, can only be used with the /if option
/? help this message
#[file] command line argument file
/Mw[message] show a warning message before committing the command
/Mq[message] show a confirmation message before committing the command
/W[flags] specifies flags and switches for the wizards (for APW & APDW)
r make the wizards to be restart-able from the last page
/G[flags] specifies global flags and switches
w suppress setup driver warnings UI (super quiet mode)
/R force selected driver to replace exisiting driver
Examples:
Run server properties:
rundll32 printui.dll,PrintUIEntry /s /t1 /c\\machine
Run printer properties:
rundll32 printui.dll,PrintUIEntry /p /n\\machine\printer
Run add printer wizard locally:
rundll32 printui.dll,PrintUIEntry /il
Run add printer wizard on \\machine:
rundll32 printui.dll,PrintUIEntry /il /c\\machine
Run queue view:
rundll32 printui.dll,PrintUIEntry /o /n\\machine\printer
Run inf install:
rundll32 printui.dll,PrintUIEntry /if /b "Test Printer" /f c:\infpath\infFile.inf /r "lpt1:" /m "Brother DCP-128C"
Run inf install (with inf dependency). In the example, prnbr002.inf depends on ntprint.inf
rundll32 printui.dll, PrintUIEntry /ia /m "Brother DCP-128C" /K /h x64 /v 3 /f "c:\infpath\prnbr002.inf" /F "c:\infpath\ntprint.inf"
Run add printer wizard using inf:
rundll32 printui.dll,PrintUIEntry /ii /f c:\infpath\infFile.inf
Add printer using inbox printer driver:
rundll32 printui.dll,PrintUIEntry /if /b "Test Printer" /r "lpt1:" /m "Brother DCP-128C"
Add per machine printer connection (the connection will be propagated to the user upon logon):
rundll32 printui.dll,PrintUIEntry /ga /c\\machine /n\\machine\printer /j"LanMan Print Services"
Delete per machine printer connection (the connection will be deleted upon user logon):
rundll32 printui.dll,PrintUIEntry /gd /c\\machine /n\\machine\printer
Enumerate per machine printer connections:
rundll32 printui.dll,PrintUIEntry /ge /c\\machine
Add printer driver using inf:
rundll32 printui.dll,PrintUIEntry /ia /c\\machine /m "Brother DCP-128C" /h "x86" /v "Type 3 - User Mode" /f c:\infpath\infFile.inf
Add printer driver using inf:
rundll32 printui.dll,PrintUIEntry /ia /K /c\\machine /m "Brother DCP-128C" /h "x86" /v 3
Add inbox printer driver:
rundll32 printui.dll,PrintUIEntry /ia /c\\machine /m "Brother DCP-128C" /h "Intel" /v "Type 3 - Kernel Mode"
Remove printer driver:
rundll32 printui.dll,PrintUIEntry /dd /c\\machine /m "Brother DCP-128C" /h "x86" /v "Type 3 - User Mode"
Remove printer driver:
rundll32 printui.dll,PrintUIEntry /dd /K /c\\machine /m "Brother DCP-128C" /h "x86" /v 3
Set printer as default:
rundll32 printui.dll,PrintUIEntry /y /n "printer"
Set printer comment:
rundll32 printui.dll,PrintUIEntry /Xs /n "printer" comment "My Cool Printer"
Get printer settings:
rundll32 printui.dll,PrintUIEntry /Xg /n "printer"
Get printer settings saving results in a file:
rundll32 printui.dll,PrintUIEntry /f "results.txt" /Xg /n "printer"
Set printer settings command usage:
rundll32 printui.dll,PrintUIEntry /Xs /n "printer" ?
Store all printer settings into a file:
rundll32 printui.dll,PrintUIEntry /Ss /n "printer" /a "file.dat"
Restore all printer settings from a file:
rundll32 printui.dll,PrintUIEntry /Sr /n "printer" /a "file.dat"
Store printer information on level 2 into a file :
rundll32 printui.dll,PrintUIEntry /Ss /n "printer" /a "file.dat" 2
Restore from a file printer security descriptor:
rundll32 printui.dll,PrintUIEntry /Sr /n "printer" /a "file.dat" s
Restore from a file printer global devmode and printer data:
rundll32 printui.dll,PrintUIEntry /Sr /n "printer" /a "file.dat" g d
Restore from a file minimum settings and resolve port name:
rundll32 printui.dll,PrintUIEntry /Sr /n "printer" /a "file.dat" m p
Enable Client Side Rendering for a printer:
rundll32 printui.dll,PrintUIEntry /Xs /n "printer" ClientSideRender enabled
Disable Client Side Rendering for a printer:
rundll32 printui.dll,PrintUIEntry /Xs /n "printer" ClientSideRender disabled
I am not sure if the WMI is the way to go for deleting printers, but you can delete wmi objects with:
$obj = Get-WmiObject -ComputerName otherServer -Class win32_printerdriver | Where-Object name -like "*PCL 5,3*"
$obj |Remove-WmiObject