Skip to content

Profile auto-elevation, version 3#12137

Merged
4 commits merged intomainfrom
dev/migrie/f/632-attempt-4
Jan 12, 2022
Merged

Profile auto-elevation, version 3#12137
4 commits merged intomainfrom
dev/migrie/f/632-attempt-4

Conversation

@zadjii-msft
Copy link
Member

Summary of the Pull Request

This is the resurrection of #8514 and #11310. WE determined that we didn't want to do #11308 after all, so this should be profile auto-elevation, without the warning.

This PR adds two features:

  • the elevate: bool property to profiles
    • If the user is running unelevated, and elevate is set to true, then instead of opening a new tab, we'll open an elevated Terminal window with the profile.
    • Otherwise, we'll just open a new tab in the existing window. This includes cases where the window is elevated, and the profile is set to elevate:false. elevate:false basically just means "do nothing special with me".
  • the elevate: bool? property to NewTerminalArgs (newTab, splitPane)
    • This allows a user to create an action that will elevate the profile, even if the profile is not otherwise set to auto-elevate.
    • elevate:null (the default) does not change the profile's elevation status. The action will use whatever is set by the profile.
    • elevate:true will attempt to auto-elevate the profile
    • elevate:false will do nothing special.

References

PR Checklist

Detailed Description of the Pull Request / Additional comments

After playing with de-elevation a bit, it turns out it behaves weirdly with packaged applications. I can try and ask explorer.exe to launch the process on our behalf. However, if the thing we're launching is an execution alias (wt.exe), and we're elevated, then the child process will still launch elevated.

There's also something super BODGEY at work here. ShellExecute is the function we use to ask the OS to elevate something for us. But ShellExecute needs to be able to send a window message to the process that called it (if the caller was a WINDOWS subsystem application). So if we die immediately after calling ShellExecute, then the elevated process never actually spawns - sad. So we're adding a helper process, elevate-shim.exe, that lives in our process. That'll be the one that actually calls ShellExecute, so that it can live for the duration of the UAC prompt.

Validation Steps Performed

  • Ran tests
  • Opened a bunch of terminal tabs at various different elevation levels
  • opened new splits too
  • In the defaults (base layer) as well, for madness

Some settings to use for testing

Details
    "keybindings" :
    [
        ////////// ELEVATION ///////////////
        { "keys": "f1", "name": "ELEVATED TAB", "icon": "\uEA18", "command": { "action": "newTab", "elevate": true } },
        { "keys": "f2", "name": "ELEVATED, Color", "icon": "\uEA18", "command": {
            "action": "newTab", "elevate": true, "commandline": "PowerShell.exe", "startingDirectory": "C:\\Windows", "tabColor": "#bbaa00"
        } },
        { "keys": "f3", "name": "unelevated ELEVATED", "icon": "🙃", "command": {
            "action": "newTab", "elevate": false, "profile": "elevated cmd"
        } },
        //////////////////////////////
    ],

    "profiles":
    {
        "defaults":
        {
            "elevate": true,
        },
        "list":
        [
            {
                "hidden":false,
                "name" : "cmd",
                "commandline" : "cmd.exe",
                "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
                "startingDirectory" : "%USERPROFILE%",
                "opacity" : 20
            },
            {
                "name" : "the COOLER cmd",
                "commandline" : "c:\\windows\\system32\\cmd.exe",
                "startingDirectory" : "%USERPROFILE%",
            },
            {
                "name" : "the sneaky cmd",
                "commandline" : "c:\\windows\\system32\\cmd.exe /k echo sneaky sneaks",
                "startingDirectory" : "%USERPROFILE%",
            },
            {
                "name": "elevated cmd",
                "commandline": "cmd.exe /k echo This profile is always elevated",
                "startingDirectory" : "well this is garbage",

                "elevate": true,
                "background": "#9C1C0C",
                "tabColor": "#9C1C0C",
                "colorScheme": "Desert"
            },
            {
                "name": "unelevated cmd",
                "commandline": "cmd.exe /k echo This profile is just as elevated as you started with",
                "elevate": false,
                "background": "#1C0C9C",
                "tabColor": "#1C0C9C",
                "colorScheme": "DotGov",
                "useAcrylic": true
            },
        ]

Also try:

  • wtd nt -p "elevated cmd" ; sp -p "elevated cmd"
  • wtd nt -p "elevated cmd" ; nt -p "elevated cmd"

This was merged manually via

git diff dev/migrie/f/non-terminal-content-elevation-warning dev/migrie/f/632-on-warning-dialog > ..\632.patch
git apply ..\632.patch --ignore-whitespace --reject

    ```
    git diff dev/migrie/f/non-terminal-content-elevation-warning dev/migrie/f/632-on-warning-dialog > ..\632.patch
    git apply ..\632.patch --ignore-whitespace --reject
    ```
@ghost ghost added Area-Settings Issues related to settings and customizability, for console or terminal Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal. labels Jan 11, 2022
@zadjii-msft
Copy link
Member Author

@carlos-zamora and @miniksa, you both signed off on #11310 last time. This should be the same, so it should be an easy s/o.

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want an answer on the sln changes. I think you may want to remove the AuditMode and Fuzzing ones.

Other than that, looks great! I'll approve assuming you'll come back and fix that.

Copy link
Member

@miniksa miniksa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this seems familiar. Let's do it.

zadjii-msft added a commit that referenced this pull request Jan 11, 2022
  To match the arg in #12137.

  `--elevate` will manually elevate the profile.

  `--no-elevate` will override a `elevate: true` in the profile with false.

  So now you can `wt --elevate cmd` and it'll do what you think

  * [x] I work here
  * [x] Tests added
  * [ ] need to update docs
@zadjii-msft zadjii-msft mentioned this pull request Jan 11, 2022
3 tasks
@github-actions
Copy link

github-actions bot commented Jan 12, 2022

@check-spelling-bot Report

Unrecognized words, please review:

  • SHELLEXECUTEINFO
Previously acknowledged words that are now absent deconstructed devicefamily guardxfg pgorepro pgort PGU Timeline timelines xfg
To accept these unrecognized words as correct (and remove the previously acknowledged and now absent words), run the following commands

... in a clone of the [email protected]:microsoft/terminal.git repository
on the dev/migrie/f/632-attempt-4 branch:

update_files() {
perl -e '
my @expect_files=qw('".github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt"');
@ARGV=@expect_files;
my @stale=qw('"$patch_remove"');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
next if /^(?:$re)(?:(?:\r|\n)*$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect/4455bdb0a3eb983ac029ab92c0e2ff709ba2a1a4.txt";
use File::Path qw(make_path);
use File::Basename qw(dirname);
make_path (dirname($new_expect_file));
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"$patch_add"');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a)."-".$a cmp lc($b)."-".$b} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;
system("git", "add", $new_expect_file);
'
}

comment_json=$(mktemp)
curl -L -s -S \
  --header "Content-Type: application/json" \
  "https://api.github.com/repos/microsoft/terminal/issues/comments/1010923954" > "$comment_json"
comment_body=$(mktemp)
jq -r .body < "$comment_json" > $comment_body
rm $comment_json

patch_remove=$(perl -ne 'next unless s{^</summary>(.*)</details>$}{$1}; print' < "$comment_body")
  

patch_add=$(perl -e '$/=undef;
$_=<>;
s{<details>.*}{}s;
s{^#.*}{};
s{\n##.*}{};
s{(?:^|\n)\s*\*}{}g;
s{\s+}{ }g;
print' < "$comment_body")
  
update_files
rm $comment_body
git add -u
✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. You can copy the contents of each perl command excluding the outer ' marks and dropping any '"/"' quotation mark pairs into a file and then run perl file.pl from the root of the repository to run the code. Alternatively, you can manually insert the items...

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

🗜️ If you see a bunch of garbage

If it relates to a ...

well-formed pattern

See if there's a pattern that would match it.

If not, try writing one and adding it to a patterns/{file}.txt.

Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

Note that patterns can't match multiline strings.

binary-ish string

Please add a file path to the excludes.txt file instead of just accepting the garbage.

File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

@zadjii-msft zadjii-msft added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jan 12, 2022
@ghost
Copy link

ghost commented Jan 12, 2022

Hello @zadjii-msft!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit bc97af7 into main Jan 12, 2022
@ghost ghost deleted the dev/migrie/f/632-attempt-4 branch January 12, 2022 11:56
ghost pushed a commit that referenced this pull request Jan 27, 2022
There are a couple places where we now bail immediately on startup, if we think the window is going to get created without any tabs. We do that to prevent a blank window from flashing on the screen when launching auto-elevate profiles. Unfortunately, those broke defterm in a particularly hard to debug way. In the defterm invocation, there actually aren't any tabs when the app completes initialization. We use the initialization to actually accept the defterm handoff. So what would happen is that the window would immediately close itself gracefully, never accepting the handoff.

In my defense, #8514, the original auto-elevated PR, predates defterm merging (906edf7) by a few months, so I totally forgot to test this when rolling it into the subsequent iterations of that PR.

* Related to: 
  * #7489
  * #12137 
  * #12205 
* [x] Closes #12267 
* [x] I work here
* [ ] No tests on this code unfortunately
* [x] Tested manually

Includes a semi-related code fix to #10922 to make that quieter. That is perpetually noisy, and when trying to debug defterm, you've only got about 30s to do that before it bails, so the `sxe eh` breaks in there are quite annoying.
@ghost
Copy link

ghost commented Feb 3, 2022

🎉Windows Terminal Preview v1.13.10336.0 has been released which incorporates this pull request.:tada:

Handy links:

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Settings Issues related to settings and customizability, for console or terminal AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Question] Configuring Windows Terminal profile to always launch elevated

3 participants