≡ Menu

The script discussed in this article will help you to query environment variable values on remote windows computer using PowerShell.

Environment variables on a computer can be accessed via  Env:\ PSdrive or [System.Environment] dotnet class locally. None of these methods can be used to query environment variables remotely. Only exception is, you can use one of these methods through PowerShell remoting to get environment variable information. However that is not true remote query and doesn’t work in cases where remoting not available plus systems where PS is not installed.

In such cases, WMI will come handy to query this information remotely. Win32_Environment WMI class has information about environmental variables and querying the instances of this class will give us the desired output. My script is a wrapper around this WMI class to return the environment variable values.

This script takes two arguments. 1) ComputerName and 2) Name. While the computer name represents name of the computer from which you want to query environment variables and Name parameter is the name of environment variable you want to query. Both of these are optional parameters.

Code:

[cmdletbinding()]            
param(            
 [string[]]$ComputerName =$env:ComputerName,            
 [string]$Name            
)            
            
foreach($Computer in $ComputerName) {            
 Write-Verbose "Working on $Computer"            
 if(!(Test-Connection -ComputerName $Computer -Count 1 -quiet)) {            
  Write-Verbose "$Computer is not online"            
  Continue            
 }            
             
 try {            
  $EnvObj = @(Get-WMIObject -Class Win32_Environment -ComputerName $Computer -EA Stop)            
  if(!$EnvObj) {            
   Write-Verbose "$Computer returned empty list of environment variables"            
   Continue            
  }            
  Write-Verbose "Successfully queried $Computer"            
              
  if($Name) {            
   Write-Verbose "Looking for environment variable with the name $name"            
   $Env = $EnvObj | Where-Object {$_.Name -eq $Name}            
   if(!$Env) {            
    Write-Verbose "$Computer has no environment variable with name $Name"            
    Continue            
   }            
   $Env               
  } else {            
   Write-Verbose "No environment variable specified. Listing all"            
   $EnvObj            
  }            
              
 } catch {            
  Write-Verbose "Error occurred while querying $Computer. $_"            
  Continue            
 }            
            
}

Usage:

.\Get-Environmentvariable.ps1 -ComputerName TESTPC1

This returns the list of environment variables on TESTPC1 computer.

.\Get-EnvironmentVariable.ps1 -ComputerName TESTPC1 -Name PATH

This returns the environment variable that matches the name PATH

I have also made this script available in TechNet Script Gallery.

{ 5 comments }

I have written a post on the same topic sometime back but that was relying on environment variables to find the CPU architecture. While that is reliable, it can not be extended easily to query remote computers CPU architecture. The script I am going to discuss in this article relies on WMI classes to get the CPU architecture.

Per MSDN, the Architecture property of Win32_Processor class represent the type of architecture of  CPU. So the below script queries the Architecture value to get the CPU architecture. It will not only cover x86/x64-bit processor architecture but also works for other architectures like ARM, MIPS, etc.

CODE

            
[cmdletbinding()]            
Param(            
 [string[]]$ComputerName =$env:ComputerName            
)            
            
$CPUHash = @{0="x86";1="MIPS";2="Alpha";3="PowerPC";5="ARM";6="Itanium-based systems";9="x64"}            
            
            
foreach($Computer in $ComputerName) {            
Write-Verbose "Working on $Computer"            
 try {            
 $OutputObj = New-Object -TypeName PSobject            
 $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.toUpper()            
 $OutputObj | Add-Member -MemberType NoteProperty -Name Architecture -Value "Unknown"            
 $OutputObj | Add-Member -MemberType NoteProperty -Name Status -Value $null            
 if(!(Test-Connection -ComputerName $Computer -Count 1 -quiet)) {            
  throw "HostOffline"            
 }            
    $CPUObj = Get-WMIObject -Class Win32_Processor -ComputerName $Computer -EA Stop            
 $CPUArchitecture = $CPUHash[[int]$CPUObj.Architecture]            
 if($CPUArchitecture) {            
  $OutputObj.Architecture = $CPUArchitecture            
  $OutputObj.Status = "Success"            
 } else {            
  $OutputObj.Architecture = ("Unknown`({0}`)" -f $CPUObj.Architecture)            
  $OutputObj.Status = "Success"            
 }            
 } catch {            
 $OutputObj.Status = "Failed"            
 Write-Verbose "More details on Failure: $_"            
 }            
$OutputObj            
}            

