Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion reference/5.1/Microsoft.PowerShell.Core/Save-Help.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ Accept wildcard characters: False
### -Module

Specifies modules for which this cmdlet downloads help. Enter one or more module names or name
patters in a comma-separated list or in a file that has one module name on each line. Wildcard
patterns in a comma-separated list or in a file that has one module name on each line. Wildcard
characters are permitted. You can also pipe module objects from the `Get-Module` cmdlet to
`Save-Help`.

Expand Down
2 changes: 1 addition & 1 deletion reference/7.4/Microsoft.PowerShell.Core/Save-Help.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ Accept wildcard characters: False
### -Module

Specifies modules for which this cmdlet downloads help. Enter one or more module names or name
patters in a comma-separated list or in a file that has one module name on each line. Wildcard
patterns in a comma-separated list or in a file that has one module name on each line. Wildcard
characters are permitted. You can also pipe module objects from the `Get-Module` cmdlet to
`Save-Help`.

Expand Down
2 changes: 1 addition & 1 deletion reference/7.5/Microsoft.PowerShell.Core/Save-Help.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ Accept wildcard characters: False
### -Module

Specifies modules for which this cmdlet downloads help. Enter one or more module names or name
patters in a comma-separated list or in a file that has one module name on each line. Wildcard
patterns in a comma-separated list or in a file that has one module name on each line. Wildcard
characters are permitted. You can also pipe module objects from the `Get-Module` cmdlet to
`Save-Help`.

Expand Down
2 changes: 1 addition & 1 deletion reference/7.6/Microsoft.PowerShell.Core/Save-Help.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ Accept wildcard characters: False
### -Module

Specifies modules for which this cmdlet downloads help. Enter one or more module names or name
patters in a comma-separated list or in a file that has one module name on each line. Wildcard
patterns in a comma-separated list or in a file that has one module name on each line. Wildcard
characters are permitted. You can also pipe module objects from the `Get-Module` cmdlet to
`Save-Help`.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Advisory Development Guidelines
ms.date: 10/05/2021
ms.date: 05/22/2025
title: Advisory Development Guidelines
---
# Advisory Development Guidelines
Expand All @@ -19,31 +19,30 @@ guidelines.
Because Windows PowerShell works directly with Microsoft .NET Framework objects, a .NET Framework
object is often available that exactly matches the type the user needs to perform a particular
operation. `InputObject` is the standard name for a parameter that takes such an object as input.
For example, the sample `Stop-Proc` cmdlet in the [StopProc Tutorial](./stopproc-tutorial.md)
defines an `InputObject` parameter of type Process that supports the input from the pipeline. The
user can get a set of process objects, manipulate them to select the exact objects to stop, and then
pass them to the `Stop-Proc` cmdlet directly.
For example, the sample `Stop-Proc` cmdlet in the [StopProc Tutorial][03] defines an `InputObject`
parameter of type Process that supports the input from the pipeline. The user can get a set of
process objects, manipulate them to select the exact objects to stop, and then pass them to the
`Stop-Proc` cmdlet directly.

### Support the Force Parameter (AD02)

Occasionally, a cmdlet needs to protect the user from performing a requested operation. Such a
cmdlet should support a **Force** parameter to allow the user to override that protection if the
user has permissions to perform the operation.

For example, the [Remove-Item](/powershell/module/microsoft.powershell.management/remove-item)
cmdlet does not normally remove a read-only file. However, this cmdlet supports a **Force**
parameter so a user can force removal of a read-only file. If the user already has permission to
modify the read-only attribute, and the user removes the file, use of the **Force** parameter
simplifies the operation. However, if the user does not have permission to remove the file, the
**Force** parameter has no effect.
For example, the [Remove-Item][18] cmdlet doesn't normally remove a read-only file. However, this
cmdlet supports a **Force** parameter so a user can force removal of a read-only file. If the user
already has permission to modify the read-only attribute, and the user removes the file, use of the
**Force** parameter simplifies the operation. However, if the user doesn't have permission to remove
the file, the **Force** parameter has no effect.

### Handle Credentials Through Windows PowerShell (AD03)

