Showing posts with label Windows Forms. Show all posts
Showing posts with label Windows Forms. Show all posts

Dec 3, 2009

The specified service has been marked for deletion error message when removing a service

If you receive this message while trying to delete a windows service - check if the Services.msc application is open.

You will need to restart in order to delete the service, but you will know to first close the Services.msc application the next time PRIOR uninstalling the service (using installutil /u service_exe_name).

Hope this helps someone outthere...

Edit : I found another scenario when this can happen and it seems to be more .NET specific and common to software developers - if your service creates some worker threads, Windows will attempt to kill the main thread, the main thread will attempt to kill the main thread but the worker threads if not marked as BackgroundThreads via the IsBackgroundThread property will remain. The GC will wait for them to reach a safe point so they can be terminated and the service will most probably be only marked for deletion, requiring you to restart windows.

Please note - if you are using the ThreadPool class you will probably not hit this problem as the ThreadPool internal threads are automatically marked as background threads.

Edit 2: Another case when you will receive The specified service has been marked for deletion error message is when you try to uninstall service which wasn't stopped first or it was marked as unstopable.
This is done if you have this.CanStop = false in your service code.
Windows knows this service shouldn't be stopped and it will only mark it for deletion but will not delete it right away.
Be careful with CanStop property.

May 19, 2009

5 minutes C# - get windows special folders path

Just a two lines of code in order to retrieve the path to a special folder of your choice (My Documents, ApplicationData etc):

string strAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
DirectoryInfo diMyDocuments = new DirectoryInfo(strAppData);

Here is the Environment.SpecialFolder Enum:

Environment.SpecialFolder.ApplicationData - the data which some applications store about the current user (mostly used for personalized settings), this is for roaming users.
Environment.SpecialFolder.CommonApplicationData - Application data which is common for all users.
Environment.SpecialFolder.CommonProgramFiles - "The directory for components that are shared across applications"
Environment.SpecialFolder.Cookies - The folder where the user cookies are stored.
Environment.SpecialFolder.Desktop - The logical desktop.
Environment.SpecialFolder.DesktopDirectory - this is the directory which is used to store file objects on the desktop.
Environment.SpecialFolder.Favorites - Current user favorite items.
Environment.SpecialFolder.History - Current user Internet History.
Environment.SpecialFolder.InternetCache - Internet cached files.
Environment.SpecialFolder.LocalApplicationData - As the first one but for non-roaming users.
Environment.SpecialFolder.MyComputer - I'll let you figure this out ...
Environment.SpecialFolder.MyDocuments - I'll let you figure this out too ...
Environment.SpecialFolder.MyMusic - ... and this one ...
Environment.SpecialFolder.MyPictures - ... and this one ...
Environment.SpecialFolder.Personal - this one is more important, this directory is used as a repository for documents...
Environment.SpecialFolder.ProgramFiles - this one is clear, I believe
Environment.SpecialFolder.Programs - Contains user program groups.
Environment.SpecialFolder.Recent - Users most recently used documetns.
Environment.SpecialFolder.SendTo - This directory is used for the Send To > item in the context menu. By adding folders here, they will appear in the Send To -> item when you click on a file or folder.
Environment.SpecialFolder.StartMenu - Contains the Start Menu items.
Environment.SpecialFolder.Startup - The Startup group (Start Menu -> All Programs -> Startup).
Environment.SpecialFolder.System - The system directory (%Windir%\System32)
Environment.SpecialFolder.Templates - Document templates repository.


Hope I helped a bit.
Have a great coding.

Dec 1, 2008

Microsoft Office Word automation in C# - How to add table to the document?

The following C# code will create a new document, add a table to it and ask the user to save it. Document will look like this:



The following code will add a table in word and then ask the user to provide a filename to save the document:
        Microsoft.Office.Interop.Word.
Application app = new Microsoft.Office.Interop.Word.ApplicationClass();
        app.Visible =
false;

        
object start = 0;
        
object end = 0;
        
