Export Printer Information to CSV in Powershell

Here is a quick one liner to export basic printer information to CSV. I have found it handy to provide my service desk with this information when they are replacing printers and need to use the same IP information.

Get-Printer | select Name, DriverName, PortName | Export-Csv Printers.csv -NoTypeInformation

For more information about the Get-Printer command check out Technet at https://technet.microsoft.com/en-us/%5Clibrary/hh918358(v=wps.630).aspx

Read More

Audit Windows Network Settings with Powershell

We have been consolidating IT groups at the university for several years now. During this time we have to convert both clients and servers to use our central division Active Directory and other centralized services. However gathering all of the networking information can be quite the task and prone to error. One of the easiest ways I have found to gather all of this information is by running a script to generate CSV file of these settings.

I used this existing script I found over on techibee.com and took it a few steps further.

I added that ability to query Active Directory and find all the computers within an OU and the ability to adjust the filter. This can be handy if you want to find just windows servers or windows clients or just plain windows. I also fixed the output for multiple DNS servers or gateways to a CSV file as well as added some standard header and footers to make the screen output a bit cleaner. This script does require you to have the Active Directory Powershell Module Installed. It will save the CSV to the local directory from which the script is executed and report the path at the end of the screen output. This script should be run with a highly privileged user as it will need to query multiple remote computer using WMI and access Active Directory.

Script

Import-Module ActiveDirectory

$localpath = Get-Location;
$CSVFileName = $localpath.Path + "\Department-Network-Information.csv";

$ComputerName = Get-ADComputer -SearchBase "OU=Department,OU=Division,DC=domain,DC=local" -Filter {OperatingSystem -Like "Windows*"} -Property "Name";

$Results = @()

foreach ($Computer in $ComputerName)
{
    if(Test-Connection -ComputerName $Computer.Name -Count 1 -ea 0) 
    {
        $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer.Name | ? {$_.IPEnabled};
        foreach ($Network in $Networks) 
        {
            $IPAddress  = $Network.IpAddress[0];
            $SubnetMask  = $Network.IPSubnet[0];
            $DefaultGateway = $Network.DefaultIPGateway;
            $DNSServers  = $Network.DNSServerSearchOrder;
            $IsDHCPEnabled = $false;
            If($network.DHCPEnabled) 
            {
                $IsDHCPEnabled = $true;
            }
            $MACAddress  = $Network.MACAddress;

            if ($DNSServers) 
            {
                $StringDNSServers = [string]::join("; ",$DNSServers);
            }
            else
            {
                $StringDNSServers = " ";
            }

            if($DefaultGateway)
            {
                $StringDefaultGateway = [string]::join("; ",$DefaultGateway);
            }
            else
            {
                $StringDefaultGateway = " ";
            }

            $ReturnedObj = New-Object -Type PSObject;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.Name.ToUpper();
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name IPAddress -Value $IPAddress;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name SubnetMask -Value $SubnetMask;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name Gateway -Value $StringDefaultGateway;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name IsDHCPEnabled -Value $IsDHCPEnabled;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name DNSServers -Value $StringDNSServers;
            $ReturnedObj | Add-Member -MemberType NoteProperty -Name MACAddress -Value $MACAddress;
            $ReturnedObj;
            $Results += $ReturnedObj;
        }
    }  
}

$Results | export-csv $CSVFileName -notype;

Write-Host
Write-Host "File Saved to: $CSVFileName";
Write-Host
Write-Host "Press any key to close ..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Screen Output Example

ComputerName  : Computer1
IPAddress     : 194.90.128.89
SubnetMask    : 255.255.255.0
Gateway       : 194.90.128.254
IsDHCPEnabled : True
DNSServers    : 8.8.8.8; 8.8.4.4
MACAddress    : 18:13:73:2A:98:FA

ComputerName  : Computer2
IPAddress     : 194.90.128.92
SubnetMask    : 255.255.255.0
Gateway       : 194.90.128.254
IsDHCPEnabled : True
DNSServers    : 8.8.8.8; 8.8.4.4
MACAddress    : F8:B1:56:AC:FB:2E


File Saved to: D:\Powershell-Scripts\Department-Network-Information.csv

Press any key to close ...

CSV Output

"Computer1","194.90.128.89","255.255.255.0","194.90.128.254","True","8.8.8.8; 8.8.4.4","18:13:73:2A:98:FA"
"Computer2","194.90.128.92","255.255.255.0","194.90.128.254","True","8.8.8.8; 8.8.4.4","F8:B1:56:AC:FB:2E"

Read More

Powershell File Sharing Permissions Report

Often I am asked to verify folder permissions for a user in a specific place out on one of our servers. Typically this requires browsing out the folder and putting eyes on the permissions dialog box looking for a group on which the user is a member and then documenting it in the ticket. A very painful long boring process. This is where Powershell comes and saves the day. I wrote a very simple script to bring that information to me. It also gives nice output that I can directly copy into tickets to answer what groups has rights to what shares.

This prompts the user to “Enter a UNC Path” once entered goes and grabs the NTFS permissions as well as the SMB Share permissions

Powershell Code

Write-Host

