Skip to content

Commit 4eb9ab0

Browse files
committed
Add #requires RFC draft
1 parent 73d3ceb commit 4eb9ab0

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
RFC: RFC
3+
Author: Robert Holt
4+
Status: Draft
5+
SupercededBy:
6+
Version:
7+
Area: \#requires
8+
Comments Due: 2018-05-15
9+
Plan to implement: Yes
10+
---
11+
12+
# \#Requires Additions
13+
14+
Currently, PowerShell's `#requires` statement (or perhaps
15+
pragma?) supports the following parameters:
16+
17+
* `-Version <N>[.<n>]`, where a minimum PowerShell version can be specified
18+
* `-PSSnapin <PSSnapin-Name> [-Version <N><n>]`, where a required PowerShell Snapin can be specified
19+
* `-Modules { <Module-name> | <Hashtable> }`, where PowerShell modules that are required can be specified
20+
* `-ShellId <ShellId>`, where the required Shell ID can be specified
21+
* `-RunAsAdministrator`, where the script is required to be run as administrator
22+
23+
These features are documented in [about_Requires](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-6), along with the statement that:
24+
25+
> You can use #Requires statements in any script. You
26+
> cannot use them in functions, cmdlets, or snap-ins.
27+
28+
Currently however, this is untrue, as `#requires`
29+
statements are effectively hoisted to the top of any
30+
script, no matter where they are placed in that script.
31+
32+
This RFC proposes the following changes:
33+
34+
* Only allow `#requires` at the top level of a script,
35+
before any lines that are not comments (i.e. with the
36+
intention that a hashbang can still work, just before
37+
any executable PowerShell code). Placing `#requires`
38+
anywhere will cause a parse-time error. This would be
39+
a **breaking change**, albeit one that the documentation
40+
already claims to be in force.
41+
* Using `#requires` in the interactive console will cause
42+
a parse-time error. This could be a **minor breaking
43+
change**, since currently PowerShell throws a [pipeline
44+
creation error](https://github.com/PowerShell/PowerShell/issues/3803).
45+
* Add support for the following new parameters (each
46+
independently up for discussion):
47+
* `-OS {Windows | Linux | MacOS}`, where an
48+
operating system (or possibly combination of them) can
49+
be specified as required. See [this PowerShell issue](https://github.com/PowerShell/PowerShell/issues/3751).
50+
* `-Assembly <Assembly-name>`, where a .NET assembly can
51+
be specified as required. See [this PowerShell issue](https://github.com/PowerShell/PowerShell/issues/5022).
52+
* `-MaxVersion <V>[.<v>]`, where a maximum PowerShell
53+
version can be specified as required. See [this PowerShell issue](https://github.com/PowerShell/PowerShell/issues/2846).
54+
55+
## Motivation
56+
57+
> As a PowerShell user, I can be sure that all the
58+
> `#requires` statements in a script come before any
59+
> PowerShell code, so that it's clear they always
60+
> execute first, and so they can all be found easily.
61+
62+
> As a PowerShell user, I get feedback that `#requires`
63+
> statements cannot be used in the interactive console,
64+
> so that it's clear that they have no effect on an
65+
> interactive session.
66+
67+
> As a PowerShell user, I can specify that my script
68+
> `#requires` being run on a specific operating system,
69+
> so that I can effectively, efficiently and declaratively
70+
> guarantee that it is used only on systems I designed it
71+
> for.
72+
73+
> As a PowerShell user, I can specify that my script
74+
> `#requires` a given .NET Assembly to run in an
75+
> efficient and declarative way, so that I don't have
76+
> to do complex runtime logic to determine my script
77+
> cannot run.
78+
79+
> As a PowerShell user, I can specify that my script
80+
> `#requires` to be run in a version of PowerShell
81+
> lower than a given version, so that I can declaratively
82+
> prevent it from being run in an environment where
83+
> changes to PowerShell would cause unintended behavior.
84+
85+
## Specification
86+
87+
1. `#requires` statements must appear in scripts
88+
above all executable PowerShell. Any `#requires`
89+
statement placed after any PowerShell code causes
90+
an unrecoverable parse-time error.
91+
2. Any use of `#requires` in an interactive session causes
92+
a specific parse-time error to be thrown, informing the
93+
user that `#requires` may not be used in the interactive
94+
console.
95+
3. `#requires` can take an `-OS` parameter, with possible
96+
arguments being `Windows`, `Linux` and `MacOS` (and
97+
possibly some syntax for `or`-ing them). This check
98+
succeeds if-and-only-if the correspoding runtime
99+
PowerShell variable (`$IsWindows`, `$IsLinux` and
100+
`$IsMacOS` is true). Requiring a given OS when the
101+
corresponding runtime variable is false results in
102+
a pre-execution error with a specific error message
103+
stating that the script is required to be run on a
104+
different operating system.
105+
4. `#requires` can take an `-Assembly` parameter, with
106+
possible arguments being exactly what a `using assembly`
107+
statement will accept. If a required assembly is not
108+
present on the executing system, a pre-execution error
109+
is raised.
110+
5. `#requires` can take a `-MaxVersion` parameter, with
111+
a major version and optional minor version, to define
112+
the maximum (inclusive) version of PowerShell it should
113+
run on. The version given does not need to correspond to
114+
any version of PowerShell, but will just be compared in
115+
standard lexicographic tuple order. Executing a script
116+
required to be on a version of PowerShell strictly lower
117+
than the executing version results in a pre-execution
118+
error.
119+
120+
Finally, scripts with `#requires` in them should still
121+
be editable in contexts that do not satisfy their
122+
requirements. For example, a script with `#requires -OS
123+
MacOS` at the top should still allow a full editing user
124+
experience on Windows or Linux. For context, see [this
125+
PowerShell issue](https://github.com/PowerShell/PowerShell/issues/4549).
126+
127+
## Alternate Proposals and Considerations
128+
129+
* An `-Assembly` parameter may be unneccessary, given the
130+
possibility of using `using assembly <Assembly-name>`.
131+
* Given the suite of proposed changes to `#requires`, any
132+
other proposed parameters for `#requires` are worth
133+
including and discussing in this RFC. Possible
134+
considerations are:
135+
* `-LanguageMode`, where a script must be run in a given
136+
PowerShell language mode.
137+
* `-Architecture`, where a script must be run on a
138+
machine with a given processor architecture.
139+
* `-Platform`, rather than trying to use combining
140+
logic with `-OS`.

0 commit comments

Comments
 (0)