Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I'm finally digging in and figuring out this PowerShell crap. I'm rewriting a VBscript in PS and so far things are going as expected. I ran into some weird behavior where this:

code:
$strMsg = `
				"Name: " + $objitem.Name `
				"Manufacturer: " + $objitem.Manufacturer `
				"Model: " + $objitem.Model `
				"Memory: " + [Math]::Round($objitem.TotalPhysicalMemory/1Gb, 2) + " Gb" `
				"Number of Processors: " + $objitem.NumberOfProcessors
When printed displayed like this:

Manufacturer: LENOVO
Model: 276712U
Memory: 3.9 Gb
Number of Processors: 1
Name: TACO-T400


With the name at the bottom instead of the top. I hopped on irc and asked for help and was told to use Format-List instead which works great. This is what I'm using instead:

code:
$objItem | Format-list Name, Manufacturer, Model, @{ Name = 'Memory'; Expression = { "{0:N2} Gb" -f ($_.TotalPhysicalMemory / 1GB)}}
Now this was written for me and it looks great, but how the dick do I store that in a variable? What I'm doing is building a function for each WMI Class so when I'm doing I can run the set of functions, store the list in a variable then print it to screen and write it to a text file for reference (I'm also generating a Spreadsheet but that's taken care of).

Ashex fucked around with this message at 00:29 on Sep 17, 2011

Adbot
ADBOT LOVES YOU

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I feel stupid, for some reason when I just tried doing that things sorta broke.

I actually tried using Here-Strings and I kept getting the following error (as I am now)

code:
The string starting:
At C:\Scripts\ComputerInfoScript.ps1:44 char:13
+         $strMsg =  <<<< @" 
is missing the terminator: "@.
At C:\Scripts\ComputerInfoScript.ps1:86 char:4
+ #    } <<<< 
    + CategoryInfo          : ParserError: (                Name:  $obj...ters)
#    {
#    }:String) [], ParseException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
This is what I'm using:

code:
		$strMsg = @" 
				Name:  $objitem.Name 
				Manufacturer:  $objitem.Manufacturer 
				Model:  $objitem.Model 
				Memory:  $([Math]::Round($objitem.TotalPhysicalMemory/1Gb, 2))
				Number of Processors:  $objitem.NumberOfProcessors
				"@
I actually built an Excel object so I can insert entries directly to an Excel workbook. One issue I'm having is there's a couple other functions that pull the Processor speed and disks via WMI, when there's multiple processors I get an extra line (i.e 2300 2300 2300 for 3 processors) and I'm not sure how to only pull the first line.
For the Disks I want to record each drive but from how I'm using the Excel it inserts each WMI Property into its own cell so only the last disk reported will be recorded (I need to figure out a way to just add columns when there is more then one line given back, I'm considering a for loop with that property).

Ashex fucked around with this message at 18:19 on Sep 19, 2011

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
Alright, I tried just copying your bit straight over and it's still breaking on me, Here's the full function:



Am I missing something?
Apparently I can't even tab indent "@ at the end. Removed all the tabs and it worked.



Edit: Going back to using format-list, I remembered why I was having issues storing it in a variable, when I try doing as you suggested before this happens when I try to print the variable with write-Host:


code:
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

Ashex fucked around with this message at 20:53 on Sep 19, 2011

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
Thanks for pointing that out for me, I don't see an easy way to append data to that without piping the gently caress out of it so I'm going to stick with Here-Strings (mainly because I'm more or less done with the script).

I've got one last question (thanks for hanging around to help me), how exactly does one do error handling? I've searched around on the web and there are a few different methods but none of them seem particularly clear.

Now that I've built all the functions, I'm going to stick it in a for loop. I'm under the assumption I'll use something like Catch to check for an error, do I have to write a Catch for each type of error if I want to know what went wrong?

This is the loop I'm talking about :

code:
foreach ($strComputer in $arrComputers)
			{
		$global:strMsg=""
		SysInfo
		ProcInfo
		NicInfo
		DiskInfo
		Write-Host $global:strMsg
		$intRow = $intRow + 1
			}

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
Got it, I'm going to add some Catches for WMI. Is there an easy way to find what errors it can throw?

I mostly want to write a catch for access denied (done), unable to connect, and other weird WMI errors that may occur.

Edit: Looks like I've got it all, I want to catch a couple WMI errors like GetWMIManagementException and GetWMICOMException but they're not actual Exceptions :(

Ashex fucked around with this message at 21:57 on Sep 20, 2011

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
Thanks for looking around, error handling with WMI is a bitch. I couldn't find a good way to handle connection failures so I'm using Test-Connection to make sure each computer is online before it runs a report.

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I've run into a slight problem with an incrementing variable that I can't control, basically I have a function that retrieves the disk drives on a computer and enters it into a spreadsheet. The problem is I'm using an excel function that writes one cell at a time so to adjust for multiple drives I have it insert a row to add a new drive, because of this I end up with a blank row at the end if there's only one disk drive.

This is the function:

code:
Function DiskInfo {

	$colitems = Get-WmiObject -Namespace "root\CIMV2" `
	-ComputerName $strComputer -Query "select * from Win32_LogicalDisk where DriveType='3'"
	foreach ($objitem in $colitems) {
		$global:strMsg += @"
			
	Drive:  $($objitem.Name.ToSTring())
	Size: $([Math]::Round($($objitem.Size)/1Gb, 2)) GB
	Free: $([Math]::Round($($objitem.FreeSpace)/1Gb, 2)) GB

"@			

		$Sheet.Cells.Item($global:intRow,8) = $objitem.Name
		$Sheet.Cells.Item($global:intRow,9) = $([Math]::Round($($objitem.Size)/1Gb, 2))
		$Sheet.Cells.Item($global:intRow,10) = $([Math]::Round($($objitem.FreeSpace)/1Gb, 2))
		$global:intRow++
		}
		
	
}
I've tried using a simple conditional counter like if ($i -gt 0) {$introw++} else {$i++} but that didn't work. I added a check at the end of the script to look for empty rows and delete them which is working but it seems rather messy.

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I see you have run into the same problem I was having! I wanted to be able to catch the RPC error message but couldn't find a way to do it, I eventually caved and wrote a General Catch that actually explained to the user what to do if they got X error from WMI. I found this article to be somewhat helpful though.

