<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="http://localhost:4000/WindowsBlog/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/WindowsBlog/" rel="alternate" type="text/html" /><updated>2026-04-26T00:18:20+02:00</updated><id>http://localhost:4000/WindowsBlog/feed.xml</id><title type="html">Windows Blog</title><subtitle>This is a blog where I write about Windows NT (these days Windows 10/11 and Windows Server 2022/2025) and related subjects.</subtitle><entry><title type="html">Windows Containers - Docker Introduction</title><link href="http://localhost:4000/WindowsBlog/docker/" rel="alternate" type="text/html" title="Windows Containers - Docker Introduction" /><published>2026-04-25T00:00:00+02:00</published><updated>2026-04-25T00:00:00+02:00</updated><id>http://localhost:4000/WindowsBlog/WindowsDocker</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/docker/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling or the weather. Read and follow at your own peril! Bring an umbrella. Don’t let anyone see you with the umbrella in front of a computer screen!</strong></p>

<p>They are called zones (Solaris), workload partitions or WPARs (AIX), “secure resource partitions” or SRPs (HP-UX), jails (FreeBSD), or containers (Linux).</p>

<p>Windows chose the Linux rather than the FreeBSD jargon for this technology.</p>

<p>Let’s go for a walk to the harbour.</p>

<p><br />
<br />
<strong>Containers</strong></p>

<p>In theory, and explained in a way that the writer of this blog can understand, the purpose of a container (or a jail etc.) is to <em>contain</em> (or imprison) all components of an application. This is a very unixy thing.</p>

<p>In DEC-style operating systems (like OpenVMS and, indeed, Windows) the usual idea was that all parts of an application go into one directory:</p>

<ul>
  <li><strong>DKA0:[APPLICATIONWHATEVER]</strong></li>
</ul>

<p>This directory then contains files like</p>

<ul>
  <li><strong>DKA0:[APPLICATIONWHATEVER]WHATEVER.EXE</strong></li>
  <li><strong>DKA0:[APPLICATIONWHATEVER]WHATEVER.DAT</strong></li>
</ul>

<p>ACLs on individual files settle the issue what should be writable and by whom (configuration files), what should never be writable (program images), and what is user-writable (settings files of various types).</p>

<p>In Windows this has changed a bit and there are now places for program images and places for data and settings files:</p>

<ul>
  <li><strong>C:\Program Files\Application Whatever</strong></li>
  <li><strong>C:\ProgramData\Application Whatever</strong></li>
</ul>

<p>In Unix-like systems instead, files are not grouped by application, but by file type:</p>

<ul>
  <li><strong>/bin</strong> (program images, some of them)</li>
  <li><strong>/usr/bin</strong> (program images, some others)</li>
  <li><strong>/etc</strong> (global configuration files)</li>
  <li><strong>/lib</strong> (libraries, some of them)</li>
  <li><strong>/usr/lib</strong> (libraries, others)</li>
  <li><strong>/opt</strong> (room for more bin and lib directories)</li>
</ul>

<p>The result is that a single application is likely distributed through five or six directories or more.</p>

<p>A container solves this problem (and others) by isolating all those files in a single place and then making the application believe the files are in their proper locations indeed.</p>

<p>Smart people would say things like “containers virtualise namespace” and that means that an application running “in” a container does not (necessarily) see the same /whatever or C:\whatever as an application running “outside” that container. This is called “operating system-level virtualisation” and looks to me similar to session virtualistion, which pretends that a SSH deamon is a VT100 terminal that can safely be talked to.</p>

<p><br />
<br />
<strong>Windows Containers</strong></p>

<p>To enable Windows containers you have to enable Windows containers:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; Add-WindowsFeature Containers

Success Restart Needed Exit Code      Feature Result
------- -------------- ---------      --------------
True    Yes            SuccessRest... {Containers}
WARNING: You must restart this server to finish the installation process.

PS C:\&gt;</code></pre></figure>

<p><br />
<br />
<strong>Docker</strong></p>

<p>One program that created, configured, and starts (and stops) containers is Docker. It is available for Linux and Windows. (It is also available for Mac OS X but on Mac OS X it only controls Linux containers in a Linux VM not Mac OS X containers.)</p>

<p>You can find it here: <a href="https://download.docker.com/win/static/stable/x86_64/">Download Docker</a></p>

<p>Pick a reasonable recent version. I seem to have ended up with 29.3.1.</p>

<p>In the archive you should find two files, docker.exe and dockerd.exe. The first is the Docker client, the second is the Docker server (deamon). The Docker client connects to the Docker server (on the same machine) and tells it to create, modify, start, and stop Windows containers. It also creates and configured container images. Copy both files into the C:\Windows\System32 directory. (You can copy them elsewhere, but let’s do it the Unix way for now.)</p>

<p>While you can simply run dockerd.exe, you should probably configure dockerd as a Windows service:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\WINDOWS\system32&gt; .\dockerd.exe --register-service
PS C:\WINDOWS\system32&gt; Get-Service docker*

Status   Name               DisplayName
------   ----               -----------
Stopped  docker             Docker Engine

PS C:\WINDOWS\system32&gt;</code></pre></figure>

<p>This service runs as LocalSystem because it actually is a system service.</p>

<p>All relevant data files appear to be stored in <strong>C:\ProgramData\docker</strong>.</p>

<p>You can create a group <strong>Docker-Users</strong>, tell Docker about it, and add accounts to it that will then have full permissions to create and modify containers. Note that this is essentially giving those accounts full administrator privileges because they can build images or run containers that allow escaping to the host system.</p>

<p>Creating such a group and adding user <em>benoit</em> to it:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\ProgramData\docker&gt; New-LocalGroup Docker-Users

Name         Description
----         -----------
Docker-Users

PS C:\ProgramData\docker&gt; Add-LocalGroupMember Docker-Users benoit
PS C:\ProgramData\docker&gt; md config

    Directory: C:\ProgramData\docker

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/25/2026   8:19 PM                config

PS C:\ProgramData\docker&gt; '{ "group": "docker-users" }'|Out-File .\config\daemon.json
PS C:\ProgramData\docker&gt; Restart-Service Docker
PS C:\ProgramData\docker&gt;</code></pre></figure>

<p>I recommend using this group anyway to avoid embarassing mistakes when confusing being inside a container and being outside a container. (This falls into the “type hostname before you type shutdown” category of computer safety.) It also potentially limits the effect of malware that travels with strange container images.</p>

<p><br />
<br />
<strong>Container Images</strong></p>

<p>A “container image” is to a container what a “program image” is to a program: it’s a file (or rather a bunch of files) that represents the running application unstarted on disk.</p>

<p>Container images are created or downloaded or modified based on a downloaded or created base image. Base images typically represent plain operating systems or operating systems with some software pre-installed.</p>

<p>You can find base images on <a href="https://hub.docker.com/">Docker Hub</a>, specifically on <a href="https://hub.docker.com/u/microsoft">Docker Hub Microsoft</a> for Windows.</p>

<p>The interesting base images are <a href="https://hub.docker.com/r/microsoft/windows-servercore">Windows Server Core image</a> and <a href="https://hub.docker.com/r/microsoft/windows-nanoserver">Windows Nano Server image</a>. Each page is good enough to give us the command needed to “pull” (download) the image. You need to pull the image matching your operating system version exactly!</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker pull mcr.microsoft.com/windows/servercore:ltsc2025
ltsc2025: Pulling from windows/servercore
97e96e9cbeb1: Downloading [&gt;                                                  ]   10.8MB/1.482GB
f82b995f31e7: Downloading [===&gt;                                               ]  39.99MB/593MB</code></pre></figure>

<p>It takes a while to pull a base image.</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker pull mcr.microsoft.com/windows/servercore:ltsc2025
ltsc2025: Pulling from windows/servercore
97e96e9cbeb1: Pull complete
f82b995f31e7: Pull complete
Digest: sha256:83374b6927f7945bb0933d03f158f84b03182017e2694fa23aedd24ea51434e4
Status: Downloaded newer image for mcr.microsoft.com/windows/servercore:ltsc2025
mcr.microsoft.com/windows/servercore:ltsc2025
PS C:\&gt; docker pull mcr.microsoft.com/windows/nanoserver:ltsc2025
ltsc2025: Pulling from windows/nanoserver
d7986950dcd8: Downloading [============================&gt;                      ]  109.2MB/193.9MB</code></pre></figure>

<p>You can see that the Nano Server image is much smaller than the Server Core image.</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker pull mcr.microsoft.com/windows/servercore:ltsc2025
ltsc2025: Pulling from windows/servercore
97e96e9cbeb1: Pull complete
f82b995f31e7: Pull complete
Digest: sha256:83374b6927f7945bb0933d03f158f84b03182017e2694fa23aedd24ea51434e4
Status: Downloaded newer image for mcr.microsoft.com/windows/servercore:ltsc2025
mcr.microsoft.com/windows/servercore:ltsc2025
PS C:\&gt;
PS C:\&gt; docker pull mcr.microsoft.com/windows/nanoserver:ltsc2025
ltsc2025: Pulling from windows/nanoserver
d7986950dcd8: Pull complete
Digest: sha256:af9cf5183e68ff0beee87a795e5761ef9143fc6ee7e3d785b5920eda6f5e03fb
Status: Downloaded newer image for mcr.microsoft.com/windows/nanoserver:ltsc2025
mcr.microsoft.com/windows/nanoserver:ltsc2025
PS C:\&gt;</code></pre></figure>

<p>And we have two base images.</p>

<p><br />
<br />
<strong>Docker Commands</strong></p>

<ul>
  <li><strong>docker pull</strong> downloads an image</li>
  <li><strong>docker images</strong> shows installed images</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker images
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B
PS C:\&gt;</code></pre></figure>

<ul>
  <li><strong>docker tag</strong> gives an image a nicer name</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker tag mcr.microsoft.com/windows/nanoserver:ltsc2025 nanoserver
PS C:\&gt; docker tag mcr.microsoft.com/windows/servercore:ltsc2025 servercore
PS C:\&gt; docker images
                                                                                                                                                                                                        i Info →   U  In Use
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B
nanoserver:latest                               299c3c7db826        487MB             0B
servercore:latest                               a5c9d9f8dc6e       4.94GB             0B
PS C:\&gt;</code></pre></figure>

<ul>
  <li><strong>docker run</strong> starts a container based on an image</li>
  <li><strong>docker run -d</strong> starts a container as a detached process</li>
  <li><strong>docker run -i</strong>  starts a container with ability to be used interactively</li>
  <li><strong>docker run -t</strong> starts a container with a terminal attached to it</li>
  <li><strong>docker run -dit</strong> starts a container as a detached process with a terminal attached to it and the ability to be used interactively</li>
  <li><strong>docker ps</strong> shows running containers</li>
  <li><strong>docker exec -it</strong> executes a command inside a container interactively via a terminal</li>
  <li><strong>docker stop</strong> stops a running container</li>
  <li><strong>docker ps -a</strong> shows all containers, running and not</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\Users\benoit&gt; docker run -dit servercore cmd
b8ac6cb6c16924405f90b371b430b675aeaf5ef4284e9d1505b185cf88e31a59
PS C:\Users\benoit&gt; docker ps
CONTAINER ID   IMAGE        COMMAND   CREATED          STATUS         PORTS     NAMES
b8ac6cb6c169   servercore   "cmd"     11 seconds ago   Up 8 seconds             elegant_leavitt
PS C:\Users\benoit&gt; docker exec -it elegant_leavitt hostname
b8ac6cb6c169
PS C:\Users\benoit&gt; hostname
Champignac
PS C:\Users\benoit&gt; docker stop elegant_leavitt
elegant_leavitt
PS C:\Users\benoit&gt; docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\benoit&gt; docker ps -a
CONTAINER ID   IMAGE        COMMAND   CREATED              STATUS                               PORTS     NAMES
b8ac6cb6c169   servercore   "cmd"     About a minute ago   Exited (3221226219) 11 seconds ago             elegant_leavitt
PS C:\Users\benoit&gt;</code></pre></figure>

<p>You can see that the running container has a different hostname that the host.</p>

<p>The <strong>docker run</strong> command above starts a container for running <strong>cmd</strong> using the <strong>servercore</strong> image.</p>

<ul>
  <li><strong>docker start</strong> starts an existing container (visible with ps -a)</li>
</ul>

<p>Note what happens when starting a container.</p>

<ol>
  <li>Processes running inside the container (here cmd) are also visible outside the container.</li>
  <li>Processes running inside the container run in a different session than processes running outside the container (here session 3 while the calling user is in session 2).</li>
  <li>Processes running outside the container (here winver) are not visible inside the container.</li>
  <li>The account inside the countainer is <strong>user manager\containeradministrator</strong>.</li>
  <li>That account is a member of the (container’s) <strong>Administrators</strong> group.</li>
</ol>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\Users\benoit&gt; docker start elegant_leavitt
elegant_leavitt
PS C:\Users\benoit&gt; Get-Process cmd

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
     76       7     5136       5096              4020   3 cmd


PS C:\Users\benoit&gt; query session
 SESSIONNAME               USERNAME                 ID  STATE   TYPE        DEVICE
 services                                            0  Disc
&gt;console                   benoit                    2  Active
 rdp-tcp                                         65536  Listen
PS C:\Users\benoit&gt; docker exec -it elegant_leavitt powershell Get-Process cmd

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
     76       6     4108       5084       0.02   4020   3 cmd


PS C:\Users\benoit&gt; winver
PS C:\Users\benoit&gt; Get-Process winver

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    184      14     2336      16500       0.08   3928   2 winver


PS C:\Users\benoit&gt; docker exec -it elegant_leavitt powershell Get-Process winver
Get-Process : Cannot find a process with the name "winver". Verify the process name and call the cmdlet again.
At line:1 char:1
+ Get-Process winver
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (winver:String) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

PS C:\Users\benoit&gt; docker exec -it elegant_leavitt whoami
user manager\containeradministrator
PS C:\Users\benoit&gt; docker exec -it elegant_leavitt whoami /groups

GROUP INFORMATION
-----------------

Group Name                           Type             SID          Attributes
==================================== ================ ============ ===============================================================
Mandatory Label\High Mandatory Level Label            S-1-16-12288
Everyone                             Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                 Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization       Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
LOCAL                                Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Administrators               Alias            S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, Group owner
                                     Unknown SID type S-1-5-93-0   Mandatory group, Enabled by default, Enabled group
