How can i install ARR on azure VM via PowerShell? - iis

I have deployed my project to Azure Cloud Service but additionally i must install Application Request Routing (ARR).
peace of .ps1 PowerShell command:
if( Get-Service was ) {
Write-Host "Stopping IIS and WAS..."
Stop-Service was -Force
}
$filepath="%temp%\arr.msi"
$process = (Start-Process -FilePath msiexec -ArgumentList /i, $filepath, /qn -Wait).ExitCode
Write-Host $process
if( Get-Service was ) {
Start-Service was,w3svc -Verbose
}
output:
Downloading MSI packages...
Downloading MSI package: D:\Users\BUTTER~1\AppData\Local\Temp\2\arr.msi
Downloaded...
Done. Performing installation...
Stopping IIS and WAS...
1619
Done
VERBOSE: Performing operation "Start-Service" on Target "World Wide Web Publishing Service (w3svc)".
VERBOSE: Performing operation "Start-Service" on Target "Windows Process Activation Service (was)".
there is no error but it doesn't install ARR. can anyone help?

I couldn't find a good way of doing this directly through PowerShell. If you don't mind using Chocolatey you can do it all from the Web Platform Installer Command Line (WebPICMD), example:
#Download and install Chocolatey and through Chocolatey install WebPICMD
iex ((new-object net.webclient).DownloadString("https://chocolatey.org/install.ps1"))
cinst webpicommandline
#Install Url Rewrite and ARR
$webPiProducts = #('UrlRewrite2', 'ARRv3_0')
WebPICMD /Install /Products:"$($webPiProducts -join ',')" /AcceptEULA
More info about WebPICMD here: http://www.iis.net/learn/install/web-platform-installer/web-platform-installer-v4-command-line-webpicmdexe-rtw-release
Inspiration for Chocolatey came from this blog post: http://www.tugberkugurlu.com/archive/script-out-everything-initialize-your-windows-azure-vm-for-your-web-server-with-iis-web-deploy-and-other-stuff

Related

How to run PowerShell cmdlets from custom PS modules when deploying a new Azure VM?

