SNMP-тестер сетевых устройств. GUI-программа на Windows.Forms для Linux.
Однако, я обратил внимание, что хотя у меня выложено достаточно много программ для Linux - однако все они выложены в версиях для командной строки, например GoogleTranslate - англо-русский онлайн переводчик.
И я решил хотя бы одну свою сетевую прогу выложить в версии GUI для Linux - заодно показать всем пример GUI для Linux на System.Windows.Forms.
Чтобы понять тему этой странички случайному начинающему программисту или члену секты мазохистов (любителей платежей Биллу Гейтсу) - нужно хотя бы для начала поставить себе Linux - Установка и начальное конфигурирование OpenSuse Linux и хоть чуть-чуть вникнуть в цель существования MONO - Low cost and platform independent ASP.NET - be free with MONO..
Итак, если мой подход написания программ на Visual Basic на System.Windows.Forms для Linux понятен - то давайте разберемся что за прога тут будет описана, и что за слова 'Public', 'Zywall 70' и последовательность цифр '6.1.2.1.1.1.0' (над словом Zywall) - видны на рисунке слева и для чего такая прога может быть нужна в принципе.
SNMP - это протокол опроса сетевых устройств, который сообщает преполезнейшие сведения о работе различных сетевых устройств. Вот для примера что говорит мне дорогая коммерческая прога о работе моих устройств ZyWall 70 и SRW2016 - это не только название устройства, но и масса преполезнейших счетчиков, показывающих направление движения трафика, загруженность каждого интерфейса:
Это конечно большая и сложная прога, которая делалась немаленькой фирмой в течении четырех лет - а моя прога была сделана за пару часов, но тем не менее она тоже полезна, ибо позволяет проверить наличие устройства в сети, опросить его название, прочитать его счетчики. Кроме того, с помощью SMNP можно совершить просто жуткие вещи над кампутером, работающим под уиндауз:
Моя простая прога имеет ровно тот же самый SNMP-движок, что и большая сложная прога, но отличается от большой проги тем, что большая прога получает все классы MIB (чтобы узнать для произвольного случая что находится в той или иной переменной ответа). А в моей проге можно посмотреть то же самое, но только ответ получается просто в виде 16-ричного дампа, а не в виде точно разобранных именованных полей, которые приходят в ответе устройства. И если вы знаете куда смотреть, то увидите там те же самые цифры.
Все те же самые счетчики по идее можно увидеть и в Web-интерфейсе сетевого устройства, только они там разбросаны по вкладкам и работа web-интерфейса требует больших накладных расходов самого устройства (и залогинивания в Web-интерфейс - чего обычно не требуется чтобы просто посмотреть по SNMP основные счетчики сетевого устройства):
Главная же фишка SNMP заключается в том, чтобы в сетевом устройстве был включен Agent SMNP - тогда все эти полезные счетчики можно не только читать, но и устанавливать, например отключить некоторый порт - просто послав команду SNMP SET. Включение агента делается или в Web-интерфейсе сетевого устройства или в его командной строке.
Теперь, познакомившись с общей теорией SNMP - посмотрим как сделана моя SNMP-программа для Linux на System.Windows.Forms.
Поскольку я привык с сервису студии, а возможно потому что у меня на Win-кампутере стоит два огромных экрана, с которыми я привык работать - я изначально сделал прогу под Visual Studio и перенес готовый проект на Linux-машину. Это мои личные пристрастия. Если бы у меня стояли два огромных экрана на машине под Линуском и я бы изначально привык работать без Intellisense - мне бы ничто не помешало сразу создать проект в MonoDevelop. Ну и кроме того, конечно, что визуальный дизайнер Windows.Forms в MonoDevelop не поддерживается, только дизайнер QT4. Поэтому я просто перенес готовый Windows.Forms-проект с Windows-машины в среду Linux.
Далее (последовательно): проект просто открывается, удаляется ссылка не ненужную сборку из виндузни, проверяется тип проекта (Winforms c GUI). Далее проект запускается - однако выясняется что переменная ANSI является ключевым словом MonoDevelop из-за чего компилятор бейсика VBNC пишет ошибку. Переменная переименовывается в ANSI1 - после чего проект стартует под MONO.
Далее я продемонстрировал как MonoDevelop показывает пространство имен MONO-сборок, заменяющих родные ссылки .NET и экспортировал проект в бинарный Linux-формат. Далее я запустил прогу уже не из под MonoDevelop, и непосредственно из командной строки:
Теперь посмотрим OpenSource-код проги. Прога состоит из модуля формирования сокета SNMP (его я взял готовый из документации и просто переписал его с C++ на бейсик):
1: Module SNMP
2:
3: Public Function [Get](ByVal request As String, ByVal IP As Net.IPAddress, ByVal community As String, ByVal MIBstring As String) As Byte()
4: Dim Packet As Byte() = New Byte(1023) {}
5: Dim MIB As Byte() = New Byte(1023) {}
6: Dim SnmpLen As Integer
7: Dim CommunityLen As Integer = community.Length
8: Dim MIBvals As String() = MIBstring.Split("."c)
9: Dim MIBlen As Integer = MIBvals.Length
10: Dim cnt As Integer = 0, temp As Integer, i As Integer
11: Dim orgMIBlen As Integer = MIBlen
12: Dim Pos As Integer = 0
13:
14: ' Convert the string MIB into a byte array of integer values
15: ' Unfortunately, values over 128 require multiple bytes
16: ' which also increases the MIB length
17: For i = 0 To orgMIBlen - 1
18: temp = Convert.ToInt16(MIBvals(i))
19: If temp > 127 Then
20: MIB(cnt) = Convert.ToByte(128 + (temp \ 128))
21: MIB(cnt + 1) = Convert.ToByte(temp - ((temp \ 128) * 128))
22: cnt += 2
23: MIBlen += 1
24: Else
25: MIB(cnt) = Convert.ToByte(temp)
26: cnt += 1
27: End If
28: Next
29: SnmpLen = 29 + CommunityLen + MIBlen - 1 'Length of entire SNMP Packet
30: 'The SNMP sequence start
31: Packet(Pos) = &H30 'Sequence start
32: Pos += 1
33: Packet(Pos) = Convert.ToByte(SnmpLen - 2) 'sequence size
34: Pos += 1
35: 'SNMP version
36: Packet(Pos) = &H2 'Integer type
37: Pos += 1
38: Packet(Pos) = &H1 'length
39: Pos += 1
40: Packet(Pos) = &H0 'SNMP version 1
41: Pos += 1
42: 'Community name
43: Packet(Pos) = &H4 ' String type
44: Pos += 1
45: Packet(Pos) = Convert.ToByte(CommunityLen) 'length
46: Pos += 1
47: 'Convert community name to byte array
48: Dim data As Byte() = System.Text.Encoding.ASCII.GetBytes(community)
49: For i = 0 To data.Length - 1
50: Packet(Pos) = data(i)
51: Pos += 1
52: Next
53: 'Add GetRequest or GetNextRequest value
54: If request = "get" Then
55: Packet(Pos) = &HA0
56: Pos += 1
57: Else
58: Packet(Pos) = &HA1
59: Pos += 1
60: End If
61:
62: Packet(Pos) = Convert.ToByte(20 + MIBlen - 1) 'Size of total MIB
63: Pos += 1
64: 'Request ID
65: Packet(Pos) = &H2 'Integer type
66: Pos += 1
67: Packet(Pos) = &H4 'length
68: Pos += 1
69: Packet(Pos) = &H0 'SNMP request ID
70: Pos += 1
71: Packet(Pos) = &H0
72: Pos += 1
73: Packet(Pos) = &H0
74: Pos += 1
75: Packet(Pos) = &H1
76: Pos += 1
77: 'Error status
78: Packet(Pos) = &H2 'Integer type
79: Pos += 1
80: Packet(Pos) = &H1 'length
81: Pos += 1
82: Packet(Pos) = &H0 'SNMP error status
83: Pos += 1
84: 'Error index
85: Packet(Pos) = &H2 'Integer type
86: Pos += 1
87: Packet(Pos) = &H1 'length
88: Pos += 1
89: Packet(Pos) = &H0 'SNMP error index
90: Pos += 1
91: 'Start of variable bindings
92: Packet(Pos) = &H30 'Start of variable bindings sequence
93: Pos += 1
94: Packet(Pos) = Convert.ToByte(6 + MIBlen - 1)
95: Pos += 1
96: ' Size of variable binding
97: Packet(Pos) = &H30 'Start of first variable bindings sequence
98: Pos += 1
99: Packet(Pos) = Convert.ToByte(6 + MIBlen - 1 - 2) 'size
100: Pos += 1
101: Packet(Pos) = &H6
102: Pos += 1
103: 'Object type
104: Packet(Pos) = Convert.ToByte(MIBlen - 1) 'length
105: Pos += 1
106: 'Start of MIB
107: Packet(Pos) = &H2B
108: Pos += 1
109: 'Place MIB array in Packet
110: For i = 2 To MIBlen - 1
111: Packet(Pos) = Convert.ToByte(MIB(i))
112: Pos += 1
113: Next
114: Packet(Pos) = &H5 'Null object value
115: Pos += 1
116: Packet(Pos) = &H0 'Null
117: ReDim Preserve Packet(Pos + 1)
118: 'Send Packet to destination
119: Dim sock As New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Dgram, Net.Sockets.ProtocolType.Udp)
120: sock.SetSocketOption(Net.Sockets.SocketOptionLevel.Socket, Net.Sockets.SocketOptionName.ReceiveTimeout, 5000)
121: '
122: Dim iep As New Net.IPEndPoint(IP, 161)
123: Dim ep As Net.IPEndPoint = DirectCast(iep, Net.EndPoint)
124: sock.SendTo(Packet, SnmpLen, Net.Sockets.SocketFlags.None, iep)
125:
126: 'Receive response from Packet
127: Dim OutBuf(1000) As Byte
128: Dim recv As Integer = sock.ReceiveFrom(OutBuf, ep)
129: ReDim Preserve OutBuf(recv)
130: Return OutBuf
131:
132: End Function
133: End Module
Из модуля вывода дампа:
1: Module DUMP
2:
3: Public Function PrintDump(ByVal ByteArray As Byte()) As String
4: If ByteArray Is Nothing Then Return ""
5: If ByteArray.Length = 0 Then Return " "
6: Dim ANSI1 As New System.Text.ASCIIEncoding
7: Dim Out As New System.Text.StringBuilder
8: For i As Integer = 0 To ByteArray.Length - 1
9: Out.Append(String.Format("{0:X2} ", ByteArray(i)))
10: If (i Mod 8 = 7) Then
11: Out.Append(" ")
12: Dim Target(7) As Byte
13: For j As Integer = 0 To 7
14: Target(j) = ByteArray(i + j - 7)
15: If Target(j) > 20 Then
16: Out.Append((ANSI1).GetString(Target, j, 1))
17: Else
18: Out.Append(".")
19: End If
20: Next
21: Out.AppendLine()
22: End If
23: Next
24: 'допечатка хвостика из последней неполной строки
25: Dim Target1(7) As Byte
26: For j As Integer = 0 To (ByteArray.Length Mod 8) - 1
27: Target1(j) = ByteArray(ByteArray.Length - (ByteArray.Length Mod 8) + j)
28: Next
29: Out.Append(New String(" ", (8 - (ByteArray.Length Mod 8)) * 3 + 4))
30: Out.Append((ANSI1).GetString(Target1))
31: Out.AppendLine()
32: Return Out.ToString
33: End Function
34:
35: End Module
Из определения GUI-интерфейса:
1: Partial Class SNMP_TESTER
2: Inherits System.Windows.Forms.Form
3:
4: 'Form overrides dispose to clean up the component list.
5: <System.Diagnostics.DebuggerNonUserCode()> _
6: Protected Overrides Sub Dispose(ByVal disposing As Boolean)
7: Try
8: If disposing AndAlso components IsNot Nothing Then
9: components.Dispose()
10: End If
11: Finally
12: MyBase.Dispose(disposing)
13: End Try
14: End Sub
15:
16: 'Required by the Windows Form Designer
17: Private components As System.ComponentModel.IContainer
18:
19: 'NOTE: The following procedure is required by the Windows Form Designer
20: 'It can be modified using the Windows Form Designer.
21: 'Do not modify it using the code editor.
22: <System.Diagnostics.DebuggerStepThrough()> _
23: Private Sub InitializeComponent()
24: Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(SNMP_TESTER))
25: Me.btStart = New System.Windows.Forms.Button
26: Me.txObjectID = New System.Windows.Forms.TextBox
27: Me.txIP = New System.Windows.Forms.TextBox
28: Me.txDump = New System.Windows.Forms.TextBox
29: Me.Label1 = New System.Windows.Forms.Label
30: Me.Label2 = New System.Windows.Forms.Label
31: Me.Label3 = New System.Windows.Forms.Label
32: Me.SuspendLayout()
33: '
34: 'btStart
35: '
36: Me.btStart.Location = New System.Drawing.Point(277, 80)
37: Me.btStart.Name = "btStart"
38: Me.btStart.Size = New System.Drawing.Size(110, 23)
39: Me.btStart.TabIndex = 0
40: Me.btStart.Text = "GET"
41: Me.btStart.UseVisualStyleBackColor = True
42: '
43: 'txObjectID
44: '
45: Me.txObjectID.BackColor = System.Drawing.Color.WhiteSmoke
46: Me.txObjectID.Font = New System.Drawing.Font("Courier New", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
47: Me.txObjectID.Location = New System.Drawing.Point(23, 29)
48: Me.txObjectID.Name = "txObjectID"
49: Me.txObjectID.Size = New System.Drawing.Size(364, 22)
50: Me.txObjectID.TabIndex = 1
51: Me.txObjectID.Text = "1.3.6.1.2.1.1.1.0"
52: '
53: 'txIP
54: '
55: Me.txIP.BackColor = System.Drawing.Color.WhiteSmoke
56: Me.txIP.Font = New System.Drawing.Font("Courier New", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
57: Me.txIP.Location = New System.Drawing.Point(24, 81)
58: Me.txIP.Name = "txIP"
59: Me.txIP.Size = New System.Drawing.Size(133, 22)
60: Me.txIP.TabIndex = 2
61: Me.txIP.Text = "192.168.0.100"
62: '
63: 'txDump
64: '
65: Me.txDump.BackColor = System.Drawing.Color.WhiteSmoke
66: Me.txDump.Font = New System.Drawing.Font("Courier New", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
67: Me.txDump.Location = New System.Drawing.Point(24, 144)
68: Me.txDump.Multiline = True
69: Me.txDump.Name = "txDump"
70: Me.txDump.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
71: Me.txDump.Size = New System.Drawing.Size(363, 194)
72: Me.txDump.TabIndex = 3
73: '
74: 'Label1
75: '
76: Me.Label1.AutoSize = True
77: Me.Label1.ForeColor = System.Drawing.SystemColors.ActiveCaption
78: Me.Label1.Location = New System.Drawing.Point(21, 13)
79: Me.Label1.Name = "Label1"
80: Me.Label1.Size = New System.Drawing.Size(52, 13)
81: Me.Label1.TabIndex = 4
82: Me.Label1.Text = "Object ID"
83: '
84: 'Label2
85: '
86: Me.Label2.AutoSize = True
87: Me.Label2.ForeColor = System.Drawing.SystemColors.ActiveCaption
88: Me.Label2.Location = New System.Drawing.Point(20, 65)
89: Me.Label2.Name = "Label2"
90: Me.Label2.Size = New System.Drawing.Size(57, 13)
91: Me.Label2.TabIndex = 5
92: Me.Label2.Text = "IP address"
93: '
94: 'Label3
95: '
96: Me.Label3.AutoSize = True
97: Me.Label3.ForeColor = System.Drawing.SystemColors.ActiveCaption
98: Me.Label3.Location = New System.Drawing.Point(21, 128)
99: Me.Label3.Name = "Label3"
100: Me.Label3.Size = New System.Drawing.Size(55, 13)
101: Me.Label3.TabIndex = 6
102: Me.Label3.Text = "Response"
103: '
104: 'SNMP_TESTER
105: '
106: Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
107: Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
108: Me.ClientSize = New System.Drawing.Size(405, 364)
109: Me.Controls.Add(Me.Label3)
110: Me.Controls.Add(Me.Label2)
111: Me.Controls.Add(Me.Label1)
112: Me.Controls.Add(Me.txDump)
113: Me.Controls.Add(Me.txIP)
114: Me.Controls.Add(Me.txObjectID)
115: Me.Controls.Add(Me.btStart)
116: Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
117: Me.Name = "SNMP_TESTER"
118: Me.Text = "SNMP_TESTER"
119: Me.ResumeLayout(False)
120: Me.PerformLayout()
121:
122: End Sub
123: Friend WithEvents btStart As System.Windows.Forms.Button
124: Friend WithEvents txObjectID As System.Windows.Forms.TextBox
125: Friend WithEvents txIP As System.Windows.Forms.TextBox
126: Friend WithEvents txDump As System.Windows.Forms.TextBox
127: Friend WithEvents Label1 As System.Windows.Forms.Label
128: Friend WithEvents Label2 As System.Windows.Forms.Label
129: Friend WithEvents Label3 As System.Windows.Forms.Label
130:
131: End Class
И из алгоритма GUI-интерфейса (понятно что алгоритм этот можно расширить в любую сторону, например вытащить на форму "прочитать" или "записать" значение SNMP-обьекта):
1: Public Class SNMP_TESTER
2:
3: Dim SnmpResponse As Byte()
4:
5: Private Sub btStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btStart.Click
6: txDump.Text = ""
7: Try
8: btStart.Enabled = False
9: SnmpResponse = SNMP.Get("get", Net.IPAddress.Parse(txIP.Text), "public", txObjectID.Text)
10: Catch generatedExceptionName As Net.Sockets.SocketException
11: 'нет ответа от устройства
12: txDump.Text = "No response"
13: Catch ex As System.Exception
14: 'общий баг проги
15: txDump.Text = "Error. " & vbCrLf & ex.Message
16: Finally
17: btStart.Enabled = True
18: End Try
19: '
20: Try
21: txDump.Text = PrintDump(SnmpResponse)
22: Catch ex As Exception
23: txDump.Text = "Print Error. " & vbCrLf & ex.Message
24: End Try
25:
26: End Sub
27: End Class
MonoDevelop устроен так же просто, как и Visual Studio - он просто формирует вызов компилятора командной строки VBNC:
vbnc "-out:/home/admin/Documents/SmnpGUI/bin/Debug/SmnpGUI.exe" -nologo -utf8output -debug:full -optionstrict- -optionexplicit+ -optioncompare:binary -optioninfer+ -define:_MYTYPE=\"WindowsForms\" -rootnamespace:SmnpGUI -define:DEBUG=-1 -define:TRACE=-1 -nowarn:42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 -doc:SmnpGUI.xml -main:SmnpGUI.My.MyApplication -target:winexe "-r:/usr/lib/mono/2.0/System.dll" "-r:/usr/lib/mono/2.0/System.Data.dll" "-r:/usr/lib/mono/2.0/System.Drawing.dll" "-r:/usr/lib/mono/2.0/System.Windows.Forms.dll" "-r:/usr/lib/mono/2.0/System.Xml.dll" "-r:/usr/lib/mono/2.0/System.Core.dll" "-r:/usr/lib/mono/2.0/System.Xml.Linq.dll" "-r:/usr/lib/mono/2.0/System.Data.DataSetExtensions.dll" "/home/admin/Documents/SmnpGUI/DUMP.vb" "/home/admin/Documents/SmnpGUI/Form1.vb" "/home/admin/Documents/SmnpGUI/Form1.Designer.vb" "/home/admin/Documents/SmnpGUI/My Project/AssemblyInfo.vb" "/home/admin/Documents/SmnpGUI/My Project/Application.Designer.vb" "/home/admin/Documents/SmnpGUI/My Project/Resources.Designer.vb" "/home/admin/Documents/SmnpGUI/My Project/Settings.Designer.vb" "/home/admin/Documents/SmnpGUI/SNMP.vb" "-resource:/home/admin/Documents/SmnpGUI/Form1.resources,SmnpGUI.SNMP_TESTER.resources" "-resource:/home/admin/Documents/SmnpGUI/My Project/Resources.resources,SmnpGUI.My Project.Resources.resources" -imports:Microsoft.VisualBasic -imports:System -imports:System.Collections -imports:System.Collections.Generic -imports:System.Data -imports:System.Drawing -imports:System.Diagnostics -imports:System.Windows.Forms -imports:System.Linq -imports:System.Xml.Linq
Warning: Option Strict Off will probably fail. Warning : VBNC2009: the option optioninfer+ was not recognized - ignored Warning : VBNC2009: the option doc was not recognized - ignored Assembly 'SmnpGUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' saved successfully to '/home/admin/Documents/SmnpGUI/bin/Debug/SmnpGUI.exe'. There were 0 errors and 2 warnings. Compilation successful Compilation took 00:00:01.8783010
На выходе компилятора получается .NET-байт код (точнее MONO-байт код) SmnpGUI.exe, которой исполняется run-time движком MONO. Есть и другие варианты, когда например байт-код может быть вперемешку, JAVA и MONO - какие-то функции вам нравится использовать из библиотеки .NET, какие-то из JAVA. Это обеспечивается ран-тайм движком IKVM.NET.
Далее мы получим из MONO байт-кода бинарник (com-файл в концепции Windows) командой mkBundle. Обратите внимание, что tаrget-платформа бинарника может быть любая - на момент написания этой заметки кроме X86 MONO поддерживается на процессорных архитектурах s390, s390x (32 and 64 bits), SPARC (32), PowerPC, AMD64, IA64, ARM, MIPS во всевозможнейших операционных системах.
mkbundle -o /home/admin/Debug/SnmpTester /home/admin/Debug/SmnpGUI.exe --deps
OS is: Linux Sources: 1 Auto-dependencies: True embedding: /home/admin/Debug/SmnpGUI.exe embedding: /usr/lib/mono/2.0/mscorlib.dll embedding: /usr/lib/mono/gac/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll embedding: /usr/lib/mono/gac/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll embedding: /usr/lib/mono/gac/System/2.0.0.0__b77a5c561934e089/System.dll embedding: /usr/lib/mono/gac/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll embedding: /usr/lib/mono/gac/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll embedding: /usr/lib/mono/gac/System.Security/2.0.0.0__b03f5f7f11d50a3a/System.Security.dll embedding: /usr/lib/mono/gac/Mono.Security/2.0.0.0__0738eb9f132ed756/Mono.Security.dll embedding: /usr/lib/mono/gac/Mono.WebBrowser/0.5.0.0__0738eb9f132ed756/Mono.WebBrowser.dll embedding: /usr/lib/mono/gac/System.Data/2.0.0.0__b77a5c561934e089/System.Data.dll embedding: /usr/lib/mono/gac/Mono.Data.Tds/2.0.0.0__0738eb9f132ed756/Mono.Data.Tds.dll embedding: /usr/lib/mono/gac/System.Transactions/2.0.0.0__b77a5c561934e089/System.Transactions.dll embedding: /usr/lib/mono/gac/System.EnterpriseServices/2.0.0.0__b03f5f7f11d50a3a/System.EnterpriseServices.dll embedding: /usr/lib/mono/gac/Mono.Posix/2.0.0.0__0738eb9f132ed756/Mono.Posix.dll embedding: /usr/lib/mono/gac/Accessibility/2.0.0.0__b03f5f7f11d50a3a/Accessibility.dll embedding: /usr/lib/mono/gac/Microsoft.VisualBasic/8.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualBasic.dll Compiling: as -o temp.o temp.s cc -ggdb -o /home/admin/Debug/SnmpTester -Wall temp.c `pkg-config --cflags --libs mono` temp.o Done
Обратите внимание, что компиляция в бинарник байт-кода MONO - это не собственно движок MONO (устанавливаемый как sudo zypper install mono-core и уж никак не интегрированная среда Monodevelop. Платформа бинарной компиляции MONO-кода - это Ассемблер и gcc конкретной процессорной архитектуры, которые устанавливаются отдельными пакетами sudo zypper install binutils и sudo zypper install gcc на целевую машину изготовления бинарника. На выполнение слинкованный бинарник можно запустить непосредственно, а MONO байт-код в режиме интерпритации движком MONO: mono /home/admin/Debug/SnmpGUI.exe. Чтобы посмотреть глазками на байт-код MONO - его можно открыть в MonoDevelop или в текстовом виде monodis /home/admin/Debug/SnmpGUI.exe, а бинарный исполняемый файл можно посмотреть командой readelf /home/admin/Debug/SnmpGUI. Обратите внимание на различие в размерах файлов - если байт-код MONO занимает 19 КилоБайт, то откпомпилированный загрузочный модуль Linux для X86 занимает 11 МегаБайт.
Вы можете распространять свои MONO-проги в виде байт-кода MONO (на виндузне они работают тоже в MONO), можете в бинарном виде для например X86 платформы, а можете в виде загружаемых USB-флешек. Как их делать я описывал здесь - Загрузочные компакты и флешки (bootable LiveCD and bootable USB).
Эту мою прогу вы можете сгрузить в виде байт-кода MONO и в виде Linux-бинарника для платформы X86 отсюда.
|