PS C:\Users\benoit&gt;</code></pre></figure>

<p>And what’s even worse, processes running inside the container do not have associated account names:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; Get-Process cmd -IncludeUserName

Handles      WS(K)   CPU(s)     Id UserName               ProcessName
-------      -----   ------     -- --------               -----------
     76       5172     0.02   4020                        cmd
     76       5084     0.02   4200                        cmd

PS C:\</code></pre></figure>

<ul>
  <li><strong>docker run -p</strong> runs a container with a port mapping, host to container</li>
  <li><strong>docker run -v</strong> runs a container a directory mapping, host to container</li>
</ul>

<p>Imagine -v like this:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; md foo

    Directory: C:\

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/25/2026  11:49 PM                foo

PS C:\&gt; ni .\foo\bar

    Directory: C:\foo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         4/25/2026  11:49 PM              0 bar

PS C:\&gt; docker run -dit -v "C:\foo:C:\foofromhost" servercore cmd
9eac0388e2ca4cb6aaa4560a14d47c1696b41e35d9069210860daaf6751f3530
PS C:\&gt; docker ps
CONTAINER ID   IMAGE        COMMAND   CREATED         STATUS         PORTS     NAMES
9eac0388e2ca   servercore   "cmd"     9 seconds ago   Up 6 seconds             adoring_allen
PS C:\&gt; docker exec -it adoring_allen cmd /c dir c:\
 Volume in drive C has no label.
 Volume Serial Number is 1001-F4AE

 Directory of c:\

04/25/2026  11:49 PM    &lt;DIR&gt;          foofromhost
01/11/2026  11:44 AM    &lt;DIR&gt;          inetpub
01/11/2026  11:35 AM             5,647 License.txt
04/13/2026  09:05 AM    &lt;DIR&gt;          Program Files
04/13/2026  08:59 AM    &lt;DIR&gt;          Program Files (x86)
04/13/2026  09:05 AM    &lt;DIR&gt;          Users
04/25/2026  11:50 PM    &lt;DIR&gt;          Windows
               1 File(s)          5,647 bytes
               6 Dir(s)  136,177,917,952 bytes free
PS C:\&gt; docker exec -it adoring_allen cmd /c dir c:\foofromhost
 Volume in drive C has no label.
 Volume Serial Number is 1001-F4AE

 Directory of c:\foofromhost

04/25/2026  11:49 PM    &lt;DIR&gt;          .
04/25/2026  11:49 PM                 0 bar
               1 File(s)              0 bytes
               1 Dir(s)  28,357,349,376 bytes free
PS C:\&gt;</code></pre></figure>

<p>I will go into details on port forwarding in a future article on running Internet Information Server in a container.</p>

<ul>
  <li><strong>docker commit</strong> “commits” a container into a new image</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\&gt; docker commit adoring_allen newimage
Error response from daemon: windows does not support commit of a running container
PS C:\&gt; docker stop adoring_allen
adoring_allen
PS C:\&gt; docker commit adoring_allen newimage
sha256:15e6323e548c0044e70dddf1094594c1f72f2ba4a33855f8aa6f15d4bd5ec9cb
PS C:\&gt; docker images
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B    U
nanoserver:latest                               299c3c7db826        487MB             0B
newimage:latest                                 15e6323e548c       5.01GB             0B
servercore:latest                               a5c9d9f8dc6e       4.94GB             0B    U
PS C:\&gt;</code></pre></figure>

<p>The idea is that you take a base image, run a container based on it, do whatever you want with it, and then create a new image from the resulting state.</p>

<ul>
  <li><strong>docker rm</strong> removes a (non-running) container</li>
  <li><strong>docker rmi</strong> removes an image</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\Users\benoit&gt; docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\benoit&gt; docker ps -a
CONTAINER ID   IMAGE        COMMAND   CREATED         STATUS                              PORTS     NAMES
9eac0388e2ca   servercore   "cmd"     7 minutes ago   Exited (3221226219) 4 minutes ago             adoring_allen
PS C:\Users\benoit&gt; docker rm adoring_allen
adoring_allen
PS C:\Users\benoit&gt; docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\benoit&gt; docker images
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B
nanoserver:latest                               299c3c7db826        487MB             0B
newimage:latest                                 15e6323e548c       5.01GB             0B
servercore:latest                               a5c9d9f8dc6e       4.94GB             0B
PS C:\Users\benoit&gt; docker rmi newimage
Untagged: newimage:latest
Deleted: sha256:15e6323e548c0044e70dddf1094594c1f72f2ba4a33855f8aa6f15d4bd5ec9cb
Deleted: sha256:4d419e6b12c4947b1a0ed5465f19d031fc0acec3913ea8cf8314aa2a905511c8
PS C:\Users\benoit&gt; docker images
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B
nanoserver:latest                               299c3c7db826        487MB             0B
servercore:latest                               a5c9d9f8dc6e       4.94GB             0B
PS C:\Users\benoit&gt;</code></pre></figure>

<p><br />
<br />
<strong>Differences between Server Core and Nano Server Images</strong></p>

<p>Running a quick <em>dir</em> in both variants shows a huge difference quickly:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">S C:\Users\benoit&gt; docker run -dit servercore cmd
64e832fe43e5946c3efcf06ccd5ff81821b2336df517803b6d975fd99a6542a3
PS C:\Users\benoit&gt; docker ps
CONTAINER ID   IMAGE        COMMAND   CREATED         STATUS         PORTS     NAMES
64e832fe43e5   servercore   "cmd"     6 seconds ago   Up 4 seconds             eager_gagarin
PS C:\Users\benoit&gt; docker exec -it eager_gagarin cmd /c dir c:\
 Volume in drive C has no label.
 Volume Serial Number is 1001-F4AE

 Directory of c:\

01/11/2026  11:44 AM    &lt;DIR&gt;          inetpub
01/11/2026  11:35 AM             5,647 License.txt
04/13/2026  09:05 AM    &lt;DIR&gt;          Program Files
04/13/2026  08:59 AM    &lt;DIR&gt;          Program Files (x86)
04/13/2026  09:05 AM    &lt;DIR&gt;          Users
04/25/2026  11:59 PM    &lt;DIR&gt;          Windows
               1 File(s)          5,647 bytes
               5 Dir(s)  136,177,942,528 bytes free
PS C:\Users\benoit&gt; docker run -dit nanoserver cmd
98399bd440816470a335d9b9dc6e6d7e6ff252c0d7a9d616b4a0297ac352bd0b
PS C:\Users\benoit&gt; docker ps
CONTAINER ID   IMAGE        COMMAND   CREATED          STATUS          PORTS     NAMES
98399bd44081   nanoserver   "cmd"     5 seconds ago    Up 2 seconds              brave_fermat
64e832fe43e5   servercore   "cmd"     43 seconds ago   Up 41 seconds             eager_gagarin
PS C:\Users\benoit&gt; docker exec -it brave_fermat cmd /c dir c:\
 Volume in drive C has no label.
 Volume Serial Number is 76D0-1E23

 Directory of c:\

04/13/2026  08:36 AM             5,647 License.txt
04/13/2026  08:39 AM    &lt;DIR&gt;          Users
04/25/2026  11:59 PM    &lt;DIR&gt;          Windows
               1 File(s)          5,647 bytes
               2 Dir(s)  136,183,414,784 bytes free
PS C:\Users\benoit&gt;</code></pre></figure>

<table>
  <tbody>
    <tr>
      <td><strong>Server Core</strong></td>
      <td><strong>Nano Server</strong></td>
    </tr>
    <tr>
      <td>PowerShell</td>
      <td>-</td>
    </tr>
    <tr>
      <td>WoW (32 bit emulation)</td>
      <td>-</td>
    </tr>
    <tr>
      <td>.NET and .NET Framework</td>
      <td>.NET only</td>
    </tr>
    <tr>
      <td>Can run stand-alone</td>
      <td>Container only</td>
    </tr>
    <tr>
      <td>Meant for complete Windows Server applications</td>
      <td>Suitable only for applications developed for the Nano Server container</td>
    </tr>
    <tr>
      <td>5 GB image size</td>
      <td>500 MB image size</td>
    </tr>
    <tr>
      <td>No GUI applications, no RDP</td>
      <td>No GUI applications, no RDP</td>
    </tr>
  </tbody>
</table>

<p><br />
<br />
<strong>Exporting and Importing Containers</strong></p>

<ul>
  <li><strong>docker save</strong> saves an image into a tarball (commit the container to an image to save)</li>
  <li><strong>docker load</strong> loads an image from a tarball</li>
</ul>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\Users\benoit&gt; docker commit brave_fermat brave_fermat
sha256:18972e6d20078a7fa3bfb701e451153c833f4fef588bec8f639a7cb64c85f672
PS C:\Users\benoit&gt; docker images
                                                                                                                                                                              i Info →   U  In Use
IMAGE                                           ID             DISK USAGE   CONTENT SIZE   EXTRA
brave_fermat:latest                             18972e6d2007        489MB             0B
mcr.microsoft.com/windows/nanoserver:ltsc2025   299c3c7db826        487MB             0B    U
mcr.microsoft.com/windows/servercore:ltsc2025   a5c9d9f8dc6e       4.94GB             0B    U
nanoserver:latest                               299c3c7db826        487MB             0B    U
servercore:latest                               a5c9d9f8dc6e       4.94GB             0B    U
PS C:\Users\benoit&gt; docker save brave_fermat -o brave_fermat.tar
PS C:\Users\benoit&gt; docker rmi brave_fermat
Untagged: brave_fermat:latest
Deleted: sha256:18972e6d20078a7fa3bfb701e451153c833f4fef588bec8f639a7cb64c85f672
Deleted: sha256:653f586307eb57d859a8f172075d849734123db34291f5ada26506ef7b0377d8
PS C:\Users\benoit&gt; docker load -i brave_fermat.tar
cb6a8faeb776: Loading layer [==================================================&gt;]  2.018MB/2.018MB
Loaded image: brave_fermat:latest
PS C:\Users\benoit&gt;</code></pre></figure>

<p>Next: TBD</p>]]></content><author><name></name></author><category term="WindowsContainers" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling or the weather. Read and follow at your own peril! Bring an umbrella. Don’t let anyone see you with the umbrella in front of a computer screen!]]></summary></entry><entry><title type="html">Windows - OpenSSH Server</title><link href="http://localhost:4000/WindowsBlog/sshd/" rel="alternate" type="text/html" title="Windows - OpenSSH Server" /><published>2026-04-12T00:00:00+02:00</published><updated>2026-04-12T00:00:00+02:00</updated><id>http://localhost:4000/WindowsBlog/WindowsOpenSSH</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/sshd/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling or the weather. Read and follow at your own peril! Bring an umbrella. Don’t let anyone see you with the umbrella in front of a computer screen!</strong></p>

<p>First, if you don’t know what <strong>ssh</strong> is, go and read this book: <a href="https://mwl.link/ssh-mastery-2nd-edition.html">SSH Mastery</a>. It’s the seminal book on ssh as far as I can tell.</p>

<p>Second, if you <strong>do</strong> what ssh is, go and the read the book anyway, if you haven’t yet.</p>

<p>Return here for Windows-specific uses of ssh.</p>

<p>You are back? Good. Let’s begin.</p>

<p>You will likely find the sshd service already installed on modern versions of Windows Server. To enable it and start it and start it automatically at boot, do this:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Service</span><span class="w"> </span><span class="nx">sshd</span><span class="w">

</span><span class="n">Status</span><span class="w">   </span><span class="nx">Name</span><span class="w">               </span><span class="nx">DisplayName</span><span class="w">
</span><span class="o">------</span><span class="w">   </span><span class="o">----</span><span class="w">               </span><span class="o">-----------</span><span class="w">
</span><span class="n">Stopped</span><span class="w">  </span><span class="nx">sshd</span><span class="w">               </span><span class="nx">OpenSSH</span><span class="w"> </span><span class="nx">SSH</span><span class="w"> </span><span class="nx">Server</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Set-Service</span><span class="w"> </span><span class="nx">sshd</span><span class="w"> </span><span class="nt">-StartupType</span><span class="w"> </span><span class="nx">Automatic</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">sc.exe</span><span class="w"> </span><span class="nx">qc</span><span class="w"> </span><span class="nx">sshd</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">QueryServiceConfig</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">

</span><span class="n">SERVICE_NAME:</span><span class="w"> </span><span class="nx">sshd</span><span class="w">
        </span><span class="kr">TYPE</span><span class="w">               </span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="w">  </span><span class="n">WIN32_OWN_PROCESS</span><span class="w">
        </span><span class="nx">START_TYPE</span><span class="w">         </span><span class="p">:</span><span class="w"> </span><span class="nx">2</span><span class="w">   </span><span class="nx">AUTO_START</span><span class="w">
        </span><span class="n">ERROR_CONTROL</span><span class="w">      </span><span class="p">:</span><span class="w"> </span><span class="nx">1</span><span class="w">   </span><span class="nx">NORMAL</span><span class="w">
        </span><span class="n">BINARY_PATH_NAME</span><span class="w">   </span><span class="p">:</span><span class="w"> </span><span class="nx">C:\WINDOWS\System32\OpenSSH\sshd.exe</span><span class="w">
        </span><span class="n">LOAD_ORDER_GROUP</span><span class="w">   </span><span class="p">:</span><span class="w">
        </span><span class="n">TAG</span><span class="w">                </span><span class="p">:</span><span class="w"> </span><span class="nx">0</span><span class="w">
        </span><span class="n">DISPLAY_NAME</span><span class="w">       </span><span class="p">:</span><span class="w"> </span><span class="nx">OpenSSH</span><span class="w"> </span><span class="nx">SSH</span><span class="w"> </span><span class="nx">Server</span><span class="w">
        </span><span class="n">DEPENDENCIES</span><span class="w">       </span><span class="p">:</span><span class="w">
        </span><span class="n">SERVICE_START_NAME</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">LocalSystem</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Start-Service</span><span class="w"> </span><span class="nx">sshd</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Service</span><span class="w"> </span><span class="nx">sshd</span><span class="w">

