Getting Windows Service To Read Registry HKLM - vb.net

I've been having a heck of a time trying to get this to work. I wrote both a service and a form application in VB.NET, both of which need to access a registry key to locate a computer that has my database on it. In the forms app it works great, but the service does not. I thought it was a permissions problem so I checked permissions on the server (Windows 2008) and they were fine - I even went as far as to run the service as the admin in case that was the problem but still no joy. Is there something wrong with my code?
I have tried ways to access the registry. The first method just sets the server variable to nothing and the second method the 'rk' variable ends up being nothing (telling me that it cannot even locate the sub key):
Dim server As String = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\EPS\XPV", "Server", Nothing)
and the second one is:
Dim rk As RegistryKey = Registry.LocalMachine.OpenSubKey("\SOFTWARE\EPS\XPV")
The service itself starts up just fine because I'm getting my log messages right after these lines that tell me the value is blank so it just comes down to figuring out why I cannot access the registry in the service even though I can in the forms app.

Either look under HKLM\SOFTWARE\Wow6432Node for your keys/values, or compile your application as 64bit.

Related

LsaAddAccountRights Custom Action Returning Error Code in Windows Server 2012

I have a custom action which is used to elevate users to be able to log on as a service. This gets run during the installer. It works fine for years on every Windows operating system up until Windows Server 2012. When the below code is run on this version of Windows instead of getting a long back of 0 for success I get a different error code back.
LsaAddAccountRights(
IntPtr PolicyHandle,
IntPtr AccountSid,
LSA_UNICODE_STRING[] UserRights,
long CountOfRights)
The problem is the code appears to be different every time and is a very large number, e.g. 102938473.
I run the error code through the following method to get the error code but this returns a different large number which doesn't appear to be a valid error code.
LsaNtStatusToWinError(long status)
I have tried looking these error codes up, but with no luck. They seem to be randomly generated and nonsensical.
If I ignore the returned error code, It appears that the user is successfully allowed to log on as a service. So everything appears to be working, except I am getting an error code back. I could ignore this error code, but what happens when it is a valid error, I may ignore it in the future.
Extra Information
I can run the code that is in the Custom action fine on its own in a console application without error. Only when it is part of the wix installer it seems not to work.
I'd take a look at the WiX Util extensions's User element. The name attribute can be a property. Using the CreateUser, LogonAsService and UpdateIfExists attributes you can take an existing account and grant it the rights. Or perhaps you have more code that you can refactor.
Issue could be with the return type of LsaAddAccountRights in C#.
I was able to solve the issue by changing the return type of LsaAddAccountRights in C# from long to UInt32. Found this information here . This change must be done for LsaNtStatusToWinError and LsaClose as well.

MS Access crashes when trying to close down a connection to Blackbaud's Raiser's Edge API

I am the IT department of a Non-Profit organization. I have a question today which might be too specialized for this forum and I hope I do not waste my time writing it up. We are using Blackbaud's 'Raiser's Edge' (RE) Software (written in VB6 and VB.net as far as I know) to keep track of our membership and donations. We have an MS Access application (have been using it since before we got RE) to process donations and for now I want to keep it and only do minor changes to adapt it to the new software.
The MS Access program is now doing a few calls to the RE API which work great. To login and establish a connection I have to create a new 'REAPI' object and use it for other API calls. That REAPI object has a method called: SignOutOnTerminate which needs to be set to TRUE when creating that object. It is supposed to kill all connections to RE once my application closes. There is no regular .close method.
Once I create the object I can do work as many times as I want and there is no problem at all as far as I can see.
However when trying to close the application or set the object to nothing (Set REAPI = Nothing) Access crashes immediately (It fades out and I get the message that Windows is looking for a solution to the problem. Then Access closes and restarts itself.)
It is more annoying and unprofessional then hindering production but I want to fix it.
The App was developed on Windows 7 64-bit with Access 2010 32-bit. It was tested on Windows XP with Office 2003 or 2007 machines (32-bit) and behaves the same way.
I have posted this problem already on 2 Blackbaud forums and tried a suggested a work around which did not work (kill the process with a shell command and then set the object to nothing). Hopefully I will get more answers soon.
I tried to just exclude the SignOutOnTerminate when creating the object. But got the same behavior.
I looked in the Event Manager --> Application Log and found the Crash. It reported that access crashed because of this dll: C:\Windows\System32\MSVBVM60.dll (It is actually located in the SysWos64 folder as it is a 32-bit application).
Looking up this error I found some suggestions to replace it with an earlier version of the dll, the one which ships with XP. I found a file and tried the suggestion but it still crashed. The error log reported the older version number as faulting so I registered it correctly.
I also created a case with Blackbaud but the rep did not know what the problem is and did not have MS Access installed. He is trying to get his support team to install it for him so he can test and investigate this error.
The last suspicion I have is that the API is causing the error and my code is fine.
But before I make this assumption and until I get my answer from Blackbaud I want to do a final check, but I have run out of ideas for further trouble shooting and resorted to pose this problem in this forum.
Any Ideas?
I realise that this is an old thread and if you have solved this by now then that is great. However this is a known issue with The Raiser's Edge API. If you use .NET with RE's API (which is COM based) there is definitely some resource that is not cleaned up properly. At one point I suspected that it was something to with making use of RE's graphical interface i.e. by calling the regular login method to log you into RE. However even if you log in to RE using the "as a server" method supplying the user name and password it still crashes on exiting the application.
We have an installer that sets up credentials in RE. The installer is in .NET and accesses the RE API. We now show a message just before the end of the application telling users to ignore the impending crash... Not a great solution by any means.

