Blog slowly looming over
This commit is contained in:
parent
b58407d358
commit
44c60f7069
17
app.vue
17
app.vue
|
@ -3,12 +3,23 @@ const config = useAppConfig()
|
|||
const theme = useVThemeSSR()
|
||||
const vdisp = ref(useVDisplay())
|
||||
const { reader } = storeToRefs(usePageStore())
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
titleTemplate: (chunk?) => {
|
||||
return chunk === config.title.short
|
||||
? config.title.full
|
||||
: `${chunk} – ${config.title.short}`
|
||||
if (route.fullPath === '/') return config.title.full
|
||||
|
||||
console.log(route.fullPath.split('/'))
|
||||
|
||||
if (route.fullPath.split('/').length === 2)
|
||||
switch (route.fullPath.split('/')[1]) {
|
||||
case 'blog':
|
||||
return 'The Enderchest'
|
||||
default:
|
||||
return `${chunk} – ${config.title.short}`
|
||||
}
|
||||
|
||||
return chunk!
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -244,6 +244,10 @@ body {
|
|||
border-radius: 8px;
|
||||
background-color: rgb(255 255 255 / 15%);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
|
@ -307,6 +311,9 @@ body {
|
|||
}
|
||||
|
||||
.post {
|
||||
scroll-snap-type: both mandatory;
|
||||
scroll-snap-stop: normal;
|
||||
|
||||
&-box {
|
||||
position: relative;
|
||||
|
||||
|
@ -363,16 +370,52 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
&-details {
|
||||
}
|
||||
|
||||
&-preamble {
|
||||
&-thumb {
|
||||
max-width: 800px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
|
||||
position: relative;
|
||||
|
||||
width: 100%;
|
||||
min-height: 400px;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
|
||||
border-radius: 1em;
|
||||
|
||||
scroll-snap-align: end;
|
||||
|
||||
text-shadow: black 1px 1px 7px;
|
||||
|
||||
iconify-icon {
|
||||
filter: drop-shadow(1px 2px 3px rgb(0 0 0 / 100%));
|
||||
}
|
||||
|
||||
&-share {
|
||||
position: absolute;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&-control {
|
||||
position: absolute;
|
||||
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
scroll-snap-align: start;
|
||||
|
||||
:is(p, li) {
|
||||
a {
|
||||
@extend %link;
|
||||
|
@ -383,6 +426,21 @@ body {
|
|||
color: royalblue;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.25em;
|
||||
|
||||
border-radius: 0.5em;
|
||||
|
||||
cursor: pointer;
|
||||
background-color: rgb(83 35 162 / 10%);
|
||||
|
||||
transition: 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(138 71 245 / 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:is(h1, h2, h3, h4, h5, h6) {
|
||||
|
@ -399,8 +457,90 @@ body {
|
|||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 0.75em 1em;
|
||||
|
||||
border-left: 0.25em solid rgb(153 153 255 / 60%);
|
||||
border-top-right-radius: 0.5em;
|
||||
border-bottom-right-radius: 0.5em;
|
||||
|
||||
background-color: rgb(153 153 255 / 10%);
|
||||
|
||||
transition: 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
border-left-color: rgb(153 153 255 / 100%);
|
||||
background-color: rgb(153 153 255 / 15%);
|
||||
}
|
||||
|
||||
:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 14px;
|
||||
padding: 1em;
|
||||
|
||||
border-radius: 0.5em;
|
||||
background-color: rgb(83 35 162 / 5%);
|
||||
|
||||
position: relative;
|
||||
|
||||
overflow-x: auto;
|
||||
|
||||
code {
|
||||
counter-reset: step;
|
||||
counter-increment: step 0;
|
||||
|
||||
scroll-padding: 0.5em;
|
||||
|
||||
.line::before {
|
||||
content: counter(step);
|
||||
counter-increment: step;
|
||||
|
||||
display: inline-block;
|
||||
|
||||
text-align: right;
|
||||
|
||||
color: rgb(238 246 250 / 40%);
|
||||
|
||||
width: 1rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
background-color: rgb(153 153 255 / 10%);
|
||||
|
||||
border: 1px solid rgb(153 153 255 / 60%);
|
||||
border-radius: 0.5em;
|
||||
|
||||
opacity: 0;
|
||||
|
||||
transition: 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.button {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,7 +610,7 @@ body {
|
|||
&-description {
|
||||
display: -webkit-box;
|
||||
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
---
|
||||
title: The Windows Context Menu – Is It a Lost Cause?
|
||||
description: We dive in deep into the Windows context menu and how to customize it to your liking.
|
||||
description: A deep dive into the Windows context menu API and customization options it offers. Shell components for beginners and context menu cleanup.
|
||||
authors: ['Enderman']
|
||||
created: 2023-08-13T15:51:19Z
|
||||
updated: 2024-02-18T21:32:12Z
|
||||
draft: false
|
||||
tags: ['windows', 'context-menu', 'customization', 'registry', 'shell', 'shell-extensions', 'context-menu-handlers']
|
||||
thumbnail: '/images/blog/thumbnails/the-windows-context-menu.png'
|
||||
tags: ['windows', 'context menu', 'customization', 'registry', 'windows tweaks', 'shell', 'shell extensions', 'shell components', 'context menu handlers', 'windows 10', 'windows 11']
|
||||
thumbnail: /images/blog/thumbnails/the-windows-context-menu.png
|
||||
ogImage:
|
||||
component: BlogImage
|
||||
props:
|
||||
image: /images/blog/thumbnails/the-windows-context-menu.png
|
||||
---
|
||||
|
||||
# The Windows context menu is... poorly made.
|
||||
|
@ -63,7 +68,7 @@ upon execution.
|
|||
There are two main components the context menu is composed of:
|
||||
|
||||
* **Shell entries** — provided locally and managed by the registry;
|
||||
* **Context menu handlers** — provided and managed by external software;
|
||||
* **Context menu handlers** — provided and managed by external software.
|
||||
|
||||
Neither of them is documented well, but
|
||||
there is some developer documentation for handlers available [on Microsoft's website](https://go.enderman.ch/Fm4t3).
|
||||
|
@ -97,7 +102,7 @@ In conclusion, there are three types of applications in terms of friendliness to
|
|||
|
||||
* **Apps using context menu handlers with customizable settings** — the friendliest;
|
||||
* **Apps using shell entries** — customizable through registry hacks;
|
||||
* **Apps using context menu handlers without settings** — the entries are uneditable;
|
||||
* **Apps using context menu handlers without settings** — the entries are uneditable.
|
||||
|
||||
The first case is the simplest and isn't worth talking about —
|
||||
consult the documentation for the software in question to find all the necessary tweaks.
|
||||
|
@ -154,7 +159,7 @@ for better understanding:
|
|||
* **Shell extension** is a general term for a plugin for the Windows Explorer — the **context menu handler** is a
|
||||
particular case of a shell extension;
|
||||
* **Shell component** is a broad term for a component that helps the shell interact with the system — that includes
|
||||
shell extensions, file extensions, protocols, etc.;
|
||||
shell extensions, file extensions, protocols, etc.
|
||||
|
||||
If this doesn't show how big of a predicament Microsoft is in with the context menu, I don't know what does.
|
||||
I tried my best to keep the technical language as clear as possible. 😒
|
||||
|
@ -167,7 +172,7 @@ Entries provided by software — the context menu handlers — are stored under
|
|||

|
||||
|
||||
Since registry key names are case-insensitive by design in Windows, capitalization plays no role.
|
||||
**The value names, however, are** — keep that in mind, as in some cases it might bite you.
|
||||
**The value names, however, are** — keep that in mind, as in some cases it might bite.
|
||||
The context menu doesn't seem to care.
|
||||
|
||||
_Truly an amazing specification!_
|
||||
|
@ -189,9 +194,9 @@ No matter how hard I tried, I could not find the exact specification of the inco
|
|||
My suggestion is to treat the default `command` value as **raw command line** (e.g. Run box),
|
||||
with an exception to the following two macros:
|
||||
* `%1` — the absolute file path without quotes
|
||||
If you right-click `C:\Users\bleh\p.txt`, execute the shell entry,
|
||||
the `%1` in the context of the command line will be equivalent to `C:\Users\bleh\p.txt`;
|
||||
* `%V` — the absolute directory path without quotes;
|
||||
When the shell entry is executed after a right-click on `C:\Users\bleh\p.txt`,
|
||||
the `%1` in the context of the command line is equivalent to `C:\Users\bleh\p.txt`;
|
||||
* `%V` — the absolute directory path without quotes.
|
||||
|
||||
::card
|
||||
---
|
||||
|
@ -210,7 +215,7 @@ The directory macro `%V` also sometimes falls flat depending on the shell entry
|
|||
|
||||
On rare occasions, the default value is left unset, with `DelegateExecute` alongside it containing a GUID.
|
||||
When that's the case, the command handler is implemented through the `IExecuteCommand` COM interface,
|
||||
and you cannot customize it.
|
||||
and hence cannot be customized by normal means.
|
||||
|
||||
**Why is that a thing?** Ask me a simpler question. It could be a compatibility layer for C, but your guess is as good as mine.
|
||||
|
||||
|
@ -281,17 +286,20 @@ you should use the `REG_SZ` value called `Icon` inside the respective `shell` ke
|
|||
|
||||
It uses that unmistakably distinct and clumsy **WinAPI resource syntax** to specify a direct link to the icon within
|
||||
a file containing resources.
|
||||
|
||||
```csv
|
||||
PATH_TO_FILE_WITH_ICON_RESOURCES,INDEX
|
||||
```
|
||||
|
||||
If you want to select the first icon (in that case, the `INDEX` part is 0),
|
||||
the `INDEX` part can be omitted completely:
|
||||
|
||||
```csv
|
||||
PATH_TO_FILE_WITH_ICON_RESOURCES
|
||||
```
|
||||
|
||||
The following expressions are completely valid and are going to work:
|
||||
|
||||
```csv
|
||||
"C:\Windows\system32\cmd.exe"
|
||||
C:\Windows\regedit.exe
|
||||
|
@ -302,6 +310,7 @@ shell32.dll,3
|
|||
SHELL32.DLL,10
|
||||
"C:\Windows\system32\SHELL32.DLL",9
|
||||
```
|
||||
|
||||
You can omit the quotes and absolute paths depending on the `%PATH%` variable that unholy concoction of an API uses.
|
||||
**Spoiler:** they don't match against the system `%PATH%`.
|
||||
Only God knows what paths it's able to parse by default.
|
||||
|
@ -381,11 +390,11 @@ Please tag me on [Twitter](https://go.enderman.ch/twitter) or [send a mail](mail
|
|||
have the knowledge.
|
||||
|
||||
**A few examples:**
|
||||
* `CanonicalName`
|
||||
* `CommandStateHandler`
|
||||
* `CommandStateSync`
|
||||
* `Description`
|
||||
* `VerbName`
|
||||
* `CanonicalName`;
|
||||
* `CommandStateHandler`;
|
||||
* `CommandStateSync`;
|
||||
* `Description`;
|
||||
* `VerbName`.
|
||||
|
||||
#### Deleting entries
|
||||
Even simpler — it's the opposite of adding one.
|
||||
|
@ -400,86 +409,195 @@ Even simpler — it's the opposite of adding one.
|
|||
which might result in the item remaining in place despite the deletion.
|
||||
|
||||
#### Sorting entries
|
||||
Now that's the funniest one. I even memed about it on Twitter.
|
||||
The only way to sort the context menu is via the alphabetical order of its respective shell entries in the registry.
|
||||
Yes. I am not kidding. Let the screenshots speak for themselves.
|
||||
That's easily the most hilarious procedure of them all. I even [tweeted](https://go.enderman.ch/3hcO9) about it.
|
||||
|
||||
The only way to sort the context menu items is...
|
||||
**by managing the alphabetical order of their respective shell entries in the registry**.
|
||||
Seriously, I am not kidding.
|
||||
Let the screenshots speak for themselves.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Yeah... I'd rather not comment on that.
|
||||
_Yeah... I'd rather leave all the obscene comments aside._
|
||||
|
||||
##### Position override
|
||||
Another silly and janky feature that has a limited number of use cases.
|
||||
You can manually override the position of your context menu item to be...
|
||||
Another silly feature with a limited number of use cases
|
||||
that's likely been created due to all prior mess Microsoft has created.
|
||||
It's possible to manually override the position of a context menu item to be...
|
||||
either at the very top, or the very bottom.
|
||||
Not much better than alphabetical sorting if you ask me...
|
||||
_Still doesn't top off the alphabetical sorting between the registry peers..._
|
||||
|
||||
In your entry under shell, create a REG_SZ value called Position.
|
||||
If you want to force the context menu handler to the top, put Top as data, otherwise put Bottom.
|
||||
In the `shell` subkey under the respective shell entry, create a `REG_SZ` value called `Position`.
|
||||
To enforce the context menu item to appear at the very top,
|
||||
insert `Top` into the value data, otherwise insert `Bottom`.
|
||||
|
||||
Sometimes this may be necessary, as, for example, Microsoft dumps their regular alphabetical sorting strategy at
|
||||
the bottom of the context menu, where display and personalization settings reside.
|
||||
They simply specify the Bottom position for each of the entries.
|
||||
If I recall correctly, they're still sorted alphabetically between themselves, as position override takes precedence.
|
||||
Sometimes directly enforcing the position happens to be necessary.
|
||||
For instance, Microsoft dumps the usual sorting strategy at the very bottom of the context menu,
|
||||
where the display and personalization settings reside.
|
||||
They simply set the `Bottom` position for each of the entries.
|
||||
|
||||
**What happens when there are multiple shell entries enforced to be in a set position?**
|
||||
The alphabetical sorting makes a comeback,
|
||||
it occurs between the shell entries with overridden positions just the same way.
|
||||
|
||||

|
||||
|
||||
##### Bottom line
|
||||
Some of the default shell entries like Powershell have specific keys
|
||||
(for the sake of that example, `ProgrammaticAccessOnly`) to control their appearance context menu.
|
||||
|
||||
As a rule of thumb, every time you're dealing with existing shell entries,
|
||||
I REALLY suggest that you search for a way to modify them online before resorting to any of the general cases I've described above.
|
||||
If you can't find anything even on the Internet, well, anything works.
|
||||
|
||||
### Uneditable entries
|
||||
As for the Context Menu handlers, there's actually not much you can do.
|
||||
They're located under the shellex\ContextMenuHandlers subkey.
|
||||
### Context menu handlers
|
||||
Compared to shell entries, there isn't much to be tweaked via registry in context menu handlers.
|
||||
Their general location is the `ContextMenuHandlers` subkey under the `shellex` key in the respective shell entry.
|
||||
|
||||

|
||||
|
||||
Most of the time, the only data they contain is a lonely GUID. That doesn't help much.
|
||||
Most of the time, the only piece of data they contain is a lonely GUID of the respective handler.
|
||||
|
||||

|
||||
|
||||
So, to remove the Context Menu handler, you should delete the subkey under ContextMenuHandlers.
|
||||
I strongly suggest you save the GUID it contained so that you could roll back at any time later.
|
||||
#### Removing handlers
|
||||
|
||||
A context menu handler always directly corresponds to some child under the `ContextMenuHandlers` key.
|
||||
Therefore, all that has to be done to remove a handler is removal of the **respective child key**.
|
||||
|
||||
I strongly suggest writing **the GUID** and **the location** of the removed entry down somewhere,
|
||||
so that there is a way to roll back any time later.
|
||||
|
||||

|
||||
|
||||
Adding your own...
|
||||
Well, that's complicated.
|
||||
You actually have to write your own handler in a language supporting Windows API or any sort of abstraction of it.
|
||||
For example, C# is a decent choice.
|
||||
I don't suggest you waste time on this,
|
||||
unless you're making full-on software that you want to make more accessible to Windows users.
|
||||
#### Adding handlers
|
||||
|
||||
Adding a custom handler is complicated.
|
||||
It's not as trivial as adding a shell entry —
|
||||
it requires implementing a handler interface using a language
|
||||
supporting Windows API or an abstraction layer on top of it.
|
||||
C# would be a decent choice precisely for this task.
|
||||
|
||||
However, it's just a waste of time to implement a handler for a single shell entry,
|
||||
unless there's software to go along with it.
|
||||
The idea behind context menu handlers is to **make native application experience nicer** for Windows users.
|
||||
|
||||
In other words, Microsoft failed to implement an accessible API for the context menu,
|
||||
so they did what they do best — shifted the responsibility to the developers writing third-party software.
|
||||
|
||||
This is how a partial implementation of the `IContextMenu` interface in C++ looks like:
|
||||
|
||||
```cpp
|
||||
STDMETHODIMP CShellExtension::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) {
|
||||
BOOL fEx = FALSE;
|
||||
BOOL fUnicode = FALSE;
|
||||
|
||||
if(lpcmi->cbSize == sizeof(CMINVOKECOMMANDINFOEX)) {
|
||||
fEx = TRUE;
|
||||
if (lpcmi->fMask & CMIC_MASK_UNICODE) fUnicode = TRUE;
|
||||
}
|
||||
|
||||
if (!fUnicode && HIWORD(lpcmi->lpVerb)) {
|
||||
if (StrCmpIA(lpcmi->lpVerb, m_pszVerb)) return E_FAIL;
|
||||
}
|
||||
else if (fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX *) lpcmi)->lpVerbW)) {
|
||||
if (StrCmpIW(((CMINVOKECOMMANDINFOEX *)lpcmi)->lpVerbW, m_pwszVerb)) return E_FAIL;
|
||||
}
|
||||
else if (LOWORD(lpcmi->lpVerb) != IDM_DISPLAY) {
|
||||
return E_FAIL;
|
||||
}
|
||||
else {
|
||||
MessageBox(
|
||||
lpcmi->hwnd,
|
||||
"The File Name",
|
||||
"File Name",
|
||||
MB_OK | MB_ICONINFORMATION
|
||||
);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
```
|
||||
|
||||
The `InvokeCommand()` method is called when a user clicks a context menu item.
|
||||
I've taken that example from [Microsoft](https://go.enderman.ch/TArYX).
|
||||
|
||||
That whole thing isn't too bad — the logic is far more robust and understandable
|
||||
compared to its surface-level registry counterpart, but it certainly requires getting used to WinAPI.
|
||||
|
||||
**By definition, it's a requirement to implement interfaces entirely.**
|
||||
However, since we're dealing with Microsoft,
|
||||
the «interface» in question is actually an _abstract class_ and can be implemented partially.
|
||||
|
||||
The `IContextMenu` interface has three methods:
|
||||
* `GetCommandString()` — retrieves the canonical name of the command (optional);
|
||||
* `InvokeCommand()` — handles the command (required);
|
||||
* `QueryContextMenu()` — adds items to the context menu (required).
|
||||
|
||||
The `IContextMenu` interface is the most common one, but there are others,
|
||||
such as `IContextMenu2` and `IContextMenu3`.
|
||||
Essentially, this is how the context menu handlers work inside.
|
||||
|
||||
While all of this is just a brief overview of the API,
|
||||
you can learn everything about them and more in the [Shell Developer's Guide](https://go.enderman.ch/W50xJ).
|
||||
|
||||
## Dealing with locked keys
|
||||
If the registry key is locked, and you don't have write permissions for it, it's owned by TrustedInstaller,
|
||||
and you have to manually reclaim ownership of the key and allow yourself to make edits to it.
|
||||
If the registry key is locked, the user you're logged in as is excluded from the ACL.
|
||||
Commonly, when the key is locked, it's owned by `TrustedInstaller`.
|
||||
When that's the case, it's necessary to reclaim ownership of the key to allow making edits to the ACL.
|
||||
There are plenty of ways to do that, I will list two common ones.
|
||||
|
||||
Optimal way: Using Process Hacker with the TrustedInstaller plugin or Winaero Tweaker,
|
||||
run regedit as Trusted Installer and perform the necessary tweaks.
|
||||
### Using external tools
|
||||
The idea here is to run `regedit` — the registry editor as the `TrustedInstaller` user directly.
|
||||
You can think of `TrustedInstaller` as the Windows equivalent of `root` in Unix-like systems —
|
||||
the superuser.
|
||||
|
||||
General solution:
|
||||
While Windows generally has more granular control over permissions,
|
||||
and the idea of having a superuser — **the ultimate authority of the system** — is less prominent and unannounced,
|
||||
`TrustedInstaller` is the closest object to a superuser Windows has.
|
||||
|
||||
Navigate to the key you want to take ownership of
|
||||
Open the «Properties» window
|
||||
Head over to the Advanced tab
|
||||
At the top of the Advanced Security Settings it states Owner: TrustedInstaller. Click Change
|
||||
Input your username into the Enter the object name to select (examples) text area.
|
||||
Click OK
|
||||
Check the «Replace owner on subcontainers and objects» checkbox
|
||||
Check the «Replace all child object permission entries» checkbox
|
||||
Click OK
|
||||
Select Administrators (PC_NAME\Administrators) in the group selector and then check Full Control box in the Permissions window down below
|
||||
Click OK
|
||||
After performing above steps, you must have gotten full and almost complete (some registry values and keys are still protected after the general procedure) access to the desired key.
|
||||
For those wondering, I've already explained [here](https://go.enderman.ch/o2KGt) why
|
||||
«sudo for Windows» makes no sense.
|
||||
|
||||
##### Process Hacker <sub>[download](https://go.enderman.ch/process-hacker)</sub>
|
||||

|
||||
|
||||

|
||||
|
||||
##### Winaero Tweaker <sub>[download](https://go.enderman.ch/winaero)</sub>
|
||||

|
||||
|
||||
[Sergey](https://go.enderman.ch/Dr0iS) makes an entirely valid point in his Winaero Tweaker:
|
||||
|
||||
> **Warning!!!**
|
||||
>
|
||||
> Running programs under TrustedInstaller privileges, especially a file manager app or Regedit,exe can be
|
||||
> VERY risky and harmful for your OS. It is like a God mode in a first-person shooter game, where nothing can
|
||||
> stop your actions, so if you execute a malware infected file as TrustedInstaller, it can cause damage to the
|
||||
> Windows operating system. Use this mode only if you perfectly understand what you are doing and if there is
|
||||
> no simpler way than running it as Trusted Installer.
|
||||
|
||||
This is exactly the reason I resort to setting permissions manually.
|
||||
It's a bit more time-consuming, but it's safer.
|
||||
|
||||
### Setting permissions manually
|
||||
The trusty old way to do it is to manually set permissions for the key.
|
||||
Once you get the hang of it, it really isn't that difficult.
|
||||
|
||||

|
||||
|
||||
##### General procedure
|
||||
1. Navigate to the key you want to claim ownership of;
|
||||
2. Open the «Properties» window;
|
||||
3. Head over to the «Advanced» tab;
|
||||
4. The current owner is shown at the top of the «Advanced Security Settings» window. Click «Change»;
|
||||
5. Type out your username in the text area with the «Enter the object name to select (examples)» label;
|
||||
6. Click «OK»;
|
||||
7. Tick the «Replace owner on subcontainers and objects» checkbox;
|
||||
8. Tick the «Replace all child object permission entries» checkbox;
|
||||
9. Click «OK»;
|
||||
10. Pick `Administrators (PC_NAME\Administrators)` in the group selector and then tick «Full Control» checkbox
|
||||
in the «Permissions» window at the bottom;
|
||||
11. You're done! Click «OK» and dismiss any warnings.
|
||||
|
||||
## Common registry paths
|
||||
Here is a list of the most common registry paths.
|
||||
There are as many «sections» as there are extensions, but these are the most common ones.
|
||||
They should cover most of your context menu.
|
||||
|
||||
#### Desktop Background — bottom rows
|
||||
`Computer\HKEY_CLASSES_ROOT\DesktopBackground`
|
||||
|
@ -497,7 +615,7 @@ Here is a list of the most common registry paths.
|
|||

|
||||
|
||||
#### Folder Item
|
||||
This extends [Folder](#folder).
|
||||
Extends [Folder](#folder).
|
||||
`Computer\HKEY_CLASSES_ROOT\Folder`
|
||||
|
||||

|
||||
|
@ -513,14 +631,15 @@ This extends [Folder](#folder).
|
|||

|
||||
|
||||
#### Library Background
|
||||
Inherits from [Folder Background](#folder-background).
|
||||
`Computer\HKEY_CLASSES_ROOT\LibraryFolder\background`
|
||||
Library background inherits from Folder Background,
|
||||
but can't parse the `%V` macro, which results in the following error.
|
||||
This is Microsoft's fault.
|
||||
To my knowledge, there is no way to fix that.
|
||||
|
||||

|
||||
|
||||
Despite the inheritance, it cannot parse the `%V` macro, which results in the following error.
|
||||
Blame Microsoft for being as consistent as ever.
|
||||
To my knowledge, there is no way to fix that.
|
||||
|
||||

|
||||
|
||||
#### All Files
|
||||
|
@ -529,12 +648,13 @@ To my knowledge, there is no way to fix that.
|
|||

|
||||
|
||||
#### All Filesystem Objects
|
||||
That's different from [All Files](#all-files) — it's a further generalization that includes system drives and symbols.
|
||||
Different from [All Files](#all-files) — it's a further generalization that includes system drives,
|
||||
symbolic links and other objects.
|
||||
`Computer\HKEY_CLASSES_ROOT\AllFilesystemObjects`
|
||||
|
||||

|
||||
|
||||
#### Type associations
|
||||
#### File type associations
|
||||
Text: `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\text`
|
||||
Images: `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\image`
|
||||
Documents: `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\document`
|
||||
|
@ -542,36 +662,58 @@ Audio: `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\audio`
|
|||
Video: `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\video`
|
||||
|
||||
## Cleaning up the context menu
|
||||
Most obnoxious default entries can be cleaned up using Winaero Tweaker.
|
||||
I suggest you use it to make the process way more bearable for yourself.
|
||||
The least fan-favorite default entries can be removed using Winaero Tweaker.
|
||||
I suggest using it to make the whole cleanup slightly more bearable.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### Areas Winaero Tweaker is unable to reach to
|
||||
Remove «Open PowerShell window here»
|
||||
Navigate to Computer\HKEY_CLASSES_ROOT\Directory\shell\Powershell
|
||||
Unlock key (The Windows Context Menu > Dealing with locked keys)
|
||||
Create a new REG_SZ value ProgrammaticAccessOnly without any data
|
||||
Navigate to Computer\HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell
|
||||
Unlock key
|
||||
Create a new REG_SZ value ProgrammaticAccessOnly without any data
|
||||
Remove «Open Linux shell here»
|
||||
Navigate to Computer\HKEY_CLASSES_ROOT\Directory\shell\WSL
|
||||
Unlock key
|
||||
Delete WSL key altogether
|
||||
Navigate to Computer\HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell
|
||||
Unlock key
|
||||
Create a new REG_SZ value ProgrammaticAccessOnly without any data
|
||||
Edit the «Edit» text context menu command
|
||||
Navigate to Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\text\shell\edit
|
||||
Make sure you've read the article thoroughly, then do anything you want with it.
|
||||
### Some extra common areas
|
||||
The following are fairly common areas Winaero Tweaker doesn't cover.
|
||||
|
||||
::card
|
||||
---
|
||||
icon: idea
|
||||
title: Tip
|
||||
---
|
||||
As a rule of thumb, whenever you're dealing with existing shell entries, I _really_ suggest
|
||||
**searching for a way to manage them online** before resorting to any measures I elaborated on in this article.
|
||||
Now if you can't find anything useful online, then anything works.
|
||||
::
|
||||
|
||||
#### Remove «Open PowerShell window here»
|
||||
1. Navigate to `Computer\HKEY_CLASSES_ROOT\Directory\shell\Powershell`;
|
||||
2. [Unlock the key](#dealing-with-locked-keys);
|
||||
3. Create a new `REG_SZ` value called `ProgrammaticAccessOnly` and leave it empty;
|
||||
4. Navigate to `Computer\HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell`;
|
||||
5. [Unlock the key](#dealing-with-locked-keys);
|
||||
6. Create a new `REG_SZ` value called `ProgrammaticAccessOnly` and leave it empty.
|
||||
|
||||
#### Remove «Open Linux shell here»
|
||||
1. Navigate to `Computer\HKEY_CLASSES_ROOT\Directory\shell\WSL`;
|
||||
2. [Unlock the key](#dealing-with-locked-keys);
|
||||
3. Remove the key;
|
||||
4. Navigate to `Computer\HKEY_CLASSES_ROOT\Directory\Background\shell\WSL`;
|
||||
5. [Unlock the key](#dealing-with-locked-keys);
|
||||
6. Create a new `REG_SZ` value called `ProgrammaticAccessOnly` and leave it empty.
|
||||
|
||||
#### Edit the «Edit» text context menu command
|
||||
1. Navigate to `Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\text\shell\edit`;
|
||||
2. Replace all mentions of the previous editor in default values with **Notepad++**
|
||||
or any other text editor you prefer.
|
||||
|
||||
## Bottom line
|
||||
No matter how terrible the context menu API might be for Windows, there's still a way to customize it.
|
||||
Hope you found the tricks useful!
|
||||
The context menu is a mess, and it's not going to change.
|
||||
It's a part of Windows that's been around for a long time and has been left behind by Microsoft.
|
||||
Shell entries are like differential equations — there's never a general solution.
|
||||
They're a pain to learn, but the acquired skill is worth it.
|
||||
|
||||
If you've spotted a mistake (be it orthographical, factual or any other)
|
||||
in this article or want to add some important details or share any important knowledge on the subject,
|
||||
please contact me on Twitter: @endermanch or hit me up on e-mail: blogs@enderman.ch
|
||||
No matter how terrible the context menu API is in Windows, there's still a way to customize it to your liking.
|
||||
Hopefully you learned something new from this article
|
||||
and are now able to make your context menu **a bit** more bearable.
|
||||
|
||||
**Spotted a mistake?**
|
||||
Want to add important details I missed or share extra knowledge on the subject?
|
||||
Tag me on [Twitter](https://go.enderman.ch/twitter) or [e-mail me](mailto:contact@enderman.ch)!
|
||||
All contributions welcome. 😉
|
||||
|
|
|
@ -59,34 +59,38 @@ export default defineNuxtConfig({
|
|||
'nuxt-link-checker',
|
||||
],
|
||||
content: {
|
||||
documentDriven: true,
|
||||
markdown: {
|
||||
remarkPlugins: ['remark-reading-time'],
|
||||
},
|
||||
highlight: {
|
||||
theme: {
|
||||
// Default theme (same as single string)
|
||||
default: 'github-light',
|
||||
// Theme used if `html.dark`
|
||||
dark: 'github-dark',
|
||||
// Theme used if `html.sepia`
|
||||
sepia: 'monokai',
|
||||
},
|
||||
theme: 'github-dark',
|
||||
langs: [
|
||||
'shell',
|
||||
'batch',
|
||||
'vb',
|
||||
'ini',
|
||||
'asm',
|
||||
'c',
|
||||
'cpp',
|
||||
'java',
|
||||
'python',
|
||||
'csv',
|
||||
'xml',
|
||||
'json',
|
||||
'js',
|
||||
'ts',
|
||||
'yaml',
|
||||
'html',
|
||||
'css',
|
||||
'sass',
|
||||
'php',
|
||||
'js',
|
||||
'ts',
|
||||
'vue',
|
||||
'shell',
|
||||
'mdc',
|
||||
'md',
|
||||
'yaml',
|
||||
'mdc',
|
||||
'pascal',
|
||||
'lisp',
|
||||
'sql',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,24 +1,111 @@
|
|||
<script setup lang="ts">
|
||||
import { formatDate } from 'date-fns'
|
||||
const { slug } = useRoute().params
|
||||
|
||||
const config = useAppConfig()
|
||||
const content = useContent()
|
||||
|
||||
const meta = {
|
||||
title: `${content.page.title}`,
|
||||
description: content.page.description,
|
||||
image: content.page.thumbnail,
|
||||
url: `${config.url}/blog`,
|
||||
}
|
||||
|
||||
defineOgImage()
|
||||
|
||||
// Hydrate the rendered items.
|
||||
onMounted(() => {
|
||||
document.querySelectorAll('pre').forEach((pre) => {
|
||||
const icon = document.createElement('iconify-icon')
|
||||
|
||||
icon.setAttribute('icon', 'mdi:content-copy')
|
||||
icon.setAttribute('inline', 'true')
|
||||
|
||||
icon.classList.add('button')
|
||||
|
||||
pre.appendChild(icon)
|
||||
})
|
||||
|
||||
document
|
||||
.querySelectorAll('code:not(pre *), pre > iconify-icon.button')
|
||||
.forEach((code) => {
|
||||
if (code instanceof HTMLElement) {
|
||||
code.onclick = () => {
|
||||
const area = document.createElement('textarea')
|
||||
|
||||
area.textContent =
|
||||
code.nodeName && code.nodeName.toLowerCase() === 'code'
|
||||
? code.textContent
|
||||
: code.parentElement!.textContent
|
||||
|
||||
// It's necessary to create the textarea element every time you copy to get access to the select() method.
|
||||
area.setSelectionRange(0, 99999) // An iOS gotcha.
|
||||
area.select()
|
||||
|
||||
// Copy the text inside the textarea.
|
||||
navigator.clipboard.writeText(area.value)
|
||||
|
||||
// TODO: Alert the user text has been successfully copied.
|
||||
|
||||
// Remove the textarea element.
|
||||
area.remove()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.querySelectorAll('code').forEach((code) => {
|
||||
code.onclick = null
|
||||
})
|
||||
|
||||
document.querySelectorAll('pre').forEach((pre) => {
|
||||
pre.querySelector('.clipboard')?.remove()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article
|
||||
class="scrollbar fade-mask-sm d-flex flex-column gap-3 flex-grow-1 overflow-x-hidden overflow-y-auto py-sm-4 pe-sm-3"
|
||||
class="post scrollbar fade-mask-sm d-flex flex-column gap-3 flex-grow-1 overflow-x-hidden overflow-y-auto py-sm-4 pe-sm-3"
|
||||
>
|
||||
<ContentDoc :path="`/blog/${slug}`">
|
||||
<template #default="{ doc }">
|
||||
<div class="post-preamble">
|
||||
<h3 class="alex">{{ doc.title }}</h3>
|
||||
<img
|
||||
draggable="false"
|
||||
:src="doc.thumbnail"
|
||||
:alt="doc.title"
|
||||
class="post-preamble-thumb rounded-4"
|
||||
/>
|
||||
<div
|
||||
class="post-preamble"
|
||||
:style="{ backgroundImage: 'url(' + doc.thumbnail + ')' }"
|
||||
>
|
||||
<div class="p-2">
|
||||
<h3 class="alex">{{ doc.title }}</h3>
|
||||
<div class="d-flex flex-row row-gap-0 column-gap-2 flex-wrap">
|
||||
<div class="d-flex flex-row gap-1 align-items-center">
|
||||
<iconify-icon icon="mdi:calendar" />
|
||||
<strong class="nobr font-small">
|
||||
{{ formatDate(doc.created, 'LLLL do, y – HH:mm') }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="d-flex flex-row gap-1 align-items-center">
|
||||
<iconify-icon icon="mdi:clock-outline" />
|
||||
<strong class="nobr font-small">
|
||||
{{ doc.readingTime.text.split(' ')[0] + ' minutes to read' }}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NuxtLink
|
||||
:href="`https://twitter.com/share?url=${config.url}/blog/${slug}&text=${doc.title}&hashtags=${doc.tags.slice(0, 3).join(',').replace(/ /g, '')}`"
|
||||
target="_blank"
|
||||
class="link post-preamble-share px-2 py-1"
|
||||
>
|
||||
<iconify-icon icon="mdi:twitter"></iconify-icon>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/blog" class="link post-preamble-control px-2 py-1">
|
||||
<iconify-icon icon="icon-park-solid:back"></iconify-icon>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="post-content">
|
||||
<Separator class="mt-0" />
|
||||
<ContentRenderer :value="doc" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,42 @@
|
|||
<script setup lang="ts">
|
||||
import { formatDate } from 'date-fns'
|
||||
|
||||
const config = useAppConfig()
|
||||
const meta = {
|
||||
title: 'The Enderchest',
|
||||
description:
|
||||
'A blog about software development, scientific research and Windows quirks.',
|
||||
image: `${config.url}/images/chest.png`,
|
||||
url: `${config.url}/blog`,
|
||||
}
|
||||
|
||||
useSeoMeta({
|
||||
title: meta.title,
|
||||
description: meta.description,
|
||||
ogTitle: meta.title,
|
||||
ogDescription: meta.description,
|
||||
ogImage: meta.image,
|
||||
ogUrl: meta.url,
|
||||
ogType: 'website',
|
||||
twitterTitle: meta.title,
|
||||
twitterDescription: meta.description,
|
||||
twitterImage: meta.image,
|
||||
twitterCard: 'summary',
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'The Enderchest',
|
||||
htmlAttrs: {
|
||||
lang: config.locale || 'en',
|
||||
},
|
||||
link: [
|
||||
{
|
||||
rel: 'icon',
|
||||
type: 'image/x-icon',
|
||||
href: '/favicon.ico',
|
||||
},
|
||||
],
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Loading…
Reference in New Issue