</span><span class="n">Status</span><span class="w">   </span><span class="nx">Name</span><span class="w">               </span><span class="nx">DisplayName</span><span class="w">
</span><span class="o">------</span><span class="w">   </span><span class="o">----</span><span class="w">               </span><span class="o">-----------</span><span class="w">
</span><span class="n">Running</span><span class="w">  </span><span class="nx">sshd</span><span class="w">               </span><span class="nx">OpenSSH</span><span class="w"> </span><span class="nx">SSH</span><span class="w"> </span><span class="nx">Server</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>The sshd service runs as LocalSystem and, as an actual system service, is supposed to run as LocalSystem.</p>

<p>The sshd service is configured in <em>C:\ProgramData\ssh</em> (where Windows emulates the Unix-style <em>/etc</em> directory):</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">cd</span><span class="w"> </span><span class="o">.</span><span class="nx">\ProgramData\ssh\</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\ProgramData\ssh</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">dir</span><span class="w">


    </span><span class="n">Directory:</span><span class="w"> </span><span class="nx">C:\ProgramData\ssh</span><span class="w">


</span><span class="n">Mode</span><span class="w">                 </span><span class="nx">LastWriteTime</span><span class="w">         </span><span class="nx">Length</span><span class="w"> </span><span class="nx">Name</span><span class="w">
</span><span class="o">----</span><span class="w">                 </span><span class="o">-------------</span><span class="w">         </span><span class="o">------</span><span class="w"> </span><span class="o">----</span><span class="w">
</span><span class="n">d-----</span><span class="w">         </span><span class="nx">4/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">                </span><span class="nx">logs</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">              </span><span class="nx">6</span><span class="w"> </span><span class="nx">sshd.pid</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">3</span><span class="n">/31/2024</span><span class="w">   </span><span class="nx">6:08</span><span class="w"> </span><span class="nx">PM</span><span class="w">           </span><span class="nx">2343</span><span class="w"> </span><span class="nx">sshd_config</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">            </span><span class="nx">513</span><span class="w"> </span><span class="nx">ssh_host_ecdsa_key</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">            </span><span class="nx">180</span><span class="w"> </span><span class="nx">ssh_host_ecdsa_key.pub</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">            </span><span class="nx">411</span><span class="w"> </span><span class="nx">ssh_host_ed25519_key</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">            </span><span class="nx">100</span><span class="w"> </span><span class="nx">ssh_host_ed25519_key.pub</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">           </span><span class="nx">2602</span><span class="w"> </span><span class="nx">ssh_host_rsa_key</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w">         </span><span class="mi">4</span><span class="n">/12/2026</span><span class="w">   </span><span class="nx">3:52</span><span class="w"> </span><span class="nx">PM</span><span class="w">            </span><span class="nx">572</span><span class="w"> </span><span class="nx">ssh_host_rsa_key.pub</span><span class="w">


</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\ProgramData\ssh</span><span class="err">&gt;</span></code></pre></figure>

<p>In the file sshd_config you will find everything you need, with two Windows-specific elements.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">AllowGroups administrators <span class="s2">"openssh users"</span>

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys</code></pre></figure>

<p>There is a group <strong>OpenSSH Users</strong> to which you must add all users that should be allowed to access the computer via ssh. The Administrators group is also allowed.</p>

<p>There is also one common authorised keys file for all members of the Administrators group here in <em>C:\ProgramData\ssh\administrators_authorized_keys</em> which is used for any ssh logon with a user that is in the Administrators group. Personally, I like commenting this out. It is perhaps best practice though better to keep track of administrators who can log in without a password.</p>

<p>Now, let’s have a look at an ssh session.</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">Microsoft Windows [Version 10.0.26100.32522]
(c) Microsoft Corporation. All rights reserved.

benoit@CHAMPIGNAC C:\Users\benoit&gt;whoami/groups

GROUP INFORMATION
-----------------

Group Name                             Type             SID          Attributes
====================================== ================ ============ ==================================================
Everyone                               Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                          Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\OpenSSH Users                  Alias            S-1-5-32-585 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                   Well-known group S-1-5-2      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users       Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization         Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account             Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication       Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label            S-1-16-8192

benoit@CHAMPIGNAC C:\Users\benoit&gt;powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\benoit&gt; Get-Process -Id $PID

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    640      31    55936      73720       0.33   3628   0 powershell


PS C:\Users\benoit&gt;</code></pre></figure>

<p>Note the following odditites:</p>

<ul>
  <li>The standard shell for an ssh session is cmd. I recommend not even trying to change it to PowerShell.</li>
  <li>The logon type (as seen in the membership of the associated well-known group <strong>NT AUTHORITY\NETWORK</strong> is <em>network</em> and not <em>interactive</em>)</li>
  <li>The process runs in session 0, the services session</li>
</ul>

<p>Compared to PowerShell remoting ssh is more powerful. It allows for the actual use of the computer and running interactive programs, albeit obviously not GUI programs (there being no obvious GUI to use).</p>

<p>In fact, since I like tables, here is a table:</p>

<table>
  <tbody>
    <tr>
      <td><strong>“Session type”</strong></td>
      <td><strong>Well-known group membership</strong></td>
      <td><strong>Required privilege</strong></td>
      <td><strong>Possible programs</strong></td>
    </tr>
    <tr>
      <td>Console</td>
      <td>INTERACTIVE</td>
      <td>SeInteractiveLogonRight (likely granted by <strong>Users</strong> group)</td>
      <td>Any (filters, interactive and GUI)</td>
    </tr>
    <tr>
      <td>Remote Desktop</td>
      <td>INTERACTIVE and REMOTE INTERACTIVE LOGON</td>
      <td>SeRemoteInteractiveLogonRight (from <strong>Remote Desktop Users</strong> group)</td>
      <td>Essentially any</td>
    </tr>
    <tr>
      <td>Secondary Logon (via runas.exe)</td>
      <td>INTERACTIVE</td>
      <td>SeInteractiveLogonRight (for some reason)</td>
      <td>Same as Console or Remote Desktop</td>
    </tr>
    <tr>
      <td>PowerShell remoting</td>
      <td>NETWORK</td>
      <td><strong>Remote Managements Users</strong> membership (for microsoft.powershell configuration)</td>
      <td>filters only</td>
    </tr>
    <tr>
      <td>ssh</td>
      <td>NETWORK</td>
      <td><strong>OpenSSH Users</strong> (per configuration file)</td>
      <td>filters and interactive programs</td>
    </tr>
  </tbody>
</table>

<p>“Filters” are programs that take input from their command line and standard input and provide output to standard output. They cannot otherwise stop and ask the user for input. Examples are cmd.exe with the “/c” parameter, all PowerShell cmdlets, and programs like compilers.</p>

<p>“Interactive” programs are programs that interact with the user (ask him questions, react to key presses etc.). Examples are edit.exe, diskpart.exe, vim.exe, amd cmd.exe with no parameter or the “/k” parameter. Some of those programs can receive mouse input (edit.exe).</p>

<p>GUI programs are programs that use their own custom windows (i.e. do not just display everything in a terminal window). Examples are notepad.exe and explorer.exe. These do not work in ssh (or rather they start and disappear into nothingness somewhere in session 0.)</p>

<p>So you might say that the session types form a hiearchy.</p>

<ul>
  <li>From a console logon you can do everything you can do in RDP, ssh, and PowerShell remoting; and you can also ssh and PowerShell remote into the local machine (although with PowerShell and local users this can be difficult).</li>
  <li>From an RDP logon you can do everything you can do in ssh and PowerShell remoting as well.</li>
  <li>In an ssh session you can do everything you can do in a PowerShell remoting session too.</li>
  <li>In a PowerShell remoting session you are limited to filters, i.e. PowerShell cmdlets and very simple non-interactive external programs.</li>
</ul>

<p>Next: <a href="../docker/">Docker</a></p>]]></content><author><name></name></author><category term="WindowsAccounts" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling or the weather. Read and follow at your own peril! Bring an umbrella. Don’t let anyone see you with the umbrella in front of a computer screen!]]></summary></entry><entry><title type="html">Windows Privileges - Trusted Computing Base</title><link href="http://localhost:4000/WindowsBlog/tcb/" rel="alternate" type="text/html" title="Windows Privileges - Trusted Computing Base" /><published>2026-04-11T00:00:00+02:00</published><updated>2026-04-11T00:00:00+02:00</updated><id>http://localhost:4000/WindowsBlog/WindowsPrivilegesTcb</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/tcb/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling. Read and digest at your own peril!</strong></p>

<p>“Act as part of the operating system”</p>

<p>That is the legal name of a privilege with the technical name <strong>SeTcbPrivilege</strong> or <strong>SE_TCB_NAME</strong>. The official description is</p>

<p><em>This privilege identifies its holder as part of the trusted computer base. Some trusted protected subsystems are granted this privilege.</em></p>

<p>I cannot see how one can be clearer than that!</p>

<p>I am myself not very familiar with SeTcbPrivilege. It is not something one runs into daily and or something that many applications would need for normal operation. In fact is it not even held by the Administrators group (and therefor also not by members of that group, usually) and Microsoft themselves apparently recommend not assinging it to any account and run services that need this privilege under the LocalSystem account which has this privilege.</p>

<p>As far as I know it allows a process to assume any identity and is meant to be used by the Local Security Authority to log on accounts (users and services likewise).</p>

<p>Thus it is required by many <strong>Lsa*</strong> APIs but also by some uses of the <strong>SetTokenInformation</strong> API which manipulates access tokens.</p>

<p>For example, to create a process in an arbitrary session (not the session of the process-creating process), SeTcbPrivilege is needed, among other things.</p>

<p>What else is needed:</p>

<ul>
  <li>the process-creating process has to run in the services session (session 0) and</li>
  <li>the process-creating process has to run in a service or batch logon context (i.e. not interactive or network) and</li>
  <li>the process-creating process has to hold <a href="../assignprimarytoken/">SeAssignPrimaryTokenPrivilege</a> as well (to create the process with the manipulated token)</li>
</ul>

<p>Alternatively, the procress-creating service has to run under LocalSystem, in which case it will have all the necessary privileges and does not matter how it logged on or in which session it runs.</p>

<p>The easiest way to accomplish this feat is to equip an account with SeTcbPrivilege and SeAssignPrimaryTokenPrivilege and create a scheduled task to create a process.</p>

<p>Remember that privileges have to be enabled before they can be used.</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// we need a handle to a token, let's use the current process' primary token</span>
<span class="n">HANDLE</span> <span class="n">hToken</span><span class="p">;</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">OpenProcessToken</span><span class="p">(</span><span class="n">GetCurrentProcess</span><span class="p">(),</span> <span class="n">TOKEN_ALL_ACCESS</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">hToken</span><span class="p">);</span>

<span class="c1">// we need a copy of the token to modify it and use it elsewhere</span>
<span class="n">HANDLE</span> <span class="n">hModifiedToken</span><span class="p">;</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">DuplicateTokenEx</span><span class="p">(</span><span class="n">hToken</span><span class="p">,</span> <span class="n">MAXIMUM_ALLOWED</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">SecurityImpersonation</span><span class="p">,</span> <span class="n">TokenPrimary</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">hModifiedToken</span><span class="p">);</span>

<span class="c1">// this next step requires SeTcbPrivilege, it changes the session id of the token to iSessionId (maybe 2)</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">SetTokenInformation</span><span class="p">(</span><span class="n">hModifiedToken</span><span class="p">,</span> <span class="n">TokenSessionId</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">iSessionId</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">DWORD</span><span class="p">));</span></code></pre></figure>

<p>The call to SetTokenInformation() will fail with an error 1314 (“privilege not held”) if the process does not hold SeTcbPrivilege:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">B:\</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\TcbDemo.exe</span><span class="w"> </span><span class="nx">C:\windows\system32\winver.exe</span><span class="w"> </span><span class="nx">2</span><span class="w">
</span><span class="n">Image</span><span class="w"> </span><span class="p">[</span><span class="n">C:\windows\system32\winver.exe</span><span class="p">]</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">session</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="w">
</span><span class="n">OpenProcessToken</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">DuplicateTokenEx</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">SetTokenInformation</span><span class="w">     </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1314</span><span class="p">]</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="n">B:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">certutil</span><span class="w"> </span><span class="nx">/error</span><span class="w"> </span><span class="nx">1314</span><span class="w">
</span><span class="mi">0</span><span class="n">x522</span><span class="w"> </span><span class="p">(</span><span class="n">WIN32</span><span class="p">:</span><span class="w"> </span><span class="mi">1314</span><span class="w"> </span><span class="n">ERROR_PRIVILEGE_NOT_HELD</span><span class="p">)</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="mi">1314</span><span class="w"> </span><span class="p">(</span><span class="mi">1314</span><span class="p">)</span><span class="w">
</span><span class="n">Error</span><span class="w"> </span><span class="n">message</span><span class="w"> </span><span class="n">text</span><span class="p">:</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="nx">required</span><span class="w"> </span><span class="nx">privilege</span><span class="w"> </span><span class="nx">is</span><span class="w"> </span><span class="nx">not</span><span class="w"> </span><span class="nx">held</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">client.</span><span class="w">
</span><span class="n">CertUtil</span><span class="p">:</span><span class="w"> </span><span class="nt">-error</span><span class="w"> </span><span class="n">command</span><span class="w"> </span><span class="n">completed</span><span class="w"> </span><span class="n">successfully.</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="n">B:\</span><span class="err">&gt;</span></code></pre></figure>

<p>Now that we have a modified second token, we can start a process with it. And if everything else is perfect (session 0, service or batch logon, SeAssignPrimaryTokenPrivilege held, moon in conjunction with venus etc.) this will start an unusable program in the requested session. (It is unusable because it does not belong into the session it runs in and is missing permissions. A window will appear though. See <a href="../privilegedscheduledtask/">Scheduled Task to Start Privileged Application</a> which describes a program that implements exactly this mechanism.)</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// creating the process, this step requires SeAssignPrimaryTokenPrivilege to, well, assign the primary token</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">CreateProcessAsUserW</span><span class="p">(</span><span class="n">hModifiedToken</span><span class="p">,</span> <span class="n">pathImage</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">FALSE</span><span class="p">,</span> <span class="n">CREATE_NEW_CONSOLE</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">si</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">pi</span><span class="p">);</span></code></pre></figure>

<p>Running this without holding SeAssignPrimaryTokenPrivilege leads to disaster again:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">B:\</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\TcbDemo.exe</span><span class="w"> </span><span class="nx">c:\windows\system32\cmd.exe</span><span class="w"> </span><span class="nx">2</span><span class="w">
</span><span class="n">Image</span><span class="w"> </span><span class="p">[</span><span class="n">c:\windows\system32\cmd.exe</span><span class="p">]</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">session</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="w">
</span><span class="n">OpenProcessToken</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">DuplicateTokenEx</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">SetTokenInformation</span><span class="w">     </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">CreateProcessAsUserW</span><span class="w">    </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1314</span><span class="p">]</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="n">B:\</span><span class="err">&gt;</span></code></pre></figure>

<p>And with SeAssignPrimaryTokenPrivilege:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">B:\</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\TcbDemo.exe</span><span class="w"> </span><span class="nx">c:\windows\system32\cmd.exe</span><span class="w"> </span><span class="nx">2</span><span class="w">
</span><span class="n">Image</span><span class="w"> </span><span class="p">[</span><span class="n">c:\windows\system32\cmd.exe</span><span class="p">]</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">session</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="w">
</span><span class="n">OpenProcessToken</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">DuplicateTokenEx</span><span class="w">        </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">SetTokenInformation</span><span class="w">     </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">CreateProcessAsUserW</span><span class="w">    </span><span class="n">OK</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="n">STATUS</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="mi">5</span><span class="p">]</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="n">B:\</span><span class="err">&gt;</span></code></pre></figure>

<p>The privilege works but creating a process in another session fails due to missing permissions. That’s where running in session 0 comes in.</p>

<p>A scheduled task defined as <strong>cmd.exe</strong> with arguments <strong>/c C:\TcbDemo\TcbDemo.exe C:\Windows\System32\cmd.exe 2 2&gt; C:\Temp\TcbDemo.log</strong> produces an error log file</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Content</span><span class="w"> </span><span class="o">.</span><span class="nx">\Temp\TcbDemo.log</span><span class="w">
</span><span class="n">OpenProcessToken</span><span class="w">        </span><span class="nx">OK:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="nx">STATUS:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="nx">Error:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">DuplicateTokenEx</span><span class="w">        </span><span class="nx">OK:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="nx">STATUS:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="nx">Error:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">SetTokenInformation</span><span class="w">     </span><span class="nx">OK:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="nx">STATUS:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="nx">Error:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">CreateProcessAsUserW</span><span class="w">    </span><span class="nx">OK:</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="nx">STATUS:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="nx">Error:</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>and a window running cmd.exe in session 2. In fact, the process still remembers where it comes from and runs inside a batch logon:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w"> </span><span class="nx">/groups</span><span class="o">|</span><span class="n">Select-String</span><span class="w"> </span><span class="s2">"NT Authority"</span><span class="w">

</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\Local</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">member</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">Administrators</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-114</span><span class="w">                                      </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\BATCH</span><span class="w">                                            </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-3</span><span class="w">                                        </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\Authenticated</span><span class="w"> </span><span class="nx">Users</span><span class="w">                              </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-11</span><span class="w">                                       </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\This</span><span class="w"> </span><span class="nx">Organization</span><span class="w">                                </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-15</span><span class="w">                                       </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\Local</span><span class="w"> </span><span class="nx">account</span><span class="w">                                    </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-113</span><span class="w">                                      </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\NTLM</span><span class="w"> </span><span class="nx">Authentication</span><span class="w">                              </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-64-10</span><span class="w">                                    </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>Note the <strong>NT AUTHORITY\BATCH</strong> pseudo group. The PowerShell process is a daughter of the cmd.exe process is a daughter of the scheduled task which logged in as a batch job.</p>

<p>Examples of how this mechanism can be used (but shouldn’t be):</p>

<ul>
  <li><a href="../privilegedscheduledtask/">Scheduled Task to Start Privileged Application</a></li>
  <li><a href="../wupservice/">Service to Start Privileged Application</a></li>
</ul>

<p>In real life it is generally completely unnecessary to start processes in arbitrary sessions unless you are writing malware.</p>

<p>And if you are writing malware you should really find a vulnerability and exploit it and not rely on idiots granting your process system privileges.</p>

<p>Although you likely can.</p>

<p>Next: <a href="../sshd/">OpenSSH on Windows</a></p>]]></content><author><name></name></author><category term="WindowsAccounts" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling. Read and digest at your own peril!]]></summary></entry><entry><title type="html">Windows History - Application Specification for Microsoft Windows 2000</title><link href="http://localhost:4000/WindowsBlog/windows2000appspec/" rel="alternate" type="text/html" title="Windows History - Application Specification for Microsoft Windows 2000" /><published>2026-04-10T00:00:00+02:00</published><updated>2026-04-10T00:00:00+02:00</updated><id>http://localhost:4000/WindowsBlog/Windows2000AppSpec</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/windows2000appspec/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling. Read and digest at your own peril!</strong></p>

<p>Some time ago I found an interesting document from 1999. The [Application Specification for Microsoft Windows 2000] is a document published by Microsoft that documents proper application design for Windows Server. I never found a newer version or replacement document. But even this old document gives an interesting insight into how enterprise applications <em>should</em> be developed. It is more least-privilege than today’s standard by far.</p>

<p>Its purpose was clear:</p>

<p><em>The Application Specification for Windows 2000 defines the technical
requirements for applications to earn the “Certified for Microsoft Windows” logo.
Applications may carry the “Certified for Microsoft Windows” logo, once they have
passed compliance testing and have executed a logo license agreement with
Microsoft. This logo lets your customers know that your application offers a high
quality computing experience available on Windows.</em></p>

<p>Since the document is from 1999 it features a few oddities when seen from today’s point of view. Some are outdated, some can be translated into the current situation.</p>

<p>Among those are</p>

<ul>
  <li>Obviously references to exlusively Windows 2000 Server (and not newer versions)</li>
  <li>Instructions for how to deal with 16-bit dependencies of 32-bit programs (today I suppose this is less relevant for 64-bit programs and 32-bit dependencies)</li>
  <li>References to the Alpha CPU (as apparently Windows 2000 was developed for Alpha until Compaq withdrew support)</li>
  <li>References to best practices that use APIs now deprecated (SHGetFolderPath())</li>
  <li>A complete lack of anything about .NET or PowerShell (which did not exist yet)</li>
</ul>

<p>But there are also points that were new then and are very current still today:</p>

<ul>
  <li>Active Directory</li>
  <li>Win64 (then for Alpha, now very much alive on x64 and ARM64)</li>
  <li>SSO (Single Sign-On was already something people tried to achieve, it’s still the <em>new</em> thing)</li>
  <li>“Browser-Hosted Applications”</li>
  <li>Terminal Services compatibility considerations</li>
</ul>

<p><em>This specification is intended for vendors and corporate developers building multi-
user applications that run on any of the Windows 2000 Server family of operating
systems.</em></p>

<p>Chapter 5 covers security requirements.</p>

<p><em>In order for Client/Sever applications to provide secure access to resources and
security for their interactions, the application must configure and run the client and
server portions in the correct security contexts. This provides access to the
resources needed in a secure manner and provides a secure communication
channel between the client and the server</em></p>

<p>It mentions specifically what has apparently been forgotten in modern times:</p>

<p><em>If a service or service account password is compromised, then the scope of
damage that can occur is limited to the capabilities of the account under which the
service is running.</em></p>

<p>It defines the security requirements for certification:</p>

<ul>
  <li>Document services that require more than User level privileges to run</li>
  <li>Win32 clients running in the context of a trusted domain account must support Single Sign-On</li>
</ul>

<p>Wow. We are still far from that.</p>

<p><em>For each service account that requires more than User-level privileges, the
following must be documented:<br />
1) The specific system resources that normal Users do not have sufficient
access to by default.<br />
2) The specific User Rights that normal Users do not have by default in
order for the service to run properly.<br />
3) The minimum permissions to the resources identified in #1 that the
service account must have in order to run properly.</em></p>

<p>Of course, today the answer many vendors give for 1, 2, and 3 is “our application has been designed to run with administrator rights”, comically extending the absurd into a farce.</p>

<p>(My April 1st post describes how to conform to such a design and how to run a server in [Enterprise Mode].)</p>

<p>Finally, the chapter ends with the clarification that certification does not require applications to run completely unprivileged or even with defined security requirements. But it does explain that the customer must be told about the situation he will face, giving him the three options of running the application with well-configured permissions, running the application with administrator rights and accept the risk, or buy an alternative product that does not have those problems.</p>

<p>I fear that a lot of today’s enterprise software for Windows would not be able to become certified for Windows Server 2000.</p>

<p>Next: <a href="../tcb/">Trusted Computing Base Privilege</a></p>]]></content><author><name></name></author><category term="WindowsHistory" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It is mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything, not even spelling. Read and digest at your own peril!]]></summary></entry><entry><title type="html">Windows - Run As Administrator</title><link href="http://localhost:4000/WindowsBlog/runasadministrator/" rel="alternate" type="text/html" title="Windows - Run As Administrator" /><published>2026-04-01T01:00:00+02:00</published><updated>2026-04-01T01:00:00+02:00</updated><id>http://localhost:4000/WindowsBlog/RunAsAdministrator</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/runasadministrator/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril! Especially now.</strong></p>

<p>This is a more enterprisey post than most. It deals with a very common issue with enterprise software and what many vendors consider <strong>best practice</strong>.</p>

<p>How to make every user an administrator:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Local</span><span class="err">​</span><span class="nx">User</span><span class="w">
</span><span class="n">Name</span><span class="w">               </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">Description</span><span class="w">
</span><span class="o">----</span><span class="w">               </span><span class="o">-------</span><span class="w"> </span><span class="o">-----------</span><span class="w">
</span><span class="n">Administrator</span><span class="w">      </span><span class="nx">True</span><span class="w">    </span><span class="nx">Built-in</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">administering</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">computer/domain</span><span class="w">
</span><span class="n">benoit</span><span class="w">             </span><span class="nx">True</span><span class="w">
</span><span class="n">DefaultAccount</span><span class="w">     </span><span class="nx">False</span><span class="w">   </span><span class="nx">A</span><span class="w"> </span><span class="nx">user</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">managed</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system.</span><span class="w">
</span><span class="n">Guest</span><span class="w">              </span><span class="nx">False</span><span class="w">   </span><span class="nx">Built-in</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">guest</span><span class="w"> </span><span class="nx">access</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">computer/domain</span><span class="w">
</span><span class="n">legrand</span><span class="w">            </span><span class="nx">True</span><span class="w">
</span><span class="n">WDAGUtilityAccount</span><span class="w"> </span><span class="nx">False</span><span class="w">   </span><span class="nx">A</span><span class="w"> </span><span class="nx">user</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">managed</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">used</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">Windows</span><span class="w"> </span><span class="nx">Defender</span><span class="w"> </span><span class="nx">Application</span><span class="w"> </span><span class="nx">Guard</span><span class="w"> </span><span class="nx">scenarios.</span><span class="w">


</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Local</span><span class="err">​</span><span class="nx">User</span><span class="o">|</span><span class="kr">For</span><span class="err">​</span><span class="n">Each-Object</span><span class="p">{</span><span class="n">Add-Local</span><span class="err">​</span><span class="nx">GroupMember</span><span class="w"> </span><span class="nx">Administrators</span><span class="w"> </span><span class="bp">$_</span><span class="p">}</span><span class="w">
</span><span class="n">Add-LocalGroupMember</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Administrator</span><span class="w"> </span><span class="nx">is</span><span class="w"> </span><span class="nx">already</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">member</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">Administrators.</span><span class="w">
</span><span class="n">At</span><span class="w"> </span><span class="nx">line:1</span><span class="w"> </span><span class="nx">char:30</span><span class="w">
</span><span class="o">+</span><span class="w"> </span><span class="n">Get-LocalUser</span><span class="o">|</span><span class="n">ForEach-Object</span><span class="p">{</span><span class="n">Add-LocalGroupMember</span><span class="w"> </span><span class="nx">Administrators</span><span class="w"> </span><span class="bp">$_</span><span class="p">}</span><span class="w">
</span><span class="o">+</span><span class="w">                              </span><span class="n">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span><span class="w">
    </span><span class="o">+</span><span class="w"> </span><span class="nx">CategoryInfo</span><span class="w">          </span><span class="p">:</span><span class="w"> </span><span class="nx">ResourceExists:</span><span class="w"> </span><span class="p">(</span><span class="n">Administrators:LocalGroup</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="n">Add</span><span class="nt">-LocalGroupMember</span><span class="p">],</span><span class="w"> </span><span class="nx">MemberExistsException</span><span class="w">
    </span><span class="o">+</span><span class="w"> </span><span class="n">FullyQualifiedErrorId</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">MemberExists</span><span class="p">,</span><span class="nx">Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Local</span><span class="err">​</span><span class="nx">GroupMember</span><span class="w"> </span><span class="nx">Administrators</span><span class="w">

</span><span class="n">ObjectClass</span><span class="w"> </span><span class="nx">Name</span><span class="w">                          </span><span class="nx">PrincipalSource</span><span class="w">
</span><span class="o">-----------</span><span class="w"> </span><span class="o">----</span><span class="w">                          </span><span class="o">---------------</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\Administrator</span><span class="w">      </span><span class="nx">Local</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\benoit</span><span class="w">             </span><span class="nx">Local</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\DefaultAccount</span><span class="w">     </span><span class="nx">Local</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\Guest</span><span class="w">              </span><span class="nx">Local</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\legrand</span><span class="w">            </span><span class="nx">Local</span><span class="w">
</span><span class="n">User</span><span class="w">        </span><span class="nx">CHAMPIGNAC\WDAGUtilityAccount</span><span class="w"> </span><span class="nx">Local</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span></code></pre></figure>

<p>For domain users:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Add-LocalGroupMember</span><span class="w"> </span><span class="nx">Administrators</span><span class="w"> </span><span class="s2">"Domain Users@</span><span class="nv">${env:ADDomain}</span><span class="s2">"</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span></code></pre></figure>

<p>Now the server is ready to run enterprise software as per the requirements of many enterprise software vendors.</p>

