PDA

View Full Version : ایجاد Pattern برای جداسازی Option های خط فرمان Console Application



ROSTAM2
چهارشنبه 29 آذر 1402, 20:00 عصر
بنام خدا.
سلام،

من یک Pattern اختراع کردم برای RegEx که قرار بود از خط فرمان Console Application به من پارامتر ها رو بصورت Option ها و مقدار هر Option رو با خودش برای من جدا سازی کنه:


\-\w*\s*.*?(?:\.\w+)*\\(\w*\s*\-*\s*\w*){30}.\w*.+?


اما چیزی که هست قرار دادن کاراکتر Backslash \ برای مقدار هر Option الزامی شده چطور می تونم این نقص رو برطرف کنم. چرا که من می خوام هم آدرس فایل و پوشه به عنوان مقادیر استفاده کنم و هم مقادیر عادی رو.... ؟!


Dim OptionsRegEx As New RegularExpressions.Regex("\-\w*\s*.*?(?:\.\w+)*\\(\w*\s*\-*\s*\w*){30}.\w*.+?")





For Each Op As RegularExpressions.Match In OptionsRegEx.Matches(Expr)
Console.WriteLine("Option: {0}, {1}, {2}", Op.Value, Op.Length, Op.Groups.Count)
Next


نشکر

ROSTAM2
پنج شنبه 30 آذر 1402, 07:38 صبح
Oops
خوب مثل اینکه مسیر و اشتباه رفته بودم و آدرس کامل رو هم نمی تونستم بگیرم....

تغییرات اعمال شده حالا به درستی شناسایی می شه هم آدرس و هم متن های دیگه:

Dim OptionsRegEx As New RegularExpressions.Regex("\-.*?[a-zA-Z]\s+\w*(" + Chr(34) + "|[A-Za-z])*[A-Za-z\\0-9-:_.\s{1}]*(" + Chr(34) + "|[A-Za-z0-9]\.)")

اما مشکل اینجاست که دابل کوتیشن الزامی شده و نباید اینجوری باشه!!!!

155159

یا این:


"\-.*?[a-zA-Z]\s+\w*(" + Chr(34) + "{1}|A-Za-z)*[A-Za-z\\0-9-:_.\s{1}]*([A-Za-z0-9]|" + Chr(34) + "{1})

mazoolagh
پنج شنبه 30 آذر 1402, 07:59 صبح
سلام و روز خوش

فکر نکنم regexp بپیچیده ای نیاز باشه؛

1- اگر اینها آرگومانهای پاس شده به اپلیکیشن هستن که که مستقیما بهشون دسترسی دارین و نیازی نیست اونها رو خودتون جدا کنین:
sub main(args as string())
...
dim options= from arg in args where arg.startswith("-") and arg.length > 1
options.tolist.foreach(sub(opt as string) console.writeline(opt))
...
dim switches= from arg in args where arg.startswith("/") and arg.length > 1
switches.tolist.foreach(sub(switch as string) console.writeline(switch))
...
end sub


2- اگر با readline یک string میخونین و میخواین اون رو parse کنین یک regexp ساده کافی هست:
dim command as string= console.readline
dim r as new regex("([^\s]+)")
dim arguments= r.matches(command).cast(of match).tolist
arguments.foreach(sub(arg) console.writeline(arg))

در هر دو حالت وقتی لیست همه تکه ها رو دارین، دیگه برای هر کاری دستتون بازه، چه validation و چه control flow
مگر این که منظور شما رو درست نگرفته باشم

ROSTAM2
پنج شنبه 30 آذر 1402, 08:09 صبح
سلام و روز خوش

فکر نکنم regexp بپیچیده ای نیاز باشه؛

