≡ Menu

Querying Hyper-V made simple with Windows 8.1 and Windows Server 2012. But these two are latest version of Operating Systems and most of the people haven’t tried them yet in corporate environment. In this post I will demonstrate how to use WMI and Powershell to query a Hyper-V server without the use of MS given Powershell module or any other third party module.

When Hyper-V role is installed on a Windows server, it creates a set of WMI classes which we can query to get the required information.

To see list of WMI classes available, just run the below command on a Server where hyper-V role is available. All the Hyper-V related WMI classes are under “root\Virtualization” name space. You can query these classes remotely also like any other WMI class.

Get-WmiObject -Namespace root\virtualization -List

The WMI classes count might vary from Windows 2008 to Windows 2012 because of added features set. In this demonstration let us see how to get list of virtual machine names from Hyper-V using these WMI classes.

Details of virtual machines are stored under Msvm_ComputerSystem WMI class so querying this should list the names of the VMs hosted on the Hyper-V server.

Get-WmiObject -Class Msvm_ComputerSystem -Namespace "root\virtualization" | ? {$_.Caption -eq "Virtual Machine" } | select ElementName

If you notice the above command, I have used additional filtering by caption because by default this WMI class returns the name of the Hyper-V host as well – so to remove it from the list, I used filter to list down only virtual machines.

Hope this helps and happy learning.

{ 6 comments }

I am using Windows 8 for quite some time. Since I have UAC enabled in my computer, I need elevated command prompt to perform some actions. There are many articles on internet explaining different procedures to open an elevated command prompt. Most of them are using the search option in Windows 8. These approaches are taking more than 2-3 clicks to open a command prompt and being a system administrator I hate to follow such no. of steps to open my frequently used app. After some search over internet, I found my answer. It is as simple as pressing “Windows logo key Windows logo key +X” and then “A”. When you press Windows logo key Windows logo key +X, it will open Quick menu like shown in below screen and now pressing A will open command prompt in elevated mode. There are quite useful other shortcuts also available here.

Do you want to see how quick I can open now?

{ 0 comments }

By default, only administrators can view security event log in a Windows Server 2003 or 2008. In this article I will show you how to grant permissions to other users or groups to view security log content in a server without admin permissions.

For Windows Server 2008:

Let me start with something easy. For windows 2008 servers, it is very straight forward. If you want to allow any user or group view security event log, just add them to “BUILT IN\Event Log Readers” group and the task is accomplished. If you want to view who all has access to a given event log, try the below command

wevtutil gl security

For Windows Server 2003:

Like Windows server 2008, there is no straightforward way in Windows Server 2003. We need to tweak registry entries a bit to get the desired results. In Windows 2003, security log permissions are stored in registry key in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog\Security\CustomSD registry value. The data for this value will be in SDDL format (search for SDDL in MSDN to know more). We need to modify the data of this value to grant permissions to new users or groups.

Now I will show two cases of granting permissions to security event log and you can form your own SDDL based on these examples.

Grant security log access to anyone logging into the computer:

Anyone who is logging into the computer either through RDP or via console is treated as a “Interactive User”. So granting permission to interactive user will give them required access to security event log. In this example, I am giving read-only access to all the users who is logging in interactive to the server. For that I just need to append the below SDDL string to aforementioned CustomID registry value. Make sure to append it without quotes.

“(A;;0x1;;;IU)” – append this without quotes

If you want to give them full access, then use the below SDDL.

“(A;;0xf0007;;;IU)”

Grant security log access to a user or group:

For granting security log access to a user or group, you need to have their SID handy so that you can form the SDDL to grant them access. You can refer to https://techibee.com/sysadmins/fetch-the-sid-of-a-user-account-using-powershell/137 if you want to know how to get SID of a user using powershell. Once you have the SID handy, you can form the SDDL string to append to the CustomID registry value. In this example, I am using the SID of my domain user “S-1-5-21-1377399363-320120969-1166362429-510”. To grant this user read-only access, I need to append below SDDL string to the CustomID registry value.

“(A;;0x1;;;S-1-5-21-1377399363-320120969-1166362429-510)”

Similarly you can grant permissions to security group as well by replacing the group SID in the above example.

This completes the procedure for granting permissions to read security log entries for non-admin users.

A few useful links:

Default ACLs on Windows event logs  — http://blogs.msdn.com/b/ericfitz/archive/2006/03/01/541462.aspx

How to set security event log security locally or using group policies –

http://support.microsoft.com/default.aspx?scid=kb;en-us;323076

Some more deep dive into permissions —  http://blogs.technet.com/b/janelewis/archive/2010/04/30/giving-non-administrators-permission-to-read-event-logs-windows-2003-and-windows-2008.aspx

