######################################################### # Script Name: PS_Remote_WMI_Installed_Applications.ps1 # Version: 1.0 # Description: Using WMI Remotely Queries # Systems for Installed Software ######################################################### #Array for Reporting Installed Software $installedApps = @(); #Array for Registry Paths to Installed Apps $appRegPaths = @("Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "Software\Microsoft\Windows\CurrentVersion\Uninstall"); #Array of System Names to Run Against $computers = @("SERVER01","SERVER02","SERVER03"); foreach($computer in $computers) { #Ping System First if(Test-Connection -ComputerName $computer -Quiet) { #Connect to WMI Registry Class $uReg = [wmiclass]"\\$computer\root\default:StdRegProv"; foreach($regPath in $appRegPaths) { #Pull the Application Registry Keys $iAppKeys = $uReg.EnumKey(2147483650,$regPath); #Null Check on Application Registry Keys if($iAppKeys) { #Loop Through Each Application Key foreach($appKey in $iAppKeys.sNames) { #Construct Key Path $keyPath = $regPath + "\" + $appKey.ToString(); #Pull the Key DisplayName String Value $keyDisplayName = $uReg.GetStringValue(2147483650,$keyPath,"DisplayName"); if(![string]::IsNullOrEmpty($keyDisplayName.sValue)) { #Local Vars Used for Reporting [string]$displayName = $keyDisplayName.sValue.ToString(); [string]$displayVersion = ""; #Pull the Key DisplayVersion String Value $keyDisplayVersion = $uReg.GetStringValue(2147483650,$keyPath,"DisplayVersion"); if(![string]::IsNullOrEmpty($keyDisplayVersion.sValue)) { $displayVersion = $keyDisplayVersion.sValue.ToString(); } #Create Custom PSObject and Add to Reporting Array $app = New-Object PSObject; $app | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computer; $app | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $displayName; $app | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $displayVersion; $installedApps += $app; }#End of Null\Empty Check on DisplayName String Value }#End of Foreach $iAppKeys }#End of Null Check on $iAppKeys }#End of Foreach Reg Path }#End of Test-Connection }#End of Foreach Computer $installedApps | Sort-Object ComputerName,DisplayName | Format-Table -AutoSize;
Wednesday, September 5, 2012
PowerShell: WMI to Report Installed Applications on Remote Systems
Recently, I've been working with more PowerShell Remoting. Earlier this week I wrote a script that queries a list of systems for installed applications using Remoting. Tomorrow, I'm demo'ing that script (which I will post after this one) and needed to show how you would do it using just WMI in PowerShell. Since the listing of installed applications is stored in the Registery it took a good amount of time trying to figure out how to access a remote registry via PowerShell just using WMI. Below is the comparison script. Enjoy.
Labels:
Installed Applications,
PowerShell,
Remote Registry,
WMI
Friday, August 10, 2012
PowerShell: WMI Basics
During my lunch hour today, I showed a few colleagues how to use of PowerShell with WMI. We mainly covered the Get-WMIObject command and a lot of fun things you can do with it. Below are the examples we went over. Enjoy.
############################################################ # WMI PowerShell Commands ############################################################ #Use -ComputerName Option with Hostname, FQDN, or IP Address in Command for Remote Systems #For Example to Get the BIOS Settings On a System Called DeanTestServer Get-WmiObject -Query "SELECT * FROM Win32_BIOS" -ComputerName "DeanTestServer" #Or Use the IP Address Get-WmiObject -Query "SELECT * FROM Win32_BIOS" -ComputerName "192.168.2.25" #Get-WMIObject Can Use A WOL Query, Filter, or PowerShell Where Statement to Limit Results #For Example the Following Three Commands Have the Same Result Get-WmiObject -Class Win32_Share | Where-Object { $_.Name -eq "C$" } Get-WmiObject -Class Win32_Share -Filter "Name='C$'" Get-WmiObject -Query "SELECT * FROM Win32_Share WHERE Name='C$'" #Get All Win_32 Classes in the CIMV2 Namespace Get-WmiObject -Namespace "root\cimv2" -List | Where-Object { $_.Name -like "Win32_*" } | Select-Object Name | Sort-Object Name | Out-File WMI_CIMV2_Classes.txt #Get All Properties and Methods for the WMI Class Get-WmiObject Win32_Volume | Get-Member #Get Basic System Information Get-WmiObject -Query "SELECT * FROM Win32_ComputerSystem" #Get Local Accounts and Groups on a System Get-WmiObject -Query "SELECT * FROM Win32_Account" | Select-Object Name,SID | Sort-Object Name #Get Disk Information (Model and Size) Get-WmiObject -Query "SELECT * FROM Win32_DiskDrive" #Get Processor Information Get-WmiObject -Query "SELECT * FROM Win32_Processor" | Select-Object Name,Description,NumberOfCores | Sort-Object Name #Get Operating System Info Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem" #Get MAC Addresses of All Network Adapters Get-WmiObject -Query "SELECT * FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL" | Select-Object Name,MACAddress | Sort-Object Name; #Get All Assigned IPs Get-WmiObject -Query "SELECT * FROM Win32_NetworkAdapterConfiguration" | Where-Object { $_.IPAddress -ne $null} | Select-Object Description,IPAddress; #List Number of Memory Slots on a System Write-Output ("Number of Memory Slots: " + (Get-WmiObject -Query "SELECT * FROM win32_PhysicalMemoryArray").MemoryDevices); #Retrieve Memory Slot Allocations Get-WMIObject -Query "SELECT * FROM Win32_PhysicalMemory" | ForEach-Object { Write-Output ($_.DeviceLocator.ToString() + " " + ($_.Capacity/1GB) + "GB") }; #Retrieve Disk Volume Sizes (Including Mount Points, Excluding Pass Through Drives) $sysVolumes = Get-WmiObject –Query "Select * FROM Win32_Volume WHERE DriveType=3 AND NOT Name LIKE '%?%'" | Sort-Object Name; foreach($sv in $sysVolumes) { #Var for Volume Size $vSize = "{0:N2}" -f ($sv.Capacity/1GB); #Var for Free Space $vFS = "{0:N2}" -f ($sv.FreeSpace/1GB); #Var for Percentage Free Space $vPF = "{0:N2}" -f (($sv.FreeSpace/$sv.Capacity)*100); #Var for Drive Letter $vLetter = $sv.Name.ToString().TrimEnd("\"); $VolumeStatus = "$vLetter | Size(GB): $vSize | Free Space(GB): $vFS | Percentage Free: $vPF"; Write-Output $VolumeStatus; }
Friday, July 20, 2012
PowerShell: Server Drive Space Report
Below is the PowerShell script code that generates an email report of drive space sizes on servers listed in an array.
#Error Handling $erroractionpreference = "SilentlyContinue"; #Function for Email Notices function uEmailNotice([string]$msgBody,[string]$msgSubject) { #Variable for Email FROM Address $mFrom = "fromAddress@mycollege.edu"; #Variable for EMail TO Address $mTo = "toAddress@mycollege.edu"; #Variable for SMTP Server $smtp = "smtpServer.mycollege.edu"; #Settings for Email Message $messageParameters = @{ Subject = $msgSubject Body = $msgBody From = $mFrom To = $mTo SmtpServer = $smtp }; #Send Report Email Message Send-MailMessage @messageParameters –BodyAsHtml; } #Var for Disk Percentage to Check $percentCheck = 12; #Array for Server Names $Servers = @( "server1.mycollege.edu", "server2.mycollege.edu", "server3.mycollege.edu", "server4.mycollege.edu" ); #Array for Systems with Low Free Disk Percentages $arLFDP = @(); #Var for HTML Message Body $msgBody = "<html> <body> <h3>Servers Disk Space Report</h3>"; #Var for HTML All Server Table Info $sTableInfo = "<table border=""0"" cellpadding=""5"" cellspacing=""2"" style=""font-size:8pt;font-family:Arial,sans-serif""> <tr bgcolor=""#000099""> <td><strong><font color=""#ffffff"">Server</font></strong></td> <td><strong><font color=""#ffffff"">Drive</font></strong></td> <td><strong><font color=""#ffffff"">Size (GBs)</font></strong></td> <td><strong><font color=""#ffffff"">Free Space (GBs)</font></strong></td> <td><strong><font color=""#ffffff"">% Free</font></strong></td> </tr>"; #Loop Through All Servers foreach($server in $Servers) { #Pull Server Name from FQDN $sName = ($server.ToString().Split("."))[0].ToString().ToUpper(); #Compose Table Row for Server Name $sTableInfo += "<tr bgcolor=""#dddddd"" cellspacing=""0""> <td>$sName</td> <td colspan=""4""></td> </tr>"; #Ping Computer Before Attempting Remote WMI if(test-connection -computername $server -quiet) { #Make WMI Call to Remote Server $sysDrives = Get-WmiObject –Query "Select * FROM Win32_LogicalDisk WHERE DriveType=3" -ComputerName $server; #Null Check on $sysDrives if($sysDrives) { #Loop Through Each Logical Disk on Server foreach($drive in $sysDrives) { #Var for Percentage Free Space $dPF = "{0:N2}" -f (($drive.FreeSpace / $drive.Size) * 100); #Var for Free Space $dFS = "{0:N2}" -f ($drive.FreeSpace / 1GB); #Var for Disk Size $dSize = "{0:N2}" -f ($drive.Size / 1GB); #Var for Drive Letter $dLetter = $drive.DeviceID.ToString(); #Double for Percentage Free Comparison $freePercent = [double]$dPF.ToString(); #Check to See If Drive Percentage Free Is Greater Than or Equal to Set Alert Amount if($freePercent -ge $percentCheck) { #Add Disk Info $sTableInfo += "<tr> <td></td> <td>$dLetter</td> <td>$dSize</td> <td>$dFS</td> <td>$dPF</td> </tr>"; } else { #Add Disk Info with Alert Formatting $sTableInfo += "<tr> <td></td> <td><font color=""#ff0000"">$dLetter</font></td> <td><font color=""#ff0000"">$dSize</font></td> <td><font color=""#ff0000"">$dFS</font></td> <td><font color=""#ff0000"">$dPF</font></td> </tr>"; #Create PS Object for Low Disk Space Alert $uEntry = new-Object PSObject; $uEntry | add-Member -memberType noteProperty -name "Server" -Value $sName.ToString().ToUpper(); $uEntry | add-Member -memberType noteProperty -name "Drive" -Value $dLetter.ToString(); $uEntry | add-Member -memberType noteProperty -name "Percentage" -Value $dPF.ToString(); #Add Entry to Summary Array $arLFDP += $uEntry; }#End of Percentage Free Check }#End of Foreach Drive } else { #RPC Not Avaialable $sTableInfo += "<tr> <td></td> <td colspan=""4""><font color=""#ff0000"">RPC Not Available</font></td> </tr>"; }#End of $sysDrives Null Check } else { #Server Not Pingable $sTableInfo += "<tr> <td></td> <td colspan=""4""><font color=""#ff0000"">Ping Failed</font></td> </tr>"; }#End of Ping Test #Add Blank Line After Server Info Placed (Readability) $sTableInfo += "<tr> <td colspan=""5""></td> </tr>"; } #Write Alerts to HTML Message Body If Any if($arLFDP.Count -gt 0) { $msgBody += "<strong>Servers with Drives Less than $percentCheck% Free</strong><br /> <table border=""0"" cellpadding=""5"" cellspacing=""2"" style=""font-size:8pt;font-family:Arial,sans-serif""> <tr bgcolor=""#ff0000""> <td><strong><font color=""#ffffff"">Server</font></strong></td> <td><strong><font color=""#ffffff"">Drive</font></strong></td> <td><strong><font color=""#ffffff"">% Free</font></strong></td> </tr>"; foreach($alert in $arLFDP) { $msgBody += "<tr><td>" + $alert.Server.ToString() + "</td><td>" + $alert.Drive.ToString() + "</td><td>" + $alert.Percentage.ToString() + "</td></tr>"; } $msgBody += "</table> <br />"; } #Title All Servers Table $msgBody += "<strong>All Servers</strong><br />"; #Add Servers Table Info to Message Body $msgBody += $sTableInfo; #Close HTML Table and Message $msgBody += "</table> </body> </html>"; #Get Current Short Date $rptDate = Get-Date -Format d; #Format Message Subject $msgSubject = "Servers Disk Space Report for " + $rptDate; #Email Report uEmailNotice $msgBody $msgSubject;
PowerShell: Useful Commands for Beginners
During lunch today I presented the first installment of a "Beginning PowerShell" series for colleagues at my work. We covered setting up the console and command syntax. Below are some of the commands we used during the session.
#Get Version of PowerShell Running on System $PSVersionTable #Start a Transcript File Start-Transcript C:\Users\userID\desktop\MyTranscript.txt #Or for the File to be Placed in the Current Directory Start-Transcript "MyTranscript.txt" #Or for the Default Location (..\Do C:\Users\userID\Documents\PowerShell_transcript.NNNNN.txt Start-Transcript #To Stop the Transcript from Recording Commands and Output Stop-Transcript #Set the Script Execution Policy for Current User Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #Get All Currently Loaded PowerShell Snapins Get-PSSnapin #Get All Commands in a Specific PowerShell Snapin Get-Command -pssnapin NameOfPSSnapin #(e.g. Microsoft.PowerShell.Security) #Get All PowerShell Modules Available on System Get-Module -ListAvailable #Import Module in Current PowerShell Session Import-Module NameOfModule #(e.g. ActiveDirectory) #Get All Commands in a Module (Should Only Be Used After Importing) Get-Command -Module NameOfModule #Get All Currently Loaded Cmdlets Get-Command -CommandType Cmdlet #Online Help for a Cmdlet Get-Help NameOfCmdlet -Online #Find .NET Object Used in Cmdlet NameOfCmdlet | Get-Member
Saturday, July 7, 2012
PowerShell: SQL Stored Procedure that Requires a Parameter
Below is a PowerShell code example of how to use a stored procedure (that requires a parameter) on a remote SQL Server. Additionally, I'm using Yes\No prompt (found the code example here)
#Var for SQL Server FQDN [string]$SQLServerFQDN = "MySQLServer.mycollege.edu"; #Var for SQL Instance Name [string]$SQLInstance = "MyInstanceName"; #Var for SQL Database [string]$SQLDatabase = "MyDatabaseName"; #Var for Insert Stored Procedure Name [string]$spInsertServer = "Insert_New_Test_Server"; #Connection String Settings (Using Integrated Security So No UserID and Password Needed) [string]$sqlConString = "Server=$SQLServerFQDN\$SQLInstance;Database=$SQLDatabase;Integrated Security=SSPI;"; #Load .NET System.Data DLL [Void][system.reflection.assembly]::LoadWithPartialName("System.Data"); #Read In the New Server Name [string]$newServer = Read-Host "Enter New Server's FQDN"; #Check to See If the Name is Null or Empty if(![string]::IsNullOrEmpty($newServer)) { #Compose Message for Choice Prompt [string]$message = "Is " + $newServer + " the Correct FQDN?"; #Prompt Choices and Options $yes = New-Object System.Management.Automation.Host.ChoiceDescription("&Yes"); $no = New-Object System.Management.Automation.Host.ChoiceDescription("&No"); $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no); #Create Choice Prompt and Assign Reponse Value (Default Set for No) $choice = $host.ui.PromptForChoice("New Server", $message, $options, 1); #Check to See If User Chose Yes (0=Yes,1=No) if($choice -eq 0) { #Create a SQL Connection Object $sqlCon = New-Object System.Data.SqlClient.SqlConnection($sqlConString); #Create and Configure a SQL Command $sqlCommSI = New-Object System.Data.SqlClient.SqlCommand($spInsertServer,$sqlCon); #Set the Command Type as a Stored Procedure $sqlCommSI.CommandType = [System.Data.CommandType]::StoredProcedure; #Add Required Parameters (In This Case Just the Server Name) [Void]$sqlCommSI.Parameters.Add("@serverName", [System.Data.SqlDbType]::NVarChar); $sqlCommSI.Parameters["@serverName"].Value = $newServer.ToUpper(); #Open the SQL Connection $sqlCon.Open(); #Execute Insert Stored Procedure $cmdStatus = $sqlCommSI.ExecuteNonQuery(); #Close the SQL Connection $sqlCon.Close(); #Check to See If Command Successfully Completed if($cmdStatus -eq 1) { Write-Output "Command Completed Successfully"; } else { Write-Output "No Go At This Station"; } } else { Write-Output "Please Start Script Over"; }#End of Choice Check } else { Write-Output "Nothing Entered. Please Start Script Over"; }#End of New Server Name Null or Empty Check
PowerShell: Query Remote SQL Server Data Using Stored Procedure
Found a while back a cool blog entry on "Database Access within PowerShell". Using that as a reference, I started configuring a few scripts to utilize stored procedures when accessing SQL Server data. Below is a quick example. Enjoy.
#Var for SQL Server FQDN $SQLServerFQDN = "MySQLServer.mycollege.edu"; #Var for SQL Instance Name $SQLInstance = "MyInstance"; #Var for SQL Database $SQLDatabase = "MyDatabase"; #Create Empty Array for Storing Server Names $servers = @(); #Load .NET System.Data DLL [Void][system.reflection.assembly]::LoadWithPartialName("System.Data"); #Connection String Settings (Using Integrated Security So No UserID and Password Needed) $sqlConString = "Server=$SQLServerFQDN\$SQLInstance;Database=$SQLDatabase;Integrated Security=SSPI;"; #Stored Procedure Name for Servers Select Statement $spSelectServers = "Get_All_Servers"; #Create a SQL Connection Object $sqlCon = New-Object System.Data.SqlClient.SqlConnection($sqlConString); #Create and Configure a SQL Command $sqlCommSR = New-Object System.Data.SqlClient.SqlCommand($spSelectServers,$sqlCon); #Set the Command Type as a Stored Procedure $sqlCommSR.CommandType = [System.Data.CommandType]::StoredProcedure; #Open the SQL Connection $sqlCon.Open(); #Execute the Command $sqlRdrSR = $sqlCommSR.ExecuteReader(); #Read Through the Returned Data #This Specific Stored Procedure Returns a "Server_Name" Column while ($sqlRdrSR.Read()) { $servers += $sqlRdrSR["Server_Name"].ToString().Trim(); } ##Close the SQL Reader and Connection $sqlRdrSR.close(); $sqlCon.close(); #Loop Through Array and Output Server Name foreach($server in $servers) { Write-Output $server; }
Wednesday, April 25, 2012
C# and PowerShell EHLO Response
Earlier today, one of my colleagues put down a challenge to create in .NET and PowerShell a way detect if a remote email server was running Exchange via a EHLO response. Below are the code examples that completed the task.
C# (Console Application)
//Var for TCP Port
Int32 port = 25;
//Byte Array for Response Data
Byte[] rData = new Byte[256];
//Var for Converted Response Data
string responseData = string.Empty;
//Create a TcpClient
TcpClient client = new TcpClient("smtp.dept.mycollege.edu", port);
//Byte Array for Message to Be Sent
Byte[] data = System.Text.Encoding.ASCII.GetBytes("EHLO");
//Initate a Stream
NetworkStream stream = client.GetStream();
//Send Message to Server
stream.Write(data, 0, data.Length);
//Initiate Int for Return Bytes and Read Response of Stream
Int32 bytes = stream.Read(rData, 0, rData.Length);
//Convert Response
responseData = System.Text.Encoding.ASCII.GetString(rData, 0, bytes);
//Write Out Response
Console.WriteLine(responseData);
//Close Stream and Client
stream.Close();
client.Close();
PowerShell
#Var for TCP Port
[int]$port = 25;
#Byte Array for Response Data
$rData = New-Object Byte[](256);
#Var for Converted Response Data
$responseData = "";
#Create a TcpClient
$tClient = New-Object System.Net.Sockets.TcpClient("smtp.dept.mycollege.edu",$port);
#ASCII Encoder
$encode = [System.Text.Encoding]::ASCII
#Byte Array for Message to Be Sent
[Byte[]]$sData = $encode.GetBytes("EHLO");
#Initiate a Stream
$stream = $tClient.GetStream();
#Send Message to Server
$stream.Write($sData,0,$sData.Length);
#Initiate Int for Return Bytes and Read Response of Stream
[int]$bytes = $stream.Read($rData,0,$rData.Length);
#Convert Response
$responseData = $encode.GetString($rData,0,$bytes);
#Notify User
Write-Host $responseData;
#Close Stream and Client
$stream.Close();
$tClient.Close();
C# (Console Application)
//Var for TCP Port
Int32 port = 25;
//Byte Array for Response Data
Byte[] rData = new Byte[256];
//Var for Converted Response Data
string responseData = string.Empty;
//Create a TcpClient
TcpClient client = new TcpClient("smtp.dept.mycollege.edu", port);
//Byte Array for Message to Be Sent
Byte[] data = System.Text.Encoding.ASCII.GetBytes("EHLO");
//Initate a Stream
NetworkStream stream = client.GetStream();
//Send Message to Server
stream.Write(data, 0, data.Length);
//Initiate Int for Return Bytes and Read Response of Stream
Int32 bytes = stream.Read(rData, 0, rData.Length);
//Convert Response
responseData = System.Text.Encoding.ASCII.GetString(rData, 0, bytes);
//Write Out Response
Console.WriteLine(responseData);
//Close Stream and Client
stream.Close();
client.Close();
PowerShell
#Var for TCP Port
[int]$port = 25;
#Byte Array for Response Data
$rData = New-Object Byte[](256);
#Var for Converted Response Data
$responseData = "";
#Create a TcpClient
$tClient = New-Object System.Net.Sockets.TcpClient("smtp.dept.mycollege.edu",$port);
#ASCII Encoder
$encode = [System.Text.Encoding]::ASCII
#Byte Array for Message to Be Sent
[Byte[]]$sData = $encode.GetBytes("EHLO");
#Initiate a Stream
$stream = $tClient.GetStream();
#Send Message to Server
$stream.Write($sData,0,$sData.Length);
#Initiate Int for Return Bytes and Read Response of Stream
[int]$bytes = $stream.Read($rData,0,$rData.Length);
#Convert Response
$responseData = $encode.GetString($rData,0,$bytes);
#Notify User
Write-Host $responseData;
#Close Stream and Client
$stream.Close();
$tClient.Close();
Subscribe to:
Posts (Atom)