As for using $colitems.count, For some reason I don't get anything back:

code:
PS C:\Users\ashex> $colitems = Get-WmiObject -Namespace "root\CIMV2" -Query "select * from Win32_LogicalDisk where Driv
eType='3'"
PS C:\Users\ashex>
PS C:\Users\ashex> $colitems.count
PS C:\Users\ashex> Write-Host $colitems.count

PS C:\Users\ashex>

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I'm running it on my laptop, if I do $colitems.name I get my C: drive. $colitems|gm spits out all the properties available.


Edit: This is interesting, I ran it against a server 2008 box and I do get a number back.

Edit Edit: Okay this is interesting, if I use a computer with more then one drive:

code:
PS C:\Users\ashex> $colitems.count
2
PS C:\Users\ashex> if ($colitems.count = $null) {Write-host "Nothing"}
"Length" is a ReadOnly property.
At line:1 char:15
+ if ($colitems. <<<< count = $null) {Write-host "Nothing"}
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

PS C:\Users\ashex> if ($colitems.count) {Write-host "Nothing"}
Nothing
PS C:\Users\ashex>
If I run it against a computer with only one drive:

code:
PS C:\Users\ashex> $colitems.count
PS C:\Users\ashex> 
PS C:\Users\ashex> if ($colitems.count) {Write-host "Nothing"}
PS C:\Users\ashex>
So it looks like I can just check if $colitems.count exists, if it is true I'll add a row.

Edit: Nope, I tried using if ($colitems.count) {$global:intRow++} with no success.

Ashex fucked around with this message at 00:18 on Sep 23, 2011

Ashex
Jun 25, 2007

These pipes are cleeeean!!!

Phone posted:

Did you submit your issue to Hey, Scripting Guy!? If not... uh... :tinfoil:

That said, I'm totally stealing the hell out this so I can audit the PCs at my work easily.

I'll give you the complete script :P Just send me a pm.

Edit: I sent an email to him, I'll see what I get.

Ashex fucked around with this message at 17:56 on Sep 26, 2011

Adbot
ADBOT LOVES YOU

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
I tried what you suggested and when I tested it out it looked like it would work but when I used it in the script it didn't increment the row for the computer with one drive :(

code:
$intDisk = 0
		$colitems | %{$intDisk++}
		if($intDisk -ne 1) {$global:intRow++}

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply