String from getter is empty when called in another Project C# - c#

I am a total beginner in C# programming language. I am trying to use Getter and Setter in order to set the string in ProjectA and the retrieve it in Project B.
Project B uses Windows Forms, and I wasnt to set the value of TextBox
with the retrieved string.
Project A is a Console Project and it just reads out some stuff from
file and stores it in string, which I want to retrieve.
However, this is my call in Project B:
string cardOwner = Transmit.Program.CardOwner;
Debug.WriteLine("Card owner = " + cardOwner);
tb_cardholder.Text = cardOwner;
And this is my Getter / Setter in Project A:
private static string _cardOwner;
public static string CardOwner
{
get
{
return _cardOwner;
}
set
{
_cardOwner = value;
}
}
_cardOwner = System.Text.Encoding.ASCII.GetString(bCardOwner);
But in Project B I get "" empty string.
I have included Project A in Project B (added Reference and wrote "using ProjectA").
Any ideas what's going wrong?
Thanks.

Just because you include a project and use its classes in your project B, it doesn't mean that you also use the instances of these classes.
Take the following class:
public class Test
{
public string Message { get; set; }
}
You can put this class into a DLL project (Tools) and reference it from other projects, like a WinForms project ProjectA and a console project ProjectB.
In both projects, you can write something like:
Test t = new Test() { Message = "Hello" };
That creates a new instance of the Test class, but the two running applications ProjectA and ProjectB do not exchange the data! They are completely separated.
The same is true for class properties.

You can't share information between two different applications so easily. Static properties only share data within the same Application Domain, that is in most simple constellations within the same Windows process.
If you want to transfer data between two different processes, you need to use an explicit mechanism for interprocess communication.

When is this line executed?
_cardOwner = System.Text.Encoding.ASCII.GetString(bCardOwner);
You'll need to put that in a method and call that method (and knowing when the call happens will help you understand why _cardOwner is not set:
public static void Init()
{
_cardOwner = System.Text.Encoding.ASCII.GetString(bCardOwner);
}
Then call this method somewhere that you know will be executed before you need _cardOwner:
Transmit.Program.Init();
string cardOwner = Transmit.Program.CardOwner;
tb_cardholder.Text = cardOwner;

Related

WebView2 AddHostObjectToScript in UWP crashes

I'm trying to pass a C# object to a WebView2 using AddHostObjectToScript. After not succeeding to retrieve the object from the webview, I've used the debugger and found out that the AddHostObjectToScript call is never completing.
Here is the full code snippet:
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class Example
{
public string Prop { get; set; } = "example";
}
namespace Example_UWP
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
InitializeAsync();
}
public async Task InitializeAsync()
{
await ExampleView.EnsureCoreWebView2Async();
ExampleView.Source = new Uri("http://localhost:3000");
ExampleView.CoreWebView2.OpenDevToolsWindow();
ExampleView.CoreWebView2.AddHostObjectToScript("example", new Example());
}
}
}
The example object is as a result not available in chrome.webview.hostObjects or chrome.webview.hostObjects.sync. The function throws the following error:
The group or resource is not in the correct state to perform the requested operation.
I've tried different alternatives without success, such as:
Keeping a reference to the Example instance in an attribute inside Example_UWP to avoid potential GC
Adding the host object before and after each of the previous steps within InitializeAsync
Wait for the event NavigationCompleted to add the host object.
Wait for 5 seconds before adding the host object.
I'm using Microsoft.Web.WebView2 version 1.0.1264.42
In order to interact with your third-party lib, you need to add a very specific C++ project, Windows Runtime Component (C++/WinRT), to your solution that must be called WinRTAdapter.
Next, you must install a lib to your C++ project from NuGet called Microsoft.Web.WebView2:
After this is done, you must your third-party lib as a reference.
Next, go to your C++ project properties go to Common Properties and choose WebView2:
Here you have to do four changes:
Set Use WebView2 WinRT APIs to No.
Set Use the wv2winrt tool to Yes.
Set Use Javascript case to Yes.
Edit Include filters and add the following ones:
Windows.System.UserProfile
Windows.Globalization.Language
CallJSInterface
CallJSInterface is the name of my third-party's namespace.
You click on OK and build your C++ lib.
After you have built your C++ lib (WinRTAdapter), you must add it to your main project as a reference.
Now, we need to do some changes to be able to invoke the functions from our third-party lib. The first one is to register it. We do it in the same LoadLocalPage() function from before or on NavigationCompleted:
var namespacesName = "CallJSInterface";
var dispatchAdapter = new WinRTAdapter.DispatchAdapter();
core_wv2.AddHostObjectToScript(namespacesName, dispatchAdapter.WrapNamedObject(namespacesName, dispatchAdapter));
Where CallJSInterface is your namespace. After this, you need to register your function in your JS like this:
var callJS;
if (chrome && chrome.webview) {
chrome.webview.hostObjects.options.defaultSyncProxy = true;
chrome.webview.hostObjects.options.forceAsyncMethodMatches = [/Async$/];
chrome.webview.hostObjects.options.ignoreMemberNotFoundError = true;
window.CallJSInterface = chrome.webview.hostObjects.sync.CallJSInterface;
callJS = new CallJSInterface.CallJSCSharp();
}
Where CallJSInterface is one more time your namespace. Now, you can invoke JS like this (the async() is mandatory):
callJS.async().KeepScreenOn()
If you need more details, I have a full tutorial on my website:
https://supernovaic.blogspot.com/2022/10/from-webview-to-webview2-in-uwp.html

