Formatting my date time - powershell

When I run the following code it outputs the information I want, but im having trouble with the final out put. It shows my UpTime as days,hours,minutes,seconds. I would just like Days and hours. And I would like to move the Uptime to display last on my list. The out put right now is Uptime, Computer, LastBootupTime.
Function Get-UpTime
{ Param ([string[]]$servers)
Foreach ($s in $servers)
{
$os = Get-WmiObject -class win32_OperatingSystem -cn $s -ErrorAction SilentlyContinue
New-Object psobject -Property #{computer=$s;
LastBootUpTime = [Management.ManagementDateTimeConverter]::ToDateTime( (Get-WmiObject - Class Win32_OperatingSystem -Computer $s | Select -Exp LastBootUpTime) )
UpTime = (Get-Date) – [System.Management.ManagementDateTimeconverter]::ToDateTime((Get-WmiObject - Class Win32_OperatingSystem -Computer $s | Select -Exp LastBootUpTime))
}
}}
Get-UpTime -servers $servers|
ConvertTo-Html -As Table -body "
<h1>Server Uptime Report</h1>
The following report was run on $(get-date)" >> $path
Invoke-Item $path

Next code snippet gives desired output: shows UpTime as days.hours:minutes last on the list; moreover, displays all tested servers (shows N/A in place of LastBootUpTime and UpTime if an RPC server is unavailable).
Function Get-UpTime
{ Param ([string[]]$servers)
Foreach ($s in $servers) {
Try
{ $os = Get-WmiObject -class win32_OperatingSystem -cn $s
$ST = [System.Management.ManagementDateTimeconverter]::
ToDateTime(($os | Select -Exp LastBootUpTime))
$UT = (Get-Date) – $ST # Days.Hours:Minutes:Seconds.MillisecondsFraction
# e.g. 114.12:32:42.6025504
New-Object psobject -Property #{
Computer = $s
#UpTime = $UT.ToString().Substring(0, $UT.ToString().Length - 11)
UpTime = '' + $UT.Days + '.' + $UT.Hours + ':' + $UT.Minutes
LastBootUpTime = $ST
}
}
Catch
{ New-Object psobject -Property #{
Computer = $s
UpTime = "N/A"
LastBootUpTime = "N/A"
}
}
}
}
Get-UpTime -servers $servers |
ConvertTo-Html -As Table -Property Computer, LastBootUpTime, UpTime -body "
<h1>Server Uptime Report</h1>
The following report was run on $(get-date)" >> $path
Invoke-Item $path

Related

Powershell, I do input a list gather data and output that whole list into one CSV

