mbomb007
mbomb007

Reputation: 4251

PowerShell: opening a file in default txt editor

I am trying to find a way to open a non-txt file (in this case, the hosts file) in the default text editor using PowerShell.

I made some progress after seeing this Reddit post, but the $txt_editor result always returns Notepad.exe, even though Notepad++ is my default editor for txt files.

$hosts_file = "$env:windir\System32\drivers\etc\hosts"
$txt_editor = ((Get-ItemProperty -Path 'Registry::HKEY_CLASSES_ROOT\txtfile\shell\open\command').'(Default)').trimend(" %1")
Start-Process -FilePath $txt_editor -Verb Runas -ArgumentList $hosts_file

This also returns Notepad.exe:

(Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\OpenWithList' -Name a).a

If I look at the above location in Registry Editor, I do see Notepad++ listed with the key d, but I don't know how to tell from only looking at a Registry key what the default text editor is, because the two solutions I saw in Reddit do not work.

I am using Windows 10, and the solution I am looking for will return the actual default text editor file location, so that it can be used to open a file as shown above.

This question still has not received an answer to my actual question, since the only answer doesn't show how to open a non-txt file using the configured default text file editor.

Update: I'm now trying to replicate this on Windows 11, and the registry key HKEY_CLASSES_ROOT\txtfile\shell\open\command doesn't exist. I need a solution that will include a solution for this aspect as well, if the registry is involved. I configured Notepad++ as the default, and a key was created at HKEY_CLASSES_ROOT\txtfilelegacy\shell\printto\command.

Upvotes: 6

Views: 16229

Answers (3)

stackprotector
stackprotector

Reputation: 13460

Beginning with Windows 8, you will find your file type associations in the registry at HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<FILE_TYPE>\UserChoice. There you will find a ProgId. Get it:

$ProgId = Get-ItemPropertyValue -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice -Name ProgId

With the ProgId you can look for the shell command in HKCR:

$Command = Get-ItemPropertyValue -Path Registry::HKEY_CLASSES_ROOT\$ProgId\shell\open\command -Name '(Default)'

In the command, replace %1 by your text file, e. g.:

$Command = $Command -replace '%1', 'C:\Windows\System32\drivers\etc\hosts'

You can then execute the command:

cmd /c $Command

This works with notepad++.exe.


Be aware, that not all programs directly register with a shell command. Some (like notepad.exe (no ++)) have a DelegateExecute value that contains a GUID. Afaik, you have to look that up by querying a DLL. As a workaround, you may still be able to guess the shell command by just appending the path of the text file. So, you could use the following logic to get your shell command:

$textfile = 'C:\Windows\System32\drivers\etc\hosts'
if ($Command.Contains('%1')) {
  $Command = $Command -replace '%1', $textfile
} else {
  $Command += " `"$textfile`""
}

You can then execute the command:

cmd /c $Command

This will at least work for notepad++.exe and for notepad.exe.

Upvotes: 1

mbomb007
mbomb007

Reputation: 4251

Using the information in @FoxDeploy's answer, I was able to construct a working PowerShell function.

function Edit-HostsFile {
    # Self-elevate if required
    if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
        if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
            $hosts_file = "$env:windir\System32\drivers\etc\hosts"
            # Get the configured application default for editing .txt files.
            $txt_app = ((Get-ItemProperty -Path Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice -Name ProgId).ProgId)
            $txt_editor = ((Get-ItemProperty -Path Registry::HKEY_CLASSES_ROOT\$($txt_app)\shell\open\command).'(Default)').replace(' "%1"', '')
            # Open the hosts file in the editor.
            Start-Process -FilePath $txt_editor -Verb Runas -ArgumentList $hosts_file
        }
    }
}

I hadn't gotten a working solution using the information in the answer when I tried a few years ago, but I was able to figure it out after trying again. A more complete solution with code would have been helpful, but it didn't take too long to create.

Upvotes: 1

FoxDeploy
FoxDeploy

Reputation: 13537

The Start command (which is an alias for Start-Process) will launch any file in its default editor.

start .\MyCoolbmp.bmp
#Opens in MSPaint

start .\SomeNotes.txt
#Opens in Notepad

start .\SomeJason.json
#Opens in Visual Studio, go ahead and grab a coffee...

If I had to guess why yours isn't working, it's that the registry key you gave is the one used for the system, while the user's default editor is stored, from Windows 7 and up, within the HKEY_CURRENT_USER hive instead, at this path Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice'.

Here's the pertinent values:

$txtKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice"
Get-ItemProperty -Path $txtKey | tee-object -variable txtPath

Hash         : noCJnt8yX5Y=
ProgId       : VSCode.txt

This ties over to info found within HKCR:\Applications, where the true path can be found.

get-itemproperty Registry::\HKEY_CLASSES_ROOT\$($txtPath.ProgId)\shell\open\command


(default)    : "C:\Program Files\Microsoft VS Code\Code.exe" "%1"
#...

If you grab that (Default) value, now you've got the true path for the editor associated with text files.

To read a bit more on the topic, this blog post is pretty good and goes in detail into how associations work.

Upvotes: 11

Related Questions