Accessing class members defined in another *.cs file

I'm writing an update checker for my program and I'm using xml from a remote server. The request is working fine and it does what I want. The problem is that I can't call the function from another file. (See code below)
The files
home.cs - The place i want to call the RequestVersion()
version.cs - Where the RequestVersion() is located
The code
version.cs
namespace MyName
{
class version
{
public string[] RequestVersion()
{
XmlDocument doc = new XmlDocument();
try
{
string[] version_data = new string[3];
doc.Load("link_here");
foreach (XmlNode node in doc.DocumentElement)
{
string version = node.Attributes[0].Value;
string date = node["date"].InnerText;
string changelog = node["changelog"].InnerText;
version_data[0] = version;
version_data[1] = date;
version_data[2] = changelog;
return version_data;
}
}
catch (Exception xml_ex)
{
}
return null;
}
}
}
(returns an array)
home.cs
private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
{
//This is the place from where i want to access the array!
}
And my XML structure:
<?xml version="1.0" encoding="UTF-8"?>
<SerialMate>
<release version="1.0.0">
<date>12-10-2014</date>
<changelog>Test</changelog>
</release>
</SerialMate>
(I'm not adding any new <release> tags on the xml so it always has 1)
The question
So, my question is: How do it access the array elements from the RequestVersion() within home.cs?
I don't really understand your problem, but:
version v = new version();
string[] s = v.RequestVersion();
Referencing code within other files and projects
Within the same project it makes absolutely no difference whether the code is in the same or in different files. The only things which matter are the access modifiers (public, protected, internal, and private).
If the two code pieces are in different projects, then the compiled code will be compiled into two different assemblies (*.exe or *.dll). Therefore one project will have to reference the other one. Typically the start up project (*.exe) will reference a class library project (*.dll).
If the two projects are within the same solution, you can add a so called project reference. Right click on the class library project in the solution explorer and click “Copy As Project Reference”. In the startup project, right click on “References” and click “Paste Reference”.
If the two projects are within different solutions you will have to add a reference to the class library DLL (usually the one in bin/Release) from within the startup project. Right click “References” and click “Add Reference…”. In the references dialog choose “Browse” and select the DLL.
Also make sure not to create circular dependencies (project A references project B and project B references project A). If you have such a dependency, you can usually resolve it by placing the code that has to be accessed by the two projects into a third project C. Then change the references to: A references C and B references C.
Calling the method of another class
Types (a class in your case) and their members (properties, methods, events …) must be declared as public in order to be accessible from other projects. Within the same project they can also be declared as internal. (They can also be declared as protected if you want to derive new classes.)
If a member is declared as static or if it is a constant, you can access it by specifying the type name dot the member name:
var result = MyClass.MyMethod();
If the member is an instance member you must call it from an instance of the type (an object):
MyClass obj = new MyClass();
var result = Obj.MyMethod();

Common "Debug" function within class library

I am using several class libraries within a project, and one of them is a typical "project.common.dll" library containing some common helper functions. One of these functions is a debug function that creates debug output.
Now I would like to enable/disable debug output by using a user-level property (application settings). How can I reference variables defined in main application's program.cs within this class library ?
Update : Thanks all. I will probably create a static method in my base application that performs the check (to debug or not) and then calls the Debug function in the common library.
You can't.
What you will need to do is have the properties in the class library itself and when you create the instance of it in your main application pass the user setting in:
var debug = new DebugInstance { Output = this.Output };
or set the parameters if it's a static class:
StaticDebug.Output = this.Output;
You can use the ConditionalAtrribute:
[Conditional("DEBUG")]
public static void WriteDebugInfo()
{
Trace.WriteLine("what ever...")
}
This way when you build in Debug mode, the method is invoked; in Release mode not.
Use parameters on the constructor of the Debug class (or a static constructor if the class is static).

Alternatives to reading config files from class libraries at design time?

I have a WinForm project that contains several UserControls. This WinForm project has a reference to an assembly (lets call it lib.dll) that is created from another project (Class Library) that exists in a different solution.
Now, several of the UserControls make calls into lib.dll that return values from the app.config file. At runtime lib.dll works fine and returns the necessary data but at design time, I am getting an exception from lib.dll because the app.config sections are NULL (the exceptions are by design).
Now I could go through each control and wrap any code that calls into lib with
if(!DesignMode) { //code }
But that is a lot of controls to go and apply that to. Is there something I can do globally that would be more elegant then testing the DesignMode property?
Edit
In response to the two comments left below: the solutions provided don't appear to work. The assembly that is causing me a problem lives in the same directory as the app.config. The general directory structure looks like this
References Folder
Configurations (Folder)
appsettings.config
app.config
lib.dll
app.config pulls in several other config files (appsettings, cnx strings, etc) which reside in the Configurations directory. In the case of my exception the value I am trying to get resides in one of these ancillary config files that is referenced by app.config.
This is an interesting question. A solution could be to create in lib.dll a static class like this one :
public static class Config
{
private static readonly _param1;
static Config()
{
_param1 = ConfigurationManager.AppSettings["Param1"] ?? "Your default value";
}
public static string Param1
{
get { return _param1; }
}
}
Then, in your code, insted of writing ConfigurationManager.AppSettings["Param1"], you will use Config.Param1. So you won't need to test the property DesignMode.
There are so many ways to do this, IMHO.
One thought that immedidately comes to mind would be to use an inheritance-based approach for the user controls in question? That way, in the base class, you can put that if (DesignMode) check in, and do the correct branching from there.
// if i were to visualizeyour lib.dll data initializer call like this:
class BaseUserControl
{
// i'm guessing that you initialize the data somehow...
void InitializeData()
{
if (!DesignMode)
{
InitializeDataLocal();
}
}
protected virtual InitializeDataLocal()
{
// whatever base behavior you want should go here.
}
}
// in the derived classes, just put the code you currently have for
// fetching the data from lib.dll here...
class UserControl : BaseUserControl
{
protected override InitializeDataLocal()
{
// fetch from lib.dll...
// optionally invoke some base behavior as well,
// if you need to...
base.InitializeDataLocal();
}
}

Passing Value Between Two Project

I have two project and having trouble on passing value between two project. As usual I have passed the file reference between project.
My project Details Is:
Project1 Project2
All forms and object Only 1 MDI Forms Containing ManuStrip
I wants to read the data of MDI Forms on showing the project1 forms
The Example is as below:
//This is on Project2 MDI Forms
private void accountMasterToolStripMenuItem_Click(object sender, EventArgs e)
{
INVOICE1.Form24 f24 = new INVOICE1.Form24();
f24.PFrom.Text = label4.Text;
f24.PTo.Text = label5.Text;
f24.Namee.Text = textBox1.Text;
f24.ID.Text = label6.Text;
f24.ShowDialog();
}
I Have Created the Properties for the same on project1 forms
public Label PFrom
{
get { return label14; }
set { label14 = value; }
}
public Label PTo
{
get { return label16; }
set { label16 = value; }
}
public Label Namee
{
get { return label2; }
set { label2 = value; }
}
public Label ID
{
get { return label3; }
set { label3 = value; }
}
The value passed from MDI To Project1 is not showing on Form24 of Project1. There are no error. The Form24 Showing without value which are passed from MDI Form.
Why The value not showing on form24 of project1 ?. And What is the Solution?.
You may have forgotten to add a project reference to Project1 in Project2. In the Solution Explorer, right-click Project2 and select "Add Reference", then under "Projects" select Project1.
Also, if the two projects have different namespaces, you'll need to put
using Project1; // replace "Project1" with the namespace of your Project1
At the top of the Project2 source file.
If there are no compiler errors then the problem is not likely to be with project references. Perhaps you have some code in the Form24 constructor or Load event which is clearing those labels
As a side note, instead of exposing the Labels as properties, just expose their Text property:
public string PFrom
{
get { return label14.Text; }
set { label14.Text = value; }
}
I have faced with the same problem..and answer was simple: it is impossible. However you can crack this situation...using database or shared solution in which you will establish communication between 2 projects. Or use 3 project and create communication driver, which will be used in 1 and 2 project. It does't meter how you will do this.
situation: database
situation: shared solution with communication protocol
perhaps creating DLL will also help
My personal solution was this: (Tested on real website and separate background project)
To create shared project, use VS template (shared project). Then create your class and inside each project include in project reference section your shared project. So for example Project A, Project B , Project SharedPr -> contains communication protocol
Project A -> references-> Add Reference -> Shared Project.
Project B -> references-> Add Reference -> Shared Project.
That communication protocol it is something like a driver which you need to create.
Easily to do this by FILE. Create Hidden file in which project A writes and project B reads. Store in your file json string or json array then read all lines and deserialize everything for example with Newtonsoft.Json NuGet package.
I hope this will help.

Categories