VB.NET read registry - vb.net

Beyond perplexed this time...
The simplest possible line of code works sometimes, sometimes it doesn't. First I thought the issue was that I was trying to read the value of a DWORD, but since I CAN read DWORD values from SOME keys, that must not be the problem. Now the problem seems to be that I can't read from ANY key if the key has a space in the name. Surely this can't be. I refuse to believe that MS didn't account for spaces in registry key paths and names.
So tell me why this doesn't work:
MsgBox(My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\CA\CA ARCserve D2D\WebService", "Port", Nothing))
It just pops up an empty box. And yes, a value does exist in the registry, and yes, I have permission to read the key.
EDIT: Yup, over and over again it seems that you can't read from the registry if there are spaces anywhere in the key name. Seriously?!?
EDIT AGAIN: "Ramhound" says code examples are stupid. Fascinating point of view. However his own suggestion also failed:
Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\ATI Technologies\CBT")
Dim objValue As Object
objValue = key.GetValue("ReleaseVersion")
MsgBox(objValue.ToString())

After an entire wasted day, the solution is to set your VS project to "any cpu" in advanced compile options because if set to x86 and running on a 64bit OS you are limited to the "Wow6432node" in the registry.

It's also worth noting than on a 64 bit version of Windows 7 while running a vb.net app in 32 bit mode, the Wow6432Node key is hidden from you when using a Microsoft.Win32.RegistryKey object. I'd written this code to check which key I needed to read to get the right ODBC Driver subkey:
Dim myReg As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine
Dim myReg_Key As Microsoft.Win32.RegistryKey
myReg_Key = myReg.OpenSubKey("SOFTWARE")
strRegistry_Keys = myReg_Key.GetSubKeyNames()
bool64_Bit_OS = False
For Each strSub_Key As String In strRegistry_Keys
If strSub_Key = "Wow6432Node" Then
bool64_Bit_OS = True
End If
Next
When you do a GetSubKeyNames() on the "SOFTWARE" key you are redirected to SOFTWARE\Wow6432Node
This does make it easier for my code as now I don't need to work out which subkey to look in to find which Oracle ODBC driver to use.
Kristian

Related

Linked SQL table in Access 2003 (!) not updatable

I'm working in a legacy app for the moment, upgrading Access 2003 to link to SQL Server tables (2008 R2 or later). With tables linked by code, I can insert, but not update or delete. I've tried everything on the web, no dice. Details below.
Being terse so not tl;dr.
Tables first created using upsizing wizard. In use, app has to connect to different ones in same schema, so can't just set and forget. Can't do local DSN's, many installs, though DSN file is possible. But problems there too, DSN not found. Details later.
Before the rest: Soon I'm further updating this app to Access 2016 or so. If this is different enough / easier there, I'll wait a few days. Maybe someone could suggest the best refsite for that.
* problem details follow *
Using a DSN and the UI to link a table, I get an editable table. Hurray.
But when I use the code below (found on every refsite), link is made but only selecting and inserting work. Everything else fails fails fails, no matter what.
Public Function LinkToSqlTable(sqlInstance As String, sqlDb As String,
sqlTableName As String, localTableName As String)
Dim linked As New TableDef
' ***factored-out functionality, known to work: reader can ignore*** '
DeleteTable localTableName
' connection-string steps, placeholders replaced by args '
Dim sCnx As String
sCnx = "ODBC;Driver=SQL Server;Server=_instance_;" & _
"Database=_db_;Integrated Security=SSPI"
sCnx = Replace(sCnx, "_instance_", sqlInstance)
sCnx = Replace(sCnx, "_db_", sqlDb)
' linked-table steps '
Set linked = CurrentDb.CreateTableDef(localTableName)
linked.Connect = sCnx
linked.SourceTableName = sqlTableName
CurrentDb.TableDefs.Append linked
' ui '
RefreshDatabaseWindow
End Function
* ID column or permissions? *
I thought the problem was lack of identity column originally, I added one, but no change. At least now I have a PK field like I should. ;-)
When I manually link table, UI demands to know the ID column. So could it still be it? Fine, but how do I set that in code? Searches revealed nothing.
I assume then it's permissions as sites etc. say. I also took all the steps I could think of to fix that. No dice.
* things I've tried *
Aside from the ID-column stuff I said before, these things (not in order):
Since DSN saved as a file, tried using it as exampled, in cnx string. Fail.
Used DSN contents, carefully winnowed & translated, in cnx string. Fail.
Used connection string from the table that I had connected manually with DSN. Fail.
Changed driver in cnx string across all major options, even omitted it. Fail.
Changed security in cnx to Integrated Security=SSPI and other options, and omitted entirely. Fail.
I added my actual local user as exampled, with and without password. Fail.
(Previous few options tried across earlier options, though not 100% coverage.)
In SQL Server, using SSMS, I tried security power:
Added SQS-authentication login to the instance
Matching user to the default db seen here
Gave that login-user read and write permissions in db here (plus others, sometimes)
Added matching id & pw to the cnx string. Fail.
I tried setting up this db in SQS to have let-everyone-do-everything "security" temporarily. Fail.
This, that, and the other thing. Everything fail!!
So a permissions issue? Some way to use DSN file after all? Mismatched permission settings in my cnx string? Boneheaded oversight? Something else that I've missed? I'm pretty good at both SQL Server and Access, but only at a basic level in their security stuff and connection strings are the devil.
* retrieved table properties *
Just in case they help, I retrieved these (after objects added to TableDefs collection).
** This one, done in UI and with DSN and this-is-ID-field, worked with editing: **
Name = dbo_tblSendTo
Updatable = False
DateCreated = 4/19/2016 11:11:40 AM
LastUpdated = 4/19/2016 11:11:42 AM
Connect = ODBC;Description=SQL Server tables for TeleSales 5;DRIVER=SQL Server Native Client 10.0;SERVER=(local)\sqlexpress;Trusted_Connection=Yes;APP=Microsoft Office 2003;WSID=CMSERVER;DATABASE=TS5_General;
Attributes = 536870912
SourceTableName = dbo.tblSendTo
RecordCount = -1
ValidationRule =
ValidationText =
ConflictTable =
ReplicaFilter =
** And this one, from table linked via code, didn't: **
Name = tblSendTo
Updatable = False
DateCreated = 4/19/2016 11:17:51 AM
LastUpdated = 4/19/2016 11:17:51 AM
Connect = ODBC;Description=SQL Server tables for TeleSales 5;DRIVER=SQL Server Native Client
> 10.0;SERVER=(local)\sqlexpress;Trusted_Connection=Yes;APP=Microsoft Office 2003;WSID=CMSERVER;DATABASE=TS5_General;
Attributes = 536870912
SourceTableName = dbo.tblSendTo
RecordCount = -1
ValidationRule =
ValidationText =
ConflictTable =
ReplicaFilter =
* my plea *
So..... Please someone help me out. I don't like feeling stupid like this, and regrettably I need to do this instead of replacing it with .NET code or similar.
Thanks, anyone who can...
Ed.
Alas, I am able to answer my own question.
edited a little since first posted in reply to HansUp's comments
I had added an identity column to the table that I couldn't edit. However, I had not set it up as a primary key. It turns out that using identity doesn't make something a primary key automatically.
But the latter, making it primary key using either of the 2 possible DDL syntaxes, is crucial. Since I thought I had dealt with the no edits without unique key problem, I focused on permissions.
All of the permissions things here, then, are just a sideshow.
The upshot of this is to be sure to add an identity column and make it a primary key if for some reason your original table schema didn't have that.
If I have the time, I will be trimming the question to reflect what I've discovered.

