All posts by andrew

A twenty year veteran of the software industry, Andrew brings considerable experience to electrongoo. From design, development, project management, and product usability; he delivers on all levels

Repairing a stuck Woodpecker Precision Router Lift

A router is a woodworkers best friend. The PRL from Woodpeckers makes it the perfect friend! I’ve been using my PRL V1 for almost 15 years without issue. The PRL V1 is no longer for sale – the PRL V2 has taken its place. Recently, the handle crank became hard to turn. After some digging-around and unscrewing, it turns out this was caused by dust between the nylon gear and the faceplate. Here’s how I fixed the issue.

Place the PRL on a sturdy surface:

You will need some tools: 9/16″ wrench, 4.5mm Allen wrench, and some lubricant (I used 3-1 oil but WD-40 or similar will work fine):

Place the PRL on its side with access to the 9/16″ bolts which hold the router in place:

Remove the router from the PRL for easier access to the gears and chain:

Once the router is removed, flip the PRL on its face with access to remove the gears and loosen the chain. Locate the gear underneath the crank handle (it’s the one with large metal stop-system and two Allen nuts) :

Unscrew the two Allen nuts to remove the stop-system:

One the adjacent side of the PRL, remove the single Allen nut holding the metallic gear:

the chain should flow freely to create slack to access the gears:

Now loosen the chain from around the nylon gear located below the hand crank:

Turn and pull the nylon gear by hand until it comes free from the face plate:

Now comes the fix! Clean the base of the gear and the inside hole on the face plate. First with a dry cloth or paper towel to get ride of the larger debris. Finally spray the areas with oil/WD-40. No need to use very much as it will dry eventually; use just enough to slide the gear back into the faceplate.

Once it’s all clean, slip the nylon gear back in the faceplate, place the chain back on the nylon gear, place the chain back on the metal gear, and screw the Allen nut so the metal gear is secure and the chain flows around all four gears. Re-secure the metal stop-system to the top of the nylon gear with the two Allen nuts. Finally, re-mount the router into the Lift.

Give the crank a whirl! Hopefully it’s back to new and cranks easily.

Getting a second video monitor to display correctly after resuming Windows 10

I run windows 10 and once in a while my second video monitor will remain dark after coming out of a suspend mode (sometimes even just turning off the monitors and turning them back on!). I believe this is an issue with the NVidia video card I have installed since I can get the monitor to refresh by restarting the device (or rebooting the PC).

Here’s how I solve this issue …

1. On the Windows Desktop (or some other folder if you prefer) create a new file named ResetVideoAdaptor.bat. You can use Windows Notepad or any text editor to do this. Just make sure the file extension is named ‘.bat’ and not ‘.txt’
2. Add the following lines to your ResetVideoAdaptor.bat file (see additional steps ‘how to customize for your system’ below)

@echo off

REM see details on blog.electrongoo.com to set your specific adaptor id!
SET MY_VID_ADAPTOR_ID=*PCI\VEN_XXXX*YYYY*

"C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon" disable %MY_VID_ADAPTOR_ID%
"C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon" enable %MY_VID_ADAPTOR_ID%

3. To use this batch file, whenever one of your video monitors goes dark, run ResetVideoAdaptor.bat as Administrator (right-click on ResetVideoAdaptor.bat and select “Run as Administrator”) and the video adaptor will be reset and the video monitor will come back to life.

How to customize for your system

You must have Microsoft’s devcon utility installed on your system for this to work. This utility is free and part of the Microsoft WDK which you can download here.

You must update the vendor id and device id in the ResetVideoAdaptor.bat file for your specific video card. You can find these values using Windows Device Manager. In the Windows Search bar type “Device Manager” and press Enter. You should see a window similar to this

Locate your video card under “display adaptors” and right-click and select Properties. From the Properties page select the Details tab and select “Hardware Ids” from the Property drop-down listbox. You should see something similar to this

Now jot-down the vendor id which will be the four digits after the “VIN_” tag (see example below) and the device id which will be the four digits after the “DEV_” tag (see example below).

Finally update your specific four digit vendor id and four digit device id in the ResetVideoAdapter.bat file. Search for “XXXX” and “YYYY” and replace those values with your specific id’s. As an example, for my video card I updated the line

SET MY_VID_ADAPTOR_ID=*PCI\VEN_XXXX*YYYY*

to

SET MY_VID_ADAPTOR_ID=*PCI\VEN_10DE*1187*

Save your final changes to ResetVideoAdapter.bat and your done.

I hope this helps!

Fixing itunes hang on Windows 10

