Issue with pushd/popd and rebooting - powershell

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.

Related

PowerShell mask Get-ItemPropertyValue one-liner in batch file

I use PowerShell one-liners in several batch scripts, but seem failing to escape the following one correctly:
if not defined LANGUAGE (
for /f "usebackq" %%v in (`PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "(Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName').Split('-')[0]"`) do set LANGUAGE=%%v
)
I verified that it is this line that fails in my batch file. The idea behind the code is to read the value from the registry and assign the first part before the hyphen to an environment variable. So if the registry value is "de-DE", LANGUAGE shall have the value of "de".
I cannot reproduce an issue with the code you've provided.
I would however suggest you consider other approaches - compare these examples and note which executes the fastest
#Echo off
Setlocal
For /f "delims=" %%v in ('where /r "%Windir%\SysWOW64\WindowsPowerShell" powershell.exe')Do Set "powershell=%%v -nologo -noprofile"
Echo(%TIME%
For /f "usebackq" %%v in (`PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "(Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName').Split('-')[0]"`) do set "LANGUAGE=%%v"
Set LANG
Echo(%TIME%
For /f "usebackq tokens=1 Delims=-" %%G in (`
%powershell% -c "Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName'"
`)Do Set "LANGUAGE=%%G"
Set LANG
Echo(%TIME%
For /f "Skip=1 tokens=3 Delims=- " %%G in ('reg query "HKEY_CURRENT_USER\Control Panel\International" /v localename')Do Set "LANGUAGE=%%G"
Set LANG
Echo(%TIME%
Endlocal
Goto:Eof

is there a way to make batch code more compact?

I am trying to create a 1 line code which downloads files and executes them. I have tried the & and && method to run more commands one after another. but I am having a hard time trying to put the second line with the first one using &.
powershell -Command "Invoke-WebRequest https://github.com/-----/unixC/archive/main.zip -OutFile I.zip" & powershell Expand-Archive I.zip & for /f %%a IN ('dir "I\unixC-main" /b') do move "I\unixC-main\%%a" "%cd%\"
#RD /S /Q "I" & del /q /f I.zip log.txt README.md & start unixC.bat & start /b "" cmd /c del "%~f0"&exit /b
Is there any way to make this snippet of code even shorter? and more compact?
Rasil
Like others have said, the whole thing could be done in powershell. Semicolon seperates commands. -command is the default so you can leave it out. Wget is a powershell alias for invoke-webrequest.
powershell wget https://github.com/-----/unixC/archive/main.zip -OutFile I.zip; Expand-Archive I.zip
Example powershell replacement for the whole thing:
Invoke-WebRequest https://github.com/-----/unixC/archive/main.zip -OutFile I.zip
Expand-Archive I.zip
move-item i\unixC-main\* $pwd # $pwd is optional
remove-item -recurse i
remove-item -force i.zip,log.txt,readme.md
.\unixC.bat
remove-item $args[0]
Try parenthesising for /f %%a IN ('dir "I\unixC-main" /b') do move "I\unixC-main\%%a" "%cd%\" and then append the &{second line}

Batch file to be converted in powershell script

I am new on powershell, I want to convert the following batch script into powershell. The reason why I want this conversion is because this script will be run on a server from my task scheduler and due to the fact that the cmd is not working with UNC paths I think that could be a good workaround.
This script is checking if there are 20 zip files in a folder and in case they are found then starts a python script to unzip them (mandatory)
for /f %%a in ('dir /b W:\XXX\XXX\*.zip ^| find /c /v ""') do (
if /i %%a EQU 0 EXIT
if /i %%a NEQ 20 timeout /t 300 /nobreak
if /i %%a NEQ 20 Powershell.exe -executionpolicy remotesigned -File W:\XXX\XXX\powershellerrormail.ps1
if /i %%a NEQ 20 EXIT
if /i %%a EQU 20 (python W:\XXX\XXX\SSC_Unzipping.py)
pause)
EXIT

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.

Installing network printers from CSV

I wrote a script to backup a users profile to a network share. My boss wants it to backup and restore network printers too. This script includes the following line of PowerShell...
Get-WMIObject -class Win32_Printer -computer $env:computername | Select Name | Export-CSV -path '\\share\printer_export.csv'
this exports all of the printers to a CSV. The values look like this.
#TYPE Selected.System.Management.ManagementObject
Name
Snagit 10
Microsoft XPS Document Writer
\\\server\printer1
\\\server\printer2
\\\server\printer3
I wrote another script to copy the users profile from the backup to the currently logged on computer. This includes the following powershell.
$PrinterList=IMPORT-CSV \\share\printer_export.csv
FOREACH ($Printer in $PrinterList) {
Invoke-Expression 'rundll32 printui.dll PrintUIEntry /in /q /n $Printer'
}
the $Printer variable should return the value \\\server\printer1 thus installing the printers from the command line... but nothing happens. Where did I go wrong?
ALSO, how can I get it to ignore any line of the CSV that does not start with "\"?
the answer below fixed the problem.
Here is the full script. It currently backs up the users profile, signatures, taskbar icons, outlook pst, chrome bookmarks, itunes mobile backups, advanced color reg settings, desktop wallpaper, exports printers to csv
REM CLOSE OUTLOOK
cscript "\\server\outlook.vbs"
REM BACKUP USERS PROFILE
xcopy "%userprofile%" "\\server\%username%\%username%" /e /y /i
REM BACKUP SIGNATURES
xcopy "%appdata%\microsoft\signatures" "\\server\%username%\Signatures" /e /y /i
REM BACKUP PINNED TASKBAR ITEMS
xcopy "%AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar" "\\server\%username%\TaskBar" /e /y /i
REM BACKUP OUTLOOK ARCHIVES PST OUTLOOK MUST BE CLOSED
xcopy "C:\Users\%username%\AppData\Local\Microsoft\Outlook\*.pst" "\\server\%username%\Outlook" /y /i
REM BACKUP CHROME BOOKMARKS
xcopy "C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default" "\\server\%username%\Chrome" /e /y /i
REM BACKUP iTUNES MOBILE BACKUPS
xcopy "C:\Users\%username%\AppData\Roaming\Apple Computer\MobileSync" "\\server\%username%\MobileSync" /e /y /i
REM BACKUP ADVANCED COLOR SETTINGS
REG EXPORT "HKCU\Control Panel\Colors" "\\server\%username%\Wallpaper\Colors1.reg" /y
REM BACKUP ADVANCED COLOR SETTINGS
REG EXPORT "HKCU\Control Panel\Desktop\Colors" "\\server\%username%\Wallpaper\Colors2.reg" /y
REM BACKUP DESKTOP BG SETTINGS
REG EXPORT "HKCU\Control Panel\Desktop\WindowMetrics" "\\server\%username%\Wallpaper\WindowMetrics_Backup.reg" /y
REM START WALLPAPER BACKUP SCRIPT
Powershell.exe -executionpolicy remotesigned -File "wallpaper.ps1"
REM ASSIGNES VALUE OF CURRENT WALLPAPER TO A VARIABLE
$wallpaper = (Get-ItemProperty 'hkcu:\control panel\desktop\' -Name Wallpaper).Wallpaper
REM COPIES THE VARIABLE TO THE USERS BACKUP
xcopy $wallpaper "\\server\$env:username\Wallpaper\"
REM EXPORTS ALL CURRENTLY INSTALLED PRINTERS TO CSV
Get-WMIObject -class Win32_Printer -computer $env:computername | Select Name | Export-CSV -path '\\server\$env:username\printer_export.csv'
Here is the Restoration script. After I image a PC I run this script to put everything back.
REM CLOSES OUTLOOK
cscript "\\itmdtren\z$\backup scripts\outlook.vbs"
REM RESTORE USERS PROFILE DATA
xcopy "\\server\%username%\%username%" "%userprofile%" /e /y /i
REM RESTORE SIGS
xcopy "\\server\%username%\Signatures" "%appdata%\microsoft\signatures" /e /y /i
REM RESTORE TASKBAR ICONS, THIS LINE NOT USED
REM xcopy "\\server\%username%\TaskBar" "%AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar" /e /y /i
REM RETORE OUTLOOK ARCHIVES PST
xcopy "\\server\%username%\Outlook\*.pst" "C:\Users\%username%\Documents\Outlook Files" /y /i
REM RETORE CHROME BOOKMARKS AND USER DEFAULT DATA
xcopy "\\server\%username%\Chrome" "C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default" /e /y /i
REM RESTORE iTUNES BACKUPS
xcopy "\\server\%username%\MobileSync" "C:\Users\%username%\AppData\Roaming\Apple Computer\MobileSync" /e /y /i
REM RESTORE ADVANCED BACKGROUND COLOR SETTINGS
REG import "\\itmdtren\z$\backup\%username%\Wallpaper\Colors1.reg"
REG import "\\itmdtren\z$\backup\%username%\Wallpaper\Colors2.reg"
REG import "\\itmdtren\z$\backup\%username%\Wallpaper\WindowMetrics_Backup.reg"
REM RESTORE USERS WALLPAPER USING wallpaperchanger.exe found here http://sg20.com/techblog/2011/06/23/wallpaper-changer-command-line-utility/
REM launches exe from the server, points at the wallpaper folder, randomly selects image, converts to bmp and copies it to the users theme folder then sets as wallpaper
"\\server\WallpaperChanger.exe" "\\server\%username%\Wallpaper" 2 "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Themes"
Powershell.exe -executionpolicy Unrestricted -File "PRINT.ps1"
# PRINT.ps1 looks like this
$PrinterList=IMPORT-CSV \\server\$env:username\printer_export.csv
FOREACH ($Printer in $PrinterList) {
Invoke-Expression 'rundll32 printui.dll PrintUIEntry /in /q /n $($Printer.Name)'
}
REM REFRESH USER SYSTEM PARAMETERS
RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters
Both questions are pretty simple... Where you went wrong is that when you import the CSV it created an array of objects. Each object has one property, Name. When you reference that object you need to specify the property that you want to use, so you Invoke-Expression line should be:
Invoke-Expression 'rundll32 printui.dll PrintUIEntry /in /q /n $($Printer.Name)'
That will expand the name, and it should work as expected at that point. As for getting it to skip entries that don't start with "\" you can do something like:
FOREACH ($Printer in ($PrinterList | Where{$_.Name -like "\*"})) {
That only passes entries that start with a "\" into the ForEach loop.