I'm getting a NullReferenceException error on some simple code for handling a button click event. I've still got just a bit of code to add at the very end to actually display the value from "TcpAddr" on the messagebox. This will allow you run the program but clicking the button causes it to throw the error.
Also: Is it better practice to move the actual query out of the click event and just make the click event handle MessageBox.Show()?
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
namespace LiteSwitch
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
RegistryKey RegKey = Registry.LocalMachine;
RegKey = RegKey.OpenSubKey("SOFTWARE\\Altiris\\Client Service");
object CurrDS = RegKey.GetValue("TcpAddr"); //This line causes the NRE Error
MessageBox.Show("Current DS:");
}
}
}
If you are sure that the registry key actually exists (use Regedit.exe) then you've got a problem if you are running on the 64-bit version of Windows. A VS2010 project is forced to run in 32-bit mode by default, it sees another set of registry keys.
Project + Properties, Build tab, Platform Target = Any CPU. Repeat for the Release configuration.
My guess is that
RegKey = RegKey.OpenSubKey("SOFTWARE\\Altiris\\Client Service");
Is returning a null, probably because that key doesn't exist.
Verify the key exists and the provided reg path is correct.
According to the documentation for OpenSubKey(), "If the specified subkey cannot be found, then null is returned." If a variable is null, calling a method on it will throw that exception.
"Is it better practice to move the actual query out of the click event and just make the click event handle MessageBox.Show()?"
If you take it out, it won't necessarily reflect the current value of the key if, for example, another program modifies it while your program is running. Depending on your program, this may be okay.
If it's throwing a NRE it's because it can't find the value, make sure it's spelled correctly or that the previous line isn't also returning null.
Related
I have a c# application that launches during startup with the next code below.
On the first windows form I have two textboxes that should be filled with data from Properties.Settings.Default, but they are empty.
If I close the app and start it again, the textboxes are filled with the correct values.
What can be the issue?
RegistryKey rk = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rk.SetValue("", Application.ExecutablePath);
I set the values in the constructor of the form with the following code:
if (Properties.Settings.Default.dbusername != string.Empty)
{
textBoxLoginUsername.Text = Properties.Settings.Default.dbusername;
string readable = EncryptionHelper.Decrypt(Properties.Settings.Default.dbpassword);
textBoxLoginPassword.Text = readable;
}
Your code shows a registry key assignment that is potentially problematic.
First, it attempts to set the default ("") value of
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
It should be making named key for your startup app e.g.
Second, is it being set in the startup app itself? This is contrary to Microsoft documentation.
Run and RunOnce Registry Keys -
A program that is run from any of these keys should not write to the key during its execution because this will interfere with the execution of other programs registered under the key.
Instead, we'll "do the right thing" by establishing this key in the installer project for the app:
Moving on...
Settings
Showing a "mystery line" like:
string readable = EncryptionHelper.Decrypt(Properties.Settings.Default.dbpassword)
makes it more difficult to diagnose the question that you actually asked. The points made by Panagiotis Kanavos are excellent, but notice that we're talking about that now instead of your original ask. I suggest you solve the main issue first using a Minimal Reproducible Example leaving out the authentication scheme. Then we take the straightforward case of two startup settings:
The textboxes are initialized here:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
textBoxLoginUsername.Text = Properties.Settings.Default.dbusername;
textBoxLoginPassword.Text = Properties.Settings.Default.dbpassword;
}
}
And after installing the app and restarting the PC we see that things are "so far so good".
Things to check
Without seeing more code, I can only make general suggestions.
Consider writing a startup log file to your app's AppData folder tracing values at various execution points.
Look for uncaught or "swallowed" exceptions that might skip your textbox initialization code.
Check for race condition where Properties.Settings.Default.Save() might be being called before textboxes are initialized.
Since there's "probably" a mechanism for saving login changes, make sure any event handlers are attached after the InitializeComponents has run. For example:
Initializing a Persist scheme
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
textBoxLoginUsername.Text = Properties.Settings.Default.dbusername;
textBoxLoginPassword.Text = Properties.Settings.Default.dbpassword;
buttonLogin.Click += onClickLogin;
}
private void onClickLogin(object? sender, EventArgs e)
{
if(tryLoginWithCredentials())
{
Properties.Settings.Default.dbusername = textBoxLoginUsername.Text;
Properties.Settings.Default.dbpassword = textBoxLoginUsername.Text;
Properties.Settings.Default.Save();
Text = $"Logged in as {Properties.Settings.Default.dbusername}";
}
}
private bool tryLoginWithCredentials() => true; // Succeeded (for testing purposes).
}
If I need To Make Variables that take value by user at the first run and keep this value when the application restarted and be able to change it any time we need that
How can I do that in C# public Class??
Keeping the value, even if the application is restarted can be referred to as 'keeping state'. If you want the application variables to keep state, even through a restart, you will have to store them somewhere else (a database perhaps) and have some logic to then read from the database when the app starts.
Your question is quite generic but if you provided code examples you may get a more detailed answer.
a Class may not be needed for it will be just another class which is rather not needed to be implemented.
Use a form instead (based on your tag, WinForm)
Let this be the form used for this solution
Open solution explorer and double click Properties. Upon opening the Application Properties, click Settings on the left side and make a variable as shown on picture below
Set the form to auto close if the boolean settings is set to true and do the other way around if not. Then you must set the btnSubmit to make the bool setting true upon clicking. Let your application concept's code be as follows. (See picture below)
(IF YOU CAN'T SEE THE CODE IN THE PICTURE DUE TO RECEIVING CAN'T HANDLE REQUEST FROM IMGUR, the following codes are what the last picture contains)
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (Properties.Settings.Default.launchedFirstTime == true)
{
Close();
}
}
private void btnSubmit_Click(object sender, EventArgs e)
{
Properties.Settings.Default.firstTimeString = txtFirstTimeString.Text;
Properties.Settings.Default.launchedFirstTime = true;
Close();
}
}
}
EDIT:
HERE IS THE DEBUGGING OF THE APPLICATION. IT DOES SET VALUES
(See firstTimeString and launchedFirstTime in the LOCALS, found at the lower left of the picture)
you can use xml or txt files to write these values and amend when you need. its just a work around.
Thanks
When I create a new project, I get a strange behavior for unhandled exceptions. This is how I can reproduce the problem:
1) create a new Windows Forms Application (C#, .NET Framework 4, VS2010)
2) add the following code to the Form1_Load handler:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
I would expect that VS breaks and shows an unhandled exception message at the second line. However, what happens is that the third line is just skipped without any message and the application keeps running.
I don't have this problem with my existing C# projects. So I guess that my new projects are created with some strange default settings.
Does anyone have an idea what's wrong with my project???
I tried checking the boxes in Debug->Exceptions. But then executions breaks even if I handle the exception in a try-catch block; which is also not what I want. If I remember correctly, there was a column called "unhandled exceptions" or something like this in this dialog box, which would do excatly what I want. But in my projects there is only one column ("Thrown").
This is a nasty problem induced by the wow64 emulation layer that allows 32-bit code to run on the 64-bit version of Windows 7. It swallows exceptions in the code that runs in response to a notification generated by the 64-bit window manager, like the Load event. Preventing the debugger from seeing it and stepping in. This problem is hard to fix, the Windows and DevDiv groups at Microsoft are pointing fingers back and forth. DevDiv can't do anything about it, Windows thinks it is the correct and documented behavior, mysterious as that sounds.
It is certainly documented but just about nobody understands the consequences or thinks it is reasonable behavior. Especially not when the window procedure is hidden from view of course, like it is in any project that uses wrapper classes to hide the window plumbing. Like any Winforms, WPF or MFC app. Underlying issue is Microsoft could not figure out how to flow exceptions from 32-bit code back to the 64-bit code that triggered the notification back to 32-bit code that tries to handle or debug the exception.
It is only a problem with a debugger attached, your code will bomb as usual without one.
Project > Properties > Build tab > Platform target = AnyCPU and untick Prefer 32-bit. Your app will now run as a 64-bit process, eliminating the wow64 failure mode. Some consequences, it disables Edit + Continue for VS versions prior to VS2013 and might not always be possible when you have a dependency on 32-bit code.
Other possible workarounds:
Debug > Exceptions > tick the Thrown box for CLR exceptions to force the debugger to stop at the line of code that throws the exception.
Write try/catch in the Load event handler and failfast in the catch block.
Use Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) in the Main() method so that the exception trap in the message loop isn't disabled in debug mode. This however makes all unhandled exceptions hard to debug, the ThreadException event is pretty useless.
Consider if your code really belongs in the Load event handler. It is very rare to need it, it is however very popular in VB.NET and a swan song because it is the default event and a double-click trivially adds the event handler. You only ever really need Load when you are interested in the actual window size after user preferences and autoscaling is applied. Everything else belongs in the constructor.
Update to Windows 8 or later, they have this wow64 problem solved.
In my experience, I only see this issue when I'm running with a debugger attached. The application behaves the same when run standalone: the exception is not swallowed.
With the introduction of KB976038, you can make this work as you'd expect again. I never installed the hotfix, so I'm assuming it came as part of Win7 SP1.
This was mentioned in this post:
The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
Here's some code that will enable the hotfix:
public static class Kernel32
{
public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;
[DllImport("Kernel32.dll")]
public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);
[DllImport("Kernel32.dll")]
public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);
public static void DisableUMCallbackFilter() {
uint flags;
GetProcessUserModeExceptionPolicy(out flags);
flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
SetProcessUserModeExceptionPolicy(flags);
}
}
Call it at the beginning of your application:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
I've confirmed (with the the simple example shown below) that this works, just as you'd expect.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
So, what I don't understand, is why it was previously impossible for the debugger to handle crossing kernel-mode stack frames, but with this hotfix, they somehow figured it out.
As Hans mentions, compile the application and run the exe without a debugger attached.
For me the problem was changing a Class property name that a BindingSource control was bound to. Running without the IDE I was able to see the error:
Cannot bind to the property or column SendWithoutProofReading on the
DataSource. Parameter name: dataMember
Fixing the BindingSource control to bind to the updated property name resolved the problem:
I'm using WPF and ran into this same problem. I had tried Hans 1-3 suggestions already, but didn't like them because studio wouldn't stop at where the error was (so I couldn't view my variables and see what was the problem).
So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.
However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).
What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...
void Window_Loaded(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Thread.Sleep(50);
CrossThread(() => { OnWindowLoaded(); });
}).Start();
}
void CrossThread(Action a)
{
this.Dispatcher.BeginInvoke(a);
}
void OnWindowLoaded()
{
...do my thing...
This way studio would break right where an uncaught exception occurs.
A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:
bool firstLoad = true; //flag to detect first form_shown
private void Form1_Load(object sender, EventArgs e)
{
//firstLoad = true;
//dowork(); //not execute initialization code here (postpone it to form_shown)
}
private void Form1_Shown(object sender, EventArgs e)
{
if (firstLoad) //simulate Form-Load
{
firstLoad = false;
dowork();
}
}
void dowork()
{
var f = File.OpenRead(#"D:\NoSuchFile756.123"); //this cause an exception!
}
My visual studio 2012 had stopped showing debugger exceptions. I mean this dialog that shows me exact exception and line: http://i.msdn.microsoft.com/dynimg/IC286574.jpg.
In example if I run following code in visual studio:
using System;
using System.Windows.Forms;
namespace debugger_test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
int zero = 0;
int a = 1/zero; // it hangs on this line
MessageBox.Show("this messagebox is never shown");
}
}
}
then it doesn't return any exception. It just starts and no code after int a = 1/zero; is executed.
But when I run the same program alone as a compiled .exe then it returns this kind of exception: http://i.msdn.microsoft.com/dynimg/IC8596.gif in this case about DivideByZeroException.
It happens to any project.
Repairing and reinstalling visual studio didn't resolve it. Although some VS settings were kept after reinstallation.
I am not aware of any changes that could cause it and I am not sure when it started happening.
How may I get debugger from the first picture working in visual studio again? Thanks.
EDIT: Sascha's advise didn't completely resolve my problem.
I can't figure out how to not throw an exception that is inside try{} code but throw an exception that is not inside try{}.
Following codes either only throw an exception or only hangs on int gg = 1/a; line no matter wherher I use try/catch or not.
public void Form1_Load(object sender, EventArgs e)
{
int zero = 0;
int a = 1/zero; // this line should throw an exception
MessageBox.Show("to be never shown");
}
__
public void Form1_Load(object sender, EventArgs e)
{
try
{
int zero = 0;
int a = 1/zero;
MessageBox.Show("to be never shown");
}
catch
{
MessageBox.Show("catched"); // it should show this messagebox
}
}
Any ideas how to set it up correctly? Thanks.
Have a look at this question about a known problem on x64 systems:
This is a known issue on 64-bit OS platform. The reason is that the
64bit OS core does not allow user mode exception through kernal mode
stacks. The exception is swallowed by OS sliently. That happens in
FormLoad handler, because it is called in an OS callback. 32bits OS
doesn't do this, so it doesn't repro there.
The OS team is investigating related issues. In the mean time, you do
have to work around this issue. Turning on "Stop on first chance
exception" will make the debugger to stop in this scenario. But it
does make the debugger to stop very often, so you might want to do
this only when you find a problem
It's a bug / limitation of Visual Studio that happens when your PC is 64 bit and the exception happens in form load.
This seems to have fixed it for me so far.
In Registry Editor, locate the following registry subkey: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Create a registry entry of the DWORD value.
Name the new registry entry DisableUserModeCallbackFilter.
Set the value of the DisableUserModeCallbackFilter registry entry to 1.
found there http://support.microsoft.com/kb/976038/en-us
And it has to be compiled as release. Ridiculous.
See this:
MAIN FORM CODE:
public partial class Principal : Form
{
string directoriodelarchivo;
...
....
private void opendicomdir_Click(object sender, EventArgs e)
{
directoriodelarchivo = System.IO.Path.GetDirectoryName(ofd.FileName);
var form = new dicomdirselectionform(_reader);
form.ShowDialog();
}
}
I do some stuff in the other form and then press a button to return to the main form, thing is that when I returin to the main form, the variable "directoriodelarchivo" IS EMPTY!
Why that is? I'm new to C# and I'm trying to figure out if there's something I'm missing
It's not immediately clear to me what may be causing this. To try to find the reason, I would suggest doing something like this:
Remove all other code that may be altering directoriodelarchivo.
Add some easy way to check the value of directoriodelarchivo after every step in your code. (Example: https://ideone.com/E38zc2)
If this works, try finding the code that you removed in step 1 that's breaking your application by changing directoriodelarchivo. If it doesn't, ofd.FileName might be causing an unsatisfactory value for directoriodelarchivo.
There are 2 causes for that
You re-create this form somehow. So it has value by default.
You change that var in some code. Just try to find references for that var and you will make sure it.
I hope it will help you!