7

I have a script that calls another script (with arguments). The called script contains the Install-WindowsFeature cmdlet. When I run the script, the called script runs, but returns the following error:

Install-WindowsFeature : The term 'Install-WindowsFeature' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path

Of course, I can run the cmdlet just fine from a PowerShell console. I can also run the called script from a PowerShell console and Install-WindowsFeature works fine. So, is it something to do with calling a script from a script that runs a cmdlet? Here is my calling code:

$script = "C:\Path\script.ps1"
$argumentList = @()
$argumentlist += ("-Arg1", "value")
$argumentlist += ("-Arg2", "value")
$argumentlist += ("-Arg3", "value")
Invoke-Expression "$script $argumentList"

In the called script, I called Install-WindowsFeature as below:

if ($someValue) { Invoke-Command -ScriptBlock {Install-WindowsFeature -Name RSAT-AD-Tools} }

I've also tried it as below:

if ($someValue) { Install-WindowsFeature -Name RSAT-AD-Tools }

12/16/16 EDIT: This script is running in a GUI built with Sapien PowerShell Studio. When I change the build type to "Native" it works. I have to reset my lab to check, but I suspect it will also run if I just run it in the x64 context. This article explains why I think this matters.

Running on Windows Server 2012 R2

8
  • Run as admin? or perhaps provide credentials to run it as? Invoke-Command -Credential Commented Nov 11, 2016 at 8:52
  • @Kage I have tried that as well. Not sure if the cmdlet would just not be visible or if it would give an access denied error, but the behavior is the same regardless. Commented Nov 11, 2016 at 13:16
  • Have you tried running import-module servermanager in script.ps1 prior to the if statement? Commented Nov 11, 2016 at 18:30
  • @TonyHinkle Just got back to this project and added the command to script.ps1 and it gave the error "The specified module 'ServerManager' was not loaded because no valid module file was found in any module directory." It's like the script's running context doesn't see the environment/file system. Commented Dec 16, 2016 at 15:42
  • I don't know what to suggest at this point. I don't have test servers to try to repro this with. I'll put a bounty on this so it will get some attention. Commented Dec 16, 2016 at 16:09

3 Answers 3

3

Unless you've got a compelling reason for it, let's see if we can clean up your calling pattern a bit - and hopefully make your other issues go away by avoiding the contortionism.

Rather than creating your parameter list as a string, take advantage of parameter splatting. It's good to get out of the habit of treating PowerShell like other scripting languages that don't work with objects.

$splat = @{ 
    Arg1 = "value1";
    Arg2 = "value2";
    Arg3 = "value3"
    }

& c:\path\script.ps1 @splat

Using that on a script.ps1 something like this:

param(
    $Arg1,
    $Arg2,
    $Arg3
)

Write-Host "Arg1 = $Arg1, Arg2 = $Arg2, Arg3 = $Arg3

You'll get an expected output of:

Arg1 = value1, Arg2 = value2, Arg3 = value3

Once you've got that, there's probably no reason to use Invoke-Command on the call to Install-WindowsFeature, unless you're leaving out details like invoking remotely to a server. Invoke-Command { Install-WindowsFeature } still works fine for me on Server 2012R2 with PowerShell 5, and there's no reason it shouldn't.

This assumes you're running this script on a Server that support Install-WindowsFeature, as the other comments point out. Client Windows doesn't support Install-WindowsFeature, and the RSAT tools are installed via a stand-alone RSAT .MSU package, which you manage differently.

Install-WindowsFeature is natively provided with Server Manager on Server 2012R2 - there's no need to Import-Module... unless you've done something to your profile or fouled up your modules folders. One of the earlier versions of Windows Server needed it - but that was a couple versions back. Likewise, Add-WindowsFeature was the old name - and it's still available as an alias for Install-WindowsFeature.

I'm assuming you've tried Install-WindowsFeature directly from the command line to ensure it's in working order, and Get-Module Install-WindowsFeature looks reasonable.