Output:

cpu-architecture

This script is available on technet scripting gallery as well.

{ 0 comments }

As you are aware, Microsoft has introduced new Task Manager from Windows 8/Windows Server 2012. In earlier versions of windows it is easy to recognize a 32-bit process in task manager as it will have an asterisk (*) symbol at the end of process name. However from Windows 8 & Windows server 2012 this appears to be changed.

In this article, let us see how to find the architecture of a process in Windows 8 & Server 2012 environment. This data is available in task manager but you need to add a new column named Platform to the view in details tab. Like previous versions of operating systems, there is no select Column option under the view menu.

So to see the platform of the process you need to switch to details tab in Task Manager and then right click on the column header row so see the options Hide column & Select Column. The Select Column will show the list of columns that are available for adding in task manager. If you scroll down, you will see platform option and after selecting that check box, you will see a new column with the name platform in task manager and it will show whether a process is 32-bit or 64-bit.

Process architechture-windows 8

Happy learning.

{ 0 comments }

Some scripts requires to be triggered from elevated powershell prompt based on what is being done in the script. In such cases, generally I use approaches like the one below. It uses a few dotnet classes to determine if the current shell is running in elevated mode or not.

$CurrentLogin = [System.Security.Principal.WindowsIdentity]::GetCurrent()            
 $secprincipal = New-Object System.Security.Principal.WindowsPrincipal($CurrentLogin)            
 $AdminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator            
 $IsAdmin=$secprincipal.IsInRole($AdminRole)            
 if(-not $IsAdmin) {            
    Write-Warning -Message "You are not running the script from 
    non elevated shell. You need elevated shell to complete the tasks in the script"            
    return            
 }            
 write-host "Staring the script execution"

While there is nothing wrong in using code like above, I came across a much nicer and easy way to do it. PowerShell has a key word called #requires which can be used to verify if the script is running from a elevated shell or not.

All you need to do is add the below line to starting of your script.

#requires -runasadministrator

So when such scripts are triggered from non elevated powershell prompt, you will see error message like below and your script execution will not start.

requires-statement-powershell

#requries has some more options using which we can verify if the shell is running a particular version of PowerShell or not and you can every verify if certain modules/snapins are imported or not.

You can get full help about requires statement by running command.

Get-Help About_requires

Thanks to PSTips from PowerShell.com for making me learn this. 🙂

Hope this help and happy learning.

{ 0 comments }

