# Technical Documentation: gerardog/gsudo

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/gerardog/gsudo)

### Overview (`README.md`)

# gsudo - a sudo for Windows

[](https://gitter.im/gsudo/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](../../actions/workflows/ci.yml)
[](https://community.chocolatey.org/packages/gsudo)
[](https://github.com/gerardog/gsudo/releases/latest)

**gsudo** is a `sudo` equivalent for Windows, with a similar user-experience as the original Unix/Linux sudo.
Allows you to run a command (or re-launch your current shell) with elevated permissions, in the current console window or a new one.

Just [prepend `gsudo`](#usage) (or the `sudo` alias) to your command and it will run elevated. For PowerShell use this [syntax](#usage-from-powershell--powershell-core): `gsudo { ScriptBlock }`

One UAC popup will appear each time. You can see less popups if you enable [gsudo cache](#credentials-cache).

It detects your current shell and elevates your command as native shell commands. (Supports `Cmd`, `PowerShell`, `WSL`, `git-bash`, `MinGW`, `Cygwin`, `Yori`, `Take Command`, `BusyBox` & `NuShell`.)

## Table of contents

- [gsudo - a sudo for Windows](#gsudo---a-sudo-for-windows)
  - [Table of contents](#table-of-contents)
  - [Demo](#demo)
  - [Features](#features)
  - [Installation](#installation)
  - [Usage](#usage)
    - [Usage from PowerShell / PowerShell Core](#usage-from-powershell--powershell-core)
      - [PowerShell Module](#powershell-module)
    - [Usage from WSL (Windows Subsystem for Linux)](#usage-from-wsl-windows-subsystem-for-linux)
  - [Configuration](#configuration)
  - [Credentials Cache](#credentials-cache)
  - [Known issues](#known-issues)
  - [FAQ](#faq)
  - [Please support gsudo! 💵](#please-support-gsudo-)

---

⭐ Extended documentation available at: [<https://gerardog.github.io/gsudo/>](https://gerardog.github.io/gsudo/docs/intro)

## Demo



(with `gsudo config CacheMode auto`)

---

## Features

- Elevated commands are shown in the current console. No new window (unless you specify `-n`)
- [Credentials cache](#credentials-cache): `gsudo` can elevate many times showing only one UAC pop-up if the user opts-in to enable the cache.
- Detects your current shell (Supports [`CMD`](#usage), [`PowerShell`](#usage-from-powershell--powershell-core), [`WSL`](#usage-from-wsl-windows-subsystem-for-linux), `Bash for Windows` (Git-Bash/MinGW/MSYS2/Cygwin), `Yori`, `Take Command` and `NuShell`), and elevates your command correctly.

- Supports being used on scripts:
  - Outputs StdOut/StdErr can be piped or captured (e.g. `gsudo dir | findstr /c:"bytes free" > FreeSpace.txt`) and exit codes too (`%errorlevel%`). If `gsudo` fails to elevate, the exit code will be 999.
  - If `gsudo` is invoked from an already elevated console, it will just run the command (it won't fail). So, you don't have to worry if you run `gsudo` or a script that uses `gsudo` from an already elevated console. (The UAC popup will not appear, as no elevation is required)

- `gsudo !!` elevates the last executed command. Works on CMD, Git-Bash, MinGW, Cygwin (and PowerShell with [gsudo module](#gsudomodule) only)

## Installation

- Using [Scoop](https://scoop.sh): `scoop install gsudo`
- Using [WinGet](https://github.com/microsoft/winget-cli/releases): `winget install gerardog.gsudo`
- Using [Chocolatey](https://chocolatey.org/install):  `choco install gsudo`
- Manual Setup: download and run the proper `MSI` installer for you system from the [latest release](https://github.com/gerardog/gsudo/releases/latest).
- Running this line: [(script)](installgsudo.ps1):
  ``` PowerShell
  PowerShell -Command "Set-ExecutionPolicy RemoteSigned -scope Process; [Net.ServicePointManager]::SecurityProtocol = 'Tls12'; iwr -useb https://raw.githubusercontent.com/gerardog/gsudo/master/installgsudo.ps1 | iex"
  ```
- Portable: 
  1. Download `gsudo.portable.zip` from the [latest release](https://github.com/gerardog/gsudo/releases/latest).
  2. Extract the folder corresponding to your processor architecture (x64, x86, or arm64) from the zip file to a suitable directory on your computer.
  3. Optionally, add that directory to your system's PATH environment variable if it's not already accessible.

**Please restart all your console windows** after installing to ensure that the `PATH` environment variable is refreshed.

Note: `gsudo.exe` is portable. No windows service is required or system change is done, except adding it to the Path.

## Usage

``` powershell
gsudo [options]                  # Starts your current shell elevated
gsudo [options] {command} [args] # Runs {command} with elevated permissions
gsudo cache [on | off | help]    # Starts/Stops a credentials cache session. (less UAC popups)
gsudo status [--json | filter ]  # Shows current user, cache and console status.
gsudo !!                         # Re-run last command as admin. (YMMV)
```

```
/* Detailed source-code truncated for AI context efficiency. */
```

**Note:** You can use anywhere **the `sudo` alias** created by the installers.

**Examples:**

``` powershell
gsudo   # elevates the current shell in the current console window (Supports Cmd/PowerShell/Pwsh Core/Yori/Take Command/git-bash/cygwin)
gsudo -n # launch the current shell elevated in a new console window
gsudo -n -w powershell ./Do-Something.ps1 # launch in new window and wait for exit
gsudo notepad %windir%\system32\drivers\etc\hosts # launch windows app

sudo notepad # sudo alias built-in

# redirect/pipe input/output/error example
gsudo dir | findstr /c:"bytes free" > FreeSpace.txt

gsudo config LogLevel "Error"          # Configure Reduced logging
gsudo config Prompt "$P [elevated]$G " # Configure a custom Elevated Prompt
gsudo config Prompt --reset            # Reset to default value

# Enable credentials cache (less UAC popups):
gsudo config CacheMode Auto
```

### Usage from PowerShell / PowerShell Core

`gsudo` detects if invoked from PowerShell and elevates PS commands (unless `-d` is used to elevate CMD commands).

The command to elevate will run in a different process, so it **can't access the parent `$variables` and scope.**

To elevate a commands or script block: **Wrap it in {curly braces}**.
   ``` powershell
   # Syntax:
   gsudo { ScriptBlock }
   gsudo [options] { ScriptBlock } [-args $argument1[..., $argumentN]] ;

   # Examples:
   gsudo { Write-Output "Hello World" }

   # Pass arguments with -args
   $MyString = "Hello World"
   gsudo { Write-Output $args[0] } -args $MyString

   # Output is serialized as PSObjects with properties.
   $services = gsudo { Get-Service 'WSearch', 'Winmgmt'}
   Write-Output $services.DisplayName

   # Inputs too: Example elevated iteration of a list.
   Get-ChildItem . | gsudo { $Input.CreationTime}
   ```

Alternative syntaxes:
<details>
  <summary>2. Invoke-gsudo wrapper function: (much slower)</summary>

   ``` powershell
   # Pass values (not variables by reference) by prefixing `$using:`. I.E.

   $MyString = "Hello World"
   Invoke-Gsudo { Write-Output $using:MyString }

   # Syntax:
   Invoke-Gsudo [-ScriptBlock] <ScriptBlock>
                [[-ArgumentList] <Object[]>]
                [-InputObject <PSObject>]
                [-LoadProfile | -NoProfile]
                [-Credential <PSCredential>]
   ```

    - PowerShell function.
    - Performs auto serialization of inputs & outputs.
    - You can prefix variables with the `$using:` scope modifier (like `$using:variableName`) and their serialized value is applied.
    - Use `-LoadProfile` or `-NoProfile` to override profile loading or not.
    - Use `-Credential` option for Run As User (same as `-u` but for `Get-Credentials`).
    - Better forwarding of your current context to the elevated instance (current Location, $ErrorActionPreference)
</details>

<details>
  <summary>3. Manual string interpolation. (not recommended) </summary>
  I don't recommend this approach as it is really hard to do proper escape all special characters.

   ``` PowerShell
   Usage: gsudo 'string literal'

   # Variable substitutions example:
   $file='C:\My Secret.txt';
   $algorithm='md5';
   $hash = gsudo "(Get-FileHash '$file' -Algorithm $algorithm).Hash"
   # or
   $hash = gsudo "(Get-FileHash ""$file"" -Algorithm $algorithm).Hash"
   ```

   - Accepts a string literal with the command to elevate.
   - Returns a list of strings.
</details>

#### PowerShell Module

- <a name="gsudomodule"></a> Optional: Import module `gsudoModule.psd1` into your PowerShell Profile:
  - Adds syntax auto-complete to gsudo in PowerShell. Plus, it suggests the 3 previous commands, making your workflow smoother than ever!
  - Enables `gsudo !!` on Powershell, to elevate the last executed command.
  - Adds Functions:
    - `Test-IsGsudoCacheAvailable` Returns true if a gsudo cache is active (meaning elevation with no UAC is possible).
    - `Test-IsProcessElevated`: Returns true if the current process is elevated.
    - `Test-IsAdminMember`: Returns true if the current user is member of the `Local Administrators` groups, which means it can elevate with.

  ``` Powershell
  # Add the following line to your $PROFILE
  Import-Module "gsudoModule"

  # Or run:
  Write-Output "`nImport-Module `"gsudoModule`"" | Add-Content $PROFILE
  ```

  - If you haven't already customized your PowerShell prompt (for example by installing Oh-My-Posh), you can easily add a red `#` indicating that the current process is elevated:
    

  To do so add this line to your profile (after importing `gsudoModule`):

  ``` powershell
  Set-Alias Prompt gsudoPrompt
  ```
---

### Usage from WSL (Windows Subsystem for Linux)

On WSL, elevation and `root` are different concepts. `root` allows full administration of WSL but not the windows system. Use WSL's native `su` or `sudo` to gain `root` access. To get admin privilege on the Windows box you need to elevate the WSL.EXE process. `gsudo` allows that (a UAC popup will appear).

On WSL bash, prepend `gsudo` to elevate **WSL commands** or `gsudo -d` for **CMD commands**.

``` bash
# elevate default shell
PC:~$ gsudo

# run elevated WSL command
PC:~$ gsudo mkdir /mnt/c/Windows/MyFolder

# run elevated Windows command
PC:~$ gsudo -d notepad C:/Windows/System32/drivers/etc/hosts
PC:~$ gsudo -d "notepad C:\Windows\System32\drivers\etc\hosts"

# test for gsudo and command success
retval=$?;
if [ $retval -eq 0 ]; then
    echo "Success";
elif [ $retval -eq $((999 % 256)) ]; then # gsudo failure exit code (999) is read as 231 on wsl (999 mod 256)
    echo "gsudo failed to elevate!";
else
    echo "Command failed with exit code $retval";
fi;
```

## Configuration

``` powershell
 gsudo config                          # Show current config settings & values.
 gsudo config {key} [--global] [value] # Read or write a user setting
 gsudo config {key} [--global] --reset # Reset config to default value
 --global                              # Affects all users (overrides user settings)
```

## Credentials Cache

The `Credentials Cache`, if enabled and active, allows to elevate several times from a parent process with only one UAC pop-up. After 5 minutes without elevations, the cache session closes automatically (Configurable timeout via `gsudo config CacheDuration`).

While this  very convenient, it's important to understand its potential security risks. Even if gsudo itself is secure, the inherent vulnerability lies in the host process. If your system is already compromised by a malicious process, it can manipulate the permitted process (e.g., Cmd/Powershell) and force an active gsudo cache instance to elevate privileges without triggering a UAC prompt.

This risk is the trade-off for using the Credentials Cache. The cache is safe to use as long as you are confident there are no malicious processes running on your system.

Here are the `Credentials Cache` Modes:
- `Explicit:` (default) Every elevation shows a UAC popup, unless a cache session is started manually...
  - To start or stop a cache session run: `gsudo cache {on | off}`
  - This is the default mode. (Use `gsudo config CacheMode Explicit` to revert to this value).
- `Auto:` Similar to unix-sudo. The first elevation shows a UAC popup and **starts a cache session automatically**.
  - Run `gsudo config CacheMode Auto` to use this mode.
- `Disabled:` Every elevation shows a UAC popup, and trying to start a cache session will throw an error..
  - Run `gsudo config CacheMode Disabled` to use this mode.

In any case, you can stop all cache sessions with `gsudo -k`.

[Learn more](https://gerardog.github.io/gsudo/docs/credentials-cache)

## Known issues

- The elevated instances do not have access to the network shares connected on the non-elevated space. This is not a `gsudo` issue but how Windows works. Use `--copyNS` to replicate Network Shares into the elevated session, but this is not bi-directional and is interactive (may prompt for user/password).

- `gsudo.exe` can be placed on a network share and invoked as `\\server\share\gsudo {command}` but doesn't work if your **current** folder is a network drive. For example do not map `\\server\share\` to `Z:` and then `Z:\>gsudo do-something`.

- Please report issues in the [Issues](https://github.com/gerardog/gsudo/issues) section.

## FAQ

- Why is it named `gsudo` instead of just `sudo`?

  When I created `gsudo`, there were other `sudo` packages on most Windows popular package managers such as `Chocolatey` and `Scoop`, so I had no other choice to pick another name. `gsudo` installers create an alias for `sudo`, so feel free to use `sudo` on your command line to invoke `gsudo`.

- Which dotnet version is built with?

  Versions prior to v1.3.0 used .NET 4.6 because it was included in every Windows 10/11 installation.

  From v1.4.0 up to v2.5.1, gsudo has been built using .net7.0 NativeAOT. This approach offers faster load times, reduced memory usage, and allows the tool to run on machines without any .NET runtime installed.

  Starting with v2.6.0, we've migrated to net9.0 due to the end-of-life of net7.0.

- Is `gsudo` a port of `*nix sudo`?

  No. `gsudo` reminds of the original sudo regarding user expectations. Many `sudo` features are `*nix` specific and could never have a `Windows` counterpart. Other features (such as `sudoers`) could potentially be implemented but are not at this point.

- What are the requirements? Does it work in Windows 7/8?

  It works on Win7 SP1 onwards. Some features may only work in Windows 10/11, like elevating as TrustedInstaller.

- How do I return to the previous security level after using gsudo?

  In the same way as you would with `Unix/Linux sudo`: `gsudo` does not alter the current process, instead it launches a new process with different permissions/integrity level. To go back to the previous level, just end the new process. For `Command Prompt` or `PowerShell` just type `exit`.

## Please support gsudo! 💵

- Please give us a star! ⭐
- Help spread the word by mentioning `gsudo` in social networks!
- [Sponsor or Donate](https://gerardog.github.io/gsudo/sponsor)

---

### Overview (`docs/README.md`)

# Website

This is the source code of gsudo documentation website.

The documentation is available at: https://gerardog.github.io/gsudo/

This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.

### Website Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

---

### Overview (`sample-scripts/readme.md`)

# gsudo Sample Scripts

This folder contains sample scripts demonstrating how to use `gsudo` to elevate privileges on a Windows machine. The provided scripts include:

1. **Script Self-Elevation:** A technique to ensure that the current script is running elevated, by detecting when it is not, and elevating itself. More details can be found in the [gsudo documentation on script self-elevation](https://gerardog.github.io/gsudo/docs/tips/script-self-elevation).

    - [`self-elevate.cmd`](./self-elevate.cmd): Batch script version
    - [`self-elevate-one-liner.cmd`](./self-elevate-one-liner.cmd): A one-liner version of the batch script.
    - [`self-elevate.ps1`](./self-elevate.ps1): PowerShell version.
    - [`self-elevate-without-gsudo.cmd`](./self-elevate-without-gsudo.cmd): Example without using `gsudo`.

2. **Many Elevations Using gsudo Cache:**

    - [`many-elevations-using-gsudo-cache.cmd`](./many-elevations-using-gsudo-cache.cmd): Batch script version
    - [`many-elevations-using-gsudo-cache.ps1`](./many-elevations-using-gsudo-cache.ps1): PowerShell version

3. **Don't show an UAC pop-up:** Perform an elevated admin task if and only if it can be done without an interactive UAC pop-up. (i.e. when already elevated or gsudo cache is active)
    - [`silent-elevation-one-liner.cmd`](./silent-elevation-one-liner.cmd): A one-liner version.
    - [`silent-elevation.cmd`](./silent-elevation.cmd): Verbose version .

These scripts are examples and should be used with caution. Always review and understand the code you are executing on your system.

---

### Overview (`build/Chocolatey/ReadMe.md`)

## Summary
How do I create packages? See https://chocolatey.org/docs/create-packages

If you are submitting packages to the community feed (https://chocolatey.org)
always try to ensure you have read, understood and adhere to the create
packages wiki link above.

## Automatic Packaging Updates?
Consider making this package an automatic package, for the best 
maintainability over time. Read up at https://chocolatey.org/docs/automatic-packages

## Shim Generation
Any executables you include in the package or download (but don't call 
install against using the built-in functions) will be automatically shimmed.

This means those executables will automatically be included on the path.
Shim generation runs whether the package is self-contained or uses automation 
scripts. 

By default, these are considered console applications.

If the application is a GUI, you should create an empty file next to the exe 
named 'name.exe.gui' e.g. 'bob.exe' would need a file named 'bob.exe.gui'.
See https://chocolatey.org/docs/create-packages#how-do-i-set-up-shims-for-applications-that-have-a-gui

If you want to ignore the executable, create an empty file next to the exe 
named 'name.exe.ignore' e.g. 'bob.exe' would need a file named 
'bob.exe.ignore'. 
See https://chocolatey.org/docs/create-packages#how-do-i-exclude-executables-from-getting-shims

## Self-Contained? 
If you have a self-contained package, you can remove the automation scripts 
entirely and just include the executables, they will automatically get shimmed, 
which puts them on the path. Ensure you have the legal right to distribute 
the application though. See https://chocolatey.org/docs/legal. 

You should read up on the Shim Generation section to familiarize yourself 
on what to do with GUI applications and/or ignoring shims.

## Automation Scripts
You have a powerful use of Chocolatey, as you are using PowerShell. So you
can do just about anything you need. Choco has some very handy built-in 
functions that you can use, these are sometimes called the helpers.

### Built-In Functions
https://chocolatey.org/docs/helpers-reference

A note about a couple:
* Get-BinRoot - this is a horribly named function that doesn't do what new folks think it does. It gets you the 'tools' root, which by default is set to 'c:\tools', not the chocolateyInstall bin folder - see https://chocolatey.org/docs/helpers-get-tools-location
* Install-BinFile - used for non-exe files - executables are automatically shimmed... - see https://chocolatey.org/docs/helpers-install-bin-file
* Uninstall-BinFile - used for non-exe files - executables are automatically shimmed - see https://chocolatey.org/docs/helpers-uninstall-bin-file

### Getting package specific information
Use the package parameters pattern - see https://chocolatey.org/docs/how-to-parse-package-parameters-argument

### Need to mount an ISO?
https://chocolatey.org/docs/how-to-mount-an-iso-in-chocolatey-package


### Environment Variables
Chocolatey makes a number of environment variables available (You can access any of these with $env:TheVariableNameBelow):

 * TEMP = Overridden to the CacheLocation, but may be the same as the original TEMP folder
 * ChocolateyInstall = Top level folder where Chocolatey is installed
 * chocolateyPackageName = The name of the package, equivalent to the id in the nuspec (0.9.9+)
 * chocolateyPackageVersion = The version of the package, equivalent to the version in the nuspec (0.9.9+)
 * chocolateyPackageFolder = The top level location of the package folder

#### Advanced Environment Variables
The following are more advanced settings:

 * chocolateyPackageParameters = (0.9.8.22+)
 * CHOCOLATEY_VERSION = The version of Choco you normally see. Use if you are 'lighting' things up based on choco version. (0.9.9+)
    - Otherwise take a dependency on the specific version you need. 
 * chocolateyForceX86 = If available and set to 'true', then user has requested 32bit version. (0.9.9+)
    - Automatically handled in built in Choco functions. 
 * OS_PLATFORM = Like Windows, OSX, Linux. (0.9.9+)
 * OS_VERSION = The version of OS, like 6.1 something something for Windows. (0.9.9+)
 * OS_NAME = The reported name of the OS. (0.9.9+)
 * IS_PROCESSELEVATED = Is the process elevated? (0.9.9+)
 
#### Experimental Environment Variables
The following are experimental or use not recommended:

 * OS_IS64BIT = This may not return correctly - it may depend on the process the app is running under (0.9.9+)
 * CHOCOLATEY_VERSION_PRODUCT = the version of Choco that may match CHOCOLATEY_VERSION but may be different (0.9.9+)
    - it's based on git describe
 * IS_ADMIN = Is the user an administrator? But doesn't tell you if the process is elevated. (0.9.9+)
 * chocolateyInstallOverride = Not for use in package automation scripts. (0.9.9+)
 * chocolateyInstallArguments = the installer arguments meant for the native installer. You should use chocolateyPackageParameters instead. (0.9.9+)

---

### Docs Intro (`docs/docs/intro.md`)

---
sidebar_position: 1
hide_title: true
title: Introduction
---
## Introduction

**gsudo** is a `sudo` equivalent for Windows, with a similar user-experience as the original *nix sudo.

It allows to run commands with elevated permissions, or to elevate the current shell, in the current console window or a new one.

Just prepend `gsudo` (or the `sudo` alias) to your command and it will run elevated. One UAC popup will appear each time. You can see less popups if you enable [gsudo cache](credentials-cache).

It is designed so it is easy to install, easy to use, and feels familiar with other popular tools.

:::info
`gsudo` allows you to easily cherry-pick which commands to elevate, and save time by not switching context between elevated and non-elevated windows.
:::

### Features

- It is a proper `sudo for windows`:
  - Executes the desired command with elevated permissions (or as another user).
  - Elevated commands are shown in the current user-level console. No new window. (Unless you specify `-n`)
  - Full console support: Colors, full keyboard, auto-completion, etc.
  - Supports I/O redirection.
  - Handles Ctrl-C properly
  - Supports worldwide encodings & codepages
- Uses the current shell to interpret the command to elevate:
  - `gsudo {command}` uses a new instance of the invoking shell to elevate the command.  
    For example, in PowerShell `gsudo mkdir x` becames `pwsh -c "mkdir x"`, while in CMD it becames `cmd /c "mkdir x"`.
  - Supported Shells:
    - [CMD](usage)
    - [PowerShell](usage/powershell)
    - [WSL](usage/wsl)
    - [Bash for Windows (MSYS2 / MinGW / Git-Bash / Cygwin)](usage/bash-for-windows)
    - Yori
    - Take Command
    - NuShell
- If no command is specified, it starts an elevated shell. 
- [Credentials cache](credentials-cache): `gsudo` can elevate many times showing only one UAC pop-up if the user opts-in to enable the cache.
- Supports being used on scripts:
  - Returns the command exit code (`%errorlevel%`). If `gsudo` fails to elevate, the exit code will be 999.
  - If `gsudo` is invoked from an already elevated console, it will run the command as-is (won't throw error). So, don't worry if you run `gsudo` or a script that uses `gsudo` when already elevated. (No elevation is required, no UAC popup)
  
- Use `gsudo !!` to elevate the last ran command. Works on CMD, Git-Bash, MinGW, MSYS2, Cygwin (and PowerShell with [gsudo module](usage/powershell#powershell-profile-config) only)
  
Read [How to Use](usage) for your favorite shell to see additional features.

### Demo

[](../../demo.gif)

---

### Blog 2022 08 21 Dotnet7 Index (`docs/blog/2022-08-21-dotnet7/index.md`)

---
slug: gsudo-dotnet-7
title: Migrating gsudo to .NET 7
authors: [gerardog]
tags: []
---


The first gsudo versions were made in 2019, around the release of .NET Core 3. I tried to figure out how .NET Core's redistribution model worked, but it didn't worked for me. One should either redistribute the full runtime, or ask the user to manually download and install it. There was another option: to build a self-contained app (with runtime embedded) but that increased the output size by more than 80mb!



The alternative was to target .NET Framework v4.6. This version is bundled with every Windows 10/11. When targeting it, gsudo build output size was around 100kb. The app on v4.6 loaded faster, so targeting v4.6 seemed logical. It was small, fast, and the installation didn't required any big runtime redistribution or additional steps.

Recently, things have changed a little with [.NET 7 Preview 3 announcement](https://devblogs.microsoft.com/dotnet/announcing-dotnet-7-preview-3/#faster-lighter-apps-with-native-aot) and NativeAOT: "Publishing your app as native AOT produces an app that is self-contained and that has been ahead-of-time (AOT) compiled to native code. Native AOT apps start up very quickly and use less memory. Users of the application can run it on a machine that doesn't have the .NET runtime installed."

I'm almost sold! Let's try it out... *(sounds of frenetic typing)*... Ok, that was [18 files changed](https://github.com/gerardog/gsudo/compare/971ea97c...7c0c1b71). Now I have a multi-target project that can compile for v4.6 or v7. Not bad. 

But not everyone's cup of tea: NativeAOT builds for each specific platform, so instead of having one AnyCPU build, now I have two (x64 and x86). But also, NativeAOT is only supported on x64. The closest for x86 is a self-contained build with Ready2Run.

Let's do some test the performance. So first let´s build for each platform:

``` powershell
# Build .NET Framework v4.6
msbuild /t:Restore /p:RestorePackagesConfig=true src\gsudo.sln /v:Minimal /p:TargetFrameworkVersion=v4.6
msbuild /t:Rebuild /p:Configuration=Release src\gsudo\gsudo.csproj /v:Minimal /p:WarningLevel=0 /p:TargetFrameworkVersion=v4.6
# Build .NET 7.0 x64 build with NativeAOT
dotnet clean .\src\gsudo\gsudo.csproj -f net7.0 | Out-null
dotnet publish .\src\gsudo\gsudo.csproj -c Release -f net7.0 -r win-x64 --sc -p:PublishAot=true -p:IlcOptimizationPreference=Size -v minimal -p:WarningLevel=0
# Build .NET 7.0 x86 build with Ready2Run
dotnet clean .\src\gsudo\gsudo.csproj -f net7.0 -r win-x86 | Out-null
dotnet publish .\src\gsudo\gsudo.csproj -c Release -f net7.0 -r win-x86 --sc -p:PublishReadyToRun=true -p:PublishSingleFile=true -v minimal -p:WarningLevel=0
```

Now let´s meassure 100 elevations using a preexisting credentials cache. I am using `gsudo -d` to force an elevation using `cmd.exe`, which loads much faster and predictable than `Powershell`. Then I repeated the tests with each different build.

``` powershell
$gsudo="C:\git\gsudo\src\gsudo\bin\net46\gsudo.exe"
& $gsudo cache on | out-null 	# start a cache session.
& $gsudo -d dir | out-null		# test the cache session.
Measure-Command { 1..100 | % { & $gsudo -d dir} } | select -Property TotalSeconds | Format-List
& $gsudo -k | out-null 			# close cache.
```

The first results were absurd. I found out Windows Defender takes extra time to verify unsigned apps in the cloud. So I disabled Defender and started over.

|                                 | v1.3.0 (Net 4.6 + ilmerge + CodeSigned) | Latest (Net 4.6 unsigned) | Net 7.0 x64 NativeAOT (unsigned) | Net 7.0 x86 Ready2Run (unsigned) |
| ------------------------------- | --------------------------------------- | ------------------------- | -------------------------------- | -------------------------------- |
| Size                            | 180.5 KB                                | 208.5 KB                  | 6.17 MB                          | 16.89 MB                         |
| Time to elevate 100 times (sum) | 12.75 s                                 | 12.62 s                   | 7.83 s                           | 10.94 s                          |
| Performance improvement         | (baseline)                              | 1.04%                     | 38.62%                           | 14.18%                           |

Wow! An improvement of 38.62% is significant enough to ignore the fact that the file size has increased 6 MB, or almost 30 times. 

## Should gsudo target .NET 7.0?

The problem is that the installer should provide for all platforms, and so far I´ve only focused on x64. What options do I have?

- I could fall back to Net 4.6 (targeting AnyCPU) for the remaining platforms. The down-side would be different prerequisites for each scenario. But the installer would only grow 6mb.
- Or include x86 Net 7.0 Read2Run version. It´s faster, but takes 16mb. The setup including both would  take 23 MB (actually 10mb when compressed)!  

## Current situation

Right now my code-signing certificate is expired. Once I´ve got a new certificate, I will be making a test release. I will update this post then.

---

### Blog Authors.Yml (`docs/blog/authors.yml`)

gerardog:
  name: Gerardo Grignoli
# title: gsudo Creator
  url: https://github.com/gerardog
  image_url: https://avatars.githubusercontent.com/u/3901474?s=96&v=4

---

### Docs Credentials Cache (`docs/docs/credentials-cache.md`)

---
sidebar_position: 4
title: Credentials Cache
#hide_title: true
---

## Introduction

The `Credentials Cache` is an optional feature that allows to elevate several times from a parent process with only one UAC pop-up.  

An active credentials cache session is just an elevated instance of gsudo that stays running and allows the invoker process to elevate again. No windows service or setup involved.

It is convenient, but it's safe only if you are not already hosting a malicious process: No matter how secure gsudo itself is, a malicious process could [trick](https://en.wikipedia.org/wiki/DLL_injection#Approaches_on_Microsoft_Windows) the allowed process (Cmd/Powershell) and force a running `gsudo` cache instance to elevate silently.

## Cache Modes

The cache mode can be set with **`gsudo config CacheMode auto|explicit|disabled`**

- **Explicit: (default)** Every elevation shows a UAC popup, unless a cache session is started explicitly with `gsudo cache on`.

```powershell
gsudo config CacheMode Explicit # This is optional since Explicit is the default.

gsudo command1 # 1st UAC Popup shown
gsudo command2 # 2nd UAC Popup shown
gsudo cache on # 3rd UAC Popup shown, cache session started
gsudo command3 # Elevation without popup 
gsudo command4 # Elevation without popup 
gsudo cache off # (or gsudo -k) Ends the cache session. Next elevation will show a UAC popup.
```

- **Auto:** Simil-unix-sudo. The first elevation shows a UAC Popup and starts a cache session automatically.

```powershell
gsudo config CacheMode Auto # Only need to run once, this setting is persistent.

gsudo command1 # 1st UAC Popup shown, cache session started
gsudo command2 # Elevation without popup
gsudo command3 # Elevation without popup 
gsudo cache off # (or gsudo -k) Ends the cache session. Next elevation will show a UAC popup.
```

- **Disabled:** Every elevation request shows a UAC popup. Attempts to start a Cache Session throws error.

---

Use `gsudo cache on|off` to start/stop a cache session manually (i.e. allow/disallow elevation of the current process with no additional UAC popups).

Use `gsudo -k` to terminate all cache sessions. (Use this before leaving your computer unattended to someone else.)

The cache session ends automatically when the allowed process ends or if no elevations requests are received for 5 minutes (configurable via `gsudo config CacheDuration`).

## Usage

- `gsudo cache [-h]`              Shows cache help
- `gsudo cache {on | off} [-p {pid}] [-d {time}]`   Start/stop a gsudo cache session.

  - `-p | --pid {pid}`            Specify which process can use the cache. (Use 0 for any, Default=`caller pid`)
  - `-d | --duration {hh:mm:ss}`  Max time the cache can stay idle before closing.
    - Use '-1' to keep open until logoff (or until `cache off`, or `-k`).
    - The default is `CacheDuration` is 5 minutes.

---

### Docs Gsudo Vs Sudo (`docs/docs/gsudo-vs-sudo.md`)

---
sidebar_position: 7
title: Comparison with Microsoft sudo
#hide_title: true
---

# Comparison between gsudo and Microsoft sudo

`gsudo` was born in 2019 as a productivity tool and is open-source. It has been downloaded over 700k times so far and has enjoyed a warm reception from users. It is very easy to install and works from Windows 7 SP1 up to Windows 11.

Microsoft initially declined to create a similar tool, citing security concerns. However `gsudo`'s documentation [challenged this view](security.md) arguing that absolute security is unattainable without altering Windows itself, and that the default same-desktop UAC is not completely secure either.

In February 2024, Microsoft reversed its stance and released [Sudo for Windows](https://devblogs.microsoft.com/commandline/introducing-sudo-for-windows/).

Surprisingly, Microsoft's sudo does not leverage new OS features to enhance security. Its mechanisms are akin to `gsudo`, making their security models comparable. The question of which one is more secure depends on which version of each are you comparing, and how many open bugs it has. The initial release of Microsoft's sudo presented some [critical issues](https://www.tiraniddo.dev/2024/02/sudo-on-windows-quick-rundown.html) that they will hopefully address very soon. `gsudo` has fixed similar issues in the past and may in the future.

## Sudo Tools Feature Comparison

### Is it a proper Sudo tool?
| Feature | `gsudo` | Sudo for Windows |
| ------- | ------- | ------------------ |
| Executes command with elevated permissions | Yes | Yes |
| Supports output redirection (`sudo dir > file.txt`) | Yes | Yes |
| Supports input redirection (`echo md SomeFolder \| sudo cmd`) | Yes | Yes |
| Returns the command exit code | Yes | Yes |
| Preserves the current directory | Yes | Yes, except in new-window mode! ⚠️ [Learn More](https://github.com/microsoft/sudo/issues/63) |
| Source code available | [Yes](https://github.com/gerardog/gsudo) | [Yes](https://github.com/microsoft/sudo) |
| Works with Win11 [`Administration Protection`](https://techcommunity.microsoft.com/blog/microsoft-security-blog/evolving-the-windows-user-model-%E2%80%93-introducing-administrator-protection/4370453) | Yes | No |

### Security Impersonation Features

| Feature | `gsudo` | Sudo for Windows |
| ------- | ------- | ------------------ |
| Run with custom Integrity | Yes  (`-i`, `--integrity`) | No |
| Run as System  | Yes (`-s`, `--system`) | No |
| Run as TrustedInstaller  | Yes (`--ti`)| No |
| Run as user  | Yes (`-u user`) | No |

### User Experience

| Feature | `gsudo` | Sudo for Windows |
| ------- | ------- | ------------------ |
| Easy to install and update | Yes (winget, choco, scoop) | No (Windows Insider build required) |
| See less UAC Pop-ups | Yes ([Credentials Cache](credentials-cache.md)) | No |
| Elevate current shell | Yes | No |
| Elevate commands using current shell | Yes | No |
| Red # indicator for elevation on CMD | Yes | No |

### Additional Features

| Feature | `gsudo` | Sudo for Windows |
| ------- | ------- | ------------------ |
| Run in new window | Yes | Yes |
| Option to keep new window open until a key is pressed | [Yes](tips/elevation-in-new-window.md) | No |
| Option to keep new window's shell open | [Yes](tips/elevation-in-new-window.md) | No |
| Run with Input Disabled | [Yes](https://gerardog.github.io/gsudo/docs/security#what-are-the-risks-of-running-gsudo) | Yes |
| Elevate last command with `sudo !!` | Yes | No |

### PowerShell

| Feature | `gsudo` | Sudo for Windows |
| ------- | ------- | ------------------ |
| Elevation syntax | `gsudo { scriptblock } -args $a,$b` [syntax](usage/powershell.md#using-gsudo-scriptblock-syntax) | `sudo pwsh { scriptblock } -args $a,$b` (Unofficial!) |
| Auto-complete of last 3 commands | Yes (with [gsudoModule](usage/powershell.md#powershell-profile-config)) | No |
| Auto-complete of command line arguments | Yes (with [gsudoModule](usage/powershell.md#powershell-profile-config)) | No |
| Red # indicator for elevation | Yes (with [gsudoModule](usage/powershell.md#powershell-profile-config)) | No |

## What if I install both?

If you have both Microsoft Sudo and `gsudo` installed, they both should work independently.

**The `sudo` keyword will run Microsoft's sudo instead of `gsudo`** because the typical install of `Sudo for Windows` puts it in `c:\Windows\System32\sudo.exe`. This folder appears first in the `PATH` environment variable, therefore when running `sudo`, the Microsoft `sudo.exe` will take precedence over gsudo's `sudo` alias.

**To change this behavior and make `sudo` point to `gsudo`** you can
call `gsudo config PathPrecedence true` and restart all your consoles to apply the change. Setting it back to `false` will revert to the normal behavior.

Additionally, gsudo now supports Microsoft sudo styled arguments such as `--inline`, `--disable-input`, `--preserve-env`, `--new-window`, and `-D` / `--chdir {directory}`, ensuring a smoother transition for users familiar with Microsoft sudo.

---

### Docs How It Works (`docs/docs/how-it-works.md`)

---
sidebar_position: 6
title: How it works
hide_title: true
---

## How does it work internally?

When gsudo is invoked, an elevated instance of `gsudo` in `service mode` is launched (with `Verb='RunAs'`). The service will allow one elevation (or many if the `credentials cache` is enabled).

## Elevation modes

To achieve the `sudo` functionality, `gsudo` has 4 different mechanisms implemented.

In a way, each one superseded the previous one, leading to the current default `TokenSwitch`.

In the source code, each mode is implemented as one `IProcessRenderer` (running non-elevated) and a `IProcessHost` (running in the elevated service).

Communication between both is done via two Named Pipes in the `ProtectedPrefix\Administrators` namespace. One for data and another for control. Each elevation mode defines the "communication protocol", what is sent thru each pipe.

These are the elevations modes implemented in `gsudo`, in the order they were implemented:

### Piped mode

This is a naive mechanism, implemented first more like a proof of concept (that later proved to be useful).

The elevated `PipedProcessHost` runs the command with its I/O redirected (For example as in `(input) > Elevated Process > (output)`), and sends all I/O to the unelevated via named pipes. 

The `PipedProcessRenderer` captures input and display the output on screen. In this mode, keyboard input is managed by the client console (without knowledge of which app you are running), and not by the elevated command/shell, hence <kbd>TAB</kbd> key auto-completion doesn't work. The user experience is far from ideal.

The process is created with the elevated Environment Variables.

Pros: 

- Redirection works

Cons:

- Apps always run in redirected mode.
- Input only support of chars, not key presses.
- Struggles with encoding, especially explicit code page changes.

### VT mode (PseudoConsole)

:::info Side story
It was the day Microsoft [announced Pseudo Consoles for Windows](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/), I asked myself: What can PseudoConsoles be used for? a sudo for windows!!
:::

The elevated instance runs a VT PseudoConsole, and sends all I/O it to the unelevated via named pipes.

The process is created with the elevated Environment Variables.

Pros:

- Full featured console screen
- Full input support.

Cons:

- Good but not best performance (compared with the following alternatives).
- Apps always runs in console mode (not redirected). Redirection could be done but the result would be more like console screen recording than process redirection.
- Struggles with encoding IF encoding or code page changes.
- Console screen resizing still not implemented.

### Attached mode

The elevated window ['attaches'](https://docs.microsoft.com/en-us/windows/console/attachconsole) to the non-elevated. The bridge is actually done by Windows and ConHost. Doesn't work with I/O redirected.

The process is created with the elevated Environment Variables.

Pros:

- Native console functioning. Full speed, colors, input, etc.
- No encoding issues
  
Cons:

- Does not support redirection

### TokenSwitch Mode

This is the current default mode. Using undocumented `kernel32` Apis, the unelevated instance creates the new process in paused mode, then the elevated host replaces it's primary token, and its execution is resumed.

The process is created with the **non-elevated** context/Environment Variables.

Pros:

- Native console functioning. Full speed, colors, input, etc.
- No encoding issues
- Supports redirection
  
Cons:

- (debatable) The new process inherits the non-elevated environment variables.

This last item is a confirmed problem when the elevation is done as somebody else (i.e. the current user is not admin and `RunAs` asks for credentials). To avoid it, and only in this scenario, this mode falls back to Attached mode (if no redirection) or Piped mode (if redirection exists).

## Should the elevated process inherit the same environment variables?

Great question. If your user is a local admin, i.e. you elevate as yourself, both contexts have similar if not same env vars.

But if you are not local admin, UAC will prompt for credentials, and then you will be running as another user, so env var isolation becomes more important. On Linux/Unix, you always `sudo` as somebody else and env vars are not preserved, unless `-E` is specified. `gsudo` provides `--copyEV` to copy all the vars, except %USERNAME%.

## How do I force one mode over the other?

You shouldn't. `gsudo` should do a better job choosing than you. Still reading? Ok... I will tell you. But this is marked as deprecated and can change anytime.

To force Attached mode use `--attached` or permanently with `gsudo config ForceAttachedConsole True`

To force Piped mode use `--piped` or permanently with `gsudo config ForcePipedConsole True`

To force VT mode use `--vt` or permanently with `gsudo config ForceVTConsole True`

Use only one at the same time.

---

### Docs Install (`docs/docs/install.md`)

---
hide_title: true 
title: How to Install
sidebar_position: 2
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## How to Install gsudo

<Tabs>
<TabItem value="W10" label="On Windows 10/11" default>

If you use any of the following Package Managers:

- Using [WinGet](https://github.com/microsoft/winget-cli/releases): Run `winget install gerardog.gsudo`
- Using [Chocolatey](https://chocolatey.org/install): Run  `choco install gsudo`
- Using [Scoop](https://scoop.sh): Run `scoop install gsudo`

Or:

- Download and run the `MSI` file from the [latest release](https://github.com/gerardog/gsudo/releases/latest).
- Or use the following script to achieve the same:  
  ```powershell
  PowerShell -Command "Set-ExecutionPolicy RemoteSigned -scope Process; [Net.ServicePointManager]::SecurityProtocol = 'Tls12'; iwr -useb https://raw.githubusercontent.com/gerardog/gsudo/master/installgsudo.ps1 | iex"
  ```
- Manually: Download the `ZIP` file from the [latest release](https://github.com/gerardog/gsudo/releases/latest). Uncompress and add to `PATH`.

</TabItem>
<TabItem value="W8" label="Windows 8.1">

- Download `gsudo.Setup.[platform].msi` from the [latest release](https://github.com/gerardog/gsudo/releases/latest), and run.

</TabItem>
<TabItem value="W7" label="Windows 7 SP1">

- Enable TLS 1.2 using [Microsoft "Easy Fix"](https://support.microsoft.com/en-us/topic/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-winhttp-in-windows-c4bd73d2-31d7-761e-0178-11268bb10392#bkmk_easy)
- Download `gsudo.Setup.[platform].msi` from the [latest release](https://github.com/gerardog/gsudo/releases/latest), and run.
- You probably want to update PowerShell up to 5.1

</TabItem>
</Tabs>

---

:::caution
Please restart your consoles after installing, to refresh the `PATH` environment variable.
:::


:::info
`gsudo` is just a portable console app. No Windows service is required or system change is done, except adding gsudo to the `PATH`.
:::


## Configure your Shell

On the following shells you get a better experience if you follow some manual configuration:

- [PowerShell](usage/powershell#powershell-profile-config)
- [Bash for Windows (MinGW / MSYS2 / Git-Bash / Cygwin)](usage/bash-for-windows#bash-profile-config)

---

### Docs Security (`docs/docs/security.md`)

---
sidebar_position: 5
title: Security Considerations
hide_title: true
---

## Why doesn't Windows have a `sudo` command? Should it have one?

To answer this question, we first have to take a look back at the history.

In August 2002, Chris Paget released a white paper describing a form of attack against event-driven systems that he termed Shatter Attack. It allowed processes in the same session to bypass security restrictions by abusing Windows Message loop.

Microsoft's response was to add "User Interface Privilege Isolation" (UIPI) and the "User Access Control" (UAC) popup to the next major release: Windows Vista. Privileged processes would then run "elevated" at high integrity level, out of reach of processes at lower, non-admin, levels.

I assume that at this point, Microsoft decided not to make a `sudo` tool for windows. It would be an unwanted bridge between two worlds that intended to isolate.

However, that insulation quickly proved to be weak. Let me [quote Raymond Chen from Microsoft](https://devblogs.microsoft.com/oldnewthing/20160816-00/?p=94105):

> There’s a setting that lets you specify how often you want to be prompted by UAC. You can set any of four levels:
>
> - Always notify
> - Notify only when apps try to change settings, use the secure desktop `(Default mode)`
> - Notify only when apps try to change settings, don’t use the secure desktop
> - Never notify
>
> Although it looks like there are four settings, in a theoretical sense, there really are only two settings.
>
> - Always notify
> - Meh
>
> The reason why all the other options collapse into Meh is that the `Notify only when apps try to change settings` option can be subverted by any app simply by injecting a thread (... a hacking technique explained ...)

And, up to this day, Windows 10 & 11, defaults corresponds to that "Meh". Microsoft's default stance is user convenience at the expense of lesser security.

---

[Windows 11 UAC Settings: Default mode is recommended only if you **don't** run untrusted software.]

---

Over time, more than a hundred UAC-bypass techniques have been disclosed. Many of them still work in an updated Windows 11. It is Windows Defender, or your antivirus of choice, who may stop them (hopefully). But if you disable your AV, UAC bypass is easy.

And Microsoft can't just patch them all without loosing 'convenience' features. They instead, they assumed publicly that `UAC/UIPI` in default mode is not a security boundary. I will [quote Microsoft documentation](https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-user-account-control#:~:text=More%20important%2C%20Same%2Ddesktop%20Elevation,be%20considered%20a%20convenience%20feature.) :

> Same-desktop Elevation in UAC isn't a security boundary. It can be hijacked by unprivileged software that runs on the same desktop. Same-desktop Elevation should be considered a convenience feature.

Which to me, it means: <b>UAC is a convenience tool. It does not protect you from threats, it works as a warning that protects you from shooting yourself in the foot.</b>

And if UAC is a convenience tool, in my opinion it's not doing the best possible job:

- You waste important time by switching between elevated and unelevated windows. You must manually carry your command and context to the elevated window, each time, back and forth.
- ... or you suffer from "elevation fatigue". For example, you elevate a whole console beforehand, and you do all your stuff there, likely running non-admin or untrusted stuff as admin.

**In conclusion:**

- Same-desktop UAC is a vulnerable convenience feature.
- `gsudo` is also a vulnerable convenience feature.
- Whether you use `gsudo` or not, **the only thing that protects you from malware is not UAC, it is you and your Antivirus.**.

So, if you decide to use `gsudo`, here are the risks:

## What are the risks of running gsudo?

gsudo could be used as an attack vector for escalation of privileges. Using antivirus software and avoiding running untrusted software

- **Abusing an elevation made with gsudo:**
  
  A medium integrity process could drive the gsudo-elevated process.
  
  When gsudo elevates **in the same console**, it creates a connection between a medium and a high integrity process. A malicious process (at medium integrity) can then drive the medium integrity console: sending keystrokes to the high integrity app, or scrapping its screen.
  
  In my opinion, this is a mild risk that you are already exposed when using UAC in default mode. In the end, your only protection is your AV.

  Ways to avoid this risk:
  - Elevating on a new console either per-command (using `-n`/`--new`) or force it using [config setting `NewWindow.Force`](tips/elevation-in-new-window.md).
  - Experimental setting `SecurityEnforceUacIsolation`:
  makes the elevated command run redirected, w/input redirected to `NULL`. Hence it will be non-interactive, so nobody will be able to drive it. Enable with `gsudo config SecurityEnforceUacIsolation true`

- **Abusing an active `gsudo's Credentials Cache` to elevate a process silently**:

   The `Credentials Cache` allows many elevations with only one UAC popup. But there is a reason why the cache is disabled by default.

   When the cache is active, it allows elevation from one invoker process and its children, which are running at the unprotected medium integrity level. A malicious process also at medium level can inject it's code into an allowed process and make it call gsudo to request elevation silently.

   You avoid this risk by default, by not enabling the credentials cache.

---

### Docs Troubleshooting (`docs/docs/troubleshooting.md`)

---
sidebar_position: 10
hide_title: true
title: Troubleshooting
---

## Troubleshooting

- After installation / upgrade. Please close your consoles and open new ones.
    - Same with error `Unauthorized. (Different gsudo.exe?)`. 

- Be sure you have [configured your shell](install#configure-your-shell)

- Use `gsudo --debug {command}` to see internal debug info.

- Search [gsudo GitHub issues](https://github.com/gerardog/gsudo/issues?q=) or create a new one if you have identified a problem.

- Chat on [gitter](https://gitter.im/gsudo/)
- Chat on [Discord](https://discord.com/invite/dEEA3P5WqF)

## Known issues

- Do not install PowerShell as a .Net global tool (i.e. with `dotnet tool install --global PowerShell`), because it uses a shim tool with [unfixed issues](https://github.com/PowerShell/PowerShell/issues/11747). Install with any [other official method](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) instead, or with `choco install pwsh`, `winget install Microsoft.PowerShell`.

- The elevated instances do not have access to the network shares connected on the non-elevated space. This is not a `gsudo` issue but how Windows works. Use `--copyNS` to replicate Network Shares into the elevated session, but this is not bi-directional and it's interactive (may prompt for user/password).

- `gsudo.exe` can be placed on a network share and invoked as `\\server\share\gsudo {command}` but doesn't work if your **current** folder is a network drive. For example do not map `\\server\share\` to `Z:` and then `Z:\>gsudo do-something`.

---

### Docs Tips  Category .Json (`docs/docs/tips/_category_.json`)

{
    "label": "Tips & Hacks",
    "position": 6
  }

---

### Docs Tips Elevation In New Window (`docs/docs/tips/elevation-in-new-window.md`)

---
#sidebar_position: 6
title: Force elevation in new window
#hide_title: true
---

As mentioned in [Security Considerations](../security.md#what-are-the-risks-of-running-gsudo), elevation in the same console exposes a mild risk. You can avoid it altogether by elevating in a new console window, for example by adding the `--new` or `-n` switch.

In gsudo v2, a new setting was introduced to force elevations in a new window. To enable it simply run:

``` powershell
gsudo config NewWindow.Force true
```

The problem with this approach is that some elevations complete too quickly and the new window may close abruptly. So to leave time to verify the window result combine it with one of the following new switches:

- `--KeepWindow`: After running a command in a new console, ask for keypress before closing the console/window.
- `--KeepShell`: After running a command, keep the elevated shell open.

You set one of those switches permanently by using the following setting:

``` powershell
gsudo config NewWindow.CloseBehaviour [ KeepShellOpen | PressKeyToClose | OsDefault ]
```

Valid values are:
  - **KeepShellOpen**: Forces `--keepShell`. Keep the elevated shell open after running the command.
  

  - **PressKeyToClose**: Forces `--keepWindow`. Asks for a keypress before closing the window.  
  

  - **OsDefault**: (default) Launch the command and let the operating system close it or keep it according to the system defaults (typically the window will close).

---

### Docs Tips Mixed Elevation In Windows Terminal (`docs/docs/tips/mixed-elevation-in-windows-terminal.md`)

---
sidebar_position: 1
#id: usage
title: Windows Terminal
hide_title: true
---

## Mixed Elevation of tabs

You can have an elevated tab inside `Windows Terminal` using gsudo. Just add a new profile (or edit an existing one), edit your command and prepend `gsudo `. Or just put `gsudo cmd` or `gsudo pwsh` as your command.

However, I personally prefer to not do this and use the following alternative.

## Elevate on demand

Use gsudo's ability to elevate the current shell in the current window. Just run `gsudo` and it will invoke caller shell (CMD, PowerShell, etc) elevated. Or even better, prepend `gsudo` to elevate specific commands.

---

### Docs Tips Script Self Elevation (`docs/docs/tips/script-self-elevation.md`)

---
sidebar_position: 1
#id: usage
title: Scripts Self-Elevation
hide_title: true
---

## Self Elevate Script

You may want to create a script that always runs elevated. The following scripts will detect if the session is not elevated and then call themselves using gsudo.

Prefer using `gsudo status` to test if the session is elevated, as alternatives such as `whoami` vary depending on the OS language, and `net session` may fail when the network is down.

- Cmd Batch file, long version: (e.g. `self-elevate.bat`) [link](https://github.com/gerardog/gsudo/tree/master/sample-scripts/self-elevate.cmd)

  ``` batch
  @echo off
  gsudo status IsElevated --no-output && goto :IsElevated

  echo Admin rights needed. Elevating using gsudo.
  gsudo "%~f0" %*
  if errorlevel 999 Echo Failed to elevate!
  exit /b %errorlevel%

  :IsElevated
  :: You are elevated here. Do admin stuff.
  ```

- One-Line version: [link](https://github.com/gerardog/gsudo/tree/master/sample-scripts/self-elevate-one-liner.cmd)

  ``` batch
  @gsudo status IsElevated --no-output || (gsudo "%~f0" & exit /b)
  :: You are elevated here. Do admin stuff.
  ```

- PowerShell: (e.g. `self-elevate.ps1`) [link](https://github.com/gerardog/gsudo/tree/master/sample-scripts/self-elevate.ps1)

  ```powershell
  function Test-IsElevated {
    return (New-Object Security.Principal.WindowsPrincipal(
      [Security.Principal.WindowsIdentity]::GetCurrent()))
      .IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
  }

  if ((Test-IsElevated) -eq $false) {
    Write-Warning "This script requires local admin privileges. Elevating..."
    gsudo "& '$($MyInvocation.MyCommand.Source)'" $args
    if ($LastExitCode -eq 999 ) {
      Write-error 'Failed to elevate.'
    }
    return
  }

  # You are elevated. Do admin stuff here.
  ```

  If you don't have gsudo installed, you can still self-elevate but in a new console window: [link](https://github.com/gerardog/gsudo/tree/master/sample-scripts/self-elevate-without-gsudo.cmd)

  ``` batch
  @echo off
  :: This script performs self-elevation, in a new console using only built-in windows tools.
  :: Detect elevation using 'net session', jump to :ElevatedTasks if we are admin.
  net session >nul 2>nul & net session >nul 2>nul && goto :ElevatedTasks
  echo Admin rights needed. Elevating using powershell...

  :: This powershell command re-executes this script in a new elevated console
  powershell -C start-Process "%~f0" -Verb RunAs -ArgumentList \"%* \""
  IF ERRORLEVEL 1 Echo Elevation failed!
  exit /b

  :ElevatedTasks
  :: You are elevated here. Add your admin tasks here.
  :: This will run as admin ::
  ```

## Detect if running elevated

- PowerShell-native method:

  ``` powershell
  function Test-IsElevated {
    return (New-Object Security.Principal.WindowsPrincipal(
      [Security.Principal.WindowsIdentity]::GetCurrent()))
      .IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
  }
  ```

Even when this code **looks like** it will check if the current user is member of the local admins group (regardless of current elevation status), instead it just returns `$true` if elevated.

- PowerShell gsudo method:

  ``` PowerShell
  $IsElevated = 'true' -eq (gsudo status IsElevated)
  ```

- Cmd Batch:

  ``` batch
  gsudo status IsElevated --no-output 
  if errorlevel 0 echo Current Process Is Not Elevated
  if errorlevel 1 echo Current Process Is Elevated
  ```

## Detect if current user is member of admins group (regardless of current elevation status)

If you want to know if the current user can elevate with a UAC popup but without entering other user credentials, you need to check if the user is a member of S-1-5-32-544 (a.k.a. BUILTIN\Administrators for english OS).

- Batch with gsudo:

  ``` batch
  gsudo status IsAdminMember --no-output 
  if errorlevel 1 goto IsAdminMember
  ```

- Batch without gsudo:

  ``` batch
  whoami /groups | findstr S-1-5-32-544 > nul
  if errorlevel 1 goto IsAdmin
  echo Not Admin
  exit /b
  :IsAdmin
  echo Current user is a member of the Local Admins group. But we don't know if this session is elevated.
  ```

- PowerShell Native

  ``` powershell
  function Test-IsMemberOfLocalAdminsGroup {
  ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Claims.Value -contains "S-1-5-32-544"
  }
  ```

- PowerShell with gsudo

  ``` PowerShell
  $IsAdminMember = 'true' -eq (gsudo status IsAdminMember)
  ```

---

### Docs Usage  Category .Json (`docs/docs/usage/_category_.json`)

{
    "label": "How to Use",
    "position": 3
  }

---

### Docs Usage Mingw Msys2 (`docs/docs/usage/mingw-msys2.md`)

---
id: bash-for-windows
sidebar_position: 4
hide_title: true
title: Usage from Bash for Windows
---
## Usage from Bash for Windows (MinGW / MSYS2 / Git-Bash / Cygwin)

Prepend `gsudo` to elevate `bash` commands (unless `-d` is used to elevate CMD commands). 

## Bash Profile Config

There is an issue with `bash for windows` shells: The process tree is split when invoking `bash` scripts such as the `gsudo` wrapper, that invalidates the Credentials Cache.
You need to add this function to your `.bashrc` profile (to skip the wrapper):

```bash
gsudo() { WSLENV=WSL_DISTRO_NAME:USER:$WSLENV MSYS_NO_PATHCONV=1 gsudo.exe "$@"; }
```

It looks like I missed a semi-colon `;` but I didn't.

---

### Docs Usage Powershell (`docs/docs/usage/powershell.md`)

---
sidebar_position: 0
hide_title: true
title: Usage from PowerShell
---
## Usage from PowerShell

:::caution

If you installed `PowerShell Core` as a `dotnet global tool` [you will have issues](https://github.com/PowerShell/PowerShell/issues/11747). 

You can check by running `dotnet tool list --global`. If so, uninstall and use any another installation method such as: `winget install Microsoft.PowerShell` / `choco install pwsh` / [Download from GitHub](https://github.com/PowerShell/PowerShell/releases/latest) / [Microsoft Store](https://apps.microsoft.com/store/detail/powershell/9MZ1SNWT0N5D)

:::

When the current shell is `PowerShell`, gsudo can be used in the following ways:

- Call `gsudo` to start an elevated PowerShell session.
- To elevate a command, any of the following syntaxes:
  1. [`gsudo { ScriptBlock }`](#using-gsudo-scriptblock-syntax) => Best performance.
  2. [`Invoke-gsudo` function](#using-invoke-gsudo-function) wrapper with PowerShell native syntax.
  3. [`gsudo 'string command'`](#using-gsudo-command-syntax) => Old, legacy syntax.

- You can [add `gsudo` PowerShell Module](#powershell-profile-config) to your `$PROFILE`
  - This allows tab-key auto-completition. For example, write 'gsudo` then `space` and then `tab` and your last executed command will be suggested.
  - Also enables to use `gsudo !!` to elevate last command.
  
- In a pipeline of commands, `gsudo` only elevates one command.
  
  `command1 | gsudo elevatedCommand2 | command3`

  Or you can elevate the whole pipeline if you put it inside a [script block](#using-gsudo-scriptblock-syntax) as in: `gsudo {command1 | command2 | command3}`

- `gsudo` uses PowerShell's built-in serialization, which can be **really slow** with big object graphs, like all the machine process tree returned by `Get-Process`.
---

### Using `gsudo {ScriptBlock}` syntax

``` powershell
# Syntax:
gsudo [-nwskd] [--loadProfile] 
      [-u|--user {username}] [--integrity {i}] [--ti]
      { ScriptBlock } [-args $argument1[..., $argumentN]] ;
```

- Express the command to elevate as a PowerShell ScriptBlock, between `{braces}`. PowerShell will parse it and auto-complete commands.
- The ScriptBlock can use literals, but can't access parent or global scope variables (remember it runs in another process). To parametrize the script, you can pass values with `-args` parameter and access them via `$args` array. If you find this painfull, try [`Invoke-gsudo`](#using-invoke-gsudo-function).
- If the result is not captured in a variable, you get best performance, as all serialization is avoided (the output is print in the console).

  ``` powershell
  gsudo { Get-Process "chrome" }
  gsudo { Get-Process $args } -args "chrome"
  gsudo { echo $args[0] $args[1] } -args "Hello", "World"
  ```

- If the result is captured, serialization is slower but automatic & transparent (you receive PSObjects).

  ``` powershell
  $services = gsudo { Get-Service 'WSearch', 'Winmgmt'} 
  Write-Output $services.DisplayName
  ```

- Pipeline input:
  - Must be explicitly mapped with `$input`
  - If marshaling doesn't work as intended, try [`Invoke-gsudo`](#using-invoke-gsudo-function)

  ``` powershell
  get-process winword | gsudo { $input | Stop-Process }
  ```

Example:
  
  ``` powershell
  $file='C:\My Secret.txt'; 
  $algorithm='md5';

  $hash = gsudo {(Get-FileHash $args[0] -Algorithm $args[1]).Hash} -args $file, $algorithm
  ```

---

### Using `Invoke-gsudo` function:

``` powershell
# Syntax:
Invoke-Gsudo [-ScriptBlock] <ScriptBlock> 
            [[-ArgumentList] <Object[]>] 
            [-InputObject <PSObject>] 
            [-LoadProfile | -NoProfile <# default #>] 
            [-Credential <PSCredential>]

# Example:
$MyString = "Hello World"
Invoke-Gsudo { Write-Output $using:MyString }             
```

**`Invoke-gsudo`** is a wrapper function of `gsudo` with the following characteristics:

- Native PowerShell function syntax.

- Automatic serialization of inputs, outputs and pipeline objects. The results are serialized and returned (as a `PSObject` or `PSObject[]`). The serialization is mandatory so this can be slower than  [`gsudo {ScriptBlock}` syntax](#using-gsudo-scriptblock-syntax).

- The command can't access parent or global scope variables. To parametrize the script, you can:
  - 🚀 Mention your `$variable` as `$using:variableName` and its serialized value will be applied.
  - Pass values with `-args` parameter and access them via `$args` array.
- Your current context is better preserved and forwarded to the elevated process:
  - Current Location for non-FileSystem providers.
  - `$ErrorActionPreference`.  
- If your command requires accessing a function on your `$PROFILE` add the `-LoadProfile` parameter. [See More](#loading-your-ps-profile-on-command-elevations).
- Add `-Credential` to specify a user & password to run.

Examples:

``` powershell
# Accepts pipeline input.
Get-process SpoolSv | Invoke-gsudo { Stop-Process -Force }

# Variable usage
$folder = "C:\ProtectedFolder"
Invoke-gsudo { Remove-Item $using:folder }

# The result is serialized (PSObject) with properties.
(Invoke-gsudo { Get-ChildItem $using:folder }).LastWriteTime
```

### Using `gsudo 'command'` syntax

- This is the old syntax. Is still supported but not recommended.
- Prepend `gsudo`, your command must be surrounded by quotes if it contains in of `'"`
- Express the command to elevate as a string literal (between `'quotes'`). (And properly escaping your quotes, if needed).
- Outputs are strings, not PSObjects.
- The command can use literals, but can't access parent or global scope variables. To parametrize the script, you can use string substitution:
  
``` powershell
$file='C:\My Secret.txt'; 
$algorithm='md5';

$hash = gsudo "(Get-FileHash '$file' -Algorithm $algorithm).Hash"
```
---

### Test elevation success

``` powershell
# Test gsudo success (optional)
if ($LastExitCode -eq 999 ) {
    'gsudo failed to elevate!'
} elseif ($LastExitCode) {
    'Command failed!'
} else { 'Success!' }
```

### Elevate CMD Commands

Use `gsudo -d {command}` to tell gsudo that your command does not requires a new instance of PowerShell to interpret it.

``` powershell
gsudo -d dir C:\ 
```

## gsudo PowerShell Module {#powershell-profile-config}

  For an enhanced experience, import `gsudoModule.psd1`. This is optional and enables `gsudo !!`, and param auto-complete for `Invoke-Gsudo` command. 
  
  Add the following line to your $PROFILE (replace with full path)

  ``` powershell
  Import-Module 'gsudoModule.psd1'

  # Or let the following line do it for you run:
  Write-Output "`nImport-Module `"gsudoModule`"" | Add-Content $PROFILE
  ```

:::tip
- You can create a custom alias for gsudo or Invoke-gsudo by adding one of these lines to your `$PROFILE`:
  - `Set-Alias 'sudo' 'gsudo'` <br/>or
  - `Set-Alias 'sudo' 'Invoke-gsudo'`
:::

## Loading your PS Profile on command elevations

When elevating commands, elevation is called with the `-NoProfile` argument. This means the elevated instance won't load your `$PROFILE`. If your command requires your PowerShell profile loaded you can:

- Per command, when using `gsudo`, infix `--loadProfile`:
  
  ``` powershell
  PS C:\> gsudo --loadProfile { echo (1+1) }
  ```

- Per command, when using `Invoke-gsudo`, add `-LoadProfile`:
  
  ``` powershell
  PS C:\> Invoke-Gsudo { echo (1+1) } -LoadProfile
  ```
- Set as a permanent setting with: `gsudo config PowerShellLoadProfile true`

---

### Docs Usage Usage (`docs/docs/usage/usage.md`)

---
sidebar_position: 1
id: usage
title: How to Use
hide_title: true
---
## How to Use

**Note:** You can use anywhere **the `sudo` alias** created by the installers.

``` powershell
gsudo [options]                  # Elevates your current shell
gsudo [options] {command} [args] # Runs {command} with elevated permissions
gsudo cache [on | off | help]    # Starts/Stops an elevated cache session. (reduced UAC popups)
gsudo status [--json | filter ]  # Shows current user, cache and console status.
gsudo !!                         # Re-run last command as admin. (YMMV)
```

```
/* Detailed source-code truncated for AI context efficiency. */
```


**Examples:**

``` powershell
gsudo   # elevates the current shell in the current console window (Supports Cmd/PowerShell/Pwsh Core/Yori/Take Command/git-bash/cygwin)
gsudo -n # launch the current shell elevated in a new console window
gsudo -n -w powershell ./Do-Something.ps1 # launch in new window and wait for exit
gsudo notepad %windir%\system32\drivers\etc\hosts # launch windows app

sudo notepad # sudo alias built-in

# redirect/pipe input/output/error example
gsudo dir | findstr /c:"bytes free" > FreeSpace.txt

gsudo config LogLevel "Error"          # Configure Reduced logging
gsudo config Prompt "$P [elevated]$G " # Configure a custom Elevated Prompt
gsudo config Prompt --reset            # Reset to default value

# Enable credentials cache (less UAC popups):
gsudo config CacheMode Auto
```

### Configuration


``` powershell
 gsudo config                          # Show current config settings & values.
 gsudo config {key} [--global] [value] # Read or write a user setting
 gsudo config {key} [--global] --reset # Reset config to default value
 --global                              # Affects all users (overrides user settings)
```

---

### Docs Usage Wsl (`docs/docs/usage/wsl.md`)

---
sidebar_position: 0
title: Usage from WSL
hide_title: true
---

## Usage from WSL

On WSL (Windows Subsystem for Linux), elevation and `root` are different concepts. `root` allows full administration of WSL but not the Windows system. Use WSL's native `su` or `sudo` to gain `root` access. To get admin privilege on the Windows box you need to elevate the `WSL.EXE` process. `gsudo` allows that (a UAC popup will appear).

On WSL bash, prepend `gsudo` to elevate **WSL commands** or `gsudo -d` for **CMD commands**. 

``` bash
# elevate default shell
PC:~$ gsudo 

# run elevated WSL command
PC:~$ gsudo mkdir /mnt/c/Windows/MyFolder

# run elevated Windows command
PC:~$ gsudo -d notepad C:/Windows/System32/drivers/etc/hosts
PC:~$ gsudo -d "notepad C:\Windows\System32\drivers\etc\hosts"
PC:~$ gsudo -d "echo 127.0.0.1 www.MyWeb.com >> %windir%\System32\drivers\etc\hosts"

# test for gsudo and command success
retval=$?;
if [ $retval -eq 0 ]; then
    echo "Success";
elif [ $retval -eq $((999 % 256)) ]; then # gsudo failure exit code (999) is read as 231 on wsl (999 mod 256)
    echo "gsudo failed to elevate!";
else
    echo "Command failed with exit code $retval";
fi;
```

---

### Src Pages Markdown Page (`docs/src/pages/markdown-page.md`)

---
title: Markdown page example
---

# Markdown page example

You don't need React to write simple standalone pages.

---

### Src Pages Sponsor (`docs/src/pages/sponsor.md`)

---
hide_title: true
title: Sponsor
---

## Sponsor gsudo

Hi, I'm Gerardo, a seasoned software developer from Argentina with a journey in programming that began at the age of 15. My passion for technology led me to create 'gsudo', an open-source project that enhances the windows desktop.

Through sponsorship, you can help sustain the ongoing development of 'gsudo', including keeping it updated, adding new features, and potentially kickstarting new projects. Your support will address practical needs like covering code-signing certificate costs and other expenses, enabling me to focus on innovation and development.

`gsudo` is delivered as a signed application. This ensures the UAC popup doesn't show "Untrusted Publisher", and protects end users detect that gsudo binaries hadn´t been altered.

On Nov 2022, [Parag Mehta @parag_c_mehta](https://twitter.com/gerardo_gr/status/1595817336405168134) gifted me a code signing certificate which expires in Nov 2025. We have some months left to collect $632 for another [3 year renewal](https://signmycode.com/code-signing-certificates).

How to donate:

💵 [Via GitHub Sponsors](https://github.com/sponsors/gerardog)

💵 One time, or recurring donations via [PayPal or Debit/Credit Card](https://www.paypal.com/donate/?business=EGM43RDQ4VRWJ&no_recurring=0&item_name=%0APlease+help+me+dedicate+more+time+to+gsudo%21%0AIf+gsudo+has+improved+your+productivity%2C+please+contribute%21&currency_code=USD) 

💵 BTC 33LVf9Ek9hg5dQYf1EFWUoJaF5W3tWrrhZ

💵 ETH/USDC/USDT/SHIB 0x3c207f47a80b6feede8e9546ea1ca68635652452

---

--- METRICS ---
- Files Extracted: 24
- Estimated Token Budget: ~18388 tokens
- Canonical Reference: https://codewiki.google/github.com/gerardog/gsudo
