|
Your form contains user interaction elements -- such as buttons / menus / textboxes etc. For service, you need single starting point for the thread.
- Malhar
|
|
|
|
|
that sounds like Chinese Algebra to me. wtf???
My articles
BlackDice
|
|
|
|
|
BlackDice wrote: that sounds like Chinese Algebra to me
I think I might know what he means.
I think he is trying to say that a service has a single starting point and has no user interaction. In otherwords, it starts and keeps on going until it is shutdown with no user interaction - unlike a GUI which starts and waits for user interaction before doing anything.
In other words, if your GUI has more than a single "Go" button, and your code interacts with the GUI in any way after that then it will need some work to get it to work as a service.
If your GUI is just using the textboxes and so on to set values for various methods to test one small area of processing, but the whole still works like a service, then there shouldn't be too many problems.
ColinMackay.net
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius
"If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell
|
|
|
|
|
Ok. I've also looked at your post about the nUnit method. that sounds ok. But keeping to what you said in this post I'm replying to, that's all that's on the form is an exit button. It actually starts running once the form starts running. the only thing on the form is a listbox that shows trace statements; this would be written to a log file instead.
It let me add a form to the project, so I copied/pasted all my code into that form. I have the service compiling now, but I still need to add the setup stuff to it. I don't want the form to actually show though. Should I just hide it, or is there also a better way?
My articles
BlackDice
|
|
|
|
|
BlackDice wrote: It let me add a form to the project, so I copied/pasted all my code into that form
You should have no logic on your form at all - Even for a GUI application. The form class is there to process GUI events. The Business logic should all happen in a separate class.
It looks like you have some refactoring to do. As you don't have a complex GUI it should be fairly simple to extract all that logic to a separate class.
Don't ask about "hiding" the form. It's just wrong and would probably take as much time to figure out how to hide a form in a service as it would to refactor your code properly. Believe me, you don't want the maintenance nightmare this could very easily become.
ColinMackay.net
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius
"If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell
|
|
|
|
|
Service and UI programs are meant for different things! Turning latter into the former is the real WTF!
Sample template for your service...
namespace MyNamespace<br />
{<br />
public class MyService : System.ServiceProcess.ServiceBase<br />
{<br />
private System.Timers.Timer timer1;<br />
private System.ComponentModel.Container components = null;<br />
<br />
public MyService()<br />
{<br />
InitializeComponent();<br />
}<br />
<br />
static void Main()<br />
{<br />
System.ServiceProcess.ServiceBase[] ServicesToRun;<br />
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new MyService() };<br />
System.ServiceProcess.ServiceBase.Run(ServicesToRun);<br />
}<br />
<br />
private void InitializeComponent()<br />
{<br />
this.timer1 = new System.Timers.Timer();<br />
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();<br />
this.timer1.Interval = 500;<br />
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);<br />
this.ServiceName = "MyService";<br />
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();<br />
}<br />
<br />
protected override void Dispose( bool disposing )<br />
{<br />
if( disposing )<br />
{<br />
if (components != null) <br />
{<br />
components.Dispose();<br />
}<br />
}<br />
base.Dispose( disposing );<br />
}<br />
protected override void OnStart(string[] args)<br />
{<br />
this.Initialize();<br />
}<br />
<br />
private void Initialize()<br />
{<br />
this.IsReady = true;<br />
this.timer1.Start();<br />
this.timer1.Enabled=true;<br />
}<br />
protected override void OnStop()<br />
{<br />
this.IsReady = false;<br />
this.timer1.Stop();<br />
this.timer1.Enabled=false;<br />
}<br />
public static DoSomethingAtSomeInterval(params object[] params)<br />
{<br />
}<br />
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)<br />
{<br />
if (!IsReady)<br />
{<br />
return;<br />
}<br />
else<br />
{<br />
IsReady = false;<br />
try<br />
{<br />
}<br />
catch (Exception ex2)<br />
{<br />
}<br />
IsReady = true;<br />
}<br />
}<br />
}<br />
<br />
<br />
[RunInstaller(true)]<br />
public class ProjectInstaller : System.Configuration.Install.Installer<br />
{<br />
private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;<br />
private System.ServiceProcess.ServiceInstaller serviceInstaller1;<br />
private System.ComponentModel.Container components = null;<br />
<br />
public ProjectInstaller()<br />
{<br />
InitializeComponent();<br />
}<br />
<br />
protected override void Dispose( bool disposing )<br />
{<br />
if( disposing )<br />
{<br />
if(components != null)<br />
{<br />
components.Dispose();<br />
}<br />
}<br />
base.Dispose( disposing );<br />
}<br />
<br />
<br />
#region Component Designer generated code<br />
private void InitializeComponent()<br />
{<br />
this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();<br />
this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();<br />
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;<br />
this.serviceProcessInstaller1.Password = null;<br />
this.serviceProcessInstaller1.Username = null;<br />
this.serviceInstaller1.DisplayName = "[%FunctionName%]Service";<br />
this.serviceInstaller1.ServiceName = "[%FunctionName%]Service";<br />
this.Installers.AddRange(new System.Configuration.Install.Installer[] {<br />
this.serviceProcessInstaller1,<br />
this.serviceInstaller1});<br />
<br />
}<br />
#endregion<br />
}<br />
}
|
|
|
|
|
I wasn't saying wtf because you said something crazy or anything like that. I said that just because your reply went over my head. No sarcasm/disrespect intended. I do thank you for your input. however, I understand what you're saying now, but as I responded in my post to Colin, I don't actually NEED the gui; it was just easier to use a gui while I was building the app.
My articles
BlackDice
|
|
|
|
|
BlackDice wrote: I've been working on an app with a gui (mostly because it's easier to test) because I know someone who said it was easy to turn an app into a service once you had it tested the way you want.
Personally, I would have used something like NUnit[^]
I would have set the solution up as follows:
Solution
-- Service Bootstrap Assembly
-- NUnit Test Assembly
-- Service logic
The Service Logic project would contain all the code that the service uses. It would have zero dependancy on either of the other two projects - If it suddenly does need a dependancy the compiler will warn me about it and I know I've coded something wrong.
The NUnit Test Assembly (which is roughly equivalent to your GUI code) contains all the tests and is dependant on the Service Logic project (because that it what it is testing).
The Service Bootstrap is the EXE that actually runs as a service, but it has very little code as all it does is access the code in the Service Logic project. Again, this project is dependant on the Service logic assembly.
This keeps all the code nicely separated to when it comes time to deploy it you can just grab the bootstrap and the logic assemblies.
So, back to your problem, the best way to do this would be to extract the GUI from the service code and try and put something together that resembles the above - otherwise you are going to create lots of problems for yourself in the future.
BlackDice wrote: He did it in VB.Net, though and I'm no longer in touch with him.
Just as well. You you were I'd tell you to tell him that I think his solution is crazy and introduces lots of problems into the project that you are now having to resolve.
ColinMackay.net
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius
"If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell
|
|
|
|
|
I've done it the other way, using reflection on a service project to run it from the command line or a gui to make it easier to debug.
I can imagine the sinking feeling one would have after ordering my book,
only to find a laughably ridiculous theory with demented logic once the book arrives - Mark McCutcheon
|
|
|
|
|
Did anyone mention the run section in the registry?
Dim regK As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
this will start your program when user logs in, you can then hide it just like a service, and make it visible after certain events. You can also hide it from Alt-Tab order.. but thats another story.
|
|
|
|
|
plus
<br />
If regK Is Nothing Then<br />
Else<br />
regK.SetValue("applicationXXX", directory + "DodgyFakingService.exe")<br />
End If<br />
|
|
|
|
|
I have 4 classes. Class A is derived from System.Object, class B is derived from ArrayList (the collection class), class C and class D are derived from class B. All 4 classes of mine have ToString methods that each show a different thing. I used the 'override' reserved word in each declaration to replace the funcionality of the inherited method. I have a form which has a drop-down listbox that utilizes the ToString methods of classes' C and D only. I also have a TreeView that shows all 4 classes in a tree diagram, consider that class B and D are root items in the tree view and only contain objects of type A and C respectively.
The problem is classes A and B work 100% fine, but only those two.
However, classes C and D are the problem. In the form with the list box, I add objects of type class C using dlg.listbox.Add(new class C("some text", somevalue)); before showing the form. Class C has that overridden ToString method that returns a special string based on that string and that value given to it. On runtime, the box simply says (Collection) instead of what it should.
Later, the same class C object shows up in the tree view, but instead of seeing the same (Collection) , you see some text but only that text. Somewhere the object is returning that custom text element and not the value, and the ToString method for class C incorporates both like I mentioned earlier.
I don't know how to fix this. I put breakpoints on every ToString method and the first two classes trigger fine but C and D's are never used. The project is too complex to just paste it all so if you have an idea and need more info, just ask and I'll be glad to answer.
|
|
|
|
|
What more do you have in the C and D classes? It seams like the listbox reads the value directly from a member. Do you have any public members that might be used by the listbox?
---
b { font-weight: normal; }
|
|
|
|
|
class B has a String and a custom class type, C has a number and D has nothing more than the String and custom class intended for B. I didn't mention it before but I know about and utilized the base constructor.
It was my understanding that I could add objects to the listbox Items collection and when the listbox is run, it shows strings from the ToString method from the specific object. The only other method I have besides class C's ToString is its constructor and a method used to gather TreeNode-derived objects from the items in its collection.
|
|
|
|
|
Make sure that you haven't missed the override keyword on any of the ToString methods. The Object.ToString method is virtual, but if you don't override it, you will be creating a non-virtual method that will only be reachable when refering to the object using a reference of the specific type. When referenced as an object, the virtual method will be used instead.
---
b { font-weight: normal; }
|
|
|
|
|
I double checked that several times and I did give all four instances of ToString the override keyword. It's very frustrating that it keeps happening. I also added marks in each ToString to display what class the ToString is being called from and the first three classes are fine, it's just that last one class can't show it's ToString in the combo box like it should.
I'll keep hammering at it though, I know it's worked before. I figure I might have a "base.ToString()" instead of a "this.ToString()" or something set wrong like that.
|
|
|
|
|
LighthouseJ wrote: the first two classes trigger fine but C and D's are never used.
I believe you may need to make B 's ToString() virtual.
/ravi
My new year's resolution: 2048 x 1536
Home | Music | Articles | Freeware | Trips
ravib(at)ravib(dot)com
|
|
|
|
|
I thought about that before and tried it but there was no difference in the outcome in runtime.
|
|
|
|
|
LighthouseJ wrote: The project is too complex
Here's a simple solution.. has the same class hierarchy as you described.. and it shows the .ToString() values. (I hope you're not confusing ListBox with ListView)
- Malhar
using System;<br />
using System.Drawing;<br />
using System.Collections;<br />
using System.ComponentModel;<br />
using System.Windows.Forms;<br />
<br />
namespace Malhar.ControlGallery<br />
{<br />
public class Form3 : System.Windows.Forms.Form<br />
{<br />
private System.Windows.Forms.ListBox listBox1;<br />
private System.Windows.Forms.Button Load;<br />
private System.ComponentModel.Container components = null;<br />
<br />
public Form3()<br />
{<br />
InitializeComponent();<br />
<br />
}<br />
<br />
protected override void Dispose( bool disposing )<br />
{<br />
if( disposing )<br />
{<br />
if(components != null)<br />
{<br />
components.Dispose();<br />
}<br />
}<br />
base.Dispose( disposing );<br />
}<br />
<br />
#region Windows Form Designer generated code<br />
private void InitializeComponent()<br />
{<br />
this.listBox1 = new System.Windows.Forms.ListBox();<br />
this.Load = new System.Windows.Forms.Button();<br />
this.SuspendLayout();<br />
this.listBox1.Location = new System.Drawing.Point(8, 16);<br />
this.listBox1.Name = "listBox1";<br />
this.listBox1.Size = new System.Drawing.Size(176, 95);<br />
this.listBox1.TabIndex = 0;<br />
this.Load.Location = new System.Drawing.Point(192, 8);<br />
this.Load.Name = "Load";<br />
this.Load.TabIndex = 1;<br />
this.Load.Text = "button1";<br />
this.Load.Click += new System.EventHandler(this.button1_Click);<br />
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);<br />
this.ClientSize = new System.Drawing.Size(292, 266);<br />
this.Controls.Add(this.Load);<br />
this.Controls.Add(this.listBox1);<br />
this.Name = "Form3";<br />
this.Text = "Form3";<br />
this.ResumeLayout(false);<br />
<br />
}<br />
#endregion<br />
<br />
private void button1_Click(object sender, System.EventArgs e)<br />
{<br />
listBox1.Items.Add(new A());<br />
listBox1.Items.Add(new B());<br />
listBox1.Items.Add(new C("John", 4));<br />
listBox1.Items.Add(new C("Lisa", 10));<br />
listBox1.Items.Add(new D());<br />
}<br />
<br />
class A<br />
{<br />
public A():base()<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return "Object of type A";<br />
}<br />
}<br />
class B:ArrayList<br />
{<br />
public B():base()<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return "Object of type B";<br />
}<br />
}<br />
class C:B<br />
{<br />
string someStr;<br />
object someVal;<br />
public C(string text, object value)<br />
{<br />
someStr = text;<br />
someVal = value;<br />
}<br />
public override string ToString()<br />
{<br />
return string.Format("Object of type C: {0}; {1}", (someStr==null?"-":someStr), (someVal==null?"-":someVal.ToString()));<br />
}<br />
}<br />
class D:B<br />
{<br />
public D()<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return "Object of type D";<br />
}<br />
}<br />
}<br />
}
|
|
|
|
|
Actually, I was wrong and it's a combobox, but class B contains the string and a custom class, and C has an int. My class structure and ToString() method definitions are basically the same thing, you say yours works so I don't know what's different to not work.
|
|
|
|
|
Hello,
In my Windows Form, I have almost 20 textboxes and editable controls. I was wondering is there any way i can apply Edit Menu (Cut, Copy, Paste, Select All) fetaures and MOUSE RIGTH CLICK MENU (CUT, COPY, PASTE, SELECT ALL) and SHORT CUT KEYs ( CTRL + C, CTRL + V, CTRL + X, CTRL + A) without writing code for each control seperately ? It is very boring and very hard to write code for each control, right ! So, I am pretty sure there must be an easy solution for that. So, would you please let me know if there is any solution to this kkind of boring task !!
thanks to all
Emran
|
|
|
|
|
You do realise you can apply the same event handler to every textbox on a form right? For example, the KeyDown event
private void MyKeyDownEventHandler(object sender, KeyEventArgs e)<br />
{<br />
}<br />
<br />
myTextBox1.KeyDown += new KeyDownEventHandler(MyKeyDownEventHandler);<br />
myTextBox2.KeyDown += new KeyDownEventHandler(MyKeyDownEventHandler);<br />
myTextBox3.KeyDown += new KeyDownEventHandler(MyKeyDownEventHandler);
|
|
|
|
|
Hi J4amieC,
Thanks for your reply.
Yes, i realize that i can use same handler, but you see, in that handler i will have to use a very big list of if else statement for every text box, right ?
like,
if(txtbox1.Focused)
txtbox1.Copy();
else if(txtBox2.Focused)
txtbox2.Copy();
............
.................
...............
ekse if(txtboxN.Focused)
txtBoxN.Copy();
and then I will have to write same if else for CUT(), PASTE, SELECTALL,... right ? and I thought it s a very hard way to maintain codes and there must be some simple method solution for this purpose as this task is essential for everyone for any kind of application and there must be some way available for this task.
thanks and regards
Emran
|
|
|
|
|
what is the best way to create a controll with my how drawing?
Can i use for it a bitmap at the place drawing it in GDI+?
(i ask this becouse i've tried to create a button using a panel then set as backgound an image loaded from the Hard disk, at the mouse action i get other images from an imagelist object, but i don't like this way futhermore on the on paint event i see this panel all black before to see the image)
|
|
|
|
|
Well if there is no image set, then just clear the control in the backgroundcolor you like, best use a property:
e.Graphics.Clear(BackgroundColor);
if (image != null) {
e.Graphics.Drawimage(...);
}
Greetings,
Ingo
------------------------------
An bug in a Microsoft Product? No! It's not a bug it's an undocumented feature!
|
|
|
|