|
devvvy wrote: In addition to AppDomain.Current.Get/SetData, can third party examine application memory.
Yes. Wouldn't be worth the effort though. I'm running Linux, Windows-applications are executed under Wine, .NET applications are run under Mono - and I can access the source-code of the VM if need be.
devvvy wrote: If the answer is yes - then it follows really the moment you load a third party dll into your own process, you cannot be sure if your process has been compromised?
You cannot even be sure if you don't load any external code; only if you have complete control over the environment.
I are Troll
|
|
|
|
|
"can third party examine application memory."
> I know reflection can enumerate types of assemblies. I also know if you pass in any object (For example, a LicenseController sitting in AppDomain.Current.Get/Set), reflection can basically enumerage types/properties (set/get any "private" members and methods!). So basically anything sitting in AppDomain.Current.Get/Set is UNSECURED.
One further question out of curiosity - can third party dll can a raw byte[] image of process memory...?
"and I can access the source-code of the VM if need be."
> Access source code? Even if I use an obfuscator..!?
So all this jazz about AppDomain are *practically useless* from security stand point. I've also tried to throw an exception from code from another appDomain, it crashes the whole app (see below).
Sounds like all theories surrounding appDomain completely b*llsh*t!
<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
<br />
using System.Threading;<br />
using System.Reflection;<br />
using System.Security.Policy;<br />
<br />
using UserUtil;<br />
using SimpleUtil;<br />
<br />
namespace SimpleTest<br />
{<br />
class Program<br />
{<br />
public const string KEY1 = "KEY1";<br />
public static AppDomain UserDomain = null;<br />
public static SimpleUtil.IServiceProvider UserProvider = null;<br />
<br />
static void Main(string[] args)<br />
{<br />
Assembly UserAssembly = null;<br />
Object oProvider = null;<br />
Thread t = null;<br />
<br />
try<br />
{<br />
AppDomain.CurrentDomain.SetData(KEY1, "PrivateKey");<br />
<br />
UserDomain = AppDomain.CreateDomain("UserDomain");<br />
UserDomain.SetData(KEY1, "Sh*t!");<br />
<br />
UserAssembly = Assembly.LoadFrom("UserUtil.dll");<br />
<br />
oProvider = UserDomain.CreateInstanceFrom("UserUtil.dll", "UserUtil.ServiceProvider").Unwrap();<br />
<br />
if (oProvider != null)<br />
{<br />
if (oProvider is SimpleUtil.IServiceProvider)<br />
{<br />
UserProvider = (SimpleUtil.IServiceProvider)oProvider;<br />
<br />
t = new Thread(new ParameterizedThreadStart(Program.AsyncDoWork));<br />
t.Start("Calling UserProvider.DoWork");<br />
}<br />
}<br />
<br />
while (true)<br />
{<br />
Console.Write(".");<br />
Thread.Sleep(1000 * 5);<br />
}<br />
}<br />
catch (Exception Ex)<br />
{<br />
Console.WriteLine(Ex.Message);<br />
}<br />
<br />
return;<br />
}<br />
<br />
public static void AsyncDoWork(object Arg)<br />
{<br />
string Message = null;<br />
Message = (string)Arg;<br />
UserProvider.DoWork(Message); << If inside third party "DoWork" throws an exception, it'd crash the hosting app even it's instantiated from different AppDomain! Also it can access AppDomain.Current.GetData("SomeSecret"). On these two reasons - all this talk about AppDomain isolation are quite pointless.<br />
return;<br />
}<br />
}<br />
}<br />
dev
|
|
|
|
|
devvvy wrote: can third party dll can a raw byte[] image of process memory
Yes/No. Most games that were created before the .NET era were cracked, despite some huge investments in copy-protection. It's not doable to reverse-engineer the entire code, but that's rarely done at all - bypassing the protection or getting the password to the database is often enough.
devvvy wrote: So all this jazz about AppDomain are *practically useless* from security stand point. I've also tried to throw an exception from code from another appDomain, it crashes the whole app (see below).
Sounds like all theories surrounding appDomain completely b*llsh*t!
Again, yes and no. An AppDomain isn't a new security-feature, it's an isolationlevel for applications. One that can be unloaded, if desired. It also means that I can execute (potentially malicious) code in a sandboxed environment[^], increasing my overall security. The code in that sandbox is restricted in what it can and cannot do.
I'm running Linux, and I have the source-code to the Operating System, as well as the Mono source-code. It'd be some work, but it could be used to backtrack what API's you're calling - even the paramaters that you pass aren't safe from prying eyes.
devvvy wrote: all this talk about AppDomain isolation are quite pointless
Depends on what you wants it for, and how secure you need to be. Do you need to prevent an ordinary user from making modifications? Prevent someone from seeing the users' data? Or are you creating an application for a nuclear plant?
In the first case, encryption would suffice. In the second case, obfuscation would suffice. In the last case, you simply need total control over the machine - then you'd only be vulnerable for stuxnet
I are Troll
|
|
|
|
|
Hello I tried out your advice - MSDN article on sand boxing third party dll [^]
The following code created new AppDomain for third party dll, invoke it and found out that AppDomain.Current.GetData[KEY1] refers to that of the "New Domain" (not old AppDomain of hosting app)
But again, two problems still remains:
a. third party can still access all AppDomain - see this.[^]
(But if MSDN is correct, GetCallingAssembly requires ReflectionPermission as well - so DENY ReflectionPermission is very key)[^]
b. third party library can simply retrieves hosting types by GetCallingAssembly
<br />
public void DoWork(string Message)<br />
{<br />
<br />
Type[] Types = Assembly.GetCallingAssembly().GetTypes();<br />
if (Types != null)<br />
{<br />
foreach (Type t in Types)<br />
{<br />
Console.WriteLine("Detected type: " + t.FullName);<br />
}<br />
}<br />
c. Am I doing it right below on how to DENY ReflectionPermission? (By setting PermissionState.None)
Anyway here's my full test code.
<br />
***** Program.cs *****<br />
using System;<br />
using System.IO;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
<br />
using System.Threading;<br />
<br />
using System.Reflection;<br />
using System.Security;<br />
using System.Security.Policy;<br />
using System.Security.Permissions;<br />
<br />
using UserUtil;<br />
using SimpleUtil;<br />
<br />
namespace TestAppDomain<br />
{<br />
class Program <br />
{<br />
public const string KEY1 = "KEY1";<br />
public static AppDomain UserDomain = null;<br />
<br />
static void Main(string[] args)<br />
{<br />
string UntrustedThirdPartyDir = @"..\..\UserUtil\UserUtil\bin\Debug";<br />
string ThirdPartyDll = "UserUtil.dll";<br />
string ThirdPartyServiceFullyQualifiedName = "UserUtil.ServiceProvider";<br />
<br />
Assembly UserAssembly = null;<br />
<br />
Object oProvider = null;<br />
SimpleUtil.IServiceProvider UserProvider = null;<br />
<br />
try<br />
{<br />
#region Sandbox preparation<br />
AppDomainSetup AdSetup = new AppDomainSetup();<br />
AdSetup.ApplicationBase = Path.GetFullPath(UntrustedThirdPartyDir);<br />
<br />
PermissionSet PermSet = new PermissionSet(PermissionState.None);<br />
PermSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));<br />
<br />
<br />
ReflectionPermission RefPerm = new ReflectionPermission(PermissionState.None);<br />
PermSet.AddPermission(RefPerm);<br />
<br />
StrongName FullTrustAssembly = typeof(Program).Assembly.Evidence.GetHostEvidence<StrongName>();<br />
#endregion<br />
<br />
<br />
UserDomain = AppDomain.CreateDomain(<br />
"UserDomain", null, AdSetup, PermSet, FullTrustAssembly<br />
);<br />
<br />
AppDomain.CurrentDomain.SetData(KEY1, "PrivateKey");<br />
UserDomain.SetData(KEY1, "NoProblem!");<br />
<br />
oProvider = Activator.CreateInstanceFrom(<br />
UserDomain, ThirdPartyDll, ThirdPartyServiceFullyQualifiedName<br />
).Unwrap();<br />
<br />
#region No need for this...<br />
#endregion<br />
<br />
#region No need for this either ..<br />
#endregion<br />
<br />
if (oProvider != null)<br />
{<br />
if (oProvider is SimpleUtil.IServiceProvider)<br />
{<br />
UserProvider = (SimpleUtil.IServiceProvider)oProvider;<br />
<br />
Object[] parameters = { "Calling UserProvider.DoWork" };<br />
<br />
while (true)<br />
{<br />
#region OPTION 1: prints out "UserUtil.DoWork - secret=NoProblem!"<br />
#endregion<br />
<br />
#region OPTION 2: prints out "UserUtil.DoWork - secret=NoProblem!"<br />
UserProvider.GetType().GetMethod("DoWork").Invoke(UserProvider, parameters);<br />
#endregion<br />
}<br />
}<br />
}<br />
}<br />
catch (Exception Ex)<br />
{<br />
Console.WriteLine(Ex.Message);<br />
}<br />
<br />
return;<br />
}<br />
}<br />
}<br />
<br />
*** SimpleUtil.ServiceProvider ***<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
<br />
using System.Runtime.Serialization;<br />
<br />
namespace SimpleUtil<br />
{<br />
[Serializable()]<br />
class ServiceProvider : SimpleUtil.IServiceProvider<br />
{<br />
public void DoWork(string Message)<br />
{<br />
Console.WriteLine("SimpleUtil.DoWork");<br />
return;<br />
}<br />
<br />
public ServiceProvider()<br />
{<br />
return;<br />
}<br />
<br />
public ServiceProvider(SerializationInfo info, StreamingContext context)<br />
{<br />
return;<br />
}<br />
<br />
public void GetObjectData(<br />
SerializationInfo info,<br />
StreamingContext context<br />
)<br />
{<br />
return;<br />
}<br />
<br />
}<br />
}<br />
<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
<br />
using System.Runtime.Serialization;<br />
<br />
namespace SimpleUtil<br />
{<br />
public interface IServiceProvider : ISerializable<br />
{<br />
void DoWork(string Message);<br />
}<br />
}<br />
<br />
<br />
***** UserUtil.ServiceProvider *****<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
<br />
#region "Inheritance security rules violated while overriding member" runtime error<br />
<br />
#endregion<br />
<br />
using System.Security;<br />
using System.Security.Policy;<br />
using System.Security.Permissions;<br />
<br />
using System.Runtime.Serialization;<br />
<br />
using SimpleUtil;<br />
<br />
namespace UserUtil<br />
{<br />
[Serializable()]<br />
public class ServiceProvider : MarshalByRefObject, SimpleUtil.IServiceProvider<br />
<br />
{<br />
public void DoWork(string Message)<br />
{<br />
<br />
object oSecret = null;<br />
string secret = null;<br />
<br />
oSecret = AppDomain.CurrentDomain.GetData("KEY1");<br />
if (oSecret != null)<br />
{<br />
secret = (string)oSecret;<br />
Console.WriteLine("UserUtil.DoWork - secret=" + secret);
}<br />
else<br />
{<br />
Console.WriteLine("UserUtil.DoWork - secret=NULL!");<br />
}<br />
return;<br />
}<br />
<br />
public ServiceProvider()<br />
{<br />
return;<br />
}<br />
<br />
public ServiceProvider(SerializationInfo info, StreamingContext context)<br />
{<br />
return;<br />
}<br />
<br />
[SecurityCriticalAttribute()]<br />
public void GetObjectData(<br />
SerializationInfo info,<br />
StreamingContext context<br />
)<br />
{<br />
return;<br />
}<br />
}<br />
}<br />
dev
modified on Saturday, March 5, 2011 6:47 AM
|
|
|
|
|
devvvy wrote: a. third party can still access all AppDomain - see this.[^][^]
It's not designed to be a security-feature where you prevent others from looking at your public properties;
Controls access to non-public types and members through the System.Reflection APIs The weakest link would be the .NET-environment itself. Again, what are you securing here? If it's your business-logic, then you might want to consider webservices - that way the other person doesn't have physical access to your code.
I are Troll
|
|
|
|
|
|
I believe the sandbox is meant to prevent other people's code from doing stupid things, not to keep the user out. It might be more efficient to buy an existing system to protect your software.
I are Troll
|
|
|
|
|
Thanks
I think I will not host third party dll in my apps - instead our app will kick start a separate win32 console exe acting as sandbox, send the request to this sandbox which will then load the third party dll. The core app will not send anything sensitive to the sandbox, permission of which will be governed by service account under which it impersonates (i.e. runas)
Screw CAS if even Microsoft is discarding it.
dev
|
|
|
|
|
Hi
I have an application that allows users to upload documents. When the user clicks upload, I want to be able to pop up a different form with a progressbar and a label. The idea is for the progress bar to indicate the total progress of the documents being uploaded, and for the label to display the kilobytes that have been uploaded so far. How can I pass the increment percentage through to this form and update the progressbar on a different thread, without the interface stalling and only updating once the operation has finished. I`m using a delegate to pass info though, and I have tried using the backgroundworker, but I don't think that would work for me. Below is a sample of what I am trying to achieve:
foreach (Document doc in Documents)
{
}
|
|
|
|
|
Assuming your upload work is done on a BackgroundWorker, then use the ProgressChanged event of the background worker, this should update the values in the other form via a function such as...
FORM 1
Form2 form2 = new Form2();
BackgroundWorker bw = new BackgroundWorker();
void OnFormLoad()
{
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
form2.UpdateProgress(e.ProgressPercentage, e.UserState);
}
void StartUpload()
{
bw.RunWorkerAsync();
form2.Show();
}
FORM 2
public void UpdateProgress(int percentageComplete, object otherData)
{
progressBar1.Value = percentageComplete;
Label1.Text = (string)otherData;
}
..hope this helps
Don't vote my posts down just because you don't understand them - if you lack the superior intelligence that I possess then simply walk away
|
|
|
|
|
I've realised that this method won't work due to various other methods that gets called from the long operation, methods that change controls etc. This raises the "control accessed from a different thread..." error. I cannot change these methods becauses it is part of a rather tightly coupled project. There must be a way to simply update the progressbar on the LoadingForm using a thread?!
|
|
|
|
|
This can be done by creating custom events on your form that has the ProgressBar and wraps a BackgroundWorker.
I have my own custom class that I use for this which I am intending to post in an article real soon but here is the code if it helps - it is using a custom progress bar that has a Marquee property rather than Style, but the calls to this can easily be altered to use the standard one. The worker part of this code is essentially the same as the .NET BackgroundWorker and I have extended the ProgressChangedEventArgs so I can pass two lots of text in addition to the usual.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace DaveyM69.Windows.Forms
{
[ToolboxBitmap(typeof(Form))]
public class ProgressForm : Form
{
public const string NoMessageChange = null;
public const int NoProgressChange = -1;
public event DoWorkEventHandler DoWork;
public event ProgressChangedEventHandler ProgressChanged;
public event RunWorkerCompletedEventHandler RunWorkerCompleted;
private object argument;
private AsyncOperation asyncOperation;
private Button button;
private bool cancellationPending;
private readonly SendOrPostCallback completed;
private bool isBusy;
private Label label;
private readonly SendOrPostCallback progress;
private ProgressBar progressBar;
private readonly ParameterizedThreadStart work;
private bool workerReportsProgress;
private bool workerSupportsCancellation;
public ProgressForm()
{
InitializeComponent();
argument = null;
asyncOperation = null;
completed = new SendOrPostCallback(Completed);
isBusy = false;
progress = new SendOrPostCallback(Progress);
work = new ParameterizedThreadStart(Work);
workerReportsProgress = true;
workerSupportsCancellation = true;
}
[Browsable(false)]
public object Argument
{
get { return argument; }
set
{
if (argument != value)
{
if (!isBusy)
argument = value;
}
}
}
[Browsable(false)]
public bool CancellationPending
{
get { return cancellationPending; }
}
[Browsable(false)]
public bool IsBusy
{
get { return isBusy; }
}
[DefaultValue(true)]
public bool WorkerReportsProgress
{
get { return workerReportsProgress; }
set
{
if (workerReportsProgress != value)
{
workerReportsProgress = value;
SetWorkerReportsProgress();
}
}
}
[DefaultValue(true)]
public bool WorkerSupportsCancellation
{
get { return workerSupportsCancellation; }
set
{
if (workerSupportsCancellation != value)
{
workerSupportsCancellation = value;
SetWorkerSupportsCancellation();
}
}
}
public void CancelAsync()
{
if (isBusy)
{
button.Enabled = false;
cancellationPending = true;
}
}
private void Completed(object state)
{
asyncOperation = null;
cancellationPending = false;
isBusy = false;
button.Enabled = false;
RunWorkerCompletedEventArgs e = (RunWorkerCompletedEventArgs)state;
OnRunWorkerCompleted(e);
if (Modal)
DialogResult = e.Cancelled ?
DialogResult.Cancel : e.Error == null ?
DialogResult.OK : DialogResult.Abort;
else
Close();
}
private void InitializeComponent()
{
this.label = new System.Windows.Forms.Label();
this.progressBar = new DaveyM69.Windows.Forms.ProgressBar();
this.button = new System.Windows.Forms.Button();
this.SuspendLayout();
this.label.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label.AutoEllipsis = true;
this.label.Location = new System.Drawing.Point(12, 9);
this.label.Name = "label";
this.label.Size = new System.Drawing.Size(200, 13);
this.label.TabIndex = 0;
this.label.Text = "Working...";
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.progressBar.Location = new System.Drawing.Point(12, 25);
this.progressBar.Marquee = false;
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(200, 23);
this.progressBar.TabIndex = 1;
this.progressBar.Text = "0%";
this.progressBar.Value = 0;
this.button.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.button.Location = new System.Drawing.Point(137, 54);
this.button.Name = "button";
this.button.Size = new System.Drawing.Size(75, 23);
this.button.TabIndex = 2;
this.button.Text = "&Cancel";
this.button.UseVisualStyleBackColor = true;
this.AcceptButton = this.button;
this.ClientSize = new System.Drawing.Size(224, 89);
this.ControlBox = false;
this.Controls.Add(this.button);
this.Controls.Add(this.progressBar);
this.Controls.Add(this.label);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ProgressForm";
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Progress";
this.ResumeLayout(false);
}
protected virtual void OnDoWork(DoWorkEventArgs e)
{
DoWorkEventHandler eh = DoWork;
if (eh != null)
eh(this, e);
}
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler eh = ProgressChanged;
if (eh != null)
eh(this, e);
}
protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
{
RunWorkerCompletedEventHandler eh = RunWorkerCompleted;
if (eh != null)
eh(this, e);
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
RunWorkerAsync();
}
private void Progress(object state)
{
DaveyM69.ComponentModel.ProgressChangedEventArgs e =
(DaveyM69.ComponentModel.ProgressChangedEventArgs)state;
if (e.TaskName != NoMessageChange)
Text = e.TaskName;
if (e.OperationName != NoMessageChange)
label.Text = e.OperationName;
if (workerReportsProgress && e.ProgressPercentage != NoProgressChange)
{
progressBar.Value = e.ProgressPercentage;
OnProgressChanged(e);
}
}
public void ReportProgress(int progressPercentage)
{
ReportProgress(
NoMessageChange, NoMessageChange, progressPercentage, null);
}
public void ReportProgress(string taskName, string operationName)
{
ReportProgress(taskName, operationName, NoProgressChange, null);
}
public void ReportProgress(string taskName, string operationName,
int progressPercentage, object userState)
{
DaveyM69.ComponentModel.ProgressChangedEventArgs state =
new ComponentModel.ProgressChangedEventArgs(
taskName, operationName, progressPercentage, userState);
if (asyncOperation == null)
progress(state);
else
asyncOperation.Post(progress, state);
}
private void RunWorkerAsync()
{
if (!isBusy)
{
isBusy = true;
button.Enabled = workerSupportsCancellation;
asyncOperation = AsyncOperationManager.CreateOperation(null);
work.BeginInvoke(argument, null, null);
}
}
private void SetWorkerReportsProgress()
{
if (InvokeRequired)
new MethodInvoker(SetWorkerReportsProgress).Invoke();
else
{
progressBar.Marquee = !workerReportsProgress;
}
}
private void SetWorkerSupportsCancellation()
{
if (InvokeRequired)
new MethodInvoker(SetWorkerSupportsCancellation).Invoke();
else
{
if (isBusy && !cancellationPending)
button.Enabled = workerSupportsCancellation;
else
button.Enabled = false;
}
}
private void Work(object obj)
{
bool cancelled = false;
Exception error = null;
object result = null;
DoWorkEventArgs doWorkEventArgs = new DoWorkEventArgs(obj);
try
{
OnDoWork(doWorkEventArgs);
if (doWorkEventArgs.Cancel)
cancelled = true;
else
result = doWorkEventArgs.Result;
}
catch (Exception ex)
{
error = ex;
}
RunWorkerCompletedEventArgs state = new RunWorkerCompletedEventArgs(
result, error, cancelled);
asyncOperation.PostOperationCompleted(completed, state);
}
}
}
namespace DaveyM69.ComponentModel
{
public class ProgressChangedEventArgs : System.ComponentModel.ProgressChangedEventArgs
{
private string operationName;
private string taskName;
public ProgressChangedEventArgs(
string taskName, string operationName,
int progressPercentage, object userState)
: base(progressPercentage, userState)
{
this.taskName = taskName;
this.operationName = operationName;
}
public string OperationName
{
get { return operationName; }
}
public string TaskName
{
get { return taskName; }
}
}
}
|
|
|
|
|
if only someone would write an article on this interesting subject...
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
I'm going to be concentrating on WP7 dev for the forseeable future so WPF will also be a logical move for desktop I suppose. I have built up quite a library of useful components/controls etc for WinForms over the years that I'm combining into one demo project to share.
|
|
|
|
|
I agree
Thanks for the post from musefan, it did help me quite a lot. My code seemed to work fine, then I renamed a couple of things and then it didn't update the progressbar correctly anymore, then I undid the changes and it still doesn't work I know it did work though so I must just be missing something
|
|
|
|
|
Here is some code in one of my methods:
webBrowser1.Focus();<br />
System.Windows.Forms.SendKeys.Send("{PGDN}");
I'm using this to force the webbrowser to scroll down so that a picture on the site I'm using is on screen.
Then I use:
findClick();
I have coded this to mean: using(image1) find image on screen and click.
It works fine.
MY PROBLEM IS:
(here is the next line of code):
webBrowser1.Focus();<br />
System.Windows.Forms.SendKeys.Send("{PGDN}");<br />
Point one = this.Location;
How do I wait for a certain amount of time before executing the next line of command?
THREAD.SLEEP DOESN'T WORK!!!!!!!!!!
This command freezes the form and doesn't do anything for this problem. I also cannot use timers because I need the code to remain in this method (preferably in one line, like thread.Sleep)
How would I go about doing this?
ANOTHER SIMILAR PROBLEM:
using:
webBrowser1.Navigate("http://google.com");<br />
second command;<br />
third command;
This doesn't wait for the first command to finish so I would like to place a timer that says wait(5000) then continue.
I KNOW ABOUT DOCUMENTCOMPLETED events, I'm using this as an example!
|
|
|
|
|
your problem description is incomplete and hard to read and understand, however I can tell you this:
1. a WinForm app needs a responsive GUI, so GUI event handlers should not contain blocking calls nor long winding calculations.
2. Thread.Sleep() is a blocking call; it should never be called by the main thread.
3. problems that are inherently asynchronous can't be solved synchronously, i.e. the correct solution has to include extra threads and/or events.
4. if and when someone tells you Application.DoEvents() will solve it for you, do not go that route, it is a recipe for failure later on.
And before you ask to "clarify" or "show code", I suggest you make things a lot clearer, showing code in PRE tags, and explaining where the code resides, and on what thread it runs, and when, etc. Showing fractions of some method, without much context, isn't very informative.
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
Luc is quite right, Thread.Sleep won't help.
Instead, set up a class level Timer, with a (say) 1/10th second interval. Use a counter in the Timer.Tick event to allow your five seconds to elapse, and then continue your processing.
The other solution is as Luc says to move your processing code onto a separate thread, which you can Sleep without affecting the GUI. Remember that you can only access UI components from the GUI thread though!
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
Digital man: "You are, in short, an idiot with the IQ of an ant and the intellectual capacity of a hose pipe."
|
|
|
|
|
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
Your first issue...
Use SendWait instead of Send...
System.Windows.Forms.SendKeys.SendWait("{PGDN}");
...consider putting this on a separate thread - as Luc has said you do not want to be making the UI wait for anything that does not complete almost instantly
Your navigate problem (second issue)...
add an event handler for the DocumentCompleted event of the WebBrowser control, then add second and third command in there...
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
}
Don't vote my posts down just because you don't understand them - if you lack the superior intelligence that I possess then simply walk away
|
|
|
|
|
Hi
I'm using C# version 2008 on Win 7.
I am building an app and need to add a console page.
In delphi I would simply click new item and click on console.
With C# there is no reference to a console item to add.
Am I missing something or is this a limitation of the Express addition?
If so, is there a workaround?
Bob
|
|
|
|
|
No, there is no such thing as a "Console Page", not even in the Ultimate editions of Visual Studio.
If you want a console window, you'll have to create one yourself with, at the very least, AllocConsole, AttachConsole, FreeConsole Win32 functions.
|
|
|
|
|
Do you mean adding a console window to a non-console app? If so - this tip[^] may help.
|
|
|
|
|
It's Easy ,
Click Menu Project -> Project Properties -> Select Application Tab -> In Out Put Type ComboBox Select "Console Application"
Have a good day !
I know nothing , I know nothing ...
|
|
|
|
|
Hy experts
I need a little help here. Can anybody tell me how to select
a radio button from another program knowing the name,id or text of the radio button.
I want to automate internet explorer by checking the "First Name" radio button then pressing the "Send" button.
This is the code I'm using to set the focus to internet explorer:
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class getWindow
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string IpClassName, string IpWindowName);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
public static void Main(string[] args)
{
IntPtr iHandle = FindWindow(null, "Details - Windows Internet Explorer");
SetForegroundWindow(iHandle);
}
}
Any help would be appreciated.
Thank you in advance.
|
|
|
|
|