1- اگر اینها آرگومانهای پاس شده به اپلیکیشن هستن که که مستقیما بهشون دسترسی دارین و نیازی نیست اونها رو خودتون جدا کنین:
sub main(args as string())
...
dim options= from arg in args where arg.startswith("-") and arg.length > 1
options.tolist.foreach(sub(opt as string) console.writeline(opt))
...
dim switches= from arg in args where arg.startswith("/") and arg.length > 1
switches.tolist.foreach(sub(switch as string) console.writeline(switch))
...
end sub


2- اگر با readline یک string میخونین و میخواین اون رو parse کنین یک regexp ساده کافی هست:
dim command as string= console.readline
dim r as new regex("([^\s]+)")
dim arguments= r.matches(command).cast(of match).tolist
arguments.foreach(sub(arg) console.writeline(arg))

در هر دو حالت وقتی لیست همه تکه ها رو دارین، دیگه برای هر کاری دستتون بازه، چه validation و چه control flow
مگر این که منظور شما رو درست نگرفته باشم

توی مثال پست دوم هست پارامترها باید طبق هر Option که با کاراکتر - تغریف می شن تا مقدار اونها که یا با دابل کوتیسن یا بدون دابل کوتیشن جدا سازی بشن تا بشه هر گزینه با مقدارشو در دسترس داشت...

بفرض مثال خط فرمان این هست:


D:\>Createshortcut -target "\Windows 10 Updates.txt" -path "C:\Users\ROSTAM\Desktop\My Link.txt"



Dim OptionsRegEx As New RegularExpressions.Regex("\-.*?[a-zA-Z]\s+\w*(" + Chr(34) + "{1}|A-Za-z)*[A-Za-z\\0-9-:_.\s{1}]*([A-Za-z0-9]|" + Chr(34) + "{1})")
Dim OptionNameRegEx As New RegularExpressions.Regex("\-\w*\S")
Dim OptionValueRegEx As New RegularExpressions.Regex("\s{1}.+\w*.+")



For Each Op As RegularExpressions.Match In OptionsRegEx.Matches(Expr)
Console.WriteLine("Option: {0}, {1}, {2}", Op.Value, Op.Length, Op.Groups.Count)
If Op.Success Then
OptionName = OptionNameRegEx.Match(Op.Value).Value.Substring(1)
OptionValue = OptionValueRegEx.Match(Op.Value).Value.Substring(1 )
If OptionsValue.ContainsKey(OptionName) Then Continue For
Me.OptionsValue.Add(OptionName, OptionValue)
Console.WriteLine("Option Name: {0}, Option Value: {1}", OptionName, OptionValue)
End If
Next



Option: -target "\Windows 10 Updates.txt", 33, 3
Option Name: target, Option Value: "\Windows 10 Updates.txt"
Option: -path "C:\Users\ROSTAM\Desktop\My Link.txt", 43, 3
Option Name: path, Option Value: "C:\Users\ROSTAM\Desktop\My Link.txt"
Target: D:\Windows 10 Updates.txt
ShortcutPath: C:\Users\ROSTAM\Desktop\My Link.txt

من فقط می خوام دابل کوتیشن برای آدرسهایی که فاصله بینشون نیست الزامی نباشه همین.

mazoolagh
پنج شنبه 30 آذر 1402, 08:36 صبح
من فقط می خوام دابل کوتیشن برای آدرسهایی که فاصله بینشون نیست الزامی نباشه همین.
پس همون متد دومی جوابه
تست کردین؟

mazoolagh
پنج شنبه 30 آذر 1402, 09:15 صبح
Sub Main()
Console.Write(" Enter Command>")
Dim command As String = Console.ReadLine
'copy -source a:\dira\a.txt -destination b:\dirb\b.txt /all /empty
Dim r As New Regex("([^\s]+)")
Dim arguments = r.Matches(command).Cast(Of Match).ToList
Console.WriteLine("=== All Arguments ===")
arguments.ForEach(Sub(arg) Console.WriteLine($" argument = {arg}"))
Console.WriteLine("=== Options ===")
Dim options = From arg In arguments Where arg.ToString.StartsWith("-") And arg.Length > 1
options.ToList.ForEach(Sub(opt) Console.WriteLine($" option = {opt}"))
Console.WriteLine("=== Switches ===")
Dim switches = From arg In arguments Where arg.ToString.StartsWith("/") And arg.Length > 1
switches.ToList.ForEach(Sub(switch) Console.WriteLine($" switch = {switch}"))
Console.WriteLine("=== parameters ===")
Dim parameters = arguments.Except(options).Except(switches)
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param}"))
Console.ReadKey()
End Sub

