Showing posts with label Utility. Show all posts
Showing posts with label Utility. Show all posts

Thursday, August 11, 2016

PowerShell: Gmailing / Emailing Screenshots

I totally scraped the script from AdminAresenal. Kris Powell wrote such a good solution that I lifted it and added a gmailer process. I'm posting this solution in case someone needs to automate emailing of screenshots. The automation component is Task Scheduler.  My scheduled job uses "powershell -executionpolicy unrestricted -windowstyle minimized c:\scripts\screenshots.ps1" so I don't have the PowerShell script window appear in each screenshot.

#Create a timestamp-based BMP filename

$filename = (get-date).tostring().replace('/','.').replace(':','.')

#Create a folder for your outputted screenshots
$File = "c:\scripts\ss\$filename.bmp"

## From the AdminArsenal blog ##
Add-Type -AssemblyName System.Windows.Forms
Add-type -AssemblyName System.Drawing

# Gather Screen resolution information
$Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen
$Width = $Screen.Width
$Height = $Screen.Height
$Left = $Screen.Left
$Top = $Screen.Top

# Create bitmap using the top-left and bottom-right bounds
$bitmap = New-Object System.Drawing.Bitmap $Width, $Height

# Create Graphics object
$graphic = [System.Drawing.Graphics]::FromImage($bitmap)

# Capture screen
$graphic.CopyFromScreen($Left, $Top, 0, 0, $bitmap.Size)

# Save to file
$bitmap.Save($File) 

#Now we send that screenshot via GMail
#Enable "Less Secure Apps" in order to use SMTP via script
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "yourgmailaccount@gmail.com"
$Password = "P@$$w0rd"

$to = "addressee@gmail.com"
$cc = "anotherperson@someotherdomain.com"
$subject = "Screenshot taken $filename"
$body = "Screenshot Attachment"
$attachment = $file

$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.cc.add($cc)
$message.from = $username
$message.attachments.add($attachment)

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)

Saturday, July 2, 2016

PowerShell: Using DNS and Printer CSV List for IP-Based Printer Installs on Random Network Environments

I support incident management teams and have been trying to find a simple-ish way to have users install printers no matter our network environment.  I setup the same server every incident so that is where I place all scripts and drivers.  We perform massive printing in a short amount of time and this can cause printers to be replaced as they wear out.  Instead of visiting every networked laptop to update printers, I now have 10 static printer numbers and use a CSV file to give driver information, IP address, and printer name.  The user locates the nearest printer, double-clicks the installation batch file, and the process removes the old driver and IP address of that printer and installs the current settings.  This process has been tested for PowerShell version 4.0.
Steps in creating this printer installation process:
  1. Remote into each printer and setup a DNS name.  Ping the IP and DNS name after making the change.  Ensure you allow the printer to take the DNS suffix of the local DHCP server.  Use DHCP.
  2. Download and test the driver that'll be used.  Find the correct INF file that has the printer driver name.  You'll have to add the printer driver name and driver shared folder location to the printerlist.csv file.
  3. Label your printers so users know which printer they need to install.
  4. Create your batch files which start the install process:

@CLS
@powershell -command "start-process powershell" -verb runas -argumentlist '-ExecutionPolicy bypass -file \\server\printers\InstallPrinter.ps1 Team12P1'
    • @cls clears screen to get rid of extraneous messages while starting script
    • @powershell -command "start-process powershell" -verb runas elevates PowerShell to runas Administrator and bypass the UAC settings which can sometimes stop driver installations
    • -argumentlist '-ExecutionPolicy bypass -file \\server\printers\InstallPrinter.ps1 Team12P1' bypasses any PS script execution policy setting that may be set on that computer.  Then it runs the InstallPrinter.ps1 script and passes the Team12P1 variable to that script so it can look up the printer in the CSV file. Create separate batch files for each printer and change the variable to the DNS name of that printer.
    1. Create and input printer information into the printerlist.csv file.  Here is a sample:

    DNSName,DriverShare,DriverINF,DriverName,LastKnownIP,MakeModel,Supplies,Notes
    Team12P1,\\Team12server\printers\Drivers\HPOJP8630,hpvyt13.inf,HP Officejet Pro 8630,192.168.1.100,HPOJP8630,951XL,
    Team12P2,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P3,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P4,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P5,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP4015,64A,
    Team12P6,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP4015,64A,
    Team12P7,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJ600,90A,
    Team12P8,\\Team12server\printers\Drivers\HPOJP8630,hpvyt13.inf,HP Officejet Pro 8630,192.168.1.100,HPOJP8630,951XL,
    ,,,,,,,
    Team12P10,\\Team12server\Printers\Drivers\HPCLJ5520,hpc5520u.inf,HP Color LaserJet CP5520 Series PCL 6,192.168.1.100,HPCLJ5525,650A,USB and WiFi Only
    Team12L1,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,,HPLJ1102W,85A,
    Team12L2,,,,,EpsonWF3640,Epson252XL(BCYM),Ordering Manager
    
    • DNSName: Printer name DNS will use to search for an IP
    • DriverShare: Printer driver UNC folder location
    • DriverINF: Printer driver INF file located at the DriverShare location
    • DriverName: Exact printer name found within the Driver INF file
    • LastKnownIP: Static IP used to create a port when the printer and laptop are on different networks. You will have to create a new IP Port when the laptop is on the same network as the printer.
    • MakeModel: Not used in scripts but for your reference
    • Supplies: Not used in scripts but place to note what print cartridges each printer needs
    • Notes: Not used in scripts but provides general information
    1. Create the InstallPrinter.ps1 file referenced in the initial printer installation batch file.  Here is the script I use:

    #No 32-bit support
    $DNSName = $args
    $printerlist = import-csv \\server\printers\installscripts\printerlist.csv|? DNSName -eq $DNSName
    $DriverShare = $printerlist.drivershare
    $DriverINF = $printerlist.driverinf
    $DriverName = $printerlist.drivername
    $LastKnownIP = $printerlist.lastknownIP
    $IP = $LastKnownIP
    
    #Checking for old version of printer, then deleting it so new version can be added
    if ((gwmi win32_service|? name -match spool|select -expand state) -eq 'Stopped'){start-service spooler}
    if ((gwmi win32_printer|select -expand name) -contains $DNSName){
    #This will remove any spooled jobs then delete the printer with the old IP address
    if ((gwmi win32_service|? name -match spool|select -expand state) -eq 'running'){stop-service spooler}
    remove-item c:\windows\system32\spool\printers\*.* -force
    do {sleep 1}until((gwmi win32_service|? name -match spool|select -expand state) -eq 'Stopped')
    start-service spooler
    sleep 5
    $settings = gwmi win32_printer|? name -eq $DNSName|select *
    write-host "`nDeleting old printer installation`n"
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -d -p $DNSName
    $Oldport = $settings.portname
    write-host "`nDeleting old Port: $Oldport`n" -f blue
    $portmsg = cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -d -r $Oldport
    $d = cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -x
    }
    
    write-host ("Printer: " + $DNSName)-f green
    if ($IP.count -gt 0){write-host ("IP address: " + $IP)-f green}else{write-host ("No Active IP, using last known IP: " + $IP)-f red}
    write-host ("`n$DNSName will be available once this window disappears (approx. 3 minutes).`n") -f yellow
    $delprinters = cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -x
    cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m $DriverName -h $DriverShare -i ($DriverShare + "\" + $DriverINF)
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -a -r $IP -h $IP -o raw -n 9100
    #rundll32 printui.dll,PrintUIEntry /if /b $DNSName /r $IP /m $DriverName
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -a -p $DNSName -m $DriverName -r $IP
    if ((gwmi win32_printer|select -expand name) -contains $DNSName){write-host "`n$DNSName installed correctly!" -f green;sleep 5}
    

    Now you have a generic printer installation process that you can easily alter when you need to update IPs, Printer Names, or Printer Driver information.  As long as you've renamed your printers DNS names correctly, they should be found on any network subnet you share.  Also, the printerlist.csv file is easy to load into Excel and use for other things besides your installation scripts.

    Last note: In my scenario, I have this system connected to a Box account so all changes are backed up to the cloud and I can update these files from the cloud outside the local subnet/network.

    Friday, June 10, 2016

    PowerShell & Google Maps Time Zone API: Check and Change Computer Time using Internet Time

    I've been using WinPE to install images on new PC's and found that since Dell computers come from Texas, the Time Zone and PC clock time needs to be updated to my Time Zone. I'm probably over complicating this process but thought I'd share this anyway:

    #Google's time variable is based on the start date/time of 1/1/1970, universal time zone
    $startdatetime = [datetime]"1/1/1970 00:00:00Z"
    
    #getting local time and converting to universal time zone
    $currentdatetime = (get-date).touniversaltime()
    
    #Google time variable takes the 1/1/1970 date and wants the total seconds from that date to current time
    [int]$totalseconds = ($currentdatetime - $startdatetime).totalseconds
    
    #get a server key by signing up for the Google Maps Time Zone API 
    #read more here
    #note: location just has to be somewhere in your area/time zone
    $timezone = invoke-restmethod ("https://maps.googleapis.com/maps/api/timezone/json?location=46,-122" + "&Timestamp=" + $totalseconds + "&key=")
    $timezonename = $timezone.timezonename
    
    #since I live in Washington, I have the two possible time zones. Obviously you'll want to add/change time zones based on your location(s).
    if ($timezonename -eq "Pacific Daylight Time"){$TZDiff = -7}
    if ($timezonename -eq "Pacific Standard Time"){$TZDiff = -8}
    
    #Now I'm pulling local timezone information
    $tz = ([timezoneinfo]::local).id
    write-host "Local Timezone setting: $tz"
    
    #creating a variable in case the timezone is incorrect
    #The ref'd timezone.ps1 script is from Peter Henchley's blog
    $changetime = "e:\scripts\timezone.ps1 $timezonename"
    if ($tz -ne $timezonename){powershell -executionpolicy bypass $changetime;write-host "Changed Timezone" -f yellow}
    
    #Once the time zone has been adjusted, now we check for time
    #We pull current time from www.timeapi.org, convert it to universal time, and add our time zone difference so it equals our current time zone
    $webtime = (([datetime](iwr http://www.timeapi.org/utc/now -usebasicparsing).content).touniversaltime()).addhours($TZDiff)
    $localhour = (get-date).hour
    if ($localhour -ne $webtime.hour){set-date $webtime;write-host "Changed Local Time" -f yellow}
    

    An example of a Google Map Time Zone API reply

    dstOffset    : 3600
    rawOffset    : -28800
    status       : OK
    timeZoneId   : America/Los_Angeles
    timeZoneName : Pacific Daylight Time
    

    Let me know if you know of a better method of checking for time zones and time without using local computers or domain servers.

    Wednesday, October 14, 2015

    PowerShell: Remove Windows 7 Telemetry Updates (Windows 10 Privacy Issue)

    Windows 10 is violating user privacy.  Microsoft is retrieving too much personalized information about each person using Windows 10.  They've also created similar privacy violating security patches for Windows 7.  The following is a PowerShell script I created to remove the violating "security updates."

    #Retrieve all Windows updates
    $updates = wmic qfe list /format:csv|convertfrom-csv

    #Search through update list and remove each violating update
    if ($updates.hotfixid -like "*2990214*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:2990214 /norestart"}

    if ($updates.hotfixid -like "*2952664*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:2952664 /norestart"}

    if ($updates.hotfixid -like "*3021917*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3021917 /norestart"}

    if ($updates.hotfixid -like "*3022345*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3022345 /norestart"}

    if ($updates.hotfixid -like "*3035583*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3035583 /norestart"}

    if ($updates.hotfixid -like "*3068708*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3068708 /norestart"}

    if ($updates.hotfixid -like "*3075249*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3075249 /norestart"}

    if ($updates.hotfixid -like "*3080149*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /kb:3080149 /norestart"}

    #End of Script

    If you want to automate the hotfix removal process, add a "/quiet" to the argumentlist.  For example: 
    if ($updates.hotfixid -like "*3080149*"){start-process "c:\windows\system32\wusa.exe" -wait -nonewwindow -argumentlist "/uninstall /quiet /kb:3080149 /norestart"}

    Each security update found will pop-up this first window:

    Then it will prompt you to confirm the removal of the update:

    Lastly, it removes the update:









    After running this script, you'll need to restart your computer. Ensure to hide these updates when Windows Updater wants to add them back into your computer.

    Thursday, April 16, 2015

    PowerShell: Box.com Drive Mapping via DAV

    Thanks to a couple of web articles I found (1,2), I'm now able to connect to my Box.com account as a drive letter.

    tl;dr:
    net use b: \\dav.box.com@SSL\dav /u:boxuser boxpassword

    Whole script:
    $password = "your embedded & encrypted Box password"

    $pscred = New-Object PSCredential -ArgumentList "yourboxaccount@mail.com", ($password | ConvertTo-SecureString)

    #Checking if a DAV connection exists and if not, then creating one and assigning it Drive B:

    if (get-psdrive|? {$_.currentlocation -like "Your Box Root Folder\Some Box Subfolder*"}){$drive = get-psdrive|? {$_.currentlocation -like "Your Box Root Folder\Some Box Subfolder*"}|select -expandproperty root}else{net use b: \\dav.box.com@SSL\dav /u:yourboxaccount@mail.com $pscred.getnetworkcredential().Password;$drive = "B:\"}

    Now you can use Robocopy instead of "Box Sync" to sync your Box.com data:
    robocopy "\\server\share\content" ($drive + "Your Box Root Folder\Some Box Subfolder") /s /e /v
    robocopy ($drive + "Your Box Root Folder\Some Box Subfolder") "\\server\share\content" /s /e /v

    Sunday, December 21, 2014

    PowerShell: Using SNMP for HTML Network Printer Report

    Managing network printers scattered throughout numerous locations is challenging when ensuring each location has replacement ink at the appropriate time.  A stopped printer loses production time and so there should be an easy way to capture current information about all network printers in a easy-to-use/share format.  As HTML is accepted by any computer and device, I thought it'd be best to use that format.

    I've been searching for a way to aggregate the printers websites in order to create a solution but that didn't work so I wondered if I could pull information via a "public" SNMP connection using PowerShell.  After many online searches, I found someone calling on the ComObject ole.Prn.OleSNMP.  

    $SNMP = new-object -ComObject olePrn.OleSNMP



    The SNMP object has a slight variation of the standard SNMP syntax.  The GetTree function is AKA SNMPWalk to those familiar with SNMP commands.  

    $snmp.open("192.168.0.28","public",2,3000)
    defined: (IP,account,how many attempts, how long before timeout)



    Once connected, use the GetTree to find out information about the area you want in your report.  In my example, I'm querying for the maximum volume of toner.

    $snmp.gettree("43.11.1.1.8.1")

    The OIDFromString function converts a name to its OID location.



    For instance:

    $snmp.OIDFromString(".iso.org.dod.internet.mgmt.mib-2.system.sysDescr")



    To capture an object:
    $printertype = $snmp.Get(".1.3.6.1.2.1.25.3.2.1.3.1")

    Since SNMP is a standard, most objects are in the same location across vendors. One area I found variance is the toner/waste container location. In printers with only one toner cartridge and no waste container, it's a standard:

    $tonername = $snmp.get("43.11.1.1.6.1.1")
    $tonercapacity = $snmp.get("43.11.1.1.8.1.1")

    $currentvolume = $snmp.get("43.11.1.1.9.1.1")

    Example of multi-cartridge printer (notice the last digit):

    $blacktonercapacity = $snmp.get("43.11.1.1.8.1.1")
    $blackcurrentvolume = $snmp.get("43.11.1.1.9.1.1")
    [int]$blackpercentremaining = ($blackcurrentvolume / $blacktonercapacity) * 100 
    $cyantonervolume = $snmp.get("43.11.1.1.8.1.2")
    $cyancurrentvolume = $snmp.get("43.11.1.1.9.1.2")
    [int]$cyanpercentremaining = ($cyancurrentvolume / $cyantonercapacity) * 100
    $magentatonervolume = $snmp.get("43.11.1.1.8.1.3")
    $magentacurrentvolume = $snmp.get("43.11.1.1.9.1.3")
    [int]$magentapercentremaining = ($magentacurrentvolume / $magentatonercapacity) * 100
    $yellowtonervolume = $snmp.get("43.11.1.1.8.1.4")
    $yellowcurrentvolume = $snmp.get("43.11.1.1.9.1.4")
    [int]$yellowpercentremaining = ($yellowcurrentvolume / $yellowtonercapacity) * 100
    $wastetonervolume = $snmp.get("43.11.1.1.8.1.10")
    $wastecurrentvolume = [math]::round([math]::abs($snmp.get("43.11.1.1.9.1.10")))

    [int]$wastepercentremaining = (($wastecurrentvolume / $wastetonercapacity) * 100)

    Amongst the printers, all have their error status location in the same OID.  Here's how I filtered my printers:

    $statustree = $snmp.gettree("43.18.1.1.8")
    $status = $statustree|? {$_ -notlike "print*"} #status, including low ink warnings

    $status = $status|? {$_ -notlike "*bypass*"}

    That's the basics to extracting printer information via SNMP.  Here's how to explore your printers information using the free SNMP software which helped me out.
    http://www.manageengine.com/products/mibbrowser-free-tool/

    Clear out all the MIBs in the module area then File, Open the Printer MIB.
    Once the Printer MIB has been loaded, start exploring by opening the tree and finding an area of interest.  Right click on the folder and select SNMPWALK.
    Here's an example of results of an OID folder search.
    If you right-click on the folder and select "MIB Description", it'll give the OID location.  Notice the .1.3.6.1.2.1.43.1.1, that will be used in your script.
    Here I've copied/pasted the OID into my command line.  Notice the difference between the GUI and command line.  It's easy to navigate once you get to figuring out the structure.

    Once you've found the SNMP information you'd like to report about, then it's time to build an input file and script.  This is how I've built my solution, obviously there are several other methods to extracting and reporting this information.

    Input text file (printerlist.txt):

    192.168.0.236,PX_SPS_FIN_BW,Finance Printer
    192.168.0.237,PX_SPS_FP_COLOR,Forest Practices
    192.168.0.238,PX_SPS_MFC1,Main Color Copier
    192.168.0.254,PH_SPS_PLT,Plotter
    -Mineral
    192.168.1.250,PX_MIN_BW
    192.168.1.235,PX_MIN_MFC

    Here's my script so you can download and customize for your use:

    What you'll see when running the report (note that the printer names are coming directly from SNMP):


    Script:
    (By the way, I style my PowerShell scripts as if they were DOS batch files.  I've been writing scripts since DOS 5.0/Novell 3.x using DOS Edit and Windows Notepad.  Some habits are hard to break so thus this script is not in the typical PS script layout.)
    In this example, I only give one printer 'if' statement.  You'll have to use the $printertype = $snmp.Get(".1.3.6.1.2.1.25.3.2.1.3.1") to gather printer type information for your 'if' statements:

    $printerlist = import-csv .\printerlist.txt -header Value,Name,Description
    $outfile = .\Printers.html
    $SNMP = new-object -ComObject olePrn.OleSNMP
    $total = ($printerlist.value|? {$_ -notlike "-*"}).length

    Write "`
    <html>`
    <head>`
    <title>Printer Report</title>`
    <style>* {font-family:'Trebuchet MS';}</style>`
    </head>`
    <body>"|out-file $outfile

    write "Reporting on $total printers"
    $x = 0

    foreach ($p in $printerlist){

    if ($p.value -like "-*"){write "<h3>",$p.value.replace('-',''),"</h3>"|add-content $outfile}

    if ($p.value -notlike "-*"){

    $x = $x + 1
    $printertype = $nul
    $status = $nul
    $percentremaining = $nul
    $blackpercentremaining = $nul
    $cyanpercentremaining = $nul
    $magentapercentremaining = $nul
    $yellowpercentremaining = $nul
    $wastepercentremaining = $nul

    if (!(test-connection $p.Value -Quiet -count 1)){write ($p.value + " is offline<br>")|add-content $outfile}
    if (test-connection $p.value -quiet -count 1){
    $snmp.open($p.value,"public",2,3000)
    $printertype = $snmp.Get(".1.3.6.1.2.1.25.3.2.1.3.1")
    write ([string]$x + ": " + [string]$p.Value + " " + $printertype)
    }

    if ($printertype -like "*WorkCentre 5655*"){

    $tonervolume = $snmp.get("43.11.1.1.8.1.1")
    $currentvolume = $snmp.get("43.11.1.1.9.1.1")
    [int]$percentremaining = 100 - (($currentvolume / $tonervolume) * 100) 

    $statustree = $snmp.gettree("43.18.1.1.8")
    $status = $statustree|? {$_ -notlike "print*"} #status, including low ink warnings
    $status = $status|? {$_ -notlike "*bypass*"}
    $name = $snmp.get(".1.3.6.1.2.1.1.5.0")
    if ($name -notlike "PX*"){$name = $p.name}

    write ("<b>" + $p.description + "</b><a style='text-decoration:none;font-weight:bold;' href=http://" + $p.value + " target='_new'> " + $name + "</a> <br>" + $printertype + "<br>")|add-content $outfile
    if ($percentremaining -gt 49){write "<b style='font-size:110%;color:green;'>",$percentremaining,"</b>% black toner<br>"|add-content $outfile}
    if (($percentremaining -gt 24) -and ($percentremaining -le 49)){write "<b style='font-size:110%;color:#40BB30;'>",$percentremaining,"</b>% black toner<br>"|add-content $outfile}
    if (($percentremaining -gt 10) -and ($percentremaining -le 24)){write "<b style='font-size:110%;color:orange;'>",$percentremaining,"</b>% black toner<br>"|add-content $outfile}
    if (($percentremaining -ge 0) -and ($percentremaining -le 10)){write "<b style='font-size:110%;color:red;'>",$percentremaining,"</b>% black toner<br>"|add-content $outfile}
    if ($status.length -gt 0){write ($status + "<br><br>")|add-content $outfile}else{write "Operational<br><br>"|add-content $outfile}
    }
    }
    }

    write "</body></html>"|add-content $outfile

    &$outfile

    Sample output:








    Wednesday, March 26, 2014

    PS1X + DareCup = Browser-based DameWare Remote Access

    I've been developing a PowerShell-based website with software created by www.powershellserver.com.  The product is PowerShell ASP and is a combination of PowerShell, ASP, and HTML.  It's great for aggregating data from SharePoint, SCCM, PC's via RWMI, and various intranet sites and spreadsheets.  I recently pulled in the agency inventory and thought it'd be great when a customer calls in to pull up their PC number via username then click on a DameWare link.  This has been a problem as the website runs under the system account so any server-side calls stay within the system account and give GUI.  Today I found a gem on the Internet.  The little program is named DareCup.  Double-click on the installer and it asks where your DameWare Remote Control software is, copies the darecup.exe file to the folder, then writes two registry entries which add a Protocol Handler.  The handler works with both Internet Explorer and Chrome.  I had to manually go into the Chrome Protocol Handler section (even though there were no entries), close the menu, then it worked.  When writing code, simply place a <a href=rc://computername>DameWare</a> and the handler redirects the call to DameWare which opens the GUI.  You can even go so far as to enter your username and password plus RDP protocol if you wish.

    Here's the article I was reading when I found the link:
    http://community.spiceworks.com/how_to/show/1794-dameware-mini-remote-spiceworks-integration

    and some instructions from the site.  The DareCup download also comes with instructions and a code sample.
    rc:// -The DareCup URL Handler
    #{ip_address} -variable from Spiceworks/Dynamic Troubleshooting Action Link (#{name} could also be used instead of #{ip_address})
    username=YOUR_USERNAME -username for Dameware
    password=YOUR_PASSWORD -password for Dameware
    domain=YOUR_DOMAIN -domain for Dameware
    Monitor=viewonly -starts Dameware in view only mode
    Connectiontype=autoconnect -attempts to automatically connect when started
    Closeondisconnect=autoclose -when disconnecting it closes Dameware

    Here's an example of how I use this utility to open a DameWare connection via weblink:

    <a title='Dameware' href='rc://targetcomputer>?domain=MyDomain&username=MyUserName&password=MyPassword&connectiontype=autoconnect&Closeondisconnect=autoclose&-a:1'><img style="margin:0px 0px 0px 5px;vertical-align:text-top;" src=/images/dw.png width=17></a>

    Note that I've added a -a:1 to the end of the GET method.  Even though DareCup doesn't know what it means, it still accepts the variable and passes it to DameWare for processing.  The -a stands for Authentication and type 1 means authenticate via NT Challenge (Active Directory/Windows SAM).

    To use:
    * Download the DareCup zip package and extract.
    * Using your admin account, install DareCup.  It will ask where your DameWare Remote software is located.
    * When finished, your web browser will redirect RC:// calls to the DareCup application.  In Chrome, it'll pop up with an external Protocol prompt:














    Saturday, February 22, 2014

    PowerShell: Downloading SCCM 2012 ReportServer Report CSV's

    The SCCM 2012 Reports interface is cumbersome for quickly pulling information together.  Instead, I updated my SCCM 2007 SQL server web-reporting technique.  I found it worked great and now can download reports as CSV's and use them in PowerShell scripts.

    Here's an example:

    invoke-webrequest "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fAsset+Intelligence%2fSoftware+02E+-+Installed+software+on+a+specific+computer&Name=$ComputerName&rs:Command=Render&rs:Format=CSV&rc:Toolbar=False" -credential $creds -outfile $destination 

    This will download a report about all of the software loaded on one computer and place it into a CSV file.  All you'd have to do is $software = import-csv $destination 

    Another example reports about all the software that starts when the computer is powered on:
    iwr "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fAsset+Intelligence%2fSoftware+04C+-+Software+configured+to+automatically+run+on+a+specific+computer&Name=$ComputerName&rs:Command=Render&rs:Format=CSV&rc:Toolbar=False" -credential $creds -outfile $autodestination

    A third example reports about what computers and IPs are currently on a subnet:

    iwr -credential $creds "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fNetwork%2fIP+-+Computers+in+a+specific+subnet&variable=192.168.0.0&rs:Command=Render&rc:toolbar=false&rs:Format=CSV" -outfile $oursubnet

    Here I get the network card information for a computer:
    iwr -credential $creds "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fHardware+-+Network+Adapter%2fNetwork+adapter+information+for+a+specific+computer&variable=$ComputerName&rs:Command=Render&rc:toolbar=false&rs:Format=CSV&quo t; -outfile $NICDestination

    A report about the users of a certain computer:
    iwr -credential $creds "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fAsset+Intelligence%2fHardware+05A+-+Console+users+on+a+specific+computer&Name=$ComputerName&rs:Comm and=Render&rc:toolbar=false&rs:Format=CSV" -outfile $cache

    A computer hardware report about a certain computer:
    iwr -credential $creds "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fHardware +-+General%2fComputer+information+for+a+specific+computer&variable=$ComputerName&rs:Command=Render&rc:toolbar=false&rs:Format=CSV" -outfile $HWDestination

    Disk information report about a certain computer:

    iwr -credential $creds "http://sccmserver/ReportServer?%2fConfigMgr_NR1%2fHardware +-+Disk%2fDisk+information+for+a+specific+computer+-+Physical+disks&variable=$ComputerName&rs:Command=Render&rc:toolbar=false&rs:Format=CSV" -outfile $diskdestination


    Monday, November 25, 2013

    CMD: Install Windows 7 IP-based Printers via batch file

    IT Departments debate over Server-based and IP-based direct printing.  I use IP-based printing as a way to lower WAN traffic, negate at least two points of failure, and speedup user response/print time.  Microsoft has developed some fine printer scripts they introduced in Windows XP.  They further polished these scripts in Windows 7 and placed them into their own printing_admin_scripts subfolder.  I'm sharing my sample script and giving a quick explanation of each command.  For more details about the Microsoft VB script switches, visit Microsoft's TechNet site or use Notepad to read the syntax notes placed inside each VBS file.

    REMARK                   --- Start of Script ---

    REMARK Added a script title so I know what printer I'm installing

    echo *** Installing Canon iPF720 Plotter ***

    REMARK Remove old printer presence via PowerShell registry search

    PowerShell "if (test-path 'hklm:\software\microsoft\windows NT\currentversion\Print\Printers\HP DesignJet 1050C Plotter'){cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -d -p 'HP DesignJet 1050C Plotter'}"

    REMARK Checking for processor type then installing appropriate driver
    REMARK AMD64 works with all typical Windows useable 64-bit processors

    if %processor_architecture% equ AMD64 (cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m "Canon iPF720" -h "\\server\share\Printers\Drivers\Canon iPF720\64-bit\Driver" -i "\\server\share\Printers\Drivers\Canon iPF720\64-bit\Driver\6WJF02M.INF") else (cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m "Canon iPF720" -h "\\server\share\printers\Drivers\Canon iPF720\Driver" -i "\\server\share\printers\Drivers\Canon iPF720\Driver\2WJF02M.INF")

    REMARK Adding the IP port the new printer will use

    cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -a -r "CanoniPF720" -h 192.168.1.100 -o raw -n 9100

    REMARK Putting the Friendly name, driver, and port together

    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -a -p "Canon iPF720 Plotter" -m "Canon iPF720" -r "CanoniPF720" 

    REMARK Added a 10 second pause so I can chain install scripts together yet still monitor each installation progress

    timeout /t 10

    REMARK                   --- End of Script ---

    I also thought about adding an audible prompt when things go right or wrong.  This would lessen the need to physically watch the install but rather allow multitasking by listening out for the correct sounds after each install while performing other duties.