Archive | May, 2013

Python in C# Using IronPython

16 May
C# calling Python

C# calling Python

I am better at Python than C# and when I couldn’t do something in C#, I would use:

System.Diagnostics.Process.Start(“DoItInPython.py”);

I had seen some posts about IronPython but always ignored them – to my own detriment. IronPython is the solution! You can call Python from C# or C# from Python. That means I can use System.Windows.Forms in my Python code.

Reading a post from MSDN, I put together this example that onClick() of button1 it passes the string from the textbox to a python function that just adds “Hello: ” to it. The python function is in name.py:

def printName(name):
return “Hello: “+name

The C# using IronPython:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
var ipy = Python.CreateRuntime();
dynamic test = ipy.UseFile(@”C:\Documents and Settings\user\Desktop\name.py”);
MessageBox.Show(test.printName(textBox1.Text.ToString()));
}
}
}

You can go the other way too. Read the documentation for IronPython.net for more information than I will give here. Here is a Python script using a Windows Form.

Python calling System.Windows.Forms.MessageBox.Show()

Python calling System.Windows.Forms.MessageBox.Show()

You can see it took me a minute to get it working using my own DLL. Here is how to use a System DLL:

import clr

clr.AddReference(“System.Windows.Forms”)

import System.Windows.Forms as f

f.MessageBox.Show(“Hello From Python!”)

This will popup a MessageBox. Simple, right? I have a DLL on my desktop I wrote. As you can see in my screenshot above, I got it to come in almost the same way – just use AddReferenceToFileAndPath(“C:\desktop\yourname.dll”). Here is the full code to call the method MyName() – yourname is the namespace, Name is the class and myName is a method:

import clr

clr.AddReferenceToFileAndPath(“C:\desktop\yourname.dll”)

import yourname as n

a=n.Name()

a.myName(“Paul”)

Ouputs: ‘Hello:  Paul’

Now I can use Python in C# and Windows DLLs in Python. I’m positive this will come in handy.

User Input in Python Without Pressing Enter

3 May

I got my hands on a barcode scanner and immediately went to writing a python script to manage my laptop inventory. The scanner prints out the value of the code as user input followed by a tab (\t). Windows users tend to click in a text box, scan, press a button and viola! This is cool, but I need to scan several laptops in a row and want it to work like a cash register – why should I have to use the mouse to highlight a text box, scan, press enter, highlight a text box…. Too much work and defeats the purpose of the scanner.

How do you not require the user to hit enter at the command line after they enter text – scan a barcode? The answer is msvcrt. There is a function msvcrt.getch() that reads in each character. Nothing is echoed to the console and it will not wait for enter to be pressed.

My scanner types 13 characters and the 14th is a tab (\t),  so each character is read individually. Not good. I solved this by buffering the characters until a tab (\t) is encountered. I then convert the array to a string and run that string through my database.

No keyboard action required!

The other thing I learned on this is that in python While has an Else.  The while loops took me a few tries to figure out but I am awful at control structures.

Here is my code:

import sqlite3
import sys
import msvcrt

conn = sqlite3.connect(“ini.db”)
cursor=conn.cursor()
d=”
a=[]
i=0
input_char=”

while(d!=’end’):

if (input_char != ‘\t’):
input_char=msvcrt.getch()
a.append(input_char)

else:

d=”.join(a)
d=d.strip(‘\t’)
inputs=”SN”+d
sql=”SELECT term FROM terminals WHERE id='”+inputs+”‘”
for row in cursor.execute(sql):
print row[0]
input_char=”
d=”
a=[]
break

else:
f=open(“My.ini”,”w+”)
f.write(“The Headers for my ini”)
for row in cursor.execute(“SELECT id,term FROM terminals”):
f.write(row[0]+”=”+row[1]+”\n”)

Send MMS from ArcGIS Desktop Explorer – or Revit.

2 May
MMS from a button in Desktop Explorer.

MMS from a button in Desktop Explorer.

I had an earlier post on sending an MMS from C#. I have taken it one step further and dropped this code in to ArcGIS Desktop Explorer as a button. click the button and it takes a screenshot, pops up a form and attaches the screenshot. Can send as email or as an MMS. This should work for Revit too since the SDK is C# and all the code is from Microsoft not the GIS API.

 

When launching a form from the buttons in GIS, threading becomes an issue. Note the use of ShowDialog().  Also, in order to caputure the screen without the form in the way, grab it before launching the form. This is how you launch a form from the button in GIS:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Windows.Forms;
using System.Drawing.Imaging;

using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;