PS C:\Windows\system32> get-module ServerManager

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     2.0.0.0    ServerManager                       {Get-WindowsFeature, Install-WindowsFeature, Uninstall-Win...

While we're on the topic, there's very little reason to drop to DISM on Server that supports Install-WindowsFeature, and a number of reasons not to.

  1. Server Manager and several other tools (including Win32_ServerFeature) rely on the feature states parsed and understood by the WMI provider used by Install-WindowsFeature. It's possible to enable the right set of features using DISM, but needs attention and detail. Enabling only "part" of a role and feature may get the functionality you want for specific cases, but the role or feature may not show up as installed in Get-WindowsFeature, may not be uninstallable via Remove-WindowsFeature, and may not offer relevant UI features in Server Manager like monitoring health of the role, viewing relevant events, or offering tools for administering it.

  2. Install-WindowsFeature integrates with additional code from the role & features you're installing, and may run additional health and pre-requisite checks to ensure your correctly configured.

  3. DISM featurenames tend to change more often than the role & feature name of Server Manager, so your script portability will be better.
    There are other points, but I won't go into them since DISM was primarily a comment fork.
Sign up to request clarification or add additional context in comments.

5 Comments

I was the development manager for Install-WindowsFeature, so the trouble you're having surprises me. I check back and see what we can do to get you sorted out.
Hello Matthew. Thanks for chiming in on this. Just to clarify, Install-WindowsFeature works fine from the command prompt. It only breaks when running the script in x32 mode (as x64 works fine). I was clued into this when Import-Module didn't work either. Also, I agree that as DISM is more of a legacy tool, Install-WindowsFeature is preferable.
I assumed it did - by streamlining your calling pattern you may avoid ending up in the x86 process, or at least reducing the moving parts and making whatever IS going wrong more obvious. :)
@McKenning, I'd still like to hear back if you figure out how you ended up in x86. That shouldn't be happening, unless there's code you left out.. I recommended eliminating the Invoke-Command as that's the only part that seems likely to cause your issue.
I can't comment yet to Martin on the other answer, but also wanted to point out another downside of using DISM to install Server Features. Both Server Manager and Win32_ServerFeature (WMI) rely on the same mechanism to determine what's installed on the system. Ultimately that goes to DISM, but it's tricky to get the right set of DISM features enabled so that we think the interconnected dependencies of the roles/features are correctly enabled. You can end up having partial functionality, but Server Manager may not show roles installed or offer their management and monitoring tooling.
2
+50

You are probably right, it seems like the script gets executed with x86 PowerShell. I want to share a snippet with you which I use for scripts that needs to run in a specific environment (e. g. x64 PowerShell).

The script restarts itself in a x64 PowerShell if its started as x86 process. Just put this at the top of your script:

# Reinvoke the script as x64 if its called from a x86 process.
if ($env:Processor_Architecture -eq "x86")
{
    &"$env:windir\sysnative\WindowsPowerShell\v1.0\powershell.exe" -noprofile -file $myinvocation.Mycommand.path -executionpolicy bypass
    exit
}

Also note that the Install-WindowsFeature cmdlet doesn't work on all windows versions so consider to use dism instead:

$featuresToInstall = @('RSAT-AD-Tools')

$dismParameter = @('/online', '/Enable-Feature', ($featuresToInstall | % { '/FeatureName:{0}' -f $_ }), '/NoRestart')
dism @dismParameter

7 Comments

Prior to Install-WindowsFeature, there was Add-WindowsFeature (for Windows Server 2008 R2). Using dism is only catering to Windows Server 2008 and earlier, which are out of support. That's fine as it goes if you need it, but for most environments Install-WindowsFeature should be fine. Especially since, with the push to more and more PowerShell cmdlets, dism might actually be the one going to way of the dodo in future versions.
@JeroenMostert In Windows 10, there is no Install-WindowsFeature cmdlet but a Enable-WindowsOptionalFeature. Thats why I prefer to use dism - its just the most reliable tool to install featues (in my experience).
Sorry, didn't consider the client OSes (I manage only from jump servers). Can you even install RSAT-AD-Tools on Windows 10, though?
I understand where you're coming from. At the same time, I'm still going to insist people install PowerShell 5 before I run my scripts, rather than, say, dropping down to cmd, which will always work. :-) (I'm teasing, I do understand where you're coming from.)
Just to chime in on this conversation, you can install RSAT on client OS (from win7) by installing an msu for that OS. I use this all the time to manage domains from a jump box. Also, I appreciate the code Martin shared to re-invoke based on architecture. That will come in handy to be sure.
|
2

The running environment determines what modules you have access to. When I created this project in PowerShell Studio, it took the default of x86 (a 32 bit environment). This worked but because I was running it on Windows Server 2012 R2 (a 64-bit environment) I did not have access to the powershell modules such as Import-Module and Install-WindowsFeature. Changing this to a x64 project resolved my issue.

In order to avoid this scenario, it is important to make sure you run PowerShell scripts and modules in the architecture that is native to the OS. You can do this by setting the project correctly (if using a tool like PowerShell Studio) or by verifying that you are running in the native mode for that OS with the code Martin Brandl provided.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.