Is it possible to install a custom PowerShell module in Azure VM post-deployment task and run PS cmdlets from that module in this task?
I have a Bicep template that deploys a new Windows Azure VM. The template has a Microsoft.Compute/virtualMachines/extensions#2020-12-01 post-deployment resource that takes these steps:
Installs an MSI-packaged application (with a new custom PowerShell module) using Start-Process (OK)
Creates several folders via PowerShell (OK)
Runs several cmdlets installed at step 1 (NOT OK)
Running a cmdlet from the custom module in the post-deployment script shows the following error in the "Extensions + applications" log:
... is not recognized as the name of a cmdlet ...
When I change the post-deployment step to Import-Module MODULENAME, I see another message:
Import-Module : The specified module 'MODULENAME' was not loaded because no valid module file was found in any module \r\ndirectory.
When I run Get-Module in the post-deployment task, I see only these two modules listsd:
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 3.1.0.0 Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Con...
Manifest 3.1.0.0 Microsoft.PowerShell.Utility {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
So the module is not getting loaded.
But when I remote to the deployed VM, I run the cmdlets from the custom PowerShell module without any errors.
I think that my scenario is supported, but I don't quite understand how to troubleshoot this further.
I resolved the problem with these two steps:
I've added -Wait to Start-Process and this has resolved the problem.
I've added a path to the module into PSModulePath and ran $Env:PSModulePath = $Env:PSModulePath+";PATH-TO-MODULE"
Import-Module MODULENAME -Force. Normally, the installed does this step for me. But it appears that I need to run these commands manually because all this is done in a single PowerShell session.
It appears that the problem was with my customScript.ps1 script. The very first line of the script installs an MSI-packaged application that adds the required PowerShell module:
Start-Process -FilePath msiexec.exe -ArgumentList #('/i', 'msi-installer-name.msi', '/qb')
PowerShell starts the installation using Start-Process and continues. So when I'm running these commands, the installation hasn't yet finished:
$env:PSModulePath | Out-File C:\Temp\psmodulepath.txt
Get-Module -ListAvailable | Out-File C:\Temp\getmodulelistavailable.txt

Start-Process : This command cannot be run due to the error: %1 is not a valid Win32 application on dev azure

I have an issue at PowerShell script for executing on pipeline at dev azure,
error is happening with message:
Start-Process : This command cannot be run due to the error: %1 is not a valid Win32 application
it was worked some time ago but now it is not, is it some updates were done on azure?
or I need to improve some code?
foreach ($alert in $alerts)
{
Write-Log "`tCreating alert $($alert.AlertName)"
$azArgs = "monitor metrics alert create --name ""$($alert.AlertName)"" --resource-group ""$($resourceGroup)"" --condition ""$($alert.AlertRule)"" --scopes ""$($alert.ResourceId)"" --window-size 5m --evaluation-frequency 1m --action ""$actionGroupResourceId"" --description "" "" --subscription ""$subscriptionId"" --auto-mitigate true"
Write-Verbose $azArgs
Start-Process "az" -ArgumentList $azArgs -NoNewWindow -Wait
}
Start-Process : This command cannot be run due to the error: %1 is not a valid Win32 application
AFAIK, the issue shows that you are not using X32 environment. so, that the error thrown. It is a common issue we cannot directly find out what exactly happens we can fix it by following
Ways to fix:
Try to uninstall and install the PowerShell Az module.
Update the PowerShell Az module with latest version
Check your Dev environment has X64. If it is X64 make sure to install the PowerShell Module Globally.
It may happen sometimes with you are passing environment variable path make sure to double check once.
issue is related to azure updates https://pullanswer.com/questions/error-with-startprocess-and-az-command
problem is Azure Cli has been updated and so now there is an az.ps1 so i need to make "az.cmd" in order to continue to call the good program...

How do you configuring Azure VMs with .NET 5.0 from the command line?

I'm setting up some virtual machines to run my service. There may be several, so I'm trying to automate the process. I've got a PowerShell script that successfully build the virtual machine, but now I want to install the dependent software that my .NET Core Web Application requires in the same script.
The first dependency I want to install is .NET 5.0 Runtime. I've done this many times from the browser, but now I want to commit this to a script that runs after the VM has been built.
Test locally or on a test VM by installing using the dotnet-install-script and finalize the parameters. Then use Set-AzVMExtension to install that script using custom script extension. The code would look like this (not tested)
$Command = "&powershell -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) <additional install-script args>"
$Settings = #{"commandToExecute" = "Powershell $Command";};
Set-AzVMExtension `
-ResourceGroupName "ResourceGroupName" `
-Location "Location" `
-VMName "VirtualMachineName" `
-Name "ExtensionName" `
-Publisher "Contoso.Compute" `
-Type "CustomScriptExtension" `
-TypeHandlerVersion "1.1" `
-Settings $Settings
Full details and schema of settings custom-script-windows
You can also use Set-AzureVMCustomScriptExtension for running custom scripts.
As #amit_g recommended, you can use Azure VM run command functionality to run install .net with scripts by PowerShell directly to meet your requirement.
This seems to work pretty well:
Invoke-AzureRmVMRunCommand -ResourceGroupName "$resourceGroupName" -Name "$machineName" -CommandId "RunPowerShellScript" -ScriptPath "configureMachine.ps1" -Parameter #{"machineName" = "$machineName"}
The contents of the Powershell script look something like this:
# The name of the VM is passed in as the first parameter.
param ($machineName)
if ($machineName -eq $null)
{
Write-Host "Usage: configureMachine -machineName <machineName>";
Exit;
}
# Download the agent installation files.
$agentZip="agent.zip";
Invoke-WebRequest -Uri "https://vstsagentpackage.azureedge.net/agent/2.181.1/vsts-agent-win-x64-2.181.1.zip" -OutFile $agentZip
# Unpack them.
$agentDirectory="$env:SystemDrive\azagent";
Add-Type -AssemblyName System.IO.Compression.FileSystem;
[System.IO.Compression.ZipFile]::ExtractToDirectory($agentZip, $agentDirectory);
# Configure the machine to work as a DevOps Agent.
&"$agentDirectory\config.cmd" --unattended --deploymentgroup --deploymentgroupname "Production" --agent "$machineName" --runasservice --work "_work" --url "https://dev.azure.com/theta-rex/" --projectname "openbook" --auth PAT --token te64yuv36tina2rvc2lsvwcsvctpwomiewz5fxihcubbdzaasoka
# Remove the Agent Zip files when installation is complete.
Remove-Item $agentZip;
# Download and install .NET 5.0
Invoke-WebRequest -Uri "https://dot.net/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1"
&"./dotnet-install.ps1" -Channel 5.0 -Runtime aspnetcore -InstallDir "C:\Program Files\dotnet"
The end result is a machine configured to participate in Azure DevOps and ASP.NET 5.0.

Use the az installer on a VM - through azure powershell

I am attempting to install an artifact through an azure VM - I have remoted into the VM through the powershell on azure and am running the following command:
Enter-AzVm -Name <MyVM> -ResourceGroupName <MyResourceGroup> -Credential (get-credential)
When I'm connected onto the VM I'm attempting this download command which works on my local machine:
az artifacts universal download --organization <MyOrganization> --project=<MyProject> --scope project --feed <MyFeed> --name <MyFirstPackage> --version 0.0.1 --path .
This is the error I'm getting while attempting that download :
The term 'az' is not recognized as the name of a cmdlet, function, script file, or operable program
I tried to run the command to install CLI on the VM which runs, but after that installation run I cannot see az --version with the same error. Any help would be appreciated.
I have never used Enter-AzVm to remote into the VM to install Azure CLI, seems the Enter-AzVm just works in Azure Cloud Shell(not sure).
I installed the Azure CLI successfully via Invoke-AzVMRunCommand command in a Windows VM, when I test az --version in cloud shell after remoting into the VM with Enter-AzVm, it works fine, you could follow the steps below.
1.Save the command below in local as a installcli.ps1 file.
Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; rm .\AzureCLI.msi
2.Run the command below in local.
Invoke-AzVMRunCommand -ResourceGroupName 'groupname' -VMName 'vmname' -CommandId 'RunPowerShellScript' -ScriptPath 'C:\Users\joyw\Desktop\installcli.ps1'
3.After the command completed, navigate to the cloud shell, use Enter-AzVm to remote into the VM, then run az --version, it works fine.
Actually, if the steps above not work for you, you can also store the azure cli command as a .ps1 file like step 1, then use Invoke-AzVMRunCommand to run it, it will work.

Failure Installing DotNet 4.6.1 via Chocolatey using DSC cChocoPackageInstaller

I'm attempting to set up a server Windows 2012 R2 in Azure via ARM templates and DSC. The DSC script runs the cChocoPackageInstaller to install dotnet4.6.1 (after running the cChocoInstaller). It looks like this:
cChocoInstaller Choco
{
InstallDir = "c:\choco"
}
cChocoPackageInstaller DotNet461
{
Name = "dotnet-461"
DependsOn = "[cChocoInstaller]Choco"
}
The DotNet installer is downloaded but it ultimately fails when it is run. The log looks like this (I've excerpted just the errors here).
2016-06-17 13:05:52,001 [DEBUG] - Running 'Start-ChocolateyProcessAsAdmin' with exeToRun:'C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\dotnet-461\4.6.01055.006\NDP461-KB3102436-x86-x64-AllOS-ENU.exe', statements: '/q /norestart /log "C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\net461.log" '
2016-06-17 13:05:52,001 [DEBUG] - Elevating Permissions and running ["C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\dotnet-461\4.6.01055.006\NDP461-KB3102436-x86-x64-AllOS-ENU.exe" /q /norestart /log "C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\net461.log" ]. This may take a while, depending on the statements.
2016-06-17 13:05:52,110 [DEBUG] - Setting RunAs for elevation
2016-06-17 13:05:53,487 [INFO ] - The application cannot find one of its required files, possibly
2016-06-17 13:05:53,487 [INFO ] -
2016-06-17 13:05:53,487 [INFO ] - because it was unable to create it in the folder. Please make
2016-06-17 13:05:53,487 [INFO ] -
2016-06-17 13:05:53,487 [INFO ] - sure that the folder in which this application was downloaded is
2016-06-17 13:05:53,487 [INFO ] -
2016-06-17 13:05:53,487 [INFO ] - accessible and not read-only.
2016-06-17 13:05:53,487 [INFO ] -
2016-06-17 13:05:53,503 [DEBUG] - Command ["C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\dotnet-461\4.6.01055.006\NDP461-KB3102436-x86-x64-AllOS-ENU.exe" /q /norestart /log "C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\net461.log" ] exited with '3'.
2016-06-17 13:05:53,518 [ERROR] - ERROR: Running ["C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\dotnet-461\4.6.01055.006\NDP461-KB3102436-x86-x64-AllOS-ENU.exe" /q /norestart /log "C:\Windows\system32\config\systemprofile\AppData\Local\Temp\chocolatey\net461.log" ] was not successful. Exit code was '3'. See log for possible error messages.
2016-06-17 13:05:53,518 [DEBUG] - Built-in PowerShell host called with ['[System.Threading.Thread]::CurrentThread.CurrentCulture = '';[System.Threading.Thread]::CurrentThread.CurrentUICulture = ''; & import-module -name 'c:\choco\helpers\chocolateyInstaller.psm1'; & 'c:\choco\helpers\chocolateyScriptRunner.ps1' -packageScript 'c:\choco\lib\dotnet-461\tools\chocolateyInstall.ps1' -installArguments '' -packageParameters '''] exited with '3'.
2016-06-17 13:05:53,534 [DEBUG] - Calling command ['"C:\Windows\System32\shutdown.exe" /a']
2016-06-17 13:05:53,549 [DEBUG] - Command ['"C:\Windows\System32\shutdown.exe" /a'] exited with '1116'
So a couple of things:
No log file is produced for the DotNet installer...so it doesn't look like it's successfully launching the installer.
The installer package is definitely downloaded to the expected location. Not sure why it would be able to download the installer to this directory but then later not access/run it.
If I RDP onto the box and run the "choco install dotnet4.6.1" command as a local admin the package installs with no errors.
I'm now running choco 0.9.10 but had the same issue with 0.9.9
I'm running the newer version of the dotnet4.6.1 installer (unapproved) that runs in /q (quite) mode instead of /passive. I had the same issue in Passive mode.
Any ideas are appreciated. Thanks!
Sorry about the delay. So you need to have an automation account. I have modified my template deployment script to create the automation account, then with the Get-AzureRmAutomationRegistrationInfo cmdlet, i get the primary key and endpoint like so:
$RegistrationInfo = Get-AzureRmAutomationRegistrationInfo `
-ResourceGroupName $ResourceGroupName `
-AutomationAccountName $AccountName
New-AzureRmResourceGroupDeployment `
-Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) `
-ResourceGroupName $ResourceGroupName -TemplateFile $TemplateFile `
-TemplateParameterFile $TemplateParametersFile `
# extra params here
-RegistrationKey ($RegistrationInfo.PrimaryKey | ConvertTo-SecureString -AsPlainText -Force) `
-RegistrationUrl $RegistrationInfo.Endpoint `
-AutomationAccountName $AccountName
Then in the template itself, you have an automation account there as well (name from param), and as child resources of that, a configuration and a compilation.
See here for automation account part of the template and the configuration. (I was doing the same thing v recently, with issues, but it works in the end.) As you can see, the configuration is a script that downloads .net installer and installs. FYI, this requires a reboot, so if you have anything else going on on the vm during deploy, you may get conflicts.
Like I said, you can also do it with a custom script extension if you want. Msft have a script on service profiler site that does it:
{
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.7",
"autoUpgradeMinorVersion": false,
"settings": {
"fileUris": [ "https://serviceprofiler.azurewebsites.net/content/downloads/InstallNetFx46.ps1" ],
"commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File InstallNetFx46.ps1"
},
"forceUpdateTag": "RerunExtension"
},
"name": "CustomScriptExtensionInstallNet46"
}
Not saying this is the best answer possible, but this works both via Chocolatey (launched directly from a CustomScript ARM extension) or via DSC (using a pull server and a custom DSC module for .Net 4.6.1) when either is initiated from an ARM template. Below is from my chocolateyInstall.ps1. I'm basically manually conducting the install instead of relying on the chocolatey install functionality. This came from the following SO question which used this approach for 4.5.2.
Function IsInstalled {
$ver = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full').Release
return (!($ver -eq $null) -and ($ver -ge 394254))
}
if (IsInstalled) {
Write-Host "Microsoft .NET Framework 4.6.1 or later is already installed"
}
else {
$SourceURI = "https://download.microsoft.com/download/3/5/9/35980F81-60F4-4DE3-88FC-8F962B97253B/NDP461-KB3102438-Web.exe"
$FileName = $SourceURI.Split('/')[-1]
$BinPath = Join-Path $env:SystemRoot -ChildPath "Temp\$FileName"
if (!(Test-Path $BinPath))
{
Invoke-Webrequest -Uri $SourceURI -OutFile $BinPath
}
write-verbose "Installing .Net 4.6.1 from $BinPath"
write-verbose "Executing $Binpath /q /norestart"
Sleep 5
Start-Process -FilePath $BinPath -ArgumentList "/q /norestart" -Wait -NoNewWindow
Sleep 5
Write-Verbose "DotNet 4.6.1 Install completed"
}

Resources