In one of my previous posts(https://techibee.com/powershell/how-to-connect-iso-image-file-to-virtual-machine-in-hyper-v-remotely-using-powershell/2306), I showed how to connect a ISO file to Virtual Machine in Hyper-V using PowerShell. This post will help you to identify and remove ISO file from a virtual machine. This works for all versions of Hyper-V(Windows Server 2008 & Windows Server 2012).

If you are just worried about managing VMs in Windows Server 2012 based Hyper-V, then all you need is just a single line. Set-VMDVDDrive cmdlet helps you disconnect a ISO or connect a ISO file. If you are on Windows server 2008, then you need this script. This is actually stripped from my previous post where I am connecting ISO using powershell & WMI.

Windows Server 2012 Hyper-V

Import-Module Hyper-V            
Set-VMDvdDrive -Path $null -VMName Win8

In case if your multiple DVD drives and you want to clear only one of them, then you need to specify the controller ID. Controller number and Controller location you can get from VM properties in Hyper-V Console.

Set-VMDvdDrive -Path $null -ControllerNumber 1 -ControllerLocation 1 -VMName Win8

Windows Server 2008 Hyper-V & Windows Sever 2012 Hyper-V

[cmdletbinding()]            
Param(            
 [string]$VMName,            
 [string]$HyperVServer = $env:ComputerName            
)            
            
$VMMS = Get-WMIObject -Namespace root\virtualization `
      -Class Msvm_VirtualSystemManagementService `
      -ComputerName $HyperVServer `
      -EA Stop            
            
# Get the virtual machine object            
$VM = Get-WMIObject -Namespace root\virtualization `
     -Class MSVM_ComputerSystem `
     -Filter "ElementName='$VMName'"  `
     -ComputerName $HyperVServer `
     -EA Stop            
            
# SettingType = 3 ensures that we do not get snapshots            
$SystemSettingData = $VM.getRelated("Msvm_VirtualSystemSettingData") | where {$_.SettingType -eq 3}            
            
# Get the first DVD drive in the system            
$DVDDrive = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where{$_.ResourceType -eq 16} | select -first 1            
            
# Make sure the DVD actually exists            
if ($DVDDrive -eq $null) {            
   Write-Warning "No DVD drive exists on that virtual machine"            
   return            
}            
             
            
# Check to see if there is already media in the DVD drive            
$existingRASD = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where {$_.Parent -eq $DVDDrive.__Path}            
            
# If there is media in the drive - eject it            
if ($existingRASD) {            
   $result1 = $VMMS.RemoveVirtualSystemResources($VM, @($existingRASD))            
   if($result1.ReturnValue -eq 0) {            
  Write-Host "Successfully ejected the exiting ISO image"            
   }            
} else {            
 Write-Host "No ISO file is currently connected"            
}

Output:

disconnect-vm-pscodeRemove ISO

Hope this helps and happy learning.

{ 1 comment }

WMI Explorer is a very handy tool for understanding and exploring WMI classes & Name spaces in Windows environment. The good thing about this tool is its ability to display instances, properties and methods of a given class. You can explore the WMI classes and namespaces available in other computers as well using this tool.

You can download this tool from here

WMI Explorer

SAPIEN also has similar tool but its licensed. You can still try the trial version of it. You can download it from http://www.sapien.com/software/wmiexplorer

{ 0 comments }

Last Saturday I attended Singapore PowerShell Saturday #009 event. This is my second PS event(read details of first event here) and what is special for me this time is, I presented on a topic.

PowerShell and WMI” is the topic I chose since this is very useful for any Windows System administrator and they can straightway try this at work. You can get a copy of my presentation from the links given at the end of the article.

Matt Hitchcock presented on new features in Windows PowerShell V5 and a few PowerShell editors from SAPIEN. His PPT has lot of useful links about various new features in PowerShell V5, I stashed them in favorites for now and will read them soon.

Milton Goh presented on Managing Azure with PowerShell. It’s a kick start for me and will definitely explore this platform as this is the future for IT. I liked the videos she shared and the way he presented. Nice.

There was also a short presentation from Katherine Chen (SEA MVP Lead) overviewing Microsoft Most Valuable Professional Program(a.k.a MVP). It’s informative. Now I know how many MVPs are in Singapore J

After stomach full lunch, the hands-on session started. Below two challenges are given to the participants and they worked hard to show their version of code to complete the challenges. PowerShell script analyser is the judge for analyzing the participant’s code for best practices. It’s a cool tool, you should try it out as well.

  1. Read the DHCP IP address, subnet, gateway, DNS servers details from all NICs in a remote server and convert these details to static
  2. Write a script that can detect and shout when a USB is plugged or unplugged into the computer.

Overall, it’s a good learning experience. You can download all presentations from below link.

DOWNLOAD

Thanks to Srinivas Addagatla and Satish Manchana (my friends/senior) for being there in the session and their support and encouragement.

If you are in Singapore and would like to join this group, use one of the below handles to subscribe.

Happy learning..

{ 1 comment }

The script posted in this article will help you to mount a ISO file to a Virtual Machine(VM) in Hyper-V running on Windows Server 2012 or Windows Server 2008 R2.

While building a VM in my test lab I was mounting ISO to start the installation. I thought why not mount the ISO using PowerShell and built this script. This script works based on WMI classes in root/Virtualization namespace. So it be used in all version of Hyper-V available in market.

Using this script you can connect ISO to DVD drive in a VM running on remote Hyper-V server as well. This script ejects if there is already a ISO connected via the DVD drive and mounts the ISO you specified.

This script is based on the article written at a MSDN blog from where I grabbed the code and polished it to suite my needs.

[cmdletbinding()]            
Param(            
 [string]$VMName,            
 [string]$HyperVServer = $env:ComputerName,            
 [string]$ISOPath            
)            
            
$VMMS = Get-WMIObject -Namespace root\virtualization `
      -Class Msvm_VirtualSystemManagementService `
      -ComputerName $HyperVServer `
      -EA Stop            
            
# Get the virtual machine object            
$VM = Get-WMIObject -Namespace root\virtualization `
     -Class MSVM_ComputerSystem `
     -Filter "ElementName='$VMName'"  `
     -ComputerName $HyperVServer `
     -EA Stop            
            
# SettingType = 3 ensures that we do not get snapshots            
$SystemSettingData = $VM.getRelated("Msvm_VirtualSystemSettingData") | where {$_.SettingType -eq 3}            
            
# Get the first DVD drive in the system            
$DVDDrive = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where{$_.ResourceType -eq 16} | select -first 1            
            
# Make sure the DVD actually exists            
if ($DVDDrive -eq $null) {            
   Write-Warning "No DVD drive exists on that virtual machine"            
   return            
}            
             
            
# Check to see if there is already media in the DVD drive            
$existingRASD = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where {$_.Parent -eq $DVDDrive.__Path}            
            
# If there is media in the drive - eject it            
if ($existingRASD) {            
   $result1 = $VMMS.RemoveVirtualSystemResources($VM, @($existingRASD))            
   if($result1.ReturnValue -eq 0) {            
  Write-Host "Successfully ejected the exiting ISO image"            
   }            
}            
            
# Create a new object for a DVD ISO, connected to the DVD drive            
            
$DVDAllocationCapabilities = Get-WMIObject -Class Msvm_AllocationCapabilities `
           -ComputerName $HyperVServer `
           -Namespace root\Virtualization `
           -Filter "ResourceType=21 and ResourceSubType='Microsoft Virtual CD/DVD Disk'" `
           -EA Stop            
                     
$DVDAllocationCapabilities = $DVDAllocationCapabilities.__Path.Replace('\', '\\')            
            
$DVDSettingsData = Get-WMIObject -Class Msvm_SettingsDefineCapabilities `
         -ComputerName $HyperVServer `
         -Namespace root\virtualization `
         -Filter "GroupComponent='$DVDAllocationCapabilities' and ValueRange=0" `
         -EA Stop            
            
$DVDSettingsData = [wmi]$DVDSettingsData.PartComponent            
$DVDSettingsData.Connection = @($ISOPath)            
$DVDSettingsData.Parent = $DVDDrive.__Path            
            
# Add the ISO to the virtual machine            
$result = $VMMS.AddVirtualSystemResources($VM, $DVDSettingsData.GetText(1))            
if($result.ReturnValue -eq 0) {            
 Write-Host "Successfully attached the ISO image $ISOPath to $VMName"            
} else {            
 Write-host "Failed to attach the ISO image $ISOPath to $VMName"            
}            
            
            

Hope this helps & happy learning..

{ 0 comments }

I came across this free ebook while  exploring a few PS articles. It has some valuable information for Windows admins and a practical approach to learn few things.

Download it by clicking on the below link.

PoshNetworking.pdf

 

{ 0 comments }

Find the size of storage drives in ESX

This post will help you with a few ESX commands that you can run from ESX console to find out details of storage connected to ESX host. ESX/ESXi can have multiple types of storage like locally connected storage, SAN, NFS, or USB. If you want to find out the size and other details of these storage, then you can use the below command based on your ESX version.

On ESXi 5.x

esxcli storage core device list

This will list all the storage devices attached to a ESX host. The size parameter for each storage drive gives you the storage size in MB.

On ESX/ESXi 4.x

esxcfg-scsidevs -l

This will list all the storage devices attached to a ESX/ESXi4.x host. The size parameter for each storage drive gives you the storage size in MB.

I found some more useful commands while searching for this. You may find these useful.

ESXi5.x

esxcli storage core path list

Generates list of LUN paths that are connected to ESX host. You will find storage device IDs, displayname, and several other information that you generally see in storage section of ESX Configuration tab in VC.

esxcli storage vmfs extent list

Provides list of extents and their details connected to ESX server.

You can refer to http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1014953 for some more useful commands.

{ 0 comments }