<p>But to be on the safe side, you can also make all services run as administrator. This will allow services that were designed to run as administrator run as administrator even if the account they run under has insufficient rights:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-</span><span class="err">​</span><span class="nx">Service</span><span class="o">|</span><span class="n">ForEach-Object</span><span class="p">{</span><span class="nv">$name</span><span class="o">=</span><span class="bp">$_</span><span class="o">.</span><span class="nf">Name</span><span class="p">;</span><span class="n">sc</span><span class="err">​</span><span class="o">.</span><span class="nf">exe</span><span class="w"> </span><span class="nx">sidtype</span><span class="w"> </span><span class="nv">$name</span><span class="w"> </span><span class="nx">unrestricted</span><span class="p">;</span><span class="n">Add-Local</span><span class="err">​</span><span class="nx">GroupMember</span><span class="w"> </span><span class="nx">Administrators</span><span class="w"> </span><span class="s2">"NT Service\</span><span class="nv">$name</span><span class="s2">"</span><span class="p">}</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="n">SC</span><span class="p">]</span><span class="w"> </span><span class="n">ChangeServiceConfig2</span><span class="w"> </span><span class="nx">SUCCESS</span><span class="w">
</span><span class="p">[</span><span class="o">...</span><span class="p">]</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\WINDOWS\system32</span><span class="err">&gt;</span></code></pre></figure>

<p>And don’t forget to disable the firewall:</p>

<figure class="highlight"><pre><code class="language-cmd" data-lang="cmd">PS C:\WINDOWS\system32&gt; net​sh advf​irewall set allprofiles state off
Ok.

PS C:\WINDOWS\system32&gt;</code></pre></figure>

<p>Now your server is absolutely enterprise-ready.</p>

<p>Next: <a href="../windows2000appspec/">Application Specification for Microsoft Windows 2000</a></p>]]></content><author><name></name></author><category term="April1" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril! Especially now.]]></summary></entry><entry><title type="html">WSL - Ubuntu Issue</title><link href="http://localhost:4000/WindowsBlog/wslubuntuissue/" rel="alternate" type="text/html" title="WSL - Ubuntu Issue" /><published>2026-03-28T00:00:00+01:00</published><updated>2026-03-28T00:00:00+01:00</updated><id>http://localhost:4000/WindowsBlog/WSLUbuntuIssue</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/wslubuntuissue/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!</strong></p>

<p>If this happens to your Ubuntu installation in WSL:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Failed to take /etc/passwd lock: Invalid argument
dpkg: error processing package systemd <span class="o">(</span><span class="nt">--configure</span><span class="o">)</span>:
 installed systemd package post-installation script subprocess returned error <span class="nb">exit </span>status 1
dpkg: dependency problems prevent configuration of systemd-timesyncd:
 systemd-timesyncd depends on systemd<span class="p">;</span> however:
  Package systemd is not configured yet.

dpkg: error processing package systemd-timesyncd <span class="o">(</span><span class="nt">--configure</span><span class="o">)</span>:
 dependency problems - leaving unconfigured
dpkg: dependency problems prevent configuration of udev:
 udev depends on systemd | systemd-standalone-sysusers | systemd-sysusers<span class="p">;</span> however:
  Package systemd is not configured yet.
  Package systemd-standalone-sysusers is not installed.
  Package systemd-sysusers is not installed.
  Package systemd which provides systemd-sysusers is not configured yet.</code></pre></figure>

<p>The solution (or workaround) might be these commands:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo sed</span> <span class="nt">-i</span> <span class="nt">-e</span> <span class="s1">'/systemd-sysusers/s/\.conf$/.conf || true/'</span> /var/lib/dpkg/info/<span class="k">*</span>.postinst
<span class="nb">sudo </span>dpkg <span class="nt">--configure</span> <span class="nt">-a</span></code></pre></figure>

<p>at least this is what Chatgippity told me.</p>

<p>If it turns out that it doesn’t work, I’ll correct or update this post as necessary.</p>

<p>Next: <a href="../runasadministrator/">Run As Administrator</a></p>]]></content><author><name></name></author><category term="WSL" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!]]></summary></entry><entry><title type="html">Windows History - Comparing Shells</title><link href="http://localhost:4000/WindowsBlog/comparingshells/" rel="alternate" type="text/html" title="Windows History - Comparing Shells" /><published>2026-03-07T00:00:00+01:00</published><updated>2026-03-07T00:00:00+01:00</updated><id>http://localhost:4000/WindowsBlog/ComparingShells</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/comparingshells/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!</strong></p>

<p>Showing all files in all subdirectories in order of last write time, newest last. Probably.</p>

<p><strong>Bash (Linux)</strong></p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">find <span class="s2">"</span><span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span><span class="s2">"</span> <span class="nt">-type</span> f <span class="nt">-printf</span> <span class="s1">'%TY-%Tm-%Td %TH:%TM:%TS %p\n'</span> | <span class="nb">sort</span></code></pre></figure>

<p><strong>DCL (OpenVMS)</strong></p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">DIRECTORY</span><span class="w"> </span><span class="p">[</span><span class="o">...</span><span class="p">]</span><span class="o">*.*</span><span class="p">;</span><span class="o">*</span><span class="w"> </span><span class="n">/FULL</span><span class="w"> </span><span class="nx">/DATE</span><span class="o">=</span><span class="n">MODIFIED</span><span class="w"> </span><span class="nx">/SORT</span><span class="o">=</span><span class="n">DATE</span></code></pre></figure>

<p><strong>PowerShell (Windows)</strong></p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">Get-ChildItem</span><span class="w"> </span><span class="nt">-Recurse</span><span class="w"> </span><span class="nt">-File</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Sort-Object</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Select-Object</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="p">,</span><span class="w"> </span><span class="nx">FullName</span></code></pre></figure>

<p>This is what people mean when they are talking about why their favourite command line shell is superior to other shells.</p>

<p>And if you find PowerShell or DCL too wordy (or too readable), you can do this:</p>

<p><strong>PowerShell (using aliases and abbreviations)</strong></p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">gci</span><span class="w"> </span><span class="nt">-r</span><span class="w"> </span><span class="nt">-fi</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">sort</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">select</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="p">,</span><span class="nx">FullName</span></code></pre></figure>

<p><strong>DCL (using abbreviations and despacing)</strong></p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">DIR</span><span class="p">[</span><span class="o">...</span><span class="p">]</span><span class="o">*.*</span><span class="p">;</span><span class="o">*</span><span class="n">/F/D</span><span class="o">=</span><span class="n">M/S</span><span class="o">=</span><span class="n">D</span></code></pre></figure>

<p>Next: <a href="../wslubuntuissue/">WSL Ubuntu Issue</a></p>]]></content><author><name></name></author><category term="WindowsHistory" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!]]></summary></entry><entry><title type="html">Windows - Sudo</title><link href="http://localhost:4000/WindowsBlog/sudo/" rel="alternate" type="text/html" title="Windows - Sudo" /><published>2026-01-17T00:00:00+01:00</published><updated>2026-01-17T00:00:00+01:00</updated><id>http://localhost:4000/WindowsBlog/WindowsSudo</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/sudo/"><![CDATA[<p>This article is on Windows sudo.</p>

<p>See the post <a href="../privilegedscheduledtask/">Privileged Scheduled Task</a> for a scheduled task-based JEA mechanism to emulate Unix-style sudo on Windows.</p>

<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!</strong></p>

<p>In a previous post <a href="../unprivilegedaccounts/">Unprivileged Accounts</a> I attempted to describe the concept of non-privileged accounts in Windows, a concept very foreign to modern enterprise computing on servers.</p>

<p>Go and read it as a primer, especially the part about <strong>User Account Control</strong>, I will wait here.</p>

<p>Are you back? Good.</p>

<p>With Windows 11 (or rather some time after Windows 11 first appeared) Microsoft introduced a <em>sudo</em> command for Windows that is entirely unsimilar to the famous Unix <strong>sudo</strong> command.</p>

<p>Let me first explain, very quickly and horribly non-precise, how Unix sudo works.</p>

<ol>
  <li>In Unix there is one user called the <strong>superuser</strong> who normally has the user name <strong>root</strong>.</li>
  <li>In Unix one of the permissions bit on a file is the so-called <strong>setuid</strong> bit. If this bit is set, the file, if executed, will run with the identity of its owner rather than of the user who executes it.</li>
  <li>One of those programs marked with the setuid bit is a program called <strong>sudo</strong>. It is owned by the superuser. If started, it will run with the identity of root.</li>
  <li>The program sudo is configured in a file <strong>/etc/sudoers</strong>.</li>
  <li>In that file it is outlined which user or group may start which program as what user.</li>
</ol>

<p>This is it, essentially.</p>

<p>Imagine a Unix-compatible system, here the Windows Subsystem for Linux, with a sudo configuration allowing the start of the program <strong>whoami</strong> as root. There is no particular purpose in running this program. But it will show the effect of using sudo best and without doing any damage.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">benoit@paris:~<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-l</span> <span class="sb">`</span>which <span class="nb">sudo</span><span class="sb">`</span>
<span class="nt">-rwsr-xr-x</span> 1 root root 277936 Jun 25  2025 /usr/bin/sudo
benoit@paris:~<span class="nv">$ </span>which <span class="nb">whoami</span>
/usr/bin/whoami
benoit@paris:~<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-l</span> <span class="sb">`</span>which <span class="nb">whoami</span><span class="sb">`</span>
<span class="nt">-rwxr-xr-x</span> 1 root root 35336 Jun 22  2025 /usr/bin/whoami
benoit@paris:~<span class="err">$</span></code></pre></figure>

<p>The first command checks that the sudo program is indeed marked setuid root. The <em>s</em> in the permissions indicates it. (It would be <em>x</em> for execute otherwise.)</p>

<p>The second command shows the whoami program file.</p>

<p>And the third command checks for its permissions, to demonstrate that it is not marked setuid at all. (There actually is an <em>x</em> in the permissions for the file owner.)</p>

<p>There is a program <strong>visudo</strong> that starts an editor (not vi but nano on Ubuntu, for some reason) that allows editing the /etc/sudoers file. (The file can only be edited by root, we should assume.)</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">benoit  <span class="nv">ALL</span><span class="o">=(</span>root<span class="o">)</span> NOPASSWD:/usr/bin/whoami</code></pre></figure>

<p>After adding user benoit, user benoit should be able to run whoami both as benoit (directly) and as root (via sudo):</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">benoit@paris:~<span class="nv">$ </span><span class="nb">whoami
</span>benoit
benoit@paris:~<span class="nv">$ </span><span class="nb">sudo whoami
</span>root
benoit@paris:~<span class="err">$</span></code></pre></figure>

<p>And this is it. Permissions management is overriden in the hope that the allowed program does not do anything it is not expected to do. This is as irresponsible as JEA but more flexible in its simplicity (it can start GUI programs, for example).</p>

<p>Windows sudo is not like that at all. Windows does not have a setuid mechanism.</p>

<p>Do note that “sudo” actually stands for “superuser do” and Windows sudo is very loyal to the concept of the name. While on Unix there is indeed a specific superuser (and it is one account that can be configured to be used by sudo), on Windows there is no such account. There is a group.</p>

<p>Very unfortunately in Windows there is an <strong>Administrators</strong> group and anyone added to it becomes a superuser. This is in effect one of the biggest problems for Windows security: it is easier to give an account <strong>all</strong> rights and privileges than it is to give an account just the rights and privileges it needs, a daily attack on the principle of least-privilege.</p>

<p>A lot of “enterprise” software sees security from the perspective of someone who can ignore permissions because the account can just be added to the Administrators group.</p>

<p>Many home and office users also find themselves with superuser rights because of the ease of adding a user to the Administrators group and the assumption by software that, of course, the user has superuser status.</p>

<p>This led to issues when users did stupid things. With superuser rights. To themselves. A lot.</p>

<p>So Microsoft invented “User Account Control” to alert users every time they are doing something potentially stupid. This was very inconvenient, and it was supposed to be.</p>

<p>To make the inconvenience less inconvenient Microsoft finally introduced a tool for users to allow them to do stupid user things better: <strong>sudo</strong>.</p>

<p>You can enable sudo as a superuser:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">C:\</span><span class="err">&gt;</span><span class="nx">whoami</span><span class="w">
</span><span class="n">paris\administrator</span><span class="w">

</span><span class="n">C:\</span><span class="err">&gt;</span><span class="nx">sudo</span><span class="w"> </span><span class="nx">help</span><span class="w"> </span><span class="nx">config</span><span class="w">
</span><span class="n">Get</span><span class="w"> </span><span class="nx">current</span><span class="w"> </span><span class="nx">configuration</span><span class="w"> </span><span class="nx">information</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">sudo</span><span class="w">

</span><span class="n">Usage:</span><span class="w"> </span><span class="nx">sudo</span><span class="w"> </span><span class="nx">config</span><span class="w"> </span><span class="p">[</span><span class="n">OPTIONS</span><span class="p">]</span><span class="w">

</span><span class="n">Options:</span><span class="w">
      </span><span class="nt">--enable</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">enable</span><span class="err">&gt;</span><span class="w">  </span><span class="p">[</span><span class="n">possible</span><span class="w"> </span><span class="n">values</span><span class="p">:</span><span class="w"> </span><span class="n">disable</span><span class="p">,</span><span class="w"> </span><span class="n">enable</span><span class="p">,</span><span class="w"> </span><span class="n">forceNewWindow</span><span class="p">,</span><span class="w"> </span><span class="n">disableInput</span><span class="p">,</span><span class="w"> </span><span class="n">normal</span><span class="p">,</span><span class="w"> </span><span class="n">default</span><span class="p">]</span><span class="w">

</span><span class="n">C:\</span><span class="err">&gt;</span><span class="nx">sudo</span><span class="w"> </span><span class="nx">config</span><span class="w"> </span><span class="nt">--enable</span><span class="w"> </span><span class="nx">default</span><span class="w">
</span><span class="n">Sudo</span><span class="w"> </span><span class="nx">is</span><span class="w"> </span><span class="nx">currently</span><span class="w"> </span><span class="nx">in</span><span class="w"> </span><span class="nx">Inline</span><span class="w"> </span><span class="nx">mode</span><span class="w"> </span><span class="nx">on</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">machine</span><span class="w">

</span><span class="n">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>“Inline mode” means that sudo will run in the same terminal/console as the calling program (usually cmd or PowerShell). It is “normal” and “default”, I guess.</p>

<p>“forceNewWindow” does the same as the traditional <strong>Start-Process -Verb RunAs someprogram.exe</strong> did and opens a new console window for the program.</p>