object oNull = System.Reflection.Missing.Value;

        
Document doc = new DocumentClass();
        doc = app.Documents.Add(
ref oNull, ref oNull, ref oNull, ref oNull);

        
Table tbl = doc.Tables.Add(doc.Range(ref start, ref end), 10, 2, ref oNull, ref oNull);
        
Random rnd = new Random();
        
for (int i = 0; i < 10; i++)
        {
           tbl.Rows[i + 1].Cells[1].Range.Text =
"Run# :" + ((int)i + 1).ToString();
           tbl.Rows[i + 1].Cells[2].Range.Text =
"Value :" + rnd.Next(0, 2000).ToString();
        }

        
object oFalse = false;
        app.Visible =
true;
        
try
        {
           doc.Save();
        }
        
catch (Exception ex)
        {
          
if (ex.Message.ToLower().IndexOf("command failed") == -1)
           {
            
throw ex;
           }
        }
        app.Quit(
ref oFalse, ref oFalse, ref oFalse);

What we done is to create a new document, a new table, and fill the table with random values.
Seems very easy but not quite sure how well document :).

Jul 10, 2008

C# Microsoft Excel Automation - very simple Microsoft Excel AddIn to get Amazon deals

First of all here is how will it look:



This is a Microsoft Excel 2003 Addin Project (under File -> New -> Project expand C# -> Office and you should see it).

Here is the code for the addin connection :

XmlDocument doc = new XmlDocument();
// Link to the Amazon feed.
doc.Load("http://rssfeeds.s3.amazonaws.com/goldbox");
XmlNodeList xmlNodeItems = doc.DocumentElement.SelectNodes("/rss/channel/item");

Excel.
Worksheet sheet = (Excel.Worksheet)Application.ActiveSheet;

int i = 0;
// Start reading each item in the rss feed.
foreach (XmlNode
xmlNodeItem in xmlNodeItems)
{
i++;
if (i > 10) break;
// Get title, link and description, the
// description will be later used to retrieve image url.
string strTitle = xmlNodeItem.SelectSingleNode("title").InnerText;
string strLink = xmlNodeItem.SelectSingleNode("link").InnerText;
string strDescription = xmlNodeItem.SelectSingleNode("description").InnerText;

// Get the cell in which we will write the title of the product.
Excel.Range rngTitle = ((Excel.Worksheet)Application.ActiveSheet).get_Range("A" + i.ToString(), "A" + i.ToString());

// Some variables for the picture creation:

float picLeft = 50;
float picTop = float.Parse(rngTitle.Top.ToString()) + 5f;
float picWidth = 50;
float picHeight = 50;
string strImageFile = GetImageUrl(strDescription);


// Make fonts bold and write the text in the first cell ("A").
rngTitle.Font.Bold = true;
rngTitle.Value2 = strTitle;

// Add the picture
Excel.Shape pic = ((Excel.Worksheet)Application.ActiveSheet).Shapes.AddPicture(strImageFile, Microsoft.Office.Core.MsoTriState.msoCTrue, Microsoft.Office.Core.MsoTriState.msoCTrue, picLeft, picTop, picWidth, picHeight);

// Make the title centered both horizontally and vertically.

rngTitle.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter;
rngTitle.VerticalAlignment = Excel.
XlVAlign.xlVAlignCenter;

// Make the picture move if neighbour cell is resized.
pic.Placement = Microsoft.Office.Interop.Excel.XlPlacement.xlMove;
}

Note : I removed the VSTO generated code region so I don't waste space. You shouldn't do this ;).

In other words if you copy the code you will need to paste it below the VSTO generated code region.

I also used a subroutine to extract the image url from the description, it is very simple, greedy regular expression:

    
private string GetImageUrl(string strDescription)
     {
        
Match mImage = Regex.Match(strDescription, "src=\".+?\"");
        
return mImage.Value.Replace("src=", "").Replace("\"", "");
     }


Things to do:

1. First of all there is no good way to resize a cell in Excel. Your user will be presented very ugly screen. Here is how it actually looks if you don't resize the cells:




Very ugly huh?

