≡ Menu

Today I got some requirement to verify the database name and DB server details of WSUS servers. This configuration is available inside HKLM\Software\Microsoft\Update Services\Server\Setup registry key of each WSUS server. So, I can query this registry value to find out what is the name of WSUS DB and DB server.

But out of curiosity, I started looked at the WSUS API that Boe Prox demonstrated in several articles on Script Guys blog as well as his personal blog. In past I have used this API query several other information like members of a WSUS group, patch approval status, and other information. So I thought it should have the DB details as well.

Luckily, I got what I need in few minutes. The root WSUS API object itself is having a method called GetDatabaseConfiguration which can return SUSDB and Database server details.

I wrapped this method inside a small function and I got what I need. Below is the sample code if you want to query this information.

function Get-WSUSDBDetails {            
[cmdletbinding()]            
param(            
[string]$WSUSServer            
)            

[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")            
$WSUSObj = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($WSUSServer,$False)            
$WSUSObj.GetDatabaseConfiguration()            

}

Happy learning…

{ 0 comments }

PowerShell: How to get exit code of a process

While working on a script that does file copy using Robocopy utility, I had the need to capture the exit code from the process I started. I relied on System.Diagnostics.Process dotnet class to start the copy operation using robocopy because it gives me an option to get the return code after the process completion.

So after my work, I started analyzing why such functionality can’t be achieved with Start-Process cmdlet. So, my conclusion is, it can be done with cmdlet as well. Let us see how to achieve that.

$process = Start-Process robocopy -ArgumentList "c:\scripts c:\temp\backup /MIR" -WindowStype Hidden -PassThru

By default start-process will not return process object it started. To get the process object, we need use the -PassThru parameter. The returned object has the capability to refresh its state automatically(I haven’t seen this with process objects returned by Get-Process). You can check HasExited value of the process obj attribute to determine it completed or not. It returns True when execution completed. And then ExitCode attribute will tell you the return code.

process-exit codeBelow are the some of the returns codes that robocopy exhibiting in different conditions.

exitcodes1

Happy learning…

{ 0 comments }

A application can go unresponsive because of various reasons. Until, we identify and kill such applications, the system hands and creates log of inconvenience to the user. Such applications also consume resources and make system unstable. So, let us see how to identify the not responding applications in a computer.

When I say “Not Responding”, I mean to refer to the status that the applications shows in Task manager. Some applications look fine from task manager perspective but may not be doing their actual task. They are out of scope for this post.

Each process returned by Get-Process has a attributed called Responding which indicates the status of application. The value of this attribute is set to True if the application is running fine. A False value indicates that application is not responding.

Code:

[CmdletBinding()]            
Param(            
 [string[]]$ComputerName = $env:ComputerName            
)            

foreach($Computer in $ComputerName) {            
 if(!(Test-Connection -ComputerName $Computer -Count 1 -quiet)) {             
  Write-Host "$Computer : OFFLINE"            
  Continue            
 }            
 try {            
  $Processes = Get-Process -ComputerName $Computer -EA Stop            
  $nProcesses = @($Processes | ? { $_.Responding -eq $false })            
 } catch {            
  Write-Error "Failed to query processes. $_"            
 }            

 if($nProcesses) {            
  foreach($nProcess in $nProcesses) {            
   $nProcess | select Name, id, MainWindowTitle, Responding            
  }            

 } else {            
  Write-host "No non-responding processes found"            
 }            

}

This function will return name, PID, windows title of the non responding process. If you want to kill such processes, refer to the article I have written for 4SYSOps(http://4sysops.com/archives/query-and-kill-a-process-on-a-remote-computer-using-powershell-and-wmi/)

{ 1 comment }

Whenever a server reboot is performed, a big question comes into mind is, “All services started properly”? Let us discuss this topic a bit more in this post.

Normal approach to verify services status after server restart is looking for automatic status and their current state(start/stop). While this is good for Operating system related services, not up to the mark for any application based services. I have seen application services where the application startup is set to manual and the service is started via some scheduled task/startup task. Both in house developed applications and third party vendor applications come in this category. In some cases, I suggested the teams to use right state(automatic) to get their services started after the server reboot, but in other cases, it was a sort of dependency on the other components of the system that making developers to create such weird kind of start up procedures.

So, while checking for a more authentic way to verify a service start up status, I came across service exit codes. Each service will have exit code set when the service is attempted to start/stop. Examining these errors codes will cover all kinds of scenarios and more efficient way to check services startup status after the server reboot.

Each service will have a exit code and we can read by using WMI. Let us look at the below example.

Get-WMIObject -Class Win32_Service -Filter "Name='spooler'"
service-returncode-0

Here I am querying spooler service using WMI and the return code from this service is 0(zero). That means it started property.

Now let us look at another service which is in stopped state.

Get-WmiObject -Class Win32_Service -Filter "Name='Fax'"
service-returncode-1

The return code here is 1077. If you type net helpmsg 1077 in command prompt, you will know what is the meaning of this error.

1077-error

So, 1077 means, this service was never attempted to start so no scope of failures here.

Like this you can analyze the startup status of a service by looking at the exit codes. I wrapped my whole explanation into small powershell code for your usage. I haven’t completely tested this yet, but you know any false positives, do let me know and I will try to improve this.

Code : Get-ServicesFailedToStart.ps1

[cmdletbinding()]            
Param(            
[string[]]$ComputerName = $env:ComputerName            
)            

foreach($Computer in $ComputerName) {            
 if(Test-Connection -Computer $Computer -Count 1 -quiet) {            
  try {            
   $services = Get-WMIObject -Class Win32_Service -Filter "State='Stopped'" -ComputerName $Computer -EA stop            
   foreach($service in $services) {            
    if(!(($service.exitcode -eq 0) -or ($service.exitcode -eq 1077))) {            
     $Error = Invoke-Expression "net helpmsg $($service.Exitcode)"            
     $Service | select Name, Startmode, State, Exitcode,@{Label="Message";Expression={$Error[1]}}            
    }            
   }            
  } catch {            
   Write-Verbose "Failed to query service status. $_"            
  }            
 } else {            
  Write-Verbose "$Computer : OFFLINE"            
 }            
}

Output:

failed-tostart-services-output

You can download this script from Technet script gallery as well(http://gallery.technet.microsoft.com/Query-that-failed-to-start-01c610d4)

Hope this article helps and let me know if you have any feedback.

{ 3 comments }

Powershell : Write-Host Vs Write-Output

What is the difference between Write-Host and Write-Output??

I came across a useful article from PowerShell inventor about why you should not use Write-Host in general context unless you want to utilize specific features of it. It is a good read and worth having a peek. To output any data to console it is wiser to use Write-Output instead of Write-Host.

http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/

The output returned by Write-Output is passed to pipeline so the functions/cmdlets after the pipeline can read this for further processing. This is not possible if you use Write-Host.

let us examine this behavior with a small example.

function Send-text {            
    write-host "I am sending to console"            

}            
function Send-textwithwriteoutput {            
    write-Output "I am sending to console"            

}            

function Receive-Text {            

    process { write-Host "Received : $_" }            
}

I have three functions

  • Send-Text #sends text to console using write-host
  • Send-TextWithWriteOutput #sends text to console using write-output
  • Receive-Text #receives input from pipeline and shows it

Now look at the below output:

It is very clear from the above output that when sent text to console using write-host, it is not passed to pipeline. But when write-output is used the receive-text function parsed and displayed the value.

Its not that you should not use Write-Host but what I mean is use at the right place. For example, no other cmdlet can replace Write-host cmdlet when you want to apply colors to text you are displaying to console. So, it is wiser to use write-output as a general practice as we expect our code to make the output utilized by other functions/cmdlets.

Hope it is clear. Happy learning.

{ 0 comments }

Yesterday I have used PowerShell to build a VHD of Windows 8.1 from ISO file. My home laptop is having Windows 8.1 home edition and features set is limited. To explore the features in Windows 8.1 enterprise edition, I decided to make my laptop multi boot.

When I decided to make multi boot, I have two options. Install Windows 8.1 from ISO on my laptop or prepare a VHD windows 8.1 pre-installed and make my laptop via the VHD file (this is called native boot from VHD). Since the latter option is easy and not much changes are required for my laptop, I searched for evaluation Windows 8.1 VHD from Microsoft. But unfortunately, there is only ISO download for evaluation and no VHD available.

So I thought I need to create a VM in Hyper-V, install windows 8.1 via ISO and then use that VHD to boot my laptop. But wait, that a long process. After searching for a while I landed on a PowerShell script in TechNet Script gallery that can take ISO file as input and prepare VHD with OS installed. I felt it amazing and started downloading the script. I tried the script and in hardly 30 minutes I had my VHD ready. I added this VHD to my boot options and I have Windows 8.1 enterprise evaluation edition running on my laptop via VHD boot.

Since this is very useful, I thought I will share this with every. Using this procedure, you can built servers in lab/production environment very fast using ISO file and not relying on newsid.exe/sysprep like utilities.

Download the Windows 8.1 evaluation ISO from Microsoft site

Download Convert-WindowsImage.ps1 from TechNet Library

After downloading, run the script as shown below from a Windows 8 or Windows server 2012 machine. The script is expected to work from either of these operating systems only as per the support matrix in TechNet gallery.

C:\local\Convert-WindowsImage.ps1   -SourcePath "D:\local\Windows8.1.ISO" `
                                    -VHDFormat VHDX `
                                    -Edition ServerDataCenterCore `
                                    -VHDPartitionStyle GPT `
                                    -Verbose

This will start the VHDX creation process and approximately 20-30 minutes, you will have the VHDX file ready.

Once the VHDX file is ready, you need to add the file to boot menu on your existing OS installation, so that you can choose to boot from it when are the boot OS selection menu.

To achieve this, you follow the below instructions.

  • Backup your existing boot menu(BCD store) using /export switch of bcdedit.exe utility. Example, bcdedit /export c:\bcdbackup
  • Execute the below command and note the GUID along with braces retuned from the command.

bcdedit /copy {default} /d “VHD BOOT”

  • In my case it returned {d15fb411-28c6-11e3-be8c-1c3e847f665e} so the next commands will look like below. Make sure to replace my GUID with yours.

bcdedit /set {d15fb411-28c6-11e3-be8c-1c3e847f665e} device vhd=[D:]\local\windows.vhdx

bcdedit /set {d15fb411-28c6-11e3-be8c-1c3e847f665e} osdevice vhd=[D:]\local\windows.vhdx

  • This completes the process for adding entries for boot menu.
  • Now restart your laptop and you should see the VHD BOOT in your boot menu and choose it to boot through the VHD you just created.

If you receive errors messages from Mount-DiskImage (like “Mount-DiskImage : The version does not support this version of the file format”) while using the Convert-WindowsImage.PS1, then you can extract the ISO contents to a folder (I used 7-zip) and pass the WIM file to –SourcePath parameter of the script as shown below. Basically, the problem here is, Mount-DiskImage is failing to mount the ISO files to read the installation media.

Finally, a BIG thanks to this script author and you can read more about this script at http://gallery.technet.microsoft.com/scriptcenter/Convert-WindowsImageps1-0fe23a8f

Happy learning

{ 1 comment }

If you are using a Windows 8 PC, but this time you must be knowing that there are two types of apps in this OS. One type is “Store application” and another is “Desktop application”. I don’t want to go in detail about explaining differences between them, but want to say in nutshell that, store application is something you install directly from windows store maintained by Microsoft. These apps are designed specially for touch screen users. Built-in Skype, Citrix Receiver are classic examples of this application in Windows 8.1. Desktop applications is same like what we have in previous versions of operating systems where installation is via MSI/MSP and usage is same as the we way we use applications in previous versions.

Keeping the differences aside, I want to show you how to query applications installed via Windows store on Windows 8.1 OS and uninstall them.

Windows 8.1 has a module called Appx for managing apps installed via Windows Store. The Get-AppxPackage cmdlet will help us to list all store installed applications. Look at the below screen.

Get-AppxPackage | select Name
get-appxpackage-listapps

Name is the most appropriate parameter to recognize the application in the output. I looked for exact display names but no such attribute in the output.

Once you have the list, identify the software that you are planning to uninstall and make a note of its name. In my case, I tried to uninstall “D50536CD.CitrixReceiver” which is the name for Citrix Receiver. This app is not working fine on my computer so decided to uninstall it so that I can get desktop version of this application.

To uninstall a windows store application we can use Remove-AppxPackage cmdlet. The usage is simple as shown below.

Get-AppxPackage | ? {$_.Name -eq "D50536CD.CitrixReceiver" } | Remove-AppxPackage

uninstall store app

Once uninstalled, you can again verify to see if it still exists.

Get-AppxPackage | ? {$_.Name -eq "D50536CD.CitrixReceiver" }

verify uninstallation

Hope this helps and happy learning.

{ 0 comments }

PowerShell: Show/Get a browse folder window

In today’s post, let us see some more useful methods inside shell.application com object. In previous post, I showed you how to get desktop icons status. In this post, I will demonstrate, how to display a window using which user can browse and select folder. You know what I am talking? Look at the below screenshot for clarity.

You no need to use any C#, dotnet, WPF stuff to get this. The script completely replies on Shell.Application COM object. This COM object has a method called BrowseForFolder using which we can generate this window. The selection is returned in the form of a object which we can process to get the path user selected via the window.

Code:

function Get-OutputFolder {            
 [CmdletBinding()]            
 Param(            
 )            

 $Shell = New-Object -ComObject "Shell.Application"            
 $Folder = $Shell.BrowseForFolder(0,"Choose Output Folder",0)            
 if($Folder) {            
  return $Folder.self.Path            
 } else {            
  Write-Warning "No folder selected"            
 }            

}

Output:

browseforfolder-output1 browseforfolder-output2

Happy learning.

{ 0 comments }

I came across this question sometime back. One of the member in a forum was asking if there is a way to find what is the status of icons visibility status on desktop. That means if the “Show Desktop Icons” option in desktop ->Right Click -> View is selected or not.

show-desktop-cons

I came across answer for this while exploring Shell.Application COM class. It has a method called GetSetting() which can return some of the shell properties. One of them is desktop icons visibility status.

Below small function can help you determine the status.

Code:

function Test-DesktopIconHiddenStatus {            
[CmdletBinding()]            
Param(            
)            

$shell = New-Object -ComObject "Shell.Application"            
if($shell.GetSetting("0x00004000")) {            
 Write-Host "Desktop icons are hidden"            
} else {            
 Write-Host "Desktop icons are visible"            
}            

}

Output:

showdesktopstatus-outputHappy learning…

{ 1 comment }

Get active window on desktop using PowerShell

In today’s post, I want to show how to know what is the active window on Desktop.  I came across this requirement when I want to determine, what is the application user is currently using. There is no PowerShell CMDLET that can do this straight away, so we need to rely on a bit of C# coding to achieve this.

The user32.dll DLL provides function called GetForegroundWindow which provides the window handle of active application/process. We can find the process name by Get-Process with returned window handle.

Code:

[CmdletBinding()]            
Param(            
)            
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class UserWindows {
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}
"@            
try {            
$ActiveHandle = [Windows]::GetForegroundWindow()            
$Process = Get-Process | ? {$_.MainWindowHandle -eq $activeHandle}            
$Process | Select ProcessName, @{Name="AppTitle";Expression= {($_.MainWindowTitle)}}            
} catch {            
 Write-Error "Failed to get active Window details. More Info: $_"            
}

Output:activewindow-using-powershell

You can download this script from Technet Gallery as well.

{ 8 comments }