How to clean up bad Azure PowerShell uninstall? - azure-powershell

Background:
I had installed Azure-PowerShell 1.x via the MSI, and subsequently added some Azure Resource Management modules via the command prompt.
Everything was working fine; then yesterday afternoon the ISE inexplicably disappeared. In an attempt to remedy that, I planned to uninstall the MSI & then reinstall. (I did not know that it is necessary to first unstall the manually-added modules.)
The uninstall appeared to run fine, but it didn't remove the manually-installed modules nor did it warn me about them.
Result: The machine no longer has Azure-PowerShell installed. I cannot Install, Uninstall or Repair the installation because some modules remain:
Azure Modules from the PowerShell Gallery are installed on this
machine. Please remove these modules before installing this MSI.
Is there a way to "fix" this installation? Either manually remove files/cleanup registry, or force the MSI to install over whatever is there?
This is all running on a VM on Azure. I could delete the entire VM & start from scratch if necessary, but would prefer to avoid that if there's a relatively simple fix.
Thanks!

Okay so I tried the above items to remove windows powershell and found that actually it doesn't fully remove powershell.
This is at least on windows 7 it doesn't seem to properly.
If you run uninstall-module Azure or Uninstall-Module AzureRM it will uninstall something, looks like the base module I think.
Then if you do:
Get-Module AzureRM -ListAvailable
it will come back with nothing.
So its done right?
No not really.
If you then do:
Get-Module -ListAvailable AzureRM*
you will find any number of sub modules still sitting there. (For some reason wildcards work with Get-Module but not with Uninstall-Module)
Okay so but then just do Uninstall-Module AzureRm* right?
No not really
Depending on your powershell version (Or maybe not, I'm not sure)
Install-Module just complains that you can't use wildcards in the Uninstall-Module command. (God knows why what's the point of wildcards if not for this?, but then this is windows so I just had to suck it up).
And if you take a look in %System-root%\Program Files\windowspowershell\modules you will still see the modules there.
Why is this? I'm not sure but this is what I had to do to cleanup all the old versions and newer versions of Azure powershell that I had to get back to a clean slate.
So to solve the problem of lack of wildcard support I just used a foreach loop as such:
foreach ($module in (Get-Module -ListAvailable AzureRM*).Name |Get-Unique) {
write-host "Removing Module $module"
Uninstall-module $module
}
Be warned Don't try to run this as Visual Studio code or visual studio for that matter, as depending on your lock you may get errors as it tends to pre-load the modules and lock things open. Put it in a file named Removeold-AzureRM.ps1 and run it from a powershell console window like this:
.\Remove-AzureRM.ps1
Also Make sure to close down Visual Studio Code and Visual studio before attempting it or you may still get a similar error message.
If you run this after you already uninstalled AzureRM you will find that things stop working and you only have one last resort.
Delete all the AzureRM modules in %System-root%\Program Files\windowspowershell\modules
Edit I have re-tested this and the code above still seems to work if you have azurerm 5.0.1 installed and you already removed azurerm so I could be wrong about other versions as well
Now you will at this point for sure have this sorted and you can now reinstall Azure powershell with Install-Module AzureRM.
If you made the mistake of nuking powershellget like me by accident, don't bother trying to reinstall it with WMF 5.1 or 5.0 as that will install fine but you still won't have powershellget, why I'm not sure and again this is windows so lets just suck it up.
Okay so how to fix it then?
Your only recourse is to download the release of powershellget
And and copy the PowerShellGet-1.5.0.0\PowerShellGet to your modules folder.
Then Install-Module will work again.
Yeah I know we are all saying isn't it just safer to re-install?
Yes likely but for those of you like me where that was not an option for one reason or another the above is your best bet. I hope this helps someone as this took me at least 3 days to sort out why I kept getting older modules executing when I was sure I had already removed everything.

