Showing posts with label Windows Vista. Show all posts
Showing posts with label Windows Vista. Show all posts

Thursday, November 6, 2008

A quick tip: Check with VB.NET if operating system is Windows Vista

One day I fixed some old VB.NET application that works fine in Windows XP and Windows 2000. The problem was, it didn't work as expected with Windows Vista.

I located the spot which handled Windows registry in a way that did not work in Vista and I was quickly able to write a Vista-compatible version. Since it was not possible to have two versions of the application and I did not have time to re-write that part of the code to be compatible with all Windows versions, I decided to include both code snippets in the same version and just check operating system.

Checking operating system version with VB.NET is an easy job and I wrote a little wrapper for my Windows Vista check:

''' <summary>
''' Returns true if the OS version is any Vista version
''' </summary>
''' <returns>True if Vista OS</returns>
''' <remarks></remarks>
Public Function IsVista() As Boolean
  '
  If Environment.OSVersion.Version.Major = 6 Then
    Return True
  Else
    Return False
  End If

End Function

In the application I use it in the following way:

If IsVista() Then
  ' Vista specific code
Else
  ' Code for older Windows versions
End If

That saved me a lot of time and testing.

Friday, September 19, 2008

Get default application in Windows XP or Vista with VB.NET

When you double click a file, Windows Explorer opens it with associated default application. Windows Explorer determines current default application with file's extension and with information that is stored in the Windows registry. Obtaining the default application with VB.NET is not a difficult task. Default application can be found in both Windows XP and Windows Vista with the same VB.NET code.

Windows stores known file extensions in HKEY_CLASSES_ROOT registry hive. So, the first thing is to check if file extension exists in the registry. If the file extension exists, it has a so called ProgID associated with it. For example, file extension ".txt" has a ProgID "txtfile". Next step is to locate this ProgID registry key and check if it has a sub key "\shell\open\command". This sub key contains finally the path and the name of the default application. In the case of "txtfile" registry key, the default application could be "%SystemRoot%\system32\NOTEPAD.EXE %1".

The VB.NET function below returns the name of the default application, if it exists. Additionally it returns a ready-to-execute string which can be used with VB.NET's Shell command. First parameter in the function is a parameter string for default application. Second parameter is the actual file extension we are searching for.

''' <summary>
''' Return registered application by file's extension
''' </summary>
''' <param name="ParamFileName">Parameter for ShellAppName</param>
''' <param name="FileExtension">File extension</param>
''' <param name="AppName">Returns application name if any</param>
''' <param name="ShellAppName">Returns a string with application name and file name as its parameter</param>
''' <returns>True if the default application for this file type was found</returns>
''' <remarks>This function is Windows XP and Vista compatible</remarks>
Public Function GetRegisteredApplication(ByVal ParamFileName As String, ByVal FileExtension As String, _
 ByRef AppName As String, ByRef ShellAppName As String) As Boolean
 '
 ' Return registered application by file's extension
 '
 Dim StrExt As String
 Dim StrProgID As String
 Dim StrExe As String
 Dim oHKCR As RegistryKey ' HKEY_CLASSES_ROOT
 Dim oProgID As RegistryKey
 Dim oOpenCmd As RegistryKey
 Dim TempPos As Integer

 Try
   ' Add starting dot to extension
   StrExt = "." & FileExtension
   ' Get Programmatic Identifier for this extension
   Try
     oHKCR = Registry.ClassesRoot
     oProgID = oHKCR.OpenSubKey(StrExt)
     StrProgID = oProgID.GetValue(Nothing).ToString
     oProgID.Close()
   Catch
     ' No ProgID, return false
     Return False
   End Try
   ' Get associated application
   Try
     oOpenCmd = oHKCR.OpenSubKey(StrProgID & "\shell\open\command")
     StrExe = oOpenCmd.GetValue(Nothing).ToString
     oOpenCmd.Close()
   Catch
     ' Missing default application
     Return False
   End Try
   TempPos = StrExe.IndexOf(" %1")
   If TempPos > 0 Then
     ' Replace %1 placeholder with ParamFileName
     StrExe = StrExe.Substring(0, TempPos)
     AppName = StrExe
     StrExe = StrExe & " " & Convert.ToChar(34) & ParamFileName & Convert.ToChar(34)
     ShellAppName = StrExe
   Else
     ' No %1 placeholder found, append ParamFileName
     AppName = StrExe
     ShellAppName = StrExe & " " & Convert.ToChar(34) & ParamFileName & Convert.ToChar(34)
   End If
   Return True
 Catch ex As Exception
   Return False
 End Try

End Function

The function returns value True if the default application was found. If the function returns False, there was some error or some issue with registry permissions. In the latter case see System.Security.AccessControl namespace. That namespace provides methods to handle permission issues and how to set registry permissions.

To test this function, here's a code snippet for testing purpose. First create a new text file to C-drives root and name it "test.txt". When you run this snippet, it opens "test.txt" file with Notepad and displays message box:

Default application for text files

Default application for text files

This is, if you have Notepad as your default text editor.

Dim ApplicationName As String
Dim ShellApplicationName As String
Dim FileExtension As String
Dim ParamFileName As String