A cmdlet should define a `Credential` parameter to represent credentials. This parameter must be of
type [System.Management.Automation.PSCredential](/dotnet/api/System.Management.Automation.PSCredential)
and must be defined using a Credential attribute declaration. This support automatically prompts the
user for the user name, for the password, or for both when a full credential is not supplied
directly. For more information about the Credential attribute, see [Credential Attribute Declaration](./credential-attribute-declaration.md).
type [System.Management.Automation.PSCredential][15] and must be defined using a Credential
attribute declaration. This support automatically prompts the user for the user name, for the
password, or for both when a full credential isn't supplied directly. For more information about the
Credential attribute, see [Credential Attribute Declaration][01].

### Support Encoding Parameters (AD04)

Expand All @@ -53,12 +52,13 @@ encoded in the binary form.

### Test Cmdlets Should Return a Boolean (AD05)

Cmdlets that perform tests against their resources should return a [System.Boolean](/dotnet/api/System.Boolean)
type to the pipeline so that they can be used in conditional expressions.
Cmdlets that perform tests against their resources should return a [System.Boolean][06] type to the
pipeline so that they can be used in conditional expressions.

## Code Guidelines

The following guidelines should be considered when writing cmdlet code. When you find a guideline that applies to your situation, be sure to look at the Design guidelines for similar guidelines.
The following guidelines should be considered when writing cmdlet code. When you find a guideline
that applies to your situation, be sure to look at the Design guidelines for similar guidelines.

### Follow Cmdlet Class Naming Conventions (AC01)

Expand All @@ -68,100 +68,116 @@ developers using Windows PowerShell because cmdlets are public types.

#### Define a Cmdlet in the Correct Namespace

You normally define the class for a cmdlet in a .NET Framework namespace that appends ".Commands" to
You normally define the class for a cmdlet in a .NET Framework namespace that appends `.Commands` to
the namespace that represents the product in which the cmdlet runs. For example, cmdlets that are
included with Windows PowerShell are defined in the `Microsoft.PowerShell.Commands` namespace.

#### Name the Cmdlet Class to Match the Cmdlet Name

When you name the .NET Framework class that implements a cmdlet, name the class
"*\<Verb>**\<Noun>**\<Command>*", where you replace the *\<Verb>* and *\<Noun>* placeholders with
the verb and noun used for the cmdlet name. For example, the [Get-Process](/powershell/module/Microsoft.PowerShell.Management/Get-Process)
cmdlet is implemented by a class called `GetProcessCommand`.
`<Verb><Noun>Command`, where you replace the `<Verb>` and `<Noun>` placeholders with the verb and
noun used for the cmdlet name. For example, the [Get-Process][17] cmdlet is implemented by a class
called `GetProcessCommand`.

### If No Pipeline Input Override the BeginProcessing Method (AC02)

If your cmdlet does not accept input from the pipeline, processing should be implemented in the [System.Management.Automation.Cmdlet.BeginProcessing](/dotnet/api/System.Management.Automation.Cmdlet.BeginProcessing)
method. Use of this method allows Windows PowerShell to maintain ordering between cmdlets. The first
cmdlet in the pipeline always returns its objects before the remaining cmdlets in the pipeline get a
chance to start their processing.
If your cmdlet doesn't accept input from the pipeline, processing should be implemented in the
[System.Management.Automation.Cmdlet.BeginProcessing][09] method. Use of this method allows Windows
PowerShell to maintain ordering between cmdlets. The first cmdlet in the pipeline always returns its
objects before the remaining cmdlets in the pipeline get a chance to start their processing.

### To Handle Stop Requests Override the StopProcessing Method (AC03)

Override the [System.Management.Automation.Cmdlet.StopProcessing](/dotnet/api/System.Management.Automation.Cmdlet.StopProcessing)
method so that your cmdlet can handle stop signal. Some cmdlets take a long time to complete their
operation, and they let a long time pass between calls to the Windows PowerShell runtime, such as
when the cmdlet blocks the thread in long-running RPC calls. This includes cmdlets that make calls
to the [System.Management.Automation.Cmdlet.WriteObject](/dotnet/api/System.Management.Automation.Cmdlet.WriteObject)
method, to the [System.Management.Automation.Cmdlet.WriteError](/dotnet/api/System.Management.Automation.Cmdlet.WriteError)
method, and to other feedback mechanisms that may take a long time to complete. For these cases the
user might need to send a stop signal to these cmdlets.
Override the [System.Management.Automation.Cmdlet.StopProcessing][12] method so that your cmdlet can
handle stop signal. Some cmdlets take a long time to complete their operation, and they let a long
time pass between calls to the Windows PowerShell runtime, such as when the cmdlet blocks the thread
in long-running RPC calls. This includes cmdlets that make calls to the
[System.Management.Automation.Cmdlet.WriteObject][14] method, to the
[System.Management.Automation.Cmdlet.WriteError][13] method, and to other feedback mechanisms that
may take a long time to complete. For these cases the user might need to send a stop signal to these
cmdlets.

