Cmdlets not found in command line but available in ISE - powershell

I'm trying to create an IIS application and app pool using PowerShell on a Windows Server 2008 R2 VM. The powershell script is as follows:
Param(
[string] $branchName,
[string] $sourceFolder
)
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Write-Warning "You do not have Administrator rights to run this script. `nPlease re-run this script as an Administrator."
Exit
}
$appPool = $branchName
$site = "Default Web Site"
#Add APPPool
New-WebAppPool -Name $appPool -Force
#Create Applications
New-WebApplication -Name $branchName -Site $site -PhysicalPath $sourceFolder - ApplicationPool $appPool -Force
If I run the script in the PowerShell ISE it works fine but if I run it from a command line (or a batch file using the command line) I get the error
The term New-WebAppPool is not recognized as the name of a cmdlet... etc.
Is there a way that the web administration cmdlets could be installed in the ISE but not the command line?

Assuming that you're using PowerShell v2 (the default version installed with Server 2008 R2) it's as #jisaak suspected: you need to import the module WebAdministration explicitly in your code:
Import-Module WebAdministration
ISE seems to do that automatically.
Another option would be to upgrade to PowerShell v4, which also automatically imports modules when one of their exported cmdlets is used.

For anyone interested, the answer was painfully simple. As suggested, the solution was to import the module, but there was an issue was that it wasn't available after closing the console and reopening it. To solve this I simply had to add the line into the powershell itself so it imports the module at every runtime.
Param(
[string] $branchName,
[string] $sourceFolder)
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Write-Warning "You do not have Administrator rights to run this script.`nPlease re-run this script as an Administrator."
Exit
}
$appPool = $branchName
$site = "Default Web Site"
*Import-Module WebAdministration*
#Add APPPool
New-WebAppPool -Name $appPool -Force
#Create Applications
New-WebApplication -Name $branchName -Site $site -PhysicalPath $sourceFolder - ApplicationPool $appPool -Force

Related

New-PSDrive doesn't work when script is run from network share, but does work when run on the local machine