ApplicationName = ""
ShellApplicationName = ""
FileExtension = "txt"
ParamFileName = "C:\test.txt"
If GetRegisteredApplication(ParamFileName, FileExtension, ApplicationName, ShellApplicationName) Then
 Shell(ShellApplicationName)
 MessageBox.Show("Default application for the files of type '" & FileExtension & "'" & _
   " is '" & ApplicationName & "'", _
   "Default Application", _
   MessageBoxButtons.OK, _
   MessageBoxIcon.Exclamation)
Else
 MessageBox.Show("No default application found for the files of type '" & FileExtension & "'", _
   "Default Application", _
  MessageBoxButtons.OK, _
  MessageBoxIcon.Exclamation)
End If

Final words of warning. Always be careful when handling registry with your application. I have tested and used this code, and it does only read from the registry. But I will not give any kind of warranty if your registry gets messed up. So backup your registry first or otherwise make sure that you can restore your system if something goes wrong. You use this code totally at your own risk!

Tuesday, September 16, 2008

Make VB.NET application to start up from registry

There are basically two ways to start application when Windows starts. First and maybe the easiest way is to copy a shortcut to your application in Startup folder. Second way is to start up VB.NET application from the Windows registry.

Some installer applications can do this for you. But if you want to give users the option not to start application when Windows starts, you have to deal application starting programmatically.

Also, you have to make the decision if the application starts always when the Windows starts or if it starts only for the current user. The code below has a parameter which allows you to choose, which way the application starts.

A few words of warning. Always be careful when changing registry with your application. I have tested and used the code below. But I will not give any kind of warranty if your registry gets messed up. So backup your registry first or otherwise make sure that you can restore your system if something goes wrong. You use this code totally at your own risk!

Start application from the registry

Starting your VB.NET application from the registry is done by adding it to either HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry hive or HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry hive.

Imports Microsoft.Win32
''' <summary>
''' Installs an application to start from the registry when Windows starts
''' </summary>
''' <param name="AppName">Application's name</param>
''' <param name="AppPath">Full path to the application</param>
''' <param name="InstallToLocalMachine">Install to LM, otherwise install to current user</param>
''' <returns>True if successfully installed</returns>
''' <remarks>Compatible with Windows XP and Vista</remarks>
Public Function StartUpInstall(ByVal AppName As String, ByVal AppPath As String, _
 ByVal InstallToLocalMachine As Boolean) As Boolean
 '
 ' Install to registry
 ' If LM then uses HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
 ' Otherwise uses HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
 '
 Dim RegRoot As RegistryKey
 Dim RegKey As RegistryKey

 Try
   If InstallToLocalMachine Then
     RegRoot = Microsoft.Win32.Registry.LocalMachine
     RegKey = RegRoot.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", _
       RegistryKeyPermissionCheck.ReadWriteSubTree, _
       Security.AccessControl.RegistryRights.SetValue)
     RegKey.SetValue(AppName, AppPath, RegistryValueKind.String)
     Return True
   Else
     RegRoot = Microsoft.Win32.Registry.CurrentUser
     RegKey = RegRoot.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", _
       RegistryKeyPermissionCheck.ReadWriteSubTree, _
       Security.AccessControl.RegistryRights.SetValue)
     RegKey.SetValue(AppName, AppPath, RegistryValueKind.String)
     Return True
   End If
 Catch ex As Exception
   Return False
 End Try

End Function

If everything goes right, the function returns True. Otherwise operation failed. The most common reason for failure is inadequate permissions to modify the registry.

Removing application from registry

If you do not want to start the application from the registry it can be done simply by deleting application's entry from the registry.

Imports Microsoft.Win32
''' <summary>
''' Uninstalls an application not to start from the registry when Windows starts
''' </summary>
''' <param name="AppName">Application's name</param>
''' <param name="InstallToLocalMachine">Uninstall from LM, otherwise uninstall from current user</param>
''' <returns>True if successfully uninstalled</returns>
''' <remarks>Compatible with Windows XP and Vista</remarks>
Public Function StartUpUnInstall(ByVal AppName As String, _
 ByVal InstallToLocalMachine As Boolean) As Boolean
 '
 ' Uninstall from registry
 ' If LM then uses HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
 ' Otherwise uses HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
 '
 Dim RegRoot As RegistryKey
 Dim RegKey As RegistryKey

 Try
   If InstallToLocalMachine Then
     RegRoot = Microsoft.Win32.Registry.LocalMachine
     RegKey = RegRoot.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", _
       RegistryKeyPermissionCheck.ReadWriteSubTree, _
       Security.AccessControl.RegistryRights.SetValue)
     RegKey.DeleteValue(AppName, False)
     Return True
   Else
     RegRoot = Microsoft.Win32.Registry.CurrentUser
     RegKey = RegRoot.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", _
       RegistryKeyPermissionCheck.ReadWriteSubTree, _
       Security.AccessControl.RegistryRights.SetValue)
     RegKey.DeleteValue(AppName, False)
     Return True
   End If
 Catch ex As Exception
   Return False
 End Try

End Function

Again, if everything goes right, the function returns True. Otherwise operation failed. And the most common reason for failure is inadequate permissions to modify the registry.

Compatibility with Windows Vista

I have used this code with standard user account in Windows Vista without any problems. I have also tested it with Windows XP, but not with any earlier Windows versions. However, if you do get problems with registry permissions, check out System.Security.AccessControl namespace. It provides methods to handle permission issues.