Wednesday 4 July 2012

DOS: Disconnect from ALL Citrix sessions with one batch file

I am pretty happy with myself for coming up with this.  It did take awhile, but it's working.

First let me start off by saying that we are concerned with the security aspect with keeping information safe but we need to also provide a suitable workflow to help facilitate others with ease of use and help broaden the functionality of the tools they already use.

Here is the Batch file contents.
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /f %%A in ('QFARM ^| find "*"') DO (
        SET curSERVER=%%A
        SET curSERVER=!curSERVER:~0,-1!)
for /f %%A in ('QFARM ^| find "CITRIX"') DO (
        SET SERVER=%%A
        SET lastCHAR=!SERVER:~-1!
        IF NOT !lastCHAR! == * for /f "skip=1 tokens=2" %%B in ('QUSER %USERNAME% /SERVER:!SERVER!') DO (
        tsdiscon %%B /SERVER:!SERVER!
         )
)
for /f "skip=1 tokens=2" %%A in ('QUSER %USERNAME%') do (
        tsdiscon %%A /SERVER:%curSERVER%)
An important note:  This is run from within Citrix... I found that when using the QUERY command locally you don't have access to the QFARM command, but in a Citrix context you do.  We also needed to run this within Citrix because we have generic logins in some locations that act as thin clients, so the %USERNAME% variable would not be effective in this case.

tsdiscon is a great tool that was overlooked initially.

Firstly we wanted to find out what the current server we are on is.  This was necessary because if you end up disconnecting from the server you are running this from, it stops.

Secondly... we loop through the output of the QFARM command finding "CITRIX"... if you have different naming conventions, you just have to massage that a little and it's good to go.

QFARM by itself spit output with the citrix servers and one of the servers has an asterisk at the end... this is one that we want to skip over until the end...  its the %curSERVER% variable.

From there on you can see... we loop through the servers finding the ica-tcp#... sessions and use that to disconnect from each of the servers.

I hope this is informative and helps you out!

Wednesday 20 June 2012

Python: Let Domain User's manage themselves

Not sure if that's a great idea ;)

I am always trying to find ways to help the 1st level support guys, they get lots of calls and when the calls pile up, I remember it being quite annoying.

So here is what I created.  Hope you enjoy!  Now obviously you need to make a few changes to make it work for you, but this little tool allows domain users with little access the ability to Add/ Remove users from groups that they are managers of. 




Heres what you need:

Active Directory;
User account; must be a member of the group as well as selected in the Managed By tab, check the box that says Manager can update the group and you are set.

*note I have images in the current directory, so be sure to change those around as well.
'''
Created on Jun 14, 2012

@author: rcummins
'''
import active_directory as AD
from Tkinter import *
from os import environ
import ttk
import win32com, win32com.client
import pythoncom
import tkMessageBox
from PIL import Image, ImageTk

login = environ["USERNAME"]
manager = []
 
LOGIN = AD.find_user(login)
grps = {}
for group in LOGIN.memberOf:
    GROUP = AD.AD_object(group)
    if str(LOGIN)[7:] == str(GROUP.managedby):
        GRP = AD.AD_object(group)
        grps[GRP.cn] = GRP.distinguishedName
        manager.append(str(GRP.cn))
   
root = Tk()
root.title("Manager Console")

root.wm_iconbitmap('mgmt.ico')


master = PanedWindow(orient=VERTICAL)
master.pack(fill=BOTH, expand=1)

userframe = LabelFrame(master, text='Groups Managed By: %s'%(LOGIN.cn))

fr = Frame(userframe)
userinfo = Label(fr, text='Manager of: ')
userinfo.pack(side=LEFT, padx=5, pady=10)
usergroups = ttk.Combobox(fr, values=manager, width=30)
usergroups.pack(side=LEFT, fill=X, expand=1, padx=5)

type=None
if(len(manager)>0):
    usergroups.set(manager[0])
    ggrp = AD.find_group(manager[0])
    type = AD.AD_object(ggrp)
grouptype = Label(userframe, text="No group(s) found..")
if(type):
    grouptype = Label(userframe, text="Description: %s"%(ggrp.description))
fr.pack(side=TOP)
grouptype.pack(side=TOP, padx=5)
master.add(userframe)