Can't read key?

Ok so I am making this system information application that runs on the desktop, but for some reason this gives me an error.
Error: [ArgumentException was unhandled] Registry key name must start with a valid base key name.
I can see the registry is there.
Dim readValue As String
readValue = My.Computer.Registry.GetValue _
("HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\SYSTEM\CentralProcessor\3","ProcessorNameString",Nothing)
Label9.Text = CStr(readValue)
Edit: This sight just helped me, there was 2 Unicode chars in there.
I think the problem with program permission ,HKEY_LOCAL_MACHINE needs administrator access, in app.manifest
Change
to

How to find the path to the executable of a program

In a VB.NET application I need to set a button to start a program - specifically, Steam. But I need to allow for the user having installed the program somewhere other than the default location "C:\Program Files (x86)\Steam". So all I know is the executable name: "steam.exe".
In searching for an answer it looks like I should be able to get the path using Microsoft.Win32.Registry somehow, but the examples I'm seeing aren't helping me (I guess I'm just not getting how to apply those examples to my situation).
This tutorial gives the example of finding the path to the excel executable:
Dim regKey As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\MICROSOFT\Windows\CurrentVersion\AppPaths\excel.exe")
Dim path As String = regKey.GetValue("Path").ToString
But I'm getting a value of "Nothing" for regKey. Not only that, even if it did get a value for regKey, how would I know the registry path for another program (Steam, in my case)?
And how much will the version of Windows change the possible registry location of a program - if at all?

Detect Operating System

I would like to know how to detect if a persons operating system is Windows 7, I'm a bit new and have no idea how to do this. Please let me know if it is possible and the code to do it.
See the Environment.OSVersion property on MSDN. It is a static property that returns an OperatingSystem object, which has a Version property and you can just check the Major and Minor version numbers to see if it is 6.1 (Windows 7 is actually version 6.1).
Dim osVer As Version = Environment.OSVersion.Version
If osVer.Major = 6 And osVer.Minor = 1 Then
Console.WriteLine("win7!!")
End If
It's easy to use My.Computer.Info.OSFullName.
you need to set up the app.manifest file to get the correct version number. even System.Environment.OSVersion.ToString() ' not gives the correct version if you have not been set the app.manifest
add an app.manifest
Console.WriteLine(My.Computer.Info.OSFullName)
Console.WriteLine(My.Computer.Info.OSVersion)
Console.WriteLine(My.Computer.Info.OSPlatform)
Output:
Microsoft Windows 10 Pro
10.0.18362.0
Win32NT
I'm guessing since you're a bit new that you're actually using VB.NET rather than classic VB 6.
In VB.NET, you can use:
Dim osVersion As String = System.Environment.OSVersion.ToString()
I would use
My.Computer.Info.OSFullName

Executable directory where application is running from?

I need to get the path (not the executable) where my application is running from:
System.AppDomain.CurrentDomain.BaseDirectory()
When I run the above statement with & "/images/image.jpg" on my local machine it works fine but when I install the application on another machine it says it cannot find the file and there is a lot of extra path information some.
I just need the directory of where the app is running. I am coding in VB.NET with Visual Studio 2008.
Thanks!
This is the first post on google so I thought I'd post different ways that are available and how they compare. Unfortunately I can't figure out how to create a table here, so it's an image. The code for each is below the image using fully qualified names.
My.Application.Info.DirectoryPath
Environment.CurrentDirectory
System.Windows.Forms.Application.StartupPath
AppDomain.CurrentDomain.BaseDirectory
System.Reflection.Assembly.GetExecutingAssembly.Location
System.Reflection.Assembly.GetExecutingAssembly.CodeBase
New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase)
Path.GetDirectoryName(Uri.UnescapeDataString((New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase).Path)))
Uri.UnescapeDataString((New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase).Path))
---
Edit October 18, 2021:
Sigh... None of the above work if using net5.0 or net6.0 and publishing app as single-file bundle. Best I got now is:
// This will give you the directory but not the assembly
string basedir = AppContext.BaseDirectory;
// Before you package the app as a single file bundle, you will get the dll.
// But after you publish it, you'll get the exe.
string pathToExecutable = Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe");
Dim strPath As String = System.IO.Path.GetDirectoryName( _
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
Taken from HOW TO: Determine the Executing Application's Path (MSDN)
I needed to know this and came here, before I remembered the Environment class.
In case anyone else had this issue, just use this: Environment.CurrentDirectory.
Example:
Dim dataDirectory As String = String.Format("{0}\Data\", Environment.CurrentDirectory)
When run from Visual Studio in debug mode yeilds:
C:\Development\solution folder\application folder\bin\debug
This is the exact behaviour I needed, and its simple and straightforward enough.
Dim P As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
P = New Uri(P).LocalPath
You could use the static StartupPath property of the Application class.
You can write the following:
Path.Combine(Path.GetParentDirectory(GetType(MyClass).Assembly.Location), "Images\image.jpg")