namespace geomms
{
public class Button : ESRI.ArcGISExplorer.Application.Button
{

public override void OnClick()
{
int screenWidth = Screen.GetBounds(new System.Drawing.Point(0, 0)).Width;
int screenHeight = Screen.GetBounds(new System.Drawing.Point(0, 0)).Height;
Bitmap bmpScreenShot = new Bitmap(screenWidth, screenHeight);
Graphics gfx = Graphics.FromImage((Image)bmpScreenShot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));
bmpScreenShot.Save(“test.jpg”, ImageFormat.Jpeg);

Form1 a = new Form1();
a.ShowDialog();

}
}
}

 

 

Here is the code to send the MMS:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Mail;
using System.Drawing.Imaging;

namespace geomms
{
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)
{
try
{
String strFileName = string.Empty;
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient(“embudo.cabq.gov”);
mail.From = new MailAddress(“pcrickard@cabq.gov”);
mail.To.Add(tobox.Text.ToString());
mail.Subject = subjbox.Text.ToString();
mail.Body = msgbox.Text.ToString();
strFileName = “test.jpg”;
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(strFileName);
mail.Attachments.Add(attachment);

SmtpServer.Send(mail);
MessageBox.Show(“Sent Message”, “MMS by Paul”);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

 

C# DataGridView Export

2 May
My .ini Magaer using DataGridView

My .ini Magaer using DataGridView

I need to manage a .ini file that contains data in the format id=value. There is some information in the first 6 lines that I deal with in my code, but for the most part the data can be dealt with by splitting on ‘=’.

This app loads the .ini in to a DataGridView and allows the user to search, edit, add or remove records. Lastly, any changes can be exported out to a new .ini file.

Here is the code to create a DataGridView, search columns, clear highlighted rows and save as text. Each function is easy to find as it is attached to a buttons onclick.

Here is the code for the form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace ini
{
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();

 

dataGrid.AutoGenerateColumns = false;

DataGridViewTextBoxColumn titleColumn = new DataGridViewTextBoxColumn();
titleColumn.DataPropertyName = “SN”;
titleColumn.HeaderText = “Machine Name”;

DataGridViewTextBoxColumn postColumn = new DataGridViewTextBoxColumn();
postColumn.DataPropertyName = “Terminal”;
postColumn.HeaderText = “Terminal ID”;
dataGrid.Columns.Add(titleColumn);
dataGrid.Columns.Add(postColumn);

dataGrid.AllowUserToOrderColumns = true;
dataGrid.AllowUserToDeleteRows = true;
dataGrid.GridColor = Color.DarkSlateGray;

var reader = new StreamReader(File.OpenRead(“Terminal.ini”));
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(‘=’);

if (line.Contains(“=”))
{
if (values[0] == null)
{
values[0] = “EMPTY”;
dataGrid.Rows.Add(values[0], values[1]);
}
else
{
dataGrid.Rows.Add(values[0], values[1]);
}
}
else
{

}

//Maybe use this later to search?
//listA.Add(values[0]);
//listB.Add(values[1]);

}
}

private void button1_Click(object sender, EventArgs e)
{
string searchValue = textBox1.Text;

dataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
if (row.Cells[0].Value.ToString().Contains(searchValue))
{
row.Selected = true;

}

}

}
catch (Exception exc)
{

}
}

private void button4_Click(object sender, EventArgs e)
{
string searchValue = textBox1.Text;

dataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
if (row.Cells[1].Value.ToString().Contains(searchValue))
{
row.Selected = true;

}

}

}
catch (Exception exc)
{

}
}

private void button2_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
row.Selected = false;
}
}

private void button3_Click(object sender, EventArgs e)
{
if (System.IO.File.Exists(“Terminal-fromApp.ini”))
{

try
{
System.IO.File.Delete(“Terminal-fromApp.ini”);
}
catch (System.IO.IOException excep)
{
Console.WriteLine(excep.Message);
return;
}
}

StringBuilder myString = new StringBuilder();
StreamWriter sw = new StreamWriter(“Terminal-fromApp.ini”, true);
// var headers = dataGrid.Columns.Cast<DataGridViewColumn>();
myString.Append(“[Settings]\r\n”+”START=GUI1\r\n”+”MAX=G999\r\n”+”[Mappings]\r\n” );
myString.AppendLine();

foreach (DataGridViewRow row in dataGrid.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
myString.Append(string.Join(“=”, cells.Select(cell => cell.Value )));
myString.AppendLine();

}
string q = myString.ToString();
string xx = q.Substring(0,q.LastIndexOf(‘=’));
sw.WriteLine(xx);
sw.Close();
MessageBox.Show(“File Exported”, “Done”);
}
}
}