vb.net 2010 - reading from registry doesn't work - win 7

I thought this would be dead simple however....
Right, so all I'm simply trying to do is read a value from my registry. I have been through several examples but can't get any of them to work. I've also tried running my application in Admin mode and still nothing. Can someone please help?
From all my examples that I've tried, I'll use the simplest one.
This works:
Dim val As String
val = Registry.LocalMachine.OpenSubKey("Hardware\Description\System\CentralProcessor\0").GetValue("Identifier").ToString()
MsgBox(val)
This (the one I want) doesn't:
Dim val As String
val = Registry.LocalMachine.OpenSubKey("SOFTWARE\PTSClient").GetValue("ConfigDB").ToString()
MsgBox(val)
THe latter path and value is one that I've manually created in the registry. I've checked the permissions between the two and they are the exact same. I've also tried running the app as administrator. I get a runtime error on the val= line, it says: Use the "new" keyword to create an object instance.
Any ideas? All the various online examples have failed and for the life of me, I can't figure out why...
Cheers,
J
Well, I have tried your code with a sample application compiled for x86 and, as expected, it fails with a null value exception.
I assume you are building an application for x86 mode and running in a 64bit environment.
Of course, if this is not the case, let me know and I will delete this answer.
In the situation outlined above, the calls to read/write in the LocalMachine.Software registry path will be automatically changed by the Operating System to read/write in the Software\Wow6432Node subkey and thus, your code is unable to find your manually inserted key ("SOFTWARE\PTSClient").
This code will give a null value as return from Registry.LocalMachine.OpenSubKey("SOFTWARE\PTSClient") leading to the failure to get the ConfigDB value.
You need to add your keys/values to the Software\Wow6432Node path or compile your application for AnyCPU mode or let your code write the value to the register (it will be redirected to the Wow6432Node).

Object already exists exception in RSACryptoServiceProvider

First let me start by saying I'm sorry if I posted this question in the wrong place. I saw the entry at Object already exists in RSACryptoServiceProvider. I tried the solutions offered there. But, they did not solve my issue. Also, I didn't see an option to re-ask the question.
I have almost the same issue. I have a class that uses RSACryptoServiceProvider that runs in two projects on the same machine and under the same account. Both projects live in the same solution and share the same encryption code. One project, the server, is a Windows service and the other, the client, is a Windows application. They use the RSACryptoServiceProvider to talk to each other over a named pipe using asymmetric encryption. I started out by just having the server run in another Windows form within the same application as the client. Everything ran fine. Then, I moved the server to a Windows service.
The Windows service starts up fine. It seems to be able to create it's instance of the RSACryptoServiceProvider fine. But, when the client, which runs in the Windows application, starts up it gets a runtime error when it tries to create it. Here is the code that runs in both projects.
rule = New CryptoKeyAccessRule("everyone", CryptoKeyRights.FullControl, AccessControlType.Allow)
csp = New CspParameters
csp.KeyContainerName = _KeyContainerName
csp.Flags = CspProviderFlags.UseMachineKeyStore
csp.CryptoKeySecurity = New CryptoKeySecurity()
csp.CryptoKeySecurity.SetAccessRule(rule)
//Object already exists exception happens here
rsa = New RSACryptoServiceProvider(_KeySize, csp)
As you can see, I have the code that sets the access rule as mentioned in the other post on this subject. Unfortunately, this did not solve my issue. Is there anything else that needs to change?

Registry.CurrentUser.OpenSubKey returns Nothing when called from a Service

In a VB.NET application that runs as a service, I am getting a value of "Nothing" returned when I use Registry.CurrentUser.OpenSubKey(). The same code executes correctly when the application runs in desktop mode. I am not much on VB.NET and unfortunately, this is not my code.
Code:
Dim regURL As String = "Software\MyCompany\" + _
System.Reflection.Assembly.GetCallingAssembly.GetName.Name + _
"\Settings"
regKey = My.Computer.Registry.CurrentUser.OpenSubKey(regURL, True)
The regKey is Nothing when used by a service. Desktop returns a valid registry key object to which I feel verifies the URL. Any ideas I am using CurrentUser because this code does not work with LocalMachine when operating on Windows Server 2008.
Thanks in advance,
Craig
For this to be a valid test you have to ensure that your service is configured at installation time to run as the same account that you used for desktop testing. Are they the same?
If not, the registry values will be different since CurrentUser is an alias for user-specific information - not the same for each user.
If they don't match, you should be able to retest by altering the service settings via AdminstrativeTools -> Services - right click your service and select Properties, then alter the service account thru the Log On tab.