To go faster, you can uninstall in parallel:
workflow Uninstall-AzureModules
{
$Modules = (Get-Module -ListAvailable Azure*).Name |Get-Unique
Foreach -parallel ($Module in $Modules)
{
Write-Output ("Uninstalling: $Module")
Uninstall-Module $Module -Force
}
}
Uninstall-AzureModules
Uninstall-AzureModules #second invocation to truly remove everything

It's just a Dev VM. I nuked it and started over. Lesson learned: Uninstall PowerShell Gallery components before uninstalling the MSI.

Try uninstalling the modules via MSI (first) and then cmdline:
# Uninstall the AzureRM component modules
Uninstall-AzureRM
# Uninstall AzureRM module
Uninstall-Module AzureRM
# Uninstall the Azure module
Uninstall-Module Azure
# Or, you can nuke all Azure* modules
# Uninstall-Module Azure* -Force
Reboot the machine after that and then install again via WebPI/MSI. https://azure.microsoft.com/en-us/blog/azps-1-0/

I created this variation on #BlueSky answer to keep one specific version and its dependencies:
workflow Uninstall-AzureModules
{
$skip = Find-Module AzureRM -RequiredVersion 2.1.0
$dependencies = $skip.Dependencies | %{ Get-Module -FullyQualifiedName #{ ModuleName=$_["Name"]; RequiredVersion=$_["RequiredVersion"] } -ListAvailable }
$modules = Get-Module azurerm* -ListAvailable |
where { $_.Version -ne '2.1.0' } |
where { -Not(Compare-Object $dependencies $_ -IncludeEqual -ExcludeDifferent) }
foreach -parallel ($module in $modules)
{
Write-Output ("Uninstalling: $($module.Name) $($module.Version)")
Uninstall-Module -Name $module.Name -RequiredVersion $module.Version -Force -ea SilentlyContinue
}
}

I found the command Get-InstalledModule works better for me for discovering my installed modules.
My latest script looks like this:
# If installed, remove the old AzureRm module
$allModules = Get-InstalledModule
foreach ($module in $allModules)
{
if ($module.Name -match "AzureRM.*")
{
Write-Host "Removing $($module.Name)..."
Uninstall-Module -Name $module.Name -Force -AllVersions
}
}
# If not installed, install the new Az module
$azModule = Get-InstalledModule -Name Az
if (!$azModule)
{
Install-Module -Name Az -Scope CurrentUser -AllowClobber -Force
}
# Enable AzureRm aliases for script compat
Enable-AzureRmAlias -Scope LocalMachine

This did not work in my case. I am on Powershell v7.02 MACOS v10.15.6. What did work was this code:
Function Uninstall-AzureModules
{
$Modules = (Get-Module -ListAvailable Azure*).Name |Get-Unique
Foreach ($Module in $Modules)
{
Write-Output ("Uninstalling: $Module")
Uninstall-Module $Module -Force
}
}
Uninstall-AzureModules
Uninstall-AzureModules
I them verified the AzureRM modules as gone with:
Get-InstalledModule -Name AzureRM*

Related

Cannot install Azure/AzureRM PowerShell modules on Worker roles

I have a Worker roles on Azure Cloud service (classic) and I want them to install Azure and AzureRM PowerShell modules on startup. I've added a startup task in my ServiceDefinition.csdef file:
<Startup>
<Task commandLine="InstallAzureModules.cmd" executionContext="elevated" taskType="simple" />
</Startup>
InstallAzureModules.cmd file looks like this:
PowerShell.exe -ExecutionPolicy Unrestricted .\InstallAzureModules.ps1 >> "D:\InstallAzureModulesLogs.txt" 2>&1
And InstallAzureModules.ps1 looks like this:
Install-PackageProvider NuGet -Force
Install-Module Azure -AllowClobber -Force
Install-Module AzureRM -AllowClobber -Force
In result I have an error There is not enough space on the disk, however when I connect to any Worker instance using Remote Desktop and run InstallAzureModules.cmd manually all modules are installed without any errors.
Please help to have these modules installed.
Thanks.
Finally after contacting Microsoft Support the issue was resolved!
According to Support Professional who was working with my request this error is due to a redirection of application temporary folder. I was recommended to go through this link for a possible fix, but it didn't work.
Also updates to my PS script were provided and what actually helped was setting TMP and TEMP environment variables to a folder on drive C. So here is my final script:
$env_TMP = $env:TMP
$env_TEMP = $env:TEMP
$env:TMP = "C:\_trashable\Modules"
$env:TEMP = "C:\_trashable\Modules"
Install-PackageProvider NuGet -Force
Install-Module Azure -AllowClobber -Force
$env:TMP = $env_TMP
$env:TEMP = $env_TEMP
ECHO "Finished"

Creating Registered Servers via Powershell in SSMS

A cool trick that used to work for me is creating Registered Server groups and registrations in SQL Server Management Studio via PowerShell. However, now that I am running the current version (SSMS 17.9.1) I find the functionality has been lost. I'm not sure when it broke.
After installing the SQLServer module:
Install-Module -Name SqlServer
you can open a PowerShell prompt by right-clicking on server group in the Registered Servers window, and clicking Start Powershell. Here, in the past, I've been able to create new groups and registrations with commands like:
Set-Location "sqlserver:\SQLRegistration\Database Engine Server Group"
# group
New-Item -Path "sqlserver:\SQLRegistration\Database Engine Server Group\AllServers"
# registration
New-Item -Name $(encode-sqlname 'sqlsrv') -path "sqlserver:\SQLRegistration\Database Engine Server Group\AllServers" -ItemType Registration -Value ("Server=sqlsrv ; integrated security=true");
These commands still run without error. But the new server registrations are not shown in the Registered Servers window afterwards after a refresh (or even a reboot).
And, server groups and registrations that are setup in the Registered Servers window are not shown with Get-Item/Get-ChildItem at the PowerShell prompt.
Is this functionality still working for anyone else in the current version?
I'm guessing something changed when the SQLPS powershell module were supplanted with the SQLServer module, but that's just a guess. If so I'm hoping there is just a tweak I need to use these commands under the new toolset.
This is an apparent bug in version 21.1.18068 of the SQLServer PowerShell module. Uninstalling that version and installing 21.0.17279 resolves the issue.
uninstall-module SQLServer
install-module -RequiredVersion 21.0.17224 -Name SQLServer

Azure powershell not executing, version issue

I created a VSTS Release Definition with that contains a Azure Powershell script
When I create a release from the following definition everything works until I get to the Azure Powershell script, I get the following log:
2016-08-02T19:06:33.1625377Z ##[command]Import-Module -Name C:\Program
Files (x86)\Microsoft
SDKs\Azure\PowerShell\ResourceManager\AzureResourceManager\AzureRM.Profile\AzureRM.Profile.psd1
-Global 2016-08-02T19:06:37.8986980Z ##[command]Add-AzureRMAccount -ServicePrincipal -Tenant ******** -Credential System.Management.Automation.PSCredential 2016-08-02T19:06:39.0397286Z
[command]Select-AzureRMSubscription -SubscriptionId ******* -TenantId ******** 2016-08-02T19:06:39.1837302Z ##[command]& 'C:\a\e214cea58\ContinuousBuild\drop\Deployment\PrepareIoTSample.ps1'
-environmentName test -configuration debug -webPackageLocation "C:\a\e214cea58\ContinuousBuild\drop\Web\Web.zip"
-webJobPackageLocation "C:\a\e214cea58\ContinuousBuild\drop\WebJob\WebJobHost.zip"
2016-08-02T19:06:40.3037302Z ##[error]Cannot find path
'C:\a\e214cea58\ContinuousBuild\VERSION.txt' because it does not
exist. 2016-08-02T19:06:43.3880731Z ##[error]Version 1.3.2; update to
1.4.0 and run again.
I tried to google the errors but didn't find anything usefull, and I don't see an option to enter a version number. Can someone point me in the right direction?
You can't run a lower version of AzurePS because there can be only one version of Azure PS installed at a time on a single machine.
The online build machines being maintained by Microsoft they all have the same version of Azure PS. (I'm assuming you're using the hosted agent)
I'd suggest you upgrade your script so it runs properly with the new version of Azure PS

Set-WebConfigurationProperty fails

I am trying to use powershell to set windowsauth on a site in IIS, this part of the script has worked in all environments so far and has now failed and I cannot figure out why.
Set-WebConfigurationproperty system.webServer/security/authentication/anonymousAuthentication -name enabled -value false -PSPath "IIS:\" -location $siteName
Set-WebConfigurationproperty system.webServer/security/authentication/windowsAuthentication -name enabled -value true -PSPath "IIS:\" -location $siteName
Anyone got any ideas as to why this script would fail?
I get a "The configuration section 'system.serviceModel' cannot be read because it is missing a section declaration"
I can manually enable windows auth and the site spins up just fine.
Cheers
So it turns out the issue was not having .Net 3.5 installed.
As powershell runs under .Net2 CLR without having 3.5 installed it didn't know what system.serviceModel was in the web.config.
Once 3.5 was installed the script ran fine
1) Verify the .NET framework 3.0 (or higher) is installed.
2) Execute the following command as administrator:
"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -i
Hope can help

