I recently had to install VNC on mass across a lot of computers on a domain and needed some info about their PC, for example:
- Host name
- Username
- MAC Address
- IPv4 Address
- Domain name
Once all of this info is gathered, it is compiled into a text file and uploaded to a FTP server. To save files from being conflicted with the same name, I set each file to be named the name of the user.
This is the first ever script and first experience I have had with Powershell so please tell me if there is anything I can improve.
function Get-MACAddress {
ipconfig /all | findstr "Physical" | Where-Object {$_.length -lt 58}
}
function Get-IPAddress {
ipconfig | findstr "IPv4 Address"
}
function Get-HostName {
get-content env:computername
}
function Get-UserName{
get-content env:UserName
}
function Get-DomainName{
get-content env:USERDOMAIN
}
function CreateCSVdocument {
Get-MACAddress | New-Item C:\Users\$($env:username)\Documents\$($env:username).txt -type file -force
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " "
Get-IPAddress | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " "
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt "Hostname:"
Get-Hostname | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " "
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt "User:"
Get-UserName | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " "
Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt "Domain:"
Get-DomainName | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt
}
function FTPUpload {
$Dir="C:\Users\$($env:username)\Documents\$($env:username).txt"
#ftp server
$ftp = "ftpserver"
$user = "username"
$pass = "password"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
#list every sql server trace file
foreach($item in (dir $Dir "$($env:username).txt")){
"Uploading $item..."
$uri = New-Object System.Uri($ftp+$item.Name)
$webclient.UploadFile($uri, $item.FullName)
}
}
Get-DomainName
Get-IPAddress
Get-MACAddress
Get-HostName
Get-UserName
CreateCSVdocument
FTPUpload
2 Answers 2
It looks quite fine to me.
I'm mainly surprised by the massive duplication in the CreateCSVdocument function:
function CreateCSVdocument { Get-MACAddress | New-Item C:\Users\$($env:username)\Documents\$($env:username).txt -type file -force Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " " Get-IPAddress | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " " Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt "Hostname:" Get-Hostname | Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt Add-Content C:\Users\$($env:username)\Documents\$($env:username).txt " "
It would be better to introduce a variable there and use that, for example:
function CreateCSVdocument {
$Dir="C:\Users\$($env:username)\Documents\$($env:username).txt"
Get-MACAddress | New-Item $Dir -type file -force
Add-Content $Dir " "
Get-IPAddress | Add-Content $Dir
Add-Content $Dir " "
Add-Content $Dir "Hostname:"
Get-Hostname | Add-Content $Dir
Add-Content $Dir " "
Actually, this is still too repetitive.
Probably there is a better way to output all the text and pipe the whole thing to ... | Add-Content $Dir once at the end,
but I don't know how to do that in powershell.
The formatting is inconsistent:
In function definitions, sometimes you put a space between function name and
{and sometimes you don't:function Get-MACAddress { function Get-UserName{I recommend to put a space always, consistently.
Indentation is inconsistent:
- You correctly indented the body of
Get-MACAddress,Get-IPAddressand others - But you didn't follow the same logic in
Get-HostName,Get-UserName,Get-DomainNameand others
- You correctly indented the body of
-
\$\begingroup\$ Thank's Janos, this has made it look a lot neater. I have put the 'Add-Content $Dir " "' to create a new line as when I have tried other code to create a new line it does not work. could you please advice? \$\endgroup\$Phasmatis– Phasmatis2014年11月24日 09:55:51 +00:00Commented Nov 24, 2014 at 9:55
-
\$\begingroup\$ @Phasmatis I don't see why that wouldn't work. \$\endgroup\$janos– janos2014年11月24日 16:12:50 +00:00Commented Nov 24, 2014 at 16:12
-
\$\begingroup\$ it seems to write it in the text file also, for example if I did /n it would create a new line but write /n in the text document also. \$\endgroup\$Phasmatis– Phasmatis2014年11月24日 16:15:32 +00:00Commented Nov 24, 2014 at 16:15
The script looks sound and functional, and quite a useful script considering it's your first. This is how I would restructure it for brevity and readability:
I would do away with the functions altogether, unless this is part of a larger script where you will call them multiple times.
The bulk of the script can be condensed using
@" ... "@. You can insert new lines to the output, and include the information you need:$outputfile = "C:\Users\$($env:username)\Documents\$($env:username).txt" @" $(ipconfig /all | ? { $_ -ilike "*physical*" -and $_.length -lt 58 }) $(ipconfig | ? { $_ -ilike "*IPv4 Address*" }) Hostname: $env:computername User: $env:UserName Domain: $env:USERDOMAIN "@ | Out-File $outputfileNotice I didn't use
findstr- there is functionality in Powershell for this. You touched on it when testing$_.length -lt 58.Declaring
$Dirwould now be unnecessary due to declaring$outputfileon the first line:$Dir="C:\Users\$($env:username)\Documents\$($env:username).txt"I don't have access to an FTP server to test the upload, but this loop is suspicious:
foreach($item in (dir $Dir "$($env:username).txt")){ ... }Using
diris fine, but note this is an alias of the Powershell commandGet-ChildItem. The loop condition here amounts to getting a single file, whose name and path is already stored in$outputfileon the first line. Therefore the entire loop is unnecessary:$item = Get-Item -Path $outputfile "Uploading $($item.FullName)..." $uri = New-Object System.Uri($ftp+$item.Name) $webclient.UploadFile($uri, $item.FullName)