explorer command doesn't work in pwsh / Windows Powershell after upgrade to Windows 11 - windows

In situations where I need to quickly switch from Powershell to the Windows Explorer, I used to be able to launch Windows Explorer from whatever directory I happened to be in, like this:
PS > explorer .
(This is really just calling C:\Windows\explorer.exe.)
It worked fine until upgrading to Windows 11. Now it silently fails to do anything.
I've confirmed that, even while using the new Terminal app, the command still works in the Command Prompt. And in pwsh, the explorer alias is still pointing at C:\Windows\explorer.exe.
So why is it now broken in Powershell? And is there any work-around?
PS: I have confirmed that the following do not work either:
PS > & explorer . # Nothing
PS > C:\Windows\explorer.exe . # Nada
PS > & C:\Windows\explorer.exe . # Zilch

This is just a workaround, but as you confirmed it working, I'll turn it into an answer:
$shell = New-Object -ComObject Shell.Application
$shell.Open( $PWD.ProviderPath )
# Also works:
# $shell.Explore( $PWD.ProviderPath )
Create an instance of the Shell COM object and then call its methods Open or Explore to open the current directory, obtained from automatic variable $PWD, in Explorer.
As mklement0 points out, we have to use $PWD.ProviderPath as $PWD.Path may be based on a PowerShell-only drive, which external programs such as File Explorer don't know about.
You might also want to check the type of the provider to make sure you call the above code only for filesystem paths:
# As a demonstration, let $PWD point to a registry location
Set-Location HKCU:\Software
# The following if branch won't be entered
if( $PWD.Provider.Name -eq 'FileSystem' ) { ... }

Related

Powershell 5.1 launches any console command on new console window

I have quite strange behavior happening on my powershell code. I pinned it down to these simple reproduceable steps.
Launch Powershell as Administrator.
Type cmd and confirm it opens cmd on the current Powershell terminal. Type exit to get out of the cmd console.
Run the following code:
Import-Module WebAdministration
cd iis:\apppools
new-item c:\temp\1 -itemType directory
Push-Location
cd c:\temp\1
Pop-Location
remove-item c:\temp\1
Type cmd and now you see it opens cmd on a new window.
Run cd c:\
Type cmd and now you see it opens cmd on a current window as expected.
Run cd iis:\apppools, and then cmd, and you see it opens on a current window as expected.
Why did #4 open in new window, and then why does cd c:\ fix the problem?
The real problem that I am dealing with is that when the console gets into the state of step #4, it launches any console command in a new window, so while I would expect the script to wait until the console command is finished, it launches the console command in a new window and move on to the next line without waiting for the console to finish.
Reproduceable on Powershell 5.1.14393.4350 (Windows 2016), 5.1.18362.1171 (Windows 10) and 5.1.19041.906 (Windows 10).
#Daniel's comment had the answer, and I am writing it here to comply with StackOverflow's rule:
When calling cmd from powershell, it tries to set path to the current path that you are in. However, iis: (env:, alias:, cert:, etc) are not available paths in cmd. So it will try to fallback to the latest folder you were in under cmd-accessible path (C:, D:\ etc.)
And when the folder does not exist, it appears that the failsafe for this in the code is to open a real cmd window instead.
This can be replicated without IIS, push-location and pop-location.
mkdir c:\temp\deleteme;
cd c:\temp\deleteme;
cd env:;
rm c:\temp\deleteme -Recurse;
cmd
#Daniel's comment had the answer:
When calling cmd from powershell, it tries to set path to the current path that you are in. However, iis: (env:, alias:, cert:, etc) are not available paths in cmd. So it will try to fallback to the latest folder you were in under cmd-accessible path (C:, D:\ etc.)
And when the folder does not exist, it appears that the failsafe for this in the code is to open a real cmd window instead.
This can be replicated without IIS, push-location and pop-location.
mkdir c:\temp\deleteme;
cd c:\temp\deleteme;
cd env:;
rm c:\temp\deleteme -Recurse;
cmd

How to open 'This PC' using CMD or Powershell?