خروجی:

=== All Arguments ===
argument = copy
argument = -source
argument = a:\dira\a.txt
argument = -destination
argument = b:\dirb\b.txt
argument = /all
argument = /empty
=== Options ===
option = -source
option = -destination
=== Switches ===
switch = /all
switch = /empty
=== parameters ===
parameter = copy
parameter = a:\dira\a.txt
parameter = b:\dirb\b.txt

155160

ROSTAM2
پنج شنبه 30 آذر 1402, 09:19 صبح
بله، امتحان کردم.

155161

همونطور ک گفتم من هر Option رو با مقدارش باهم می خوام این جداسازی که اینجاست کار رو برای گرفتن گزینه ها و مقادیر توی حلقه سخت می کنه.

ROSTAM2
پنج شنبه 30 آذر 1402, 10:31 صبح
Sub Main()
Console.Write(" Enter Command>")
Dim command As String = Console.ReadLine
'copy -source a:\dira\a.txt -destination b:\dirb\b.txt /all /empty
Dim r As New Regex("([^\s]+)")
Dim arguments = r.Matches(command).Cast(Of Match).ToList
Console.WriteLine("=== All Arguments ===")
arguments.ForEach(Sub(arg) Console.WriteLine($" argument = {arg}"))
Console.WriteLine("=== Options ===")
Dim options = From arg In arguments Where arg.ToString.StartsWith("-") And arg.Length > 1
options.ToList.ForEach(Sub(opt) Console.WriteLine($" option = {opt}"))
Console.WriteLine("=== Switches ===")
Dim switches = From arg In arguments Where arg.ToString.StartsWith("/") And arg.Length > 1
switches.ToList.ForEach(Sub(switch) Console.WriteLine($" switch = {switch}"))
Console.WriteLine("=== parameters ===")
Dim parameters = arguments.Except(options).Except(switches)
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param}"))
Console.ReadKey()
End Sub

خروجی:

=== All Arguments ===
argument = copy
argument = -source
argument = a:\dira\a.txt
argument = -destination
argument = b:\dirb\b.txt
argument = /all
argument = /empty
=== Options ===
option = -source
option = -destination
=== Switches ===
switch = /all
switch = /empty
=== parameters ===
parameter = copy
parameter = a:\dira\a.txt
parameter = b:\dirb\b.txt

155160

ی مشکل دیگه هم داره که اگز بین آدرس فاصله باشه اون رو به تعداد فاصله ها جداسازی می کنه....

155162

ROSTAM2
پنج شنبه 30 آذر 1402, 10:39 صبح
همچنین Pattern ی که من ایجاد کردم بدون دابل کوتیشن کارش لنگه:

155163

ROSTAM2
پنج شنبه 30 آذر 1402, 15:40 عصر
با تغییراتی که اعمال شد نتیجه این شد که تا مقدار هر Option دابل کوتیشین نگیره Option برگردونده نمی شه:

155164


Dim LDblQuotes As String = String.Format("\{0}", Chr(34))
Dim RDblQuotes As String = String.Format("[{0}\.]", Chr(34))
Dim OptionsRegEx As New RegularExpressions.Regex("\-.*?[a-zA-Z]\s+\w*[" + LDblQuotes + "A-Za-z]*[A-Za-z\\0-9-:_.\s{1}]*[A-Za-z0-9]" + RDblQuotes + "")
Dim OptionNameRegEx As New RegularExpressions.Regex("\-\w*\S")
Dim OptionValueRegEx As New RegularExpressions.Regex("\s{1}.+\w*.+")



