Configure Windows Explorer Folder Options through Powershell - powershell

I'm looking for a way to configure a few options in Folder Option dialog of Windows Explorer through Powershell.
The options are:
Choose "Show hidden files, folders, and drives"
Uncheck "Hide extensions for known file types"
Uncheck "Hide protected operating system files (Recommended)"

Keith's answer didn't work for me out of the box. The only thing that took to the registry value modification was ShowSuperHidden. Both the Hidden (Show hidden files...) and HideFileExt (hide file extension) reverted back to their previous values as soon as I opened the View tab in Folder Settings.
Here's my solution, which I found after some trial and error (explorer.exe is automatically restarted):
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'
Set-ItemProperty $key Hidden 1
Set-ItemProperty $key HideFileExt 0
Set-ItemProperty $key ShowSuperHidden 1
Stop-Process -processname explorer
I tested this on Windows Server 2008 R2 and Windows 7.

sample windows registry (article) script:
Windows Registry Editor Version 5.00
[hkey_current_user\software\microsoft\windows\currentversion\explorer\advanced]
;hide empty drives [uncheck]
"hidedriveswithnomedia"=dword:00000000
;hide extensions for known file types [uncheck]
"hidefileext"=dword:00000000
;show hidden files, folders, and drives [check]
"showsuperhidden"=dword:00000001
;hide folder merge conflicts [uncheck]
"hidemergeconflicts"=dword:00000000
;hide protected operating system files (recommended) [uncheck]
"hidden"=dword:00000001
;use check boxes to select items [check]
"autocheckselect"=dword:00000001
save as *.reg file, and import by clicking on it and confirming the action, or through issuing the reg /import (examples) command on file.
ps: no explorer or system restart required

I believe these correspond to registry entries under reg key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced. You can use the Set-ItemProperty cmdlet to change their value e.g.:
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'
Set-ItemProperty $key ShowSuperHidden 1
There also seems to be a corresponding key for local machine (as opposed to the per user setting above): HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder.

The above registry patches are correct, but they don't fix the entire problem. Here's the script I use. It loops through ALL the users in the registry and the profiles directory (including DEFAULT, so newly-created users get them too) and sets these options for them all.
REM Changes to HKLM are not user-specific
REM Turns "hide file extensions" OFF and "show hidden files" ON.
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\HideFileExt /v DefaultValue /t REG_DWORD /d 0 /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden\SHOWALL /v DefaultValue /t REG_DWORD /d 1 /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v HideFileExt /t REG_DWORD /d 0 /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v Hidden /t REG_DWORD /d 1 /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v ShowSuperHidden /t REG_DWORD /d 1 /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v DontPrettyPath /t REG_DWORD /d 1 /f
REM Get path to "Users" dir.
echo WScript.Echo CreateObject("WScript.Shell").RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\ProfilesDirectory") >%temp%\profpath.vbs
for /f "tokens=*" %%i in ('cscript //nologo %temp%\profpath.vbs') do set ProfPath=%%i
del /q %temp%\profpath.vbs
REM Modifies registry keys in for all logged in users
REM Also modify it in the .DEFAULT hive so future users get it.
REM Also edits the registry hive for users who are not logged in
REM This section Copyright Jared Barneck
REM Modified by Ken Carlilep0 and Sam Hills
FOR /F "tokens=2* delims=\" %%a IN ('REG QUERY HKU ^|Findstr /R "DEFAULT S-1-5-[0-9]*-[0-9-]*$"') DO CALL :modkey %%a
For /d %%b in ("%ProfPath%\*") do call :modlokey "%%b"
#REM Exiting here ends the whole batch file.
EXIT /B 0
REM Modify logged-out users
:modlokey
set RegFile=%~1\ntuser.dat
REG LOAD HKU\TempHive "%RegFile%">NUL 2>&1
call :modkey TempHive
REG UNLOAD HKU\TempHive >NUL 2>&1
EXIT /B 0
REM Modifications to HKEY_USERS go here:
:modkey
REM Turns "hide file extensions" OFF and "show hidden files" ON.
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d "0" /f
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "Hidden" /t REG_DWORD /d "1" /f
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ShowSuperHidden" /t REG_DWORD /d "1" /f
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "DontPrettyPath" /t REG_DWORD /d "1" /f
REM Combine taskbar buttons only when taskbar is full
REM 0 = Always combine, hide labels, 1 = Combine when taskbar is full, 2 = Never combine
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarGlomLevel" /t REG_DWORD /d "1" /f
REM Enable this line if you use multiple monitors:
REM REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "MMTaskbarGlomLevel" /t REG_DWORD /d "1" /f
REM Don't add "- Shortcut" to new shortcuts
REG ADD "HKU\%1\Software\Microsoft\Windows\CurrentVersion\Explorer" /v "link" /t REG_BINARY /d 00000000 /f
REM Turns on "Computer" Desktop Icon
REG ADD HKU\%1\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel /v "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" /t REG_DWORD /d 0 /f
REG ADD HKU\%1\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu /v "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" /t REG_DWORD /d 0 /f
#REM Exiting here only ends this instance of the call to the
#REM :modkey label. It does not end the whole batch file.
EXIT /B 0