Can you remove an Add-ed Type in PowerShell again?

I'm currently writing a library in C# and was using PowerShell to quickly test it on some occasions. However, this prevents me from re-building the project as PowerShell obviously still has the DLL open.
Is there a way of unloading the DLL again after adding it with Add-Type? The documentation doesn't seem to have clues on that and the obvious candidate would be Remove-Type (which doesn't exist – there is only one command anyway with Type as its noun). It gets cumbersome to close PowerShell and do all the stuff of navigating to the build directory and adding the type again each time I want to rebuild.
Like the others say, this is a .NET behavior. Assemblies loaded into an AppDomain cannot be unloaded. Only the AppDomain can be unloaded, and powershell uses a single appdomain. I blogged a bit about this some years ago:
https://web.archive.org/web/20170707034334/http://www.nivot.org/blog/post/2007/12/07/WhyAppDomainsAreNotAMagicBullet
When I test like this, I usually keep a shell open and use a nested shell to do tests. start powershell, cd to bin location then run "powershell" to start nested shell (new process.) "exit" to start over, and run "powershell" again.
I find the simplest way to get around this problem is to wrap the Add-Type and the test code inside of a Start-Job. Start-Job will create a background process, and the type will be loaded there. Once you are done, the process goes away and you're free to retry.
Here's an example of how it looks:
$job = Start-Job -ScriptBlock {
Add-Type -path 'my.dll'
$myObj = new-object My.MyTestClassName
$result = $myObj.TestMethod
$result
}
Wait-Job $job
Receive-Job $job
The output from the test method will be echoed to the console.
If your assembly doesn't require a binding context you can do this:
$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
Here is a complete example that allows to run the Add-Type command as a background job so that the assembly is unloaded once it finishes:
# Start-Job will not preserve the working directory, so do it manually
# Other arguments can also be passed to the job this way
$cd = Split-Path $MyInvocation.MyCommand.Path
$jobParams = #{
'cd' = $cd
}
Start-Job -InputObject $jobParams -ScriptBlock {
cd $Input.cd
Add-Type -Path assembly.dll
} | Receive-Job -Wait -AutoRemoveJob
Receive-Job -Wait will make sure that the output of the job is received since otherwise it will be lost.
I have been facing to similar problem. It is not possible to unload a type/assembly (that's because it applies to .NET framework).
In .NET you can solve it if you crate a new application domain (System.AppDomain) and load the assembly into that domain. It is possible to unload the app domain and that unloads all the dlls as well.
I haven't tried it yet, because for me it is much simpler to close a tab in Console and open new one.
Visual Studio Code:
Settings -> Extensions -> PowerShell Configuration -> Debugging: Create Temporary Integrated Console
Check checkbox: "Determines whether a temporary PowerShell Integrated Console is created for each debugging sessions, usefull for debugging PowerShell classes and binary modules."