Me.OptionsValue.Clear()
Dim x% = 0
For Each Op As RegularExpressions.Match In OptionsRegEx.Matches(Expr)
x += 1
Console.WriteLine("Option: {0}, {1}, {2}", Op.Value, Op.Length, Op.Groups.Count)
If Op.Success Then
OptionName = OptionNameRegEx.Match(Op.Value).Value.Substring(1)
OptionValue = OptionValueRegEx.Match(Op.Value).Value.Substring(1 )
If OptionsValue.ContainsKey(OptionName) Then Continue For
Me.OptionsValue.Add(OptionName, OptionValue)
Console.ForegroundColor = ConsoleColor.Cyan
Console.WriteLine("Option {2}) Name: {0}, Value: {1}", OptionName, OptionValue, x)
Console.ResetColor()
End If
Next

ROSTAM2
شنبه 02 دی 1402, 08:02 صبح
سلام.
شاید این پست چندان مرتبط نباشه ولی دونستنش بد نیست:

آموزش ساخت Console Application ایجاد میانبر فایل و بکارگیری بعنوان دستور خارجی (External Command) در PowerShell و Command Prompt

آموزش ساخت دستور خارجی ایجاد میانبر فایل - PowerShell and Command Prompt (https://www.aparat.com/v/120aZ)
155167 (https://www.aparat.com/v/120aZ)

mazoolagh
شنبه 02 دی 1402, 19:50 عصر
همچنین Pattern ی که من ایجاد کردم بدون دابل کوتیشن کارش لنگه:


با تغییراتی که اعمال شد نتیجه این شد که تا مقدار هر Option دابل کوتیشین نگیره Option برگردونده نمی شه:

دابل کوت که اصلا برای optionها و switchها نیاز نیست،
ولی خب برای چیزهایی که در بینشون space هست لازمه - مثل بعضی از pathها (نه همه شون) !
یک اما اینجا هست اون هم برای حالت خاص که اگه دوست داشتین دست آخر در موردش بحث کنیم.

شما به جای regexp پیچیده از همین روش ساده برین راحتتره:
میتونین اول هرچی که درون دابل کوت هست کپچر کنین،
بعد هرچی space تو اینها هست با یک کارآکتر دیگه جایگزین کنین،
بعد این ها رو در دستور اصلی جایگزین کنین و ادامه کد قبلی.

Const blank As Char = ChrW(&H20)
Const xChar As Char = ChrW(&HAE)
Const DoubleQuote As Char = ChrW(&H22)
Sub Main()
Console.Write(" Enter Command>")
Dim command As String = Console.ReadLine
'copy -source "a:\dir a\a a\*.txt" /verify -destination "b:\dir b\b b\*.csv" -temp f:\temp\a's /all /empty
Dim rq As New Regex("""(.*?)""")
Dim quoted = rq.Matches(command).Cast(Of Match).Select(Function(x) x.Value).ToList
quoted.ForEach(Sub(x) command = command.Replace(x, x.Replace(blank, xChar)))

Dim r As New Regex("([^\s]+)")
Dim arguments = r.Matches(command).Cast(Of Match).Select(Function(x) x.Value.Replace(xChar, blank)).ToList
arguments.ForEach(Sub(arg) arg = arg.ToString.Replace(xChar, blank))

Console.WriteLine("=== All Arguments ===")
arguments.ForEach(Sub(arg) Console.WriteLine($" argument = {arg}"))

Console.WriteLine("=== Options ===")
Dim options = From arg In arguments Where arg.ToString.StartsWith("-") And arg.Length > 1
options.ToList.ForEach(Sub(opt) Console.WriteLine($" option = {opt}"))

Console.WriteLine("=== Switches ===")
Dim switches = From arg In arguments Where arg.ToString.StartsWith("/") And arg.Length > 1
switches.ToList.ForEach(Sub(switch) Console.WriteLine($" switch = {switch}"))

Console.WriteLine("=== parameters ===")
Dim parameters = arguments.Except(options).Except(switches)
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param}"))

Console.WriteLine("=== parameters unquoted ===")
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param.Replace(DoubleQuote, String.Empty)}"))
Console.ReadKey()