$path = Read-host “Enter a UNC Path: ”
$pathparts = $path.split("\")
$ComputerName = $pathparts[2]
$ShareName = $pathparts[3]

Write-Host "File Sharing Permissions Report - $path"
Write-Host 

$acl = Get-Acl $path

Write-Host "File/NTFS Permissions"
Write-Host 

foreach($accessRule in $acl.Access)
{
    Write-Host "   " $accessRule.IdentityReference $accessRule.FileSystemRights
}
Write-Host 
Write-Host "Share/SMB Permissions"
Write-Host

    $Share = Get-WmiObject win32_LogicalShareSecuritySetting -Filter "name='$ShareName'" -ComputerName $ComputerName
    if($Share){
        $obj = @()
        $ACLS = $Share.GetSecurityDescriptor().Descriptor.DACL
        foreach($ACL in $ACLS){
            $User = $ACL.Trustee.Name
            if(!($user)){$user = $ACL.Trustee.SID}
            $Domain = $ACL.Trustee.Domain
            switch($ACL.AccessMask)
            {
                2032127 {$Perm = "Full Control"}
                1245631 {$Perm = "Change"}
                1179817 {$Perm = "Read"}
            }
            Write-Host "   $Domain\$user  $Perm"
        }
    }
Write-Host

Example Output

.\Get-Permissions-NTFS-SMB.ps1

Enter a UNC Path: : \\filesrv\Working Groups
File Sharing Permissions Report - \\filesrv\Working Groups

File/NTFS Permissions

    BUILTIN\Administrators FullControl
    DOMAIN\Domain Admins FullControl
    DOMAIN\Domain Users ReadAndExecute, Synchronize
    DOMAIN\Folder - File Server Admins FullControl

Share/SMB Permissions

   DOMAIN\Domain Admins  Full Control
   DOMAIN\Domain Users  Full Control

Read More

How to Remove Old Cached Roaming Profiles from Workstations

Earlier this year I was tasked with cleaning up the workstations on our network to help reduce the amount of time needed for our daily virus scan to complete. One of the issues I took on was cleaning up old cached profiles from the use of roaming profiles. This was not something I wanted to do manually for the 150 PCs that we have across our building, so I made a script that would look for profiles that had not been modified in the last 90 days and wasn’t a system account (localservice, networkservice, default user, all users). Also, an advantage of using a script to do this is it can produce a report of what it will remove without actually doing it. That way you can be sure that you are not deleting things that you do want to keep.

This script does depending on file and print sharing being turned on for the workstation so the script can access the administrative shares on each computer. It does make the assumption that your profiles are saved in the default windows location C:\Documents and Settings\%username% and that you are the administrator for the domain.

Configuration

  1. Be sure to update the LDAP string ‘LDAP://OU=workstations,DC=subdomain,DC=domain,DC=com’ to match your Active Directory structure. The script needs to know where all the workstation are in Active Directory
  2. Find objConnection.Open “DomainController” and modify the put your Domain Controller in place of DomainController
  3. Find OldProfile objRecordSet.Fields(“Name”).Value, “C:\deletedprofiles.csv” and modify the filename to save the file where you and and named what you want, just be sure to leave the extension as CSV so it will open properly with your spreadsheet application.
  4. Most Importantly – Comment out fsoFolder.DeleteFolder objSubfolder, TRUE if you just want a report of what it will delete when run, if not it is currently setup to remove the unwanted profiles
Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "shs-login"

Set objCOmmand.ActiveConnection = objConnection
objCommand.CommandText = _
    "Select Name, Location from 'LDAP://OU=workstations,DC=subdomain,DC=domain,DC=com' " _
        & "Where objectClass='computer'"  
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst

Do Until objRecordSet.EOF
	OldProfile objRecordSet.Fields("Name").Value, "C:\deletedprofiles.csv"
    objRecordSet.MoveNext
Loop

Sub OldProfile(strComputer, strFilename)
	On Error Resume Next
	Set StdOut = WScript.StdOut
	 
	Set objFSO = CreateObject("scripting.filesystemobject")
	Set logStream = objFSO.opentextfile(strFilename, 8, True)
	 
	Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
	If Err.Number Then
	      logStream.writeline(strComputer & ",Offline")
	      Err.Clear
	Else
		On Error Resume Next
		Set objShell = CreateObject("Shell.Application")
		Set fsoFolder = CreateObject("Scripting.FileSystemObject")

		root = "\\" & strComputer &"\C$\Documents and Settings"

		Set objFolder = fsoFolder.GetFolder(root)
		Set colSubfolders = objFolder.Subfolders
		
			For Each objSubfolder in colSubfolders
				If (lcase(objSubfolder.Name) <> "localservice" AND lcase(objSubfolder.Name) <> "networkservice"_
					AND lcase(objSubfolder.Name) <> "default user" AND lcase(objSubfolder.Name) <> "all users") then
						
						If (DateDiff("D", objSubfolder.DateLastModified, Date()) > 90) then
							logStream.writeline(strComputer & ",Online,Delete," & objSubfolder & "," & objSubfolder.DateLastModified)
							fsoFolder.DeleteFolder objSubfolder, TRUE
						else
							logStream.writeline(strComputer & ",Online,Active," & objSubfolder & "," & objSubfolder.DateLastModified)
						End If
						
				else
					logStream.writeline(strComputer & ",Online,System," & objSubfolder & "," & objSubfolder.DateLastModified)
				End If
			Next
	End If
	logStream.Close
End Sub

Read More

Passing Parameters to VB Script to Map Network Drives

The other day I got an instant message from a fellow network administrator asking for a script that would map drives to by simply passing parameters from command line. This caused me to go into Google mode checking how parameters are passed in to Visual Basic Script and then applying the basic network drive mapping script. Now I feel that only the proper thing to do is share it with everyone out there that is looking for the same thing he was. This is a very simple script that does something equally simple. Hopefully this will simply some of the group policies that are out there.

Usage: mapme.vbs Z //server/share

This would result in passing Z as the drive letter and mapping it to the UNC path of //server/share

Set objArgs = WScript.Arguments
Set objNetwork = WScript.CreateObject("WScript.Network")
objNetwork.MapNetworkDrive  objArgs(0) & ":" , objArgs(1)

Read More