C# Kodundan MBX’e Parametre Gönderme

Bir integrated mapping uygulamasında bazen elimizde hazır bulunan bir MBX uygulamasını kullanmak isteyebiliriz. Bunun bazı faydaları olabilir:

1) Tekrar kullanım: Daha önce sapasağlam çalışan bu MBX uygulamasını integrated mapping e taşıma zahmetinden kurtulabiliriz.

2) Senkronizasyon problemlerine çözüm: Integrated mapping de özellikle uzun süren bazı işlemlerde karşımıza çıkabilen senkronizasyon problemlerini çözmede kullanabiliriz. Peki ne zaman çıkar bu senkronizasyon problemleri? Bir MapBasic programındaki kod satırları sırayla, yani senkron olarak çalışır. Örneğin bir MapBasic kod satırı saatlerce süren bir işlem yapıyor olsa bile, bu işlem bitmeden sonraki kod satırına geçilmez. Ama integrated mapping uygulamalarında durum böyle değildir çünkü ortada birbirinden bağımsız çalışan 2 ayrı proses (C# uygulama exe si ve MapInfow.exe) vardır. Gerçi normal olarak MapInfo C# tarafından gelen MapBasic komutlarını kuyruğa (queue) alır ve bu komutları sırayla çalıştırır. Ama bazı durumlarda (mesela Spatial VT den linked tablo ile download yapan bazı MapBasic komutlarında) senkronizasyon problemi olabiliyor. Böyle bir durumda uzun süren bu gibi işlemleri bir MBX e yaptırmak daha uygun olabilir.

Tabi burada daha önceden belirlenmiş sabit bir iş yapan bir MBX den söz etmiyoruz. Herhangi bir parametre almayan statik bir MBX i çalıştırmak bildiğimiz gibi gayet kolay:

mi.Do("Run Application ... MBX yolu");

gibi tek satırlık bir kodla bu işi kolayca yapabiliyoruz. Peki bir MBX e C# tarafından parametre göndermemiz gerekirse ne yapacağız? Bu sorunun cevabı MBApplications koleksiyonuyla verilebilir. MBApplications, MapInfo’nun o an çalıştırdığı tüm MapBasic uygulamalarını döndüren bir koleksiyondur. MBApplications kullanımı VB6 ve C# ta farklılık arz ediyor. VB6’daki kullanımı son derece kolay. Mesela çalışan bir MBX uygulamasına rahatça ulaşabilir ve bu uygulamadaki global MapBasic değişkenlerine aşağıdaki gibi değer atayabiliriz:

mi.MBApplications("test.mbx").MBGlobals("globalVar").Value = Text1.Text

Veya test.mbx deki RemoteMsgHandler prosedürüne şu şekilde parametre gönderebiliriz:

mi.MBApplications("test.mbx").Do ("parametre")

Ama C# ta işimiz bu kadar kolay değil. Öncelikle şunu belirtelim ki yukarıdaki örneklerden de anlaşılacağı üzere C# tan (aynı zamanda diğer dillerden) bir MBX e parametre göndermenin 2 yolu (DDE yi de sayarsak 3 olur ama şu anki konumuzun dışında oluyor kendileri) vardır:

1) MBGlobals koleksiyonunu kullanıp Global MapBasic değişkenlerine değer atamak:

mi.MBApplications

bize object tipinde bir nesne döndürdüğü için MBApplications koleksiyonunun elemanlarına yani çalışmakta olan MBX uygulamalarına doğrudan ulaşamayız. İşte burada yapmamız gereken DMBApplications interface ini kullanmaktır:

(DMBApplications)mi.MBApplications

ifadesi bize gerekli yardımı sağlayacaktır. DMBApplications interface i IEnumerable dan extend ettiği için bir foreach döngüsüyle çalışmakta olan tüm MBX’lere ulaşabiliriz:

private DMapBasicApplication GetMBXByName(string mbxName) {
  foreach (DMapBasicApplication mbApp in (DMBApplications)mi.MBApplications) {
    if (mbApp.Name.Equals(mbxName)) {
      return mbApp;
    }
  }
  return null;
}

Bu kod bize adı verilen bir MBX uygulamasını DMapBasicApplication tipinde döndürür.

İstediğimiz MBX e bu şekilde ulaştıktan sonra sıra geldi MBX’imizin içindeki global MapBasic değişkenlerine ulaşmaya:

private DMBGlobals GetMapBasicGlobals(string mbxName) {
  return (DMBGlobals)GetMBXByName(mbxName).MBGlobals;
}

Bu MapBasic global değişkenlerine C# tarafından değer atayabilmek için aşağıdaki gibi bir metot kullanabiliriz:

private void SetMapBasicGlobalVariable(string mbxName, string globalName, string globalValue) {
  DMBGlobals mbGlobals = GetMapBasicGlobals(mbxName);
  if (mbGlobals != null) {
    foreach (DMBGlobal mbGlobal in mbGlobals) {
      if (mbGlobal.Name.ToUpper().Equals(globalName.ToUpper())) {
        mbGlobal.Value = globalValue;
      }
    }
  }
}

Peki MBX de bulunan ve asıl işi yapacak olan ShadeByRangeOfValues() metodunu C# tarafından nasıl çağıracağız?