End Sub

خروجی:


Enter Command>copy -source "a:\dir a\a a\*.txt" /verify -destination "b:\dir b\b b\*.csv" -temp f:\temp\a's /all /empty
=== All Arguments ===
argument = copy
argument = -source
argument = "a:\dir a\a a\*.txt"
argument = /verify
argument = -destination
argument = "b:\dir b\b b\*.csv"
argument = -temp
argument = f:\temp\a's
argument = /all
argument = /empty
=== Options ===
option = -source
option = -destination
option = -temp
=== Switches ===
switch = /verify
switch = /all
switch = /empty
=== parameters ===
parameter = copy
parameter = "a:\dir a\a a\*.txt"
parameter = "b:\dir b\b b\*.csv"
parameter = f:\temp\a's
=== parameters unquoted ===
parameter = copy
parameter = a:\dir a\a a\*.txt
parameter = b:\dir b\b b\*.csv
parameter = f:\temp\a's

ROSTAM2
چهارشنبه 06 دی 1402, 10:22 صبح
دابل کوت که اصلا برای optionها و switchها نیاز نیست،
ولی خب برای چیزهایی که در بینشون space هست لازمه - مثل بعضی از pathها (نه همه شون) !
یک اما اینجا هست اون هم برای حالت خاص که اگه دوست داشتین دست آخر در موردش بحث کنیم.

شما به جای regexp پیچیده از همین روش ساده برین راحتتره:
میتونین اول هرچی که درون دابل کوت هست کپچر کنین،
بعد هرچی space تو اینها هست با یک کارآکتر دیگه جایگزین کنین،
بعد این ها رو در دستور اصلی جایگزین کنین و ادامه کد قبلی.

Const blank As Char = ChrW(&H20)
Const xChar As Char = ChrW(&HAE)
Const DoubleQuote As Char = ChrW(&H22)
Sub Main()
Console.Write(" Enter Command>")
Dim command As String = Console.ReadLine
'copy -source "a:\dir a\a a\*.txt" /verify -destination "b:\dir b\b b\*.csv" -temp f:\temp\a's /all /empty
Dim rq As New Regex("""(.*?)""")
Dim quoted = rq.Matches(command).Cast(Of Match).Select(Function(x) x.Value).ToList
quoted.ForEach(Sub(x) command = command.Replace(x, x.Replace(blank, xChar)))

Dim r As New Regex("([^\s]+)")
Dim arguments = r.Matches(command).Cast(Of Match).Select(Function(x) x.Value.Replace(xChar, blank)).ToList
arguments.ForEach(Sub(arg) arg = arg.ToString.Replace(xChar, blank))

Console.WriteLine("=== All Arguments ===")
arguments.ForEach(Sub(arg) Console.WriteLine($" argument = {arg}"))

Console.WriteLine("=== Options ===")
Dim options = From arg In arguments Where arg.ToString.StartsWith("-") And arg.Length > 1
options.ToList.ForEach(Sub(opt) Console.WriteLine($" option = {opt}"))

Console.WriteLine("=== Switches ===")
Dim switches = From arg In arguments Where arg.ToString.StartsWith("/") And arg.Length > 1
switches.ToList.ForEach(Sub(switch) Console.WriteLine($" switch = {switch}"))

Console.WriteLine("=== parameters ===")
Dim parameters = arguments.Except(options).Except(switches)
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param}"))

Console.WriteLine("=== parameters unquoted ===")
parameters.ToList.ForEach(Sub(param) Console.WriteLine($" parameter = {param.Replace(DoubleQuote, String.Empty)}"))
Console.ReadKey()

End Sub

خروجی:


Enter Command>copy -source "a:\dir a\a a\*.txt" /verify -destination "b:\dir b\b b\*.csv" -temp f:\temp\a's /all /empty
=== All Arguments ===
argument = copy
argument = -source
argument = "a:\dir a\a a\*.txt"
argument = /verify
argument = -destination
argument = "b:\dir b\b b\*.csv"
argument = -temp
argument = f:\temp\a's
argument = /all
argument = /empty
=== Options ===
option = -source
option = -destination
option = -temp
=== Switches ===
switch = /verify
switch = /all
switch = /empty
=== parameters ===
parameter = copy
parameter = "a:\dir a\a a\*.txt"
parameter = "b:\dir b\b b\*.csv"
parameter = f:\temp\a's
=== parameters unquoted ===
parameter = copy
parameter = a:\dir a\a a\*.txt
parameter = b:\dir b\b b\*.csv
parameter = f:\temp\a's


سلامی دوباره، با آرزوی روز و روزگاری خوب و خش
جداسازی با این روش شما امکان پذیر شده درست.
اما یک نکته مهم می مونه زمان استفاده از Option ها و مقادیر اونها که باید براش دستور نوشته بشه و شناسایی بشه.
در روشی که خواسته منه هر کلمه که با (-) علامت گذاری شده باشه بعنوان Option و مقدار بعد ازون می شه مقدار یا مقادیر که می خواستم با pattern از RegEx اون رو دریافت کنم که تنها دابل کوتیشن الزامی شده.
تنها راهی که میمونه جدا سازی با Space و شرط گذاری آرایه برای شناسایی Option ها مقادیر اونها و سوئیچ هاست،

ROSTAM2
چهارشنبه 06 دی 1402, 18:36 عصر
خوب من این دستور رو نوشتم و ازش جواب گرفتم فقط باید بشتر تست بشه، نظرتون رو بگید....

کلاس CommandInfo:


Imports System.Text
Public Class CommandInfo
Sub New()
MyBase.New()
End Sub
Sub New(CommandLine As String)
MyBase.New()
Me.CommandLine = CommandLine
End Sub

Private CommandLineValue As String
Public Property CommandLine() As String
Get
Return CommandLineValue
End Get
Set(ByVal value As String)
CommandLineValue = value


Dim Expr As String = ""
If value.Contains(Space(1)) Then
Dim Length As SByte = InStr(value, Space(1)) - 1
KeyWordValue = value.Substring(0, Length)
Expr = value.Substring(Length + 1)
Me.ParametersValue = Expr
Me.OptionsValue.Clear()
Dim NewOption As Boolean = False
Dim Opt As OptionInfo = Nothing
Dim Words() As String = Expr.Split(Space(1))
For i = 0 To Words.Length - 1
If Words(i).StartsWith("-") Then
Opt = New OptionInfo(Words(i).Remove(0, 1))
Me.OptionsValue.Add(Opt)
Continue For
NewOption = True
End If
If Words(i).StartsWith("/") Then
If Opt Is Nothing Then
Me.Switches.Add(Words(i).Remove(0, 1))
Else
Opt.Switches.Add(Words(i).Remove(0, 1))
End If
Continue For
End If
If Words(i).StartsWith(Chr(34)) Then
For x = i To Words.Length - 1
Opt.Value += Words(x) + " "
If Words(x).EndsWith(Chr(34)) Then
i = x
Exit For
End If
Next
Else
Opt.Value += Words(i)
End If
Next


For Each Op As OptionInfo In Me.Options
Console.WriteLine("Option) Name: {0}, Value: {1}, Switchs: {2}", Op.Name, Op.Value, Op.Switches.Count)
Next
Else
KeyWordValue = value
End If
End Set
End Property