I am creating a script that reads a list of computer names and collects data from security event logs about who is on the computer, how long they have been on for, and how long it has been since the computer has restarted. I have it working except that it does not output all the data into one CSV. I just receive one CSV file with one computer name.
function Get-KioskInfo {
param (
[parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True,Position=0)]
[Alias('PSComputerName','DNSHostName','CN','Hostname')]
[string]
$ComputerName = $env:COMPUTERNAME
)
#PARAM
$User = try {(Get-WmiObject -ComputerName $ComputerName Win32_ComputerSystem | Select-Object -ExpandProperty username).trimstart("NG\")} catch {Write-Output "User not detected";break}
$BootStart = ((get-date) - (Get-CimInstance win32_operatingsystem -ComputerName $ComputerName).LastBootUpTime).Days
#These variables are for the DATE & Time calculation
If ($user -NE $null)
{ Write-Verbose 1
# Do something
$Date1 = Get-date
Write-Verbose 2
$SP = Get-WinEvent -ComputerName $ComputerName -FilterHashTable #{LogName = "Security";ID="5379";Data=$User; StartTime=((Get-Date).AddDays(-1))}
Write-Verbose 3
$Date2 =($SP | select -first 1).timecreated
Write-Verbose 4
$USERLOGTIME = ($Date1-$Date2).hours.tostring("N2")
Write-Verbose 5
}
else{Write-Output "No user";break}
Write-Verbose 6
#Rename-Computer -ComputerName "Srv01" -NewName "Server001" -DomainCredential Domain01\Admin01 -Force ------ Rename script for computers if it is needed.
#$computers = Get-Content C:\Users\jaycbee\Desktop\kiosknames.txt ------ To load kiosk list
#foreach ($c in $computers) {start-job -Name $c -ScriptBlock ${Function:get-kioskinfo} -ArgumentList $c} for learning how to do a foreach script
Write "Computer Name: $Computername"
Write "---USER---"
Write "Name: $User"
Write "Log in Time $USERLOGTIME"
Write "Boot start $BootStart days ago"
$ComputerName | ForEach-Object {
if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)
{
Invoke-Command -ComputerName $ComputerName {
}
} # Offline Check
else
{
Write-Host "Computer is Unreachable or Offline" -ForegroundColor Gray
}
} # Foreach
$Continue = Read-Host "WARNING! This will READ LIST of computers in \\ou\ouor-groups\Desktop_Support\SD\Kiosks\kiosknames.txt Type CONTINUE to proceed."
if ($Continue -eq "CONTINUE")
{
$Computers = Get-Content '\\ou\ouor-groups\Desktop Support\SD\Kiosks\kiosknames.txt'
foreach ($C in $Computers) {start-job -Name $c -ScriptBlock ${Function:get-kioskinfo} -ArgumentList $c
}
}
[pscustomobject]#{ Name = $ComputerName ; User = $User ; "User Log in time in hours" = $USERLOGTIME;"BootStart days ago" = $BootStart} | export-csv -path "\\ou\ouor-groups\Desktop Support\SD\Kiosks\test45$ComputerName.csv" -Append
} #Function
#For each-computer | do this at this location,
Continuing from my comment. I too wonder why the use of jobs for this use case. Unless you are doing this on hundreds of computers, thus needing parallel processing.
This refactor/formatting is just my way of making sense of what you posted. I'm old, and crowded code just really hurts my eyes. ;-} Yet, code the way you like of course. ;-}
I do not have an environment to test this, but give it a shot.
function Get-KioskInfo
{
param
(
[parameter(ValueFromPipeline = $True,ValueFromPipelineByPropertyName = $True,Position = 0)]
[Alias(
'PSComputerName',
'DNSHostName',
'CN',
'Hostname'
)]
[string]
$ComputerName = $env:COMPUTERNAME
)
($User = try
{
(Get-WmiObject -ComputerName $ComputerName Win32_ComputerSystem |
Select-Object -ExpandProperty username).trimstart("NG\")
}
catch
{
'User not detected'
break
}
)
($BootStart = ((get-date) - (Get-CimInstance win32_operatingsystem -ComputerName $ComputerName).LastBootUpTime).Days)
If ($user -NE $null)
{
($Date1 = Get-date)
($SP = Get-WinEvent -ComputerName $ComputerName -FilterHashTable #{
LogName = 'Security'
ID = '5379'
Data = $User
StartTime = ((Get-Date).AddDays(-1))
})
($Date2 = (
$SP |
select -first 1
).timecreated)
($USERLOGTIME = ($Date1-$Date2).hours.tostring('N2'))
}
else
{
'No user'
break
}
"Computer Name: $Computername
---USER---
Name: $User
Log in Time $USERLOGTIME
Boot start $BootStart days ago"
$ComputerName |
ForEach-Object {
if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)
{Invoke-Command -ComputerName $ComputerName}
else
{Write-Warning -Message 'Computer is Unreachable or Offline'}
}
$UserMessage = '
WARNING!
This will READ LIST of computers in:
\\ou\ouor-groups\Desktop_Support\SD\Kiosks\kiosknames.txt
Type CONTINUE to proceed'
$Continue = Read-Host $UserMessage
if ($Continue -eq 'CONTINUE')
{
Get-Content '\\ou\ouor-groups\Desktop Support\SD\Kiosks\kiosknames.txt' |
foreach {
{start-job -Name $PSItem -ScriptBlock ${Function:get-kioskinfo} -ArgumentList $PSItem}
[pscustomobject]#{
Name = $ComputerName
User = $User
'User Log in time in hours' = $USERLOGTIME
'BootStart days ago' = $BootStart
}
} |
Export-Csv -path "$PWD\$ComputerName.csv" -Append
}
}
These didn't help me with my solution, but you were right about the start-jobs. I have to rework the entire script in order to get the correct info.

new-object PSObject causes null-valued expression error