I need a way of opening the explorer at This PC , in the same way as opening in a windows explorer Gui, but I am incapable of this as using Explorer.exe in CMD opens quick access.
I tried opening it with a shortcut and that too failed.
Does anyone know of a way to do this?
Cheers
Just like you can run explorer.exe C:\ to open up the C: (or any other drive or folder path), you can also use a file: URI to open paths in Explorer as well. If you just specify the file: protocol without a directory (or specify file:\\), it will open This PC:
explorer file:
explorer file:\\
Note that you can also change the default Explorer location from Quick Access to This PC as well from Folder Options:
You can set this in the registry too if you're after automation to configure this. See my answer on how you can use PowerShell to set the default launch folder in the registry.
My experience is that, the following should work:
From cmd:
Start "" "%SystemRoot%\explorer.exe" /Select,"This PC"
From powershell:
Start "$Env:SystemRoot\explorer.exe" "/Select,'This PC'"
You can use this in cmd:
Explorer /root,
On Powershell, we can do this:
(New-Object -ComObject Shell.Application).Namespace("").Self.InvokeVerb()
We create a com object of class Shell.Application, then call
.InvokeVerb() that invokes the default verb "open".
Or more rigourously, by defining ssfDRIVES constant (see Microsoft reference)
Set-Variable ssfDRIVES -Option Constant -Value 0x11
(New-Object -ComObject Shell.Application).Namespace($ssfDRIVES).Self.InvokeVerb()
ssfDRIVES 0x11 (17). Namespace points to My Computer—the virtual folder that
contains everything on the local computer: storage devices, printers,
and Control Panel. This folder can also contain mapped network drives.
Open the Command Prompt and type this in:
explorer =

How can I get PowerShell current location every time I open terminal from file explorer