Private SwitchesValue As New List(Of String)
Public ReadOnly Property Switches() As List(Of String)
Get
Return SwitchesValue
End Get
End Property
Private KeyWordValue As String = ""
Public ReadOnly Property KeyWord() As String
Get
Return KeyWordValue
End Get
End Property


Public ReadOnly Property HasOptions() As Boolean
Get
Return Me.OptionsValue.Count > 0
End Get
End Property
Public ReadOnly Property HasOptions(Count As SByte) As Boolean
Get
Return Me.OptionsValue.Count = Count
End Get
End Property
Private OptionsValue As New OptionCollection
Public ReadOnly Property Options() As OptionCollection
Get
Return OptionsValue
End Get
End Property
Private ParametersValue As String
Public ReadOnly Property Parameters() As String
Get
Return ParametersValue
End Get
End Property


End Class
Public Class OptionCollection
Inherits List(Of OptionInfo)


Public Overloads Function Contains(Name As String) As Boolean
For Each O As OptionInfo In Me
If O.Name.Equals(Name, StringComparison.OrdinalIgnoreCase) Then
Return True
End If
Next
Return False
End Function


Default Public Shadows ReadOnly Property Item(Name As String) As String
Get
For Each O As OptionInfo In Me
If O.Name.Equals(Name, StringComparison.OrdinalIgnoreCase) Then
Return O.Value
End If
Next
Return ""
End Get
End Property


End Class
Public Class OptionInfo
Sub New()


End Sub
Sub New(name As String)
Me.NameValue = name
End Sub
Sub New(name As String, value As String)
Me.NameValue = name
Me.ValueValue = value
End Sub
Private NameValue As String = ""
Public Property Name() As String
Get
Return NameValue
End Get
Set(value As String)
NameValue = value
End Set
End Property
Private ValueValue As String = ""
Public Property Value() As String
Get
Return ValueValue.Replace(Chr(34),"")
End Get
Set(value As String)
ValueValue = value
End Set
End Property
Private SwitchesValue As New List(Of String)
Public ReadOnly Property Switches() As List(Of String)
Get
Return SwitchesValue
End Get
End Property


End Class


و دستورات ماجول اصلی:


Imports IWshRuntimeLibrary
Imports System.IO
Module Module1


Sub Main()
Dim CommandInf As New CommandInfo
With CommandInf
Do Until .KeyWord.ToLower = "exit"
Console.Write("{0}>", IO.Path.GetFullPath("."))
Try
.CommandLine = Console.ReadLine
Catch ex As Exception
Continue Do
End Try


Select Case .KeyWord.ToLower
Case "time"
Console.WriteLine("{0}Time:{1}", vbTab, Now.ToLongTimeString)
Case "cls"
Console.Clear()
Case "cd"
ChDir(.Parameters)
Case "files"
For Each D As String In IO.Directory.GetFiles(IO.Path.GetFullPath("."))
Console.WriteLine("{0}.\{1}", Space(2), IO.Path.GetFileName(D))
Next
Case "dirs"
For Each D As String In IO.Directory.GetDirectories(IO.Path.GetFullPath("."))
Console.WriteLine("{0}.\{1}", Space(2), FileIO.FileSystem.GetName(D))
Next
Case "filelen"
Dim Path As String = .Parameters
If Path.Length = 0 Then Exit Select
Console.WriteLine("{0}File Length:{1}", vbTab, FileLen(Path))


