WMI

[POWERSHELL] CHECK QUEST KACE ONE AGENT SERVICE FOR MULTIPLE COMPUTER (VERSION #3)

Here is the #3 version, changes as below:

  • use of Win32_PingStatus for a ping timeout of 1500ms because Test-Connection defaults to 4 seconds and there is no option to change that.
  • Added error handling with try/catch
  • use Start-Job to start checking for service status once found PC is online.

 

#The OU to search
 $SearchBase = "OU=COMPUTER,OU=World_First,DC=domain,DC=local"

#output files
 $ServiceStatusFile = "ServiceStatus.csv"
 $OfflineFile = "Offline.csv"
 $noServiceFile = "noService.csv"

#Search result of computers (Windows only)
 $Computers = Get-ADComputer -Filter {OperatingSystem -Like "Windows*"} -SearchBase $SearchBase -SearchScope Subtree|sort Name

#Array for online computers
 $onlineComputers = @()

#Array for offline computers
 $offlineComputers = @()

$func={

function checkService{

param (
 [parameter(Mandatory=$true,ValueFromPipeline=$true)]
 [string]$client
 )

try{

$serviceStatus=get-service -DisplayName "Quest KACE One Agent" -ComputerName $client -ErrorAction SilentlyContinue -ErrorVariable ServiceNotAvailable|select-object MachineName,DisplayName,Status

if($serviceStatus){
 return $serviceStatus
 }

else{

write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable
 return $output
 }

}
 Catch [System.Management.Automation.CmdletInvocationException]{

write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable.Message
 return $output

}

Catch{
 $ErrorMessage = $_.Exception.Message
 $FailedItem = $_.Exception.ItemName

}

}
 }




#Check if computers are online
 foreach($computer in $computers) {

$client = $computer.Name
 #win32_PingStatus variables
 $filter='Address="{0}" and Timeout={1}' -f $client, $timeout
 $timeout= 1500
 Write-Progress -Activity "Checking computer availablilty....." -status "Ping computer $client" -percentComplete ($computers.IndexOf($computer) / $Computers.count*100)

if((Get-WmiObject Win32_PingStatus -Filter $filter).StatusCode -eq '0'){
 Start-Job -ScriptBlock {checkService $args[0]} -ArgumentList @($client) -Name "$client" -InitializationScript $func
 $onlineComputers= $onlineComputers+($computer)

}
 else{

$offlineComputers= $offlineComputers+($computer)
 Write-Warning -Message "$client is offline"

$client|Out-File -FilePath $OfflineFile -Append
 }

}







Get-Job|Wait-Job

foreach($onlineComputer in $onlineComputers){




$result=receive-job -Name $onlineComputer.Name -Keep

#Contains MachineName, service available
 if([bool]($result.PSobject.Properties.name -match "MachineName")){
 $result|select-object MachineName,DisplayName,Status|export-csv -Path $ServiceStatusFile -NoTypeInformation -Append

}

else{

$result|Out-File -FilePath $noServiceFile -Append

}

}

Remove-Job -State Completed

import-csv -Path ServiceStatus.csv
Advertisements

[AutoIT] Creating a Welcome document for new joiners.

The WelcomePack is an application written in AutoIT to generate a Word document with information of the current login user. The generated document will be saved under a folder with the current user’s display name.

WelcomePack.exe will search for $Date, $Username, $tel, $ext, $Email, $ComputerName, $NetworkDrives, $Printers and replace them with the information gathered.

The information includes with the source listed:

  • logon name – Windows session
  • direct line – AD
  • extension number – Shoretel
  • email address – AD
  • distribution list the user is a member of – AD
  • computer name – Windows session
  • mapped drive – Windows session
  • connected printers – Windows session

 

System requirements:

  • Word 2010 or later
  • The template file named “!Default Template.doc”
  • MySQL ODBC 5.3 Unicode Driver

 

*Shoretel DB credential  and server info removed

Minimal error handling has been implement into the code.

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****

#AutoIt3Wrapper_Compression=4

#AutoIt3Wrapper_UseX64=Y

#AutoIt3Wrapper_Res_Comment=Welcome Pack Executable

#AutoIt3Wrapper_Res_Description=WF Welcome Pack

#AutoIt3Wrapper_Res_Fileversion=1.0

#AutoIt3Wrapper_Res_LegalCopyright=Max Lee (argentolee@hotmail.com)

#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <Word.au3>

#include <Date.au3>

#include <MsgBoxConstants.au3>

 


;*****************************************

;WelcomePack.au3 by Max Lee

;Created with ISN AutoIt Studio v. 0.95 BETA

;*****************************************

 


; Create application object

Global $oWord = _Word_Create()

If @error <> 0 Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocFindReplace Example", _

        "Error creating a new Word application object." & @CRLF & "@error = " & @error & ", @extended = " & @extended)

