Showing posts with label Powershell. Show all posts
Showing posts with label Powershell. Show all posts

Thursday, 19 October 2017

Troubles with PowerShell Modules

Working with Azure, I regularly have to run PowerShell CmdLets and scripts to get things done.

Unfortunately this means regularly installing and updating Azure PowerShell modules to make use of the latest and greatest features. Sometimes, too I have to downgrade to earlier module versions just to "get stuff done".

The result can be a nasty mess of my powershell environment, leaving behind modules that cannot be removed. For example, I regularly uninstall the AzureRM module with


Uninstall-Module AzureRM


Which completes without error, but a subsequent

Get-Module -ListAvailable

Still reports that the module and sub-scripts are installed. The situation doesn't improve when you try to uninstall the AzureRM module again, this time you receieve an error stating:
No match was found for the specified search criteria and module names "AzureRM"
So, how do you get rid of modules that "seemingly" can't be uninstalled? One solution I dreamt up is as follows:
Get-Module -ListAvailable | where { $_.Name -like "Azure*" } | Select Name | Write-Output -PipelineVariable modname | ForEach { Uninstall-Module $modname.Name }
This utilises the PipelineVariable common parameter to capture the list of "installed" Azure modules and then forcefully uninstall them one-by-one. Be patient, this can take some time to run, but gets the job done.

Monday, 14 August 2017

Stuck! How to change both the local admin account password and account name for an Azure Windows VM

I recently had to change both the account name and account password for a Windows VM running in Azure. Luckily, help is at hand thanks to some PowerShell and the VM Access Virtual Machine extension. No point in re-inventing the wheel, details are in the articles below...

https://blogs.technet.microsoft.com/askpfeplat/2016/02/08/resetting-the-local-admin-name-and-password-for-azure-arm-virtual-machines-with-powershell/

https://docs.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmaccessextension?view=azurermps-4.2.0

Wednesday, 8 February 2017

Copying an Azure Blob snapshot to another storage account using PowerShell

I've been working with Azure Blobs and Snapshots recently. One gripe is that the Azure portal and the various storage explorers don't give you the power to copy a blob snapshot. Blobs, yes, but their snapshots, no.

Depending on your requirements there are many approaches. The PowerShell below gives an example where the snapshot timestamp is extracted from the snapshot URI and then used to obtain an object to the specific snapshot before copying it with the Start-AzureStorageBlobCopy cmdlet.

# Define the source snapshot blob URI
$SrcBlobURI="https://<SOURCE_STORAGE_ACCOUNT>.blob.core.windows.net/vhds/<SOURCE_VHD_PREFIX>.vhd?snapshot=2017-01-24T21:08:36.9371576Z"

# Define the destination storage account and context.
$DestStorageAccountName = "<DESTINATION_STORAGE_ACCOUNT>"
$DestStorageAccountKey = "<DESTINATION_STORAGE_ACCOUNT_KEY>"
$DestContainerName = "<DESTINATION_CONTAINER_NAME>"
$DestContext = New-AzureStorageContext -StorageAccountName $DestStorageAccountName -StorageAccountKey $DestStorageAccountKey

# Determine source snapshot blob container name and context
$SrcDiskInfo = "" | Select StorageAccountName, VHDName, ContainerName
$SrcDiskInfo.StorageAccountName = ($SrcBlobURI -split "https://")[1].Split(".")[0]
$SrcDiskInfo.VHDName = $SrcBlobURI.Split("/")[-1]
$SrcDiskInfo.ContainerName = $SrcBlobURI.Split("/")[3]
$SrcContainerName = $SrcDiskInfo.ContainerName
$SrcStorageAccount = Find-AzureRmResource `
    -ResourceNameContains $SrcDiskInfo.StorageAccountName `
    -WarningAction Ignore
$SrcStorageKey = Get-AzureRmStorageAccountKey `
    -Name $SrcStorageAccount.Name `
    -ResourceGroupName $SrcStorageAccount.ResourceGroupName
$SrcContext = New-AzureStorageContext `
    -StorageAccountName $SrcStorageAccount.Name `
    -StorageAccountKey $SrcStorageKey[0].Value

# Extract timestamp from the Snapshot filename and convert to a datetime
$pre, $post = $SrcBlobURI.split("=")
$snapdt = [uri]::UnescapeDataString($post)
$snapdt = [datetime]::ParseExact( `
    $snapdt,'yyyy-MM-dd"T"HH:mm:ss"."fffffff"Z"',$null `
)

# Get a reference to blobs in the source container.
$blob = Get-AzureStorageBlob -Container $SrcContainerName `
    -Context $SrcContext `
    | Where-Object {`
        $_.ICloudBlob.IsSnapshot `
        -and $_.SnapshotTime -eq $snapdt `
    }

# Copy blobs from one container to another.
$blob | Start-AzureStorageBlobCopy `
    -DestContainer $DestContainerName `
    -DestContext $DestContext `
    -DestBlob "acopy_$($blob.Name)"

Thursday, 19 January 2017

PowerShell Pea - Check Disk Usage on Remote Windows Servers using PowerShell

Found this useful script today that (given a list of Windows server names) will check the disk usage on each Windows Server (whose name is supplied in a file) and can also report results back via email.

It demonstrates an alternative to PowerShell remoting, if you want to build reports across a number of servers using a script and need to avoid labour-intensive checks of each server via RDP, for example.

Wednesday, 28 December 2016

Globally Unique Identifiers - Creating GUIDs in Powershell

Powershell Pea...

New-Guid

I've been working more and more with Powershell, specifically with Azure Automation and scripting and wanted to share a useful Cmdlet for creating GUIDs. This link provides more detail, but ultimately this command will provide you with a unique ID that can be assigned to arbitrary objects that require a unique ID.

Bear in mind that this doesn't protect you from duplicates, but the probability of them occurring is small. So if you need GUIDs for relatively small record/object sets and your application can handle the prospect of duplicates, then this function is a quick way to generate a "unique" ID.

See this link for more details on GUIDs/UUIDs.

Wednesday, 14 December 2016

Azure Automation Troubles

A recent venture into Azure Automation threw up some unexpected problems.

A simple script, run locally, that called Get-AzureRmVM was working to my subscription, but the same script did not work within an Azure Runbook.

I'd created the AzureRunAsConnection by default with the Azure Automation account and followed the same code as given in the AzureAutomationTutorialScript powershell runbook to login to the subscription and execute Cmdlets.

The problem came when executing the Get-AzureRmVM Cmdlet in the runbook, receiving the error:
Get-AzureRmVM : Run Login-AzureRmAccount to login.
+     $VM = Get-AzureRmVM | ? {$_.Name -eq $VMName}
+           ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-AzureRmVM], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.Azure.Commands.Compute.GetAzureVMCommand

After several googles I found this post...
https://feedback.azure.com/forums/246290-automation/suggestions/16590229-get-azurermvm-failing-in-azure-automation

Therefore, if anyone else sees errors when running basic Cmdlets in a runbook (that work fine from PowerShell), try updating all the modules in the Automation account using a script like this one...
https://www.powershellgallery.com/packages/Update-ModulesInAutomationToLatestVersion/1.03/DisplayScript
(Note that the deploy to Azure button didn't work for me, so I had to import the script and run manually.)

Note also that (depending on when you created your Automation Account) the above may, or may not work, and you may have to create a new Automation Account and update the modules before starting to use the account. Microsoft suggest setting the script to run on a schedule in the automation account to keep the modules up to date.