I can open PowerShell window in any directory using Windows File Explorer.
I want to run a script every time a new PowerShell window is open and use current directory where it was open in the script.
Using $profile let me for automatic script execution but $pwd variable does not have directory used to open PowerShell window but has C:\WINDOWS\system32. I understand PowerShell starts in C:\WINDOWS\system32, run $profile and next change location used with File Explorer. How can I get file explorer current directory it when my script is executes from $profile or maybe there is another way to automatic execute my script after PowerShell window is open?
Note: The answer below provides a solution based on the preinstalled File Explorer shortcut-menu commands for Window PowerShell.
If modifying these commands - which requires taking ownership of the registry keys with administrative privileges - or creating custom commands is an option, you can remove the NoWorkingDirectory value from the following registry keys (or custom copies thereof):
HKEY_CLASSES_ROOT\Directory\shell\Powershell
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell
Doing so will make the originating folder the working directory before PowerShell is invoked, so that $PROFILE already sees that working directory, as also happens when you submit powershell.exe via File Explorer's address bar.[1]
Shadowfax provides an important pointer in a comment on the question:
When you hold down Shift and then invoke the Open PowerShell window here shortcut-menu command on a folder or in the window background in File Explorer, powershell.exe is initially started with C:\Windows\System32 as the working directory[1], but is then instructed to change to the originating folder with a Set-Location command passed as a parameter; e.g., a specific command may look like this:
"PowerShell.exe" -noexit -command Set-Location -literalPath 'C:\Users\jdoe'
As an aside: The way this shortcut-menu command is defined is flawed, because it won't work with folder paths that happen to contain ' chars.
At the time of loading $PROFILE, C:\Windows\System32 is still effect, because any command passed to -command isn't processed until after the profiles have been loaded.
If you do need to know in $PROFILE what the working directory will be once the session is open, use the following workaround:
$workingDir = [Environment]::GetCommandLineArgs()[-1] -replace "'"
[Environment]::GetCommandLineArgs() returns the invoking command line as an array of arguments (tokens), so [-1] returns the last argument, assumed to be the working-directory path; -replace "'" removes the enclosing '...' from the result.
However, so as to make your $PROFILE file detect the (ultimately) effective working directory (location) irrespective of how PowerShell was invoked, more work is needed.
The following is a reasonably robust approach, but note that a fully robust solution would be much more complex:
# See if Set-Location was passed and extract the
# -LiteralPath or (possibly implied) -Path argument.
$workingDir = if ([Environment]::CommandLine -match '\b(set-location|cd|chdir\sl)\s+(-(literalpath|lp|path|PSPath)\s+)?(?<path>(?:\\").+?(?:\\")|"""[^"]+|''[^'']+|[^ ]+)') {
$Matches.path -replace '^(\\"|"""|'')' -replace '\\"$'
} else { # No Set-Location command passed, use the current dir.
$PWD.ProviderPath
}
The complexity of the solution comes from a number of factors:
Set-Location has multiple aliases.
The path may be passed positionally, with -Path or with -LiteralPath or its alias -PSPath.
Different quoting styles may be used (\"...\", """...""", '...'), or the path may be unquoted.
The command may still fail:
If the startup command uses prefix abbreviations of parameter names, such as -lit for -LiteralPath.
If a named parameter other than the path follows set-location (e.g., -PassThru).
If the string set-location is embedded in what PowerShell ultimately parses as a string literal rather than a command.
If the startup command is passed as a Base64-encoded string via -EncodedCommand.
[1] When you type powershell.exe into File Explorer's address bar instead, the currently open folder is made the working directory before PowerShell is started, and no startup command to change the working directory is passed; in that case, $PROFILE already sees the (ultimately) effective working directory.
1.open the registry (command:regedit)
2.find out the path \HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command (not \HKEY_CLASSES_ROOT\Directory\Background\shell\cmd\command)
3.the default value should be powershell.exe -noexit -command Set-Location -literalPath "%V"
4.you can change some param,
ps: you change the command to cmd.exe /s /k pushd "%V". if you do so, shift & right button in the explorer will open the cmd, not powershell

How to run an application as shell replacement on Windows 10 Enterprise

I need to create a special account on a computer running Windows 10 Enterprise. This account would launch an application directly on login instead of the default shell and exiting the application should force the computer to restart.
I was able to do this easily on Windows 8.1 Embedded Industry Pro using the configuration console and lockdown features.
Now, on Windows 10 I try to follow the two tutorials on technet WESL_UserSetting and Set up a kiosk on Windows 10 Pro, Enterprise, or Education
However, neither of the tutorials work. I have managed to execute the scripts described in them but they have no effect (I've modified them so they do not remove the shells set).
Finally I've ended up with the following code:
$COMPUTER = "localhost"
$NAMESPACE = "root\standardcimv2\embedded"
$ACCOUNT_NAME = "cmp"
$ShellLauncherClass = [wmiclass]"\\$COMPUTER\${NAMESPACE}:WESL_UserSetting"
$NTUserObject = New-Object System.Security.Principal.NTAccount($ACCOUNT_NAME)
$NTUserSID = $NTUserObject.Translate([System.Security.Principal.SecurityIdentifier]).Value
$NTUser_Shell = Get-WmiObject -namespace $NAMESPACE -computer $COMPUTER -class WESL_UserSetting |
where {$_.Sid -eq $NTUserSID}
if ($NTUser_Shell) {
"`Custom shell already set for [$ACCOUNT_NAME] removing it"
$ShellLauncherClass.RemoveCustomShell($NTUserSID)
}
$restart_shell = 0
$restart_device = 1
$shutdown_device = 2
$ShellLauncherClass.SetCustomShell($NTUserSID, "cmd.exe", ($null), ($null), $restart_device)
"`nCurrent settings for custom shells:"
Get-WmiObject -namespace $NAMESPACE -computer $COMPUTER -class WESL_UserSetting | Select Sid, Shell, DefaultAction
Executing this script in an admin powershell produces the desired output:
Custom shell already set for [cmp] removing it
Current settings for custom shells:
Sid Shell DefaultAction
--- ----- -------------
S-1-5-21-3842421150-1098587697-2315725148-1002 cmd.exe 1
However logging as the 'cmp' user simply shows the standard Windows 10 shell.
What should I change in order to be able to run a program instead of a standard shell?
I had the same problem right now. And yes, Microsoft has changed the way to do a shell replacement. You can install and use the Embedded Shell Launcher to customize windows as you like it for kiosk mode. But this is only available for Enterprise and Education.
If you don't want to buy the Enterprise version you can use the already known registry locations in HKCU and HKLM. https://msdn.microsoft.com/en-us/library/ms838576(v=WinEmbedded.5).aspx
But wait, oh no since Windows 10 it is only possible to use Microsoft signed applications, so your normal .net application isn't started and the screen keeps being black after login. But we've figured out a workaround.
Just use a Batch-File as bootstrapping. If you set the registry keys you like to a Batch-File and the Batch-File starts the real application, then it works like a charm.
#echo off
echo Bootstrapping, please wait ...
start /b "Bootstrap" "C:\vmwatcher\VMViewClientWatcher.exe"
Have you tried changing the users shell?
https://msdn.microsoft.com/en-us/library/ms838576(v=WinEmbedded.5).aspx
There are a few registry keys you need to set. First one enables the ability to give the user a unique shell, the second one defines the executable that starts instead of explorer.
I wanted to do something similar, and I borrowed heavily from other answers, but none of them were a complete working answer for me. Here's what I ended up doing.
Create a new user account
Setup the following vbs script (largely inspired by this thread) to launch the shell application and name it something like "launch.vbs"
set oShell=createobject("wscript.shell")
sCmd="d:\launchbox\launchbox.exe"
oShell.run sCmd,,true 'true forces it to wait for process to finish
sCmd="shutdown /r /t 0"
oShell.run sCmd
Login as the new user
Run regedit
Add a new string value named Shell to HKEY_Current_User\Software\Microsoft\Windows NT\CurrentVersion\Winlogon with a value of the command that you need to run to execute your script:
wscript d:\launchbox\launch.vbs
Logoff and log back on as the user to see it in action
I battled with this one myself. If you look at the notes for Windows 10 Shell Launcher, it only works in the Enterprise or Education version. If you try using this in Home or Pro versions it simply boots to a blank screen. Using the same script in Enterprise, I confirmed works perfectly...
I think you set up correctly the custom shell for the user, but maybe you need to activate the ShellLanuncher behaviour.
Try this (at the end of your script):
$ShellLauncherClass.SetEnabled($TRUE)
This way the standard windows 10 shell is not launched when you log on with the other account, but (at least in my case) the command line does not start and the result is a black screen.
You can still run the task manager and run a new task from there, but I don't understand why the command line does not automatically start.
I ran into the same issue, and that's because the Script from TechNet on how to configure ShellLauncher actually enables, then disables the same Shell!
# Enable Shell Launcher
$ShellLauncherClass.SetEnabled($TRUE)
$IsShellLauncherEnabled = $ShellLauncherClass.IsEnabled()
"`nEnabled is set to " + $IsShellLauncherEnabled.Enabled
# Remove the new custom shells.
$ShellLauncherClass.RemoveCustomShell($Admins_SID)
$ShellLauncherClass.RemoveCustomShell($Cashier_SID)
# Disable Shell Launcher
$ShellLauncherClass.SetEnabled($FALSE)
$IsShellLauncherEnabled = $ShellLauncherClass.IsEnabled()
"`nEnabled is set to " + $IsShellLauncherEnabled.Enabled
I was lazily just copying and pasting the code and expected it to work.
If you comment out the final ten lines, this process will work.
Remember Kids: don't just copy and paste code from Strangers!
I want to begin by apologizing for commenting on a very old thread.
I have struggled for the past 6 months trying to get a custom app to run as a default shell, and retain administrator rights. Like many people, these scripts and/or commands just weren't working, and I needed something quick, effective and EASY!
Simply replacing the "explorer.exe" (HKLM\SOFTWARE\Microsoft\Window NT\Winlogon\Shell) with a custom app location provided a black screen.
A much simpler way, and it works great, was to create a BATCH script to call the custom app through elevated powershell...
powershell -nologo -noprofile -executionpolicy bypass -command "start-process -verb 'runas' -filepath <full path of custom app executable>"
By replacing "explorer.exe" with this batch script I was able to successfully create a kiosk style lockdown under Windows 10 PRO with a non-UWP app.
My fist attempt to help where I have received much. Not a complete answer, but maybe enough to get you to your destination. This worked on my "Kiosk" app which is on "my" Windows 10 Enterprise system which was built specifically for my app. It will set your "shell" to start on system startup and then start your click once program. Hope this helps.
Imports System.Threading
Public Class Form1
# Path to your ClickOnce app
Dim startPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Programs) _
& '"\"' & '"remaining path to your app"' & '".appref-ms"'
# Path to your shell which is also a clickonce app(this one)
Dim spath As String = Application.StartupPath & '"\"' & My.Application.Info.AssemblyName _
& '".exe"'
# This sets the registry to start your shell which in turn starts your app.
# I did this so that if the app is closed, they see the shell background.
# You can add controls to your shell to restart the app, shutdown....
#Just be cautious, make sure your app is 100% done and updates on it's own before you
# disable the ability to get back to windows explorer.
# Other wise you could have a very bad day.
My.Computer.Registry.SetValue('"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\ _
CurrentVersion\Winlogon"', '"Shell"', spath)
Thread.Sleep(500)
Process.Start(startPath)
End Class
You can create a Provisioning Package using Windows Configuration Designer.
The gui will help in creating a simple shell replacement when you choose 'provision kiosk devices'

Windows Powershell: Shortcut for change directory

I just started using Windows Powershell and one major problem I've run into is when I start it, it starts me off in this directory:
C:\Users\Username
However, the directory I usually need to navigate to is in something like:
C:\Users\Username\Dropbox\Websites\2014\Projects\ProjectName
And sometimes it goes much deeper. So you can see how it is a little annoying to navigate each time I start the shell to this directory using ten separate cd commands. I was wondering if there was a way to set up a shortcut or alias for something like:
cd C:\Users\Username\Dropbox\Websites\2014\Projects\ProjectName
Or possibly I could set some sort of shortcut to the directory only so I could do something like:
cd shortcut
And it would cd to the proper directory. Does anyone have any experience with something like this? Is this a dumb thing to do? I'm very new to using any command line so I'm just trying to get used to navigating around files and folders more easily.
There is also another way to do this:
function PP { cd C:\Users\Username\Dropbox\Websites\2014\Projects\ProjectName }
Set-Alias shortcut `PP`
new-psdrive is your friend :
New-PSDrive -Name docs -PSProvider FileSystem -Root "C:\Users\username\Documents"
cd docs:
Run this in powershell:
start notepad $profile
That will open up your profile in notepad (notepad will prompt you to create it if it doesn't exist).
Any code you write in this .ps1 file will be executed when powershell starts.
You can also set a system environment variable, like if you were to set MYPSPATH equal to C:\Users\Username\Dropbox\Websites\2014\Projects then you could do this:
cd $env:MYPSPATH
That could be done either manually each time, or automatically within your $profile.
Also it's unclear from your question, but it sounds like you're doing a cd for every path component.
There's no need to do that. This command that you wished for:
cd C:\Users\Username\Dropbox\Websites\2014\Projects\ProjectName
will work as is. If I misunderstood this point I apologize.
Something that also might be useful to you is pushd which is an alias of Push-Location. This lets you change to a new directory and easily revert back where you started with popd or Pop-Location.
PS C:\users\Xenostar> Push-Location .\Dropox\Websites\2014\Projects
PS C:\users\Xenostar\Dropbox\Websites\2014\Projects> Pop-Location
PS C:\users\Xenostar>
And you can push multiple levels deep, and keep popping back to the previous ones.
I believe this is the documentation you are looking for to change the default location where powershell starts up: The Windows PowerShell Profile
Although it doesn't directly answer the question, I found using this utility makes navigating around in powershell far easier: https://github.com/rupa/z
Install using Install-Module z -AllowClobber
Then navigate with z whatever where it will match "whatever" against your most frequently visited folders.
If the directory you want to go is named X; then write cd X:\

Resources