### Implement the IDisposable Interface (AC04)

If your cmdlet has objects that are not disposed of (written to the pipeline) by the [System.Management.Automation.Cmdlet.ProcessRecord](/dotnet/api/System.Management.Automation.Cmdlet.ProcessRecord)
method, your cmdlet might require additional object disposal. For example, if your cmdlet opens a
file handle in its [System.Management.Automation.Cmdlet.BeginProcessing](/dotnet/api/System.Management.Automation.Cmdlet.BeginProcessing)
method and keeps the handle open for use by the [System.Management.Automation.Cmdlet.ProcessRecord](/dotnet/api/System.Management.Automation.Cmdlet.ProcessRecord)
method, this handle has to be closed at the end of processing.

The Windows PowerShell runtime does not always call the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
method. For example, the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
method might not be called if the cmdlet is canceled midway through its operation or if a
terminating error occurs in any part of the cmdlet. Therefore, the .NET Framework class for a cmdlet
that requires object cleanup should implement the complete [System.IDisposable](/dotnet/api/System.IDisposable)
interface pattern, including the finalizer, so that the Windows PowerShell runtime can call both the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
and [System.IDisposable.Dispose*](/dotnet/api/System.IDisposable.Dispose) methods at the end of
processing.
If your cmdlet has objects that aren't disposed of (written to the pipeline) by the
[System.Management.Automation.Cmdlet.ProcessRecord][11] method, your cmdlet might require additional
object disposal. For example, if your cmdlet opens a file handle in its
[System.Management.Automation.Cmdlet.BeginProcessing][09] method and keeps the handle open for use
by the [System.Management.Automation.Cmdlet.ProcessRecord][11] method, this handle has to be closed
at the end of processing.

The Windows PowerShell runtime doesn't always call the
[System.Management.Automation.Cmdlet.EndProcessing][10] method. For example, the
[System.Management.Automation.Cmdlet.EndProcessing][10] method might not be called if the cmdlet is
canceled midway through its operation or if a terminating error occurs in any part of the cmdlet.
Therefore, the .NET Framework class for a cmdlet that requires object cleanup should implement the
complete [System.IDisposable][07] interface pattern, including the finalizer, so that the Windows
PowerShell runtime can call both the [System.Management.Automation.Cmdlet.EndProcessing][10] and
[System.IDisposable.Dispose*][08] methods at the end of processing.

### Use Serialization-friendly Parameter Types (AC05)

To support running your cmdlet on remote computers, use types that can be easily serialized on the
client computer and then rehydrated on the server computer. The follow types are
serialization-friendly.
To support running your cmdlet on remote computers, use types that can be serialized on the client
computer and then rehydrated on the server computer. The follow types are serialization-friendly.

Primitive types:

- Byte, SByte, Decimal, Single, Double, Int16, Int32, Int64, Uint16, UInt32, and UInt64.

- Boolean, Guid, Byte[], TimeSpan, DateTime, Uri, and Version.

- Char, String, XmlDocument.

Built-in rehydratable types:

- PSPrimitiveDictionary

- SwitchParameter

- PSListModifier

- PSCredential

- IPAddress, MailAddress

- CultureInfo

- X509Certificate2, X500DistinguishedName

- DirectorySecurity, FileSecurity, RegistrySecurity

Other types:

- SecureString

- Containers (lists and dictionaries of the above type)

### Use SecureString for Sensitive Data (AC06)

When handling sensitive data always use the [System.Security.Securestring](/dotnet/api/System.Security.SecureString)
data type. This could include pipeline input to parameters, as well as returning sensitive data to
the pipeline.
When handling sensitive data always use the [System.Security.SecureString][16] data type. This could
include pipeline input to parameters, as well as returning sensitive data to the pipeline.

## See Also

