how to check .net version installed on 500 workstations

I work for a company with a lot of workstations and we currently use IBM BigFix to query worksations for their .Net framework version. My question is Is there another way to query workstations besides using BigFix or Tanium? All I want to do is check each workstation for .Net 4.0 and above and report all the names of the workstations that does not have .Net 4.0 or above.
matthew phungAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Wylie BayesNetwork Technician IIICommented:
What OS are the workstations?  Windows 7 or higher?
Dave HoweSoftware and Hardware EngineerCommented:
Its certainly possible, don't have any code on hand to do it though.  I can think of two ways immediately that you could achieve this.  The first is a bit crude (actually, a lot!) , but has the benefit of being easy to understand and very short indeed :)

Both answers rely on the fact that the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP has one subkey per installed framework - so reading that on each machine in turn would give you the info you need. Further, all dotnet frameworks from 4.0 onwards use a registry key of "v4" - so checking for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4 would tell you have 4.0 *or better* without investigating further, which is probably good enough

Now, on to the crude method :)

Assuming you have your users logging into a domain, you can establish a network share on a server that is world writable, and have each user login script execute the relatively simple command:


(placing the share path in front of the computername variable so that it writes to the network)

as %COMPUTERNAME% contains the name of the computer (logically enough) that should give you a separate file for each workstation, containing the registry keys under the key indicated. Simply wait a few days, then you should have the info you need (although not really in a tidy list without further processing)

For a less crude method - there is a powershell module (formerly on the ms site, now on codeplex) that lets you query the registry of a remote machine.  You could logically write a powershell script to check the registry key above for a single named remote machine (passed as an argument) then you need to call that script once per machine, and record the result.

With 500 workstations though, iterating though the set (particularly if you aren't going to know what IP they might have or if they are turned on at any given moment) could be interesting.  You can also use WMI (although its more awkward to code for than a dedicated PS module) - both methods would have the benefit of outputting a tidy list.  Combining this with the first method, you could run (say) vbscript in the login script, extract the info you need locally, then write it to a database or similar on a server - but that's a fair bit of work to code up (of course, if you wanted to re-use the technique for other checks, then it might be worth investing time coding a solution so that you have an example to modify when you have something you want and can't get easily by any other method)
Wylie BayesNetwork Technician IIICommented:
This can be easily achieved with powershell.  If the workstations are Windows 7 or higher.
Angular Fundamentals

Learn the fundamentals of Angular 2, a JavaScript framework for developing dynamic single page applications.

matthew phungAuthor Commented:
Thank you Dave for your detailed answer. I am not too familiar with PowerShell so is there a good tutorial/resource you guys recommend. I am very strong in C# and VB.Net. I appreciate your help, guys
Wylie BayesNetwork Technician IIICommented:
Gather Machine IP's via LDAP / Pulling from OU and machine objects:

<#          .SYNOPSIS
        AD Searcher unites with .Net DNS object to quickly provide IPs by organizations
            for asset list import to Nessus.
            Collects IP addresses for Active Directory computer objects by OU.
            Name: Get-PMOIPs
        Author: Steve Jarvi
        DateCreated: 9 April 2014
          FOR Changing Machine OUs: "LDAP://OU=SomeOU,OU=SomeOU,OU=SomeOU,OU=SomeOU,DC=SomeDC,DC=SomeDC,DC=SomeDC,DC=COM"

$searcher = New-Object System.DirectoryServices.DirectorySearcher $([ADSI] "LDAP://OU=SomeOU,OU=SomeOU,OU=SomeOU,OU=SomeOU,DC=SomeDC,DC=SomeDC,DC=SomeDC,DC=COM")
$searcher.pagesize = 1
$searcher.filter = ("(objectCategory=computer)")
$array = @($($searcher.findall()) | % {$})

@(for ($i=0;$i -lt $array.count; $i++){
            Try {
            Write-Host "Forward lookup entry found for: $($array[$i])" -Fore green
            Catch {
            Write-Host "There is no forward lookup DNS entry for: $($array[$i])" -Fore red
      }) > machine_ips.txt

get-software function (Can be tuned for just ".net" frameworks)

Function Get-Software{
    <# .SYNOPSIS
        Gets the software applications on a remote computer.
        This function interrogates the remote registry for installed
            software products.
        It then returns an array of powershell objects that can be sorted
            and parsed.
        Optionally, you can provide a product name that will filter
            applications based on displayname before they are returned, thus reducing the typing
            needed to get specific results.
            .PARAMETER computer
        The name of the computer to retrieve a software list from.
            .PARAMETER product
        The partial name of a software application to search for.
        Name: Get-Software
        Author: Geoffrey Guynn
        DateCreated 9 Aug 2011
        Get-Software -computer "computer" -command "Adobe"
        Returns all instances of Adobe software on the computer.

        SupportsShouldProcess = $True,
        DefaultParameterSetName = "process",
        ConfirmImpact = "low"
    if (TestRemoteAdmin $Computer){
        #Get Architechture Type of the system
        #$OSArch = (Gwmi -computer $Computer win32_operatingSystem).OSArchitecture
         $OSArch = (Gwmi -computer $Computer win32_operatingSystem).caption
        if ($OSArch -like "*64*") {$Architectures = @("32bit","64bit")}
        else {$Architectures = @("32bit")}
        #Create an array to capture program objects.
        $arApplications = @()
        foreach ($Architecture in $Architectures){
            #We have a 64bit machine, get the 32 bit software.
            if ($Architecture -like "*64*"){
                #Define the entry point to the registry.
                $strSubKey = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
                $SoftArchitecture = "32bit"
                $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry64
            #We have a 32bit machine, use the 32bit registry provider.
            elseif ($Architectures -notcontains "64bit"){
                #Define the entry point to the registry.
                $strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
                $SoftArchitecture = "32bit"
                $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry32
            #We have "64bit" in our array, capture the 64bit software.
                #Define the entry point to the registry.
                $strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
                $SoftArchitecture = "64bit"
                $RegViewEnum = [Microsoft.Win32.RegistryView]::Registry64
            #The standard routine to get software.
            #Create a remote registry connection to the server.
            $remRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer, $RegViewEnum)
            #Open the entry point.
            $remKey = $remRegistry.OpenSubKey($strSubKey)
            #Get all subkeys that exist in the entry point.
            $remSoftware = $remKey.GetSubKeyNames()
            #Loop through the applications and capture data.
            foreach ($remApplication in $RemSoftware){
                $remProgram = $remRegistry.OpenSubKey("$strSubKey\\$remApplication")
                $strDisplayName = $remProgram.GetValue("DisplayName")
                if ($strDisplayName){
                    #Get a list of all available properties for the program.
                    $arProperties = $remProgram.GetValueNames()
                    #Create a custom object for this program.
                    $objApplication = New-Object System.Object
                    #Write-Host "`n"
                    foreach ($strProperty in $arProperties){
                        #Get the value associated with the current property.
                        $strValue = [string]($remProgram.GetValue($strProperty))
                        if ($strValue){
                            #If the property has a value but no name, then it is the default property.
                            if (!$strProperty){
                                $objApplication | Add-Member -type NoteProperty -Name "(Default)" -Value $strValue
                            #The property has a value and a name, assign them both as a new property on the object.
                                $objApplication | Add-Member -type NoteProperty -Name ([string]$strProperty) -Value $strValue
                        #Write-Host $strValue ": "
                    #Add a final property to denote the software architecture type.
                    $objApplication | Add-Member -type NoteProperty -Name "Architecture" -Value $SoftArchitecture
                    #Add the last application to the array of programs.
                    $arApplications += $objApplication
            #Sort the array by each object's displayName.
        if ($Product){
            $objApplication = $arApplications | ? {$_.DisplayName -Like "*$Product*"}
            return $objApplication
        $arApplications = $arApplications | Sort-Object -property Architecture,DisplayName
        return $arApplications
    return $null

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Are you able to run a DOS command remotely on all the 500 workstations ?
It could search for the .net string to detect if the .NET is installed or not.
Would that be sufficient ? If Yes i can provide the command i have somewhere.
matthew phungAuthor Commented:
Wiley, Thank you for the detailed reply again. I will definitely play around with the code.

Stampel, I  might be able to run DOS remotely so can you provide me the command? Once again, thank you everyone for your help
FrankCrastCo-founder and CEOCommented:
Some of this may already be covered before, but Microsoft has a good MSDN article that helps summarize how to do this:

In BigFix, you should be able to create a simple fixlet to search for the reg key and values you need -- e.g., HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP (from article above). Fixlets are much easier than writing custom scripts in my opinion. You may as well use BF if you already have it, to keep it simple.

IBM has lots of sample solutions to help with this, for instance this example to search for a value in a reg key:

Hope this helps.
Ok here is the command to return any installed software matching ".NET"

C:\>wmic product get name | findstr .NET
result for me =>
Microsoft .NET Framework 4.5.1 (EN)
Microsoft .NET Framework 4.5.1
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Windows Networking

From novice to tech pro — start learning today.