<p>And “disableInput” runs sudo-started programs in the same terminal window as the calling program but does not allow for any interactivity.</p>

<p>Windows sudo does not run programs as another user. It does not run them as <strong>the</strong> superuser, like in Unix. It runs programs as the calling user, but with superuser rights. Let me demonstrate in the most intelligent way I can:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w">
</span><span class="n">paris\benoit</span><span class="w">
</span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w"> </span><span class="nx">/priv</span><span class="w">

</span><span class="n">PRIVILEGES</span><span class="w"> </span><span class="nx">INFORMATION</span><span class="w">
</span><span class="o">----------------------</span><span class="w">

</span><span class="n">Privilege</span><span class="w"> </span><span class="nx">Name</span><span class="w">                </span><span class="nx">Description</span><span class="w">                          </span><span class="nx">State</span><span class="w">
</span><span class="o">=============================</span><span class="w"> </span><span class="o">====================================</span><span class="w"> </span><span class="o">========</span><span class="w">
</span><span class="n">SeShutdownPrivilege</span><span class="w">           </span><span class="nx">Shut</span><span class="w"> </span><span class="nx">down</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system</span><span class="w">                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeChangeNotifyPrivilege</span><span class="w">       </span><span class="nx">Bypass</span><span class="w"> </span><span class="nx">traverse</span><span class="w"> </span><span class="nx">checking</span><span class="w">             </span><span class="nx">Enabled</span><span class="w">
</span><span class="n">SeUndockPrivilege</span><span class="w">             </span><span class="nx">Remove</span><span class="w"> </span><span class="nx">computer</span><span class="w"> </span><span class="nx">from</span><span class="w"> </span><span class="nx">docking</span><span class="w"> </span><span class="nx">station</span><span class="w"> </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeIncreaseWorkingSetPrivilege</span><span class="w"> </span><span class="nx">Increase</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">process</span><span class="w"> </span><span class="nx">working</span><span class="w"> </span><span class="nx">set</span><span class="w">       </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeTimeZonePrivilege</span><span class="w">           </span><span class="nx">Change</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="nx">zone</span><span class="w">                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">sudo</span><span class="w"> </span><span class="nx">whoami</span><span class="w">
</span><span class="n">paris\benoit</span><span class="w">
</span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">sudo</span><span class="w"> </span><span class="nx">whoami</span><span class="w"> </span><span class="nx">/priv</span><span class="w">

</span><span class="n">PRIVILEGES</span><span class="w"> </span><span class="nx">INFORMATION</span><span class="w">
</span><span class="o">----------------------</span><span class="w">

</span><span class="n">Privilege</span><span class="w"> </span><span class="nx">Name</span><span class="w">                            </span><span class="nx">Description</span><span class="w">                                                        </span><span class="nx">State</span><span class="w">
</span><span class="o">=========================================</span><span class="w"> </span><span class="o">==================================================================</span><span class="w"> </span><span class="o">========</span><span class="w">
</span><span class="n">SeIncreaseQuotaPrivilege</span><span class="w">                  </span><span class="nx">Adjust</span><span class="w"> </span><span class="nx">memory</span><span class="w"> </span><span class="nx">quotas</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">process</span><span class="w">                                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeSecurityPrivilege</span><span class="w">                       </span><span class="nx">Manage</span><span class="w"> </span><span class="nx">auditing</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">security</span><span class="w"> </span><span class="nx">log</span><span class="w">                                   </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeTakeOwnershipPrivilege</span><span class="w">                  </span><span class="nx">Take</span><span class="w"> </span><span class="nx">ownership</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="nx">or</span><span class="w"> </span><span class="nx">other</span><span class="w"> </span><span class="nx">objects</span><span class="w">                           </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeLoadDriverPrivilege</span><span class="w">                     </span><span class="nx">Load</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">unload</span><span class="w"> </span><span class="nx">device</span><span class="w"> </span><span class="nx">drivers</span><span class="w">                                     </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeSystemProfilePrivilege</span><span class="w">                  </span><span class="nx">Profile</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">performance</span><span class="w">                                         </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeSystemtimePrivilege</span><span class="w">                     </span><span class="nx">Change</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">time</span><span class="w">                                             </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeProfileSingleProcessPrivilege</span><span class="w">           </span><span class="nx">Profile</span><span class="w"> </span><span class="nx">single</span><span class="w"> </span><span class="nx">process</span><span class="w">                                             </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeIncreaseBasePriorityPrivilege</span><span class="w">           </span><span class="nx">Increase</span><span class="w"> </span><span class="nx">scheduling</span><span class="w"> </span><span class="nx">priority</span><span class="w">                                       </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeCreatePagefilePrivilege</span><span class="w">                 </span><span class="nx">Create</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">pagefile</span><span class="w">                                                  </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeBackupPrivilege</span><span class="w">                         </span><span class="nx">Back</span><span class="w"> </span><span class="nx">up</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">directories</span><span class="w">                                      </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeRestorePrivilege</span><span class="w">                        </span><span class="nx">Restore</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">directories</span><span class="w">                                      </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeShutdownPrivilege</span><span class="w">                       </span><span class="nx">Shut</span><span class="w"> </span><span class="nx">down</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system</span><span class="w">                                               </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeDebugPrivilege</span><span class="w">                          </span><span class="nx">Debug</span><span class="w"> </span><span class="nx">programs</span><span class="w">                                                     </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeSystemEnvironmentPrivilege</span><span class="w">              </span><span class="nx">Modify</span><span class="w"> </span><span class="nx">firmware</span><span class="w"> </span><span class="nx">environment</span><span class="w"> </span><span class="nx">values</span><span class="w">                                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeChangeNotifyPrivilege</span><span class="w">                   </span><span class="nx">Bypass</span><span class="w"> </span><span class="nx">traverse</span><span class="w"> </span><span class="nx">checking</span><span class="w">                                           </span><span class="nx">Enabled</span><span class="w">
</span><span class="n">SeRemoteShutdownPrivilege</span><span class="w">                 </span><span class="nx">Force</span><span class="w"> </span><span class="nx">shutdown</span><span class="w"> </span><span class="nx">from</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">remote</span><span class="w"> </span><span class="nx">system</span><span class="w">                                </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeUndockPrivilege</span><span class="w">                         </span><span class="nx">Remove</span><span class="w"> </span><span class="nx">computer</span><span class="w"> </span><span class="nx">from</span><span class="w"> </span><span class="nx">docking</span><span class="w"> </span><span class="nx">station</span><span class="w">                               </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeManageVolumePrivilege</span><span class="w">                   </span><span class="nx">Perform</span><span class="w"> </span><span class="nx">volume</span><span class="w"> </span><span class="nx">maintenance</span><span class="w"> </span><span class="nx">tasks</span><span class="w">                                   </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeImpersonatePrivilege</span><span class="w">                    </span><span class="nx">Impersonate</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">client</span><span class="w"> </span><span class="nx">after</span><span class="w"> </span><span class="nx">authentication</span><span class="w">                          </span><span class="nx">Enabled</span><span class="w">
</span><span class="n">SeCreateGlobalPrivilege</span><span class="w">                   </span><span class="nx">Create</span><span class="w"> </span><span class="nx">global</span><span class="w"> </span><span class="nx">objects</span><span class="w">                                              </span><span class="nx">Enabled</span><span class="w">
</span><span class="n">SeIncreaseWorkingSetPrivilege</span><span class="w">             </span><span class="nx">Increase</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">process</span><span class="w"> </span><span class="nx">working</span><span class="w"> </span><span class="nx">set</span><span class="w">                                     </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeTimeZonePrivilege</span><span class="w">                       </span><span class="nx">Change</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="nx">zone</span><span class="w">                                               </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeCreateSymbolicLinkPrivilege</span><span class="w">             </span><span class="nx">Create</span><span class="w"> </span><span class="nx">symbolic</span><span class="w"> </span><span class="nx">links</span><span class="w">                                              </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeDelegateSessionUserImpersonatePrivilege</span><span class="w"> </span><span class="nx">Obtain</span><span class="w"> </span><span class="nx">an</span><span class="w"> </span><span class="nx">impersonation</span><span class="w"> </span><span class="nx">token</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">another</span><span class="w"> </span><span class="nx">user</span><span class="w"> </span><span class="nx">in</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">same</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>If you try this out you will notice, assuming User Account Control is configured properly, that every time sudo is used, Windows will ask the user to confirm that he wants do something superuser-like. This remains the idea of User Account Configuration.</p>

<p>If you need superuser rights for several commands, you can just start a shell using sudo, like so:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">sudo</span><span class="w"> </span><span class="nx">powershell</span><span class="w">
</span><span class="n">Windows</span><span class="w"> </span><span class="nx">PowerShell</span><span class="w">
</span><span class="n">Copyright</span><span class="w"> </span><span class="p">(</span><span class="n">C</span><span class="p">)</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w"> </span><span class="nx">Corporation.</span><span class="w"> </span><span class="nx">All</span><span class="w"> </span><span class="nx">rights</span><span class="w"> </span><span class="nx">reserved.</span><span class="w">

</span><span class="n">Install</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">latest</span><span class="w"> </span><span class="nx">PowerShell</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">new</span><span class="w"> </span><span class="nx">features</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">improvements</span><span class="o">!</span><span class="w"> </span><span class="nx">https://aka.ms/PSWindows</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w">
</span><span class="n">paris\benoit</span><span class="w">
</span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">exit</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>And exit it when you are done being superuser-like.</p>

<p>Do note that it is still not advisable to use a computer with an account with superuser rights all the time. The reason it is done on Windows is, of course, for compatibility reasons:</p>

<ol>
  <li>First, which is quite reasonable, for running programs that predate any such permissions or multiuser environments.</li>
  <li>Second, which is less reasonable, for running programs made by software vendors, typically advertising themselves as “enterprise software” vendors, that assume that all users are superusers and that security issues created by such software are the customer’s problem.</li>
</ol>

<p>Until Microsoft somehow fully virtualises the experience of the superuser, we will have to live with sudo.</p>

<p>Next: <a href="../comparingshells/">Comparing Shells</a></p>]]></content><author><name></name></author><category term="Windows" /><summary type="html"><![CDATA[This article is on Windows sudo.]]></summary></entry><entry><title type="html">Windows Unprivileged - Scheduled Tasks JEA</title><link href="http://localhost:4000/WindowsBlog/scheduledtasksjea/" rel="alternate" type="text/html" title="Windows Unprivileged - Scheduled Tasks JEA" /><published>2026-01-07T00:00:00+01:00</published><updated>2026-01-07T00:00:00+01:00</updated><id>http://localhost:4000/WindowsBlog/ScheduledTasksJEA</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/scheduledtasksjea/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!</strong></p>

<p>As partly explained in the post on <a href="../scheduledtasks/">Scheduled Tasks</a>, setting permissions on scheduled tasks is not trivial.</p>

<p>So what is more obvious than avoiding those permissions using Just Enough Admin again?</p>

<p>The immediate problem is that allowing non-privileged users to create and modify scheduled tasks using a virtual administrator account will allow those users to create scheduled tasks running as LocalSystem that will then do whatever those users want, perhaps just add them to the Administrators group.</p>

<p>Any JEA configuration for scheduled tasks would have to disallow creation or modification of scheduled tasks that use privileged accounts. Perhaps it is sufficient to stop creation of scheduled tasks that run as a system account (LocalSystem, LocalService, or NetworkService). Scheduled tasks to be modified can then simply be recreated, then being subject to the same restriction.</p>

<p>This requires two cmdlets to be available:</p>

<ul>
  <li><strong>Get-ScheduledTask</strong> to get any scheduled task as a PowerShell object (so that it can then be modified in PowerShell)</li>
  <li><strong>Register-RestrictedScheduledTask</strong> as a wrapper for <strong>Register-ScheduledTask</strong> that makes the -Password parameter a required parameter (to disallow creation of scheduled tasks that use accounts without passwords)</li>
</ul>

<p>As a bonus, another cmdlet can annex and permission a scheduled task for the calling user, to allow manipulation in the Task Scheduler GUI (<strong>taskschd.msc</strong>) as a non-privileged user.</p>

<ul>
  <li>
    <p><strong>Claim-ScheduledTask</strong> changes the owner of a scheduled task to the calling user and adds the user to the scheduled task’s ACL with <em>Full Access</em> before any other entry (to preempt deny entries as well, also, it’s easier).</p>
  </li>
  <li>
    <p><strong>Get-ScheduledTaskPermissions</strong> shows the permissions of a scheduled task. <strong>Set-ScheduledTaskPermissions</strong> sets the permissions.</p>
  </li>
</ul>

<p>And as a further bonus, the ability simply to enable or disable any scheduled task is included.</p>

<ul>
  <li><strong>Enable-ScheduledTask</strong> and <strong>Disable-ScheduledTask</strong></li>
</ul>

<p>Get ScheduledTasks.pssc and ScheduledTasts.psrc from <a href="https://github.com/ajbrehm/JEA">GitHub</a>, register ScheduledTasks.pssc, and create the associated JEA group:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\WindowsPowerShell\Modules\JEA</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">New-LocalGroup</span><span class="w"> </span><span class="nx">JEA_ScheduledTasks</span><span class="w">

</span><span class="n">Name</span><span class="w">               </span><span class="nx">Description</span><span class="w">
</span><span class="o">----</span><span class="w">               </span><span class="o">-----------</span><span class="w">
</span><span class="n">JEA_ScheduledTasks</span><span class="w">


</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\WindowsPowerShell\Modules\JEA</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Add-LocalGroupMember</span><span class="w"> </span><span class="nx">JEA_ScheduledTasks</span><span class="w"> </span><span class="nx">benoit</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\WindowsPowerShell\Modules\JEA</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">ScheduledTasks</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="o">.</span><span class="nx">\ScheduledTasks.pssc</span><span class="w">
</span><span class="n">WARNING:</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">need</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">service</span><span class="w"> </span><span class="nx">if</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">configuration</span><span class="w"> </span><span class="nx">using</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">name</span><span class="w"> </span><span class="nx">has</span><span class="w"> </span><span class="nx">recently</span><span class="w"> </span><span class="nx">been</span><span class="w"> </span><span class="nx">unregistered</span><span class="p">,</span><span class="w"> </span><span class="nx">certain</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="nx">structures</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">still</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">cached.</span><span class="w"> </span><span class="nx">In</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">case</span><span class="p">,</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">required.</span><span class="w">
</span><span class="n">All</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">sessions</span><span class="w"> </span><span class="nx">connected</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">Windows</span><span class="w"> </span><span class="nx">PowerShell</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="p">,</span><span class="w"> </span><span class="nx">such</span><span class="w"> </span><span class="nx">as</span><span class="w"> </span><span class="nx">Microsoft.PowerShell</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">created</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">cmdlet</span><span class="p">,</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">disconnected.</span><span class="w">


   </span><span class="n">WSManConfig:</span><span class="w"> </span><span class="nx">Microsoft.WSMan.Management\WSMan::localhost\Plugin</span><span class="w">