My PowerShell script:
Param([string]$Computers) #Must supply a comma seperated list of servers
$Threshold = 20 #Only show CPU over this number
$NoP = 20 #Number of processes to list
$NoRS = 4 #Number of result sets
If (! $Computers) {
Write-Host "Connection to server failed - please specify a server name." -ForegroundColor Red
Break
} Else {
$ComputerList = $Computers -Split " "#,[StringSplitOptions]'RemoveEmptyEntries')
}
$Credential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "NetBiosUserName")
If (! $Credential) {
Write-Host "Authentication failed - please verify your username and password." -ForegroundColor Red
Break
}
$UserName = $Credential.Username
$Password = $Credential.GetNetworkCredential().Password
$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$Domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)
If ($Domain.Name -eq $null){
Write-Host "Authentication failed - please verify your username and password." -ForegroundColor Red
Break
}
ForEach ($ComputerName In $ComputerList) {
$LoadPercentage = $Processors.LoadPercentage
If (!$LoadPercentage) {$LoadPercentage = 0}
Write-Host "Server: $ComputerName (CPU load $LoadPercentage%)" -NoNewline
$Processors = Get-WmiObject win32_processor -ComputerName $ComputerName -Credential $Credential
$i = 1
$TopProcess = #()
$PercentComplete = 0
Do{
$PercentComplete = [Math]::Floor($i/$NoRS*100)
Write-Progress -Activity $ComputerName -Status "$PercentComplete% Complete:" -PercentComplete $PercentComplete
$ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process -ComputerName $ComputerName -Credential $Credential |
Select IDProcess,Name,PercentProcessorTime |
Where {$_.Name -ne "_Total" -and $_.Name -ne "Idle"} |
Sort PercentProcessorTime -Descending |
Select -First $NoP
ForEach ($Process In $ProcessList) {
$row = New-Object PSObject -Property #{
Id = $Process.IDProcess
Name = $Process.Name
User = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).GetOwner().User
CPU = $Process.PercentProcessorTime/$Processors.NumberOfLogicalProcessors -f {P}
Description = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).Description
}
$TopProcess += $row
}
$i++
} While ($i -lt $NoRS + 1)
Write-Progress -Activity $ComputerName -Completed
$Group = $TopProcess | Where {$_.CPU -gt $Threshold} | Group 'ID' | Where Count -eq $NoRS
If (!$Group) {
Write-Host " has no processes persistently above $Threshold percent CPU usage."
} Else {
$Processes = #()
ForEach ($Groupee In $Group) {
$Ungroup = $Groupee | Select -ExpandProperty Group
$CPU = 0
ForEach ($ugr in $Ungroup) {
$CPU += $ugr.CPU
}
$row = new-object PSObject -Property #{
Id = $Ungroup.Id | Select -First 1
Name = $Ungroup.Name | Select -First 1
CPU = $CPU/$NoRS
User = $Ungroup.User | Select -First 1
Description = $Ungroup.Description | Select -First 1
}
$Processes += $row
}
$Processes | Format-Table #{Expression={$_.User};Label="User Name";width=25},#{Expression={$_.CPU};Label="CPU";width=5},#{Expression={$_.Id};Label="ID";width=8},#{Expression={$_.Description};Label="Description";width=48}
}
}
intermittantly gives the following error:
You cannot call a method on a null-valued expression. At C:\Users\Jasons1\CPUusage.ps1:41 char:4
$row = new-object PSObject -Property #{
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : InvokeMethodOnNull
which I fail to understand as it is within a loop and should either work or get skipped as there is a test for null.
Pretty sure that your issues are stemming from this line:
User = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).GetOwner().User
Specifically from .GetOwner(). Your where clause must not be finding a matching process for that item while it is in the loop. I realize there is not much time elapsed but WMI queries are not the fastest things out there.
What is happening is likely a result of a process queried earlier in $ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process and then later when you are using gwmi Win32_Process the list of processes changed. You need to account for this as well. Time has elapsed and threads do not live forever.
$queryResult = gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}
$owner = if($queryResult){$queryResult.GetOwner().User}else{"Process DNE"}
#...
User = $owner
Not very pretty but accounts for the potential of a null return from the wmi query.

Resolve-DnsName inside Test-Connection