; Open template document, read-only

Global $oDoc = _Word_DocOpen($oWord, @ScriptDir & "\!Default Template.doc", Default, Default, True)

If @error <> 0 Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocFindReplace Example", _

        "Error opening '!Default Template.doc'." & @CRLF & "@error = " & @error & ", @extended = " & @extended)

 


; *****************************************************************************

; Replacing variables in the Word document

; *****************************************************************************

_Word_DocFindReplace($oDoc, "$Date", _NowDate())

_Word_DocFindReplace($oDoc, "$Username", @UserName)

_Word_DocFindReplace($oDoc, "$ComputerName", @ComputerName)

_Word_DocFindReplace($oDoc, "$Email", GetMail())

_Word_DocFindReplace($oDoc, "$NetworkDrives", GetMappedDrives())

_Word_DocFindReplace($oDoc, "$Printers", GetMappedPrinters())

_Word_DocFindReplace($oDoc, "$tel", GetTel())

_Word_DocFindReplace($oDoc, "$DL", _GetDL())

_Word_DocFindReplace($oDoc, "$ext", _GetExt())

;_Word_DocFindReplace($oDoc, "$othertel", GetotherTelephone())

 


 


 


If @error <> 0 Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocFindReplace Example", _

        "Error replacing text in the document." & @CRLF & "@error = " & @error & ", @extended = " & @extended)

;MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocFindReplace Example", "Text successfully replaced.")

 