</span><span class="kr">Type</span><span class="w">            </span><span class="n">Keys</span><span class="w">                                </span><span class="nx">Name</span><span class="w">
</span><span class="o">----</span><span class="w">            </span><span class="o">----</span><span class="w">                                </span><span class="o">----</span><span class="w">
</span><span class="n">Container</span><span class="w">       </span><span class="p">{</span><span class="n">Name</span><span class="o">=</span><span class="n">ScheduledTasks</span><span class="p">}</span><span class="w">               </span><span class="n">ScheduledTasks</span><span class="w">
</span><span class="nx">WARNING:</span><span class="w"> </span><span class="nx">Set-PSSessionConfiguration</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">need</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">service</span><span class="w"> </span><span class="nx">if</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">configuration</span><span class="w"> </span><span class="nx">using</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">name</span><span class="w"> </span><span class="nx">has</span><span class="w"> </span><span class="nx">recently</span><span class="w"> </span><span class="nx">been</span><span class="w"> </span><span class="nx">unregistered</span><span class="p">,</span><span class="w"> </span><span class="nx">certain</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="nx">structures</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">still</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">cached.</span><span class="w"> </span><span class="nx">In</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">case</span><span class="p">,</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">required.</span><span class="w">
</span><span class="n">All</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">sessions</span><span class="w"> </span><span class="nx">connected</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">Windows</span><span class="w"> </span><span class="nx">PowerShell</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="p">,</span><span class="w"> </span><span class="nx">such</span><span class="w"> </span><span class="nx">as</span><span class="w"> </span><span class="nx">Microsoft.PowerShell</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">created</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">cmdlet</span><span class="p">,</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">disconnected.</span><span class="w">
</span><span class="n">WARNING:</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">need</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">service</span><span class="w"> </span><span class="nx">if</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">configuration</span><span class="w"> </span><span class="nx">using</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">name</span><span class="w"> </span><span class="nx">has</span><span class="w"> </span><span class="nx">recently</span><span class="w"> </span><span class="nx">been</span><span class="w"> </span><span class="nx">unregistered</span><span class="p">,</span><span class="w"> </span><span class="nx">certain</span><span class="w"> </span><span class="nx">system</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="nx">structures</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">still</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">cached.</span><span class="w"> </span><span class="nx">In</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">case</span><span class="p">,</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">restart</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">may</span><span class="w"> </span><span class="nx">be</span><span class="w"> </span><span class="nx">required.</span><span class="w">
</span><span class="n">All</span><span class="w"> </span><span class="nx">WinRM</span><span class="w"> </span><span class="nx">sessions</span><span class="w"> </span><span class="nx">connected</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">Windows</span><span class="w"> </span><span class="nx">PowerShell</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="p">,</span><span class="w"> </span><span class="nx">such</span><span class="w"> </span><span class="nx">as</span><span class="w"> </span><span class="nx">Microsoft.PowerShell</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="nx">configurations</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">created</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">Register-PSSessionConfiguration</span><span class="w"> </span><span class="nx">cmdlet</span><span class="p">,</span><span class="w"> </span><span class="nx">are</span><span class="w"> </span><span class="nx">disconnected.</span><span class="w">


</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\WindowsPowerShell\Modules\JEA</span><span class="err">&gt;</span></code></pre></figure>

<p>Note that this configuration gives access to two cmdlets <strong>Get-ScheduledTask</strong> and <strong>Get-Help</strong>. The latter is included to allow showing help for the two exposed functions.</p>

<p>It also gives access to three functions <strong>Register-RestrictedScheduledTask</strong>, <strong>Get-ScheduledTaskPermissions</strong>, and <strong>Claim-ScheduledTask</strong>. (The latter cmdlet might need a cooler name.)</p>

<p><strong>Register-RestrictedScheduledTask</strong> is simple: it just calls <strong>Register-ScheduledTask</strong> but will insist that the <strong>-Password</strong> parameter exists and that something is given as argument for it. (See <a href="https://developer.mozilla.org/en-US/docs/Glossary/Parameter">Parameters and Arguments</a>. It’s never quite clear to me.) Since system accounts don’t take a password, the user cannot register a scheduled task that runs as a system account. (The user can still register a scheduled task that runs as another privileged account, like a member of the Administrators group, but if the user knows such an account, then why does he bother using this JEA configuration?)</p>

<p><strong>Get-ScheduledTaskPermissions</strong> uses a COM (<a href="https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal">Component Object Model</a>) API to read scheduled task permissions and gets an SDDL (<a href="https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-definition-language">Security Descriptor Definition Language</a>) representation of the scheduled task’s security descriptor which it will then produly display. <strong>Set-ScheduledTaskPermissions</strong> uses the same API to set scheduled task permissions.</p>

<p><strong>Claim-ScheduledTask</strong> is a bit pseudo-clever. It also uses the COM API to modify scheduled task permissions . It gets an SDDL representation of the scheduled task’s security descriptor and modifies it by a) replacing the owner and b) inserting an entry at the beginning of the access control list giving the new owner full access. Then it writes the SDDL back into the scheduled task COM object.</p>

<p>Note that you understood correctly: This <strong>does</strong> allow the user to annex any scheduled task he wants. (Modify the cmdlet code if you want to prevent this.) But he cannot change what it does and and keep it running under an account of which he does not know the password. So, yes, the user can cause damage with this cmdlet. Deploy with care!</p>

<p>Make sure your user is in both the <strong>Remote Management Users</strong> and <strong>JEA_ScheduledTasks</strong> groups and:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w">
</span><span class="n">achaemenes\benoit</span><span class="w">
</span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">whoami</span><span class="w"> </span><span class="nx">/priv</span><span class="w">

</span><span class="n">PRIVILEGES</span><span class="w"> </span><span class="nx">INFORMATION</span><span class="w">
</span><span class="o">----------------------</span><span class="w">

</span><span class="n">Privilege</span><span class="w"> </span><span class="nx">Name</span><span class="w">                </span><span class="nx">Description</span><span class="w">                          </span><span class="nx">State</span><span class="w">
</span><span class="o">=============================</span><span class="w"> </span><span class="o">====================================</span><span class="w"> </span><span class="o">========</span><span class="w">
</span><span class="n">SeShutdownPrivilege</span><span class="w">           </span><span class="nx">Shut</span><span class="w"> </span><span class="nx">down</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">system</span><span class="w">                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeChangeNotifyPrivilege</span><span class="w">       </span><span class="nx">Bypass</span><span class="w"> </span><span class="nx">traverse</span><span class="w"> </span><span class="nx">checking</span><span class="w">             </span><span class="nx">Enabled</span><span class="w">
</span><span class="n">SeUndockPrivilege</span><span class="w">             </span><span class="nx">Remove</span><span class="w"> </span><span class="nx">computer</span><span class="w"> </span><span class="nx">from</span><span class="w"> </span><span class="nx">docking</span><span class="w"> </span><span class="nx">station</span><span class="w"> </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeIncreaseWorkingSetPrivilege</span><span class="w"> </span><span class="nx">Increase</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">process</span><span class="w"> </span><span class="nx">working</span><span class="w"> </span><span class="nx">set</span><span class="w">       </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">SeTimeZonePrivilege</span><span class="w">           </span><span class="nx">Change</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">time</span><span class="w"> </span><span class="nx">zone</span><span class="w">                 </span><span class="nx">Disabled</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="o">=</span><span class="n">New-PSSession</span><span class="w"> </span><span class="nt">-ConfigurationName</span><span class="w"> </span><span class="nx">ScheduledTasks</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$action</span><span class="o">=</span><span class="n">New-ScheduledTaskAction</span><span class="w"> </span><span class="nt">-Execute</span><span class="w"> </span><span class="s2">"cmd.exe"</span><span class="w"> </span><span class="nt">-Argument</span><span class="w"> </span><span class="s2">"/c cls"</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task</span><span class="o">=</span><span class="n">New-ScheduledTask</span><span class="w"> </span><span class="nt">-Action</span><span class="w"> </span><span class="nv">$action</span><span class="w"> </span><span class="nt">-Settings</span><span class="w"> </span><span class="p">(</span><span class="n">New-ScheduledTaskSettingsSet</span><span class="p">)</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="kr">param</span><span class="p">(</span><span class="nv">$task</span><span class="p">);</span><span class="w"> </span><span class="n">Register-RestrictedScheduledTask</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="w"> </span><span class="nt">-User</span><span class="w"> </span><span class="nx">benoit</span><span class="w"> </span><span class="nt">-InputObject</span><span class="w"> </span><span class="nv">$task</span><span class="p">}</span><span class="w"> </span><span class="nt">-ArgumentList</span><span class="w"> </span><span class="nv">$task</span><span class="w">

</span><span class="n">cmdlet</span><span class="w"> </span><span class="nx">Register-RestrictedScheduledTask</span><span class="w"> </span><span class="nx">at</span><span class="w"> </span><span class="nx">command</span><span class="w"> </span><span class="nx">pipeline</span><span class="w"> </span><span class="nx">position</span><span class="w"> </span><span class="nx">1</span><span class="w">
</span><span class="n">Supply</span><span class="w"> </span><span class="nx">values</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">following</span><span class="w"> </span><span class="nx">parameters:</span><span class="w">
</span><span class="n">Password:</span><span class="w"> </span><span class="nx">BenoitsSecretPassword</span><span class="w">

</span><span class="n">TaskPath</span><span class="w">                                       </span><span class="nx">TaskName</span><span class="w">                          </span><span class="nx">State</span><span class="w">      </span><span class="nx">PSComputerName</span><span class="w">
</span><span class="o">--------</span><span class="w">                                       </span><span class="o">--------</span><span class="w">                          </span><span class="o">-----</span><span class="w">      </span><span class="o">--------------</span><span class="w">
</span><span class="n">\</span><span class="w">                                              </span><span class="nx">BenoitTask</span><span class="w">                        </span><span class="nx">Ready</span><span class="w">      </span><span class="nx">localhost</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="n">Get-ScheduledTask</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="p">}</span><span class="w">

</span><span class="n">TaskPath</span><span class="w">                                       </span><span class="nx">TaskName</span><span class="w">                          </span><span class="nx">State</span><span class="w">      </span><span class="nx">PSComputerName</span><span class="w">
</span><span class="o">--------</span><span class="w">                                       </span><span class="o">--------</span><span class="w">                          </span><span class="o">-----</span><span class="w">      </span><span class="o">--------------</span><span class="w">
</span><span class="n">\</span><span class="w">                                              </span><span class="nx">BenoitTask</span><span class="w">                        </span><span class="nx">Ready</span><span class="w">      </span><span class="nx">localhost</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="n">Get-ScheduledTaskPermissions</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="p">}</span><span class="w">
</span><span class="n">O:S-1-5-94-3G:S-1-5-94-3D:</span><span class="p">(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">BA</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">SY</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="n">FA</span><span class="p">;;;</span><span class="n">S-1-5-94-3</span><span class="p">)(</span><span class="n">A</span><span class="p">;;</span><span class="n">FR</span><span class="p">;;;</span><span class="n">S-1-5-21-2059049455-1877585131-3415813230-1007</span><span class="p">)</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="n">Claim-ScheduledTask</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="p">}</span><span class="w">
</span><span class="n">Writing</span><span class="w"> </span><span class="nx">security</span><span class="w"> </span><span class="nx">descriptor</span><span class="w"> </span><span class="p">[</span><span class="n">O:S-1-5-21-2059049455-1877585131-3415813230-1007G:S-1-5-94-3D:</span><span class="p">(</span><span class="n">A</span><span class="p">;;</span><span class="n">FA</span><span class="p">;;;</span><span class="n">S-1-5-21-2059049455-1877585131-3415813230-1007</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">BA</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">SY</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="n">FA</span><span class="p">;;;</span><span class="n">S-1-5-94-3</span><span class="p">)(</span><span class="n">A</span><span class="p">;;</span><span class="n">FR</span><span class="p">;;;</span><span class="n">S-1-5-21-2059049455-1877585131-3415813230-1007</span><span class="p">)]</span><span class="w"> </span><span class="n">into</span><span class="w"> </span><span class="n">scheduled</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="p">[</span><span class="n">BenoitTask</span><span class="p">]</span><span class="o">.</span><span class="w"> </span><span class="n">Press</span><span class="w"> </span><span class="n">ctrl</span><span class="o">+</span><span class="n">c</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">cancel.:</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="n">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="n">Get</span><span class="nt">-ScheduledTaskPermissions</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="n">BenoitTask</span><span class="p">}</span><span class="w">
</span><span class="n">O:S-1-5-21-2059049455-1877585131-3415813230-1007G:S-1-5-94-3D:AI</span><span class="p">(</span><span class="n">A</span><span class="p">;;</span><span class="n">FA</span><span class="p">;;;</span><span class="n">S-1-5-21-2059049455-1877585131-3415813230-1007</span><span class="p">)(</span><span class="n">A</span><span class="p">;;</span><span class="n">FR</span><span class="p">;;;</span><span class="n">S-1-5-21-2059049455-1877585131-3415813230-1007</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">BA</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="mi">0</span><span class="n">x1f019f</span><span class="p">;;;</span><span class="n">SY</span><span class="p">)(</span><span class="n">A</span><span class="p">;</span><span class="n">ID</span><span class="p">;</span><span class="n">FA</span><span class="p">;;;</span><span class="n">S-1-5-94-3</span><span class="p">)</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="n">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>Observe how user <em>benoit</em> can register a scheduled task. With the the <strong>-Force</strong> parameter set, it will also overwrite an existing scheduled task.</p>

<p>To modify a task, benoit can <strong>Get-ScheduledTask</strong> it, modify the task object and then <strong>Register-RestrictedScheduledTask -Force</strong> it:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task1</span><span class="o">=</span><span class="n">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="n">Get-ScheduledTask</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="p">}</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task1</span><span class="w">