Well known security identifiers in Windows –

https://support.microsoft.com/kb/243330

Hope this helps.. Happy learning.

{ 1 comment }

New year wishes to my blog readers

A very happy and prosperous New Year to all my blog readers. I hope my articles in the blog are useful and you enjoy reading the content. I am really enjoying blogging and learning a lot from this.

I will do my best to keep the quality content flow in this blog. If you have any suggestions about type of content or any other, please feel free to send me an email; we can discuss further. Two frequent topics that people often ask me about are free e-books for learning and interview questions for Windows administrators. I have already written a few articles about free e-books (search the blog) and will try to keep them up to date. Interview questions is not something I focused so far but it is in my to-do list.  I try to blog some content about this soon.

Once again Happy New Year and happy learning.

{ 0 comments }

The PowerShell function discussed in this article will help you to find out list of Hyper-V servers in Domain.

In today’s post, let us see how to find list of Hyper-V servers in domain. Whenever a Hyper-V server is added to active directory, it creates a Service Connection point (SCP) object in Active Directory under the Hyper-V server computer name with name “Microsoft Hyper-V”. This SCP can be used to discover list of Hyper-V servers in active directory. Both Hyper-V2008 and 2012 exhibit this behavior. Now let us form a script based on this information to get Hyper-V servers in Active Directory.

Code:

function Get-HyperVServersInDomain {            
[cmdletbinding()]            
param(            
)            
try {            
 Import-Module ActiveDirectory -ErrorAction Stop            
} catch {            
 Write-Warning "Failed to import Active Directory module. Exiting"            
 return            
}            

try {            
 $Hypervs = Get-ADObject -Filter 'ObjectClass -eq "serviceConnectionPoint" -and Name -eq "Microsoft Hyper-V"' -ErrorAction Stop            
} catch {            
 Write-Error "Failed to query active directory. More details : $_"            
}            
foreach($Hyperv in $Hypervs) {            
 $temp = $Hyperv.DistinguishedName.split(",")            
 $HypervDN = $temp[1..$temp.Count] -join ","            
 $Comp = Get-ADComputer -Id $HypervDN -Prop *            
 $OutputObj = New-Object PSObject -Prop (            
 @{            
  HyperVName = $Comp.Name            
  OSVersion = $($comp.operatingSystem)            
 })            
 $OutputObj            
}            
}

In this script I am using a flaky code to get computer DN from SCP DN. I couldn’t find any better way at the moment. Please share if you are aware of any.

Output:

HyerVInDomain

Hope this helps.

{ 4 comments }

The Powershell script discussed in this article will help you to find out the physical host name of a virtual machine using powershell. It works for both VMware based virtual machines and Hyper-V based virtual machines.

Virtualization is growing very fast and many companies switching most of their infrastructure to virtual space. Depending on budget and feature set requirements companies are switching to VMware or Hyper-V virtualization. In some cases, they place critical servers in VMware and low priority in Hyper-V. Since the virtual world is spread across multiple platforms, there is a need to identify the physical host of a given virtual machine. Though companies maintain some sort of naming convention, it is not a full-fledged solution to determine if a host is physical or virtual. This is even truer in cases where P2V is performed to migrate physical machines to virtual world where name of the computer is not changed. I too had such requirement and thought that building a script for this is very useful for everyone.

Each virtual machine stores the physical host information in registry at “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters” in PhysicalHostName value. So to get physical host name of a virtual machine, we should just query the data of aforementioned registry value. The below script helps you in that course. Before querying the registry, first it verifies if the given host is virtual or not by verifying its mode. This is done by querying model attribute of Win32_ComputerSystem WMI class. If it is a virtual machine, then the script makes a remote registry call using [Microsoft.Win32.RegistryKey] dotnet class and connects to HKLM and then queries the value of the key mentioned before.

The script is capable of taking multiple computers from command line find their physical host names.

Save the below code into a file (Get-PhysicalHostName.ps1 for example) and use as shown below.

.\get-physicalhostname.ps1 –computername computer1,computer2

[This code is working for only Hyper-V servers at the moment. I am working on how to device this information for VMware VMs as well]

[cmdletbinding()]            
param(            
 [string[]]$ComputerName = $env:ComputerName            
)            
$KeyName = "SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters"            
$ValueName = "PhysicalHostName"            