Updating this with a bit more info, using Powershell on Windows 10 (v1703-1809) I was able to reference and set the Folder options registry keys for both Current User and Local machine, with the following code.
The biggest realization for me, not obvious in previous posts, was that the reg key paths for folder-options-related settings are subtly different depending on whether you want to get/set Local Machine or Current User, both in key path consistency and key value access. Also, if not obvious, Current User settings will override Local Machine.
Here is a example code snippet (tested w/ PS 5.1):
## Grab Current User setting(s):
$CUfvHidden = (Get-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name 'Hidden').Hidden
$CUfvHideFileExt = (Get-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name 'HideFileExt').HideFileExt
$CUfvFullPath = (Get-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState -Name 'FullPath').FullPath
if ($CUfvHidden -eq 1) { Write-host "CU: Show Hidden set to 'ON'" } #expecting val 1 or 2
else { Write-host "CU: Show Hidden set to 'OFF'" }
if (-not $CUfvHideFileExt) { Write-host "CU: File extensions DISPLAYED" } #expecting val 1 or 0
else { Write-host "CU: File extensions hidden" }
if ($CUfvFullPath) { Write-host "CU: SHOW full path in title bar" } #expecting val 1 or 0
else { Write-host "CU: DO NOT show full path in title bar" }
## Grab Local Machine setting(s)...As you can see the LM reference paths are
## slightly different, to get 1 and 0 values, compared to CU and each other:
$LMfvHidden = (Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden\ShowAll).CheckedValue
$LMfvHideFileExt = (Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\HideFileExt).CheckedValue
$LMfvFullPath = (Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowFullPath).CheckedValue
if ($LMfvHidden) { Write-host "LM: Show Hidden set to 'ON'" } #expecting val 1 or 2
else { Write-host "LM: Show Hidden set to 'OFF'" }
if (-not $LMfvHideFileExt) { Write-host "LM: File extensions DISPLAYED" } #expecting val 1 or 0
else { Write-host "LM: File extensions hidden" }
if ($LMfvFullPath) { Write-host "LM: SHOW full path in title bar" } #expecting val 1 or 0
else { Write-host "LM: DO NOT show full path in title bar" }

Related

Mass extract Icon images from .url and .lnk files