Direkt olarak çağıramıyoruz. Zaten bu yüzden bu işlerle uğraşıyoruz. 🙂 Önceki adımlardan sonra MBX deki 3 global değişkenimizi set ettik ve ShadeByRangeOfValues() metodu da bu değişkenleri kullanıyor. Bu yüzden yapılması gereken şey RemoteMsgHandler prosedürüne

Call ShadeByRangeOfValues()

satırı ekleyerek ShadeByRangeOfValues() prosedürünü çalıştırmak. RemoteMsgHandler prosedürünü çalıştırmak için ise tek yapmamız gereken C# tarafındaki MBX uygulamamızın Do() metodunu aşağıdaki gibi çağırmak:

private void MbxDo(string mbxName, string command) {
  DMapBasicApplication mbApp = GetMBXByName(mbxName);
  if (mbApp != null) {
    mbApp.Do(command);
  }
}

Bu metodu örneğin

MbxDo("Shade.mbx", "");

şeklinde çağırırsak MBX imize tablo, kolon ve aralık sayısı parametrelerini göndererek tematik yaptırmış oluruz. Global MapBasic değişkenlerine değer atama yöntemi bu şekilde. Bu arada kullanacağımız MapBasic dosyası da aşağıdaki gibi olsun:

include "mapbasic.def"

declare sub Main
declare sub RemoteMsgHandler
declare sub ShadeByRangeOfValues

global tableName as string
global columnName as string
global rangeNum as integer

Sub Main
  'Burada bir şey yapmamıza gerek yok.
  'MBX çalıştırıldığında RemoteMsgHandler dinlemeye geçer ve
  'C# tarafından Form1.MbxDo() metodu ile gelecek parametreyi bekler.
End Sub

Sub RemoteMsgHandler
  'C# ta Form1.MbxDo() metodunda bulunan mbApp.Do(command); satırı ile gönderilen command değerini al
  Note CommandInfo(CMD_INFO_MSG)
  Call ShadeByRangeOfValues()
End Sub

Sub ShadeByRangeOfValues()
  '...
  Shade tableName With columnAlias Ranges From Variable range_limits Style Variable brush_styles
End Sub

2) MBX.Do() metodu ile MapBasic tarafındaki RemoteMsgHandler prosedürüne komut (parametre) göndermek:

Global değişkenleri hiç kullanmadan aşağıdaki gibi daha kısa bir MapBasic ile RemoteMsgHandler prosedürüne bir ayıraç ile ayrılmış değerler gönderebiliriz:

private void MbxDo(string mbxName, string command) {
  DMapBasicApplication mbApp = GetMBXByName(mbxName);
  if (mbApp != null) {
    // Bu satır çalıştığında göndermekte olduğumuz command değeri Shade.mb de bulunan
    // RemoteMsgHandler prosedüründeki CommandInfo(CMD_INFO_MSG) komutu ile alınabilir.
    mbApp.Do(command);
  }
}

 

include "mapbasic.def"

declare sub Main
declare sub RemoteMsgHandler
declare sub ShadeByRangeOfValues

Sub Main
  'Burada bir şey yapmamıza gerek yok.
  'MBX çalıştırıldığında RemoteMsgHandler dinlemeye geçer ve
  'C# tarafından Form1.MbxDo() metodu ile gelecek parametreyi bekler.
End Sub

Sub RemoteMsgHandler
  'C# ta Form1.MbxDo() metodunda bulunan mbApp.Do(command); satırı ile gönderilen command değerini al
  Note CommandInfo(CMD_INFO_MSG) 'Burası örneğin "Mahalle|Nufus|5" gibi bir string olabilir. (Ayıraç olarak pipe (|) kullandık.)
  Call ShadeByRangeOfValues()
End Sub

Sub ShadeByRangeOfValues()
  'CommandInfo(CMD_INFO_MSG) ile alınan ve ayıraç ile ayrılan parametreleri parse et ve
  'tableName, columnName vb. değişkenlerinin değerini buradan al.
  Shade tableName With columnAlias Ranges From Variable range_limits Style Variable brush_styles
End Sub

Örnek C# projesini aşağıdaki linkten indirebilirsiniz:

https://dl.dropboxusercontent.com/u/54151940/GIS/MapInfo/IntegratedMapping/CS_MBApplications.rar

Advertisements
  1. ömer
    29/05/2015 at 12:20

    http://www.sonercelix.com/MakaleDetay/2060/C-ile-exe-dosyasina-parametre-gonderimi

    Bu konuyla ilgili anlatımlar sitede mevcuttur. Ayrıca bu tarz konularla ilgili bilgi bulabileceğiniz bir sitedir. Uzun zamandır takip ettiğim ve beğendiğim bir sitedir. Tavsiye ederim.

    • 29/05/2015 at 15:06

      Bağlantısını verdiğiniz sitede C# hakkında faydalı yazılar olmakla birlikte, bu sayfada bahsettiğim konu biraz farklı. Burada bahsedilen, bir C# uygulamasından bir *.exe ye parametre göndermek değil, bir MapBasic programına (*.mbx) parametre göndermektir.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: