I'm using Visual Studio 2013 to create a Visual C# Windows Forms Application and I'm not using the Designer to setup the form.
I'm trying to use a Dictionary to store Bitmaps so that I can call them later by name. But when I debug the script I get the error:
An unhandled exception of type 'System.NullReferenceException' occurred in SimpleForm.exe
Additional information: Object reference not set to an instance of an object.
From the line:
width = imgLetters["a"].Width;
Any help would be greatly appreciated.
Cut down version of code which still produces the error:
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace SimpleForm
{
public class Test : Form
{
static Bitmap bmpLetterA;
static Bitmap bmpLetterB;
static Bitmap bmpLetterC;
private Dictionary<string, Bitmap> imgLetters;
public Test()
{
ImgInitialize();
ImgWidth();
}
private void ImgInitialize()
{
Dictionary<string, Bitmap> imgLetters;
bmpLetterA = new Bitmap("a.png");
bmpLetterB = new Bitmap("b.png");
bmpLetterC = new Bitmap("c.png");
imgLetters = new Dictionary<string, Bitmap>();
imgLetters.Add("a", bmpLetterA);
imgLetters.Add("b", bmpLetterB);
imgLetters.Add("c", bmpLetterC);
}
private void ImgWidth()
{
int width = 0;
width = imgLetters["a"].Width;
}
}
}
Remove the line Dictionary<string, Bitmap> imgLetters; from ImgInitialize. This creates a local variable with the same name as the member variable. It is then filled, but never used, while the member variable remains uninitialized.
Tipps for avoiding problems like this:
You could name instance members in a special way to make clear the variable is an instance member (for example m_member instead of member).
You could prefix access to an instance member with this. to make clear which variable you want to access.
You could try to avoid naming local variables the same as instance members.
The problems lies here:
private void ImgInitialize()
{
Dictionary<string, Bitmap> imgLetters;
This variable shadows the class's field private Dictionary<string, Bitmap> imgLetters;. Remove this declaration from the method ImgInitialize and it'll work fine.
Friendly tip to prevent such mistakes in the future: when using a class member, append this:
this.imgLetters = new Dictionary<string, Bitmap>();
this.imgLetters.Add("a", bmpLetterA);
this.imgLetters.Add("b", bmpLetterB);
this.imgLetters.Add("c", bmpLetterC);
This way, even if you have local variable with the same name it won't interfere.
The problem is in your ImgInitialize() method.
remove this Line
Dictionary<string, Bitmap> imgLetters;
What you are doing is creating a local variable with the same name as your global variable. So it is this one that you are adding values to. This then lost when the method has completed due to its scope.
Your global variable is still null at this point and this is why the error occurs.
Related
I got a CS0426 compiler error when trying to open an Excel using SpreadsheetDocument class from DocumentFormat.OpenXml.Packaging namespace.
I realized that this was because I was using new and, for some reason, the compiler didn't like it.
Why can't I create an instance of the object using new?
//Error CS0426
using (SpreadsheetDocument goldenFile = new SpreadsheetDocument.Open(goldenPath, true));
//Ok code
using (SpreadsheetDocument goldenFile = SpreadsheetDocument.Open(goldenPath, true));
Judging by its name and context, the SpreadsheetDocument.Open method opens a new spreadsheet file for you to read/write from/to.
This should be the correct way to use this API:
using (SpreadsheetDocument goldenFile = SpreadsheetDocument.Open(goldenPath, true)) {
...
}
You need to understand that not every class needs to be created by you writing the word new and directly calling the constructor. Sometimes, in this case for example, the instance of SpreadsheetDocument is probably created somewhere inside the Open method. The Open method simply returns the new instance, so that you can assign it to a variable (goldenFile in this case).
You can write a class that gets created with a static method too:
class Foo {
// properties...
// private constructor
private Foo() { ... }
public static GiveMeAFoo() {
return new Foo();
}
}
I can now create an instance of Foo without directly using new:
var foo = Foo.GiveMeAFoo();
Something similar is happening inside Open.
The compiler gives off the error CS0426 because it thinks like this:
I see that you are using the new operator, so you are creating a new instance of a type. What type is it that you are creating? Let's see... It's SpreadsheetDocument.Open! But wait a minute! That's not a type! I can't find a type called Open in SpreadsheetDocument!
Hence the error:
The type name 'Open' does not exist in the type 'SpreadsheetDocument'.
It's not working because as is, when you're using new you essentially telling your code - "Create an object of a nested class 'Open'".
Either get rid of new or implement public constructor, and then call static Open method.
The Open method is a static method which uses new in its implementation and returns an instance of SpreadsheetDocument. This is why you don't need to use new. Refer to documentation.
I've created a simple script that I can't debug. Here is my issue :
I'm looking to store the content of a directory into a variable in SSIS with Visual Studio 2015.
I've created a variable in my SSIS package, and set it's data type to Object.
I've added to my package a Script Task, that contains this code :
#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
#endregion
namespace ST_c6399821104c42c2859b7b2481055848 {
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase {
public void Main() {
string CSVFilesCompletePath;
if (Dts.Variables.Contains("User::CSVFilesPathAbsolute") == true
&& Dts.Variables.Contains("User::CSVFilesPathRelativeCountry") == true
&& Dts.Variables.Contains("User::CSVFilesCountryObject") == true) {
CSVFilesCompletePath = Dts.Variables["User::CSVFilesPathAbsolute"].ToString() + Dts.Variables["User::CSVFilesPathRelativeCountry"].ToString();
String[] fileListTable = Directory.GetFiles(CSVFilesCompletePath, "*.xlsx");
List<string> fileList = new List<string>(fileListTable);
Dts.Variables["User::CSVFilesCountryObject"].Value = fileList;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
#region ScriptResults declaration
/// <summary>
/// This enum provides a convenient shorthand within the scope of this class for setting the
/// result of the script.
///
/// This code was generated automatically.
/// </summary>
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
}
}
As explained here :
SSIS Script Task Get File Names and Store to an SSIS Object Variable
But this code returns the following error when I try to Start it through the SSIS Job :
Variables are correctly set in the Script Wizard as ReadWriteVariables.
The thing is that my code shows this error when I try to affect the SSIS Variable and try to put the String[] in it.
Try adding a try-catch in the
Directory.GetFiles
call or in the whole body, then set the error message and/or the stack trace of the exception into a write SSIS variable for debugging purposes.
Edit: Looks like #H.Fadlallah point out the problem. You should use the Value property of the DtsVariable, not the ToString()
My error was :
CSVFilesCompletePath = Dts.Variables["User::CSVFilesPathAbsolute"].ToString() + Dts.Variables["User::CSVFilesPathRelativeCountry"].ToString();
I had to use : Dts.Variables[].Value.ToString() instead of Dts.Variables[].ToString()
As I was using the name of the Variable instead of the content of the Variable, the GetFiles returned a null object, and it couldn't be stored inside my variable, creating the different errors.
I have the following code which works fine when I use it within a Windows Forms application, however the application I'm writing needs to run as a Windows service, and when I moved my code into the Windows Service template in Visual Studio 2015 Community Edition, I get the following error.
Cannot implicitly convert type "MyWindowsService.Main" to "System.ComponentModel.ISynchronizeVoke". An explicit conversion exists (are you missing a cast?)
Could anyone shed some light on why I am getting this error, and what I need to do to resolve it?
The code which throws the error is the line below, and it is located within the OnStart method of my main class (named Main.cs). The code is used to create an instance of the DataSubscriber class (AdvancedHMI library).
dataSubscribers[dataSubscriberIndex].SynchronizingObject = this;
It has to have something to do with the fact that the code is in a Windows service template, because using this works perfectly in my forms application running the same code.
UPDATE
Correction, I've attempted to cast this to the required type, and now get the following error on run.
Additional information: Unable to cast object of type 'MyWindowsService.Main' to type 'System.ComponentModel.ISynchronizeInvoke'.
Code:
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (System.ComponentModel.ISynchronizeInvoke)this;
UPDATE
I've included the entire contents of the Main.cs file from my Windows Service application.
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using AdvancedHMIDrivers;
using AdvancedHMIControls;
using MfgControl.AdvancedHMI.Drivers;
using MfgControl.AdvancedHMI.Controls;
using System.Collections.ObjectModel;
namespace PLCHistoricDataHarvester {
public partial class Main : ServiceBase {
private EthernetIPforCLXCom commObject = new EthernetIPforCLXCom();
private globals globals = new globals();
private Dictionary<String, String> operationLines = new Dictionary<String, String>();
private Dictionary<String, String> tags = new Dictionary<String, String>();
private Collection<DataSubscriber> dataSubscribers = new Collection<DataSubscriber>();
private int harvesterQueueCount = 0;
private string harvesterInsertValues = String.Empty;
public Main() {
InitializeComponent();
}
protected override void OnStart(string[] args) {
// Initialize our harvester program
initializeHarvester();
Console.WriteLine("The program has started");
}
protected override void OnStop() {
// Call code when the service is stopped
Console.WriteLine("Program has stopped");
Console.ReadLine();
}
public void initializeHarvester() {
// First, we connect to the database using our global connection object
globals.dbConn.DatabaseName = "operations";
if (!globals.dbConn.IsConnect()) {
// TODO: Unable to connect to database. What do we do?
}
// Second, we connect to the database and pull data from the settings table
globals.initializeSettingsMain();
// Set IP address of PLC
commObject.IPAddress = globals.getSettingsMain("Processor_IP");
// Pull distinct count of our parent tags (Machines ex: Line 1, etc)
operationLines = globals.getOperationLines();
// If we have at least 1 operation line defined...we continue
if (operationLines.Keys.Count > 0) {
//Now we loop over the operation lines, and pull back the data points
int dataSubscriberIndex = 0;
foreach (KeyValuePair<String, String> lines in operationLines) {
int line_id = int.Parse(lines.Key);
string name = lines.Value;
tags = globals.getTags(line_id);
// If we have at least 1 tag for this operation line, we continue...
if (tags.Keys.Count > 0 && tags["tags"].ToString().IndexOf(",") != -1) {
// Create our dataSubscriber object
dataSubscribers.Add(new DataSubscriber());
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (ISynchronizeInvoke)this;
dataSubscribers[dataSubscriberIndex].CommComponent = commObject;
dataSubscribers[dataSubscriberIndex].PollRate = 1000;
dataSubscribers[dataSubscriberIndex].PLCAddressValue = tags["tags"];
dataSubscribers[dataSubscriberIndex].DataChanged += new EventHandler<MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs>(subscribeCallback);
// Increment our dataSubscriberIndex
dataSubscriberIndex++;
}
}
}
}
private void subscribeCallback(object sender, MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs e) {
// code removed as it is irrelevant
}
}
}
The error message says this:
An explicit conversion exists (are you missing a cast?)
So add a cast like this:
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (ISynchronizeInvoke)this;
^^^^^^^^^^^^^^^^^^^^
//Add this
If you've got a console app, the easiest way to convert it to a windows service is by using Topshelf, a nuget package which lets you run in either console mode or nt service mode.
Here's the quickstart guide.
We use it to write services all the time and it helps you avoid this kind of fragile shenanigans.
I want to enter the following command into the debugger
po [[UIWindow keyWindow] _autolayoutTrace]
How would I do that in Xamarin Studio?
Edit:
I saw this Objective-C code
NSLog(#"%#", [[UIWindow keyWindow] _autolayoutTrace]);
in programatically change autolayout on orientation change together with an interface definition for that.
// for debugging auto layout.
#interface UIWindow (AutoLayoutDebug)
+(UIWindow *)keyWindow;
-(NSString *)_autolayoutTrace;
#end
I'd like to know how this can be done in Xamarin iOS?
If you are using the unified API the solution posted by miguel.de.icaza doesn't work anymore, because you get
`ObjCRuntime.Messaging' is inaccessible due to its protection level
One has to use P/Invoke:
using System;
using System.Runtime.InteropServices;
using Foundation;
using UIKit;
using ObjCRuntime;
public static class UIViewAutolayoutTraceExtensions
{
[DllImport(Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend")]
private static extern IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector);
public static NSString AutoLayoutTrace(){
return (NSString)Runtime.GetNSObject(IntPtr_objc_msgSend(UIApplication.SharedApplication.KeyWindow.Handle, new Selector ("_autolayoutTrace").Handle));
}
public static NSString RecursiveDescription(){
return (NSString)Runtime.GetNSObject(IntPtr_objc_msgSend(UIApplication.SharedApplication.KeyWindow.Handle, new Selector ("recursiveDescription").Handle));
}
}
Then you can use it like this:
Console.WriteLine(UIViewAutolayoutTraceExtensions.RecursiveDescription ());
One caveat though: You can only call this code after everything has been loaded. Otherwise KeyWindow will be null. So there is no possibility to set a breakpoint and then call this code. You can only call this code if you provide a button or something similar with which you trigger the action.
using MonoTouch.ObjCRuntime;
var str = new NSString (Messaging.IntPtr_objc_msgSend (UIApplication.SharedApplication.KeyWindow.Handle, new Selector ("_autolayoutTrace").Handle));
And "str" will contain the string that you can then use with Console.WriteLine
Environment: c#.net VS 2010
Solution has the following two projects:
A dll with several tested methods I've added.
A test project
The only thing in the test project is a form with following code: (names changed for readability)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using DLL_PROJECT; //Yes I remembered to include the dll project
namespace DLL_PROJECT_Test
{
public partial class frmTest : Form
{
private Class_1 myClass_1; //this comes from the dll - no errors here
private Class_2 myClass_2 = new Class_2(); // no errors here either
public frmTest()
{
InitializeComponent();
//TransparencyKey = BackColor;
this.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = System.Drawing.Color.FromArgb(0, System.Drawing.Color.Black);
myDebouncer = new Debouncer(this);
this.SetDragging(true); //THIS EXTENSION COMES FROM THE DLL AND WORKS FINE
this.RoundCorners(40, 80); //AS DOES THIS ONE
myClass_2 = new Class_2();
myClass_2.HoldStartEvent += new Class_2EventHandler(myClass_2_HoldStartEvent);
myClass_2.DragStartEvent += new Class_2EventHandler(myClass_2_DragStartEvent);
}
private void myClass_2_DragStartEvent(Class_2 sender)
{
myClass_2("DragStart") += 1; //THE ONLY ERROR IS HERE AS FOLLOWS
//ERROR: "The name 'myClass_2' does not exist in the current context"
// - Yes, the DLL is included
// - Yes, the project is .Net 4 (not client profile)
// - Yes xxx WRONG xxx, this exact syntax has been tested before on an instance of
// this class, it's just a default parameter.
// xxx should be [] instead of () for the indexer in c#. #VB_Fails
}
void myClass_2_HoldStartEvent(Class_2 sender)
{
this.Close();
}
}
}
This code:
myClass_2("DragStart") += 1;
... is using myClass_2 as if it were either the name of a method or a delegate instance.
Did you actually mean to use the indexer? That would be:
myClass_2["DragStart"] += 1;
What does "DragStart" mean here? Is it actually a property name? Perhaps you want:
myClass_2.DragStart += 1;
I very much doubt that "this exact syntax has been tested before on an instance of this class".
Admittedly the error message doesn't make much sense in this case. I think it's actually more likely that you've got a typo in your real code - a typo which isn't propagated here because you've changed the names. If you could reproduce this in a short but complete program, it would make life a lot simpler.