So the goal of this project was to automate a rainmeter skin to extract icons and names from .url and .lnk files on your desktop.
(This would than be used later to display icon image as clickable shortcut in a desktop overlay).
Anyway, did a bunch of research, got stuck
First I locate the Desktop folder, which could be on another drive so...
set "DesktopFolder="
for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder set "DesktopFolder=\"
if "%DesktopFolder:~-1%" == "\" set "DesktopFolder=%DesktopFolder:~0,-1%"
if not defined DesktopFolder set "DesktopFolder=%UserProfile%\Desktop"
This appears to work.
Than I get a list of items in that directory
set "LIST="
for %%G in (%DesktopFolder%\*.url, %DesktopFolder%\*.lnk) do set LIST=!LIST! %%~nxG
This also appears to work. But appears to be one long string when echoed to a txt file. Which might be a problem.
So also tried
for /F "usebackq tokens=*" %%A in (DirContents.txt) do set LIST=!LIST! %%A
Next I need to feed that list into something else to pull the icons, save them, and name them.
set "exe_in=%LIST%"
set "out_dir=Icons"
set "out_nam=%LIST%"
set "ico_out=%out_dir%\%out_nam%.ico"
set "psCommand1="Remove-Item(\"%ico_out%\")""
set "psCommand2="[void][Reflection.Assembly]::LoadWithPartialName('System.Drawing');^
[Drawing.Icon]::ExtractAssociatedIcon(\"%DesktopFolder%\%exe_in%\").ToBitmap().Save(\"%ico_out%\")""
set "psCommand3="[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"%DesktopFolder%\%exe_in%\").FileDescription""
powershell -noprofile -noninteractive %psCommand1%
powershell -noprofile -noninteractive %psCommand2%
powershell -noprofile -noninteractive %psCommand3%
Still appears to not be able to feed them one at a time and loop until all items are processed and all icon files extracted and named.

How would I need to change my code to fit into the HKEY_USERS format instead of HKCU?

We are upgrading our Software to its 2019 version. Apparently it is a
bugger, so it has been suggested to do a clean install including deleting
some registry keys from previous versions.
We also want to save the autologins of our users so they don't need to
reset them up and we can also do something similar with new deployments.
I got some code working for what we want to do, but the problem is that
when I went to add it to our uninstall script, the uninstall script has
some different paths using HKEY_USERS vs my HKCU.
How can I modify my code to fit into our uninstall script which is using
HKEY_USERS?
Haven't tried anything other than the original code yet. Not sure where
to begin. This is my 1st attempt using powershell (or any coding really).
#Basically this is supposed to grab the users autologin key, save it,
#then after nuking the reg, put it back
$path = 'HKCU:\Software\SolidWorks\Applications\PDMWorks
Enterprise\ServerConfig\FakeVaultName'
$autologinkey = "HKCU\Software\SolidWorks\Applications\PDMWorks
Enterprise\ServerConfig\FakeVaultName"
$user=(Get-ItemProperty -Path $path -Name User).user.ToLower()
#/y forces overwriting the existing file without prompt.
if($user -ne 'fakeusername' -and $user){
reg export $autologinkey "$env:TEMP\fakekeyname.reg" /y
}
#These next steps need to be done after the uninstall/reg scrubbing
if($user -ne 'fakeusername' -and $user){
reg.exe import "$env:TEMP\fakekeyname.reg"
}
#I think this could maybe get away with just the else part instead of
#elseif + the user?
elseif($user -eq 'fakeusername' -or !$user){
reg.exe import
"\\fakecompanyname.com\Files\Public\IT\Protected\Projects\SOLIDWORKS
2019
deployment\Vault fakeusername auto login keys.reg"
}
#I need to make my code work with the following that loops through
#all the different users on the machine (not the whole code, just the
#HKEY_USERS part that I'm concerned with
# This is where you can read/modify a users portion of the registry
$unwantedDirectories += "registry::HKEY_USERS\
{0}\Software\SolidWorks" -f
$($Item.SID)
$unwantedDirectories += "registry::HKEY_USERS\{0}\Software\SRAC" -f
$($Item.SID)
$unwantedDirectories += "registry::HKEY_USERS\{0}\Software\eDrawings"
-f
$($Item.SID)
$unwantedDirectories += "registry::HKEY_USERS\{0}\Software\SOLIDWORKS
2017" -f $($Item.SID)
I don't know where to begin. My code works, but not sure how to tie it in
with the other HKEY_USERS part.
Please advise.
Edit: 7/9/2019
The script is kind of working, but it will import the reg key to the logged in user vs. the profile we want it to. Below is current working (mostly) code.
###############################################################################
#This part is ran before the reg nuke.
$autologinpath = registry::HKEY_USERS\0}\Software\SolidWorks\Applications\PDMWorks Enterprise\ServerConfig\FakeVaultName' -f $($Item)
$autologinkey = "HKU\{0}\Software\SolidWorks\Applications\PDMWorks Enterprise\ServerConfig\FakeVaultName" -f $($Item)
$autologinuser=(Get-ItemProperty -Path $autologinpath -Name User).user.ToLower()
if($autologinuser -ne 'fakeusername' -and $autologinuser){
reg export $autologinkey "$env:TEMP\fakekeyname.reg" /y
}
###############################################################################
#This part is ran after the reg nuke.
if($user -ne 'fakeusername' -and $autologinuser){
reg.exe import "$env:TEMP\fakekeyname.reg"
}
else {
reg.exe import "\\fakecompanyname.com\Files\Public\IT\Protected\Projects\SOLIDWORKS 2019 deployment\Vault fakeusername auto login keys.reg"
}
Edit: 7/9/2019 2:09pm
Thanks for the help! I think we got it. We ended up doing a manual add of the reg key values. Probably not very elegant, but seems to be working.
Else {
reg add $autologinkey /v "SettingsFromServer" /t REG_DWORD /f /d #
reg add $autologinkey /v "User" /t REG_SZ /f /d fakeusername
reg add $autologinkey /v "Config" /t REG_BINARY /f /d blahblahblahinfinity..
reg add $autologinkey /v "CacheW" /t REG_DWORD /f /d #
reg add $autologinkey /v "SinglePointLogin" /t REG_DWORD /f /d #
}

Windows / Powershell get Program Version into variable

I'm close but not there. I can get the version of my application via powershell, but it's got a bunch of text along with it.
This command:
powershell -NoLogo -NoProfile -Command ^
(get-item -Path 'c:\myapp.exe').VersionInfo ^| ^
Format-List -Force | findstr "ProductVersion" > c:\version.txt
produces (in a text file):
ProductVersion : 1.6.7.0
Is it possible via a single command in powershell to split it? I can't run ps scripts in my environment. But if I could, I would run this:
$mystr = (get-item -Path 'c:\myapp.exe').VersionInfo | Format-List -Force | findstr ProductVersion
$arr = $mystr -split ": "
$arr[1]
Is there a way to put this on a single line and put it into a environment (batch) variable?
Given your provided method, with some modification, perhaps this would do it?
#Echo Off
For /F "Delims=" %%A In ('Powershell -C^
"(GI 'C:\myapp.exe').VersionInfo.ProductVersion"') Do Set "PV=%%A"
Echo=%PV%
Pause
Mayhap
| for /f "tokens=3" %%a in ('findstr "ProductVersion"') do echo %%a>filename
or
| for /f "tokens=3" %%a in ('findstr "ProductVersion"') do set "prodver=%%a"
or
| for /f "tokens=3" %%a in ('findstr "ProductVersion"') do setx prodver "%%a"
but no guarantees. Note the setx version may establish a registry entry for future process instances, not for the current instance. /m would need to be added to make it a HKLM instead of a HKCU variable (if it works)
You can also use WMIC to get version of your application :
#echo off
Title Get File Version of any Application using WMIC
Set "Version="
Set "AppFullPath=%Windir%\notepad.exe"
Call :Get_AppName "%AppFullPath%" AppName
Call :Add_backSlash "%AppFullPath%"
Call :GetVersion %Application% Version
If defined Version (
echo Vesrion of %AppName% ==^> %Version%
)
pause>nul & Exit
::*******************************************************************
:Get_AppName <FullPath> <AppName>
Rem %1 = FullPath
Rem %2 = AppName
for %%i in (%1) do set "%2=%%~nxi"
exit /b
::*******************************************************************
:Add_backSlash <String>
Rem Subroutine to replace the simple "\" by a double "\\" into a String
Set "Application=%1"
Set "String=\"
Set "NewString=\\"
Call Set "Application=%%Application:%String%=%NewString%%%"
Exit /b
::*******************************************************************
:GetVersion <ApplicationPath> <Version>
Rem The argument %~1 represent the full path of the application
Rem without the double quotes
Rem The argument %2 represent the variable to be set (in our case %2=Version)
FOR /F "tokens=2 delims==" %%I IN (
'wmic datafile where "name='%~1'" get version /format:Textvaluelist 2^>^nul'
) DO FOR /F "delims=" %%A IN ("%%I") DO SET "%2=%%A"
Exit /b
::*******************************************************************
Just use the ProductVersion property on the VersionInfo object and assign the result to an environment variable:
$ENV:MyEnvVariable = (get-item -Path 'c:\myapp.exe').VersionInfo.ProductVersion

Replace ACLs with Inherited Defaults using PowerShell

I have a number of folders within user directories that have ended up with the wrong ACLs. I would like to find a way to use PowerShell (or a regular command prompt if that is easier) to remove the existing ACL and replace it with what it should inherit from its parent folder. The trick is that only the user that owns the folder has access to it (get-acl '.\folder' returns "Attempted to perform an unauthorized operation."). These folders all sit on a Windows Server 2003 Std system.
Try this:
#You have a textfile with FOLDER-paths
#$a = Get-Content d:\list.txt
#You have an array of FOLDER-paths
$a = #("d:\mytestfolder", "d:\my2ndtestfolder")
$a | % {
#Take ownership to admin-group
& TAKEOWN /F $_ /A /R /D Y
#Reset acl to default recursively
& ICACLS $_ /RESET /T /C
}
It turns out that this was much easier to accomplish with the regular command prompt tools. The attached script did what I needed in just a couple of lines:
#Echo Off
#Echo Taking ownership of files in %1
takeown /f %1 /r /d Y /a > :nul
#Echo Restoring default ACLs in %1
icacls %1 /reset /t /c > :nul
#Echo Restoring ownership of files to %2
subinacl /file %1 /setowner=%2 > :nul
subinacl /subdirectories %1\*.* /setowner=%2 > :nul

Batch File XCopy Command

I have a batch file which loops through a content of a text file and copies a specific file using xcopy command.
here's the snippet.
for /f %%a in (FilesToCopy.txt) do (
xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f
xcopy Common\%%a ..\..\Common\%%a /i /d /C /v /s /y /f
)
%%a contains values like
Images\image1.jpg
Images\image2.jpg
so when xcopy is executed it would look like
xcopy ..\..\Common\Images\image1.jpg Common\Images\image1.jpg /i /d /c /v /s /y
upon execute it would then prompt this message
Does Common\Images\image1.png specify a file name
or directory name on the target
(F = file, D = directory)?
it seems that the /i command doesn' work or i am missing something here to suppress the message above.
Well, you left out the second statement the help gives about /I:
/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.
You are only ever copying one file at a time, so /I doesn't apply.
You can probably hack-solving this by piping F into the command and suppressing output:
echo F|xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f >nul
(Won't work on non-English versions of Windows; but probably that's the least of your problems, given that the batch already fails for file names with spaces :-))
You could try building a single long list of file names to copy:
setlocal enabledelayedexpansion enableextensions
set LIST=
for /f %%a in (FilesToCopy.txt) do set LIST=!LIST! "..\..\Common\%%a"
xcopy %LIST% Common /i /d /c /v /s /y /f
This requires two passes over the initial file, though. And it fails when the list of file names gets longer than 8190 characters.
The destination should be a path, then it won't ask:
xcopy ..\..\Common\Images\image1.jpg Common\Images\ /i /d /c /v /s /y
In your case, you can use path extraction with %~p on the destination since you may want to preserve that:
xcopy ..\..\Common\%%a Common\%%~pa /i /d /c /v /s /y