How to Install AWS Tools for PowerShell for All Users on Windows
You end up with AWS.Tools in Program Files, where a task running as SYSTEM finds it; SYSTEM’s module path never includes your Documents folder.

On this page
TL;DR
Open the PowerShell edition your automation uses as Administrator, then install the modular S3 package for all users:
Install-Module -Name AWS.Tools.Installer -MinimumVersion 2.0.0 -MaximumVersion 2.9.999 `
-Repository PSGallery -Scope AllUsers -Force
Import-Module AWS.Tools.Installer -MinimumVersion 2.0.0 -MaximumVersion 2.9.999 `
-ErrorAction Stop
Install-AWSToolsModule -Name AWS.Tools.S3 -Version '5.*' -Scope AllUsersSwap AWS.Tools.S3 for the service module your script calls. An older 1.x
installer may already be there, and 1.x has no -Version parameter, so the
last line would fail with it. Without -Force, Install-Module only warns
that 1.x is already installed and leaves it. With -Force it installs 2.x
beside it, and the import line loads 2.x rather than 1.x. -MaximumVersion 2.9.999 on both lines, as in AWS’s own install command, keeps a future 3.x
out of a workflow written for 2.x.
Keep -Version '5.*'. Without it the installer takes the
latest major version, which can carry breaking changes, as AWS’s
Installer v2 announcement (opens in a new tab)
warns. With -Name it installs only the modules you name plus
AWS.Tools.Common, and leaves other AWS.Tools modules at their versions, so
name every module your tasks use together if they should move in step.
In Windows PowerShell 5.1, run this first:
$protocol = [Net.ServicePointManager]::SecurityProtocol
$tls12 = [Net.SecurityProtocolType]::Tls12
if ($protocol -ne 'SystemDefault' -and -not ($protocol -band $tls12)) {
[Net.ServicePointManager]::SecurityProtocol = $protocol -bor $tls12
}
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force | Out-NullThe if adds TLS 1.2 only when the session has neither it nor the operating
system’s default. It never removes a protocol, and it leaves the OS default
alone, as Microsoft’s
TLS guidance (opens in a new tab)
recommends, since that default can negotiate newer versions. The gallery needs
TLS 1.2, as Microsoft’s
PowerShell Gallery TLS post (opens in a new tab)
explains, and so does the NuGet provider download, which is why the check
comes first. On the test server it changed nothing. The last line installs the
NuGet provider, and does nothing where it’s already in place. If the gallery still can’t be reached after both, TLS
isn’t the cause; look at a proxy, DNS or a firewall. An install that reaches
the gallery and then fails is a different problem, such as the .NET or
PowerShellGet version the package requires.
Verify from a fresh session under the account that runs the task:
Import-Module AWS.Tools.S3 -ErrorAction Stop
(Get-Module AWS.Tools.S3).ModuleBaseThe path should start $env:ProgramFiles\WindowsPowerShell\Modules\ for
Windows PowerShell, or $env:ProgramFiles\PowerShell\Modules\ for PowerShell 7.
That’s C:\Program Files for a 64-bit host and C:\Program Files (x86) for a
32-bit one.
Note
Module availability and AWS authentication are separate problems that fail at different points. A task that imports the module and then reports access denied has finished with this article.
The script works in your terminal. Task Scheduler reports that Write-S3Object
isn’t recognized.
Before rewriting the script, check where you installed its dependencies. A module beneath your Documents folder is an installation for you. The scheduled task may run as someone else, using a different PowerShell executable.
Choose AWS.Tools for a new installation
AWS currently recommends AWS.Tools, with separate service modules such as
AWS.Tools.S3 and a shared AWS.Tools.Common dependency. The installer manages
dependencies and coordinates service-module versions. Follow the
AWS modular installation guide (opens in a new tab)
for that workflow.
For a script that uploads to S3, install S3. Add AWS.Tools.EC2 or another
service module when the script actually uses it.
The Windows installation options also include the large AWSPowerShell.NetCore
module and the legacy Windows-specific AWSPowerShell module. They are separate
packaging choices, not three prerequisites to install together. AWS lists them
in its Windows setup overview (opens in a new tab).
Use the same PowerShell host as the scheduled task
Check the shell before installing:
$PSVersionTable | Select-Object PSVersion, PSEdition
(Get-Process -Id $PID).Path
$env:PSModulePath -split ';'For new automation, use a supported PowerShell 7 release. For an existing Windows PowerShell 5.1 task, verify package and .NET requirements before changing its dependencies. Do not assume a package’s major-version upgrade is only a packaging change.
Typical system-wide module locations differ:
| Shell | Usual AllUsers location |
|---|---|
PowerShell 7 (pwsh.exe) | C:\Program Files\PowerShell\Modules |
Windows PowerShell 5.1 (powershell.exe) | C:\Program Files\WindowsPowerShell\Modules |
PowerShell discovers modules through $env:PSModulePath, and the sharing runs
one way: PowerShell 7 also searches the Windows PowerShell AllUsers folder, but
Windows PowerShell never searches PowerShell 7’s. A successful import in one
edition is not proof that the other can load the same installation. Microsoft documents the defaults and
startup behavior in about_PSModulePath (opens in a new tab).
Check the executable configured in Task Scheduler, including its architecture:
a 32-bit powershell.exe resolves Program Files to Program Files (x86). Use
that host for the verification below.
Install once in an elevated session
Run the commands in the answer box. Keep -Scope AllUsers on both installation
commands: installing the installer globally does not make the service package’s
scope implicit.
Install-Module comes from PowerShellGet. If it is missing, provision
PowerShellGet before running this workflow; an older installation may prompt
for a NuGet provider. Check that the repository is the one you intend to use:
Get-Command Install-Module
Get-PSRepository -Name PSGalleryReview the Gallery prompt when it appears. A one-time installation does not
require changing the repository’s trust policy permanently. The installer
itself comes from PSGallery, but Install-AWSToolsModule downloads the service
modules as one archive from sdk-for-net.amazonwebservices.com, which its help
says, and not from PSGallery. A server behind a proxy needs that host allowed
as well as the Gallery’s own, which Microsoft lists under
network access to the PowerShell Gallery (opens in a new tab).
Microsoft’s
Install-Module documentation (opens in a new tab)
explains scope, repository selection, and installation prompts.
The installer pulls in AWS.Tools.Common with S3. You do not need to install
every AWS module. The example also omits -CleanUp, which removes older module
versions; decide on cleanup after checking whether existing jobs pin them.
Verify the module loads as the task account
Close the elevated session. You can’t open a console as SYSTEM, and a
scheduled task keeps none of its output. Put these lines at the top of the
task’s script, start it with Start-ScheduledTask, and read the log it writes:
& {
[Security.Principal.WindowsIdentity]::GetCurrent().Name
$env:PSModulePath -split ';'
Get-Module -ListAvailable AWS.Tools.Common, AWS.Tools.S3 |
Select-Object Name, Version, ModuleBase | Format-Table -AutoSize
Import-Module AWS.Tools.S3 -ErrorAction Stop
(Get-Module AWS.Tools.S3).ModuleBase
} *> (Join-Path $env:ProgramData 'aws-tools-check.log')Run as SYSTEM, the first line prints NT AUTHORITY\SYSTEM. On the test
server SYSTEM’s module path had no Documents folder in it at all. Where it has
one, it’s SYSTEM’s own profile, not yours, so a module you installed for
yourself is invisible to the task either way. The -ListAvailable call lists every copy the account can find; more than one
row per module means more than one installation. The last line is the copy that
actually loaded. These checks load code and resolve a command; they do not
contact S3.
For unattended work, put the explicit import in the script. That gives a missing or incompatible dependency a clear failure point before any work starts.
Where AWSPowerShell.NetCore still fits
An existing script may explicitly import AWSPowerShell.NetCore. If retaining
that package is part of maintaining the script, install it from the appropriate
elevated host:
Install-Module -Name AWSPowerShell.NetCore -Repository PSGallery -Scope AllUsersThat’s an alternative to the modular path. Start a fresh session before
switching package families; loading overlapping AWS assemblies and command
names complicates diagnosis. AWS still documents
AWSPowerShell.NetCore installation (opens in a new tab),
while directing new installations to AWS.Tools.
Common failures
Installation fails with access denied
The installation session isn’t elevated. The ordinary task doesn’t need administrator rights merely because an administrator installed its dependencies.
Module installed, but the task can’t find it
Compare the task’s
executable, account, module path, and ModuleBase with your interactive session.
Use the same verification commands in the task’s diagnostic output.
Import fails because script execution is disabled
Inspect
Get-ExecutionPolicy -List and follow the machine’s approved policy. Installation
scope and script-execution policy solve different problems.
Import works, but AWS reports missing credentials or access denied
The installation is no longer the issue. Configure authentication for the task’s identity and verify its permissions. Your interactive profile isn’t evidence that another account has working AWS access.
The useful completion check is the task account loading the expected module in the expected shell. An installer success message is only the first step.
Tested with
- OS
- Windows Server 2019 (10.0.17763)
- PowerShell
- Windows PowerShell 5.1
- AWS Tools
- AWS.Tools.Installer 2.0.5, AWS.Tools.S3 5.0.304
- Account
- SYSTEM, through a scheduled task
- Date
- October 2026