foreach($Computer in $ComputerName) {            
 if(!(Test-Connection -ComputerName $Computer -Count 1 -quiet)) {             
  Write-Warning "$Computer is offline"            
  Continue             
 }            

 try {            
  $CompObj = Get-WMIObject -Class Win32_ComputerSystem -ComputerName $Computer -ErrorAction Stop            
  if($CompObj.Model -notmatch "Virtual") { throw "Not a virtual machine" }            

 } catch {            
  Write-Warning "$Computer : FAILED. Details : $_"            
  Continue            
 }            

 try {            
  $BaseKeyObj = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $computer)            
  $KeyObj = $BaseKeyObj.OpenSubKey($KeyName)            
  $Hostname = $KeyObj.GetValue($ValueName)            
 } catch {            
  Write-Warning "$Computer : Failed to get Physical host name. Details : $_"            
  Continue            
 }            

 $OutputObj = New-Object PSObject -Prop (            
  @{            
   ComputerName = $Computer.ToUpper()            
   PhysicalHostName = $Hostname            
  })            
 $OutputObj            

}

Hope this helps…

{ 8 comments }

The powershell script discussed in this article will help you reset and purge the policies on a SCCM client remotely using PowerShell.

SCCM(System Centre Configuration Manager) has variety of WMI classes and one of them is SMS_Client. This class helps you querying the machine policy remotely as well as reset and purge the existing policies.

You can check http://msdn.microsoft.com/en-us/library/cc146352.aspx for various methods available in this class. The script I am going to discuss below relies on ResetPolicy method to reset and purge the policies.

The script takes two arguments. 1) ComputerName 2) Purge. You can pass one or more computers(cama separated) to the ComputerName parameter. When this parameter is not specified it executes against local computer. The Purge argument is a switch type parameter. When it is used, the policy data will be purged. When not specified the reset policy will get executed with argument 1 which means full download of existing policy.

[cmdletbinding()]            
param(            
[string[]]$ComputerName = $env:ComputerName,            
[switch]$Purge = 0            
)            

if($Purge) {            
 $Gflag = 1            
} else {            
 $Gflag = 0            
}            

foreach($Computer in $ComputerName) {            
 $client = Get-WMIObject -Class SMS_Client -Namespace root\ccm -ComputerName $Computer            
 $returnval = $Client.ResetPolicy($Gflag)            
 if($returnvalue) {            
 Write-Warning "Error occurred while resetting/purging the policy on $Computer"            
 } else {            
 Write-Host "Purge/Reset successful on $Computer"            
 }            
}

I learned this from one of the contributor in “Hyderabad Powershell User Group” FB group. I am not an expert in SCCM but given that use case of this seems very high, I thought of converting it to a post.

Since I haven’t tried this script practically, I STRONGLY request you to try in a lab environment to see if it is giving desired results. Use at your own risk.

{ 6 comments }

In this article, I will show you how to create multiple test user accounts in active directory using PowerShell.

While playing with some stuff in my lab setup today, I got a requirement to have 100 test user accounts. I am not concerned much about the display name or any other properties of these test users and having names like user1, user2…user100 is enough in my case. I quickly looked around the options for doing this using PowerShell and finally settled with below approach as it seems much easy.

Since this is a very common requirement for anyone who are building and using their test labs for learning purpose, I thought of posting it here so that everyone can use it.

I used ActiveDirectory module that comes with Windows Server 2008 or above. It has cmdlet, New-ADUser, that simplifies the work. For this demonstration, I am creating user accounts from testuser1 to testuser100 with common password(“testme123”). I am also enabling the accounts after creation. All the new accounts will be created under the OU called LABAccounts at the room of my domain ad.techibee.com

You can copy paste the below code into a PowerShell window in your test lab and change –Path parameter to match your OU structure where you want to place the accounts and execute the script. You will see test accounts with in a minute.

Import-Module ActiveDirectory            
foreach($i in 1..100) {            
$AccountName = "TestUser{0}" -f $i            
$Password = Convertto-secureString -string "testme123" -AsPlainText            
New-ADUser -Name $AccountName -AccountPassword $Password -Path "OU=Labaccounts,DC=ad,DC=techibee,DC=com" -Enabled:$true            
            
}

Please note this above code is for lab purpose only where you want 100 or 1000 dummy user accounts for testing purpose. If you want to create users in production environment, you might want to set the required attribute values accordingly (like display name, telephone, etc).

{ 0 comments }

This article will help you understanding how to configure Memory (both static and Dynamic) on a Hyper-V Virtual machine. You can increase or decrease memory using the PowerShell scripts given in this article.

Ever since I am running my test lab on Windows Server 2012 Datacentre edition, I have been playing with various options in the OS and especially Hypervisor. I have multiple VMs running in the Hypervisor and today I wanted to increase Memory of one of my virtual machine name Infra2. I know it is very easy to do it from Hyper-V Manager but my love towards PowerShell won’t let me do that way. So started looking at options for increasing memory of my virtual machine from 1GB to 2GB using PowerShell code.