2. The other think that bothers me is that Amazon lists about 100 products in their deals feed. So it is a bit slowly to get all the images (they are downloaded on the fly).

I will be very happy to discuss this problem with any of you.

Cheers ;).


Mar 19, 2008

Very simple tool to watch ending Sedo Auctions

Few months ago I was interested in the domain trading business. It was interesting to me as it generated 14.2 million dollars back in 2006. It is based on speculla I think. Something like FOREX but not quite.

I registered two domains and placed them on Sedo Auctions.

I was also interested on how other domains are going so I decided to write a small tool. It will stay in your tray and will show you the auctions which are about to end the next 24 hours. The following information is gathered about each auction:

- Domain for sale
- Price
- Currency
- Time left before the auction is closed
- Google PR for each domain

The program is available for download from Chameleon Bulgaria

I decided to put a banner on this program so my domains
for sale are visible to the users (well, after all I spent some time on this program and I would really like ot have some incomes after all ;).

Here is a direct link to the program page on Chameleon Bulgaria may be found
here

Mar 16, 2008

5 minutes C# to dispose your NotifyIcon object

If you have this problem - try calling .Dispose() method for your NotifyIcon explicitly in the FormClosing event:


    
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
     {
        notifyIcon1.Dispose();
     }

Note : this trick may not work if the Application was terminated abnormally. I will investigate that issue when I have some free time and report back what is the best approach on this.
>

Feb 4, 2008

5 minutes C# code to load CSV file into a DataSet


Step 1 : add button for browsing files, a textbox to hold the file name and paste the followin code in the browse button click handler (this code will basically popup a OpenFileDialog, set up to only open files with .csv extension):

             OpenFileDialog ofd = new OpenFileDialog ();
            ofd.Filter =
"CSV Files|*.csv" ;
            
if (ofd.ShowDialog() == DialogResult .OK)
            {
               
this .textBox2.Text = ofd.FileName;
                GetData();
            }

Then we need to get the file from the textbox2 and load it into data set:

      
private void GetData()
       {
            
FileInfo fi = new FileInfo (textBox2.Text);
            
OleDbConnection con = new OleDbConnection ( @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fi.Directory.FullName + ";Extended Properties='text;HDR=Yes;FMT=Delimited'" );
            con.Open();

            
DataSet dsThings = new DataSet ();
            
OleDbCommand cmd = new OleDbCommand ( "SELECT * FROM " + fi.Name, con);
            
OleDbDataAdapter adapt = new OleDbDataAdapter (cmd);
            adapt.Fill(dsThings);
            
this .dataGridView1.DataSource = dsThings.Tables[0];
            
       }

As you can see we use OleDB provider to load the CSV file into the dataset.

Jan 28, 2008

Job Done!

I think I made it finally. The osCommerce 2 vShop import was made this afternoon. Just waiting QA test now.
>

Jan 22, 2008

.NET C# to parse MySQL queries? Impossible? Pavel can make it ;) (with some ifs and buts offcourse ;)

The most interesting task in my career came the end of the last week. As a Vizibility employee I was asked if I can port osCommerce live site to out vShop solution (http://www.vizibility.co.uk/tmenu/vshop.asp) The interesting thing is that I had no access to osCommerce nor did I ever worked with it. What's even more chalenging - osCommerce database was given to me as SQL queries, something like :

drop table if exists table ;
create table table (
-- Some things here ...
);

insert into table () values ( );

As a normal software developer so there were 3 big chalanges:

1. How to parse this SQL thing (it is MySQL) ?
2. How to figure out
the osCommerce Logic ?
3. How to port all those things as a script so it can be applied to our live servers by the support team?


It's really chalanging don't you think? First I thought it will be a good step to install fresh copy of osCommerce, import the products and try to port them as CSV or something. But then I understood it will take too much time, so I decided to parse the SQL queries on my own and store them in a predefined objects like tables, rows and so on and so on. Then I could easilly transfer them as a text files in the format we needed.

And I almost made it - the parsing methods are done (I was able to parse this thing in a day but some bugs still appear).

Seems the more I work on our shopping solution the more easier I can understand other's shopping solutions.

Great task in a great company!

Jan 21, 2008

5 minutes C# code to open Web.Config from Windows Forms application.

In my previous post about IIS, Virtual Directories and Directory Services you saw how can you obtain the sites per IIS instance as well sa all the root virtual directories. Now it is time to show you how can you obtain the Web.Config file for a root directory.

At first glance I thought it will be easy, I thought I will simply need declare the following:

using System.Web.Configuration;

And / or :

using System.Configuration;

Well it's not quite this way. In order to load web.config file from a windows forms application you need to have some kind of context to be used or, in other words, file mapping.

The following method takes two parameters : path to the root directory and DirectoryEntry, representing the root directory
object (you can see my previous post ( Get IIS sites and virtual directories with .NET / C# / Directory Services ) learn how to obtain DirectoryEntry for a web root directory.
And here is the method:

      
List < string []> GetWebConfigAppSettings( string Path, DirectoryEntry entry)
       {
            
List < string []> items = new List < string []>();
            
if (entry.Properties[ "Path" ].Value != null )
            {
               
FileInfo fiWebConfig = new FileInfo (entry.Properties[ "Path" ].Value + @"\web.config" );
               
if (fiWebConfig.Exists)
                {
                  
WebConfigurationFileMap fm = new WebConfigurationFileMap ();
                   System.Collections.
Hashtable props = new System.Collections. Hashtable ();
                  
foreach (System.DirectoryServices. PropertyValueCollection property in entry.Properties)
                   {
                        
string propertyName = property.PropertyName;
                        props.Add(propertyName, property.Value);
                   }
                  
VirtualDirectoryMapping mapping = new VirtualDirectoryMapping (fiWebConfig.Directory.FullName, true );
                   fm.VirtualDirectories.Add(entry.Properties[
"AppRoot" ].Value.ToString(), mapping);
                   System.Configuration.
Configuration cfg = System.Web.Configuration. WebConfigurationManager .OpenMappedWebConfiguration(fm, entry.Properties[ "AppRoot" ].Value.ToString());
                  
foreach ( KeyValueConfigurationElement elmt in cfg.AppSettings.Settings)
                   {
                        items.Add(
new string [] { elmt.Key, elmt.Value });
                   }
                }
            }
            
return items;
       }



The method above will return a List of all in the web.config file (the appSettings section), you can easilly adjust it to fit your needs.

As you can see the magic begins in :

> System.Configuration. Configuration cfg = System.Web.Configuration. WebConfigurationManager .OpenMappedWebConfiguration(fm, entry.Properties[ "AppRoot" ].Value.ToString());


method. You simply need to make some preparations befor ask it to open the web.config.

Note : this code again is written in few minutes and does not pretend to be optimized, you can again use it at your own will.

Jan 13, 2008

Another 5 minutes with C# to post to Google Blogs (Blogger.com) using Google Blogs SDK (2)

I revised the tool a bit, here is how it looks now:





Also I made some refactoring to the code and it looks better now (no more richTextBox1 names ;).
I plan to release this tool in order to help developers blog code to their blogger accounts easier. The next secret I am going to reveal is that I started a toolkit to help you create blog related programs with C# / .NET / Google Blogs API.

For now I am planning to release the program for free, as a Lite version and I plan to spend some more time to create a better looking version with SEO features in it and distribute it for a small fee (something like 10 EU).
The Toolkit will released for free now.

Well that's it. I am looking forward when I will have some more time to develop those
controls and programs to help the Blogger community grow ;)

Jan 10, 2008

5 minutes with C# - Get your blog in TreeView Control

I played a bit more with the Google Blogs Api and was able to create a custom TreeView control to help you get your blog in Hierarchical View.

Here is a screenshot of the TreeView:



The control will be soon released to my site and new blog post will be published to let you know
.

Another 5 minutes with C# to post to Google Blogs (Blogger.com) using Google Blogs SDK

             // Create service to be used for queries
             Service service = new Service ( "blogger" , "blogger-sample" );
            
AtomEntry createdEntry = new AtomEntry ();
            
// Create credentials you should add your blog username
             // and password here
            service.Credentials = new GDataCredentials ( "your_username" , "your_password" );

            
// As I only have one blog to speed up - I am taking it,
             // You can extend here in order to allow the user to
             // select from mutliple
blogs if he / she has.
             Uri firstBlogUri = GetFirstBlogUri(service);
            
            
// If we have the Uri - it's time to actually post.
             if (firstBlogUri != null )
            {
               
// Create FeedQuery and assign Uri.
                FeedQuery query = new FeedQuery ();
                query.Uri = firstBlogUri;

               
// Create Atom Feed from that query.
                AtomFeed feed = service.Query(query);

               
// Create atom entry for the new post
                AtomEntry newPost = new AtomEntry ();

               
// Fill in the post information
                // You need to have a control named richTextBox2 which will
                // contain the post body and a textBox1 control which will
                // contain the post title.

                newPost.Title.Text = this .textBox1.Text;
                newPost.Content =
new AtomContent ();
                newPost.Content.Content = richTextBox2.Text;
                newPost.Content.Type =
"html" ;
                newPost.Authors.Add(
new AtomPerson ());
                newPost.Authors[0].Name =
"Pavel Donchev" ;

               
// Try to publish and report success / fail:
                try
                {
                   createdEntry = service.Insert(query.Uri, newPost);
                }
               
catch ( Exception ex)
                {
                  
MessageBox .Show(ex.Message);
                }
               
if (createdEntry != null )
                {
                  
MessageBox .Show(newPost.Title.Text + " posted successfully!" );
                }
            }

There is also a helper function to retrieve the blog Uri:

      
Uri GetFirstBlogUri( Service service)
       {
            
FeedQuery query = new FeedQuery ();
            
// Retrieving a list of blogs
            query.Uri = new Uri ( "http://www.blogger.com/feeds/default/blogs" );

            
AtomFeed feed = null ;
            feed = service.Query(query);
            
AtomEntry entry = feed.Entries[0];
            
for ( int i = 0; i < entry.Links.Count; i++)
            {
               
if (entry.Links[i].Rel.Equals( "http://schemas.google.com/g/2005#post" ))
                {
                  
return new Uri (entry.Links[i].HRef.ToString());
                }
            }
            
return null ;
       }

Jan 8, 2008

5 minutes C# code to help you blog source ...

As I was unabled to find a reliable editor to convert my code samples to html, I decided to write one. You need two richTextBox components, named richTextBox1 and richTextBox2 and a Button, named button1.

Here is the code you need to put into the button1 click event handler:
       private void button1_Click(object sender, EventArgs e)
       {
            
string oldColor = "-";
            
string newColor = string.Empty;

            
StringBuilder strHtml = new StringBuilder();

            
for (int i = 0; i < this.richTextBox1.Text.Length; i++)
            {
                richTextBox1.Select(i, 1);
               
newColor = System.Drawing.ColorTranslator.ToHtml(richTextBox1.SelectionColor);
               
if ((newColor != oldColor) && (newColor != string.Empty))
                {
                  
if (!oldColor.Equals("-"))
                   {
                        strHtml.Append(
"");
                   }
                   strHtml.Append(
" + newColor + ";\">");
                   oldColor = newColor;
                }
                strHtml.Append(richTextBox1.SelectedText.Replace(
"<", "<").Replace(">", ">"));
               
Application.DoEvents();
            }
            strHtml.Append(
""
);
            
StringBuilder sbNew = new StringBuilder();
            sbNew.Append(strHtml.ToString().Replace(
"   ", "   "));
            richTextBox2.AppendText(sbNew.ToString());
       }


PLEASE NOTE: this code was written in 5 or 10 minutes, it doesn't pretend to be either clean or readable, it simply works. If you want - you can take it, optimize it, use it or whatever, just have in mind it wasn't written carefully ;).