Consider this small program:
class Program
{
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Please copy something into the clipboard.");
WaitForClipboardChange();
Console.WriteLine("You copied " + Clipboard.GetText());
Console.ReadKey();
}
static void WaitForClipboardChange()
{
Clipboard.SetText("xxPlaceholderxx");
while (Clipboard.GetText() == "xxPlaceholderxx" &&
Clipboard.GetText().Trim() != "")
Thread.Sleep(90);
}
}
I run it, and I copy a string from Notepad. But the program just gets an empty string from the clipboard and writes "You copied ".
What's the problem here? Is there something that makes clipboard access behave weirdly in a console application?
This is Windows 7 SP1 x86, .NET 4 Client Profile.
Use this function
static string GetMeText()
{
string res = "starting value";
Thread staThread = new Thread(x =>
{
try
{
res = Clipboard.GetText();
}
catch (Exception ex)
{
res = ex.Message;
}
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
return res;
}
In this line:
Console.WriteLine("You copied " + Clipboard.GetMeText());
The problem is that the clipboard only works with certain threading models (ApartmentState.STA) so you have to make a new thread and give it that model this code does that.
I can reproduce the problem with your code on .NET 4 Client Profile, but when I switch to .NET 4 or 4.5 it works as expected.
However, the ClipBoard.GetText() manual states:
Use the ContainsText method to determine whether the Clipboard contains text data before retrieving it with this method.
I take that as an instruction, not a suggestion, so, try this:
class Program
{
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Please copy something into the clipboard.");
WaitForClipboardChange();
Console.WriteLine("You copied " + Clipboard.GetText());
Console.ReadKey();
}
static void WaitForClipboardChange()
{
Clipboard.Clear();
while (!Clipboard.ContainsText())
Thread.Sleep(90);
}
}
It does show the copied text, although I must say this lets my system hang horribly when I copy some text.
This works for me:
static void Main(string[] args)
{
Console.WriteLine("Please copy something into the clipboard.");
string text = WaitForClipboardChange();
Console.WriteLine("You copied " + text);
}
static string WaitForClipboardChange()
{
string placeholderText = "xxPlaceholderxx";
Clipboard.SetText(placeholderText);
string text = null;
do
{
Thread.Sleep(90);
text = Clipboard.GetText();
}
while (string.IsNullOrWhiteSpace(text) || text.Equals(placeholderText));
return text;
}
Your current code explicitly waits for first change from "xxPlaceholderxx" to anything (your condition is "not particular string AND not empty" which turns false as soon as string changes from "xxPlaceholderxx" to anything, including ""):
while (Clipboard.GetText() == "xxPlaceholderxx"
&& Clipboard.GetText().Trim() != "")
You probably want || (or) instead of and:
// assuming System.Windows.Forms.Clipboard
static void WaitForClipboardChange()
{
Clipboard.SetText("xxPlaceholderxx");
while (Clipboard.GetText() == "xxPlaceholderxx"
|| string.IsNullOrWhiteSpace(Clipboard.GetText()))
Thread.Sleep(90);
}
Related
I have been tackling this issue for 3 months now.
Error I am Getting in Native Debugging:
"Exception thrown at 0x5A222FC2 (comct123.dll) in FileReader.exe:
0xC0000005: Access violation reading location 0x0000000C."
Normal Debug:
'System.AccessVioliationException' in System.Windows.Forms.dll
My setup is really simple:
public static Form_Interface Interface;
public static void Initialize()
{
Application.SetCompatibleTextRenderingDefault(false);
Interface = new Form_Interface();
Interface.Filesdgv.DataSource = File.SortableBindingList;
Application.Run(Interface);
}
Seems simple enough, right? No.
So basically I have a simple Event that simply opens the file using Process.Start() and no matter what I do it will randomly crash with 'System.AccessVioliationException' in System.Windows.Forms.dll here:
private void Filesdgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
Filesdgv.Invoke((Action)(() =>
{
try
{
int rowIndex = e.RowIndex;
if (rowIndex >= 0)
{
int columnIndex = e.ColumnIndex;
File file = (File)((DataGridView)sender).Rows[rowIndex].DataBoundItem;
switch (columnIndex)
{
case 0:
{
Process.Start(file.Location);
}
break;
}
}
}
catch
{
// This fking catch never works anyway.
}
}));
}
private void FileInterface_Load(object sender, EventArgs e)
{
foreach (string oCurrent in Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Files To Check")))
if (oCurrent.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
new File(oCurrent.Split('\\').Last(), oCurrent);
}
It doesn't matter if I am opening files/links or anything else, it still behaves in the same way.
The link and file location is a readonly field as well.
I have many other uses for reading row data and it never crashes, even if i spam click 10000 times, It will only crash randomly with Process.Start()
Things I tried:
Using BeginInvoke
Using Invoke
Not Using Invoke/BeginInvoke
Putting File Link into a string before reading it.
Using multiple Try Catch
Recoded on another machine... same results there aswell.
I tried using File.Open (either doesn't open the file or throws same error lmao)
Tried using [HandleProcessCorruptedStateExceptions], still won't catch the exception.
Dosen't matter if i click slow or fast still 1/30 chance it happens.
Tried Putting Task.Run(() => Process.Start()); you'd think that a thread will protect you from an exception? no still crashes...
File Class looks like this:
public class File
{
public static SortableBindingList<File> SortableBindingList = new SortableBindingList<File>(new List<File>());
public readonly string fileName;
public readonly string filePath;
public void AddRow()
{
Client.Interface.Invoke((Action)(() =>
{
lock (SortableBindingList)
if (!SortableBindingList.Contains(this))
SortableBindingList.Add(this);
}));
}
public string FileName
{
get
{
return fileName;
}
}
public string Location
{
get
{
return filePath;
}
}
public File(string fileName, string filePath)
{
this.fileName = fileName;
this.filePath = filePath;
AddRow();
}
}
Initalize() is called in static void Main(string[] args) btw.
There are no other threads running editing stuff or anything like that, the only thread running is the form thread. which waits for user input.
Solutions I am looking for:
Alternative Method to launch files/hyperlinks.
A way to avoid form crashing (try catch style)
Crashes even with static data!:
Other threads running although these were not started by me.
Task.Run(() =>
{
Thread.Sleep(100);
Process.Start("https://www.youtube.com");
});
This has fixed my issues, it seems that when trying to immediately run "process.start" during a click event, the GUI unfocusing + starting a new process the exact same moment causes an Exception. (Microsoft pls fix.)
I have coded a system based of the theory that while loops can work anywhere in a system. So once a while loop has been passed by it can run. Here is a simple version of my code:
using System;
namespace test___login
{
class Program
{
static void Main(string[] args)
{
string location = "homepage";
while (location.Equals("Homepage", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("homepage");
Console.WriteLine("WHere to now: ");
location = Console.ReadLine();
}
while (location.Equals("login", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("login");
Console.WriteLine("Where to now: ");
location = Console.ReadLine();
}
}
}
}
So I assumed that once the variable changes from "login" to "homepage" in the second while loop, would mean the first while loop would run once again. Is my theory on how the code works wrong or am i simply not typing the right thing. I just started last week so sorry for the basic question
It wouldn't run again, because the code has already executed past that line so unless you call it again, the next thing down the line will execute, in your case nothing - this is called procedural programming.
Why don't you make one while loop, and a switch statement instead.
bool run = true;
while (run)
{
Console.WriteLine("WHere to now: ");
string location = Console.ReadLine();
switch(location.ToLower()){
case "homepage":
Console.WriteLine("HomePage");
break;
default:
run = false;
break;
}
}
Not with the way you have your code currently structured. It will exit the application. You need to surround all of that with one more while loop, which can be similar to your other loops. See below:
using System;
namespace test___login {
class Program
{
static void Main(string[] args)
{
string location = "homepage";
while (!location.ToUpper().Equals("EXIT"))
{
while (location.Equals("Homepage", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("homepage");
Console.WriteLine("WHere to now: ");
location = Console.ReadLine();
}
while (location.Equals("login", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("login");
Console.WriteLine("Where to now: ");
location = Console.ReadLine();
}
}
}
}
}
iam quite desperate here. I couldn't find any example code for this in C#.
I want to rename BrowserSubProcess.exe and i want it to embed my main exe, if possible.
I am aware of this solution;
https://github.com/cefsharp/CefSharp/issues/1149#issuecomment-225547869
Rename CefSharp.BrowserSubprocess winforms
but i couldn't implemented it. I need sample program or code to understand. I hope #amaitland will see this and helps me.
I embed the BrowserSubProcess Program.cs to my Program.cs so it is embedded now.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
if (args.Count() < 5)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
}
else
{
MyBrowserSubProcess(args);
}
}
static int MyBrowserSubProcess(string[] args)
{
Debug.WriteLine("BrowserSubprocess starting up with command line: " + String.Join("\n", args));
SubProcess.EnableHighDPISupport();
int result;
var type = args.GetArgumentValue(CefSharpArguments.SubProcessTypeArgument);
var parentProcessId = -1;
// The Crashpad Handler doesn't have any HostProcessIdArgument, so we must not try to
// parse it lest we want an ArgumentNullException.
if (type != "crashpad-handler")
{
parentProcessId = int.Parse(args.GetArgumentValue(CefSharpArguments.HostProcessIdArgument));
if (args.HasArgument(CefSharpArguments.ExitIfParentProcessClosed))
{
Task.Factory.StartNew(() => AwaitParentProcessExit(parentProcessId), TaskCreationOptions.LongRunning);
}
}
// Use our custom subProcess provides features like EvaluateJavascript
if (type == "renderer")
{
var wcfEnabled = args.HasArgument(CefSharpArguments.WcfEnabledArgument);
var subProcess = wcfEnabled ? new WcfEnabledSubProcess(parentProcessId, args) : new SubProcess(args);
using (subProcess)
{
result = subProcess.Run();
}
}
else
{
result = SubProcess.ExecuteProcess();
}
Debug.WriteLine("BrowserSubprocess shutting down.");
return result;
}
private static async void AwaitParentProcessExit(int parentProcessId)
{
try
{
var parentProcess = Process.GetProcessById(parentProcessId);
parentProcess.WaitForExit();
}
catch (Exception e)
{
//main process probably died already
Debug.WriteLine(e);
}
await Task.Delay(1000); //wait a bit before exiting
Debug.WriteLine("BrowserSubprocess shutting down forcibly.");
Environment.Exit(0);
}
}
And my BrowserSubprocessPath is my main exe.
settings.BrowserSubprocessPath = System.AppDomain.CurrentDomain.FriendlyName;
I finally managed to rename this sub process! Haven't found any solution how to do it through the CefSharp API, but found my own worked solution.
So, In your code that uses CefSharp add one setting to the Cef Settings, before Cef.Initialize()
using CefSharp;
using CefSharp.Wpf;
using System.IO;
using System.Reflection;
using System.Windows;
public App()
{
var settings = new CefSettings
{
BrowserSubprocessPath = Path.Combine(GetAppPath(), $#"runtimes\win-x64\native{ GetAppName() }.exe")
};
Cef.InitializeAsync(settings);
}
private static string GetAppPath()
{
return new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;
}
private static string GetAppName()
{
return Assembly.GetExecutingAssembly().GetName().Name;
}
After this go to the bin\Debug\net6.0-windows\runtimes\win-x64\native\ and rename CefSharp.BrowserSubprocess.exe to Name you want to use.
Done. Now it will use this file with custom name you need.
P.S. For the auto name set you can always use Post-Build event with command to rename the file after project built and set the name same as your assembly name. I use this approach for my needs.
Keep getting the error message does not contain a static main method for suitable entry point. Would anyone be able to explain this error to me and possibly help me fix it? Thanks. New to C#
{
class Authenticator
{
private Dictionary<string, string> dictionary = new Dictionary<string, string>();
public void IntialValues()
{
dictionary.Add("username1", "password1");
dictionary.Add("username2", "password2");
dictionary.Add("username3", "password3");
dictionary.Add("username4", "password4");
dictionary.Add("username5", "password5");
}
public bool Authenticate(Boolean authenticated)
{
Console.WriteLine("Please enter a username");
string inputUsername = Console.ReadLine();
Console.WriteLine("Please enter your password");
string inputPassword = Console.ReadLine();
if (dictionary.ContainsKey(inputUsername) && dictionary[inputUsername] == inputPassword)
{
authenticated = true;
}
else
{
authenticated = false;
}
return authenticated;
}
}
}
If all of your code consists only of the block shown above then the error is more than clear. A Main method is required in your program.
The Main method is, by convention, the default point where the code starts executing. You can get here a more in depth explanation
So, for example, you need to add the following code
class Authenticator
{
static void Main(string[] args)
{
Authenticator au = new Authenticator();
au.InitialValues();
if(au.Authenticate())
Console.WriteLine("Authenticated");
else
Console.WriteLine("NOT Authenticated");
Console.WriteLine("Press Enter to end");
Console.ReadLine();
}
// Move the boolen variable inside the method
public bool Authenticate()
{
bool authenticated = false;
Console.WriteLine("Please enter a username");
string inputUsername = Console.ReadLine();
Console.WriteLine("Please enter your password");
string inputPassword = Console.ReadLine();
if (dictionary.ContainsKey(inputUsername) && dictionary[inputUsername] == inputPassword)
{
authenticated = true;
}
else
{
authenticated = false;
}
return authenticated;
}
}
By the way, you should remove the parameter passed in input to the Authenticate method. You should declare it as an internal variable, set it depending on the outcome of the check and return it.
However, you could remove that variable altogether writing
....
return (dictionary.ContainsKey(inputUsername)) &&
(dictionary[inputUsername] == inputPassword)
}
All executable programs must have a Main function somewhere in the project that is compiled to the exe.
If you just want to compile a class (eg to a dll) then you have to set that as the "project type" in visual studio.
The easiest way is to create a new project, but select class library as project type, and then paste your code in there. Alternatively you can use the command line to compile a file to a dll like so:
c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:library Authenticator.cs
I'm a newbie in java from c# background. In c# when i want to make sure the user cannot does null data in the Console Application i make a loop like
static void Main(string[] args)
{
Console.WriteLine("Enter your name : ");
string name = Console.ReadLine();
while (name == "")
{
Console.WriteLine("Enter your name : ");
name = Console.ReadLine();
}
}
Now I want to implement the same in java. I am using
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Enter your name : ");
String pname;
Scanner scan=new Scanner(System.in);
pname=scan.next();
while ("".equals(pname))
{
System.out.println("Enter your name : ");
pname=scan.next();
}
}
But when a null value is entered, the output doesn't show the Enter your name again it only moves one line waiting for a value to be entered.
What am i doing wrong?
Try using nextLine() instead. next() only gets up to the next space, nextLine() gets the next linebreak. I vaguely remember this from my java class in college.
while ("".equals(pname))
{
System.out.println("Enter your name : ");
pname=scan.next();
}
Instead use
while (pname.equals(""))
{
System.out.println("Enter your name : ");
pname=scan.next();
}
If you look at javadocs for equals, you will know what i am talking about.
And also a hint, i started using buffred reader when i started coding in java
You can use:
while (pname == null || "".equals(pname))
{
System.out.println("Enter your name : ");
pname = scanner.nextLine();
}
I also faced similar type of problem once. The problem is not in while loop. It is in reusing same Scanner object. Try creating new Scanner object each time.
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Enter your name : ");
String pname;
Scanner scan=new Scanner(System.in);
pname=scan.next();
while (pname.equals(""))
{
System.out.println("Enter your name : ");
scan = new Scanner(System.in);
pname=scan.next();
}
}