The Hyper-V PowerShell module in Windows Server 2012 has two cmdlets for adjusting the memory configuration of Virtual Machines. One is Set-VM and another is Set-VMMemory. While the first one is used for modifying any configuration of Virtual Memory, second one is explicitly designed to change memory configuration. In this article I will focus on Set-VM cmdlet.

Windows Server 2012 Hyper-V comes with Dynamic Memory concept. If you haven’t heard about it, you can try this TechNet page for more details. Using Set-VM cmdlet, we can set both Dynamic and static Memory of virtual machine. Let us start looking into some of the examples.

First let us see how to check the current memory configuration. Using Get-VM cmdlet we can see what is the current memory assignment, whether it is static or dynamic memory, if dynamic memory what is the max and min values.

Get-VM -Name Infra2 | select *Memory*
Virtual Machine Memory Change Powershell

The above output is pretty much self-descriptive. I want you to make a note of DynamicMemoryEnabled property value. If it is true, you have dynamic memory enabled. A False value like shown in above screen indicates that it’s a static assignment. In case of static assignment, MemoryStatup is the value that we need to focus. The value stored in this property is bytes.

So, now let us go ahead and see how to change the memory of this VM from 1GB (1073741824 in bytes) to 2GB. It is as simple as executing below command.

Set-VM -StaticMemory -Name Infra2 -MemoryStartupBytes 2GB

Now you verify your memory values again using Get-VM cmdlet and you will see new value in the MemoryStartup property.

Similarly, if you want to increase memory values in case of Dynamic memory, just do your math and come up with what values to you want to give for MemoryStartup, MemoryMinimum, MemoryMaximum properties and assign them like shown below. In the below example, I want my VM to start up with 1GB of RAM and can utilize up to 2GB and minimum value is 500MB.

Set-VM -Name Infra2 -MemoryStartupBytes 1GB -MemoryMinimumBytes 500MB -MemoryMaximumBytes 2GB

Hope this article helps and happy reading…

{ 2 comments }

Mount ISO file using Powershell

In this post I will show you how to mount a ISO file using Powershell in Windows Server 2012 and Windows 8 using native cmdlets. I will also explain how to get the drive letter of already mounted ISOs.

We all are aware that ISO files can be mounted as drives in Windows XP/7/8, windows server 2003/2008/2012. While it can be mounted on XP/Windows7 or Windows Server 2003/2008 using third party tools like “Virtual CD/DVD-ROM” from Magic ISO, Windows 8 and Windows Server 2012 provides direct ability to mount ISO files as physical drives. It is not that only ISO can be mounted, we can also mount exisiting VHD files and VHDX(new format of Hyper-V disks) files using the powershell commands in Windows Server 2012 and Windows 8.

I downloaded a Visual Studio ISO for my development requirements and I will show you how to mount that ISO using Powershell. In Windows Server 2012 and Windows 8, there is function called Mount-DiskImage in Storage module that comes by default with the OS installation. This cmdlet can be used to mount the ISO files.

This Mount-DiskImage function takes path of Image file using the -ImagePath argument and type of Image file using -StorageType argument. The -ImagePath argument is mandatory and StorageType argument is optional. When storageType argument is not specified it picks the storage type using the extension of file that you provided.

What I feel missing in this cmdlet is, ability to provide drive letter to which it should be mounted. That will help us easily determine the drive letter without scripts after mounting the ISO file.

Below is the command to mount the ISO file.

Mount-DiskImage -ImagePath c:\local\VS2012_WDX_ENU.iso

This function will not show any output after successful completion, but it will report errors if there are any. Similarly you can pass VHD or VHDX files to mount as physical drives using this function.

If the ISO you are trying to mount is already mounted as physical drive, then you will see error message like below.

Mount-DiskImage : The process cannot access the file because it is being used by another process.At line:1 char:1+ Mount-DiskImage -ImagePath C:\Users\administrator.AD\Downloads\VS2012_WDX_ENU.is …+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    + CategoryInfo          : NotSpecified: (MSFT_DiskImage …torageType = 1):ROOT/Microsoft/…/MSFT_DiskImage) [Mou   nt-DiskImage], CimException    + FullyQualifiedErrorId : HRESULT 0x80070020,Mount-DiskImage
If you want to know what is the drive letter assigned this ISO file after mounting, you can find it by using below command.

Get-DiskImage -ImagePath c:\local\VS2012_WDX_ENU.iso | Get-Volume

This will display the drive letter and other details as shown in below output.

Hope this article helps and happy learning.

{ 0 comments }