How to make a powershell program restart on user input - powershell

Ok, so this is my first time posting on here and my first time writing PowerShell. My school computer maintenance and repair class requested from all the students that one of them create a PowerShell script that calculates a computers ram. The one I created calculates total physical ram, total ram usable by the user, and the modules in the computer and how much is on each module. However, after successfully coding it, I need a bit of advice as to tweaking the code so it can be use for my school.
The first part of my program opens up and talks about what each line means, follows by total physical ram, user accessible ram, and then the way the cards are set up. This leads right into a text that says to close the program. What I want to add in (I am a beginner at PowerShell by the way) is a way for the user to rerun the application if any of the variables from the program come up as zero (cause obviously the computer has ram of some sort if the computer is running). Right now its a Read-Host "Rerun memsrch ('y'/'n')?"
The other thing I want to add in is the ability for the user to select if the code is for the local computer or a distant machine. The user then could select the computer via IP or computer name. Below is the code I have now so everyone can see.
# Mesa Public Schools
$mps="Mesa Public Schools Information Technology Services"
$mps
# User Help
$print="The first section calculates your total physical memory,
the second line calculates the ram available to the user,
and the third line shows how the ram is divided up among
the ram cards.`n"
$print
#where I want to put a line of code to allow user to select if its local or remote
$ram = get-wmiobject win32_computersystem | select totalPhysicalMemory
Write-Host "Total usable RAM capacity"
$ramOutput = get-wmiobject win32_computersystem | select totalPhysicalMemory | foreach {$_.totalPhysicalMemory}
"RAM: " + "{0:N2}" -f ($ram.TotalPhysicalMemory/1GB) + "GB"
Get-WMIObject -class win32_physicalmemory | Format-Table devicelocator, capacity -a
Write-Host "Summary of System Memory"
Get-WmiObject -class Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum
# Coded BY
$credits="Coded by Michael Meli"
$credits
#where I want to have the code reloop to the part of the code where
#you first select if the computer is local or remote.
Read-Host "Rerun memsrch (y/n)?"
I also have a bit of experience with HTML 4.01 and HTML 5 code, so I understand the basics of constructs and arguments, but aside from that a large part of powershell at the moment is above my head, so don't get to technical cause I don't want my brain to explode. :P Also note that the code if for computers running windows 8.1, but must be compatible with windows 7 as well. This also is not for a grade in my class either, it's extra credit.

If you wrap your code in a function, you will be able to call it again when you want. For instance, if the user input for the second question is y.
Store user input for the computer name or IP address, so you can use it in the WMI calls you make in the script, with the -ComputerName parameter
Example code:
function Show-MemoryReport {
#...
#where I want to put a line of code to allow user to select if its local or remote
#if computer name is null (first pass)
if($computerName -eq $null) {
#ask the user
$computerName = Read-Host "Enter computer name or IP, or leave blank for local"
#if the string is empty, use the local computer name
if($computerName -eq "") {
$computerName = $env:COMPUTERNAME
}
}
$ram = Get-WmiObject -ComputerName $computerName -Class Win32_Computersystem | Select-Object totalPhysicalMemory
#...
#where I want to have the code reloop to the part of the code where you first select if the computer is local or remote.
$rerun = Read-Host "Rerun report (y/n)?"
if($rerun -eq "y") { Show-MemoryReport }
}
#at first run, make sure computer name will be asked
$computerName = $null
#run report
Show-MemoryReport
After the first pass, $computerName will not be $null anymore.
Tip : you don't need to store a string in a variable to be able to output it. Just write it on a separate line like "print this on the screen" and it will be output.
For more information about PowerShell constructs and functions, you can read this and this

Related

Check AD users' network share mapping with PowerShell

I tried using net use, net share, among others - none of which return the expected output. So instead, I'm modifying a script I found to see which network drives/shares are mapped to a user the script is pushed to. Then I go to my log file, look at the data, and determine if the account is set up properly. Here's the current script:
Get-WmiObject Win32_MappedLogicalDisk -computer $env:COMPUTERNAME | select name, providername
Out-File -filepath "\\*UNC filepath*\Mapped_Drives_$env:USERNAME$(get-date -Format _MM-dd-yy" # "HH.mm.ss" "tt).txt"
When I run it, the log file returns empty and I'm not sure why. I changed "Out-File -filepath" to "Start-Transcript" which isn't working the way I want it to either (with too much verbose output). It outputs fine in my PowerShell ISE with all the proper shares listed, but doesn't work when I navigate to the logged output. What am I missing?
You must pipe the output into the logfile
$logfile = "\\*UNC filepath*\Mapped_Drives_$env:USERNAME$(get-date -Format _MM-dd-yy" # "HH.mm.ss" "tt).txt"
Get-WmiObject Win32_MappedLogicalDisk | select name, providername | Out-File $logfile
On a more general note I'd use the commands to fix the mapped drives right there and then, instead of just writing them to a logfile for later inspection.

using powershell to check active IP's or MAC's connected to router

I want to run a Powershell script that talks to the router/AP and figures out what IP (I have Reserved IPS) or MAC address is currently connected to the Router/AP. The script would output what is connected so that I could see "who's home".
At first I used IE though powershell logging into the router and trying to capture data of the wifi client page but I don't think that is the way to go. Is there another way to do this? A way to scan the network without worrying about logging into the router?
If you have DNS resolution on the names of your PCs, you can try this out.
$Computer = "value or foreach loop of values"
$IPAddress = ([System.Net.Dns]::GetHostByName($Computer).AddressList[0]).IpAddressToString
$IPMAC = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $Computer
$MACAddress = ($IPMAC | where { $_.IpAddress -eq $IPAddress}).MACAddress
I have tested this with a couple individual names and a foreach loop getting the names from a txt or csv file, and I tested using
write-host $IPAddress $MACAddress
at the end for a sanity check.
If you want to verify an up/down state of the computer before querying, try using the 'test-connection' powershell command (basically a ping that grabs the results)

Running Command as Administrator from a SYSTEM Process

So I need to clear a user's run dialog history which I can do perfectly fine with "reg delete HKEY_CURRENT_USER\Software\Windows etc..." from an elevated powershell window on the logged in user's machine, but what I'm looking to do is that same command but from a SYSTEM powershell process. I have already used psexec to create a powershell window which runs as SYSTEM, but because you can't just use HKEY_CURRENT_USER as SYSTEM with the same results, I am finding it quite difficult. If I could just run that command but as username\Administrator then I wouldn't have this problem.
Also to note, if I can somehow grab the username of the logged on user (from SYSTEM still) in one line in plain text (with no other output in sight), then I can store the username in a variable and convert that to an SID and use HKEY_USERS instead.
P.S. Don't ask why I'm running powershell as SYSTEM, I know what I'm doing :D
you can use get-process under the system context powershell and filter where explorer.exe process is running, get the account it is running under then use to convert to SID and go through the registry.
something like this assuming only 1 explorer.exe process is running which is the norm on windows client OS.
$proc = Get-CimInstance Win32_Process -Filter "name = 'explorer.exe'"
$owner = Invoke-CimMethod -InputObject $proc -MethodName GetOwner
$username = $owner.user
$username will contain the user, $owner will also contain domain and a few other things.
to convert to sid
$objUser = New-Object System.Security.Principal.NTAccount($owner.Domain, $owner.User)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value

Net view - get Just ' Share Name'

I need to get all of the shares name in some storage's.
Im using Net view $StorageName and it's show The result in a Table format :
Share name Type Used as Comment
----------------------------------------------------------------------------
Backups Disk
CallRecordings Disk
Download Disk System default share
home Disk Home
homes Disk System default share
Installs Disk
Justin Disk Copy of files from Justin laptop
michael Disk
Multimedia Disk System default share
Network Recycle Bin 1 Disk [RAID5 Disk Volume: Drive 1 2 3 4]
Public Disk System default share
Qsync Disk Qsync
Recordings Disk System default share
Sales Disk Sales Documents
SalesMechanix Disk
Server2012 Disk Windows Server 2012 Install Media
Usb Disk System default share
VMWareTemplates Disk
Web Disk System default share
The command completed successfully.
Thats good, but I need Just the Share Name.
I need Help please.
Thanke You!
Here is one way you could do it with the net view output:
(net view $StorageName | Where-Object { $_ -match '\sDisk\s' }) -replace '\s\s+', ',' | ForEach-Object{ ($_ -split ',')[0] }
Basically that is saying find the lines that have Disk surrounded by whitespace just in case something else might have Disk in the name. Then replace multiple spaces with a comma. Then, for each of those lines, split again by the comma and take the first value which would be the share name.
If you are on a Windows 8/2012 or newer system (and attempting to enumerate shares on other Windows systems), you could use a CIM session along with Get-SmbShare instead of net view which would return the results as objects and allow you to select the fields you want in the native PowerShell way.
For example:
$cimSession = New-CimSession $StorageName
Get-SmbShare -CimSession $cimSession | Select Name
Name
----
Admin
ADMIN$
C$
IPC$
J$
print$
Public
Software
Another option for parsing the net view output that relies on positioning rather than regular expression matching. personally I feel it's a bit easier to read and just as reliable.
function get-shares {
param($server)
$rawShares = net view \\$server
$shares = $rawShares[7..($s.Count - 3)]
$shares | . {process{$_.substring(0,($_.indexof(" ")))}}
}

How to check if a server is running windows 2003 or Windows 2008 by checking its RDP screen, through script?

We have recently acquired a small firm having 1500 servers on which our team doesn't has access as of now although they are in domain. We need to find out how many servers are running Windows 2k3 and how many are Windows 2k8.
I know the RDP screen of both of these versions are different , for example: if we RDP a Win2k3 machine, it gives a warning notice first and once we click Ok, it takes us to the credentials screen , but in case of Win2k8, it directly takes us to Crendentials which is a proof of the OS on the server. Doing this manually for 1500 servers is a time consuming task.
Can we implement this RDP screen logic using a script to find out the Windows OS version.
I can imagine an Algorithm something like that:
Enter server name.
Invoke mstsc for that server
Verify if the dialogue box is a direct prompt for credentials or not?
If so, print Windows 2k8, else 2k3/2k.
If this logic successful on one server, I can use it in a foreach loop for all servers and export in in Excel.
With 1500 servers I'm going to assume that you have an Active Directory in place. In that case you should be able to simply run a query against AD to retrieve the desired information:
Import-Module ActiveDirectory
$server = 'somehostname'
$dc = '...' # domain controller of trusted domain
$fltr = "OperatingSystem -like '*server*'"
Get-ADComputer -Filter $fltr -Property OperatingSystem -Server $dc |
Where-Object { $_.Enabled } |
Select-Object Name, OperatingSystem |
Sort-Object OperatingSystem, Name
Pipe the result into Export-Csv to create a CSV file that you can import into Excel.