</span><span class="n">TaskPath</span><span class="w">                                       </span><span class="nx">TaskName</span><span class="w">                          </span><span class="nx">State</span><span class="w">      </span><span class="nx">PSComputerName</span><span class="w">
</span><span class="o">--------</span><span class="w">                                       </span><span class="o">--------</span><span class="w">                          </span><span class="o">-----</span><span class="w">      </span><span class="o">--------------</span><span class="w">
</span><span class="n">\</span><span class="w">                                              </span><span class="nx">BenoitTask</span><span class="w">                        </span><span class="nx">Ready</span><span class="w">      </span><span class="nx">localhost</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task1</span><span class="o">.</span><span class="nf">Actions</span><span class="w">

</span><span class="n">Id</span><span class="w">               </span><span class="p">:</span><span class="w">
</span><span class="n">Arguments</span><span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="nx">/c</span><span class="w"> </span><span class="nx">cls</span><span class="w">
</span><span class="n">Execute</span><span class="w">          </span><span class="p">:</span><span class="w"> </span><span class="nx">cmd.exe</span><span class="w">
</span><span class="n">WorkingDirectory</span><span class="w"> </span><span class="p">:</span><span class="w">
</span><span class="n">PSComputerName</span><span class="w">   </span><span class="p">:</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$action</span><span class="o">=</span><span class="n">New-ScheduledTaskAction</span><span class="w"> </span><span class="nt">-Execute</span><span class="w"> </span><span class="s2">"cmd.exe"</span><span class="w"> </span><span class="nt">-Argument</span><span class="w"> </span><span class="s2">"/c echo foo"</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task1</span><span class="o">.</span><span class="nf">Actions</span><span class="o">=</span><span class="nv">$action</span><span class="w">

</span><span class="n">TaskPath</span><span class="w">                                       </span><span class="nx">TaskName</span><span class="w">                          </span><span class="nx">State</span><span class="w">      </span><span class="nx">PSComputerName</span><span class="w">
</span><span class="o">--------</span><span class="w">                                       </span><span class="o">--------</span><span class="w">                          </span><span class="o">-----</span><span class="w">      </span><span class="o">--------------</span><span class="w">
</span><span class="n">\</span><span class="w">                                              </span><span class="nx">BenoitTask</span><span class="w">                        </span><span class="nx">Ready</span><span class="w">      </span><span class="nx">localhost</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$task1</span><span class="o">.</span><span class="nf">Actions</span><span class="w">

</span><span class="n">Id</span><span class="w">               </span><span class="p">:</span><span class="w">
</span><span class="n">Arguments</span><span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="nx">/c</span><span class="w"> </span><span class="nx">echo</span><span class="w"> </span><span class="nx">foo</span><span class="w">
</span><span class="n">Execute</span><span class="w">          </span><span class="p">:</span><span class="w"> </span><span class="nx">cmd.exe</span><span class="w">
</span><span class="n">WorkingDirectory</span><span class="w"> </span><span class="p">:</span><span class="w">
</span><span class="n">PSComputerName</span><span class="w">   </span><span class="p">:</span><span class="w">

</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nv">$scheduledtasks</span><span class="w"> </span><span class="p">{</span><span class="kr">param</span><span class="p">(</span><span class="nv">$task</span><span class="p">);</span><span class="w"> </span><span class="n">Register-RestrictedScheduledTask</span><span class="w"> </span><span class="nt">-TaskName</span><span class="w"> </span><span class="nx">BenoitTask</span><span class="w"> </span><span class="nt">-User</span><span class="w"> </span><span class="nx">benoit</span><span class="w"> </span><span class="nt">-Password</span><span class="w"> </span><span class="nx">BenoitsSecretPassword</span><span class="w"> </span><span class="nt">-InputObject</span><span class="w"> </span><span class="nv">$task</span><span class="w"> </span><span class="nt">-Force</span><span class="p">}</span><span class="w"> </span><span class="nt">-ArgumentList</span><span class="w"> </span><span class="nv">$task</span><span class="w">

</span><span class="n">TaskPath</span><span class="w">                                       </span><span class="nx">TaskName</span><span class="w">                          </span><span class="nx">State</span><span class="w">      </span><span class="nx">PSComputerName</span><span class="w">
</span><span class="o">--------</span><span class="w">                                       </span><span class="o">--------</span><span class="w">                          </span><span class="o">-----</span><span class="w">      </span><span class="o">--------------</span><span class="w">
</span><span class="n">\</span><span class="w">                                              </span><span class="nx">BenoitTask</span><span class="w">                        </span><span class="nx">Ready</span><span class="w">      </span><span class="nx">localhost</span><span class="w">


</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span></code></pre></figure>

<p>The task now does a “cmd.exe /c echo foo” instead of the original “cmd.exe /c cls”. (But it is running as the account given to it when registering it after modification.)</p>

<p>And if user benoit needs to have access to this (or any other) scheduled task in the Task Scheduler GUI (or with PowerShell but without JEA) <strong>Claim-ScheduledTask</strong> annexes the scheduled task to him and grants him access.</p>

<p><strong>Note again that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it is wrong or dangerous or will lead to disaster or confusion. I am not taking responsibility here for anything.</strong></p>

<p>Happy new year, everyone!</p>

<p>P.S.: In case you ever wondered. The “Run with highest privileges” checkbox in Task Scheduler does nothing to non-interactive scheduled tasks (batch jobs). What it does do is affect interactive scheduled tasks. It only becomes relevant when “Run only when user is logged on” is selected (instead of “Run whether user is logged on or not”). It acts as a preemptive OK to a UAC prompt that might otherwise prevent the interactive process from running elevated. I don’t know where this is properly documented.</p>

<p>Next: <a href="../sudo/">Windows Sudo</a></p>]]></content><author><name></name></author><category term="JEA" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!]]></summary></entry><entry><title type="html">Windows - Help</title><link href="http://localhost:4000/WindowsBlog/help/" rel="alternate" type="text/html" title="Windows - Help" /><published>2025-12-28T00:00:00+01:00</published><updated>2025-12-28T00:00:00+01:00</updated><id>http://localhost:4000/WindowsBlog/Help</id><content type="html" xml:base="http://localhost:4000/WindowsBlog/help/"><![CDATA[<p><strong>Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!</strong></p>

<p>Windows Help is not always up-to-date.</p>

<p>You have probably seen something like this:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Help</span><span class="w"> </span><span class="nx">Get-VM</span><span class="w">

</span><span class="n">NAME</span><span class="w">
    </span><span class="nx">Get-VM</span><span class="w">

</span><span class="n">SYNTAX</span><span class="w">
    </span><span class="nx">Get-VM</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Name</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">string</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-CimSession</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimSession</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-ComputerName</span><span class="w"> </span><span class="err">&lt;</span><span class="n">string</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-Credential</span><span class="w"> </span><span class="err">&lt;</span><span class="n">pscredential</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w">  </span><span class="p">[</span><span class="err">&lt;</span><span class="n">CommonParameters</span><span class="err">&gt;</span><span class="p">]</span><span class="w">

    </span><span class="n">Get-VM</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Id</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">guid</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-CimSession</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimSession</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-ComputerName</span><span class="w"> </span><span class="err">&lt;</span><span class="n">string</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-Credential</span><span class="w"> </span><span class="err">&lt;</span><span class="n">pscredential</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w">  </span><span class="p">[</span><span class="err">&lt;</span><span class="n">CommonParameters</span><span class="err">&gt;</span><span class="p">]</span><span class="w">

    </span><span class="n">Get-VM</span><span class="w"> </span><span class="p">[</span><span class="nt">-ClusterObject</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">ClusterObject</span><span class="err">&gt;</span><span class="w">  </span><span class="p">[</span><span class="err">&lt;</span><span class="n">CommonParameters</span><span class="err">&gt;</span><span class="p">]</span><span class="w">


</span><span class="n">ALIASES</span><span class="w">
    </span><span class="nx">gvm</span><span class="w">


</span><span class="n">REMARKS</span><span class="w">
    </span><span class="nx">Get-Help</span><span class="w"> </span><span class="nx">cannot</span><span class="w"> </span><span class="nx">find</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">Help</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">cmdlet</span><span class="w"> </span><span class="nx">on</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">computer.</span><span class="w"> </span><span class="nx">It</span><span class="w"> </span><span class="nx">is</span><span class="w"> </span><span class="nx">displaying</span><span class="w"> </span><span class="nx">only</span><span class="w"> </span><span class="nx">partial</span><span class="w"> </span><span class="nx">help.</span><span class="w">
        </span><span class="o">--</span><span class="w"> </span><span class="n">To</span><span class="w"> </span><span class="nx">download</span><span class="w"> </span><span class="nx">and</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">Help</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">module</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">includes</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">cmdlet</span><span class="p">,</span><span class="w"> </span><span class="nx">use</span><span class="w"> </span><span class="nx">Update-Help.</span></code></pre></figure>

<p>Apparently the idea is that Windows does not ship with the help files for PowerShell cmdlets because they might be outdated. That is, the help files would be of the same (by then outdated) version as the cmdlets they describe.</p>

<p>By forcing you to <strong>Update-Help</strong>, MSFT make sure that you have the current version of help files, i.e. help files for newer versions of the cmdlets which you likely don’t have, unless you have also updated the cmdlets.</p>

<p>But this is not the only oddity concerning PowerShell help files. Look at this:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">Get-Help</span><span class="w"> </span><span class="nx">New-ScheduledTask</span><span class="w">

</span><span class="n">NAME</span><span class="w">
    </span><span class="nx">New-ScheduledTask</span><span class="w">

</span><span class="n">SYNOPSIS</span><span class="w">
    </span><span class="nx">Creates</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">scheduled</span><span class="w"> </span><span class="nx">task</span><span class="w"> </span><span class="nx">instance.</span><span class="w">


</span><span class="n">SYNTAX</span><span class="w">
    </span><span class="nx">New-ScheduledTask</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Action</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimInstance</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-AsJob</span><span class="w"> </span><span class="err">&lt;</span><span class="n">SwitchParameter</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-CimSession</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimSession</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Description</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">String</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Principal</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimInstance</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Settings</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimInstance</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="nt">-ThrottleLimit</span><span class="w">
    </span><span class="err">&lt;</span><span class="n">Int32</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[[</span><span class="nt">-Trigger</span><span class="p">]</span><span class="w"> </span><span class="err">&lt;</span><span class="n">CimInstance</span><span class="p">[]</span><span class="err">&gt;</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="err">&lt;</span><span class="n">CommonParameters</span><span class="err">&gt;</span><span class="p">]</span><span class="w">


</span><span class="n">DESCRIPTION</span><span class="w">
    </span><span class="nx">The</span><span class="w"> </span><span class="o">**</span><span class="nx">New-ScheduledTask</span><span class="o">**</span><span class="w"> </span><span class="nx">cmdlet</span><span class="w"> </span><span class="nx">creates</span><span class="w"> </span><span class="nx">an</span><span class="w"> </span><span class="nx">object</span><span class="w"> </span><span class="nx">that</span><span class="w"> </span><span class="nx">contains</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">definition</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">scheduled</span><span class="w"> </span><span class="nx">task.</span><span class="w"> </span><span class="o">**</span><span class="nx">New-ScheduledTask</span><span class="o">**</span><span class="w"> </span><span class="nx">does</span><span class="w"> </span><span class="nx">not</span><span class="w"> </span><span class="nx">automatically</span><span class="w"> </span><span class="nx">register</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">object</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">Task</span><span class="w"> </span><span class="nx">Scheduler</span><span class="w"> </span><span class="nx">service.</span><span class="w">

    </span><span class="n">You</span><span class="w"> </span><span class="nx">can</span><span class="w"> </span><span class="nx">register</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">task</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">run</span><span class="w"> </span><span class="nx">any</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">following</span><span class="w"> </span><span class="nx">application</span><span class="w"> </span><span class="nx">or</span><span class="w"> </span><span class="nx">file</span><span class="w"> </span><span class="nx">types:</span><span class="w"> </span><span class="nx">Win32</span><span class="w"> </span><span class="nx">applications</span><span class="p">,</span><span class="w"> </span><span class="nx">Win16</span><span class="w"> </span><span class="nx">applications</span><span class="p">,</span><span class="w"> </span><span class="nx">OS/2</span><span class="w"> </span><span class="nx">applications</span><span class="p">,</span><span class="w"> </span><span class="nx">MS-DOS</span><span class="w"> </span><span class="nx">applications</span><span class="p">,</span><span class="w"> </span><span class="nx">batch</span><span class="w"> </span><span class="nx">files</span><span class="w"> </span><span class="p">(</span><span class="o">*.</span><span class="nf">bat</span><span class="p">),</span><span class="w"> </span><span class="kr">command</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="p">(</span><span class="o">*.</span><span class="nf">cmd</span><span class="p">),</span><span class="w">
    </span><span class="n">or</span><span class="w"> </span><span class="nx">any</span><span class="w"> </span><span class="nx">properly</span><span class="w"> </span><span class="nx">registered</span><span class="w"> </span><span class="nx">file</span><span class="w"> </span><span class="nx">type.</span></code></pre></figure>

<p>Really? You can register a scheduled task of the application type “OS/2 applications”? Even Win16 applications are not working on 64 bit Windows. But OS/2 applications have not been supported by Windows NT since Windows 2000. I am not sure if there even was a version of Windows that supported both the OS/2 subsystem <strong>and</strong> PowerShell.</p>

<p><br />
<strong>Windows-on-Windows-64</strong></p>

<p>For some reason Server Manager thinks that removing WoW64 (the system component that runs 32 bit programs) would remove the entire GUI.</p>

<p><img src="../assets/images/WoW64FeatureHelp.png" alt="image" /></p>

<p>But it does not.</p>

<p>Of course, some people would love to be able to convert a desktop server into a core server.</p>

<p><br />
Next: <a href="../scheduledtasksjea/">Scheduled Tasks JEA</a></p>]]></content><author><name></name></author><category term="Windows" /><summary type="html"><![CDATA[Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!]]></summary></entry></feed>