I have a multi-user configuration setup on my Windows 10 PC at home. My entire family can log into their own Windows account and have their own desktop and storage space. This works nicely but I noticed that iTunes is not very friendly with this multi-user configuration – iTunes hangs after sync’ing with an iPhone/ipad and can’t be used again until after a system reboot. Here’s how I resolved this issue: I created a batch file which terminates iTunes and creates a “clean” state …

  1. On the Desktop create a new file called ResetITunes.bat. You can use Windows Notepad or any text editor to do this.
  2. Add the following to the ResetITunes.bat file
@echo off

taskkill /F /IM itunes.exe
taskkill /F /IM distnoted.exe

3. Now, whenever you close iTunes, simply run ResetITunes.bat as Administrator (right-click and select “Run as Administrator”) and iTunes will terminate and be ready for the next user to sync their iPhone or iPad.

Hope this helps!

Copying files recursively in MS Excel with VBA

When managing projects I use a few different off-the-shelf products.  But, it always seems there is some task I need to do that can’t be done efficiently with these tools so I make sure to include MS Excel (Office 365) in my suite of project management utilities.  VBA macros within Excel give me the power to complete any custom tasks I require.

I needed to copy a set of folders (an entire recursive tree) to a new location.  VBA does not natively include this feature.  I searched the web for solutions but it seemed all were either out-of-date (non functional) or simply incomplete (never worked!).  So, I thought I’d share my solution built on the VBA scripting.filesystemobject. Hopefully it will help others. Here it is …

Public Sub TestCopyFiles()
    ' Call the recursive copy operation
    CopyFiles "c:\temp\a", "c:\temp\b"
End Sub

Public Sub CopyFiles(ByVal strPath As String, ByVal strTarget As String, Optional ByVal basePath As String, Optional ByVal baseTarget As String)
    If basePath = "" Then basePath = strPath
    If baseTarget = "" Then baseTarget = strTarget
    Set FSO = CreateObject("scripting.filesystemobject")
    ' First loop through files in this folder
    For Each nextFile In FSO.getfolder(strPath).Files
        fullTargetPath = strTarget + "\" + nextFile.Name
        mkdir (strTarget)
        ' Copy one file
        FileInFromFolder.Copy fullTargetPath
    Next
    ' Next loop through folders in this folder
    For Each nextFolder In FSO.getfolder(strPath).SubFolders
        nextStrTarget = baseTarget + Right(nextFolder, Len(nextFolder) - Len(basePath))
        mkdir (nextStrTarget)
        CopyFiles nextFolder.Path, nextStrTarget, basePath, baseTarget
    Next
End Sub

Private Sub mkdir(folder As String)
    ' Create a folder if it doesn't exist
    Set FSO = CreateObject("scripting.filesystemobject")
    On Error Resume Next
    FSO.CreateFolder (folder)
    On Error GoTo 0
End Sub

Git cheat-sheet

As a recent cross-over user of Subversion to Git, I occasionally need a refresher of some command-line git operations … and I find myself searching the web.  So, I created this list in a single, easy to locate post.  Here is a list of Git operations I find most useful.  Listed in order of a typical workflow.  Hence more interesting (and more easily forgotten) operations are listed at the end.