groupframe = LabelFrame(master, text='Group Detail and Modification')
groupinfo = Listbox(groupframe, height=20, width=30)
groupinfo.pack(side=LEFT, padx=5, pady=10)
controlframe = Frame(groupframe)
controlframe.pack(side=LEFT, padx=5, fill=BOTH)

master.add(groupframe)
def ADDUser(event=None):
    geo = root.winfo_pointerxy()
    xx = geo[0]
    yy = geo[1]
   
   
    TOPr = Toplevel()
    TOPr.title("Add a user to this group")
    TOPr.geometry("+%d+%d"%(xx,yy))
   
    x = Label(TOPr, text="Enter username:")
    x.pack(side=TOP, fill=X, padx=10)
    f = Frame(TOPr)
    em = Label(f, text="@WORK.com")
    em.pack(side=RIGHT)
    uname = Entry(f, width=15)
    uname.pack(side=RIGHT)
    f.pack(side=TOP, padx=10)
       
    def plusONE(event=None):
        if len(str(uname.get()))>0:
            usr = AD.find_user(str(uname.get()).strip())
            grp = AD.find_group(str(usergroups.get()).strip())
            uLDAP = "LDAP://%s"%(str(usr.distinguishedName))
            gLDAP = "LDAP://%s"%(str(grp.distinguishedName))
            try:
                grp_obj = win32com.client.GetObject(gLDAP)
                grp_obj.Add(uLDAP)
                #grp_obj.Remove(uLDAP)
                grp_obj.SetInfo()
                groupinfo.insert(END, usr.cn)
            except pythoncom.com_error,( hr,msg,exc,arg ):
                print "Error adding user %s to group %s..." % (usr.cn, grp.cn)
                print hr, msg, exc, arg
            #http://code.activestate.com/recipes/511447-add-account-to-group-in-active-directory/
    addButton = Button(TOPr, text='Add User', command=plusONE)
    addButton.image = photo
   
    addButton.pack(side=TOP, fill=X)
    root.update()
    TOPr.mainloop()

img = Image.open(r"business_user.png")
photo = ImageTk.PhotoImage(img)
addBTN = Button(groupframe, compound=TOP, image=photo, text='Add User', command=ADDUser)
addBTN.pack(side=TOP)


def DELUser(event=None):
    usr = AD.find_user(str(groupinfo.selection_get()).strip())
    grp = AD.find_group(str(usergroups.get()).strip())
    uLDAP = "LDAP://%s"%(str(usr.distinguishedName))
    gLDAP = "LDAP://%s"%(str(grp.distinguishedName))
    try:
        grp_obj = win32com.client.GetObject(gLDAP)
        #grp_obj.Add(uLDAP)
        xray = tkMessageBox.askokcancel("Delete User from Group", "Are you sure you want to delete: %s from %s"%(usr.cn, grp.cn))
        print xray
        if(xray):
            grp_obj.Remove(uLDAP)
            grp_obj.SetInfo()
    except pythoncom.com_error,( hr,msg,exc,arg ):
        print "Error adding user %s to group %s..." % (usr.cn, grp.cn)
        print hr, msg, exc, arg
        #http://code.activestate.com/recipes/511447-add-account-to-group-in-active-directory/
    root.update()
    groupname = usergroups.get()
    usrs = []
    for groupmbr in AD.find_group(groupname).member:
        usrs.append(str(groupmbr.cn))
    usrs.sort()
    groupinfo.delete(0, END)
    for usrer in usrs:
        if usrer != usr.displayName:
            groupinfo.insert(END, usrer)
    return

img2 = Image.open(r"business_user_delete.png")
photo2 = ImageTk.PhotoImage(img2)
delBTN = Button(groupframe, compound=TOP, image=photo2, text='Remove User', command=DELUser)
delBTN.pack(side=TOP)

master.add(groupframe)

def SelectDropdown(event=None):
    if(usergroups.get()):
        groupname = usergroups.get()
        usrs = []
        for groupmbr in AD.find_group(groupname).member:
            usrs.append(str(groupmbr.cn))
        usrs.sort()
        groupinfo.delete(0, END)
        for usrer in usrs:
            groupinfo.insert(END, usrer)
        root.update()