[Required Development Guidelines](./required-development-guidelines.md)
While .NET recommends against using **SecureString** for new development, PowerShell continues to
support the **SecureString** class for backward compatibility. Using a **SecureString** is still
more secure than using a plain text string. PowerShell still relies on the **SecureString** type to
avoid accidentally exposing the contents to the console or in logs. Use **SecureString** carefully,
because it can be easily converted to a plain text string. For a full discussion about using
**SecureString**, see the [System.Security.SecureString class][01] documentation.

[Strongly Encouraged Development Guidelines](./strongly-encouraged-development-guidelines.md)
## See Also

[Writing a Windows PowerShell Cmdlet](./writing-a-windows-powershell-cmdlet.md)
[Required Development Guidelines][02]

[Strongly Encouraged Development Guidelines][04]

[Writing a Windows PowerShell Cmdlet][05]

<!-- link references -->
[01]: ./credential-attribute-declaration.md
[02]: ./required-development-guidelines.md
[03]: ./stopproc-tutorial.md
[04]: ./strongly-encouraged-development-guidelines.md
[05]: ./writing-a-windows-powershell-cmdlet.md
[06]: xref:System.Boolean
[07]: xref:System.IDisposable
[08]: xref:System.IDisposable.Dispose
[09]: xref:System.Management.Automation.Cmdlet.BeginProcessing
[10]: xref:System.Management.Automation.Cmdlet.EndProcessing
[11]: xref:System.Management.Automation.Cmdlet.ProcessRecord
[12]: xref:System.Management.Automation.Cmdlet.StopProcessing
[13]: xref:System.Management.Automation.Cmdlet.WriteError%2A
[14]: xref:System.Management.Automation.Cmdlet.WriteObject%2A
[15]: xref:System.Management.Automation.PSCredential
[16]: xref:System.Security.SecureString
[17]: xref:Microsoft.PowerShell.Management.Get-Process
[18]: xref:Microsoft.PowerShell.Management.Remove-Item
19 changes: 10 additions & 9 deletions reference/docs-conceptual/security/security-features.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: PowerShell has several features designed to improve the security of your scripting environment.
ms.date: 09/19/2024
ms.date: 05/22/2025
title: PowerShell security features
---
# PowerShell security features
Expand All @@ -14,7 +14,7 @@ PowerShell loads configuration files and runs scripts. This feature helps preven
malicious scripts. You can use a Group Policy setting to set execution policies for computers and
users. Execution policies only apply to the Windows platform.

For more information see [about_Execution_Policies][02].
For more information, see [about_Execution_Policies][02].

## Use of the SecureString class

Expand All @@ -25,16 +25,17 @@ using passwords and rely on other means to authenticate, such as certificates or
authentication.

PowerShell continues to support the **SecureString** class for backward compatibility. Using a
**SecureString** is still more secure than using a plain text string. By default, PowerShell doesn't
show the unprotected value of a **SecureString** object. However, **SecureString** can be easily
converted to a plain text string. For a full discussion about using **SecureString**, see the
[System.Security.SecureString class][01] documentation.
**SecureString** is still more secure than using a plain text string. PowerShell still relies on the
**SecureString** type to avoid accidentally exposing the contents to the console or in logs. Use
**SecureString** carefully, because it can be easily converted to a plain text string. For a full
discussion about using **SecureString**, see the [System.Security.SecureString class][01]
documentation.

## Module and script block logging

Module Logging allows you to enable logging for selected PowerShell modules. This setting is
effective in all sessions on the computer. PowerShell records pipeline execution events for the
specified modules in the Windows PowerShell log in Event Viewer.
specified modules in the Windows PowerShell event log.

Script Block Logging enables logging for the processing of commands, script blocks, functions, and
scripts - whether invoked interactively, or through automation. PowerShell logs this information to
Expand All @@ -52,8 +53,8 @@ The Windows Antimalware Scan Interface (AMSI) is an API that allows applications
an antimalware scanner, such as Windows Defender, to scan for malicious payloads. Beginning with
PowerShell 5.1, PowerShell running on Windows 10 (and higher) passes all script blocks to AMSI.

PowerShell 7.3 extends the data that's sent to AMSI for inspection. It now includes all invocations
of .NET method members.
PowerShell 7.3 extends the data it sends to AMSI for inspection. It now includes all .NET method
invocations.

For more information about AMSI, see [How AMSI helps][09].

Expand Down
Loading