Case "createshortcut"
Dim Target As String = ""
Dim ShortcutPath As String = ""
Dim WSH As New WshShell
' Console.WriteLine("{0}: {1}", .Parameters, .HasOptions)
If .Options.Contains("target") Then
Target = IO.Path.GetFullPath(.Options("target").Replace(Chr(34), ""))
Console.WriteLine("Target: {0}", Target)
Else
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine("createshortcut '-target' option is lost!")
Console.ResetColor()
End If
If .Options.Contains("path") Then
ShortcutPath = .Options("path").Replace(Chr(34), "")
If ShortcutPath.StartsWith("[Desktop]", StringComparison.OrdinalIgnoreCase) Then
ShortcutPath = WSH.SpecialFolders.Item("Desktop") + ShortcutPath.Substring(9)
Else
ShortcutPath = IO.Path.GetFullPath(ShortcutPath)
End If
Console.WriteLine("ShortcutPath: {0}", ShortcutPath)
Else
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine("createshortcut '-path' option is lost!")
Console.ResetColor()
End If
If .HasOptions(2) = False Then Exit Select
If ShortcutPath.Contains("*") Then
ShortcutPath = ShortcutPath.Replace("*", IO.Path.GetFileNameWithoutExtension(Target))
End If
If ShortcutPath.EndsWith(".lnk", StringComparison.InvariantCultureIgnoreCase) = False Then
ShortcutPath += ".lnk"
End If
Dim Shortcut As WshShortcut = WSH.CreateShortcut(ShortcutPath)
With Shortcut
.TargetPath = Target
.Save()
End With
Case Else
If .KeyWord.StartsWith("$env:", StringComparison.OrdinalIgnoreCase) Then
Dim env As String() = .KeyWord.Split(":")


Exit Select
End If
Dim DrvName As String = CommandInf.KeyWord + ""
For Each drv As IO.DriveInfo In My.Computer.FileSystem.Drives
Select Case drv.DriveType
Case IO.DriveType.NoRootDirectory, IO.DriveType.Ram, IO.DriveType.Unknown
Continue For
End Select
If DrvName.Equals(drv.Name, StringComparison.CurrentCultureIgnoreCase) Then
ChDir(drv.RootDirectory.FullName)
End If
Next


End Select
Loop


End With
End Sub
End Module

ROSTAM2
چهارشنبه 06 دی 1402, 18:47 عصر
تغییرات در کدهای پست قبل ایجاد شد....

این هم از نتیجه دلنشینش:

155179

155180

ROSTAM2
چهارشنبه 06 دی 1402, 18:52 عصر
بتظر میاد آخر آدرس ها یک فاصله اضافه داره که باید درست بشه...

ROSTAM2
چهارشنبه 06 دی 1402, 18:59 عصر
خصوصیت CommandLine این تغییرات رو لازم داشت:


Private CommandLineValue As String
Public Property CommandLine() As String
Get
Return CommandLineValue
End Get
Set(ByVal value As String)
CommandLineValue = value


Dim Expr As String = ""
If value.Contains(Space(1)) Then
Dim Length As SByte = InStr(value, Space(1)) - 1
KeyWordValue = value.Substring(0, Length)
Expr = value.Substring(Length + 1)
Me.ParametersValue = Expr
Me.OptionsValue.Clear()

Dim Opt As OptionInfo = Nothing
Dim Words() As String = Expr.Split(Space(1))
For i = 0 To Words.Length - 1
If Words(i).StartsWith("-") Then
Opt = New OptionInfo(Words(i).Remove(0, 1))
Me.OptionsValue.Add(Opt)
Continue For
End If
If Words(i).StartsWith("/") Then
If Opt Is Nothing Then
Me.Switches.Add(Words(i).Remove(0, 1))
Else
Opt.Switches.Add(Words(i).Remove(0, 1))
End If
Continue For
End If
If Words(i).StartsWith(Chr(34)) Then
For x = i To Words.Length - 1
Opt.Value += Words(x) + " "
If Words(x).EndsWith(Chr(34)) Then
Opt.Value = Opt.Value.Remove(Opt.Value.Length - 1, 1)
i = x
Exit For
End If
Next
Else
Opt.Value += Words(i)
End If
Next


For Each Op As OptionInfo In Me.Options
Console.WriteLine("Option) Name: {0}, Value: {1}, Switchs: {2}", Op.Name, Op.Value, Op.Switches.Count)
Next
Else
KeyWordValue = value
End If
End Set
End Property