Context: IT staff may or may not log in with a local administrator account and run the following script. Due to the way Windows credential caching works on a local admin account, a simple copy and paste of the files without hardcoded credentials from a UNC path may not work occasionally.
My workaround for this issue was to just create a PSDrive for the session using a set of credentials that are reserved exclusively for scripting and domain joins.
IT staff access this script from the same server (fileserver05). The script attempts to make a temporary map of fileserver05. Is it just looping and confusing itself, or what?
Function Install {
Start-Process net -wait -ArgumentList "use X /delete" -ErrorAction SilentlyContinue
Remove-PSDrive X -Force -ErrorAction SilentlyContinue
Try {
$agentPass = Read-Host -AsSecureString -Prompt "Deployment operations supervisor password"
$agentUser = 'domain.com\agent'
$agentCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $agentUser,$agentPass
New-PSDrive -Name "X" -PSProvider "FileSystem" -Root "\\fileserver05\Fileserver05\IT\Programs\Windows\Yardi CHECKscan Client" -Credential $agentCred -ErrorAction Stop
Write-Host 'Deploying CHECKscan client to local machine...'
Copy-Item -Path "X:\install.msi" -Destination "${env:TEMP}" -Force
Start-Process msiexec -Wait -ArgumentList "/i `"${env:TEMP}\install.msi`" /qn /norestart"
Write-Host 'Deploying connection settings to current and default user profile...'
Copy-Item -Path "X:\yCheckSettings.xml" -Destination "${env:APPDATA}" -Force
Copy-Item -Path "X:\yCheckSettings.xml" -Destination "C:\Users\Default\AppData\Roaming" -Force
}
Catch {
Write-Host ""
Write-Host "An error occured during installation" -BackgroundColor Red -ForegroundColor White
Write-Host "Ensure you have the correct credentials and a connection to the corporate network"
Write-Host "Ensure that paths to the installation files have not changed on the fileserver"
Write-Host ""
Install
}
}
Install
Please also note that ExecutionPolicy is set to Unrestricted.
If a staff member runs the script from the server, it fails and is unable to map the drive, therefore making the rest of the script not work. If a staff member takes the script and drags it to the local desktop, then runs it, it succeeds.
How can I make it so it can be ran from the server itself?

Start and Stop APP Pool Using Powershell on Remote Machine

I am trying to get PowerShell to stop and start an AppPool on a remote machine, after providing credentials.
Function To Start Application Pool:
Function fnStartApplicationPool([string]$appPoolName)
{
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Started')
{
Start-WebAppPool -Name $appPoolName
}
}
Function To Stop Application Pool:
Function fnStopApplicationPool([string]$appPoolName)
{
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Stopped')
{
Stop-WebAppPool -Name $appPoolName
}
}
My code that is not working:
if ($pathback -eq $false)
{
#Copying Data from Source to Destination
copy-Item -Recurse $backupsrc -Destination $backupdes
write-host "Backup Successful"
#Validating the apppool value
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Stopped')
{
#Stop apppool
Stop-WebAppPool -Name $appPoolName
write-host "AppPool Stopped Successfully"
}
#Copying Data from Source to Destination
#Start apppool
Start-WebAppPool -Name $appPoolName
write-host "AppPool Started Sucessfully"
cd c:\
}
For running a script remotely, you have to ensure that PS-Remoting is enabled.
Start Windows PowerShell as an administrator by right-clicking the Windows PowerShell shortcut and selecting Run As Administrator.
The WinRM service is configured for manual startup by default. You must change the startup type to Automatic and start the service on each computer you want to work with. At the PowerShell prompt, you can verify that the WinRM service is running using the following command:
get-service winrm
If the service is not running, please make it running by Start-Service winrm
To configure Windows PowerShell for remoting, type the following command:
Enable-PSRemoting –force
To enable authentication, you need to add the remote computer to the list of trusted hosts for the local computer in WinRM. To do so, type:
winrm s winrm/config/client '#{TrustedHosts="RemoteComputer"}'
Verify that the service on the remote host is running and is accepting requests by running the following command on the remote host:
winrm quickconfig
This command analyzes and configures the WinRM service.
In your case, you have to do all these in ServerB because ServerB has to trust ServerA.
After doing these, you can run the below script from ServerA. Certain points I have added in the script itself for your reference. You can change the placeholders according to your requirement.
# Embedding the password in the script.
# If you do not have a domain creds, then use the username and password directly.
$MyDomain='MyDomain' ;
$MyClearTextUsername='Username' ;
$MyClearTextPassword='Password' ;
$MyUsernameDomain=$MyDomain+'\'+$MyClearTextUsername;
$SecurePassword=Convertto-SecureString –String $MyClearTextPassword –AsPlainText –force ;
$MyCreds=New-object System.Management.Automation.PSCredential $MyUsernameDomain,$SecurePassword ;
# Placing the script under a ScriptBlock
$MyScriptblock={param($appPoolName,$pathback)
# Since you have mentioned that it is working fine locally, I am not checking this part. Assuming its fine.
# Defining the functions as Global. So that you can use it anywhere although I am putting in the scriptblock.
# Make sure the module is present in the remote system. It should be cause you have already mentioned it is working fine when you are running from that system.
Function fnStartApplicationPool([string]$appPoolName)
{
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Started')
{
Start-WebAppPool -Name $appPoolName
}
}
Function fnStopApplicationPool([string]$appPoolName)
{
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Stopped')
{
Stop-WebAppPool -Name $appPoolName
}
}
if ($pathback -eq $false)
{
#Copying Data from Source to Destination
copy-Item -Recurse $backupsrc -Destination $backupdes
write-host "Backup Successful"
#Validating the apppool value
import-module WebAdministration
if((Get-WebAppPoolState $appPoolName).Value -ne 'Stopped')
{
#Stop apppool
Stop-WebAppPool -Name $appPoolName
write-host "AppPool Stopped Successfully"
}
#Copying Data from Source to Destination
#Start apppool
Start-WebAppPool -Name $appPoolName
write-host "AppPool Started Sucessfully"
cd c:\
}
}
# As you want to Stop the App pool in Server B from Server A.
# run the script under server A and provide the Server B creds
$result=Invoke-Command -ComputerName 'ServerB' -Credential $MyCreds -ScriptBlock $MyScriptblock -ArgumentList $appPoolName,$pathback ;
$result ;
If you are satisfied with the answer, feel free to like and accept the answer that will help others also.

Powershell Workflow not able to use -parameters to create a VM

I am having a problem with my Powershell Workflow that I am authoring in Windows Azure Pack Admin Site. In Powershell ISE, the following works but in Service Management Portal Admin Site Runbook Authoring, it does not work. Where it is getting stuck is that it is saying that it cannot validate the arguments passed -Name. I remove -Name out and now -FullName doesnt work. It seems like all the switch parameters for the command is not working. Can anyone help me out?
param (
[string]$DomainAdminAcct,
[string]$DomainAdminPass,
[string]$ServerName
)
InlineScript {
Add-PSSnapin VMWare.VimAutomation.Core
$vCenter = "test300"
Connect-ViServer -server $vCenter -ErrorAction Stop
$myCluster = Get-Cluster -Name "DC Test"
$myTemplate = Get-Template -Name "2012dc" -Location "our company"
$OSCustomizationSpec = New-OSCustomizationSpec –Name “$ServerName” –FullName “$ServerName” –OrgName “our company” –Domain “our.domain.com” –DomainUsername “$DomainAdminAcct” –DomainPassword "$DomainAdminPass" -AdminPassword "changeme" -ChangeSid
New-VM -Name $ServerName -ResourcePool $myCluster -Template $myTemplate -OSCustomizationSpec $OSCustomizationSpec
}
}
Sounds like you have Hyper-V and PowerCLI modules loaded and the commands are conflicting. It is trying to run New-VM from the Hyper-V module. You can confirm this by running:
get-command New-VM -all
You should see two commands one from the Hyper-V module and one from the Vmware module.
To get past the problem you can add the module name to the command name:
VMware.VimAutomation.Core\New-VM
for using parameters inside INLINESTRING structure, you must use $using:<>

Recycle an application pool using a PowerShell script

I want to recycle my application pool using one-liner command which I can put in my PowerShell script. I added the following code in my PowerShell script:
Import-Module WebAdministration
$site = "Default Web Site"
$pool = (Get-Item "IIS:\Sites\$site"| Select-Object applicationPool).applicationPool
Restart-WebAppPool $pool
But I am getting an error that name IIS doesn't exist. How can I fix it?
Short and simple, like this...
Restart-WebAppPool (Get-Website -Name <YourSiteName>).applicationPool
You can use appcmd.exe:
appcmd recycle apppool /apppool.name:'MyAppPool'
You can also retrieve the corresponding WMI instance and invoke the Recycle() method:
$myAppPool = Get-WmiObject -Namespace root\WebAdministration -Class ApplicationPool -Filter "Name = 'MyAppPool'"
$myAppPool.Recycle()
The following command works for me
invoke-command -computername servername -scriptblock {C:\Windows\System32\inetsrv\appcmd.exe recycle apppool "apppoolname"}
This may work:
Write-Host "App Pool Recycling Started...."
& $env:windir\system32\inetsrv\appcmd list apppools /state:Started /xml | & $env:windir\system32\inetsrv\appcmd recycle apppools /in
Write-Host "App Pool Recycling Completed"
It works for me in AWS through the Run command.
Use:
Import-Module WebAdministration
$site = "MySite"
$pool = (Get-Item "IIS:\Sites\$site"| Select-Object applicationPool).applicationPool
#Recycle the application pool:
Restart-WebAppPool $pool
Since WebAdministration is old and badly supported under PowerShell 7, here's an updated answer using the fresher IISAdministration module:
Import-Module IISAdministration
$pool = Get-IISAppPool -Name "DefaultAppPool"
$pool.Recycle()
You can also do this as a two-liner, or even one-liner if you import the module in your profile:
Import-Module IISAdministration
(Get-IISAppPool("DefaultAppPool")).Recycle()
Do note that accessing the IISServerManager object requires administrative permissions.
I don't run all PowerShell scripts as administrator - it's dangerous.
But appcmd.exe is not available unless running in an administrator prompt.
This command line will prompt for elevation if you're running in a regular, un-elevated prompt:
Start-Process c:\windows\System32\inetsrv\appcmd.exe "recycle apppool /apppool.name:MyAppPool" -Verb RunAs
In case you need to recycle all the Application Pools:
Import-Module IISAdministration
Get-IISAppPool | ForEach-Object{ if($_.State -eq "Started"){ $_.Recycle() } }
If the AppPool is stopped it will throw an exception
Use the -Name option:
IIS:\> Restart-WebAppPool -Name "DefaultAppPool"

Run powershell commands in parallel

How can I run a PowerShell script in parallel on multiple computers?
$TempFolder = "C:\DOWNLOADED_APPLICATIONS"
if(!(test-path $TempFolder))
{New-Item -path $TempFolder -type directory}
Write-Host ""
Write-Host "Downloading .NET framework v4.0 installation package" -ForegroundColor Yellow;
$src = "\\onesoul\tools\DOTNET45\dotNetFx45_Full_x86_x64.exe"
$dest = "$TempFolder" + "\" + "dotNetFx45_Full_x86_x64.exe"
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($src, $dest)
$args = " /q /norestart"
Write-Host "Installing .NET framework v4.0" -ForegroundColor Yellow;
Start-Process -FilePath $dest -ArgumentList $args -Wait
Write-Output "Dot net 4.5 installed"
This script works fine if I run it remotely on one computer at a time. How do I make it run in parallel?
To run scripts on multiple remote computers you use PowerShell remoting. This requires that every computer you connect to has to have PowerShell remoting enabled which you do with the command:
Enable-PSRemoting -Force
Then from your PC, running an elevated console, use the Invoke-Command to run a script against multiple computers e.g.:
Invoke-Command -Computer server1,server2,server3 -Auth CredSSP `
-FilePath c:\script.ps1 -ArgumentList scriptParameter1, scriptParameter2
I suggest you use the -Auth CredSSP to avoid a second hop issue with your credentials since you're accessing a network share from the remote computer. Also the FilePath parameter will take the path to a local script and copy its contents across the wire to each remote computer. That script should not rely on other scripts unless they exist on all the remote computers. Finally, if you use your credentials, you should admin privs on all the remote computers. If you don't, use the -Credential parameter to provides credentials for an account that does.