• Category Archives Windows
  • Technology » Windows
  • Windows 10s – A revolution for Accessibility

    Microsoft released the Surface laptop last week. As someone who absolutely loves the Surface Book, I’ve been following with interest the developments in the surface line. I’m not hugely blown away with the Surface Pro line but that’s a reflection of the state of touch screen access using screen readers more than the device itself. Physically, I think the surface pro is very nice to hold, powerful enough to run all standard productivity and development tools and durable enough to be used for both business and pleasure every day. The surface book however is the perfect computer. When relaxing on the bus on the way to and from work I can easily consume content but with this machine, an I7 with 16GB RAM and a 512GB solid state hard disk, I can just as easily run up a few virtual machines, Visual Studio 2017 and a suite of debug and analysis tools and it hardly breaks a swet. It’s perfectly comfortable to type on for 12 hours a day and the battery life is just brilliant. I sound like an advertisement for Surface Book which is fine. It’s easily the nicest laptop I’ve ever owned.

     

    The Surface Laptop doesn’t quite tick all the boxes for me but that’s a good thing at the moment. It is expensive. Maybe too expensive for most people but it’s what it represents that is important. The Surface line is aspirational. It’s expensive but it’s a product line that shows off the power of Windows. It’s Microsoft’s way of showing the world what can be done with devices that run Windows and as a result, PC manufacturers are following their lead. This means that although the Surface Laptop is at the higher end of the price scale, the introduction of Windows10S in parallel means that Microsoft partners are again following Microsoft’s example by releasing their own devices built on Windows 10S. This will mean lower prices for lower spec machines that although do less, still do more than a device like the iPad or Android tablet.

     

    What has all this got to do with accessibility for Blind people? The answer is unfortunately a bit long but please stick with me for a minute so I can explain. Because the result in a year or two could be huge if the current pace of change is retained.

     

    I love the Jaws screen reader for what I do every day. But for many people, all they need to use is a browser and Microsoft Office. I’m not sure if Jaws will be as compelling in the long term as it is right now for the average user with the recent developments in Narrator, the built in screen reader for Microsoft Windows. Not that I’m saying I could personally use Narrator every day. I think it’s still years behind Jaws but look at Voiceover, the built in screen reader for Apple’s OSX and IOS operating systems. It’s also years behind Jaws and it has quite a few bugs but yet, it’s probably the most popular screen reader in the world at the moment. It is highly likely that it has taken over from Jaws in terms of overall screen reader market

    share as more blind users have access to mobile devices than Windows PC’s I’m sure. Those same users might be happy paying $189 to $1200 for various specs of low powered laptops.

     

    For those of you who remember or paid any attention to Windows RT, this really isn’t that. From an accessibility perspective, Windows RT was completely unusable. But with Surface pro, Surface book, the surface studio and now the surface laptop, a blind user can turn it on, hit two buttons and get access to the core of the OS without a commercial screen reader. I bet Freedom scientific are very worried about this – and if they aren’t, they certainly should be.

     

    I’m talking to Microsoft in Ireland and the US every week at the moment about offers for education as that’s the area I’m now working in. I’m consistently delighted when they raise the topic of accessibility without being prompted. There’s a fella heading up the applications for children that includes Minecraft who is great at working on accessibility problems for many difficult areas.

     

    I think it’s a case of watch this space.

     

    I’m also putting my money where my mouth is. There’s an application called Whats up gold that isn’t working with Jaws at all at the moment. I’ve switched to narrator and Edge when using it as I get the best results. This should come as a huge shock for anyone related to the development of Jaws. It certainly shocks me. There are controls that Narrator is reading perfectly such as grid views, tree views and toolbars that Jaws isn’t even seeing in Chrome, Firefox or IE.

     

    I need Narrator to be more responsive and I’ve left feedback with Microsoft in relation to this so here’s hoping that it gets better. I can see myself using it more as time goes on unless Jaws gets a lot better for touch screen access.

     

    I travel a lot on busses so using the laptop isn’t always very comfortable. For that reason, I use a touch screen device such as my phone. I’d really like to be able to use my surface book more for consuming content on the go. If Narrator gives me this freedom first, then there will be no contest.

     

    This is coming from someone who has used Jaws as the primary screen reader for twenty years. So, I have a certain level of brand loyalty. So, the point I’m making is even with brand loyalty from a person who has used this software for 20 years, if Microsoft can take the lead, even I’ll switch. That should drive some serious innovation and changes in Jaws version 19. Because if someone like me will change over, someone who just uses a computer for browsing and Email will change much sooner.


  • Using PuTTY with Jaws 18.

    Please be aware that I don’t recommend that you use PuTTY exclusively for SSH access. Especially in Windows 10. There are a number of better alternatives out there at this point for most day to day use. I’ll add links to one or two below. However, there are times when PuTTY or Putty as it’s pronounced is just the best tool for the job so it’s important that you can get some feedback from Jaws.

    Note as of 26th October 2017

    Please note that this post is now out of date. You should use these fantastic PuTTY scripts instead as they provide much more complete functionality.

    I had posted a script before that worked with previous versions of Jaws and in fact, it would probably work with Jaws 18 as well but the SayNonHighlightedText function in Jaws 18 has been updated so it’s only right that I tweak it slightly and publish it here to be used in a PuTTY.jss file.

    Here’s the code:

    Include “HjGlobal.jsh” ; default HJ global variables
    Include “hjconst.jsh” ; default HJ constants
    Include “HjHelp.jsh” ; Help Topic Constants
    Include “common.jsm” ; message file
    include “MSAAConst.jsh”
    include “UIA.jsh”

    const
    NavigationByLineTickThreshold = 200
    globals
    int LastLineNavigationTick

    Void Function SayNonHighlightedText (handle hwnd, string buffer)
    ; NonHighlightedText Function for speaking all newly written nonhighlighted
    ; text.
    If GetScreenEcho () > ECHO_NONE
    && hWnd == GetFocus()
    If GetWindowClass(GetFocus()) == “PuTTY”
    && GetTickCount()-LastLineNavigationTick > NavigationByLineTickThreshold
    ;New text should be spoken only if it is not a result of navigation by line.
    ;This prevents double speaking when navigating through a command history,
    ;since the SayLineUnit will already have spoken the new text.
    Say(buffer, OT_NONHIGHLIGHTED_SCREEN_TEXT)
    ;Now clear LastLineNavigationTick, just in case more new text appears shortly after the navigation.
    LastLineNavigationTick = 0
    Return
    endIf
    endIf
    if (GetScreenEcho() > 1) then
    Say (buffer, OT_NONHIGHLIGHTED_SCREEN_TEXT)
    endIf
    EndFunction

    There are a number of great alternatives to PuTTY.
    Over on Git Hub, Microsoft have a rather nice SSH Powershell module that provides a method of accessing an OpenSSH server on Linux from within Powershell.
    The best way to use SSH on Windows in my opinion is to install Git. Be sure that you choose to make git features available from the command line so that you can use SSH without starting the Git Bash shell first.
    Lastly, another really good option if you are using Windows 10 is to install Bash or Linux for Windows. This is an add on that you can install from within Programs and Features\Windows Features.

    There are now more ways than ever to access your Linux servers over SSH from within Windows. Have fun!


  • A possible new note taking application

    OneNote, FlashNote, Sticky Notes, Outlook notes and Ever Note are great applications However, if you have privacy concerns and or you are Blind and depend on assistive technologies, these applications probably don’t give you the usability, security and mobility that you need.

    If you are interested in this application, please Email me. If I don’t get enough interest, I won’t write it.

    A note taker should do the following:
    • Open really quickly and allow you to take a note right away.
    • Save automatically.
    • Securely and reliably upload to the cloud.
    • Allow you to retain ownership of your notes.
    • Give you a way of downloading your notes so that if you ever want to move to something new, you have a way of bringing your notes with you.

    The note taking application that I propose to create will provide the following features:
    • Encryption of all notes before they are uploaded by the client. Each note client will use a custom cert along with a custom password so that your notes can only be decrypted by you.
    • Hash tags. Tag your notes with keywords so that you can find notes that have words in common. For example, if you are referencing an upcoming holiday and you want to refer to your flights. Use the #Flights2016 tag so you can quickly jump to all mentions of that tag.
    • Notes will be in a tree structure. Create sub notes to group notes relating to a particular topic.
    • Search for any word contained in all notes.
    • Quickly create a note based on the current date and time.
    • Quickly minimise to the system tray.
    • Open links by pressing enter on the link or by clicking it.
    • Autocomplete using IntelliSense for hash tags.
    • Share a note by Email.
    • Download all notes as CSV.
    • For the next version: Create reminders based on a note.

    The cost of this application will be €15
    The initial version will work on Windows but I’d like to look at a cross platform client eventually.


  • A skype chat with Nicky Kealy discussing and exploring some of the latest tech news and events.

     

    | Open Player in New Window


    There is a lot happening in the tech world at the moment. Some good, some not so good and some that’s just very interesting.
    In this podcast we discuss:

    • Satya Nadella, the CEO of Microsoft visited the ST. Patrick’s campus of DCU where I work a week ago. I got to speak to him briefly about accessibility and inclusion in education.
    • Elon Musk thinks we’ll be in mars by 2022. Do you agree? Is he a visionary or a mad man? All his efferts seem to be connected to autonomy and sustainable power so here’s hoping.Another organization Mars one thinks we’ll be ready by 2027. What do you think?
    • Speaking of self driving cars, we discuss the potential assistive technology requirements of a blind person using a self driving car.
    • Facebook’s Mark Zukkerburg was live for about half an hour yesterday while he was preparing dinner. Yet he had eighty three to eighty six thousand viewers. Why! How!
    • We discuss augmented reality and AI. Where could it be in 5 years.

    Listen to this tech review with special guest Nicky Kealy.
    Thanks to my special guest Nicky Kealy for helping with this podcast.


  • Logon script to migrate users to a new file server and remove and recreate mapped network drives

    I’m migrating a few hundred users over to a new file server.

    The paths will be different. It’s not just the server name that’s changing.

    1. I have run into several problems.
    2. Although I’m a domain admin, I don’t have access to most of the folders. In the worst case scenario I need to take ownership to gain access.
    3. Inheritance is disabled on some of the sub folders.
    4. Permissions are sometimes configured on the fifth or even tenth sub folder.
    5. There are drive paths distributed using group policy but 99% of the paths are mapped directly on the PC.
    6. Five minutes of down time causes untold problems.
    7. The tool that is used to replicate the files isn’t replicating the permissions in all cases. It is also having the same problem that I’m encountering in terms of access to some files and folders.
    8. Permissions aren’t given to groups. Each person is added to the folder directly.
    9. There are often eight different drive maps. Some of these are even pointing to duplicate locations.

    Here’s what I’ve tried.

    1. Section shares will be mapped to S. However, the policy is set to update. IT isn’t changing locally mapped drives. This is ok. It allows users to come to support if they can’t access their files. The benefit of this is support are noting down what S was previously mapped to.
    2. I’m using powershell to level the permissions on all sub directories.
    3. I’m talking to section heads to determine the permissions that each person needs.
    4. I’m adding these people to groups based on the section and directory name and applying access to the group.
    5. I’m marking the old files as hidden. Mainly so that if someone continues using the old path they will think the drive is empty. That will result in a call to support where they can tell the user to use the new drive and then also delete the old map.

    There are far too many manual steps in this.

    There’s also too many remaining drive maps that aren’t needed.

    Here is what the script does to automate most of these manual steps.
    This is run at log in and targets one or more groups.

    1. List the currently mapped network drives.
    2. Check the groups that the user is a member of.
    3. Remove all drive maps
    4. Map drives based on assigned groups.
    5. Show a message to the user to inform them that the migration has completed.

    The main remaining problem is that if I move Drive Q that is used by ApplicationX to the letter Y, all the users who used the old letter will probably have problems opening files. There’s nothing I can really do about this. However, so far, the instances where this has been encountered has been managed easily by support.

    One choice I also made was to remove all existing permissions from the folder and reapply the permissions on the new file server so that only groups that should have access are applied to each folder. Of course, this requires that staff speak to their section heads to in turn ask me for access but this removes the potential that people have access to folders that they no longer need. It also helps to promote a more structured method of processing access requests. I could implement a form for tracking these requests but this overhead would be justifiably resisted by section heads.

    The script follows:

    Option Explicit
    Dim objShell,grouplistD,ADSPath,userPath,listGroup,WshNetwork,objFSO,objFile,strComputer,objWMIService,IPConfigSet,strIPAddress,colItems,strDrives,mappedDrives,objNetwork,x
    dim objTS, sReadLine, bReturn, strOutputFile, RunBefore, WshShell, IPConfig,i,objItem, objOutputFile
    strOutputFile = “\\spd-adc01.spd.dcu.ie\RemainingComputer\SharedFolders.txt”
    On Error Resume Next
    Set objShell = CreateObject(“WScript.Shell”)
    Const ForAppending = 8
    Set WshShell = CreateObject(“WScript.Shell”)
    Set WshNetwork = CreateObject(“WScript.Network”)
    Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Set objFile = objFSO.OpenTextFile(strOutputFile, ForAppending)

    ScriptNotRunBefore
    if (RunBefore = “False”) Then
    objFile.WriteLine WshNetwork.ComputerName & “,” & WshNetwork.UserName & “,” & GetIpAddress & “,” & GetMappedNetworkDrives

    DeleteMappedDrives
    If isMember(“SPD President”) Then
    MapPresidentsDrive
    End If
    End If
    objFile.Close

    Function GetIPAddress
    strComputer = “.”
    Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
    Set IPConfigSet = objWMIService.ExecQuery _
    (“Select IPAddress from Win32_NetworkAdapterConfiguration WHERE IPEnabled = ‘True'”)

    For Each IPConfig in IPConfigSet
    If Not IsNull(IPConfig.IPAddress) Then
    For i = LBound(IPConfig.IPAddress) to UBound(IPConfig.IPAddress)
    If Not Instr(IPConfig.IPAddress(i), “:”) > 0 Then
    strIPAddress = strIPAddress & IPConfig.IPAddress(i) & ” ”
    End If
    Next
    End If
    Next
    GetIPAddress = strIPAddress
    End Function

    Function GetMappedNetworkDrives
    On Error Resume Next
    strComputer = “.”
    Set objWMIService = GetObject(“winmgmts:” & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)
    Set colItems = objWMIService.ExecQuery(“Select * from Win32_MappedLogicalDisk”)

    For Each objItem in colItems
    strDrives = strDrives & “,” & objItem.Name & ” ” & objItem.ProviderName
    Next
    GetMappedNetworkDrives = strDrives
    End Function

    Function DeleteMappedDrives
    On Error Resume Next
    Set objNetwork = CreateObject(“Wscript.Network”)
    Set mappedDrives = objNetwork.EnumNetworkDrives
    For x = 0 to mappedDrives.Count
    objNetwork.RemoveNetworkDrive mappedDrives.Item(x), True, True
    Next
    End Function

    Function MapPresidentsDrive
    DeleteMappedDrives
    If isMember(“SPD President”) Then
    Set objNetwork = WScript.CreateObject(“WScript.Network”)
    objNetwork.MapNetworkDrive “S:” , “\\ad.dcu.ie\data\dept\spd\college admin\President”
    MsgBox”Drive S added successfully.” & vbcrlf & “The presidents section share is available in this new location.” & vbcrlf & vbcrlf & “Please contact the helpdesk if you have any questions.”,64,”Migration successfull”
    Else
    WMsgBox”False”
    End If

    End Function

    Function IsMember(groupName)
    If IsEmpty(groupListD) then
    Set groupListD = CreateObject(“Scripting.Dictionary”)
    groupListD.CompareMode = 1
    ADSPath = EnvString(“userdomain”) & “/” & EnvString(“username”)
    Set userPath = GetObject(“WinNT://” & ADSPath & “,user”)
    For Each listGroup in userPath.Groups
    groupListD.Add listGroup.Name, “-”
    Next
    End if
    IsMember = CBool(groupListD.Exists(groupName))
    End Function

    Function EnvString(variable)
    variable = “%” & variable & “%”
    EnvString = objShell.ExpandEnvironmentStrings(variable)
    End Function
    Set objShell = Nothing

    Function ScriptNotRunBefore
    Set WshNetwork = CreateObject(“WScript.Network”)
    RunBefore = “False”
    strComputer = WshNetwork.ComputerName
    set objFSO = CreateObject(“Scripting.FileSystemObject”)
    set objOutputFile = objFSO.GetFile(strOutputFile)
    set objTS = objOutputFile.OpenAsTextStream(1)

    ‘Loop through the output file to see if “Computer name in STRComputer” is found,
    ‘if it is then the script has run before.
    do while objTs.AtEndOfStream <> true
    sReadLine = objTs.ReadLine
    if instr(sReadLine, strComputer) > 0 then
    RunBefore = “True”
    exit do
    end if
    loop

    ‘Close output file and release objects
    objTS.close
    set objTS = nothing
    set strOutputFile = nothing
    set objFSO = nothing
    end function


  • VBS to inventory your workstations or servers

    Sometimes you just need a clear picture of what is in your environment.

    Sometimes you just need to see how much disk space, RAM and CPU capacity a few dozen workstations have available.

    Sometimes you walk into an office and you haven’t a clue what’s live, what’s turned off and what is very out of date.

    This script fixes all of that. Give it a text file with as many Windows workstations or servers as you like and let it go off and get the version of Windows, the license type, the RAM, CPU, Hard disk capacity, the software and hardware serial number and the Windows installation directory. It saves this into a CSV file that you can then open in Excel to sort and play with as much as you want.

    I wrote this to create an inventory of the servers in use here so I could see what version of windows they have, ensure they are using the most recent service pack and ensure they were all using the enterprise skew. I then expanded it to give me more information. Mainly so I can save it somewhere for use on a later date.

    On Error Resume Next

    Const ForReading = 1
    Const ForWriting = 2
    Const Forappend = 8
    filecomputer = “.\computer.txt” ‘ -> File that contains the computers list
    strComputer = “.”
    Star = “*”
    InventoryOutputFile = “inventory.txt”
    logfilename = “.\inventory.log”

    Dim hostname,OSType,CSDVersion,WinSerialNumber,Version,Windir,Timewritten,sw,Make,Model,CPU,Drives,TotalMemory,SerialNumber

    sw = 0

    ‘—————————————
    ‘ Call the routine for log file creation
    ‘—————————————

    createlogfile logfilename

    ‘————————
    ‘ Read computer.txt file
    ‘————————

    Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Set objTextFile = objFSO.OpenTextFile(filecomputer,ForReading)
    Do While objTextFile.AtEndOfStream <> True
    strLinetoParse = objTextFile.ReadLine
    First_char = Left(strLinetoParse, 1)
    if (First_char <> star) And (First_char <> ” “) then ‘ Bypass the row starting with * and blank char
    hostname = Trim(strLinetoParse)

    Get_user_info hostname
    If WinSerialNumber > 0 then ‘ If the computer exist or is UP
    hostname = strLinetoParse

    AddLineToOutputFile hostname,OSType,CSDVersion,WinSerialNumber,Version,Windir,TotalMemory,Make,Model,CPU,Drives,SerialNumber,Forappend
    WinSerialNumber = 0
    Else
    msg = “=====> Hostname ” & hostname & ” not found or Down”

    writetofile msg,Forappend
    End if
    End if
    Loop
    objTextFile.Close

    ‘————————————————–
    ‘ Retrieve the information from the remote computer
    ‘————————————————–

    Function Get_user_info(strComputer)
    Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)

    Set colItems = objWMIService.ExecQuery(“Select * from Win32_OperatingSystem”,,48)
    For Each objItem in colItems
    OSType = objItem.Caption
    CSDVersion = objItem.CSDVersion
    WinSerialNumber = objItem.SerialNumber
    Version = objItem.Version
    Windir = objItem.WindowsDirectory
    TotalMemory = Round(Trim(objItem.TotalVisibleMemorySize) / 1024, 2 /1024) /1024
    Next

    Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_Processor”,,48)
    For Each objItem in colItems
    CPU = Trim(objItem.Name)
    Next

    Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_LogicalDisk WHERE DriveType=3″,,48)
    For Each objItem in colItems
    Drives = Drives & Trim(objItem.DeviceID) & ” ” & Round(Trim(objItem.Size) / (1024^2), 2) & “;”
    Next

    Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_ComputerSystem”,,48)
    For Each objItem in colItems
    Make = Trim(objItem.Manufacturer)
    Model = Trim(objItem.Model)
    Next

    Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_BIOS”,,48)
    For Each objItem in colItems
    SerialNumber = Trim(objItem.SerialNumber)
    Next
    End function

    ‘————————
    ‘ Add/Update the records
    ‘————————

    function AddLineToOutputFile(hostname,OSType,CSDVersion,WinSerialNumber,Version,Windir,TotalMemory,Make,Model,CPU,Drives,SerialNumber,forwriting)
    ‘WScript.Echo hostname
    Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Set WriteInventory = objFSO.OpenTextFile(InventoryOutputFile,forwriting, True)
    WriteInventory.WriteLine(hostname & “,” & OSType & “,” & CSDVersion & “,” & WinSerialNumber & “,” & Version & “,” & Windir & “,” & TotalMemory & “,” & Make& “,” & Model & “,” & CPU & “,” & Drives & “,” & SerialNumber)
    WriteInventory.Close
    End function

    ‘———————
    ‘ Create the log file
    ‘———————

    function createlogfile(logfilename)
    Dim objFileSystem, objOutputFile
    Dim strOutputFile
    strOutputFile = logfilename
    Set objFileSystem = CreateObject(“Scripting.fileSystemObject”)
    Set objOutputFile = objFileSystem.CreateTextFile(strOutputFile, TRUE)
    objOutputFile.WriteLine(“——————— Inventory Report ” & now() & ” ———————“)
    objOutputFile.WriteLine(” “)
    objOutputFile.Close
    Set objFileSystem = Nothing
    End function

    ‘——————-
    ‘ Write to log file
    ‘——————-

    function writetofile(msg,forwriting)
    Set myFSO = CreateObject(“Scripting.FileSystemObject”)
    Set WriteStuff = myFSO.OpenTextFile(logfilename,forwriting, True)
    WriteStuff.WriteLine(“—————————————————————————“)
    WriteStuff.WriteLine(” “)
    WriteStuff.WriteLine(msg)
    WriteStuff.WriteLine(” “)
    WriteStuff.Close
    End function


  • Script to delete Chrome cache on all PC’s listed in a text file

    Another problem that could be fixed with a script today. Moving machines and users to a different domain resulted in a problem for some people. Chrome is a very popular browser but a number of people have reported to support that Chrome takes a very long time to start and then open the first page after log in to windows.

    It was determined that deleting the cache directory from within the users Chrome application data folder resolved this.

    Waiting for every effected user to report the problem wouldn’t be a great course of action of course. It would be a lot better to proactively go after all Chrome installations and remove the cache directory.

    So that’s what I’ve done. The script does the following:

    1. Check to see if the computer is on the network by pinging it.
    2. List all the user directories in c:\users on each computer.
    3. Check to see if the Chrome cache directory exists.
    4. Deletes the cache directory.
    5. Logs the result including any encountered errors to a file called results.txt.

    I could have searched Active Directory directly of course but I want to be able to easily add and remove computers when needed. It also allows me to run the script on 10 computers to start off and ramp up to a few thousand by the end.

    It should go without saying that as the script uses the admin share, you need to have access to the workstations that you intend to administer.

    Option Explicit
    Const ForReading = 1
    Const ForAppending = 8
    Dim objFSO : Set objFSO = CreateObject(“Scripting.FileSystemObject”)
    Dim objFile : Set objFile = objFSO.OpenTextFile(“Z:\Scripts\Chrome cleanup\AccountingsectionComputers.txt”, ForReading, False)
    Dim objWriteFile : Set objWriteFile = objFSO.OpenTextFile(“Z:\Scripts\Chrome cleanup\Result.txt”, ForAppending)

    Do Until objFile.AtEndOfStream
    Dim strComputer : strComputer = Trim(objFile.ReadLine)
    If PingMachine(strComputer) Then
    ‘Computer is pinging
    Dim objFolder : Set objFolder = objFSO.GetFolder(“\\” & strComputer & “\c$\users\”)
    Dim strUserParentPath : Set strUserParentPath = objFolder.SubFolders
    Dim strUserFolder
    For Each strUserFolder in strUserParentPath
    Dim strRemoteBasePath : strRemoteBasePath = “\\” & strComputer & “\c$\users\” & strUserFolder.name & “\AppData\Local\Google\Chrome\User Data\Default\Cache”
    If objFSO.FolderExists(strRemoteBasePath) Then
    On Error Resume Next
    objFSO.DeleteFolder strRemoteBasePath, True
    If Err.Number = 0 Then
    objWriteFile.WriteLine strRemoteBasePath & vbTab & ” DELETE SUCCESSFUL”
    Else
    objWriteFile.WriteLine strRemoteBasePath & vbTab & ” DELETE FAILED: ” & Err.Number & ” ” & Err.Description
    End If
    On Error GoTo 0
    Else
    objWriteFile.WriteLine strRemoteBasePath & vbTab & ” FOLDER DOES NOT EXIST”
    End If
    Next
    Else
    objWriteFile.WriteLine strComputer & vbTab & ” PING FAILED”
    End If
    Loop
    objFile.Close

    Function PingMachine(device_name)
    PingMachine = False
    Dim colItems : Set colItems = GetObject(“winmgmts:root\cimv2”).ExecQuery _
    (“Select StatusCode from Win32_PingStatus Where Address = ‘” & device_name & “‘”)
    Dim objItem
    For Each objItem in colItems
    If objItem.StatusCode = 0 Then PingMachine = True
    Next
    End Function

    If there are other scripts that you would like to see, please let me know in the comments section.


  • See who is logging onto your domain

    I was looking a migration from one domain to another a short while ago. Almost all the users accounts had been migrated over but there were a few hanging on.

    The migration tool wasn’t doing a great job of picking them up so I wrote a small script and added it to group policy for all servers and workstations. Now when someone logs in to the old domain a line is written to the log with their username, computer name and IP address.

    Using this the person responsible for the migration can get through the last few people on the old domain. This has saved a lot of time as before I wrote this th eprocess was very manual.


    Const ForAppending = 8
    Set WshShell = CreateObject("WScript.Shell")
    Set WshNetwork = CreateObject("WScript.Network")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile("\\ServerName.DomainName.TLD\RemainingComputer\log.txt", ForAppending)
    objFile.WriteLine WshNetwork.ComputerName & "," & WshNetwork.UserName & "," & GetIpAddress
    objFile.Close

    Function GetIPAddress
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set IPConfigSet = objWMIService.ExecQuery _
    ("Select IPAddress from Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'True'")

    For Each IPConfig in IPConfigSet
    If Not IsNull(IPConfig.IPAddress) Then
    For i = LBound(IPConfig.IPAddress) to UBound(IPConfig.IPAddress)
    If Not Instr(IPConfig.IPAddress(i), ":") > 0 Then
    strIPAddress = strIPAddress & IPConfig.IPAddress(i) & " "
    End If
    Next
    End If
    Next
    GetIPAddress = strIPAddress
    End Function


  • Jaws scripts to virtualize list view items.

    In work at the moment, I spend a huge amount of time in massive list views. These list views could have thousands of items and up to 256 columns. At first, reading them with Jaws was one of the most stressful things I’ve ever done. The customize list view scripts don’t work because of a bug in the user interface of this application. Every time focus changes to or away from the main application, the control that previously had focus will no longer have it when you return to the main window. It is a torturous situation to be in because when I’m in this application, I need information quickly and accurately. Also, most of the columns contain numbers that are very important so for the first week or two of starting in my new job you’d find me with my head down in major concentration mode trying to listen to Jaws fly through all the columns so I could pick out the tiny nugget of information that I needed from column 10 or worse, 210. I’d finish the day completely exhausted from this effort so I badly needed a solution.

    Jaws has a script that will allow you to read the first ten columns of a list view but this is stupidly limited when you consider that this only allows a user to intentionally work with ten list view columns. What I needed was a script that would let me walk forward and back through each column from the beginning to the end of that item. If I found something that I needed, I could then listen to it and it would be clear. You would not believe how much easier this made my day. However, it became clear that I couldn’t always trust myself to remember all the information that I was being given by Jaws when working through these list view items so I decided to expand the script a little to add the current column into the virtual viewer. This is handy as I can then examine the text character by character if I need to and I can use the clipboard to store that text if I need to use it in notes or SQL statements that will pull more information from the database again, this minor change made things much easier for me.

    However, there was one more thing that I needed. When sighted people were using these lists they could compare two items visually much faster than I could with my scripts. Yes, the column I was on was retained even when I was on different list items so say / virtualize current column worked very well. However, it wasn’t quite what I needed for every situation. The next solution has proven to be even more helpful than the first. Now, when I choose to, I can virtualize the entire list item so using the virtual viewer, I can arrow up and down the list of column headers and the text within each one to get the data in the best format for me to understand quickly. Thanks to some excel queries, I can virtualize two columns then use a dif function to work out the differences much faster than anyone who can see.

    These scripts have actually changed the way I work with list views. I really hope they are helpful to you.

    Disclaimer: I won’t support these. I’m not a script writer; I sometimes manage to scrape scripts together with the help of others or by taking script chunks from existing scripts written for Jaws. In this instance, I butchered a few other scripts to make these. Moving back and forward through list items works very well but for some reason, the count is slightly off so you may find that you need to move to the next list item twice to make it actually go forward.

    I added these to my default scripts because I needed this functionality in a number of applications after a while. Add them where ever you like. At the top of your file in the globals section, you need to declare a variable for holding the current list column number. The line is below:


    int CurrentListColumn

    Remember to add a comma from the previous variable declaration or your script won’t compile.

    Here are the scripts. Add them to the bottom of the default file if you choose to use that. Remember to also assign keyboard commands to each script. I’m sorry, but if you aren’t particularly sure how to do this, you may need to ask the Jaws script mailing list or read the script help topics. I cant promis to help you out as I’m busy enough as it is.


    Script ReadNextListviewColumn ()
    var
    int nCol,
    int nMaxCols,
    string sHeader,
    string sText,
    handle hCurrent,
    int nCurrent
    If (CurrentListColumn<1) then CurrentListColumn = 1 EndIf If !(GetRunningFSProducts() & product_JAWS) then return EndIf let hCurrent=getCurrentWindow() if !IsTrueListView(hCurrent) then sayMessage(OT_ERROR,cmsgNotInAListview_L,cmsgNotInAListview_S) return endIf let nMaxCols=lvGetNumOfColumns(hCurrent) let nCurrent=lvGetFocusItem(hCurrent) let nCol=CurrentListColumn let sHeader=lvGetColumnHeader(hCurrent,nCol) let sText=lvGetItemText(hCurrent,nCurrent,nCol) say(sHeader,OT_NO_DISABLE) say(sText,OT_NO_DISABLE) say(IntToString(CurrentListColumn),OT_NO_DISABLE) if (nCol < nMaxCols) then CurrentListColumn = CurrentListColumn + 1 EndIf if (nCol > nMaxCols) then
    SayFormattedMessage(OT_ERROR,formatString(cmsgListviewContainsXColumns_L,intToString(nCol),intToString(nMaxCols)),formatString(cmsgListviewContainsXColumns_S,intToString(nCol)))
    return
    endIf
    EndScript

    Script ReadPreviousListviewColumn ()
    var
    int nCol,
    int nMaxCols,
    string sHeader,
    string sText,
    handle hCurrent,
    int nCurrent
    if (CurrentListColumn > 1) then
    CurrentListColumn = CurrentListColumn - 1
    EndIf
    If !(GetRunningFSProducts() & product_JAWS) then
    return
    EndIf
    let hCurrent=getCurrentWindow()
    if !IsTrueListView(hCurrent) then
    sayMessage(OT_ERROR,cmsgNotInAListview_L,cmsgNotInAListview_S)
    return
    endIf
    let nMaxCols=lvGetNumOfColumns(hCurrent)
    let nCol=CurrentListColumn
    let nCurrent=lvGetFocusItem(hCurrent)
    if (nCol < 1) then let nCol=1 endIf if (nCol > nMaxCols) then
    SayFormattedMessage(OT_ERROR,formatString(cmsgListviewContainsXColumns_L,intToString(nCol),intToString(nMaxCols)),formatString(cmsgListviewContainsXColumns_S,intToString(nCol)))
    return
    endIf
    let sHeader=lvGetColumnHeader(hCurrent,nCol)
    let sText=lvGetItemText(hCurrent,nCurrent,nCol)
    say(sHeader,OT_NO_DISABLE)
    say(sText,OT_NO_DISABLE)
    say(IntToString(CurrentListColumn),OT_NO_DISABLE)
    EndScript

    Script VirtualizeCurrentListColumn ()
    var
    int nCol,
    int nMaxCols,
    string sHeader,
    string sText,
    handle hCurrent,
    int nCurrent

    If !(GetRunningFSProducts() & product_JAWS) then
    return
    EndIf
    let hCurrent=getCurrentWindow()
    if !IsTrueListView(hCurrent) then
    sayMessage(OT_ERROR,cmsgNotInAListview_L,cmsgNotInAListview_S)
    return
    endIf
    let nMaxCols=lvGetNumOfColumns(hCurrent)
    let nCol=CurrentListColumn
    let nCurrent=lvGetFocusItem(hCurrent)
    if (nCol < 1) then let nCol=1 endIf if (nCol > nMaxCols) then
    SayFormattedMessage(OT_ERROR,formatString(cmsgListviewContainsXColumns_L,intToString(nCol),intToString(nMaxCols)),formatString(cmsgListviewContainsXColumns_S,intToString(nCol)))
    return
    endIf
    let sHeader=lvGetColumnHeader(hCurrent,nCol)
    let sText=lvGetItemText(hCurrent,nCurrent,nCol)
    say(sHeader,OT_NO_DISABLE)
    say(sText,OT_NO_DISABLE)
    say(IntToString(CurrentListColumn),OT_NO_DISABLE)
    UserBufferClear ()
    UserBufferAddText (sHeader)
    UserBufferAddText (sText)
    UserBufferActivate ()
    SayLine ()
    EndScript

    Script VirtualizeAllListColumns ()
    var
    int nCol,
    int nMaxCols,
    string sHeader,
    string sText,
    handle hCurrent,
    int nCurrent

    If !(GetRunningFSProducts() & product_JAWS) then
    return
    EndIf
    let hCurrent=getCurrentWindow()
    if !IsTrueListView(hCurrent) then
    sayMessage(OT_ERROR,cmsgNotInAListview_L,cmsgNotInAListview_S)
    return
    endIf
    let nMaxCols=lvGetNumOfColumns(hCurrent)
    let nCol=1
    let nCurrent=lvGetFocusItem(hCurrent)
    UserBufferClear ()
    while nCol<=nMaxCols let sHeader=lvGetColumnHeader(hCurrent,nCol) let sText=lvGetItemText(hCurrent,nCurrent,nCol) UserBufferAddText (sHeader) UserBufferAddText (sText) LET nCol = nCol + 1 EndWhile UserBufferActivate () EndScript