DirCreate(@ScriptDir & "\" & GetDisplayName())

_Word_DocSaveAs($oDoc, @ScriptDir & "\" & GetDisplayName() & "\" & GetDisplayName() & ".doc")

 


 


Func GetDisplayName()

    Local $objRootDSE, $strDomain, $objConnection, $objCommand, $objRecordSet, $strDN

    ;Const ADS_SCOPE_SUBTREE = 2

 


    

    $objRootDSE = ObjGet("LDAP://RootDSE")

    $strDomain = $objRootDSE.Get("DefaultNamingContext")

 


 


 


    ;Set ADO connection

    $objConnection = ObjCreate("ADODB.Connection")

    $objConnection.Provider = "ADsDSOObject"

    $objConnection.Open("Active Directory Provider")

 


    ;Set ADO command

    $objCommand = ObjCreate("ADODB.Command")

    $objCommand.ActiveConnection = $objConnection

    $objCommand.Properties("Searchscope") = 2

    $objCommand.CommandText = "SELECT distinguishedName FROM 'LDAP://" & $strDomain & "' WHERE objectCategory='user' AND samAccountName = '" & @UserName & "'"

 


    ;Set recordset to hold the query result

    $objRecordSet = $objCommand.Execute

 


    ;If a user was found - Retrieve the distinguishedName

    If Not $objRecordSet.EOF Then

        $strDN = $objRecordSet.Fields("distinguishedName").Value

 


        Dim $objUser = ObjGet("LDAP://" & $strDN)

 


        Return $objUser.displayName

    Else

        ;"Not found"

        Return

    EndIf

 


EndFunc   ;==>GetDisplayName

 


 


Func GetMail()

    Local $objRootDSE, $strDomain, $objConnection, $objCommand, $objRecordSet, $strDN

    ;Const ADS_SCOPE_SUBTREE = 2

 


    

    $objRootDSE = ObjGet("LDAP://RootDSE")

    $strDomain = $objRootDSE.Get("DefaultNamingContext")

 


 


 


    ;Set ADO connection

    $objConnection = ObjCreate("ADODB.Connection")

    $objConnection.Provider = "ADsDSOObject"

    $objConnection.Open("Active Directory Provider")

 


    ;Set ADO command

    $objCommand = ObjCreate("ADODB.Command")

    $objCommand.ActiveConnection = $objConnection

    $objCommand.Properties("Searchscope") = 2

    $objCommand.CommandText = "SELECT distinguishedName FROM 'LDAP://" & $strDomain & "' WHERE objectCategory='user' AND samAccountName = '" & @UserName & "'"

 


    ;Set recordset to hold the query result

    $objRecordSet = $objCommand.Execute

 


    ;If a user was found - Retrieve the distinguishedName

    If Not $objRecordSet.EOF Then

        $strDN = $objRecordSet.Fields("distinguishedName").Value

 


        Dim $objUser = ObjGet("LDAP://" & $strDN)

 


        Return $objUser.mail

    Else

        ;Msgbox(4096,"Title","Not found")

        Return

    EndIf

 


EndFunc   ;==>GetMail

 


Func GetMappedDrives()

 


    Local $strNetworkDrives

    Local $aArray = DriveGetDrive("NETWORK")

    If @error Then

        ; An error occurred when retrieving the drives.

        MsgBox($MB_SYSTEMMODAL, "", "It appears an error occurred.")

    Else

        For $i = 1 To $aArray[0]

            ; Show all the drives found and convert the drive letter to uppercase.

            ;MsgBox($MB_SYSTEMMODAL, "", "Drive " & $i & "/" & $aArray[0] & ":" & @CRLF & StringUpper($aArray[$i]) & "  " & DriveMapGet($aArray[$i]) &@CRLF )

            $strNetworkDrives = $strNetworkDrives & (@TAB & @TAB & @TAB & StringUpper($aArray[$i]) & "  " & DriveMapGet($aArray[$i]) & @CR)

        Next

 


        Return $strNetworkDrives

    EndIf

 


EndFunc   ;==>GetMappedDrives

 


 


Func GetMappedPrinters()

 


    $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2")

    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Printer")

    Local $strNetworkPrinters

 


    For $objItem In $colItems

 


        If StringLen($objItem.ShareName) > 3 Then

            $strNetworkPrinters = $strNetworkPrinters & @TAB & @TAB & @TAB & $objItem.ShareName & @CR

        Else

 


        EndIf

 


    Next

 


    Return $strNetworkPrinters

 


EndFunc   ;==>GetMappedPrinters

 


Func GetTel()

    Local $objRootDSE, $strDomain, $objConnection, $objCommand, $objRecordSet, $strDN

    ;Const ADS_SCOPE_SUBTREE = 2

 


    

    $objRootDSE = ObjGet("LDAP://RootDSE")

    $strDomain = $objRootDSE.Get("DefaultNamingContext")

 


 


 


    ;Set ADO connection

    $objConnection = ObjCreate("ADODB.Connection")

    $objConnection.Provider = "ADsDSOObject"

    $objConnection.Open("Active Directory Provider")

 


    ;Set ADO command

    $objCommand = ObjCreate("ADODB.Command")

    $objCommand.ActiveConnection = $objConnection

    $objCommand.Properties("Searchscope") = 2

    $objCommand.CommandText = "SELECT distinguishedName FROM 'LDAP://" & $strDomain & "' WHERE objectCategory='user' AND samAccountName = '" & @UserName & "'"

 


    ;Set recordset to hold the query result

    $objRecordSet = $objCommand.Execute

 


    ;If a user was found - Retrieve the telephoneNumber

    If Not $objRecordSet.EOF Then

        $strDN = $objRecordSet.Fields("distinguishedName").Value

 


        Dim $objUser = ObjGet("LDAP://" & $strDN)

 


        Return $objUser.telephoneNumber

    Else

        ;Not found

        Return

    EndIf

 


EndFunc   ;==>GetTel

Func _GetExt()

    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")

    Local $sUsername = 'username'

    Local $sPassword = 'password'

    Local $sDatabase = 'shoreware'

    Local $sServer = 'server'

    Local $sDriver = "{MySQL ODBC 5.3 Unicode Driver}"

    Local $iPort = 4308!Default Template

    Local $result

 


 


    $ObjConn = ObjCreate("ADODB.Connection")

    $ObjConn.ConnectionString = "DRIVER=" & $sDriver & ";SERVER=" & $sServer & ";DATABASE=" & $sDatabase & ";User=" & $sUsername & ";Password=" & $sPassword & ";PORT=" & $iPort

    If IsObj($ObjConn) Then

        $ObjConn.open()

    Else

        Exit

    EndIf

 


 


    $rsResult = $ObjConn.Execute("SELECT UserDN FROM users WHERE GuiLoginName='" & @UserName & "'")

    With $rsResult

        While Not .EOF

            

            ;MsgBox(0,'',.Fields("UserDN").Value)

            $result = .Fields("UserDN").Value

            .MoveNext

        WEnd

        .Close

    EndWith

    $ObjConn.Close

    ;MsgBox(0,'',$result)

    Return $result

    

EndFunc   ;==>_GetExt

 


 


 


 


 


Func _ErrFunc($oError)

    ; Do anything here.

    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _

            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _

            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _

            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _

            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _

            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _

            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _

            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _

            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _

            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)

EndFunc   ;==>_ErrFunc

 


 


Func _GetDL()

    

    Local $objUser, $objRootDSE, $objConnection, $objRecordSet, $objCommand

    Local $GroupCollection, $ObjGroup, $result

    Local $StrUserName, $StrDomName, $StrSQL

 


    $objRootDSE = ObjGet("LDAP://RootDSE")

    $StrDomName = $objRootDSE.Get("DefaultNamingContext")

 


 


    $StrUserName = @UserName

    $StrSQL = "Select ADsPath From 'LDAP://" & $StrDomName & "' Where ObjectCategory = 'User' AND SAMAccountName = '" & $StrUserName & "'"

 


    ;Set ADO connection

    $objConnection = ObjCreate("ADODB.Connection")

    $objConnection.Provider = "ADsDSOObject"

    $objConnection.Open("Active Directory Provider")

 


 


 


 


    ;Set ADO command

    $objCommand = ObjCreate("ADODB.Command")

    $objCommand.ActiveConnection = $objConnection

    $objCommand.Properties("Searchscope") = 2

    $objCommand.CommandText = $StrSQL

    ;Set recordset to hold the query result

    $objRecordSet = $objCommand.Execute

 


 


    If Not $objRecordSet.EOF Then

        $objRecordSet.MoveLast

        $objRecordSet.MoveFirst

        $objUser = ObjGet($objRecordSet.Fields("ADsPath").Value)

        $GroupCollection = $objUser.Groups

 


        For $ObjGroup In $GroupCollection

            If ($ObjGroup.GroupType = 2 Or $ObjGroup.GroupType = 4 Or $ObjGroup.GroupType = 8) Then

                $result = $result & @TAB & @TAB & @TAB & $ObjGroup.CN & @CR

            Else

                ;Do nothing

            EndIf

            

        Next

 


        $ObjGroup = Null ;

        $GroupCollection = Null ;

        $objUser = Null ;

 


        Return $result ;

    Else

 


    EndIf

    

EndFunc   ;==>_GetDL

 


 


 


Func GetotherTelephone()

    Local $objRootDSE, $strDomain, $objConnection, $objCommand, $objRecordSet, $strDN

    ;Const ADS_SCOPE_SUBTREE = 2

 


    

    $objRootDSE = ObjGet("LDAP://RootDSE")

    $strDomain = $objRootDSE.Get("DefaultNamingContext")

 


 


 


    ;Set ADO connection

    $objConnection = ObjCreate("ADODB.Connection")

    $objConnection.Provider = "ADsDSOObject"

    $objConnection.Open("Active Directory Provider")

 


    ;Set ADO command

    $objCommand = ObjCreate("ADODB.Command")

    $objCommand.ActiveConnection = $objConnection

    $objCommand.Properties("Searchscope") = 2

    $objCommand.CommandText = "SELECT distinguishedName FROM 'LDAP://" & $strDomain & "' WHERE objectCategory='user' AND samAccountName = '" & @UserName & "'"

 


    ;Set recordset to hold the query result

    $objRecordSet = $objCommand.Execute

 


    ;If a user was found - Retrieve the otherTelephone

    If Not $objRecordSet.EOF Then

        $strDN = $objRecordSet.Fields("distinguishedName").Value

 


        Dim $objUser = ObjGet("LDAP://" & $strDN)

 


        Return $objUser.otherTelephone

    Else

        ;"Not found"

        Return

    EndIf

 


EndFunc   ;==>GetotherTelephone

Default template attached:

[PowerShell] Retrieving hard disk health through SMART status

To get the SMART status of the hard disk with PowerShell, you could run the following:

Get-WmiObject win32_diskdrive|Select-Object Status

 

Below is a sample script to check multiple PC’s SMART status by getting a list of PC names from a text file.

$allComputers=Get-Content -Path C:\temp\pc.txt

foreach($computer in $allComputers)
{

$isonline=test-connection -Quiet -count 2 -ComputerName $computer
if($isonline)
{

$diskStatus= Get-WmiObject win32_diskdrive -ComputerName $computer|Select-Object -ExpandProperty Status

Write-Host -ForegroundColor Green "$computer is online and disk status is $diskStatus";
$diskStatus="";
}
else
{
Write-Host -ForegroundColor Red "$computer is offline";
}

}

[PowerShell] Retrieve temperature information for Nvidia display cards

Some Nvidia display cards has support for WMI such that you could retrieve the temperature information.

For more information, please check out NVIDIA Windows Management Instrumentation SDK

Below is the code for local computer, you can always change the $ComputerName variable to point to a remote computer. I had it probe for all instances of the ThermalProbe, you can comment that out and un-comment the last 3 lines for temperature only. The majority part of the code comes from Nvidia’s SDK examples, which you could download from the link above.

Please note, as I only have NVS cards, I had filled up $supportedModels with the NVS model I have.

$ComputerName="localhost"
$supportedModels= "NVIDIA NVS 290","NVIDIA NVS 295","NVIDIA NVS 300","NVIDIA NVS 310","NVIDIA NVS 315","NVIDIA NVS 420","NVIDIA NVS 450","NVIDIA NVS 510","NVIDIA Quadro NVS 450"


$video_card_name=(gwmi win32_videocontroller -ComputerName $ComputerName)|select-object -expand name
write-host $video_card_name

If($supportedModels|?{$video_card_name -match $_})
{

#Write-Host "True"
gwmi -ComputerName $ComputerName -Namespace root\CIMV2\NV gpu|select-object name,percent*


$namespace = "root\CIMV2\NV"
$classname = "ThermalProbe"
# For local system (e.g. "LocalHost", ".") '-computername $computer' could be omitted
# retrieve all instances of the ThermalProbe class and store them:
$probes =Get-WmiObject -class $classname -computername $ComputerName -namespace $namespace
# print all ThermalProbe instances
$probes
# iterate through all Probe instances
foreach( $probe in $probes )
{
#"Call the info() method and print all the data"
$res = $probe.InvokeMethod("info",$Null)
$res
#"Query just the temperature"
#$temp = $probe.temperature
#$temp
}
}

[AutoIT] Check free disk space for multiple drives.

Sometimes you may want to check for the free disk space for multiple drives, even multiple computers in your network. If you are a server guy or someone with domain admin rights, you may want something more robust such as Lansweeper, Spiceworks, Open-AudIT, Zabbix, Nagios, OCS Inventory NG or the like to do an inventory. What if you are just a desktop admin?

The traditional way is to map the drives and jot down the free space manually, but that would not work if you have a large numbers of drives to check. I wrote the following code to accomplish the task, all you have to do is create a text file with one drive letters/UNC path per line and drag and drop it to the executable (alternatively, you can pass the text file’s filename as a parameter to the executable). The result will be presented in a Excel table.

#include <Excel.au3>
If $CmdLine[0] < 1 Then
    MsgBox(0, "Error", "Please provide text file as parameter.")

    Exit
EndIf
$file = FileOpen($CmdLine[1], 0)

$lineNo = 1

If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

Local $oExcel = _ExcelBookNew() ;Create new book, make it visible
If @error Then
    MsgBox(0, "Error", "Unable to create Excel instance.")
    Exit
EndIf

;Writing the header
_ExcelWriteCell($oExcel, "Disk", 1, 1)
_ExcelWriteCell($oExcel, "Free Space", 1, 2)
_ExcelWriteCell($oExcel, "Total Space", 1, 3)

While 1
    $line = FileReadLine($file)
    If @error = -1 Then ExitLoop

    $lineNo = $lineNo + 1

    ;Write the disk name
    _ExcelWriteCell($oExcel, $line, $lineNo, 1)
    ;Write the disk free space
    _ExcelWriteCell($oExcel, (Round( (DriveSpaceFree($line)/1024 ),2) &" GB"), $lineNo, 2 )
    ;Write the total disk space
    _ExcelWriteCell($oExcel, (Round( (DriveSpaceTotal($line)/1024 ),2) &" GB"), $lineNo, 3 )

Wend

FileClose($file)

The compiled executable including source file and project file for ISN AutoIT Studio can be downloaded here.

Feel free to download drivespace.zip from the link above.

For simplicity, not much error checking had been implemented and the code is provided as is.

WMI Explorer for those who are interest in WMI programming

For those of you who are interest in WMI programming, tools like WMI code Creator and Scriptomatic can be useful. The command wbemtest might come in handy sometimes as well but I find that WMI Explorers are more useful when you would like to know what classes are avaiable and when you would like to run and see what results does the Query produces.

I find the following three WMI Explorer to be very useful:

Happy programming 🙂