Initial setup
sudo apt-get install git
Initial configuration
git config --global user.name "Iam me"
git config --global user.email me@here.com
git config --global core.editor nano
git config --global credential.helper "cache --timeout=900"
Configure ignored files (using .gitignore file)
nano .gitignore
*.o
nohup.out
doc/*.txt
.vscode
.idea
Help
git help <command>
Initialize a repository
git init
OR
git clone git://your.git.url.goes.here
View status
git status
git diff
Add/commit files
git add <filename>
git commit
OR
git commit -am "commit message goes here"     (add all tracked files and commit them in a single command)
Remove files
git rm <filename
Move files
git mv <filename> <newfilename>
Updating a commit (before push)
git commit -am 'initial commit'
git add <somefile>
git commit --amend
View commits
git status
Reverting a modified file (not yet staged)
git checkout -- <file
Reverting a staged file (e.g. via git add)
git reset HEAD <file
Reverting a commit
git revert <commit-id>
git push
Reverting all local changes
git reset --hard origin/master
Create a new branch
git checkout -b <name_of_your_new_branch>
git push origin <name_of_your_new_branch
Save/restore work temporarily
git stash
***change branches or whatever
git stash pop
Delete a remote branch
git push origin --delete <branchName>
git fetch -p    "to refresh local repro"
Delete a local branch
git branch -d <branch_name>
git fetch -p    #"to refresh local repro"
Tag a commit (for release or tracking)
git tag -a <tagname> <commitid>
git push origin <tagname>
Checkout at a tag
git checkout <tagname>
Merge a branch back into master branch
git checkout master
git pull
git checkout <branch>
git merge master
# if you have conflicts ... edit the conflicts and then run "git add <files_edited>" "git commit"
git push

Enable and disable hyper-V service on Windows

Both Hyper-V and Virtual Box are excellent virtualization tools.  Unfortunately, they compete for the BIOS virtualization feature.  I’ve been using the HoloLens emulator recently which requires Hyper-V.

I created some simple batch files to easily enable/disable Hyper-V as I move to/from the HoloLens emulator.  Create two new files  (add the contents specified below) , right-click and run as Administrator, a  reboot is required.

hyperv-enable.bat

@echo off
echo "NOTE: you must run this script at administrator level"
bcdedit /set hypervisorlaunchtype auto
echo "press enter to reboot ..."
pause
shutdown /r

hyperv-disable.bat

@echo off
echo "NOTE: you must run this script at administrator level"
bcdedit /set hypervisorlaunchtype off
echo "press enter to reboot ..."
pause
shutdown /r

to switch hyper-V on/off simply right-click on the bat file and select ‘run as administrator’ … after a reboot, the hyper-V service will be updated.

How to update the default behavior script in Unity3D

Creating new C# scripts in Unity3D is a simple process with a click of a mouse; although I find myself updating the default behavior script to match my coding preferences each time I create a new script.

Here’s how I update the default script to simplify my development process.

Browse to the Unity3D installation folder (typically named “C:\Program Files (x86)\Unity\”) and locate the sub-folder “Editor/Data/Resources/ScriptTemplates”

unity3d-template

Here you will see the template files used to create new scripts.  On my system I have five templates: javascript, C#, Boo, shader, and computer shader.  I am interested in the C# template.

Open the file named “81-C# Script-NewBehaviourScript.cs.txt”

unity3d-template-1

Update the layout file

unity3d-template-2

Save the file

Now, when I create a new C# script in Unity3D it uses my preferred coding style layout.

Note: if you re-install Unity3D then you will need to update the layout file again.

How to update Unity3d’s default Project Location

Unity3d Project Location:

Unity3d is an excellent cross-platform tool for developing interactive content.  Unfortunately some desirable work-flow features are just not available.  One such feature is the ability to change the default Project Location where all new Unity projects are saved.  With Unity, I find myself creating new projects quite often to test new features and ideas.  Being able to set a custom default Project Location would be a great time-saver so I would not have to drill-down into a file dialog to locate a specific folder.

While searching for a solution I found many others looking for the same feature.  Unfortunately, no solutions were available.  I found one mention of a registry key which could be altered but that did not work.  I used the Microsoft  Process Monitor to view registry and file access by the Unity process but I never saw any interesting data being read.

After some quick tests I found that Unity always uses the personal documents folder.  The personal documents folder is located by Unity using the Microsoft SHGetFolderPath API.  By default, Unity saves new projects under a folder named “New Unity Project (X)” under your personal documents folder.   So, the task is to get Unity to read a different value for the personal documents folder.

The following details how to update Unity running on Windows.  These steps are not valid for Unity running OSX or Linux.

 Instructions:

In order to get Unity to display a custom Project Location folder when you select File | New Project … you must update a value in the Windows registry.  To accomplish this, create a simple Visual Basic script to update the personal folder name, launch Unity, then revert the personal folder name when Unity is closed.  Here are the step-by-step instructions …

Create a new empty document (e.g. within Windows Explorer Right-click New | Text Document)

updateunityprojloc_1

rename the file LaunchUnity.vbs

updateunityprojloc_2

Open the Windows registry (e.g. regedit.exe) and browse to the key named HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders.  Find the value named Personal.  This is the value returned by the Microsoft SHGetFolderPath API.  It should be of the form C:\Users\<yourname>\Documents.

Make a note of this value.  You will use it later to update your Visual Basic script.

Now, right-click on your Unity3d icon and select Properties. Select the Shortcut tab and locate the Target textbox which contains the path to Unity3d on your system.  It should be of the form “C:\Program Files (x86)\Unity\Editor\Unity.exe”  but can vary based on where you installed Unity and if you are running 32-bit or 64-bit Windows.

Make a note of this value.  You will use it later to update your Visual Basic script.

updateunityprojloc_4

Now create the Visual Basic script to update the folder name and launch Unity.  Right-click on the “LaunchUnity.vbs” file you created and select Edit.

updateunityprojloc_5

Copy and paste the following Visual Basic script code into the LaunchUnity.vbs file

Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal", "C:\YOUR\PROJECT\FOLDER", "REG_SZ"
sReturn = WshShell.Run("""c:\Program Files (x86)\Unity\Editor\Unity.exe""" , 0, True)
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal", "C:\YOUR\PERSONAL\FOLDER", "REG_SZ"

Replace the three strings “C:\YOUR\PROJECT\FOLDER”, “c:\Program Files (x86)\Unity\Editor\Unity.exe”,  and “C:\YOUR\PERSONAL\FOLDER” with the default path you want to save Unity projects, the path to unity.exe, and your existing personal folder respectively.  Warning: make sure you do not use a trialing \ on the paths or that will break the vbs script.

For example,  here is my final vbs script using “G:\UnityProjects” as my custom project location and “C:\Users\andrew\Documents” as my existing personal folder.

Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal", "G:\UnityProjects", "REG_SZ"
sReturn = WshShell.Run("""c:\Program Files (x86)\Unity\Editor\Unity.exe""" , 0, True)
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal", "D:\Users\andrew\Documents", "REG_SZ"

Launching Unity

When you want to use the new custom project location, simply launch Unity via the new LaunchUnity.vbs script you just created.

Verify the custom project location

Launch Unity via the LaunchUnity.vbs script you just created.  Unity should launch as usual.  If it does not then go back and verify you followed all steps correctly.

From Unity, select File | New Project … and you should see your new custom project location.  Easy!

updateunityprojloc_7

While Unity is running, you can view the Personal key in Windows regedit.exe.  Press F5 in regedit to refresh the view.  You will notice that it is set to you custom folder name.

updateunityprojloc_61

When you close Unity, the Personal key will automatically revert back to its previous value.

updateunityprojloc_3

Wrap up:

So, when ever you want to create a new project in Unity, simply open Unity with the LaunchUnity.vbs script.  As a benefit, once the new project is created, Unity will automatically close itself and re-open so the Personal folder will be reverted back to normal after your new project is open!

 Pros:

  • Simplify new project creation in Unity3d
  • Guarantee all new projects are placed within your developer storage
  • Easy one-click launch of Unity3d configures the project location folder and terminating Unity3d automatically reverts your personal folder to its default value
  • Since Unity automatically closes and re-opens after creating a new project the Personal folder will be reverted automatically after creating a new project

Cons:

  • All programs requesting the Personal folder via the Microsoft SHGetFolderPath API while Unity3d is running will get the custom folder you defined for Unity3d.  You can shut-down Unity to automatically revert the original folder name

 

Localizing Windows applications

Background:

The amazing global economy opens many doors to your software product. Localizing your software in different languages will improve its success. While many people whose primary language is not English can probably trudge their way through your non-localized English software, a localized version of your software will always be a benefit; both to your customers and your product viability.

The task of localizing software varies based on the platform (iOS, Android, Windows desktop, Linux, etc) as well as the language being used (Java, C#, C++, Objective C, etc). Many old-school software engineers might recall a time when localization was designed and coded in-house; typically once, and then that software code was re-used on other projects. Regardless, the process was typically tedious and prone to bugs and glitches. Fortunately, today, the major development platforms offer simple localization features built-into their developer stack. This post will discuss localization of Windows applications using C#. View this other post regarding localization in Java on Android.

The task:

Okay, so you just created a cool Windows application in C# and now you’ve been tasked with localizing it into fourteen different languages. After staring at your non-localized application project in Visual Studio and searching the Internet you probably have some confusion about how difficult localizing your project actually is. I’ve seen many people obfuscate the simplicity of the task. There are various methods, but if you follow some simple rules, the process can be very painless. Adding new languages to a localization-ready project at any time in the project cycle is a simple process too!

Step by step:

Open your project in Visual Studio. From the solution Explorer right-click on you project name and select Add | New Folder and name the folder Resources

Create resource folder in Visual Studio
Create resource folder in Visual Studio

 

From the Installed Templates section, select Visual C# Items and then select Resource Files. This first resource file will contain your default native English resources strings. Name the file generically resources.resx to simplify the process.

Select Resource Dll to add to project
Select Resource Dll to add to project

A new resource file will be created and will be displayed in Visual Studio ready for you to add the resource strings.

New native English resource file created
New native English resource file created

Enter each of the strings used in your project in the resx file.   In the Name column enter a unique name that you can reference the string from within your code. I recommend prefixing each of your string names with str_ to make your source code easier to read. Enter the string as it will appear to the user in your software under the Value column. You will do this for each string in your project. Don’t worry if you don’t enter all of the strings at this time, you can always return and enter more strings.   The key to success here is to ensure that your first resource file is complete, and contains ALL strings, before you begin to create additional resource files. You can add new strings at any time but make sure you add each new string to ALL resx files you create.

Native English resources added to resx file
Native English resources added to resx file

From the Solution Explorer, open one of your dialog files. Note, you will obviously have multiple dialog files for a single project; you will need to process each file. In the Design layout window make sure the dialog is selected then go to the Properties page and select the Events button (this will appear as a lightning bolt).

Add the Load() event handler to each dialog resource
Add the Load() event handler to each dialog resource

Scroll down to the “Load” event and double-click. The wizard will automatically create a new Load function, if it does not exist, which will be called by the Windows framework when the dialog is loaded but before it is displayed to the user. This is the preferred Windows event to handle updating resources in dialog boxes.

Event handler automatically added
Event handler automatically added

Now, within the Load() event handler, set the Text field for each of the controls within your dialog to a string you created in the resource file. You will use the Resources.Resource class to resolve each string

private void Form_Login_Load(object sender, EventArgs e)
{
  label_userName.Text = Resources.Resource.str_user_name;
  label_password.Text = Resources.Resource.str_password;
  button_login.Text = Resources.Resource.str_login;
}

Now, simply repeat the steps above for each dialog in your project. If you do this during initial development of your project it makes the task much easier. At this point, you have a fully ready to localize project.

Now that you have all your dialogs using resources files and you have a base native English resource file, you can start creating new resources files; one for each language you want your project to support. The steps are similar to creating the base English resource file above. Right-click on the Resources folder and select Add | New Item then select Resources File and name the file based on the language being added. You must use the filename convention resources.XX.resx where XX is the two-letter language identifier. Doing so will greatly simply the localization process. For example, to create a German resource file create the file named Resource.de.resx and to create a French resource file create the file named Resource.fr.resx.

Create a new resource file for localized text
Create a new resource file for localized text

Now you have a new resource file to contain the strings for a new language.   Now return to the base native English Resource.resx file and click on the box in the upper-left corner (or press Control-A) to select all of the strings and press Control-C to copy the strings to the Windows clipboard. Return to the newly created Resouce.de.resx file and press Control-V to paste the strings from the Windows clipboard into the new resx file.

Copy existing English resource strings into the new resource file
Copy existing English resource strings into the new resource file

It’s that simple! Now, you have a localization-ready project which supports two languages. You can easily add new languages by creating new resources files under the Resources folder at any time. The key is to use the naming convention Resource.XX.resx as discussed above.

When you build your project, the resource files will automatically be created under subfolders named XX, where XX is the language code of the Resource.XX.resx file you created.

Language folders automatically created during Visual Studio build
Language folders automatically created during Visual Studio build

Each subfolder will contain the resource strings for the specific language

Language dll located in its language folder
Language dll located in its language folder

Finally, provide the Resource.XX.resx files you created to your localization provider such as inwhatlanguage.com for localization. When the resx files are returned to you, simply drop them into your project overwriting the previous temporary English versions and rebuild your project.

Make sure your project installer creates an identical folder structure under the folder containing your executable (this folder structure should look identical to the folder created by Visual Studio after a build).   When you project starts it will automatically search that folder structure for a supporting language id. If the resource dll for that language exists then the resource file will be loaded. If it does not exist then the default native English resource file will be used.

Debugging:

Debugging new localization files is simple.  Simply add the following lines of temporary code to the primary Load() event handler in your project

using System.Globalization;

private void Form_Login_Load(object sender, EventArgs e)
{
   Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");        //e.g. de-DE   zh-CN   ja-JP

Set the CultureInfo string specified in the constructor to the language-region code you wish to test.  For example, to test German in Germany use “de-DE” and for Chinese in Hong Kong use “zh-HK.”   A full list of language and region codes can be found here.  Rebuild and run your project and the strings from the specified locality will be displayed automatically.

Tips:

  • Even if you don’t have current plans to support localization, always build new projects targeted for localization by moving your text strings into a resource file and use the Resources.resource class to update all your user visible components
  • Always name resource files with the format Resource.XX.resx (where XX is the two-letter language id) to simplify the build process
  • Make sure your first native English resource file contains all of the strings before creating localized resource files. Adding new (or forgotten) strings to each localized resource file can be a painful repetitious task prone to errors