usergroups.bind("<<ComboboxSelected>>", SelectDropdown)
SelectDropdown()
root.mainloop()

As always, I accept constructive feedback, so if it could be cleaner, please let me know! always looking for feedback.

Monday 18 June 2012

Python: Backup your data on the fly

I have been bitten before, and so to prevent any unforeseen loss of data, I set out to create something of the sort.

I did it.  And I am quite proud of it.  Even though its not perfect... the concept is pretty rad.

Things you will need.

  1. Python [Modules] - wmi, shutil, os, sys, winpaths(optional....)
  2. TaskScheduler
  3. USB or SD card, need to change its name to eBackup, instead of "Removable Disk"
The basic idea is to:
  • have a scheduled task run when the system is on idle...
  • only runs when a drive is present that is labeled eBackup
  • copy directories, specified in a cfg file.
Here is the code for this project:

'''
Created on Apr 30, 2012
@author: rcummins
'''
import wmi
import shutil
import os
import winpaths
import sys
def getDrive(computer=None):
    c = wmi.WMI(computer)
    host_info = c.Win32_LogicalDisk(VolumeName='EBACKUP')
    return host_info[0].Name
def fileChange(source):
    drive = getDrive()
    for dirs in os.listdir(source):
        path = source+'\\'+dirs
        dest = path.replace("C:\\", drive[0]+":\\")
        if os.path.getmtime(dest) - os.path.getmtime(path) < 0:
            shutil.copytree(path, dest)
if __name__ == '__main__':
    computer = ''
    logfile = ''
    x = getDrive(computer)
    try:
        logfile = str(sys.argv[1]).strip()
    except:
        logfile = 'eBrake.cfg'
    if os.path.exists(logfile):
        f = open(logfile,'r')
        for q in f.readlines():
            source = q.strip()
            for(path, dirs, files) in os.walk(source):
                for filez in files:
                    src = os.path.join(path, filez)
                    dst = str(os.path.join(path, filez)).replace("C:\\",x[0]+":\\")
                    if str(src).find(".metadata") < 0:
                        try:
                            if os.path.getmtime(dst) - os.path.getmtime(src) < 0:
                                print "Overwriting >> " + dst
                                shutil.copy(src, dst)
                        except:
                            print "Created: " + dst
                            if not os.path.exists(dst): os.makedirs(dst)
                            try:
                                shutil.copytree(src, dst)
                            except: shutil.copy(src, dst)
    else:              
        print "Create file: %s \n\n Enter paths to backup on SD card\n\ncard needs to be named 'EBACKUP'"%(logfile)
        pass                   
I hope this has either inspired you or saved your data.  Enjoy!

Thursday 14 June 2012

Python: Breaking apart large files into smaller chunks

Something that I find really neat with Python is its flexibility and strong support in the online community.  I found a really good example somewhere on how to do this and I adapted it to my own needs...  like most programmers ;)
import os
def UnpileFile(src, outPATH, parts):
    if not os.path.isdir(outPATH): os.mkdir(outPATH)
    f = open(src, 'rb')
    data = f.read()
    f.close()
    byts = len(data)
    inc = (byts+4)/int(parts)
    filenames = []
    for i in range(0, byts+1, inc):
        fn1 = outPATH + "\\file %s" % i
        filenames.append(fn1)
        f = open(fn1, 'wb')
        f.write(data[i:i+inc])
        f.close()
def CompileFile(srcPATH, outFILE):
    if not os.path.isdir(srcPATH): os.mkdir(srcPATH)
    dataList = []
    for root, dirs, files in os.walk(srcPATH):
        for fn in files:
            f = open(str(root+'\\'+fn), 'rb')
            dataList.append(f.read())
            f.close()
    f = open(outFILE, 'wb')
    for data in dataList:
        f.write(data)
    f.close()
if __name__ == '__main__':
    pass
There's not much to import which is a plus... ;)

So say you had an ISO image... you only have 2 2gb usb drives?  no problem... break these guys up into 2 parts by saying;
src = the path to the ISO you want to break up
outPATH = the directory you want to save the broken pieces to
parts = the number of parts you want the files split into
UnpileFile(src, outPATH, parts)


















And to put humpty dumpty back together again... so to speak... you just say:

srcPATH = the directory that has the broken files
outFILE = the name you want to give your patched up ISO...
CompileFile(srcPATH, outFILE)
*NOTE... I am pretty sure I specified mkdir and not makedirs, there is a difference...

http://docs.python.org/library/os.html?highlight=os.mkdir#os.mkdir

Android: Learning to walk... and then programmatically add TableRows to a TableLayout

I have had some long spent nights trying to learn developing for Android... LayoutParams... oh you light of my life, LayoutParams...

One recent problem I have been facing is the TableRow widget I intend on populating with data scraped from the web...  store it in a ArrayList<String> and pop it into the TableRow as necessary.

I did buy an idiots guide to Android Development... and I gently set it aside and started Google-ing how to accomplish what I wanted an android app to do.  If you are struggling, Google is your friend...  and just like real life... some friends take you down the wrong path, and others have just what you need.

http://stackoverflow.com/questions/3200691/dynamically-add-tablerow-to-tablelayout

import android.widget.TableRow.LayoutParams;
//import android.widget.RelativeLayout.LayoutParams; 

Just like dfetter88 mentions in his/her answer... ensure you are importing the right thing.

So the background, before getting into the gritty for loop, is that I have scraped data from the web and stored it into an arraylist.  So here's my scratch;
ArrayList<String> prices = getPrice (doc);
for(int i =0; i<prices.size(); i++)
{
    Log.d("PRINT", prices.get(i));
    //RelativeLayout RLay = new RelativeLayout(getParent());
    TableRow TR = new TableRow(getApplicationContext());
    TR.setId(10);
    TR.setLayoutParams(lp);
    TextView price = new TextView(getApplicationContext());
    price.setId(20);
    price.setLayoutParams(lp);
    price.setText(prices.get(i));
    TR.addView(price);
    TLay.addView(TR, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
I had a difficult time wrapping my head around the context argument.  Because this for-loop was triggered by a button click, the context was changed and you couldn't use the term THIS...  which refers to the current object...  and the current object in that situation is BUTTON...  so you can't very well create a new TableRow within the Button context, so I had to use getApplicationContext()...

I think that is explained right, but then again... I really SHOULD read the Android Developer book.

Another really cool trick I learned is to import the Log "module"
import android.util.Log;
This will help you troubleshoot issues while you are testing.  you use it like this;

Log.d("LEVEL1","about to go through the loop... buckle up.");
 LEVEL1 is just the Tag you can assign to the log...  makes it really handy.  Eclipse is a super powerful tool that you definitely need to have if you want to explore android development... There are at least a gajillion resources at your disposal.

Here's where you go to get started: http://developer.android.com/guide/index.html  Do it up.





Wednesday 13 June 2012

VBScript: XP only!: Find Computer by User Name

When I was working for "The helpdesk" a long time ago... I would always forget to write down the computer name and it seemed to be taking more time than it should just to get that info back... I sometimes called the end user... I was looking online and actually didn't find anything until I ran into an old classmate who had a huge script that he sent me, it was really awesome, filled with SUBS and whatnot.

Here's the bare necessity:

Dim inputStr, UserName, Domain, splitInput, sName, oArgs, Session
Dim oUser, userFullName, userHome, fService, LoggedOn, q, ss
'On Error Resume Next
q = Chr(34)
Domain = "Domain"
username = inputbox("Enter username: ")
Set oUser = GetObject("WinNT://" & Domain & "/" & UserName & ",user")

userFullName = oUser.FullName
userHome = oUser.HomeDirectory
sName = Split(userHome, "\")

Set fService = GetObject("WinNT://" & Domain & "/" & sName(2) & "/LanmanServer")
Set ss = fService.Sessions
For Each Session In ss
If LCase(Session.User) = LCase(UserName) Then
LoggedOn = LoggedOn & vbcr & Session.Computer
End If
Next
If LoggedOn = "" then
msgbox "User " & q & UserName & q & " (" & userFullName & ") is not logged on.", 64, "Query:"
Else
MsgBox "User " & q & UserName & q & " (" & userFullName & ") logged on to the following workstations: " & vbcr & vbcr & LoggedOn, , "Query:"
End If

One of the cool things about this script is that it doesn't return the first one it finds, it returns a list of them.

So you may find a bunch of Citrix Servers.  I have found it to be flaky at times and have never been able to get this to work with Windows 7...  I think because of the LanmanServer part.

Anyways, enjoy!

VBScript: Shutdown / Reboot workarounds

Every now and then I find myself trying to script the silliest things.

I was really annoyed at how when you are using Remote Desktop to connect to a workstation, the Shutdown / Reboot option is replaced by the Disconnect option... I think it's probably a safe guard, which is nice to have, but I like to have the option.

I created a VBScript on my desktop called Shutdown.vbs; its remarkably simple.

Set OpSysSet = GetObject("winmgmts:{(Shutdown)}//./root/cimv2").ExecQuery("select * from Win32_OperatingSystem where Primary=true")
for each OpSys in OpSysSet
x = InputBox("Reboot or Shutdown?", "Reboot or Shutdown?", "Shutdown")
if Left(x, 1) = "R" Then
OpSys.Reboot()
end if
if Left(x, 1) = "S" Then
OpSys.Shutdown()
end if
next
the section that contains
x = InputBox("Reboot or Shutdown?", "Reboot or Shutdown?", "Shutdown")
can be modified; if you change the last parameter, you can set it to "Reboot"

like I mentioned, its not overly complicated, but I found it annoying to keep typing
shutdown -s -t 1 or shutdown -r -t 1

*Note... when showing this to people from a remote location, be sure you really want to shutdown... otherwise you risk taking the walk of shame and force yourself to either call somebody there to turn it back on or do what every System Admin hates doing... get up and do it yourself.

Tuesday 12 June 2012

Python: Preventing an application from exiting.

I overheard somebody complaining that a program needs to be "Always open" and that the "Stinkin' Users" always close it causing issues down the line...

This can be really easy to fix... create a watcher with the WMI module for python and when the event is triggered, open the program again... then call the 'def' again recursively so the watcher program stays open all the time...  I don't think that's very clear to them, so I just said I could make something for them.

Heres what it looks like:

'''
Created on Feb 13, 2012
@author: rcummins
'''
import wmi
import subprocess
def ohnoyoudidnt():
    c = wmi.WMI()
    watcher = c.watch_for (
                               notification_type="Deletion",
                               wmi_class="Win32_Process",
                               delay_secs=1,
                               Name="application.exe"
                               )
    watcher ()
    exe_path = r'C:\Program Files\application.exe'
    subprocess.Popen(exe_path)
    ohnoyoudidnt()
if __name__ == '__main__':
    ohnoyoudidnt()
Now you need to get yourself the WMI Module here: http://timgolden.me.uk/python/wmi/index.html
It's a really awesome module and I have seen Tim Golden's posts around the web; very helpful.

the Subprocess module is standard so theres nothing to download there...

Hope it helps you out!
       
 

Monday 11 June 2012

Moving from VBScript to Python to Java to PowerShell

I have always been an idea person.  I like the idea of things and if I like the idea so much, I follow through with it.

An example of this is when I was asked to stay for a week during a project go live from 10 pm to 10 am...  well I actually almost jumped at the opportunity.  I had needed some time to start getting into VBScript since I had little to no experience with programming, I thought it would be a great place to start.  Luckily the project go live was very successful and i was not busy by any means.

http://cbtnuggets.com/ has training courses available to view any time so I started there.  During that time we had a run in with a pretty annoying virus.  One thing about this virus... actually its a worm.  Anyways, this thing created scheduled tasks to do whatever it was doing.  I then used the training videos to help guide me through the process...  first it was finding out "What is the scope of the problem?", then it was "What am I looking for?"

So just moseying along I determined that if I could get a list of computers from Active Directory, I might be able to find out if the scheduled tasks are in the 'Tasks' folder...  it was a little more tricky than that because we had a mix of Windows 2000 desktops along with XP, but after learning the magical "On Error Resume Next", I was set.

From then on, I was determined to make scripting / app development a priority.  Everyday tasks can be automated.  At one point I was picked to create over 150 user accounts in just 3 days.  Then I learned this would continue to happen.  I needed to learn more.  That's when I remembered that in school we were given an MSDN academy account and Visual Basic 6.0 was part of that.  So now I could leverage the power of VBScript and add buttons to it... entry fields... graphics.

I created a password reset utility for our receptionists.
I created a bulk user account creation form.
I created a front end for starting stopping services on remote systems.

All along, I had been using Google to get what I need to know.

I was in a Chapters one day looking around and saw a book called Gray hat Python...  It looked intimidating.  I wanted to know it.  I slowly took python in, thinking it was nice but still sticking to my vbscript guns and just feeling out python...  I noticed that python had a little section in the CBTnuggets site, so I checked it out and now I, only seldom, go back to VBScript for odds and ends.

There are a lot of modules available for Python... its nearly limitless

I created a banner application that displays messages sent via TCP or UDP. (not in production)
I created a SQL frontend for our current inventory control system and am linking documentation... make registry changes... yada yada, its very robust.

In an effort to actually make money from learning these things... I decided to try my hand at developing for Android... since its only 25 to sign up for the developer account.  Agh, see the problem there... gotta learn Java.  Well CBTnuggets offers an intro to Java, so that has gotten my foot in the door.

I created the ohsnAPP Band Name Generator...  the free version has 177 downloads so far..

The paid version has 1 download... my brother in law...  he didn't leave any comments..  I have to laugh though, I never thought I'd be swimming in the money for developing something that serves no other purpose than making people chuckle.  It's a little disappointing, but the real reward is to be able to say that I published something.  It's also very rewarding to be able to help others accomplish their needs and know that I helped them in some way.

And while I am developing for Android, I am also trying to learn PowerShell... seems like a really interesting tool and I plan on sharing as much as possible with it. 




VBScript: Alert system for certificates that will expire in 'n' days.

One day, an individual was called at... oh lets say 3 in the morning, because some certificates which were not set to auto renew and the outlook reminder was never set to tell him or her that the certificates were going to expire.


This could have been avoided by preparing a scheduled task to help alert the Computer System Technician of the upcoming demise and prompt them to take action 5, 10, 30, 60 days before the certs expired. 

I did a bit of research to help the person out... no it was not me called at 3am, thankfully! 

Breaking the VBScript into parts helps out a lot... portability is key when it comes to any scripting language.  I do not have any formal education when it comes to programming, however I do have a lot of confidence in two things... Trial and Error... and Google.

One part of this overall task is the alerting piece.... yes, standard email will do the trick.  I already had something I had used this for anyhow and its a pretty standard piece of code that sys admins should have readily available.  The below code is derived from http://www.paulsadowski.com/wsh/cdo.htm

Sub EMAIL(mailto,txtbody)
    Set objMessage = CreateObject("CDO.Message")
    objMessage.Subject = "Certificates are expiring soon..."
    objMessage.From = "CertificateAuthorityExpirations@work.com"
    objMessage.To = mailto
    objMessage.TextBody = txtbody

    objMessage.Configuration.Fields.Item _
    ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2

    objMessage.Configuration.Fields.Item _
    ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "exchange.server.dot.com"

    objMessage.Configuration.Fields.Item _
    ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25

    objMessage.Configuration.Fields.Update
    objMessage.Send
END SUB
The next part is derived from http://blogs.msdn.com/b/spatdsg/archive/2007/07/19/notify-users-of-cert-expiration.aspx  and modified to meet my needs...  so you can add any arguments you want like number of days to check for... also maybe who you want the email to go to.  Like I mentioned before portability is a sys admins best friend.  Along with documentation... but... like I said, I don't have any formal programming education, so that's my excuse for not commenting my code enough ;)

Const CV_OUT_BASE64 = &H1
Const DUMMY_CERT = "modifiable cert to exclude"  '<== I used this part to skip common certs that all desktops use, because they auto renew anyways and nothing will go down if they are expired

' Setup arguments if there are any....
SET Args = WScript.Arguments

If WScript.Arguments.Count = 1 Then    ' This part can be modified to something hard coded
    mailto = Args.Item(0)                         ' definitely up to you though.
    limit = 60
else
    limit = 60   ' <-- number of days to check for...
    mailto = "system_admin@work.com"
End if
'Log it...
Set objFSO = CreateObject("Scripting.FileSystemObject")
SET writeFile = objFSO.OpenTextFile("Certificates.log", 2, True)  '<-- just creates a new log every time... you can set it to append if you want.

'THIS IS THE <Machinename>\CAName
CAName = "domain_controller.work.int\WORK"     '=======>> CHANGE THIS TO THE CORRECT MACHINE\CA==

'create the CAView object
set oCAView = CreateObject("CertificateAuthority.View")


'open the connection to the Machine\CA
oCAView.OpenConnection (CAName)

'retrieve specific columns from DB  (This part took me awhile to figure out the field names...)
oCAView.SetResultColumnCount(4)
Index0 = oCAView.GetColumnIndex(False, "CommonName") 
Index1 = oCAView.GetColumnIndex(False, "NotAfter")
Index2 = oCAView.GetColumnIndex(False, "SerialNumber")
Index3 = oCAView.GetColumnIndex(False, "CertificateTemplate")
oCAView.SetResultColumn (Index0)
oCAView.SetResultColumn (Index1)
oCAView.SetResultColumn (Index2)
oCAView.SetResultColumn (Index3)
'open the view
Set RowObj= oCAView.OpenView

txtbody = ""

on error resume next
Do Until RowObj.Next = -1

   Set ColObj = RowObj.EnumCertViewColumn()
        x = ""
        Do Until ColObj.Next = -1
            x = x + Cstr(ColObj.GetValue(CV_OUT_BASE64))+","
        Loop
        if Left(x, 1) <> " " then
            items = split(x,",")
            Machine = items(0)
            Expires = items(1)
            Subject = items(2)
            Info = items(3)
            if Info <> DUMMY_CERT then
                edate = cdate(Expires)
                odate = Date
                blarg = DateDiff("y", edate, odate)
                if blarg < 0 then
                    if abs(blarg) < limit then
                        difference = Abs(DateDiff("y", edate, odate)) & " Days until it expires!"
                        writeFile.writeline(Machine & "," & difference & ",SerialNumber: " & Subject & ",CertificateTemplate: " & Info)
                        txtbody = txtbody + "Certificate for: "& Machine & "      Has Only: " & difference & vbcrlf & vbcrlf & _
                        "CA Details;" & vbcrlf & "SerialNumber: " & Subject & vbcrlf & "CertificateTemplate: " & Info & _
                        vbcrlf & "=======================" & vbcrlf & vbcrlf
                    end if
                end if
            end if
        end if
  Set ColObj = Nothing

Loop
call EMAIL(mailto,txtbody)   '<-- this is the SUB i mentioned earlier... cdo send method
writeFile.Close
There is a lot going on it there, but its not hard to pick out what needs to change.  The domain controller
I found from the command line using the certutil exe found in system32...  I don't recall the actual command, but I'm sure its not hard to find on the msdn site...

Hopefully this has been informative and takes you all less time than it took me ;)

Happy testing/fixing/administering

Thursday 7 June 2012

PowerShell: Email me my EventLog, Please.

Today at work I decided to try my hand at PowerShell a little bit.

I DO like it... it's a little tricky to learn any new language, but it is really powerful.

I have a Server (Windows Server 2003...) and occasionally something happens when a process crashes.  Based on that... I thought maybe I could setup some sort of means for reporting to my email (which coincidently, I get my work email on my phone... so voila..)


Heres what I used..  and its all under 15 lines of code... some good potential here

----------------------------
$FROM = "SERVER@work.com"
$TO = "RCUMMINS@WORK.COM" 
$SMTP_Server = "Exchange.Dot.Com"
$smtp = New-Object Net.Mail.SmtpClient($SMTP_Server)
$SUBJECT = "Server Health Report"

$x = Get-EventLog "Application" -EntryType 'Error' -After (Get-Date).addHours(-1) | 
    Where-Object {$_.Source -eq 'Application Hang'}

if($x)
{
    $xx = $x | select TimeGenerated, Message | Out-String
    $smtp.Send($FROM, $TO, $SUBJECT, $xx)
}
---------------------------

So to setup the scheduled task... I just had to do a quick google for the hidden window option...

---------------------------

C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle "Hidden" -Command ".'C:\Path\To\Scripts\Process Checking.ps1'"
---------------------------

That was enjoyable.

Python: Scraping Ebay for Prices

I created a tool to search Ebay.ca for the values of baseball cards... you can actually search whatever you want with it, but I thought it was clever at the time... (01:00am)


Card Collector

Here's the path and the source for it is saved there as well... written in Python, enjoy!