I was wondering how I could return the Resolve-DnsName output from my Test-Connection script and add it to the CSV I created.
I like to capture the Name, Type, TTL, Section from that please.
Only invoke the Resolve-DnsName when the ping is not successful.
$servers = Get-Content "servers.txt"
$collection = $()
foreach ($server in $servers)
{
$status = #{ "ServerName" = $server; "TimeStamp" = (Get-Date -f s) }
$result = Test-Connection $server -Count 1 -ErrorAction SilentlyContinue
if ($result)
{
$status.Results = "Up"
$status.IP = ($result.IPV4Address).IPAddressToString
}
else
{
$status.Results = "Down"
$status.IP = "N/A"
$status.DNS = if (-not(Resolve-DnsName -Name $server -ErrorAction SilentlyContinue))
{
Write-Output -Verbose "$server -- Not Resolving"
}
else
{
"$server resolving"
}
}
New-Object -TypeName PSObject -Property $status -OutVariable serverStatus
$collection += $serverStatus
}
$collection | Export-Csv -LiteralPath .\ServerStatus3.csv -NoTypeInformation
but nothing new is added to the CSV.
You ran into a PowerShell gotcha. PowerShell determines the columns displayed in tabular/CSV output from the first object processed. If that object doesn't have a property DNS that column won't be shown in the output, even if other objects in the list do have it. If other objects don't have properties that were present in the first object they will be displayed as empty values.
Demonstration:
PS C:\> $a = (New-Object -Type PSObject -Property #{'a'=1; 'b'=2}),
>> (New-Object -Type PSObject -Property #{'a'=3; 'b'=4; 'c'=5}),
>> (New-Object -Type PSObject -Property #{'b'=6; 'c'=7})
>>
PS C:\> $a | Format-Table -AutoSize
a b
- -
1 2
3 4
6
PS C:\> $a[1..2] | Format-Table -AutoSize
c b a
- - -
5 4 3
7 6
If you want to generate tabular output always create your objects uniformly with the same set of properties. Choosing sensible defaults even allows you to reduce your total codebase.
$collection = foreach ($server in $servers) {
$status = New-Object -Type PSObject -Property #{
'ServerName' = $server
'TimeStamp' = Get-Date -f s
'Results' = 'Down'
'IP' = 'N/A'
'HasDNS' = [bool](Resolve-DnsName -Name $server -EA SilentlyContinue)
}
$result = Test-Connection $server -Count 1 -EA SilentlyContinue
if ($result) {
$status.Results = 'Up'
$status.IP = ($result.IPV4Address).IPAddressToString
}
$status
}

PowerShell - Export Mailbox Statistics to HTML Report

I'm trying to generate a general system report that pulls basic statistics for network hosts. My script works as expected up until the "o365ExchConn" function, whereby it pipes all of the "Import-Pssession" output into the variable that's used to generate the HTML fragment at the end of the script.
How do I exclude this output? I just require the statistics specified in the array within the function. (i.e. Displayname, TotalItemsize & TotalItemCount).
$computername = Read-Host -Prompt "Enter Hostname"
$path = Read-Host -Prompt "Enter path for HTML report output (e.g. C:\Temp)"
$date = Get-Date
function Get-CSInfo {
param($computername)
$os = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computername
$cs = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computername
$props = #{‘Hostname’=$computername
‘OS Version’=$os.version
‘OS Build’=$os.buildnumber
‘Service Pack’=$os.sevicepackmajorversion;
'OS Name'=$os.caption}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
function Get-RamInfo {
$os = Get-WmiObject -class Win32_OperatingSystem -ComputerName $ComputerName
$cs = Get-WmiObject -class Win32_ComputerSystem -ComputerName $ComputerName
$props = #{'RAM (GB) - Total Available'="{0:N2}" -f ($cs.totalphysicalmemory / 1GB);
'RAM (GB) - Free for Use'="{0:N2}" -f ($os.freephysicalmemory / 1MB);
'RAM (GB) - Currently in Use'="{0:N2}" -f ($cs.totalphysicalmemory / 1GB) - ($os.freephysicalmemory / 1MB)}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
function Get-InfoDisk {
param($computername)
$drives = Get-WmiObject -class Win32_LogicalDisk -ComputerName $ComputerName -Filter "DriveType=3"
foreach ($drive in $drives) {
$props = #{'Drive'=$drive.DeviceID;
'Size'=$drive.size / 1GB -as [int];
'Free'="{0:N2}" -f ($drive.freespace / 1GB);
'FreePct'=$drive.freespace / $drive.size * 100 -as [int]}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
}
function Get-InfoBadService {
$svcs = Get-WmiObject -class Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State<>'Running'"
foreach ($svc in $svcs) {
$props = #{'ServiceName'=$svc.name;
'LogonAccount'=$svc.startname;
'DisplayName'=$svc.displayname}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}}
function Get-EventLogs {
$time = (Get-Date) - (New-TimeSpan -Day 1)
$logs = Get-WinEvent -ComputerName $ComputerName -FilterHashTable #{LogName='Application', 'System'; Level=1,2,3; StartTime=$time}
foreach ($log in $logs) {
$props = #{'Provider Name'=$log.ProviderName;
'Timestamp'=$log.TimeCreated;
'Id'=$log.Id;
'Error Type'=$log.LevelDisplayName;
'Message'=$log.Message;
}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
}
function Get-SecurityLogs {
$time = (Get-Date) - (New-TimeSpan -Day 1)
$sec_logs = Get-EventLog -ComputerName $computername -LogName Security -EntryType FailureAudit -After $time
foreach ($sec_log in $sec_logs) {
$props = #{'Timestamp'=$sec_log.TimeGenerated;
'Event ID'=$sec_log.EventID;
'Error Type'=$sec_log.EntryType;
'Message'=$sec_log.Message;
}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
}
function O365ExchConn {
$credentials = Get-Credential
Write-Output "Creating remote PowerShell session ..."
$session = New-PSSession -ConfigurationName Microsoft.Exchange -Credential $credentials -ConnectionUri https://outlook.office365.com/powershell-liveid?DelegatedOrg=*ENTERCOMPANYNAMETENANTNAME* -Authentication Basic -AllowRedirection
Write-Output "Importing PowerShell session ..."
Import-PSSession $session -AllowClobber
$userlist = Get-Mailbox | Get-MailboxStatistics | ft displayname, totalitemsize, itemcount
foreach($user in $userlist){
$props = #{'DisplayName'=$user.displayname;
'Total Size'=$user.totalitemsize;
'Total Items'=$user.itemcount;
}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
}
$frag1 = Get-CSInfo –computername $computername |
ConvertTo-Html -As LIST -Fragment -PreContent ‘<h2>System Info</h2>’ |
Out-String
$frag2 = Get-InfoDisk -ComputerName $computername |
ConvertTo-Html -As Table -Fragment -PreContent '<h2>Disk Info</h2>' |
Out-String
$frag3 = Get-RamInfo -ComputerName $computername |
ConvertTo-Html -As Table -Fragment -PreContent '<h2>Memory Info</h2>' |
Out-String
$frag4 = Get-InfoBadService -ComputerName $computername |
ConvertTo-Html -As Table -Fragment -PreContent '<h2>Stopped Services</h2>' |
Out-String
$frag5 = Get-EventLogs -ComputerName $computername |
ConvertTo-Html -As Table -Fragment -PreContent '<h2>Application / System Logs</h2>' |
Out-String
$frag6 = Get-SecurityLogs -ComputerName $computername |
ConvertTo-Html -As Table -Fragment -PreContent '<h2>Security Logs</h2>' |
Out-String
$frag7 = O365ExchConn -ComputerName $computername |
ConvertTo-Html -As List -Fragment -PreContent '<h2>Exchange Mailbox Stats</h2>' |
Out-String
$head = #’
<style>
body { background-color:#dddddd;
font-family:Tahoma;
font-size:12pt; }
td, th { border:1px solid black;
border-collapse:collapse; }
th { color:white;
background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px }
table { margin-left:50px; }
</style>
‘#
$filepath = Join-Path -Path $path -ChildPath "$computername.html"
ConvertTo-HTML -head $head -PostContent $frag1,$frag2,$frag3,$frag4,$frag5,$frag6,$frag7 -PreContent “<h1>System Maintenance Report for $computername</h1><br><h2>Generated on $date” |
Out-File $filepath
There are multiple ways in PowerShell to prevent cmdlets from outputting text where it's not desired.
See this question for more information
[void] Import-PSSession $session -AllowClobber
Import-PSSession $session -AllowClobber | Out-Null
$ImportPSSession = Import-PSSession $session -AllowClobber

How to make script run remotelly on computers?

I have written a script that is to collect hardware and software information from a forrest/domain. I've read several posts about running a PS-script from a computer on a server, but I want to do the opposite.
How do you know that a script is "remotely accesible".
I've seen this command beeing used:
Invoke-Command -ComputerName {serverName} –ScriptBlock { commands }
Is there any other alternatives than computername? I'm thinking that this is not exclussive as several computers can have the same name..
This is my script:
try{
$ConfirmPreference="none"
$error.clear()
$erroractionpreference = "silentlycontinue"
#Gets the date of this day, used as name for XML-file later.
$a = get-date -uformat "%Y_%m_%d"
#Saves computername to compname variable(HELPER)
$compname = gc env:computername
#Gets the path to directory for all saved files and folders
$scriptpath = Split-Path -parent $myinvocation.MyCommand.Definition
#PC Serial Number, is used as name for directory containing XML files for this computer.
$serialnr = gwmi win32_bios | select -Expand serialnumber
#Creates a folder with the name of the computers hardware serialnumber if it does not exist.
if(!(Test-Path -path $scriptpath\$serialnr)) {
New-item -path $scriptpath -name $serialnr -type directory
}
#Username
$username = gc env:username
#System Info
gwmi -computer $compname Win32_ComputerSystem | ForEach {$siname = $_.Name; $simanufacturer = $_.Manufacturer; $simodel = $_.Model}
#Graphic card
$gpuname = gwmi win32_VideoController | select -Expand Name
#Processor Info
gwmi -computer $compname Win32_Processor | ForEach-Object {$cpuname = $_.Name; $cpumanufacturer = $_.Manufacturer; $cpucores = $_.NumberOfCores; $cpuaddresswidth = $_.AddressWidth}
#Memory
$totalmem = 0
$memsticks = gwmi -Class win32_physicalmemory
foreach ($stick in $memsticks) { $totalmem += $stick.capacity }
$totalmem = [String]$($totalmem / 1gb) + " GB"
#Drive
$totalspace = 0
$totalsize = gwmi -Class win32_logicaldisk
foreach($size in $totalsize) { $totalspace += $size.size }
$totalspace = "{0:N2}" -f ($totalspace/1Gb) + " GB"
#Install time for windows OS
$utctime = get-wmiobject win32_OperatingSystem | select-object -expandproperty installDate
$installtime = [System.Management.ManagementDateTimeConverter]::ToDateTime($utctime);
$installtime = Get-Date $installtime -uformat "%d/%m/%Y %X"
#--------#
#XML-form
#--------#
try{
$erroractionpreference = "stop"
$template = "<computer version='1.0'>
<hardware>
<serialnumber>$serialnr</serialnumber>
<systeminfo>
<name>$siname</name>
<manufacturer>$simanufacturer</manufacturer>
<model>$simodel</model>
</systeminfo>
<drive>
<size>$totalspace</size>
</drive>
<memory>
<size>$totalmem</size>
</memory>
<gpu>
<name>$gpuname</name>
</gpu>
<cpu>
<name>$cpuname</name>
<manufacturer>$cpumanufacturer</manufacturer>
<id>cpuid</id>
<numberofcores>$cpucores</numberofcores>
<addresswidth>$cpuaddresswidth</addresswidth>
</cpu>
</hardware>
<software>
<user>
<name>$username</name>
</user>
<osinfo>
<caption></caption>
<installdate>$installtime</installdate>
<servicepack></servicepack>
</osinfo>
</software>
</computer>"
$template | out-File -force $ScriptPath\$serialnr\$a.xml
$systemroot = [System.Environment]::SystemDirectory
$xml = New-Object xml
$xml.Load("$ScriptPath\$serialnr\$a.xml")
}catch{
}
#OSInfo, software
$newosinfo = (#($xml.computer.software.osinfo)[0])
Get-WmiObject -computer $compname Win32_OperatingSystem |
ForEach-Object {
$newosinfo = $newosinfo.clone()
[String] $bitversion = $_.osarchitecture
$newosinfo.caption = [String]$_.caption + "" + $_.osarchitecture
$newosinfo.servicepack = $_.csdversion
$xml.computer.software.AppendChild($newosinfo) > $null
}
$xml.computer.software.osinfo | where-object {$_.caption -eq ""} | foreach-object {$xml.computer.software.RemoveChild($_)}
#-------Save and get content--------
$xml.Save("$scriptpath\$serialnr\$a.xml")
#$new = Get-Content $scriptpath\$serialnr\$a.xml
#-----------------------------------
if(!$?){
"An error has occured"
}
}catch{
[system.exception]
"Error in script: system exception"
}finally{
}
For the -ComputerName parameter, you can use NETBIOS name, IP address, or fully-qualified domain name. For more details, see Invoke-Command on TechNet.
Seems like your script is "only" saving the data on the machine it is running, you will probably want it to return something in order to be useful with Invoke-Command.